feat: add Claude CLI agent support alongside Codex#64
Open
mzhaom wants to merge 3 commits into
Open
Conversation
Introduce a translator.Translator interface so the wrapper can drive either Codex or Claude CLI as the underlying agent. The agent type is selected via config (agentType: "claude") or env var (CODEX_REMOTE_AGENT_TYPE=claude). New packages: - internal/core/translator: defines the Translator interface and Result type - internal/adapter/claude: Claude CLI SDK protocol translator (NDJSON, stream events, control_request/response, permission flow) Key changes: - Extract BootstrapFrames from hardcoded Codex headless init into the Translator interface so each agent handles its own startup handshake - Wrapper selects translator and binary based on AgentType config - Claude child process gets CLAUDE_CODE_ENTRYPOINT=sdk-go env var - Daemon passes CODEX_REMOTE_AGENT_TYPE to headless wrapper instances - Rename OutboundToCodex -> OutboundToAgent across the codebase Claude v1 limitations: single thread per instance (no thread switching), no turn/steer support, no --resume session persistence.
- Integration test (go test -tags integration) spawns real Claude CLI, sends a prompt, and verifies the translator produces the correct agentproto event sequence (thread.discovered → turn.started → item.started → item.delta → item.completed → turn.completed) - Records the full NDJSON session with privacy masking for replay - clauderecord package: Entry/Recorder for capture, MaskEntries for privacy (session_id, uuid, email, org, paths, api keys), LoadFixture for replay - Replay unit tests load the masked fixture and verify translator output without needing a live Claude CLI - Fixture testdata/hello_simple.ndjson committed with all PII masked Key finding during implementation: Claude CLI sends the system init message only after the first user message is written to stdin, not immediately after the initialize control_response.
…lti-turn Add three new integration test scenarios against real Claude CLI: - TestClaudeCLIToolUse: Bash tool invocation with input_json_delta streaming, tool result echo, and follow-up text response - TestClaudeCLIThinking: reasoning_content blocks with thinking_delta - TestClaudeCLIMultiTurn: two sequential turns with context retention Fix translator block index tracking: - Track blocks by protocol index field (map[int]*blockState) instead of a single activeBlockIndex counter. This correctly handles: - Multiple concurrent blocks (thinking at index 0, text at index 1) - assistant messages arriving before content_block_stop - signature_delta and unknown delta types (silently skipped) Replay tests now cover all 4 fixtures with structural assertions: - Block index uniqueness and start/complete pairing - Multi-turn ID separation - Tool metadata (toolName) propagation - Thinking delta presence Fixtures are privacy-masked (session_id, uuid, email, org, paths).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduce a translator.Translator interface so the wrapper can drive either Codex or Claude CLI as the underlying agent. The agent type is selected via config (agentType: "claude") or env var (CODEX_REMOTE_AGENT_TYPE=claude).
New packages:
Key changes:
Claude v1 limitations: single thread per instance (no thread switching), no turn/steer support, no --resume session persistence.