openclaw_oauth_sync/tests/test-anthropic-connection.mjs
shamid202 22731fff60 Add complete OAuth token refresh and sync solution
- Setup wizard with auto-detection of OpenClaw paths and Claude CLI
- Token sync watcher (inotifywait) for real-time credential updates
- Auto-refresh trigger timer that runs Claude CLI every 30 min
- Supports Claude CLI in Docker container or on host
- Temporary ANTHROPIC_BASE_URL override for container environments
- Anthropic model configuration for OpenClaw
- Auth profile management (fixes key vs access field)
- Systemd services and timers for both sync and trigger
- Comprehensive documentation and troubleshooting guides
- Re-authentication notification system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 01:51:18 +07:00

110 lines
2.9 KiB
JavaScript

#!/usr/bin/env node
// test-anthropic-connection.mjs — Test Anthropic API connectivity with OAuth token
// Usage: node test-anthropic-connection.mjs [token]
// If no token provided, reads from oauth.json or .env
import https from 'node:https';
import fs from 'node:fs';
// Find token
let token = process.argv[2];
if (!token) {
// Try oauth.json
for (const path of [
'/root/.openclaw/credentials/oauth.json',
'/home/node/.openclaw/credentials/oauth.json',
]) {
try {
const data = JSON.parse(fs.readFileSync(path, 'utf8'));
token = data.anthropic?.access;
if (token) { console.log(`Token from: ${path}`); break; }
} catch {}
}
}
if (!token) {
// Try .env
try {
const env = fs.readFileSync('/root/openclaw/.env', 'utf8');
const match = env.match(/ANTHROPIC_OAUTH_TOKEN="?([^"\n]+)/);
if (match) { token = match[1]; console.log('Token from: .env'); }
} catch {}
}
if (!token) {
console.error('ERROR: No token found. Provide as argument or ensure oauth.json/.env exists.');
process.exit(1);
}
console.log(`Token: ${token.substring(0, 20)}...`);
console.log('');
// Test API
const body = JSON.stringify({
model: 'claude-sonnet-4-20250514',
max_tokens: 20,
messages: [{ role: 'user', content: 'Say "hello" and nothing else.' }],
});
const isOAuth = token.startsWith('sk-ant-oat');
const headers = {
'Content-Type': 'application/json',
'anthropic-version': '2023-06-01',
'Content-Length': Buffer.byteLength(body),
};
if (isOAuth) {
headers['Authorization'] = `Bearer ${token}`;
// Claude Code identity headers required for OAuth
headers['anthropic-beta'] = 'claude-code-20250219,oauth-2025-04-20';
headers['user-agent'] = 'claude-cli/2.1.0';
headers['x-app'] = 'cli';
console.log('Auth: Bearer (OAuth token)');
} else {
headers['x-api-key'] = token;
console.log('Auth: x-api-key');
}
console.log('Sending test request to api.anthropic.com...');
console.log('');
const req = https.request({
hostname: 'api.anthropic.com',
path: '/v1/messages',
method: 'POST',
headers,
}, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => {
console.log(`Status: ${res.statusCode}`);
if (res.statusCode === 200) {
try {
const parsed = JSON.parse(data);
const text = parsed.content?.[0]?.text || '';
console.log(`Response: "${text}"`);
console.log(`Model: ${parsed.model}`);
console.log('');
console.log('SUCCESS: Anthropic API connection working');
} catch {
console.log('Response:', data.substring(0, 200));
}
} else {
console.log('Response:', data.substring(0, 500));
console.log('');
console.log('FAILED: API returned non-200 status');
process.exit(1);
}
});
});
req.on('error', (err) => {
console.error('Connection error:', err.message);
process.exit(1);
});
req.write(body);
req.end();