#!/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();