feat: Claude Code AI SDK v5 Integration (#1114)
Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
This commit is contained in:
@@ -1,54 +1,125 @@
|
||||
/**
|
||||
* src/ai-providers/claude-code.js
|
||||
*
|
||||
* Implementation for interacting with Claude models via Claude Code CLI
|
||||
* using a custom AI SDK implementation.
|
||||
* 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 './custom-sdk/claude-code/index.js';
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override validateAuth to skip API key validation for Claude Code
|
||||
* @param {object} params - Parameters to validate
|
||||
* Optional CLI availability check for Claude Code
|
||||
* @param {object} params - Parameters (ignored)
|
||||
*/
|
||||
validateAuth(params) {
|
||||
// Claude Code doesn't require an API key
|
||||
// No validation needed
|
||||
// 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 and returns a Claude Code client instance.
|
||||
* @param {object} params - Parameters for client initialization
|
||||
* @param {string} [params.commandName] - Name of the command invoking the service
|
||||
* @param {string} [params.baseURL] - Optional custom API endpoint (not used by Claude Code)
|
||||
* @returns {Function} Claude Code client function
|
||||
* @throws {Error} If initialization fails
|
||||
* 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) {
|
||||
getClient(params = {}) {
|
||||
try {
|
||||
// Claude Code doesn't use API keys or base URLs
|
||||
// Just return the provider factory
|
||||
const settings =
|
||||
getClaudeCodeSettingsForCommand(params.commandName) || {};
|
||||
|
||||
return createClaudeCode({
|
||||
defaultSettings: getClaudeCodeSettingsForCommand(params?.commandName)
|
||||
defaultSettings: settings
|
||||
});
|
||||
} catch (error) {
|
||||
this.handleError('client initialization', 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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user