mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-14 06:17:27 +00:00
feat(api): add Anthropic direct API key support
Support native Anthropic API keys (sk-ant-...) via `ccs api create --preset anthropic`. Profiles use ANTHROPIC_API_KEY env var without BASE_URL, letting Claude CLI authenticate natively with x-api-key header instead of proxy Bearer token. - Add anthropic preset to provider catalog - Branch profile-writer env structure (native vs proxy) - Add validateAnthropicKey() preflight with x-api-key header - Auto-detect api.anthropic.com URL in interactive flow - Fix hasApiKey/isConfigured to recognize ANTHROPIC_API_KEY - Update delegation-validator for native mode profiles - Add Droid target API key fallback (ANTHROPIC_API_KEY) Closes #688 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
0c4d5244c8
commit
fedb4d4cde
11 files changed
+301
-20
No files matched your search
@@ -166,3 +166,76 @@ export async function validateMiniMaxKey(
|
||||
timeoutMs
|
||||
);
|
||||
}
|
||||
|
||||
/** Validate Anthropic direct API key using x-api-key header (not Bearer) */
|
||||
export async function validateAnthropicKey(
|
||||
apiKey: string,
|
||||
timeoutMs = 2000
|
||||
): Promise<ValidationResult> {
|
||||
if (process.env.CCS_SKIP_PREFLIGHT === '1') {
|
||||
return { valid: true };
|
||||
}
|
||||
|
||||
if (!apiKey || DEFAULT_PLACEHOLDERS.includes(apiKey.toUpperCase())) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Anthropic API key not configured',
|
||||
suggestion: 'Set ANTHROPIC_API_KEY in your profile settings.json',
|
||||
};
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let resolved = false;
|
||||
const safeResolve = (result: ValidationResult) => {
|
||||
if (resolved) return;
|
||||
resolved = true;
|
||||
resolve(result);
|
||||
};
|
||||
|
||||
const options: https.RequestOptions = {
|
||||
hostname: 'api.anthropic.com',
|
||||
port: 443,
|
||||
path: '/v1/models',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'x-api-key': apiKey,
|
||||
'anthropic-version': '2023-06-01',
|
||||
'User-Agent': 'CCS-Preflight/1.0',
|
||||
},
|
||||
};
|
||||
|
||||
const req = https.request(options, (res) => {
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
safeResolve({ valid: true });
|
||||
} else if (res.statusCode === 401 || res.statusCode === 403) {
|
||||
safeResolve({
|
||||
valid: false,
|
||||
error: 'Anthropic API key rejected',
|
||||
suggestion:
|
||||
'Your key may have expired. To fix:\n' +
|
||||
' 1. Go to console.anthropic.com/settings/keys and regenerate your API key\n' +
|
||||
' 2. Update ANTHROPIC_API_KEY in your profile settings.json\n' +
|
||||
' 3. Or run: ccs api create --preset anthropic',
|
||||
});
|
||||
} else {
|
||||
safeResolve({ valid: true });
|
||||
}
|
||||
|
||||
res.resume();
|
||||
});
|
||||
|
||||
req.on('error', () => {
|
||||
clearTimeout(timeoutId);
|
||||
safeResolve({ valid: true });
|
||||
});
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
req.destroy();
|
||||
safeResolve({ valid: true });
|
||||
}, timeoutMs);
|
||||
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
@@ -69,16 +69,17 @@ export class DelegationValidator {
|
||||
}
|
||||
|
||||
// Validate API key exists and is not default
|
||||
const apiKey = settings.env?.ANTHROPIC_AUTH_TOKEN;
|
||||
// Support both proxy mode (ANTHROPIC_AUTH_TOKEN) and native mode (ANTHROPIC_API_KEY)
|
||||
const apiKey = settings.env?.ANTHROPIC_AUTH_TOKEN || settings.env?.ANTHROPIC_API_KEY;
|
||||
|
||||
if (!apiKey) {
|
||||
return {
|
||||
valid: false,
|
||||
error: `API key not configured for ${profileName}`,
|
||||
suggestion:
|
||||
`Missing ANTHROPIC_AUTH_TOKEN in settings.\n\n` +
|
||||
`Missing ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY in settings.\n\n` +
|
||||
`Edit: ${settingsPath}\n` +
|
||||
`Set: env.ANTHROPIC_AUTH_TOKEN to your API key`,
|
||||
`Set: env.ANTHROPIC_AUTH_TOKEN (proxy) or env.ANTHROPIC_API_KEY (direct) to your API key`,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user