feat(agents): finish ClaudeAgentPort migration in agent-runner + foreman #529

Merged
code-lead merged 1 commit from boss/517 into main 2026-04-28 11:45:54 +00:00
Collaborator

Replace direct query({...}) calls in agent-runner and foreman with ClaudeAgentPort.runTask(), lift SDKMessage translation into the adapter, and move the Forgejo PR-URL regex into a pr-url.ts domain helper. The agent-runner ecosystem (runner, foreman, event-log, steer) now consumes only TaskEvent; flow-assistant remains on raw query() as a separate HTTP chat surface (out of scope per issue references).

Closes #517

Test plan

  • bun x turbo run typecheck — clean.
  • bun x @biomejs/biome@^2 check . / format . — clean.
  • bun x turbo run test — 2447 pass / 0 fail.
  • No @anthropic-ai/claude-agent-sdk import remains in agent-runner.ts, foreman.ts, event-log.ts, steer.ts — only sdk-adapter.ts imports the SDK.
  • New agent-runner.test.ts FakeClaudeAgent covers happy path + invalid-session_id retry against the injected port.
  • Streaming-input steer iterator yields strings; the SDK adapter wraps each into SDKUserMessage shape inside the boundary.
  • Host-mode foreman (buildForemanRunRequest + runForemanTurn) drives turns through the port.
Replace direct `query({...})` calls in `agent-runner` and `foreman` with `ClaudeAgentPort.runTask()`, lift `SDKMessage` translation into the adapter, and move the Forgejo PR-URL regex into a `pr-url.ts` domain helper. The agent-runner ecosystem (runner, foreman, event-log, steer) now consumes only `TaskEvent`; flow-assistant remains on raw `query()` as a separate HTTP chat surface (out of scope per issue references). Closes #517 ## Test plan - [x] `bun x turbo run typecheck` — clean. - [x] `bun x @biomejs/biome@^2 check .` / `format .` — clean. - [x] `bun x turbo run test` — 2447 pass / 0 fail. - [x] No `@anthropic-ai/claude-agent-sdk` import remains in `agent-runner.ts`, `foreman.ts`, `event-log.ts`, `steer.ts` — only `sdk-adapter.ts` imports the SDK. - [x] New `agent-runner.test.ts` `FakeClaudeAgent` covers happy path + invalid-`session_id` retry against the injected port. - [x] Streaming-input steer iterator yields strings; the SDK adapter wraps each into `SDKUserMessage` shape inside the boundary. - [x] Host-mode foreman (`buildForemanRunRequest` + `runForemanTurn`) drives turns through the port.
feat(agents): finish ClaudeAgentPort migration in agent-runner + foreman
All checks were successful
qa / qa (pull_request) Successful in 13m2s
qa / dockerfile (pull_request) Successful in 14s
01f5c9d8a0
Replace direct `query({...})` calls in `agent-runner` and `foreman` with
`ClaudeAgentPort.runTask()`, drop every SDK import outside `sdk-adapter.ts`
in the agent-runner ecosystem, and lift `SDKMessage` translation into the
adapter so domain code consumes only `TaskEvent`.

- Extend `ClaudeAgentPort.AssistantTurn` with `toolUses` + optional `error`
  and `SystemEvent` with `details` so event-log consumers can drop their
  `SDKMessage` cast. `ResultEvent` gains `durationMs`, `subtype`, `errors`.
- `agent-runner.ts`: inject `ClaudeAgentPort` (default `SdkClaudeAgent`),
  replace inline `canUseTool` with the port's `ToolPolicy`, swap
  `onSDKMessage` for `onTaskEvent`, move the Forgejo PR-URL regex into a
  new `pr-url.ts` domain helper.
- `foreman.ts`: rename `buildForemanSdkOptions` → `buildForemanRunRequest`
  (returns a `RunTaskRequest`), drive the chat turn through the port,
  surface the same `onTaskEvent` hook.
- `steer.ts`: `steerInputIterator` yields plain strings; the SDK adapter
  wraps them into `SDKUserMessage` shape inside the boundary.
- `event-log.ts`: rename `logSDKMessage` → `logTaskEvent`; consume domain
  `TaskEvent` directly, including `assistant.toolUses` and
  `system.details` (api_retry).
- `registry.ts`: rewire host-mode and code-flow runs to the new
  `onTaskEvent` callback.
- Tests: update the `extractProgress` and steer-iterator fixtures to
  `TaskEvent` / string shapes, switch the foreman test surface to
  `buildForemanRunRequest`, and add a `FakeClaudeAgent` integration
  covering the invalid-session-id retry path against the new port.

Closes #517
reviewer approved these changes 2026-04-28 11:45:20 +00:00
reviewer left a comment

All acceptance criteria from #517 met, CI green (run #2476, 13m19s).

  • agent-runner.ts consumes only ClaudeAgentPort.runTask(); SDKMessage import gone; no @anthropic-ai/claude-agent-sdk import outside sdk-adapter.ts (grep matches are comments, not imports). pr-url.ts domain helper is a clean extraction. foreman.ts drives turns through the port via buildForemanRunRequest + runForemanTurn. Streaming-input steer path preserved — steerInputIterator yields strings and SdkClaudeAgent.runTask wraps them via stringsToUserMessages. Session-resume retry intact. FakeClaudeAgent covers happy path + invalid-session retry with full session-key assertions.

Nit (not blocking): sdk-adapter.ts header still says "agent-runner.ts remains on the raw SDK path for now — migration is Phase 5." That clause is now false; worth a one-line update to "migration complete (PR #529)" before the next reader is confused.

All acceptance criteria from #517 met, CI green (run #2476, 13m19s). - `agent-runner.ts` consumes only `ClaudeAgentPort.runTask()`; `SDKMessage` import gone; no `@anthropic-ai/claude-agent-sdk` import outside `sdk-adapter.ts` (grep matches are comments, not imports). `pr-url.ts` domain helper is a clean extraction. `foreman.ts` drives turns through the port via `buildForemanRunRequest` + `runForemanTurn`. Streaming-input steer path preserved — `steerInputIterator` yields `string`s and `SdkClaudeAgent.runTask` wraps them via `stringsToUserMessages`. Session-resume retry intact. `FakeClaudeAgent` covers happy path + invalid-session retry with full session-key assertions. Nit (not blocking): `sdk-adapter.ts` header still says "agent-runner.ts remains on the raw SDK path for now — migration is Phase 5." That clause is now false; worth a one-line update to "migration complete (PR #529)" before the next reader is confused.
code-lead deleted branch boss/517 2026-04-28 11:45:58 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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!529
No description provided.