From 5f94f0bbffa54c42609e202b4ca4b8a73f3d6011 Mon Sep 17 00:00:00 2001 From: sherlock Date: Fri, 20 Mar 2026 10:00:47 +0530 Subject: [PATCH 01/15] =?UTF-8?q?refactor:=20rename=20claudeCode=20?= =?UTF-8?q?=E2=86=92=20claudeAgent=20to=20align=20with=20upstream=20naming?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preparatory rename for upstream sync. Upstream renamed the provider kind from "claudeCode" to "claudeAgent" and type names accordingly. This rename reduces future sync friction. - Provider kind: "claudeCode" → "claudeAgent" - ClaudeCodeProviderStartOptions → ClaudeProviderStartOptions - ClaudeCodeModelOptions → ClaudeModelOptions - ClaudeCodeAdapter → ClaudeAdapter (files + class) - ClaudeCodeTraitsPicker → ClaudeTraitsPicker --- .docs/provider-architecture.md | 2 +- .plans/17-claude-code.md | 18 ++-- .../OrchestrationEngineHarness.integration.ts | 2 +- .../TestProviderAdapter.integration.ts | 10 +-- .../orchestrationEngine.integration.test.ts | 84 +++++++++---------- apps/server/src/git/Layers/GitManager.test.ts | 2 +- .../Layers/CheckpointReactor.test.ts | 22 ++--- .../Layers/ProviderCommandReactor.test.ts | 14 ++-- .../Layers/ProviderRuntimeIngestion.test.ts | 8 +- ...eAdapter.test.ts => ClaudeAdapter.test.ts} | 82 +++++++++--------- ...{ClaudeCodeAdapter.ts => ClaudeAdapter.ts} | 48 +++++------ .../src/provider/Layers/CodexAdapter.test.ts | 4 +- .../Layers/ProviderAdapterConformance.test.ts | 10 +-- .../Layers/ProviderAdapterRegistry.test.ts | 14 ++-- .../Layers/ProviderAdapterRegistry.ts | 4 +- .../provider/Layers/ProviderService.test.ts | 16 ++-- .../Layers/ProviderSessionDirectory.ts | 2 +- .../src/provider/Services/ClaudeAdapter.ts | 31 +++++++ .../provider/Services/ClaudeCodeAdapter.ts | 31 ------- .../src/provider/Services/ProviderAdapter.ts | 2 +- apps/server/src/serverLayers.ts | 4 +- apps/server/src/wsServer.ts | 4 +- apps/web/src/appSettings.test.ts | 8 +- apps/web/src/appSettings.ts | 10 +-- apps/web/src/components/ChatView.tsx | 26 +++--- apps/web/src/components/ProviderLogo.tsx | 2 +- apps/web/src/components/Sidebar.tsx | 8 +- ...raitsPicker.tsx => ClaudeTraitsPicker.tsx} | 4 +- .../components/chat/ProviderModelPicker.tsx | 8 +- apps/web/src/composerDraftStore.ts | 44 +++++----- apps/web/src/lib/threadDraftDefaults.test.ts | 10 +-- apps/web/src/lib/threadProvider.test.ts | 4 +- apps/web/src/lib/threadProvider.ts | 10 +-- apps/web/src/routes/__root.tsx | 2 +- apps/web/src/routes/_chat.settings.tsx | 4 +- apps/web/src/session-logic.test.ts | 6 +- apps/web/src/session-logic.ts | 4 +- apps/web/src/store.test.ts | 10 +-- packages/contracts/src/model.ts | 20 ++--- packages/contracts/src/orchestration.test.ts | 4 +- packages/contracts/src/orchestration.ts | 10 +-- packages/contracts/src/provider.test.ts | 12 +-- .../contracts/src/providerRuntime.test.ts | 2 +- packages/shared/src/model.test.ts | 26 +++--- packages/shared/src/model.ts | 8 +- 45 files changed, 328 insertions(+), 328 deletions(-) rename apps/server/src/provider/Layers/{ClaudeCodeAdapter.test.ts => ClaudeAdapter.test.ts} (93%) rename apps/server/src/provider/Layers/{ClaudeCodeAdapter.ts => ClaudeAdapter.ts} (97%) create mode 100644 apps/server/src/provider/Services/ClaudeAdapter.ts delete mode 100644 apps/server/src/provider/Services/ClaudeCodeAdapter.ts rename apps/web/src/components/chat/{ClaudeCodeTraitsPicker.tsx => ClaudeTraitsPicker.tsx} (93%) diff --git a/.docs/provider-architecture.md b/.docs/provider-architecture.md index 794b6aa5d5e..9c140b2f4d0 100644 --- a/.docs/provider-architecture.md +++ b/.docs/provider-architecture.md @@ -13,7 +13,7 @@ Methods mirror the `NativeApi` interface defined in `@t3tools/contracts`: - `providers.respondToRequest`, `providers.stopSession` - `shell.openInEditor`, `server.getConfig` -Codex is the only implemented provider. `claudeCode` is reserved in contracts/UI. +Codex is the only implemented provider. `claudeAgent` is reserved in contracts/UI. ## Client transport diff --git a/.plans/17-claude-code.md b/.plans/17-claude-code.md index 822dbd806be..c697011d3c6 100644 --- a/.plans/17-claude-code.md +++ b/.plans/17-claude-code.md @@ -1,6 +1,6 @@ # Plan: Claude Code Integration (Orchestration Architecture) -> **Note -- Multi-provider scope:** This plan was originally written for the Claude Code adapter, but the patterns described here (adapter shape, canonical runtime mapping, resume cursor ownership, provider registry wiring, and orchestration integration) apply equally to the full multi-provider adapter infrastructure now implemented in this PR: **ClaudeCodeAdapter**, **CopilotAdapter**, **OpenCodeAdapter**, **GeminiCliAdapter**, **KiloAdapter**, and **AmpAdapter**. Where the text says "Claude adapter", read it as the reference implementation; every other adapter follows the same contract surface. +> **Note -- Multi-provider scope:** This plan was originally written for the Claude Code adapter, but the patterns described here (adapter shape, canonical runtime mapping, resume cursor ownership, provider registry wiring, and orchestration integration) apply equally to the full multi-provider adapter infrastructure now implemented in this PR: **ClaudeAdapter**, **CopilotAdapter**, **OpenCodeAdapter**, **GeminiCliAdapter**, **KiloAdapter**, and **AmpAdapter**. Where the text says "Claude adapter", read it as the reference implementation; every other adapter follows the same contract surface. ## Why this plan was rewritten @@ -90,8 +90,8 @@ Update/add tests in `packages/contracts/src/*.test.ts` for: Create: -1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` -2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` +1. `apps/server/src/provider/Services/ClaudeAdapter.ts` +2. `apps/server/src/provider/Layers/ClaudeAdapter.ts` Adapter must implement `ProviderAdapterShape`. @@ -181,7 +181,7 @@ const acquireSession = (input: ProviderSessionStartInput) => }, catch: (cause) => new ProviderAdapterProcessError({ - provider: "claudeCode", + provider: "claudeAgent", sessionId: "pending", detail: "Failed to start Claude runtime session.", cause, @@ -200,7 +200,7 @@ const sdkMessageStream = Stream.fromAsyncIterable( session.result, (cause) => new ProviderAdapterProcessError({ - provider: "claudeCode", + provider: "claudeAgent", sessionId, detail: "Claude runtime stream failed.", cause, @@ -223,7 +223,7 @@ const sdkMessageStream = Stream.async `ClaudeCodeAdapter` +1. add `claudeAgent` -> `ClaudeAdapter` 2. ensure `ProviderService.listProviderStatuses()` reports Claude availability ### 3.2 Persist provider binding @@ -309,7 +309,7 @@ Required validation: Update `ProviderCommandReactor` / orchestration flow: -1. If a thread turn start requests `provider: "claudeCode"`, start Claude if no active session exists. +1. If a thread turn start requests `provider: "claudeAgent"`, start Claude if no active session exists. 2. If a thread already has Claude session binding, reuse it. 3. If provider switches between Codex and Claude, explicitly stop/rebind before next send. @@ -405,7 +405,7 @@ Cover: ### 6.2 Adapter layer tests -Add `ClaudeCodeAdapter.test.ts` covering: +Add `ClaudeAdapter.test.ts` covering: 1. session start 2. event mapping diff --git a/apps/server/integration/OrchestrationEngineHarness.integration.ts b/apps/server/integration/OrchestrationEngineHarness.integration.ts index 642f9b3dec8..04433700d34 100644 --- a/apps/server/integration/OrchestrationEngineHarness.integration.ts +++ b/apps/server/integration/OrchestrationEngineHarness.integration.ts @@ -205,7 +205,7 @@ export interface OrchestrationIntegrationHarness { } interface MakeOrchestrationIntegrationHarnessOptions { - readonly provider?: "codex" | "claudeCode"; + readonly provider?: "codex" | "claudeAgent"; readonly realCodex?: boolean; } diff --git a/apps/server/integration/TestProviderAdapter.integration.ts b/apps/server/integration/TestProviderAdapter.integration.ts index 76a9cb8973c..374265a5c70 100644 --- a/apps/server/integration/TestProviderAdapter.integration.ts +++ b/apps/server/integration/TestProviderAdapter.integration.ts @@ -36,7 +36,7 @@ export interface TestTurnResponse { export type FixtureProviderRuntimeEvent = { readonly type: string; readonly eventId: EventId; - readonly provider: "codex" | "claudeCode" | "cursor"; + readonly provider: "codex" | "claudeAgent" | "cursor"; readonly createdAt: string; readonly threadId: string; readonly turnId?: string | undefined; @@ -178,7 +178,7 @@ function normalizeFixtureEvent(rawEvent: Record): ProviderRunti export interface TestProviderAdapterHarness { readonly adapter: ProviderAdapterShape; - readonly provider: "codex" | "claudeCode"; + readonly provider: "codex" | "claudeAgent"; readonly queueTurnResponse: ( threadId: ThreadId, response: TestTurnResponse, @@ -198,7 +198,7 @@ export interface TestProviderAdapterHarness { } interface MakeTestProviderAdapterHarnessOptions { - readonly provider?: "codex" | "claudeCode"; + readonly provider?: "codex" | "claudeAgent"; } function nowIso(): string { @@ -206,7 +206,7 @@ function nowIso(): string { } function sessionNotFound( - provider: "codex" | "claudeCode", + provider: "codex" | "claudeAgent", threadId: ThreadId, ): ProviderAdapterSessionNotFoundError { return new ProviderAdapterSessionNotFoundError({ @@ -216,7 +216,7 @@ function sessionNotFound( } function missingSessionEffect( - provider: "codex" | "claudeCode", + provider: "codex" | "claudeAgent", threadId: ThreadId, ): Effect.Effect { return Effect.fail(sessionNotFound(provider, threadId)); diff --git a/apps/server/integration/orchestrationEngine.integration.test.ts b/apps/server/integration/orchestrationEngine.integration.test.ts index 5223ead40b5..4102b3d86eb 100644 --- a/apps/server/integration/orchestrationEngine.integration.test.ts +++ b/apps/server/integration/orchestrationEngine.integration.test.ts @@ -36,7 +36,7 @@ const PROJECT_ID = asProjectId("project-1"); const THREAD_ID = ThreadId.makeUnsafe("thread-1"); const FIXTURE_TURN_ID = "fixture-turn"; const APPROVAL_REQUEST_ID = asApprovalRequestId("req-approval-1"); -type IntegrationProvider = "codex" | "claudeCode"; +type IntegrationProvider = "codex" | "claudeAgent"; function nowIso() { return new Date().toISOString(); @@ -883,7 +883,7 @@ it.live( ), ); -it.live("starts a claudeCode session on first turn when provider is requested", () => +it.live("starts a claudeAgent session on first turn when provider is requested", () => withHarness( (harness) => Effect.gen(function* () { @@ -893,20 +893,20 @@ it.live("starts a claudeCode session on first turn when provider is requested", events: [ { type: "turn.started", - ...runtimeBase("evt-claude-start-1", "2026-02-24T10:10:00.000Z", "claudeCode"), + ...runtimeBase("evt-claude-start-1", "2026-02-24T10:10:00.000Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", - ...runtimeBase("evt-claude-start-2", "2026-02-24T10:10:00.050Z", "claudeCode"), + ...runtimeBase("evt-claude-start-2", "2026-02-24T10:10:00.050Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Claude first turn.\n", }, { type: "turn.completed", - ...runtimeBase("evt-claude-start-3", "2026-02-24T10:10:00.100Z", "claudeCode"), + ...runtimeBase("evt-claude-start-3", "2026-02-24T10:10:00.100Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", @@ -919,25 +919,25 @@ it.live("starts a claudeCode session on first turn when provider is requested", commandId: "cmd-turn-start-claude-initial", messageId: "msg-user-claude-initial", text: "Use Claude", - provider: "claudeCode", + provider: "claudeAgent", }); const thread = yield* harness.waitForThread( THREAD_ID, (entry) => - entry.session?.providerName === "claudeCode" && + entry.session?.providerName === "claudeAgent" && entry.session.status === "ready" && entry.messages.some( (message) => message.role === "assistant" && message.text === "Claude first turn.\n", ), ); - assert.equal(thread.session?.providerName, "claudeCode"); + assert.equal(thread.session?.providerName, "claudeAgent"); }), - "claudeCode", + "claudeAgent", ), ); -it.live("recovers claudeCode sessions after provider stopAll using persisted resume state", () => +it.live("recovers claudeAgent sessions after provider stopAll using persisted resume state", () => withHarness( (harness) => Effect.gen(function* () { @@ -947,20 +947,20 @@ it.live("recovers claudeCode sessions after provider stopAll using persisted res events: [ { type: "turn.started", - ...runtimeBase("evt-claude-recover-1", "2026-02-24T10:11:00.000Z", "claudeCode"), + ...runtimeBase("evt-claude-recover-1", "2026-02-24T10:11:00.000Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", - ...runtimeBase("evt-claude-recover-2", "2026-02-24T10:11:00.050Z", "claudeCode"), + ...runtimeBase("evt-claude-recover-2", "2026-02-24T10:11:00.050Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Turn before restart.\n", }, { type: "turn.completed", - ...runtimeBase("evt-claude-recover-3", "2026-02-24T10:11:00.100Z", "claudeCode"), + ...runtimeBase("evt-claude-recover-3", "2026-02-24T10:11:00.100Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", @@ -973,7 +973,7 @@ it.live("recovers claudeCode sessions after provider stopAll using persisted res commandId: "cmd-turn-start-claude-recover-1", messageId: "msg-user-claude-recover-1", text: "Before restart", - provider: "claudeCode", + provider: "claudeAgent", }); yield* harness.waitForThread( @@ -993,20 +993,20 @@ it.live("recovers claudeCode sessions after provider stopAll using persisted res events: [ { type: "turn.started", - ...runtimeBase("evt-claude-recover-4", "2026-02-24T10:11:01.000Z", "claudeCode"), + ...runtimeBase("evt-claude-recover-4", "2026-02-24T10:11:01.000Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", - ...runtimeBase("evt-claude-recover-5", "2026-02-24T10:11:01.050Z", "claudeCode"), + ...runtimeBase("evt-claude-recover-5", "2026-02-24T10:11:01.050Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Turn after restart.\n", }, { type: "turn.completed", - ...runtimeBase("evt-claude-recover-6", "2026-02-24T10:11:01.100Z", "claudeCode"), + ...runtimeBase("evt-claude-recover-6", "2026-02-24T10:11:01.100Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", @@ -1029,20 +1029,20 @@ it.live("recovers claudeCode sessions after provider stopAll using persisted res const recoveredThread = yield* harness.waitForThread( THREAD_ID, (entry) => - entry.session?.providerName === "claudeCode" && + entry.session?.providerName === "claudeAgent" && entry.messages.some( (message) => message.role === "user" && message.text === "After restart", ) && !entry.activities.some((activity) => activity.kind === "provider.turn.start.failed"), ); - assert.equal(recoveredThread.session?.providerName, "claudeCode"); + assert.equal(recoveredThread.session?.providerName, "claudeAgent"); assert.equal(recoveredThread.session?.threadId, "thread-1"); }), - "claudeCode", + "claudeAgent", ), ); -it.live("forwards claudeCode approval responses to the provider session", () => +it.live("forwards claudeAgent approval responses to the provider session", () => withHarness( (harness) => Effect.gen(function* () { @@ -1052,13 +1052,13 @@ it.live("forwards claudeCode approval responses to the provider session", () => events: [ { type: "turn.started", - ...runtimeBase("evt-claude-approval-1", "2026-02-24T10:12:00.000Z", "claudeCode"), + ...runtimeBase("evt-claude-approval-1", "2026-02-24T10:12:00.000Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "approval.requested", - ...runtimeBase("evt-claude-approval-2", "2026-02-24T10:12:00.050Z", "claudeCode"), + ...runtimeBase("evt-claude-approval-2", "2026-02-24T10:12:00.050Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, requestId: APPROVAL_REQUEST_ID, @@ -1067,7 +1067,7 @@ it.live("forwards claudeCode approval responses to the provider session", () => }, { type: "turn.completed", - ...runtimeBase("evt-claude-approval-3", "2026-02-24T10:12:00.100Z", "claudeCode"), + ...runtimeBase("evt-claude-approval-3", "2026-02-24T10:12:00.100Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", @@ -1080,7 +1080,7 @@ it.live("forwards claudeCode approval responses to the provider session", () => commandId: "cmd-turn-start-claude-approval", messageId: "msg-user-claude-approval", text: "Need approval", - provider: "claudeCode", + provider: "claudeAgent", }); const thread = yield* harness.waitForThread(THREAD_ID, (entry) => @@ -1109,11 +1109,11 @@ it.live("forwards claudeCode approval responses to the provider session", () => ); assert.equal(approvalResponses[0]?.decision, "accept"); }), - "claudeCode", + "claudeAgent", ), ); -it.live("forwards thread.turn.interrupt to claudeCode provider sessions", () => +it.live("forwards thread.turn.interrupt to claudeAgent provider sessions", () => withHarness( (harness) => Effect.gen(function* () { @@ -1123,20 +1123,20 @@ it.live("forwards thread.turn.interrupt to claudeCode provider sessions", () => events: [ { type: "turn.started", - ...runtimeBase("evt-claude-interrupt-1", "2026-02-24T10:13:00.000Z", "claudeCode"), + ...runtimeBase("evt-claude-interrupt-1", "2026-02-24T10:13:00.000Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", - ...runtimeBase("evt-claude-interrupt-2", "2026-02-24T10:13:00.050Z", "claudeCode"), + ...runtimeBase("evt-claude-interrupt-2", "2026-02-24T10:13:00.050Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "Long running output.\n", }, { type: "turn.completed", - ...runtimeBase("evt-claude-interrupt-3", "2026-02-24T10:13:00.100Z", "claudeCode"), + ...runtimeBase("evt-claude-interrupt-3", "2026-02-24T10:13:00.100Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", @@ -1149,7 +1149,7 @@ it.live("forwards thread.turn.interrupt to claudeCode provider sessions", () => commandId: "cmd-turn-start-claude-interrupt", messageId: "msg-user-claude-interrupt", text: "Start long turn", - provider: "claudeCode", + provider: "claudeAgent", }); const thread = yield* harness.waitForThread( @@ -1175,11 +1175,11 @@ it.live("forwards thread.turn.interrupt to claudeCode provider sessions", () => ); assert.equal(interruptCalls.length, 1); }), - "claudeCode", + "claudeAgent", ), ); -it.live("reverts claudeCode turns and rolls back provider conversation state", () => +it.live("reverts claudeAgent turns and rolls back provider conversation state", () => withHarness( (harness) => Effect.gen(function* () { @@ -1189,20 +1189,20 @@ it.live("reverts claudeCode turns and rolls back provider conversation state", ( events: [ { type: "turn.started", - ...runtimeBase("evt-claude-revert-1", "2026-02-24T10:14:00.000Z", "claudeCode"), + ...runtimeBase("evt-claude-revert-1", "2026-02-24T10:14:00.000Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", - ...runtimeBase("evt-claude-revert-2", "2026-02-24T10:14:00.050Z", "claudeCode"), + ...runtimeBase("evt-claude-revert-2", "2026-02-24T10:14:00.050Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "README -> v2\n", }, { type: "turn.completed", - ...runtimeBase("evt-claude-revert-3", "2026-02-24T10:14:00.100Z", "claudeCode"), + ...runtimeBase("evt-claude-revert-3", "2026-02-24T10:14:00.100Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", @@ -1219,7 +1219,7 @@ it.live("reverts claudeCode turns and rolls back provider conversation state", ( commandId: "cmd-turn-start-claude-revert-1", messageId: "msg-user-claude-revert-1", text: "First Claude edit", - provider: "claudeCode", + provider: "claudeAgent", }); yield* harness.waitForThread( @@ -1232,20 +1232,20 @@ it.live("reverts claudeCode turns and rolls back provider conversation state", ( events: [ { type: "turn.started", - ...runtimeBase("evt-claude-revert-4", "2026-02-24T10:14:01.000Z", "claudeCode"), + ...runtimeBase("evt-claude-revert-4", "2026-02-24T10:14:01.000Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, }, { type: "message.delta", - ...runtimeBase("evt-claude-revert-5", "2026-02-24T10:14:01.050Z", "claudeCode"), + ...runtimeBase("evt-claude-revert-5", "2026-02-24T10:14:01.050Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, delta: "README -> v3\n", }, { type: "turn.completed", - ...runtimeBase("evt-claude-revert-6", "2026-02-24T10:14:01.100Z", "claudeCode"), + ...runtimeBase("evt-claude-revert-6", "2026-02-24T10:14:01.100Z", "claudeAgent"), threadId: THREAD_ID, turnId: FIXTURE_TURN_ID, status: "completed", @@ -1269,7 +1269,7 @@ it.live("reverts claudeCode turns and rolls back provider conversation state", ( (entry) => entry.latestTurn?.turnId === "turn-2" && entry.checkpoints.length === 2 && - entry.session?.providerName === "claudeCode", + entry.session?.providerName === "claudeAgent", ); yield* harness.engine.dispatch({ @@ -1296,6 +1296,6 @@ it.live("reverts claudeCode turns and rolls back provider conversation state", ( ); assert.deepEqual(harness.adapterHarness!.getRollbackCalls(THREAD_ID), [1]); }), - "claudeCode", + "claudeAgent", ), ); diff --git a/apps/server/src/git/Layers/GitManager.test.ts b/apps/server/src/git/Layers/GitManager.test.ts index f60dc7c1007..78f8c3cac08 100644 --- a/apps/server/src/git/Layers/GitManager.test.ts +++ b/apps/server/src/git/Layers/GitManager.test.ts @@ -454,7 +454,7 @@ function runStackedAction( provider?: | "codex" | "copilot" - | "claudeCode" + | "claudeAgent" | "cursor" | "opencode" | "geminiCli" diff --git a/apps/server/src/orchestration/Layers/CheckpointReactor.test.ts b/apps/server/src/orchestration/Layers/CheckpointReactor.test.ts index 64547bd0efe..cf8eab18c88 100644 --- a/apps/server/src/orchestration/Layers/CheckpointReactor.test.ts +++ b/apps/server/src/orchestration/Layers/CheckpointReactor.test.ts @@ -48,7 +48,7 @@ type LegacyProviderRuntimeEvent = { readonly provider: | "codex" | "copilot" - | "claudeCode" + | "claudeAgent" | "cursor" | "opencode" | "geminiCli" @@ -67,7 +67,7 @@ function createProviderServiceHarness( cwd: string, hasSession = true, sessionCwd = cwd, - providerName: "codex" | "claudeCode" = "codex", + providerName: "codex" | "claudeAgent" = "codex", ) { const now = new Date().toISOString(); const runtimeEventPubSub = Effect.runSync(PubSub.unbounded()); @@ -244,7 +244,7 @@ describe("CheckpointReactor", () => { readonly projectWorkspaceRoot?: string; readonly threadWorktreePath?: string | null; readonly providerSessionCwd?: string; - readonly providerName?: "codex" | "claudeCode"; + readonly providerName?: "codex" | "claudeAgent"; }) { const cwd = createGitRepository(); tempDirs.push(cwd); @@ -487,10 +487,10 @@ describe("CheckpointReactor", () => { expect(thread.checkpoints[0]?.checkpointTurnCount).toBe(1); }); - it("captures pre-turn and completion checkpoints for claudeCode runtime events", async () => { + it("captures pre-turn and completion checkpoints for claudeAgent runtime events", async () => { const harness = await createHarness({ seedFilesystemCheckpoints: false, - providerName: "claudeCode", + providerName: "claudeAgent", }); const createdAt = new Date().toISOString(); @@ -502,7 +502,7 @@ describe("CheckpointReactor", () => { session: { threadId: ThreadId.makeUnsafe("thread-1"), status: "ready", - providerName: "claudeCode", + providerName: "claudeAgent", runtimeMode: "approval-required", activeTurnId: null, lastError: null, @@ -515,7 +515,7 @@ describe("CheckpointReactor", () => { harness.provider.emit({ type: "turn.started", eventId: EventId.makeUnsafe("evt-turn-started-claude-1"), - provider: "claudeCode", + provider: "claudeAgent", createdAt: new Date().toISOString(), threadId: ThreadId.makeUnsafe("thread-1"), turnId: asTurnId("turn-claude-1"), @@ -529,7 +529,7 @@ describe("CheckpointReactor", () => { harness.provider.emit({ type: "turn.completed", eventId: EventId.makeUnsafe("evt-turn-completed-claude-1"), - provider: "claudeCode", + provider: "claudeAgent", createdAt: new Date().toISOString(), threadId: ThreadId.makeUnsafe("thread-1"), turnId: asTurnId("turn-claude-1"), @@ -863,8 +863,8 @@ describe("CheckpointReactor", () => { ).toBe(false); }); - it("executes provider revert and emits thread.reverted for claudeCode sessions", async () => { - const harness = await createHarness({ providerName: "claudeCode" }); + it("executes provider revert and emits thread.reverted for claudeAgent sessions", async () => { + const harness = await createHarness({ providerName: "claudeAgent" }); const createdAt = new Date().toISOString(); await Effect.runPromise( @@ -875,7 +875,7 @@ describe("CheckpointReactor", () => { session: { threadId: ThreadId.makeUnsafe("thread-1"), status: "ready", - providerName: "claudeCode", + providerName: "claudeAgent", runtimeMode: "approval-required", activeTurnId: null, lastError: null, diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts index 4c530ecec9a..b27d5ed5309 100644 --- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts +++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts @@ -98,7 +98,7 @@ describe("ProviderCommandReactor", () => { input !== null && "provider" in input && (input.provider === "codex" || - input.provider === "claudeCode" || + input.provider === "claudeAgent" || input.provider === "cursor") ? input.provider : "codex"; @@ -404,7 +404,7 @@ describe("ProviderCommandReactor", () => { text: "hello claude", attachments: [], }, - provider: "claudeCode", + provider: "claudeAgent", interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", createdAt: now, @@ -414,7 +414,7 @@ describe("ProviderCommandReactor", () => { await waitFor(() => harness.startSession.mock.calls.length === 1); await waitFor(() => harness.sendTurn.mock.calls.length === 1); expect(harness.startSession.mock.calls[0]?.[1]).toMatchObject({ - provider: "claudeCode", + provider: "claudeAgent", cwd: "/tmp/provider-project", model: "gpt-5-codex", runtimeMode: "approval-required", @@ -422,7 +422,7 @@ describe("ProviderCommandReactor", () => { const readModel = await Effect.runPromise(harness.engine.getReadModel()); const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); - expect(thread?.session?.providerName).toBe("claudeCode"); + expect(thread?.session?.providerName).toBe("claudeAgent"); expect(thread?.session?.threadId).toBe("thread-1"); }); @@ -736,7 +736,7 @@ describe("ProviderCommandReactor", () => { text: "second", attachments: [], }, - provider: "claudeCode", + provider: "claudeAgent", interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, runtimeMode: "approval-required", createdAt: now, @@ -749,7 +749,7 @@ describe("ProviderCommandReactor", () => { expect(harness.stopSession.mock.calls.length).toBe(0); expect(harness.startSession.mock.calls[1]?.[1]).toMatchObject({ threadId: ThreadId.makeUnsafe("thread-1"), - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "approval-required", }); expect(harness.startSession.mock.calls[1]?.[1]).not.toHaveProperty("resumeCursor"); @@ -757,7 +757,7 @@ describe("ProviderCommandReactor", () => { const readModel = await Effect.runPromise(harness.engine.getReadModel()); const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); expect(thread?.session?.threadId).toBe("thread-1"); - expect(thread?.session?.providerName).toBe("claudeCode"); + expect(thread?.session?.providerName).toBe("claudeAgent"); expect(thread?.session?.runtimeMode).toBe("approval-required"); }); diff --git a/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts b/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts index e4c0c672761..ddc61f569a7 100644 --- a/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts +++ b/apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts @@ -49,7 +49,7 @@ type LegacyProviderRuntimeEvent = { readonly provider: | "codex" | "copilot" - | "claudeCode" + | "claudeAgent" | "cursor" | "opencode" | "geminiCli" @@ -423,7 +423,7 @@ describe("ProviderRuntimeIngestion", () => { session: { threadId: ThreadId.makeUnsafe("thread-1"), status: "ready", - providerName: "claudeCode", + providerName: "claudeAgent", runtimeMode: "approval-required", activeTurnId: null, updatedAt: seededAt, @@ -436,7 +436,7 @@ describe("ProviderRuntimeIngestion", () => { harness.emit({ type: "turn.started", eventId: asEventId("evt-turn-started-claude-placeholder"), - provider: "claudeCode", + provider: "claudeAgent", createdAt: new Date().toISOString(), threadId: asThreadId("thread-1"), turnId: asTurnId("turn-claude-placeholder"), @@ -452,7 +452,7 @@ describe("ProviderRuntimeIngestion", () => { harness.emit({ type: "turn.completed", eventId: asEventId("evt-turn-completed-claude-placeholder"), - provider: "claudeCode", + provider: "claudeAgent", createdAt: new Date().toISOString(), threadId: asThreadId("thread-1"), turnId: asTurnId("turn-claude-placeholder"), diff --git a/apps/server/src/provider/Layers/ClaudeCodeAdapter.test.ts b/apps/server/src/provider/Layers/ClaudeAdapter.test.ts similarity index 93% rename from apps/server/src/provider/Layers/ClaudeCodeAdapter.test.ts rename to apps/server/src/provider/Layers/ClaudeAdapter.test.ts index 46c444f2a37..8d8d74ce9ae 100644 --- a/apps/server/src/provider/Layers/ClaudeCodeAdapter.test.ts +++ b/apps/server/src/provider/Layers/ClaudeAdapter.test.ts @@ -11,11 +11,11 @@ import { assert, describe, it } from "@effect/vitest"; import { Effect, Fiber, Random, Stream } from "effect"; import { ProviderAdapterValidationError } from "../Errors.ts"; -import { ClaudeCodeAdapter } from "../Services/ClaudeCodeAdapter.ts"; +import { ClaudeAdapter } from "../Services/ClaudeAdapter.ts"; import { - makeClaudeCodeAdapterLive, - type ClaudeCodeAdapterLiveOptions, -} from "./ClaudeCodeAdapter.ts"; + makeClaudeAdapterLive, + type ClaudeAdapterLiveOptions, +} from "./ClaudeAdapter.ts"; class FakeClaudeQuery implements AsyncIterable { private readonly queue: Array = []; @@ -98,7 +98,7 @@ class FakeClaudeQuery implements AsyncIterable { } interface Harness { - readonly layer: ReturnType; + readonly layer: ReturnType; readonly query: FakeClaudeQuery; readonly getLastCreateQueryInput: () => | { @@ -110,7 +110,7 @@ interface Harness { function makeHarness(config?: { readonly nativeEventLogPath?: string; - readonly nativeEventLogger?: ClaudeCodeAdapterLiveOptions["nativeEventLogger"]; + readonly nativeEventLogger?: ClaudeAdapterLiveOptions["nativeEventLogger"]; }): Harness { const query = new FakeClaudeQuery(); let createInput: @@ -120,7 +120,7 @@ function makeHarness(config?: { } | undefined; - const adapterOptions: ClaudeCodeAdapterLiveOptions = { + const adapterOptions: ClaudeAdapterLiveOptions = { createQuery: (input) => { createInput = input; return query; @@ -138,7 +138,7 @@ function makeHarness(config?: { }; return { - layer: makeClaudeCodeAdapterLive(adapterOptions), + layer: makeClaudeAdapterLive(adapterOptions), query, getLastCreateQueryInput: () => createInput, }; @@ -163,11 +163,11 @@ function makeDeterministicRandomService(seed = 0x1234_5678): { const THREAD_ID = ThreadId.makeUnsafe("thread-claude-1"); const RESUME_THREAD_ID = ThreadId.makeUnsafe("thread-claude-resume"); -describe("ClaudeCodeAdapterLive", () => { - it.effect("returns validation error for non-claudeCode provider on startSession", () => { +describe("ClaudeAdapterLive", () => { + it.effect("returns validation error for non-claudeAgent provider on startSession", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const result = yield* adapter .startSession({ threadId: THREAD_ID, provider: "codex", runtimeMode: "full-access" }) .pipe(Effect.result); @@ -179,9 +179,9 @@ describe("ClaudeCodeAdapterLive", () => { assert.deepEqual( result.failure, new ProviderAdapterValidationError({ - provider: "claudeCode", + provider: "claudeAgent", operation: "startSession", - issue: "Expected provider 'claudeCode' but received 'codex'.", + issue: "Expected provider 'claudeAgent' but received 'codex'.", }), ); }).pipe( @@ -193,10 +193,10 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("derives bypass permission mode from full-access runtime policy", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); @@ -213,13 +213,13 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("keeps explicit claude permission mode over runtime-derived defaults", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", providerOptions: { - claudeCode: { + claudeAgent: { permissionMode: "plan", }, }, @@ -247,10 +247,10 @@ describe("ClaudeCodeAdapterLive", () => { process.env.PATH = "/usr/bin:/bin"; return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); @@ -296,7 +296,7 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("maps Claude stream/runtime messages to canonical provider runtime events", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const runtimeEventsFiber = yield* Stream.take(adapter.streamEvents, 11).pipe( Stream.runCollect, @@ -305,7 +305,7 @@ describe("ClaudeCodeAdapterLive", () => { const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", model: "claude-sonnet-4-5", runtimeMode: "full-access", }); @@ -435,7 +435,7 @@ describe("ClaudeCodeAdapterLive", () => { () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const runtimeEventsFiber = yield* Stream.take(adapter.streamEvents, 9).pipe( Stream.runCollect, @@ -444,7 +444,7 @@ describe("ClaudeCodeAdapterLive", () => { const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); @@ -527,7 +527,7 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("falls back to assistant payload text when stream deltas are absent", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const runtimeEventsFiber = yield* Stream.take(adapter.streamEvents, 9).pipe( Stream.runCollect, @@ -536,7 +536,7 @@ describe("ClaudeCodeAdapterLive", () => { const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); @@ -597,7 +597,7 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("does not fabricate provider thread ids before first SDK session_id", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const runtimeEventsFiber = yield* Stream.take(adapter.streamEvents, 5).pipe( Stream.runCollect, @@ -606,7 +606,7 @@ describe("ClaudeCodeAdapterLive", () => { const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); assert.equal(session.threadId, THREAD_ID); @@ -687,11 +687,11 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("bridges approval request/response lifecycle through canUseTool", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "approval-required", }); @@ -764,11 +764,11 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("passes parsed resume cursor values to Claude query options", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const session = yield* adapter.startSession({ threadId: RESUME_THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", resumeCursor: { threadId: "resume-thread-1", resume: "550e8400-e29b-41d4-a716-446655440000", @@ -798,11 +798,11 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("does not synthesize resume session id from generated thread ids", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); @@ -821,11 +821,11 @@ describe("ClaudeCodeAdapterLive", () => { () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); @@ -845,11 +845,11 @@ describe("ClaudeCodeAdapterLive", () => { it.effect("updates model on sendTurn when model override is provided", () => { const harness = makeHarness(); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); yield* adapter.sendTurn({ @@ -886,11 +886,11 @@ describe("ClaudeCodeAdapterLive", () => { }, }); return Effect.gen(function* () { - const adapter = yield* ClaudeCodeAdapter; + const adapter = yield* ClaudeAdapter; const session = yield* adapter.startSession({ threadId: THREAD_ID, - provider: "claudeCode", + provider: "claudeAgent", runtimeMode: "full-access", }); const turn = yield* adapter.sendTurn({ @@ -933,7 +933,7 @@ describe("ClaudeCodeAdapterLive", () => { assert.equal(nativeEvents.length > 0, true); assert.equal( - nativeEvents.some((record) => record.event?.provider === "claudeCode"), + nativeEvents.some((record) => record.event?.provider === "claudeAgent"), true, ); assert.equal( diff --git a/apps/server/src/provider/Layers/ClaudeCodeAdapter.ts b/apps/server/src/provider/Layers/ClaudeAdapter.ts similarity index 97% rename from apps/server/src/provider/Layers/ClaudeCodeAdapter.ts rename to apps/server/src/provider/Layers/ClaudeAdapter.ts index 5f1a328b516..a5d095c8c64 100644 --- a/apps/server/src/provider/Layers/ClaudeCodeAdapter.ts +++ b/apps/server/src/provider/Layers/ClaudeAdapter.ts @@ -1,10 +1,10 @@ /** - * ClaudeCodeAdapterLive - Scoped live implementation for the Claude Code provider adapter. + * ClaudeAdapterLive - Scoped live implementation for the Claude Code provider adapter. * * Wraps `@anthropic-ai/claude-agent-sdk` query sessions behind the generic * provider adapter contract and emits canonical runtime events. * - * @module ClaudeCodeAdapterLive + * @module ClaudeAdapterLive */ import { createRequire } from "node:module"; import * as Path from "node:path"; @@ -50,13 +50,13 @@ import { type ProviderAdapterError, } from "../Errors.ts"; import { getProviderCapabilities } from "../Services/ProviderAdapter.ts"; -import { ClaudeCodeAdapter, type ClaudeCodeAdapterShape } from "../Services/ClaudeCodeAdapter.ts"; +import { ClaudeAdapter, type ClaudeAdapterShape } from "../Services/ClaudeAdapter.ts"; import { type EventNdjsonLogger, makeEventNdjsonLogger } from "./EventNdjsonLogger.ts"; import { toMessage } from "../toMessage.ts"; import { createLogger } from "../../logger"; -const PROVIDER = "claudeCode" as const; +const PROVIDER = "claudeAgent" as const; const logger = createLogger(PROVIDER); /** @@ -237,7 +237,7 @@ interface ClaudeQueryRuntime extends AsyncIterable { readonly close: () => void; } -export interface ClaudeCodeAdapterLiveOptions { +export interface ClaudeAdapterLiveOptions { readonly createQuery?: (input: { readonly prompt: AsyncIterable; readonly options: ClaudeQueryOptions; @@ -622,7 +622,7 @@ function sdkNativeItemId(message: SDKMessageLoose): string | undefined { return undefined; } -function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { +function makeClaudeAdapter(options?: ClaudeAdapterLiveOptions) { return Effect.gen(function* () { const nativeEventLogger = options?.nativeEventLogger ?? @@ -1564,7 +1564,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { return Effect.succeed(context); }; - const startSession: ClaudeCodeAdapterShape["startSession"] = (input) => + const startSession: ClaudeAdapterShape["startSession"] = (input) => Effect.gen(function* () { if (input.provider !== undefined && input.provider !== PROVIDER) { return yield* new ProviderAdapterValidationError({ @@ -1723,12 +1723,12 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { }), ); - const providerOptions = input.providerOptions?.claudeCode; - const claudeCodeModelOptions = input.modelOptions?.claudeCode; + const providerOptions = input.providerOptions?.claudeAgent; + const claudeAgentModelOptions = input.modelOptions?.claudeAgent; const permissionMode = toPermissionMode(providerOptions?.permissionMode) ?? (input.runtimeMode === "full-access" ? "bypassPermissions" : undefined); - const effort = claudeCodeModelOptions?.effort as EffortLevel | undefined; + const effort = claudeAgentModelOptions?.effort as EffortLevel | undefined; const pathToClaudeCodeExecutable = yield* Effect.try({ try: () => @@ -1890,7 +1890,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { }; }); - const sendTurn: ClaudeCodeAdapterShape["sendTurn"] = (input) => + const sendTurn: ClaudeAdapterShape["sendTurn"] = (input) => Effect.gen(function* () { const context = yield* requireSession(input.threadId); @@ -1963,7 +1963,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { }; }); - const interruptTurn: ClaudeCodeAdapterShape["interruptTurn"] = (threadId, _turnId) => + const interruptTurn: ClaudeAdapterShape["interruptTurn"] = (threadId, _turnId) => Effect.gen(function* () { const context = yield* requireSession(threadId); yield* Effect.tryPromise({ @@ -1972,13 +1972,13 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { }); }); - const readThread: ClaudeCodeAdapterShape["readThread"] = (threadId) => + const readThread: ClaudeAdapterShape["readThread"] = (threadId) => Effect.gen(function* () { const context = yield* requireSession(threadId); return yield* snapshotThread(context); }); - const rollbackThread: ClaudeCodeAdapterShape["rollbackThread"] = (threadId, _numTurns) => + const rollbackThread: ClaudeAdapterShape["rollbackThread"] = (threadId, _numTurns) => Effect.gen(function* () { yield* requireSession(threadId); return yield* new ProviderAdapterRequestError({ @@ -1989,7 +1989,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { }); }); - const respondToRequest: ClaudeCodeAdapterShape["respondToRequest"] = ( + const respondToRequest: ClaudeAdapterShape["respondToRequest"] = ( threadId, requestId, decision, @@ -2009,7 +2009,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { yield* Deferred.succeed(pending.decision, decision); }); - const respondToUserInput: ClaudeCodeAdapterShape["respondToUserInput"] = ( + const respondToUserInput: ClaudeAdapterShape["respondToUserInput"] = ( threadId, requestId, _answers, @@ -2022,7 +2022,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { }), ); - const stopSession: ClaudeCodeAdapterShape["stopSession"] = (threadId) => + const stopSession: ClaudeAdapterShape["stopSession"] = (threadId) => Effect.gen(function* () { const context = yield* requireSession(threadId); yield* stopSessionInternal(context, { @@ -2030,16 +2030,16 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { }); }); - const listSessions: ClaudeCodeAdapterShape["listSessions"] = () => + const listSessions: ClaudeAdapterShape["listSessions"] = () => Effect.sync(() => Array.from(sessions.values(), ({ session }) => ({ ...session }))); - const hasSession: ClaudeCodeAdapterShape["hasSession"] = (threadId) => + const hasSession: ClaudeAdapterShape["hasSession"] = (threadId) => Effect.sync(() => { const context = sessions.get(threadId); return context !== undefined && !context.stopped; }); - const stopAll: ClaudeCodeAdapterShape["stopAll"] = () => + const stopAll: ClaudeAdapterShape["stopAll"] = () => Effect.forEach( sessions, ([, context]) => @@ -2075,12 +2075,12 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { hasSession, stopAll, streamEvents: Stream.fromQueue(runtimeEventQueue), - } satisfies ClaudeCodeAdapterShape; + } satisfies ClaudeAdapterShape; }); } -export const ClaudeCodeAdapterLive = Layer.effect(ClaudeCodeAdapter, makeClaudeCodeAdapter()); +export const ClaudeAdapterLive = Layer.effect(ClaudeAdapter, makeClaudeAdapter()); -export function makeClaudeCodeAdapterLive(options?: ClaudeCodeAdapterLiveOptions) { - return Layer.effect(ClaudeCodeAdapter, makeClaudeCodeAdapter(options)); +export function makeClaudeAdapterLive(options?: ClaudeAdapterLiveOptions) { + return Layer.effect(ClaudeAdapter, makeClaudeAdapter(options)); } diff --git a/apps/server/src/provider/Layers/CodexAdapter.test.ts b/apps/server/src/provider/Layers/CodexAdapter.test.ts index 394b2754563..8cdca0cb0a7 100644 --- a/apps/server/src/provider/Layers/CodexAdapter.test.ts +++ b/apps/server/src/provider/Layers/CodexAdapter.test.ts @@ -172,7 +172,7 @@ validationLayer("CodexAdapterLive validation", (it) => { const adapter = yield* CodexAdapter; const result = yield* adapter .startSession({ - provider: "claudeCode", + provider: "claudeAgent", threadId: asThreadId("thread-1"), runtimeMode: "full-access", }) @@ -184,7 +184,7 @@ validationLayer("CodexAdapterLive validation", (it) => { new ProviderAdapterValidationError({ provider: "codex", operation: "startSession", - issue: "Expected provider 'codex' but received 'claudeCode'.", + issue: "Expected provider 'codex' but received 'claudeAgent'.", }), ); assert.equal(validationManager.startSessionImpl.mock.calls.length, 0); diff --git a/apps/server/src/provider/Layers/ProviderAdapterConformance.test.ts b/apps/server/src/provider/Layers/ProviderAdapterConformance.test.ts index ec40f84752e..2925bf94cfe 100644 --- a/apps/server/src/provider/Layers/ProviderAdapterConformance.test.ts +++ b/apps/server/src/provider/Layers/ProviderAdapterConformance.test.ts @@ -7,7 +7,7 @@ import { AmpServerManager } from "../../ampServerManager.ts"; import { GeminiCliServerManager } from "../../geminiCliServerManager.ts"; import { ServerConfig } from "../../config.ts"; import { makeAmpAdapterLive } from "./AmpAdapter.ts"; -import { makeClaudeCodeAdapterLive } from "./ClaudeCodeAdapter.ts"; +import { makeClaudeAdapterLive } from "./ClaudeAdapter.ts"; import { makeCodexAdapterLive } from "./CodexAdapter.ts"; import { makeCopilotAdapterLive } from "./CopilotAdapter.ts"; import { makeCursorAdapterLive } from "./CursorAdapter.ts"; @@ -18,7 +18,7 @@ import { validateProviderAdapterConformance, } from "../Services/ProviderAdapter.ts"; import { AmpAdapter } from "../Services/AmpAdapter.ts"; -import { ClaudeCodeAdapter } from "../Services/ClaudeCodeAdapter.ts"; +import { ClaudeAdapter } from "../Services/ClaudeAdapter.ts"; import { CodexAdapter } from "../Services/CodexAdapter.ts"; import { CopilotAdapter } from "../Services/CopilotAdapter.ts"; import { CursorAdapter } from "../Services/CursorAdapter.ts"; @@ -57,7 +57,7 @@ const copilotLayer = makeCopilotAdapterLive({ Layer.provideMerge(NodeServices.layer), ); -const claudeLayer = makeClaudeCodeAdapterLive({ +const claudeLayer = makeClaudeAdapterLive({ createQuery: () => ({ [Symbol.asyncIterator]: async function* () { @@ -104,11 +104,11 @@ describe("provider adapter conformance", () => { ), }, { - provider: "claudeCode" as const, + provider: "claudeAgent" as const, load: () => Effect.runPromise( Effect.gen(function* () { - return yield* ClaudeCodeAdapter; + return yield* ClaudeAdapter; }).pipe(Effect.provide(claudeLayer)), ), }, diff --git a/apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts b/apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts index 6b52803dd35..cce8d43c9c6 100644 --- a/apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts +++ b/apps/server/src/provider/Layers/ProviderAdapterRegistry.test.ts @@ -5,7 +5,7 @@ import type { ProviderKind } from "@t3tools/contracts"; import { Effect, Layer, Stream } from "effect"; import { ProviderUnsupportedError } from "../Errors.ts"; -import { ClaudeCodeAdapter, type ClaudeCodeAdapterShape } from "../Services/ClaudeCodeAdapter.ts"; +import { ClaudeAdapter, type ClaudeAdapterShape } from "../Services/ClaudeAdapter.ts"; import { CopilotAdapter, type CopilotAdapterShape } from "../Services/CopilotAdapter.ts"; import { CodexAdapter, type CodexAdapterShape } from "../Services/CodexAdapter.ts"; import { CursorAdapter, type CursorAdapterShape } from "../Services/CursorAdapter.ts"; @@ -34,9 +34,9 @@ const fakeCodexAdapter: CodexAdapterShape = { streamEvents: Stream.empty, }; -const fakeClaudeAdapter: ClaudeCodeAdapterShape = { - provider: "claudeCode", - capabilities: getProviderCapabilities("claudeCode"), +const fakeClaudeAdapter: ClaudeAdapterShape = { + provider: "claudeAgent", + capabilities: getProviderCapabilities("claudeAgent"), startSession: vi.fn(), sendTurn: vi.fn(), interruptTurn: vi.fn(), @@ -159,7 +159,7 @@ const layer = it.layer( Layer.mergeAll( Layer.succeed(CodexAdapter, fakeCodexAdapter), Layer.succeed(CopilotAdapter, fakeCopilotAdapter), - Layer.succeed(ClaudeCodeAdapter, fakeClaudeAdapter), + Layer.succeed(ClaudeAdapter, fakeClaudeAdapter), Layer.succeed(CursorAdapter, fakeCursorAdapter), Layer.succeed(OpenCodeAdapter, fakeOpenCodeAdapter), Layer.succeed(GeminiCliAdapter, fakeGeminiCliAdapter), @@ -177,7 +177,7 @@ layer("ProviderAdapterRegistryLive", (it) => { const registry = yield* ProviderAdapterRegistry; const codex = yield* registry.getByProvider("codex"); const copilot = yield* registry.getByProvider("copilot"); - const claude = yield* registry.getByProvider("claudeCode"); + const claude = yield* registry.getByProvider("claudeAgent"); const cursor = yield* registry.getByProvider("cursor"); const opencode = yield* registry.getByProvider("opencode"); const geminiCli = yield* registry.getByProvider("geminiCli"); @@ -197,7 +197,7 @@ layer("ProviderAdapterRegistryLive", (it) => { assert.deepEqual(providers, [ "codex", "copilot", - "claudeCode", + "claudeAgent", "cursor", "opencode", "geminiCli", diff --git a/apps/server/src/provider/Layers/ProviderAdapterRegistry.ts b/apps/server/src/provider/Layers/ProviderAdapterRegistry.ts index aed87db0aca..3a4b89baebc 100644 --- a/apps/server/src/provider/Layers/ProviderAdapterRegistry.ts +++ b/apps/server/src/provider/Layers/ProviderAdapterRegistry.ts @@ -16,7 +16,7 @@ import { ProviderAdapterRegistry, type ProviderAdapterRegistryShape, } from "../Services/ProviderAdapterRegistry.ts"; -import { ClaudeCodeAdapter } from "../Services/ClaudeCodeAdapter.ts"; +import { ClaudeAdapter } from "../Services/ClaudeAdapter.ts"; import { CopilotAdapter } from "../Services/CopilotAdapter.ts"; import { CodexAdapter } from "../Services/CodexAdapter.ts"; import { CursorAdapter } from "../Services/CursorAdapter.ts"; @@ -37,7 +37,7 @@ const makeProviderAdapterRegistry = (options?: ProviderAdapterRegistryLiveOption : [ yield* CodexAdapter, yield* CopilotAdapter, - yield* ClaudeCodeAdapter, + yield* ClaudeAdapter, yield* CursorAdapter, yield* OpenCodeAdapter, yield* GeminiCliAdapter, diff --git a/apps/server/src/provider/Layers/ProviderService.test.ts b/apps/server/src/provider/Layers/ProviderService.test.ts index 41d9a098a65..f2709ec4086 100644 --- a/apps/server/src/provider/Layers/ProviderService.test.ts +++ b/apps/server/src/provider/Layers/ProviderService.test.ts @@ -56,7 +56,7 @@ type LegacyProviderRuntimeEvent = { readonly provider: | "codex" | "copilot" - | "claudeCode" + | "claudeAgent" | "cursor" | "opencode" | "geminiCli" @@ -224,15 +224,15 @@ const sleep = (ms: number) => function makeProviderServiceLayer() { const codex = makeFakeCodexAdapter(); - const claude = makeFakeCodexAdapter("claudeCode"); + const claude = makeFakeCodexAdapter("claudeAgent"); const registry: typeof ProviderAdapterRegistry.Service = { getByProvider: (provider) => provider === "codex" ? Effect.succeed(codex.adapter) - : provider === "claudeCode" + : provider === "claudeAgent" ? Effect.succeed(claude.adapter) : Effect.fail(new ProviderUnsupportedError({ provider })), - listProviders: () => Effect.succeed(["codex", "claudeCode"]), + listProviders: () => Effect.succeed(["codex", "claudeAgent"]), }; const providerAdapterLayer = Layer.succeed(ProviderAdapterRegistry, registry); @@ -504,24 +504,24 @@ routing.layer("ProviderServiceLive routing", (it) => { }), ); - it.effect("routes explicit claudeCode provider session starts to the claude adapter", () => + it.effect("routes explicit claudeAgent provider session starts to the claude adapter", () => Effect.gen(function* () { const provider = yield* ProviderService; const session = yield* provider.startSession(asThreadId("thread-claude"), { - provider: "claudeCode", + provider: "claudeAgent", threadId: asThreadId("thread-claude"), cwd: "/tmp/project-claude", runtimeMode: "full-access", }); - assert.equal(session.provider, "claudeCode"); + assert.equal(session.provider, "claudeAgent"); assert.equal(routing.claude.startSession.mock.calls.length, 1); const startInput = routing.claude.startSession.mock.calls[0]?.[0]; assert.equal(typeof startInput === "object" && startInput !== null, true); if (startInput && typeof startInput === "object") { const startPayload = startInput as { provider?: string; cwd?: string }; - assert.equal(startPayload.provider, "claudeCode"); + assert.equal(startPayload.provider, "claudeAgent"); assert.equal(startPayload.cwd, "/tmp/project-claude"); } }), diff --git a/apps/server/src/provider/Layers/ProviderSessionDirectory.ts b/apps/server/src/provider/Layers/ProviderSessionDirectory.ts index 937a883dbfe..26f62e4dd14 100644 --- a/apps/server/src/provider/Layers/ProviderSessionDirectory.ts +++ b/apps/server/src/provider/Layers/ProviderSessionDirectory.ts @@ -25,7 +25,7 @@ function decodeProviderKind( if ( providerName === "codex" || providerName === "copilot" || - providerName === "claudeCode" || + providerName === "claudeAgent" || providerName === "cursor" || providerName === "opencode" || providerName === "geminiCli" || diff --git a/apps/server/src/provider/Services/ClaudeAdapter.ts b/apps/server/src/provider/Services/ClaudeAdapter.ts new file mode 100644 index 00000000000..f08a3aab875 --- /dev/null +++ b/apps/server/src/provider/Services/ClaudeAdapter.ts @@ -0,0 +1,31 @@ +/** + * ClaudeAdapter - Claude Code implementation of the generic provider adapter contract. + * + * This service owns Claude runtime/session semantics and emits canonical + * provider runtime events. It does not perform cross-provider routing, shared + * event fan-out, or checkpoint orchestration. + * + * Uses Effect `ServiceMap.Service` for dependency injection and returns the + * shared provider-adapter error channel with `provider: "claudeAgent"` context. + * + * @module ClaudeAdapter + */ +import { ServiceMap } from "effect"; + +import type { ProviderAdapterError } from "../Errors.ts"; +import type { ProviderAdapterShape } from "./ProviderAdapter.ts"; + +/** + * ClaudeAdapterShape - Service API for the Claude Code provider adapter. + */ +export interface ClaudeAdapterShape extends ProviderAdapterShape { + readonly provider: "claudeAgent"; +} + +/** + * ClaudeAdapter - Service tag for Claude Code provider adapter operations. + */ +export class ClaudeAdapter extends ServiceMap.Service< + ClaudeAdapter, + ClaudeAdapterShape +>()("t3/provider/Services/ClaudeAdapter") {} diff --git a/apps/server/src/provider/Services/ClaudeCodeAdapter.ts b/apps/server/src/provider/Services/ClaudeCodeAdapter.ts deleted file mode 100644 index 6ef68760612..00000000000 --- a/apps/server/src/provider/Services/ClaudeCodeAdapter.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * ClaudeCodeAdapter - Claude Code implementation of the generic provider adapter contract. - * - * This service owns Claude runtime/session semantics and emits canonical - * provider runtime events. It does not perform cross-provider routing, shared - * event fan-out, or checkpoint orchestration. - * - * Uses Effect `ServiceMap.Service` for dependency injection and returns the - * shared provider-adapter error channel with `provider: "claudeCode"` context. - * - * @module ClaudeCodeAdapter - */ -import { ServiceMap } from "effect"; - -import type { ProviderAdapterError } from "../Errors.ts"; -import type { ProviderAdapterShape } from "./ProviderAdapter.ts"; - -/** - * ClaudeCodeAdapterShape - Service API for the Claude Code provider adapter. - */ -export interface ClaudeCodeAdapterShape extends ProviderAdapterShape { - readonly provider: "claudeCode"; -} - -/** - * ClaudeCodeAdapter - Service tag for Claude Code provider adapter operations. - */ -export class ClaudeCodeAdapter extends ServiceMap.Service< - ClaudeCodeAdapter, - ClaudeCodeAdapterShape ->()("t3/provider/Services/ClaudeCodeAdapter") {} diff --git a/apps/server/src/provider/Services/ProviderAdapter.ts b/apps/server/src/provider/Services/ProviderAdapter.ts index be6f8b61eb9..f153c2bf072 100644 --- a/apps/server/src/provider/Services/ProviderAdapter.ts +++ b/apps/server/src/provider/Services/ProviderAdapter.ts @@ -121,7 +121,7 @@ export const PROVIDER_CAPABILITIES_BY_PROVIDER: Readonly< supportsAttachments: true, persistentRuntime: true, }, - claudeCode: { + claudeAgent: { sessionModelSwitch: "in-session", transport: "sdk-query", modelDiscovery: "session-native", diff --git a/apps/server/src/serverLayers.ts b/apps/server/src/serverLayers.ts index 08457d5bf4b..3b489c1d6e0 100644 --- a/apps/server/src/serverLayers.ts +++ b/apps/server/src/serverLayers.ts @@ -19,7 +19,7 @@ import { OrchestrationProjectionSnapshotQueryLive } from "./orchestration/Layers import { ProviderRuntimeIngestionLive } from "./orchestration/Layers/ProviderRuntimeIngestion"; import { RuntimeReceiptBusLive } from "./orchestration/Layers/RuntimeReceiptBus"; import { ProviderUnsupportedError } from "./provider/Errors"; -import { makeClaudeCodeAdapterLive } from "./provider/Layers/ClaudeCodeAdapter"; +import { makeClaudeAdapterLive } from "./provider/Layers/ClaudeAdapter"; import { makeCopilotAdapterLive } from "./provider/Layers/CopilotAdapter"; import { makeCodexAdapterLive } from "./provider/Layers/CodexAdapter"; import { makeCursorAdapterLive } from "./provider/Layers/CursorAdapter"; @@ -69,7 +69,7 @@ export function makeServerProviderLayer(): Layer.Layer< const copilotAdapterLayer = makeCopilotAdapterLive( nativeEventLogger ? { nativeEventLogger } : undefined, ); - const claudeAdapterLayer = makeClaudeCodeAdapterLive( + const claudeAdapterLayer = makeClaudeAdapterLive( nativeEventLogger ? { nativeEventLogger } : undefined, ); const cursorAdapterLayer = makeCursorAdapterLive( diff --git a/apps/server/src/wsServer.ts b/apps/server/src/wsServer.ts index 99c1daaf2be..b5cc9efce1d 100644 --- a/apps/server/src/wsServer.ts +++ b/apps/server/src/wsServer.ts @@ -77,7 +77,7 @@ import { fetchOpenCodeModels } from "./opencodeServerManager.ts"; import { fetchCopilotModels, fetchCopilotUsage } from "./provider/Layers/CopilotAdapter.ts"; import { fetchCursorModels } from "./provider/Layers/CursorAdapter.ts"; import { fetchCursorUsage } from "./provider/Layers/CursorUsage.ts"; -import { fetchClaudeCodeUsage } from "./provider/Layers/ClaudeCodeAdapter.ts"; +import { fetchClaudeCodeUsage } from "./provider/Layers/ClaudeAdapter.ts"; import { fetchCodexUsage } from "./provider/Layers/CodexAdapter.ts"; import { @@ -984,7 +984,7 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< }); return usage satisfies ProviderUsageResult; } - if (provider === "claudeCode") { + if (provider === "claudeAgent") { return fetchClaudeCodeUsage() satisfies ProviderUsageResult; } if (provider === "geminiCli") { diff --git a/apps/web/src/appSettings.test.ts b/apps/web/src/appSettings.test.ts index 2085b727aaa..8f080baf83a 100644 --- a/apps/web/src/appSettings.test.ts +++ b/apps/web/src/appSettings.test.ts @@ -79,8 +79,8 @@ describe("normalizeCustomModelSlugs", () => { }); it("normalizes provider-specific aliases for claude and cursor", () => { - expect(normalizeCustomModelSlugs(["sonnet"], "claudeCode")).toEqual([]); - expect(normalizeCustomModelSlugs(["claude/custom-sonnet"], "claudeCode")).toEqual([ + expect(normalizeCustomModelSlugs(["sonnet"], "claudeAgent")).toEqual([]); + expect(normalizeCustomModelSlugs(["claude/custom-sonnet"], "claudeAgent")).toEqual([ "claude/custom-sonnet", ]); expect(normalizeCustomModelSlugs(["composer"], "cursor")).toEqual([]); @@ -116,7 +116,7 @@ describe("getAppModelOptions", () => { }); it("keeps a saved custom provider model available as an exact slug option", () => { - const options = getAppModelOptions("claudeCode", ["claude/custom-opus"], "claude/custom-opus"); + const options = getAppModelOptions("claudeAgent", ["claude/custom-opus"], "claude/custom-opus"); expect(options.some((option) => option.slug === "claude/custom-opus" && option.isCustom)).toBe( true, @@ -169,7 +169,7 @@ describe("timestamp format defaults", () => { }); it("includes provider-specific custom slugs in non-codex model lists", () => { - const claudeOptions = getAppModelOptions("claudeCode", ["claude/custom-opus"]); + const claudeOptions = getAppModelOptions("claudeAgent", ["claude/custom-opus"]); const cursorOptions = getAppModelOptions("cursor", ["cursor/custom-model"]); expect(claudeOptions.some((option) => option.slug === "claude/custom-opus")).toBe(true); diff --git a/apps/web/src/appSettings.ts b/apps/web/src/appSettings.ts index c1d4200a7be..6904775f647 100644 --- a/apps/web/src/appSettings.ts +++ b/apps/web/src/appSettings.ts @@ -37,7 +37,7 @@ export const DEFAULT_TIMESTAMP_FORMAT: TimestampFormat = "locale"; const BUILT_IN_MODEL_SLUGS_BY_PROVIDER: Record> = { codex: new Set(getModelOptions("codex").map((option) => option.slug)), copilot: new Set(getModelOptions("copilot").map((option) => option.slug)), - claudeCode: new Set(getModelOptions("claudeCode").map((option) => option.slug)), + claudeAgent: new Set(getModelOptions("claudeAgent").map((option) => option.slug)), cursor: new Set(getModelOptions("cursor").map((option) => option.slug)), opencode: new Set(getModelOptions("opencode").map((option) => option.slug)), geminiCli: new Set(getModelOptions("geminiCli").map((option) => option.slug)), @@ -47,7 +47,7 @@ const BUILT_IN_MODEL_SLUGS_BY_PROVIDER: Record const PROVIDER_KINDS = [ "codex", "copilot", - "claudeCode", + "claudeAgent", "cursor", "opencode", "geminiCli", @@ -216,7 +216,7 @@ export function getCustomModelsForProvider( switch (provider) { case "copilot": return settings.customCopilotModels; - case "claudeCode": + case "claudeAgent": return settings.customClaudeModels; case "cursor": return settings.customCursorModels; @@ -238,7 +238,7 @@ export function patchCustomModels(provider: ProviderKind, models: string[]): Par switch (provider) { case "copilot": return { customCopilotModels: models }; - case "claudeCode": + case "claudeAgent": return { customClaudeModels: models }; case "cursor": return { customCursorModels: models }; @@ -283,7 +283,7 @@ function normalizeAppSettings(settings: AppSettings): AppSettings { ...settings, customCodexModels: normalizeCustomModelSlugs(settings.customCodexModels, "codex"), customCopilotModels: normalizeCustomModelSlugs(settings.customCopilotModels, "copilot"), - customClaudeModels: normalizeCustomModelSlugs(settings.customClaudeModels, "claudeCode"), + customClaudeModels: normalizeCustomModelSlugs(settings.customClaudeModels, "claudeAgent"), customCursorModels: normalizeCustomModelSlugs(settings.customCursorModels, "cursor"), customOpencodeModels: normalizeCustomModelSlugs(settings.customOpencodeModels, "opencode"), customGeminiCliModels: normalizeCustomModelSlugs(settings.customGeminiCliModels, "geminiCli"), diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index dbf352a715f..97155717f4b 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -160,7 +160,7 @@ import { import { ComposerCommandItem, ComposerCommandMenu } from "./chat/ComposerCommandMenu"; import { ComposerPendingApprovalActions } from "./chat/ComposerPendingApprovalActions"; import { CodexTraitsPicker } from "./chat/CodexTraitsPicker"; -import { ClaudeCodeTraitsPicker } from "./chat/ClaudeCodeTraitsPicker"; +import { ClaudeTraitsPicker } from "./chat/ClaudeTraitsPicker"; import { CursorTraitsPicker } from "./chat/CursorTraitsPicker"; import { CompactComposerControlsMenu } from "./chat/CompactComposerControlsMenu"; import { ComposerPendingApprovalPanel } from "./chat/ComposerPendingApprovalPanel"; @@ -603,7 +603,7 @@ export default function ChatView({ threadId }: ChatViewProps) { () => ({ codex: settings.customCodexModels, copilot: settings.customCopilotModels, - claudeCode: settings.customClaudeModels, + claudeAgent: settings.customClaudeModels, cursor: settings.customCursorModels, opencode: settings.customOpencodeModels, geminiCli: settings.customGeminiCliModels, @@ -642,10 +642,10 @@ export default function ChatView({ threadId }: ChatViewProps) { const selectedEffort = composerDraft.effort ?? getDefaultReasoningEffort(selectedProvider); const selectedCodexFastModeEnabled = selectedProvider === "codex" ? composerDraft.codexFastMode : false; - const claudeCodeEffortOptions = getClaudeCodeEffortOptions(selectedProvider); - const supportsClaudeCodeEffort = claudeCodeEffortOptions.length > 0; + const claudeAgentEffortOptions = getClaudeCodeEffortOptions(selectedProvider); + const supportsClaudeCodeEffort = claudeAgentEffortOptions.length > 0; const selectedClaudeCodeEffort = - composerDraft.claudeCodeEffort ?? getDefaultClaudeCodeEffort(selectedProvider); + composerDraft.claudeAgentEffort ?? getDefaultClaudeCodeEffort(selectedProvider); const selectedModelOptionsForDispatch = useMemo(() => { if (selectedProvider === "codex") { const codexOptions = { @@ -654,8 +654,8 @@ export default function ChatView({ threadId }: ChatViewProps) { }; return Object.keys(codexOptions).length > 0 ? { codex: codexOptions } : undefined; } - if (selectedProvider === "claudeCode" && supportsClaudeCodeEffort && selectedClaudeCodeEffort) { - return { claudeCode: { effort: selectedClaudeCodeEffort } }; + if (selectedProvider === "claudeAgent" && supportsClaudeCodeEffort && selectedClaudeCodeEffort) { + return { claudeAgent: { effort: selectedClaudeCodeEffort } }; } return undefined; }, [ @@ -3908,12 +3908,12 @@ export default function ChatView({ threadId }: ChatViewProps) { onThinkingModeChange={onCursorThinkingModeChange} /> )} - {selectedProvider === "claudeCode" && + {selectedProvider === "claudeAgent" && supportsClaudeCodeEffort && selectedClaudeCodeEffort != null && ( - )} @@ -3972,7 +3972,7 @@ export default function ChatView({ threadId }: ChatViewProps) { onFastModeChange={onCodexFastModeChange} /> - ) : selectedProvider === "claudeCode" && + ) : selectedProvider === "claudeAgent" && supportsClaudeCodeEffort && selectedClaudeCodeEffort != null ? ( <> @@ -3980,9 +3980,9 @@ export default function ChatView({ threadId }: ChatViewProps) { orientation="vertical" className="mx-0.5 hidden h-4 sm:block" /> - diff --git a/apps/web/src/components/ProviderLogo.tsx b/apps/web/src/components/ProviderLogo.tsx index ec6d63dd4b8..a3bb15259c3 100644 --- a/apps/web/src/components/ProviderLogo.tsx +++ b/apps/web/src/components/ProviderLogo.tsx @@ -18,7 +18,7 @@ import { const PROVIDER_ICON_BY_PROVIDER: Record = { codex: OpenAI, copilot: GitHubIcon, - claudeCode: ClaudeAI, + claudeAgent: ClaudeAI, cursor: CursorIcon, opencode: OpenCodeIcon, geminiCli: Gemini, diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx index c241b82ff24..de3120db81d 100644 --- a/apps/web/src/components/Sidebar.tsx +++ b/apps/web/src/components/Sidebar.tsx @@ -516,7 +516,7 @@ const USAGE_PROVIDERS: ReadonlyArray<{ provider: ProviderKind; label: string }> { provider: "copilot", label: "Copilot" }, { provider: "codex", label: "Codex" }, { provider: "cursor", label: "Cursor" }, - { provider: "claudeCode", label: "Claude Code" }, + { provider: "claudeAgent", label: "Claude Code" }, { provider: "geminiCli", label: "Gemini" }, { provider: "amp", label: "Amp" }, ]; @@ -547,7 +547,7 @@ function ProviderUsageSection() { const copilotUsage = useProviderUsage("copilot"); const codexUsage = useProviderUsage("codex"); const cursorUsage = useProviderUsage("cursor"); - const claudeUsage = useProviderUsage("claudeCode"); + const claudeUsage = useProviderUsage("claudeAgent"); const geminiUsage = useProviderUsage("geminiCli"); const ampUsage = useProviderUsage("amp"); @@ -555,7 +555,7 @@ function ProviderUsageSection() { copilot: copilotUsage.data, codex: codexUsage.data, cursor: cursorUsage.data, - claudeCode: claudeUsage.data, + claudeAgent: claudeUsage.data, geminiCli: geminiUsage.data, amp: ampUsage.data, }; @@ -617,7 +617,7 @@ function ProviderUsageSection() { } // Session usage (no quota) — show token/cost summary if ( - provider !== "claudeCode" && + provider !== "claudeAgent" && data?.sessionUsage && (data.sessionUsage.totalTokens || data.sessionUsage.totalCostUsd) ) { diff --git a/apps/web/src/components/chat/ClaudeCodeTraitsPicker.tsx b/apps/web/src/components/chat/ClaudeTraitsPicker.tsx similarity index 93% rename from apps/web/src/components/chat/ClaudeCodeTraitsPicker.tsx rename to apps/web/src/components/chat/ClaudeTraitsPicker.tsx index 41f917294ae..293f87173b9 100644 --- a/apps/web/src/components/chat/ClaudeCodeTraitsPicker.tsx +++ b/apps/web/src/components/chat/ClaudeTraitsPicker.tsx @@ -12,13 +12,13 @@ export const CLAUDE_CODE_EFFORT_LABEL: Record = { max: "Max", }; -export const ClaudeCodeTraitsPicker = memo(function ClaudeCodeTraitsPicker(props: { +export const ClaudeTraitsPicker = memo(function ClaudeTraitsPicker(props: { effort: ClaudeCodeEffort; options: ReadonlyArray; onEffortChange: (effort: ClaudeCodeEffort) => void; }) { const [isMenuOpen, setIsMenuOpen] = useState(false); - const defaultEffort = getDefaultClaudeCodeEffort("claudeCode"); + const defaultEffort = getDefaultClaudeCodeEffort("claudeAgent"); return ( = { codex: OpenAI, copilot: GitHubIcon, - claudeCode: ClaudeAI, + claudeAgent: ClaudeAI, cursor: CursorIcon, opencode: OpenCodeIcon, geminiCli: Gemini, @@ -281,7 +281,7 @@ export const ProviderModelPicker = memo(function ProviderModelPicker(props: { aria-hidden="true" className={cn( "size-4 shrink-0", - props.provider === "claudeCode" ? "" : "text-muted-foreground/70", + props.provider === "claudeAgent" ? "" : "text-muted-foreground/70", )} /> {selectedModelLabel} @@ -438,7 +438,7 @@ export const ProviderModelPicker = memo(function ProviderModelPicker(props: { aria-hidden="true" className={cn( "size-4 shrink-0 opacity-80", - option.value === "claudeCode" ? "" : "text-muted-foreground/85", + option.value === "claudeAgent" ? "" : "text-muted-foreground/85", )} /> {option.label} diff --git a/apps/web/src/composerDraftStore.ts b/apps/web/src/composerDraftStore.ts index 0e82d3fa081..45afa7d1830 100644 --- a/apps/web/src/composerDraftStore.ts +++ b/apps/web/src/composerDraftStore.ts @@ -99,7 +99,7 @@ interface PersistedComposerThreadDraftState { interactionMode?: ProviderInteractionMode | null; effort?: CodexReasoningEffort | null; codexFastMode?: boolean | null; - claudeCodeEffort?: ClaudeCodeEffort | null; + claudeAgentEffort?: ClaudeCodeEffort | null; serviceTier?: string | null; } @@ -131,7 +131,7 @@ interface ComposerThreadDraftState { interactionMode: ProviderInteractionMode | null; effort: CodexReasoningEffort | null; codexFastMode: boolean; - claudeCodeEffort: ClaudeCodeEffort | null; + claudeAgentEffort: ClaudeCodeEffort | null; } export interface DraftThreadState { @@ -241,7 +241,7 @@ const EMPTY_THREAD_DRAFT = Object.freeze({ interactionMode: null, effort: null, codexFastMode: false, - claudeCodeEffort: null, + claudeAgentEffort: null, }) as ComposerThreadDraftState; const REASONING_EFFORT_VALUES = new Set( @@ -249,7 +249,7 @@ const REASONING_EFFORT_VALUES = new Set( ); const CLAUDE_CODE_EFFORT_VALUES = new Set( - CLAUDE_CODE_EFFORT_OPTIONS_BY_PROVIDER.claudeCode, + CLAUDE_CODE_EFFORT_OPTIONS_BY_PROVIDER.claudeAgent, ); function createEmptyThreadDraft(): ComposerThreadDraftState { @@ -265,7 +265,7 @@ function createEmptyThreadDraft(): ComposerThreadDraftState { interactionMode: null, effort: null, codexFastMode: false, - claudeCodeEffort: null, + claudeAgentEffort: null, }; } @@ -338,14 +338,14 @@ function shouldRemoveDraft(draft: ComposerThreadDraftState): boolean { draft.interactionMode === null && draft.effort === null && draft.codexFastMode === false && - draft.claudeCodeEffort === null + draft.claudeAgentEffort === null ); } function normalizeProviderKind(value: unknown): ProviderKind | null { return value === "codex" || value === "copilot" || - value === "claudeCode" || + value === "claudeAgent" || value === "cursor" || value === "opencode" || value === "geminiCli" || @@ -584,12 +584,12 @@ function normalizePersistedComposerDraftState(value: unknown): PersistedComposer const codexFastMode = draftCandidate.codexFastMode === true || (typeof draftCandidate.serviceTier === "string" && draftCandidate.serviceTier === "fast"); - const claudeCodeEffortCandidate = - typeof draftCandidate.claudeCodeEffort === "string" ? draftCandidate.claudeCodeEffort : null; - const claudeCodeEffort = - claudeCodeEffortCandidate && - CLAUDE_CODE_EFFORT_VALUES.has(claudeCodeEffortCandidate as ClaudeCodeEffort) - ? (claudeCodeEffortCandidate as ClaudeCodeEffort) + const claudeAgentEffortCandidate = + typeof draftCandidate.claudeAgentEffort === "string" ? draftCandidate.claudeAgentEffort : null; + const claudeAgentEffort = + claudeAgentEffortCandidate && + CLAUDE_CODE_EFFORT_VALUES.has(claudeAgentEffortCandidate as ClaudeCodeEffort) + ? (claudeAgentEffortCandidate as ClaudeCodeEffort) : null; const prompt = ensureInlineTerminalContextPlaceholders( promptCandidate, @@ -605,7 +605,7 @@ function normalizePersistedComposerDraftState(value: unknown): PersistedComposer !interactionMode && !effort && !codexFastMode && - !claudeCodeEffort + !claudeAgentEffort ) { continue; } @@ -619,7 +619,7 @@ function normalizePersistedComposerDraftState(value: unknown): PersistedComposer ...(interactionMode ? { interactionMode } : {}), ...(effort ? { effort } : {}), ...(codexFastMode ? { codexFastMode } : {}), - ...(claudeCodeEffort ? { claudeCodeEffort } : {}), + ...(claudeAgentEffort ? { claudeAgentEffort } : {}), }; } return { @@ -731,7 +731,7 @@ function toHydratedThreadDraft( interactionMode: persistedDraft.interactionMode ?? null, effort: persistedDraft.effort ?? null, codexFastMode: persistedDraft.codexFastMode === true, - claudeCodeEffort: persistedDraft.claudeCodeEffort ?? null, + claudeAgentEffort: persistedDraft.claudeAgentEffort ?? null, }; } @@ -1198,7 +1198,7 @@ export const useComposerDraftStore = create()( const nextEffort = effort && CLAUDE_CODE_EFFORT_VALUES.has(effort) && - effort !== DEFAULT_CLAUDE_CODE_EFFORT_BY_PROVIDER.claudeCode + effort !== DEFAULT_CLAUDE_CODE_EFFORT_BY_PROVIDER.claudeAgent ? effort : null; set((state) => { @@ -1207,12 +1207,12 @@ export const useComposerDraftStore = create()( return state; } const base = existing ?? createEmptyThreadDraft(); - if (base.claudeCodeEffort === nextEffort) { + if (base.claudeAgentEffort === nextEffort) { return state; } const nextDraft: ComposerThreadDraftState = { ...base, - claudeCodeEffort: nextEffort, + claudeAgentEffort: nextEffort, }; const nextDraftsByThreadId = { ...state.draftsByThreadId }; if (shouldRemoveDraft(nextDraft)) { @@ -1581,7 +1581,7 @@ export const useComposerDraftStore = create()( draft.interactionMode === null && draft.effort === null && draft.codexFastMode === false && - draft.claudeCodeEffort === null + draft.claudeAgentEffort === null ) { continue; } @@ -1618,8 +1618,8 @@ export const useComposerDraftStore = create()( if (draft.codexFastMode) { persistedDraft.codexFastMode = true; } - if (draft.claudeCodeEffort) { - persistedDraft.claudeCodeEffort = draft.claudeCodeEffort; + if (draft.claudeAgentEffort) { + persistedDraft.claudeAgentEffort = draft.claudeAgentEffort; } persistedDraftsByThreadId[threadId as ThreadId] = persistedDraft; } diff --git a/apps/web/src/lib/threadDraftDefaults.test.ts b/apps/web/src/lib/threadDraftDefaults.test.ts index 49c1a273e53..c7a003471ee 100644 --- a/apps/web/src/lib/threadDraftDefaults.test.ts +++ b/apps/web/src/lib/threadDraftDefaults.test.ts @@ -53,7 +53,7 @@ describe("resolveDraftThreadDefaults", () => { makeThread({ id: ThreadId.makeUnsafe("thread-other-project"), projectId: ProjectId.makeUnsafe("project-2"), - provider: "claudeCode", + provider: "claudeAgent", model: "claude-sonnet-4-6", createdAt: "2026-03-09T10:00:00.000Z", }), @@ -80,7 +80,7 @@ describe("resolveDraftThreadDefaults", () => { makeThread({ id: ThreadId.makeUnsafe("thread-newest"), projectId: ProjectId.makeUnsafe("project-2"), - provider: "claudeCode", + provider: "claudeAgent", model: "claude-sonnet-4-6", createdAt: "2026-03-09T10:00:00.000Z", }), @@ -90,7 +90,7 @@ describe("resolveDraftThreadDefaults", () => { }); expect(defaults).toEqual({ - provider: "claudeCode", + provider: "claudeAgent", model: "claude-sonnet-4-6", }); }); @@ -108,7 +108,7 @@ describe("resolveDraftThreadDefaults", () => { }), makeThread({ id: ThreadId.makeUnsafe("thread-newer"), - provider: "claudeCode", + provider: "claudeAgent", model: "claude-sonnet-4-6", createdAt: "2026-03-08T10:00:00.000Z", }), @@ -131,7 +131,7 @@ describe("resolveDraftThreadDefaults", () => { }); expect(defaults).toEqual({ - provider: "claudeCode", + provider: "claudeAgent", model: "claude-sonnet-4-6", }); }); diff --git a/apps/web/src/lib/threadProvider.test.ts b/apps/web/src/lib/threadProvider.test.ts index 2737379da22..eb7f59a236c 100644 --- a/apps/web/src/lib/threadProvider.test.ts +++ b/apps/web/src/lib/threadProvider.test.ts @@ -6,9 +6,9 @@ describe("inferProviderForThreadModel", () => { expect( inferProviderForThreadModel({ model: "gpt-5.3-codex", - sessionProviderName: "claudeCode", + sessionProviderName: "claudeAgent", }), - ).toBe("claudeCode"); + ).toBe("claudeAgent"); }); it("infers cursor threads from composer models", () => { diff --git a/apps/web/src/lib/threadProvider.ts b/apps/web/src/lib/threadProvider.ts index 3689401c4ed..fdf019353f4 100644 --- a/apps/web/src/lib/threadProvider.ts +++ b/apps/web/src/lib/threadProvider.ts @@ -5,7 +5,7 @@ import type { Thread } from "../types"; const PROVIDER_KINDS = [ "codex", "copilot", - "claudeCode", + "claudeAgent", "cursor", "opencode", "geminiCli", @@ -20,7 +20,7 @@ const COPILOT_MODEL_SLUGS = new Set( getModelOptions("copilot").map((option) => option.slug), ); const CLAUDE_MODEL_SLUGS = new Set( - getModelOptions("claudeCode").map((option) => option.slug), + getModelOptions("claudeAgent").map((option) => option.slug), ); const CURSOR_MODEL_SLUGS = new Set(getModelOptions("cursor").map((option) => option.slug)); const OPENCODE_MODEL_SLUGS = new Set( @@ -89,9 +89,9 @@ export function inferProviderForThreadModel(input: { return "cursor"; } - const normalizedClaude = normalizeModelSlug(input.model, "claudeCode"); + const normalizedClaude = normalizeModelSlug(input.model, "claudeAgent"); if (normalizedClaude && CLAUDE_MODEL_SLUGS.has(normalizedClaude)) { - return "claudeCode"; + return "claudeAgent"; } const normalizedCodex = normalizeModelSlug(input.model, "codex"); @@ -117,7 +117,7 @@ export function inferProviderForThreadModel(input: { return "cursor"; } - return input.model.trim().startsWith("claude-") ? "claudeCode" : "codex"; + return input.model.trim().startsWith("claude-") ? "claudeAgent" : "codex"; } export function resolveThreadProvider(thread: Pick): ProviderKind { diff --git a/apps/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx index 3be2df7320b..883204b74d2 100644 --- a/apps/web/src/routes/__root.tsx +++ b/apps/web/src/routes/__root.tsx @@ -41,7 +41,7 @@ export const Route = createRootRouteWithContext<{ const PROVIDER_KINDS = [ "codex", "copilot", - "claudeCode", + "claudeAgent", "cursor", "opencode", "geminiCli", diff --git a/apps/web/src/routes/_chat.settings.tsx b/apps/web/src/routes/_chat.settings.tsx index 01107dae573..dd0aa3cfda9 100644 --- a/apps/web/src/routes/_chat.settings.tsx +++ b/apps/web/src/routes/_chat.settings.tsx @@ -76,7 +76,7 @@ const MODEL_PROVIDER_SETTINGS: Array<{ example: "gpt-5.1-codex-max", }, { - provider: "claudeCode", + provider: "claudeAgent", title: "Claude Code", description: "Save additional Claude model slugs for the picker and `/model` command.", placeholder: "your-claude-model-slug", @@ -231,7 +231,7 @@ function SettingsRouteView() { >({ codex: "", copilot: "", - claudeCode: "", + claudeAgent: "", cursor: "", opencode: "", geminiCli: "", diff --git a/apps/web/src/session-logic.test.ts b/apps/web/src/session-logic.test.ts index fbd0104332f..eab66866f1b 100644 --- a/apps/web/src/session-logic.test.ts +++ b/apps/web/src/session-logic.test.ts @@ -772,7 +772,7 @@ describe("deriveActiveWorkStartedAt", () => { describe("PROVIDER_OPTIONS", () => { it("advertises all currently integrated providers", () => { const copilot = PROVIDER_OPTIONS.find((option) => option.value === "copilot"); - const claude = PROVIDER_OPTIONS.find((option) => option.value === "claudeCode"); + const claude = PROVIDER_OPTIONS.find((option) => option.value === "claudeAgent"); const cursor = PROVIDER_OPTIONS.find((option) => option.value === "cursor"); const opencode = PROVIDER_OPTIONS.find((option) => option.value === "opencode"); const geminiCli = PROVIDER_OPTIONS.find((option) => option.value === "geminiCli"); @@ -780,7 +780,7 @@ describe("PROVIDER_OPTIONS", () => { expect(PROVIDER_OPTIONS).toEqual([ { value: "codex", label: "Codex", available: true }, { value: "copilot", label: "GitHub Copilot", available: true }, - { value: "claudeCode", label: "Claude Code", available: true }, + { value: "claudeAgent", label: "Claude Code", available: true }, { value: "cursor", label: "Cursor Agent", available: true }, { value: "opencode", label: "OpenCode", available: true }, { value: "geminiCli", label: "Gemini CLI", available: true }, @@ -793,7 +793,7 @@ describe("PROVIDER_OPTIONS", () => { available: true, }); expect(claude).toEqual({ - value: "claudeCode", + value: "claudeAgent", label: "Claude Code", available: true, }); diff --git a/apps/web/src/session-logic.ts b/apps/web/src/session-logic.ts index 50cc33e5d2c..37683df5cc7 100644 --- a/apps/web/src/session-logic.ts +++ b/apps/web/src/session-logic.ts @@ -18,7 +18,7 @@ import type { TurnDiffSummary, } from "./types"; -export type ProviderPickerKind = ProviderKind | "claudeCode" | "cursor"; +export type ProviderPickerKind = ProviderKind | "claudeAgent" | "cursor"; export const PROVIDER_OPTIONS: Array<{ value: ProviderPickerKind; @@ -27,7 +27,7 @@ export const PROVIDER_OPTIONS: Array<{ }> = [ { value: "codex", label: "Codex", available: true }, { value: "copilot", label: "GitHub Copilot", available: true }, - { value: "claudeCode", label: "Claude Code", available: true }, + { value: "claudeAgent", label: "Claude Code", available: true }, { value: "cursor", label: "Cursor Agent", available: true }, { value: "opencode", label: "OpenCode", available: true }, { value: "geminiCli", label: "Gemini CLI", available: true }, diff --git a/apps/web/src/store.test.ts b/apps/web/src/store.test.ts index 77e822b97c4..8c3816d231d 100644 --- a/apps/web/src/store.test.ts +++ b/apps/web/src/store.test.ts @@ -199,7 +199,7 @@ describe("store read model sync", () => { expect(next.threads[0]?.model).toBe("claude-opus-4-6"); }); - it("resolves claude aliases when session provider is claudeCode", () => { + it("resolves claude aliases when session provider is claudeAgent", () => { const initialState = makeState(makeThread()); const readModel = makeReadModel( makeReadModelThread({ @@ -207,7 +207,7 @@ describe("store read model sync", () => { session: { threadId: ThreadId.makeUnsafe("thread-1"), status: "ready", - providerName: "claudeCode", + providerName: "claudeAgent", runtimeMode: "approval-required", activeTurnId: null, lastError: null, @@ -247,10 +247,10 @@ describe("store read model sync", () => { it("preserves the previous provider when a thread session closes", () => { const initialState = makeState( makeThread({ - provider: "claudeCode", + provider: "claudeAgent", model: "claude-sonnet-4-6", session: { - provider: "claudeCode", + provider: "claudeAgent", status: "ready", orchestrationStatus: "ready", createdAt: "2026-02-27T00:00:00.000Z", @@ -267,7 +267,7 @@ describe("store read model sync", () => { const next = syncServerReadModel(initialState, readModel); - expect(next.threads[0]?.provider).toBe("claudeCode"); + expect(next.threads[0]?.provider).toBe("claudeAgent"); expect(next.threads[0]?.model).toBe("claude-sonnet-4-6"); expect(next.threads[0]?.session).toBeNull(); }); diff --git a/packages/contracts/src/model.ts b/packages/contracts/src/model.ts index 60b46f8f622..78a67a552bd 100644 --- a/packages/contracts/src/model.ts +++ b/packages/contracts/src/model.ts @@ -30,11 +30,11 @@ export const OpencodeModelOptions = Schema.Struct({ }); export type OpencodeModelOptions = typeof OpencodeModelOptions.Type; -export const ClaudeCodeModelOptions = Schema.Struct({ +export const ClaudeModelOptions = Schema.Struct({ thinking: Schema.optional(Schema.Boolean), effort: Schema.optional(Schema.Literals(CLAUDE_CODE_EFFORT_OPTIONS)), }); -export type ClaudeCodeModelOptions = typeof ClaudeCodeModelOptions.Type; +export type ClaudeModelOptions = typeof ClaudeModelOptions.Type; export const CursorModelOptions = Schema.Struct({ reasoning: Schema.optional(Schema.Literals(CURSOR_REASONING_OPTIONS)), @@ -65,7 +65,7 @@ export type KiloModelOptions = typeof KiloModelOptions.Type; export const ProviderModelOptions = Schema.Struct({ codex: Schema.optional(CodexModelOptions), copilot: Schema.optional(CopilotModelOptions), - claudeCode: Schema.optional(ClaudeCodeModelOptions), + claudeAgent: Schema.optional(ClaudeModelOptions), cursor: Schema.optional(CursorModelOptions), opencode: Schema.optional(OpencodeModelOptions), geminiCli: Schema.optional(GeminiCliModelOptions), @@ -146,7 +146,7 @@ export const MODEL_OPTIONS_BY_PROVIDER = { { slug: "gpt-5-mini", name: "GPT-5 mini" }, { slug: "gpt-4.1", name: "GPT-4.1" }, ], - claudeCode: [ + claudeAgent: [ { slug: "claude-opus-4-6", name: "Claude Opus 4.6" }, { slug: "claude-sonnet-4-6", name: "Claude Sonnet 4.6" }, { slug: "claude-haiku-4-5", name: "Claude Haiku 4.5" }, @@ -223,7 +223,7 @@ export type CursorModelSlug = (typeof MODEL_OPTIONS_BY_PROVIDER)["cursor"][numbe export const DEFAULT_MODEL_BY_PROVIDER = { codex: "gpt-5.4", copilot: "claude-sonnet-4.6", - claudeCode: "claude-sonnet-4-6", + claudeAgent: "claude-sonnet-4-6", cursor: "opus-4.6-thinking", opencode: "gpt-5", geminiCli: "gemini-2.5-pro", @@ -263,7 +263,7 @@ export const MODEL_SLUG_ALIASES_BY_PROVIDER: Record { it("accepts claude runtime knobs", () => { const parsed = decodeProviderSessionStartInput({ threadId: "thread-1", - provider: "claudeCode", + provider: "claudeAgent", cwd: "/tmp/workspace", model: "claude-sonnet-4-6", providerOptions: { - claudeCode: { + claudeAgent: { binaryPath: "/usr/local/bin/claude", permissionMode: "plan", maxThinkingTokens: 12_000, @@ -78,10 +78,10 @@ describe("ProviderSessionStartInput", () => { }, runtimeMode: "full-access", }); - expect(parsed.provider).toBe("claudeCode"); - expect(parsed.providerOptions?.claudeCode?.binaryPath).toBe("/usr/local/bin/claude"); - expect(parsed.providerOptions?.claudeCode?.permissionMode).toBe("plan"); - expect(parsed.providerOptions?.claudeCode?.maxThinkingTokens).toBe(12_000); + expect(parsed.provider).toBe("claudeAgent"); + expect(parsed.providerOptions?.claudeAgent?.binaryPath).toBe("/usr/local/bin/claude"); + expect(parsed.providerOptions?.claudeAgent?.permissionMode).toBe("plan"); + expect(parsed.providerOptions?.claudeAgent?.maxThinkingTokens).toBe(12_000); expect(parsed.runtimeMode).toBe("full-access"); }); diff --git a/packages/contracts/src/providerRuntime.test.ts b/packages/contracts/src/providerRuntime.test.ts index 6daf679fe2d..b049830605d 100644 --- a/packages/contracts/src/providerRuntime.test.ts +++ b/packages/contracts/src/providerRuntime.test.ts @@ -10,7 +10,7 @@ describe("ProviderRuntimeEvent", () => { const parsed = decodeRuntimeEvent({ type: "turn.plan.updated", eventId: "event-1", - provider: "claudeCode", + provider: "claudeAgent", sessionId: "runtime-session-1", createdAt: "2026-02-28T00:00:00.000Z", threadId: "thread-1", diff --git a/packages/shared/src/model.test.ts b/packages/shared/src/model.test.ts index 9587045643f..49e97627a69 100644 --- a/packages/shared/src/model.test.ts +++ b/packages/shared/src/model.test.ts @@ -43,9 +43,9 @@ describe("normalizeModelSlug", () => { }); it("uses provider-specific aliases", () => { - expect(normalizeModelSlug("sonnet", "claudeCode")).toBe("claude-sonnet-4-6"); - expect(normalizeModelSlug("opus-4.6", "claudeCode")).toBe("claude-opus-4-6"); - expect(normalizeModelSlug("claude-haiku-4-5-20251001", "claudeCode")).toBe("claude-haiku-4-5"); + expect(normalizeModelSlug("sonnet", "claudeAgent")).toBe("claude-sonnet-4-6"); + expect(normalizeModelSlug("opus-4.6", "claudeAgent")).toBe("claude-opus-4-6"); + expect(normalizeModelSlug("claude-haiku-4-5-20251001", "claudeAgent")).toBe("claude-haiku-4-5"); expect(normalizeModelSlug("composer", "cursor")).toBe("composer-1.5"); expect(normalizeModelSlug("gpt-5.3-codex-spark", "cursor")).toBe("gpt-5.3-codex-spark-preview"); expect(normalizeModelSlug("gpt-5.4", "cursor")).toBe("gpt-5.4-medium"); @@ -79,12 +79,12 @@ describe("resolveModelSlug", () => { }); it("supports provider-aware resolution", () => { - expect(resolveModelSlugForProvider("claudeCode", undefined)).toBe( - DEFAULT_MODEL_BY_PROVIDER.claudeCode, + expect(resolveModelSlugForProvider("claudeAgent", undefined)).toBe( + DEFAULT_MODEL_BY_PROVIDER.claudeAgent, ); - expect(resolveModelSlugForProvider("claudeCode", "sonnet")).toBe("claude-sonnet-4-6"); - expect(resolveModelSlugForProvider("claudeCode", "gpt-5.3-codex")).toBe( - DEFAULT_MODEL_BY_PROVIDER.claudeCode, + expect(resolveModelSlugForProvider("claudeAgent", "sonnet")).toBe("claude-sonnet-4-6"); + expect(resolveModelSlugForProvider("claudeAgent", "gpt-5.3-codex")).toBe( + DEFAULT_MODEL_BY_PROVIDER.claudeAgent, ); expect(resolveModelSlugForProvider("cursor", undefined)).toBe(DEFAULT_MODEL_BY_PROVIDER.cursor); expect(resolveModelSlugForProvider("cursor", "composer")).toBe("composer-1.5"); @@ -99,7 +99,7 @@ describe("resolveModelSlug", () => { it("keeps codex defaults for backward compatibility", () => { expect(getDefaultModel()).toBe(DEFAULT_MODEL); expect(getModelOptions()).toEqual(MODEL_OPTIONS); - expect(getModelOptions("claudeCode")).toEqual(MODEL_OPTIONS_BY_PROVIDER.claudeCode); + expect(getModelOptions("claudeAgent")).toEqual(MODEL_OPTIONS_BY_PROVIDER.claudeAgent); expect(getModelOptions("cursor")).toEqual(MODEL_OPTIONS_BY_PROVIDER.cursor); expect(getCursorModelFamilyOptions()).toEqual(CURSOR_MODEL_FAMILY_OPTIONS); }); @@ -190,8 +190,8 @@ describe("getReasoningEffortOptions", () => { expect(getReasoningEffortOptions("codex")).toEqual(REASONING_EFFORT_OPTIONS_BY_PROVIDER.codex); }); - it("returns no reasoning options for claudeCode", () => { - expect(getReasoningEffortOptions("claudeCode")).toEqual([]); + it("returns no reasoning options for claudeAgent", () => { + expect(getReasoningEffortOptions("claudeAgent")).toEqual([]); }); it("returns no reasoning options for cursor", () => { @@ -202,8 +202,8 @@ describe("getReasoningEffortOptions", () => { describe("getDefaultReasoningEffort", () => { it("returns provider-scoped defaults", () => { expect(getDefaultReasoningEffort("codex")).toBe(DEFAULT_REASONING_EFFORT_BY_PROVIDER.codex); - expect(getDefaultReasoningEffort("claudeCode")).toBe( - DEFAULT_REASONING_EFFORT_BY_PROVIDER.claudeCode, + expect(getDefaultReasoningEffort("claudeAgent")).toBe( + DEFAULT_REASONING_EFFORT_BY_PROVIDER.claudeAgent, ); expect(getDefaultReasoningEffort("cursor")).toBe(DEFAULT_REASONING_EFFORT_BY_PROVIDER.cursor); }); diff --git a/packages/shared/src/model.ts b/packages/shared/src/model.ts index 7ad63ca16de..49cf928de0c 100644 --- a/packages/shared/src/model.ts +++ b/packages/shared/src/model.ts @@ -222,7 +222,7 @@ const CURSOR_MODEL_CAPABILITY_BY_FAMILY: Record> = { codex: new Set(MODEL_OPTIONS_BY_PROVIDER.codex.map((option) => option.slug)), copilot: new Set(MODEL_OPTIONS_BY_PROVIDER.copilot.map((option) => option.slug)), - claudeCode: new Set(MODEL_OPTIONS_BY_PROVIDER.claudeCode.map((option) => option.slug)), + claudeAgent: new Set(MODEL_OPTIONS_BY_PROVIDER.claudeAgent.map((option) => option.slug)), cursor: new Set(MODEL_OPTIONS_BY_PROVIDER.cursor.map((option) => option.slug)), opencode: new Set(MODEL_OPTIONS_BY_PROVIDER.opencode.map((option) => option.slug)), kilo: new Set(MODEL_OPTIONS_BY_PROVIDER.kilo.map((option) => option.slug)), @@ -443,15 +443,15 @@ export function getDefaultReasoningEffort( } export function getClaudeCodeEffortOptions( - provider: ProviderKind = "claudeCode", + provider: ProviderKind = "claudeAgent", ): ReadonlyArray { return CLAUDE_CODE_EFFORT_OPTIONS_BY_PROVIDER[provider]; } -export function getDefaultClaudeCodeEffort(provider: "claudeCode"): ClaudeCodeEffort; +export function getDefaultClaudeCodeEffort(provider: "claudeAgent"): ClaudeCodeEffort; export function getDefaultClaudeCodeEffort(provider: ProviderKind): ClaudeCodeEffort | null; export function getDefaultClaudeCodeEffort( - provider: ProviderKind = "claudeCode", + provider: ProviderKind = "claudeAgent", ): ClaudeCodeEffort | null { return DEFAULT_CLAUDE_CODE_EFFORT_BY_PROVIDER[provider]; } From 1fb7a2698b8f8413a6c103c778fa271b8b08577e Mon Sep 17 00:00:00 2001 From: Utkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com> Date: Wed, 18 Mar 2026 22:16:09 +0530 Subject: [PATCH 02/15] fix: implement button overflow (#1193) --- apps/web/src/components/ChatView.tsx | 2 +- .../src/components/chat/CodexTraitsPicker.tsx | 25 ++++++++++++------- .../components/chat/ProviderModelPicker.tsx | 13 ++++++---- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 97155717f4b..2002597fae8 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -3881,7 +3881,7 @@ export default function ChatView({ threadId }: ChatViewProps) { "flex min-w-0 flex-1 items-center", isComposerFooterCompact ? "gap-1 overflow-hidden" - : "gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden sm:min-w-max sm:overflow-visible", + : "gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", )} > {/* Provider/model picker */} diff --git a/apps/web/src/components/chat/CodexTraitsPicker.tsx b/apps/web/src/components/chat/CodexTraitsPicker.tsx index 6c72f497ba9..a8a65250ed7 100644 --- a/apps/web/src/components/chat/CodexTraitsPicker.tsx +++ b/apps/web/src/components/chat/CodexTraitsPicker.tsx @@ -28,12 +28,7 @@ export const CodexTraitsPicker = memo(function CodexTraitsPicker(props: { high: "High", xhigh: "Extra High", }; - const triggerLabel = [ - reasoningLabelByOption[props.effort], - ...(props.fastModeEnabled ? ["Fast"] : []), - ] - .filter(Boolean) - .join(" · "); + const effortLabel = reasoningLabelByOption[props.effort]; return ( } > - {triggerLabel} -