Skip to content

[claude-code] Implement ClaudeCodeHandler and wire into provider factory #759

Description

@edelauna

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.claudeCodeCliPathwhich 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions