Parent issue
#756
Depends on
#757 #758
Context
Core handler class following the same BaseProvider pattern as OpenAiCodexHandler. Uses @anthropic-ai/claude-agent-sdk query() with includePartialMessages: true to stream text deltas, and maps SDKResultError to ApiProviderError.
Files
src/api/providers/claude-code.ts (new)
src/api/providers/index.ts
src/api/index.ts
src/api/providers/__tests__/claude-code.spec.ts (new)
Work
ClaudeCodeHandler extends BaseProvider implements SingleCompletionHandler
createMessage(): call query() with includePartialMessages: true, iterate events:
SDKPartialAssistantMessage (type: "stream_event") → yield { type: "text", text } from content_block_delta events
SDKResultMessage (subtype: "error") → throw ApiProviderError
getModel(): return selected model id + info from claudeCodeModels
completePrompt(): single-turn, collect text from result
case "claude-code" in src/api/index.ts factory switch
- Export from
src/api/providers/index.ts
- Resolve CLI binary path via
options.claudeCodeCliPath → which claude fallback
Tests
Mock @anthropic-ai/claude-agent-sdk:
- Text streaming yields correct
{ type: "text" } chunks
SDKResultError maps to ApiProviderError
completePrompt() returns concatenated text
- Abort signal propagates to
query() options
- Factory returns
ClaudeCodeHandler for "claude-code" provider
Acceptance criteria
- Handler streams text from a mocked Agent SDK
- Errors surface as
ApiProviderError with provider name and model id
- Factory switch correctly instantiates the handler
- All tests pass
Parent issue
#756
Depends on
#757 #758
Context
Core handler class following the same
BaseProviderpattern asOpenAiCodexHandler. Uses@anthropic-ai/claude-agent-sdkquery()withincludePartialMessages: trueto stream text deltas, and mapsSDKResultErrortoApiProviderError.Files
src/api/providers/claude-code.ts(new)src/api/providers/index.tssrc/api/index.tssrc/api/providers/__tests__/claude-code.spec.ts(new)Work
ClaudeCodeHandler extends BaseProvider implements SingleCompletionHandlercreateMessage(): callquery()withincludePartialMessages: true, iterate events:SDKPartialAssistantMessage(type: "stream_event") → yield{ type: "text", text }fromcontent_block_deltaeventsSDKResultMessage(subtype: "error") → throwApiProviderErrorgetModel(): return selected model id + info fromclaudeCodeModelscompletePrompt(): single-turn, collect text from resultcase "claude-code"insrc/api/index.tsfactory switchsrc/api/providers/index.tsoptions.claudeCodeCliPath→which claudefallbackTests
Mock
@anthropic-ai/claude-agent-sdk:{ type: "text" }chunksSDKResultErrormaps toApiProviderErrorcompletePrompt()returns concatenated textquery()optionsClaudeCodeHandlerfor"claude-code"providerAcceptance criteria
ApiProviderErrorwith provider name and model id