feat(agents): finish ClaudeAgentPort migration — eliminate SDK leaks in agent-runner #517

Closed
opened 2026-04-28 09:24:41 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As a maintainer, I want all SDK calls and types to live behind ClaudeAgentPort / SdkClaudeAgent, so that agent-runner.ts consumes only domain types and the SDK can be swapped or mocked at the boundary.

Acceptance criteria

Migration

  • agent-runner.ts:715–780: replace direct query({...}) call with claudeAgent.run(request) via injected ClaudeAgentPort
  • agent-runner.ts:24: drop SDKMessage import
  • agent-runner.ts:679: PR-extract regex moved into adapter (or into a domain helper if used elsewhere)
  • domain/foreman/foreman.ts: stop building Options directly — use ClaudeAgentPort like containerised agents
  • No remaining @anthropic-ai/claude-agent-sdk import outside infrastructure/agents/sdk-adapter.ts

Behavioural parity

  • Streaming-input path for /task/:id/steer preserved (port exposes a write-side handle)
  • Session-resume retry on invalid session_id (agent-runner.ts:780–814) still fires
  • Host-mode foreman still works (cwd workdir, no container)

Tests

  • Existing agent-runner tests pass with adapter swapped for an in-memory fake
  • New test: invalid session_id retry path covered against the fake

Out of scope

  • AgentDispatchPort extraction — that is the orchestrator that comes next
  • Container/MCP port extractions — separate issues

References

  • apps/server/src/domain/agent/claude-port.ts
  • apps/server/src/infrastructure/agents/sdk-adapter.ts
  • apps/server/src/infrastructure/agents/agent-runner.ts
## User story As a maintainer, I want all SDK calls and types to live behind `ClaudeAgentPort` / `SdkClaudeAgent`, so that `agent-runner.ts` consumes only domain types and the SDK can be swapped or mocked at the boundary. ## Acceptance criteria ### Migration - [ ] `agent-runner.ts:715–780`: replace direct `query({...})` call with `claudeAgent.run(request)` via injected `ClaudeAgentPort` - [ ] `agent-runner.ts:24`: drop `SDKMessage` import - [ ] `agent-runner.ts:679`: PR-extract regex moved into adapter (or into a domain helper if used elsewhere) - [ ] `domain/foreman/foreman.ts`: stop building `Options` directly — use `ClaudeAgentPort` like containerised agents - [ ] No remaining `@anthropic-ai/claude-agent-sdk` import outside `infrastructure/agents/sdk-adapter.ts` ### Behavioural parity - [ ] Streaming-input path for `/task/:id/steer` preserved (port exposes a write-side handle) - [ ] Session-resume retry on invalid session_id (`agent-runner.ts:780–814`) still fires - [ ] Host-mode foreman still works (cwd workdir, no container) ### Tests - [ ] Existing agent-runner tests pass with adapter swapped for an in-memory fake - [ ] New test: invalid session_id retry path covered against the fake ## Out of scope - AgentDispatchPort extraction — that is the orchestrator that comes next - Container/MCP port extractions — separate issues ## References - `apps/server/src/domain/agent/claude-port.ts` - `apps/server/src/infrastructure/agents/sdk-adapter.ts` - `apps/server/src/infrastructure/agents/agent-runner.ts`
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#517
No description provided.