Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
126 lines
3.5 KiB
JavaScript
126 lines
3.5 KiB
JavaScript
/**
|
|
* src/ai-providers/claude-code.js
|
|
*
|
|
* Claude Code provider implementation using the ai-sdk-provider-claude-code package.
|
|
* This provider uses the local Claude Code CLI with OAuth token authentication.
|
|
*
|
|
* Authentication:
|
|
* - Uses CLAUDE_CODE_OAUTH_TOKEN managed by Claude Code CLI
|
|
* - Token is set up via: claude setup-token
|
|
* - No manual API key configuration required
|
|
*/
|
|
|
|
import { createClaudeCode } from 'ai-sdk-provider-claude-code';
|
|
import { BaseAIProvider } from './base-provider.js';
|
|
import { getClaudeCodeSettingsForCommand } from '../../scripts/modules/config-manager.js';
|
|
import { execSync } from 'child_process';
|
|
import { log } from '../../scripts/modules/utils.js';
|
|
|
|
let _claudeCliChecked = false;
|
|
let _claudeCliAvailable = null;
|
|
|
|
/**
|
|
* Provider for Claude Code CLI integration via AI SDK
|
|
*
|
|
* Features:
|
|
* - No API key required (uses local Claude Code CLI)
|
|
* - Supports 'sonnet' and 'opus' models
|
|
* - Command-specific configuration support
|
|
*/
|
|
export class ClaudeCodeProvider extends BaseAIProvider {
|
|
constructor() {
|
|
super();
|
|
this.name = 'Claude Code';
|
|
this.supportedModels = ['sonnet', 'opus'];
|
|
}
|
|
|
|
/**
|
|
* @returns {string} The environment variable name for API key (not used)
|
|
*/
|
|
getRequiredApiKeyName() {
|
|
return 'CLAUDE_CODE_API_KEY';
|
|
}
|
|
|
|
/**
|
|
* @returns {boolean} False - Claude Code doesn't require API keys
|
|
*/
|
|
isRequiredApiKey() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Optional CLI availability check for Claude Code
|
|
* @param {object} params - Parameters (ignored)
|
|
*/
|
|
validateAuth(params) {
|
|
// Claude Code uses local CLI - perform lightweight availability check
|
|
// This is optional validation that fails fast with actionable guidance
|
|
if (
|
|
process.env.NODE_ENV !== 'test' &&
|
|
!_claudeCliChecked &&
|
|
!process.env.CLAUDE_CODE_OAUTH_TOKEN
|
|
) {
|
|
try {
|
|
execSync('claude --version', { stdio: 'pipe', timeout: 1000 });
|
|
_claudeCliAvailable = true;
|
|
} catch (error) {
|
|
_claudeCliAvailable = false;
|
|
log(
|
|
'warn',
|
|
'Claude Code CLI not detected. Install it with: npm install -g @anthropic-ai/claude-code'
|
|
);
|
|
} finally {
|
|
_claudeCliChecked = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a Claude Code client instance
|
|
* @param {object} params - Client parameters
|
|
* @param {string} [params.commandName] - Command name for settings lookup
|
|
* @returns {Function} Claude Code provider function
|
|
* @throws {Error} If Claude Code CLI is not available or client creation fails
|
|
*/
|
|
getClient(params = {}) {
|
|
try {
|
|
const settings =
|
|
getClaudeCodeSettingsForCommand(params.commandName) || {};
|
|
|
|
return createClaudeCode({
|
|
defaultSettings: settings
|
|
});
|
|
} catch (error) {
|
|
// Provide more helpful error message
|
|
const msg = String(error?.message || '');
|
|
const code = error?.code;
|
|
if (code === 'ENOENT' || /claude/i.test(msg)) {
|
|
const enhancedError = new Error(
|
|
`Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${error.message}`
|
|
);
|
|
enhancedError.cause = error;
|
|
this.handleError('Claude Code CLI initialization', enhancedError);
|
|
} else {
|
|
this.handleError('client initialization', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @returns {string[]} List of supported model IDs
|
|
*/
|
|
getSupportedModels() {
|
|
return this.supportedModels;
|
|
}
|
|
|
|
/**
|
|
* Check if a model is supported
|
|
* @param {string} modelId - Model ID to check
|
|
* @returns {boolean} True if supported
|
|
*/
|
|
isModelSupported(modelId) {
|
|
if (!modelId) return false;
|
|
return this.supportedModels.includes(String(modelId).toLowerCase());
|
|
}
|
|
}
|