Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
37eb492
Add provider-specific model resolution and defaults
juliusmarminge Feb 27, 2026
2ed16e5
redo contracts a bit
juliusmarminge Feb 27, 2026
310c763
revised plan
juliusmarminge Feb 27, 2026
f2e087c
Add Claude Code adapter live layer with error mapping tests
juliusmarminge Feb 27, 2026
b8e3b46
Wire Claude adapter into registry and server provider layer
juliusmarminge Feb 27, 2026
1fb3574
Support provider-aware session selection in reactor
juliusmarminge Feb 27, 2026
b8069d2
Enable Claude provider selection in chat composer
juliusmarminge Feb 27, 2026
fb62d21
Add Claude checkpoint and revert reactor coverage
juliusmarminge Feb 27, 2026
83b7200
Add Claude integration coverage across orchestration flows
juliusmarminge Feb 27, 2026
344d9b4
Make Claude runtime boundary Effect-native
juliusmarminge Feb 27, 2026
b03287e
Use typed errors for unavailable Claude runtime path
juliusmarminge Feb 27, 2026
fb1e7c1
unnecessary catch
juliusmarminge Feb 27, 2026
e45cd8f
Inline Claude adapter behavior into live layer
juliusmarminge Feb 27, 2026
8be8fcb
Use grouped provider/model select in chat composer
juliusmarminge Feb 27, 2026
600cfaf
Show provider logos in composer model trigger
juliusmarminge Feb 27, 2026
b6f93ea
Update Claude model catalog to latest 4.6/4.5 gen
juliusmarminge Feb 27, 2026
67eef99
Fix Claude model fallback in web store sync
juliusmarminge Feb 27, 2026
f00d414
Include all provider models in /model slash command
juliusmarminge Feb 27, 2026
e5f12e6
Integrate Claude agent SDK into server provider adapter
juliusmarminge Feb 27, 2026
6ff39f9
Refactor ClaudeCodeAdapter session flow and stream handling
juliusmarminge Feb 27, 2026
3e6ac44
Fix Claude resume cursor to only persist valid session UUIDs
juliusmarminge Feb 27, 2026
2113000
Align orchestration integration tests with latestTurn metadata
juliusmarminge Feb 27, 2026
8d23276
Ignore stale resume cursors and Claude placeholder thread IDs
juliusmarminge Feb 28, 2026
870096b
Fix ProviderService sendTurn recovery expectation after rebase
juliusmarminge Feb 28, 2026
02c89a5
Stabilize Claude turn event ordering and native event logging
juliusmarminge Feb 28, 2026
d75ca11
Align Claude permissions and provider-specific reasoning effort
juliusmarminge Feb 28, 2026
2c631e8
Track runtime event sequence and order thread activities by sequence
juliusmarminge Feb 28, 2026
f265f56
Add Cursor CLI stream event schemas and decoding tests
juliusmarminge Feb 27, 2026
87c797b
Add Cursor provider support across backend, contracts, and UI
juliusmarminge Feb 28, 2026
ebd44f9
Add Cursor ACP probe script and captured session logs
juliusmarminge Mar 1, 2026
5d42e4b
Revise Cursor provider plan for ACP JSON-RPC integration
juliusmarminge Mar 1, 2026
acd57a1
Document Cursor ACP mapping in canonical runtime event spec
juliusmarminge Mar 1, 2026
719c7dc
Introduce v2 provider runtime event schema and validation tests
juliusmarminge Mar 1, 2026
7ef6b20
Scope reasoning effort defaults and options by provider
juliusmarminge Mar 1, 2026
14865dc
Implement v2 canonical provider runtime adapters
cursoragent Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 49 additions & 46 deletions .plans/17-claude-code.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov

---

## Current constraints to design around
## Current constraints to design around (post-Stage 1)

1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.

Expand DownExpand Up@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:

This removes the implicit “Codex unless session already exists” behavior as the only path.

### 1.3 Provider session start input for Claude runtime knobs
### 1.3 Provider session start input for Claude runtime knobs (completed)

Update `packages/contracts/src/provider.ts`:

1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
2. Keep fields optional so current call sites remain valid.
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
1. Move provider-specific start fields into typed `providerOptions`:
- `providerOptions.codex`
- `providerOptions.claudeCode`
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
3. Deprecate/remove `resumeThreadId` from the generic start contract.
4. Treat `resumeCursor` as adapter-owned opaque state.

### 1.4 Contract tests
### 1.4 Contract tests (completed)

Update/add tests in `packages/contracts/src/*.test.ts` for:

1. New command payload shape.
2. Provider-aware model resolution behavior.
3. Backward compatibility of existing command/schema decoding.
3. Breaking-change expectations for removed top-level provider fields.

---

Expand All@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:

1. `cwd`
2. `model`
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
4. `permissionMode`
5. `maxThinkingTokens`
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
6. `resume`
7. `resumeSessionAt`
8. `includePartialMessages`
Expand All@@ -120,7 +123,7 @@ Required capabilities:
2. Multi-turn input queue.
3. Interrupt support.
4. Approval request/response bridge.
5. Resume support via `resumeThreadId` / `resumeCursor`.
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).

#### 2.2.a Agent SDK details to preserve

Expand All@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
2. Multi-turn input is supported via async-iterable prompt input.
3. Tool approval decisions are provided via `canUseTool`.
4. Resume support uses `resume` and optional `resumeSessionAt`.
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.

#### 2.2.b Effect-native session lifecycle skeleton
Expand All@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
Effect.acquireRelease(
Effect.tryPromise({
try: async () => {
const claudeOptions = input.providerOptions?.claudeCode;
const resumeState = readClaudeResumeState(input.resumeCursor);
const abortController = new AbortController();
const result = query({
prompt: makePromptAsyncIterable(input.sessionId),
prompt: makePromptAsyncIterable(),
options: {
cwd: input.cwd,
model: input.model,
permissionMode: input.permissionMode,
maxThinkingTokens: input.maxThinkingTokens,
pathToClaudeCodeExecutable: input.claudeBinaryPath,
resume: input.resumeThreadId,
resumeSessionAt: readResumeCursor(input.resumeCursor),
permissionMode: claudeOptions?.permissionMode,
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
resume: resumeState?.threadId,
resumeSessionAt: resumeState?.sessionAt,
signal: abortController.signal,
includePartialMessages: true,
canUseTool: makeCanUseTool(input.sessionId),
hooks: makeClaudeHooks(input.sessionId),
canUseTool: makeCanUseTool(),
hooks: makeClaudeHooks(),
},
});
return { abortController, result };
Expand DownExpand Up@@ -345,7 +350,8 @@ Define explicit adapter semantics:

1. `sessionId`: adapter-owned stable session id.
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.

### 2.5 Rollback/read strategy

Expand DownExpand Up@@ -402,11 +408,12 @@ Update integration tests to ensure:

## Phase 4: Orchestration command/reactor updates

### 4.1 Decider propagation
### 4.1 Decider propagation (completed)

Update `apps/server/src/orchestration/decider.ts`:

1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).

### 4.2 ProviderCommandReactor provider selection

Expand All@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
1. Prefer provider from turn-start event payload when starting a new session.
2. Fallback to existing thread session provider when payload omitted.
3. Fallback to default provider only when neither is present.
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).

Switch behavior policy (explicit in implementation):

Expand DownExpand Up@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter

## File checklist

Likely files to touch:

1. `packages/contracts/src/model.ts`
2. `packages/contracts/src/orchestration.ts`
3. `packages/contracts/src/provider.ts`
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
7. `apps/server/src/serverLayers.ts`
8. `apps/server/src/orchestration/decider.ts`
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
10. `apps/web/src/session-logic.ts`
11. `apps/web/src/components/ChatView.tsx`
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
Likely remaining files to touch:

1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
4. `apps/server/src/serverLayers.ts`
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
6. `apps/web/src/session-logic.ts`
7. `apps/web/src/components/ChatView.tsx`
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.

---

## Delivery order

1. Contracts for provider selection + models.
2. Claude adapter + unit tests.
3. Registry/layer wiring.
4. Reactor updates for provider-aware session start.
5. Web provider picker + provider-aware models.
6. Checkpoint/revert compatibility.
7. End-to-end integration tests and stabilization.
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
2. Registry/layer wiring.
3. Remaining reactor updates for provider-aware session selection/switching invariants.
4. Web provider picker + provider-aware models.
5. Checkpoint/revert compatibility.
6. End-to-end integration tests and stabilization.

This order keeps risk isolated and maintains a working orchestrated path at each stage.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
37eb492
Add provider-specific model resolution and defaults
juliusmarminge Feb 27, 2026
2ed16e5
redo contracts a bit
juliusmarminge Feb 27, 2026
310c763
revised plan
juliusmarminge Feb 27, 2026
f2e087c
Add Claude Code adapter live layer with error mapping tests
juliusmarminge Feb 27, 2026
b8e3b46
Wire Claude adapter into registry and server provider layer
juliusmarminge Feb 27, 2026
1fb3574
Support provider-aware session selection in reactor
juliusmarminge Feb 27, 2026
b8069d2
Enable Claude provider selection in chat composer
juliusmarminge Feb 27, 2026
fb62d21
Add Claude checkpoint and revert reactor coverage
juliusmarminge Feb 27, 2026
83b7200
Add Claude integration coverage across orchestration flows
juliusmarminge Feb 27, 2026
344d9b4
Make Claude runtime boundary Effect-native
juliusmarminge Feb 27, 2026
b03287e
Use typed errors for unavailable Claude runtime path
juliusmarminge Feb 27, 2026
fb1e7c1
unnecessary catch
juliusmarminge Feb 27, 2026
e45cd8f
Inline Claude adapter behavior into live layer
juliusmarminge Feb 27, 2026
8be8fcb
Use grouped provider/model select in chat composer
juliusmarminge Feb 27, 2026
600cfaf
Show provider logos in composer model trigger
juliusmarminge Feb 27, 2026
b6f93ea
Update Claude model catalog to latest 4.6/4.5 gen
juliusmarminge Feb 27, 2026
67eef99
Fix Claude model fallback in web store sync
juliusmarminge Feb 27, 2026
f00d414
Include all provider models in /model slash command
juliusmarminge Feb 27, 2026
e5f12e6
Integrate Claude agent SDK into server provider adapter
juliusmarminge Feb 27, 2026
6ff39f9
Refactor ClaudeCodeAdapter session flow and stream handling
juliusmarminge Feb 27, 2026
3e6ac44
Fix Claude resume cursor to only persist valid session UUIDs
juliusmarminge Feb 27, 2026
2113000
Align orchestration integration tests with latestTurn metadata
juliusmarminge Feb 27, 2026
8d23276
Ignore stale resume cursors and Claude placeholder thread IDs
juliusmarminge Feb 28, 2026
870096b
Fix ProviderService sendTurn recovery expectation after rebase
juliusmarminge Feb 28, 2026
02c89a5
Stabilize Claude turn event ordering and native event logging
juliusmarminge Feb 28, 2026
d75ca11
Align Claude permissions and provider-specific reasoning effort
juliusmarminge Feb 28, 2026
2c631e8
Track runtime event sequence and order thread activities by sequence
juliusmarminge Feb 28, 2026
f265f56
Add Cursor CLI stream event schemas and decoding tests
juliusmarminge Feb 27, 2026
87c797b
Add Cursor provider support across backend, contracts, and UI
juliusmarminge Feb 28, 2026
ebd44f9
Add Cursor ACP probe script and captured session logs
juliusmarminge Mar 1, 2026
5d42e4b
Revise Cursor provider plan for ACP JSON-RPC integration
juliusmarminge Mar 1, 2026
acd57a1
Document Cursor ACP mapping in canonical runtime event spec
juliusmarminge Mar 1, 2026
719c7dc
Introduce v2 provider runtime event schema and validation tests
juliusmarminge Mar 1, 2026
7ef6b20
Scope reasoning effort defaults and options by provider
juliusmarminge Mar 1, 2026
14865dc
Implement v2 canonical provider runtime adapters
cursoragent Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 49 additions & 46 deletions .plans/17-claude-code.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov

---

## Current constraints to design around
## Current constraints to design around (post-Stage 1)

1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.

Expand DownExpand Up@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:

This removes the implicit “Codex unless session already exists” behavior as the only path.

### 1.3 Provider session start input for Claude runtime knobs
### 1.3 Provider session start input for Claude runtime knobs (completed)

Update `packages/contracts/src/provider.ts`:

1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
2. Keep fields optional so current call sites remain valid.
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
1. Move provider-specific start fields into typed `providerOptions`:
- `providerOptions.codex`
- `providerOptions.claudeCode`
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
3. Deprecate/remove `resumeThreadId` from the generic start contract.
4. Treat `resumeCursor` as adapter-owned opaque state.

### 1.4 Contract tests
### 1.4 Contract tests (completed)

Update/add tests in `packages/contracts/src/*.test.ts` for:

1. New command payload shape.
2. Provider-aware model resolution behavior.
3. Backward compatibility of existing command/schema decoding.
3. Breaking-change expectations for removed top-level provider fields.

---

Expand All@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:

1. `cwd`
2. `model`
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
4. `permissionMode`
5. `maxThinkingTokens`
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
6. `resume`
7. `resumeSessionAt`
8. `includePartialMessages`
Expand All@@ -120,7 +123,7 @@ Required capabilities:
2. Multi-turn input queue.
3. Interrupt support.
4. Approval request/response bridge.
5. Resume support via `resumeThreadId` / `resumeCursor`.
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).

#### 2.2.a Agent SDK details to preserve

Expand All@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
2. Multi-turn input is supported via async-iterable prompt input.
3. Tool approval decisions are provided via `canUseTool`.
4. Resume support uses `resume` and optional `resumeSessionAt`.
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.

#### 2.2.b Effect-native session lifecycle skeleton
Expand All@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
Effect.acquireRelease(
Effect.tryPromise({
try: async () => {
const claudeOptions = input.providerOptions?.claudeCode;
const resumeState = readClaudeResumeState(input.resumeCursor);
const abortController = new AbortController();
const result = query({
prompt: makePromptAsyncIterable(input.sessionId),
prompt: makePromptAsyncIterable(),
options: {
cwd: input.cwd,
model: input.model,
permissionMode: input.permissionMode,
maxThinkingTokens: input.maxThinkingTokens,
pathToClaudeCodeExecutable: input.claudeBinaryPath,
resume: input.resumeThreadId,
resumeSessionAt: readResumeCursor(input.resumeCursor),
permissionMode: claudeOptions?.permissionMode,
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
resume: resumeState?.threadId,
resumeSessionAt: resumeState?.sessionAt,
signal: abortController.signal,
includePartialMessages: true,
canUseTool: makeCanUseTool(input.sessionId),
hooks: makeClaudeHooks(input.sessionId),
canUseTool: makeCanUseTool(),
hooks: makeClaudeHooks(),
},
});
return { abortController, result };
Expand DownExpand Up@@ -345,7 +350,8 @@ Define explicit adapter semantics:

1. `sessionId`: adapter-owned stable session id.
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.

### 2.5 Rollback/read strategy

Expand DownExpand Up@@ -402,11 +408,12 @@ Update integration tests to ensure:

## Phase 4: Orchestration command/reactor updates

### 4.1 Decider propagation
### 4.1 Decider propagation (completed)

Update `apps/server/src/orchestration/decider.ts`:

1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).

### 4.2 ProviderCommandReactor provider selection

Expand All@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
1. Prefer provider from turn-start event payload when starting a new session.
2. Fallback to existing thread session provider when payload omitted.
3. Fallback to default provider only when neither is present.
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).

Switch behavior policy (explicit in implementation):

Expand DownExpand Up@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter

## File checklist

Likely files to touch:

1. `packages/contracts/src/model.ts`
2. `packages/contracts/src/orchestration.ts`
3. `packages/contracts/src/provider.ts`
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
7. `apps/server/src/serverLayers.ts`
8. `apps/server/src/orchestration/decider.ts`
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
10. `apps/web/src/session-logic.ts`
11. `apps/web/src/components/ChatView.tsx`
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
Likely remaining files to touch:

1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
4. `apps/server/src/serverLayers.ts`
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
6. `apps/web/src/session-logic.ts`
7. `apps/web/src/components/ChatView.tsx`
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.

---

## Delivery order

1. Contracts for provider selection + models.
2. Claude adapter + unit tests.
3. Registry/layer wiring.
4. Reactor updates for provider-aware session start.
5. Web provider picker + provider-aware models.
6. Checkpoint/revert compatibility.
7. End-to-end integration tests and stabilization.
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
2. Registry/layer wiring.
3. Remaining reactor updates for provider-aware session selection/switching invariants.
4. Web provider picker + provider-aware models.
5. Checkpoint/revert compatibility.
6. End-to-end integration tests and stabilization.

This order keeps risk isolated and maintains a working orchestrated path at each stage.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
37eb492
Add provider-specific model resolution and defaults
juliusmarminge Feb 27, 2026
2ed16e5
redo contracts a bit
juliusmarminge Feb 27, 2026
310c763
revised plan
juliusmarminge Feb 27, 2026
f2e087c
Add Claude Code adapter live layer with error mapping tests
juliusmarminge Feb 27, 2026
b8e3b46
Wire Claude adapter into registry and server provider layer
juliusmarminge Feb 27, 2026
1fb3574
Support provider-aware session selection in reactor
juliusmarminge Feb 27, 2026
b8069d2
Enable Claude provider selection in chat composer
juliusmarminge Feb 27, 2026
fb62d21
Add Claude checkpoint and revert reactor coverage
juliusmarminge Feb 27, 2026
83b7200
Add Claude integration coverage across orchestration flows
juliusmarminge Feb 27, 2026
344d9b4
Make Claude runtime boundary Effect-native
juliusmarminge Feb 27, 2026
b03287e
Use typed errors for unavailable Claude runtime path
juliusmarminge Feb 27, 2026
fb1e7c1
unnecessary catch
juliusmarminge Feb 27, 2026
e45cd8f
Inline Claude adapter behavior into live layer
juliusmarminge Feb 27, 2026
8be8fcb
Use grouped provider/model select in chat composer
juliusmarminge Feb 27, 2026
600cfaf
Show provider logos in composer model trigger
juliusmarminge Feb 27, 2026
b6f93ea
Update Claude model catalog to latest 4.6/4.5 gen
juliusmarminge Feb 27, 2026
67eef99
Fix Claude model fallback in web store sync
juliusmarminge Feb 27, 2026
f00d414
Include all provider models in /model slash command
juliusmarminge Feb 27, 2026
e5f12e6
Integrate Claude agent SDK into server provider adapter
juliusmarminge Feb 27, 2026
6ff39f9
Refactor ClaudeCodeAdapter session flow and stream handling
juliusmarminge Feb 27, 2026
3e6ac44
Fix Claude resume cursor to only persist valid session UUIDs
juliusmarminge Feb 27, 2026
2113000
Align orchestration integration tests with latestTurn metadata
juliusmarminge Feb 27, 2026
8d23276
Ignore stale resume cursors and Claude placeholder thread IDs
juliusmarminge Feb 28, 2026
870096b
Fix ProviderService sendTurn recovery expectation after rebase
juliusmarminge Feb 28, 2026
02c89a5
Stabilize Claude turn event ordering and native event logging
juliusmarminge Feb 28, 2026
d75ca11
Align Claude permissions and provider-specific reasoning effort
juliusmarminge Feb 28, 2026
2c631e8
Track runtime event sequence and order thread activities by sequence
juliusmarminge Feb 28, 2026
f265f56
Add Cursor CLI stream event schemas and decoding tests
juliusmarminge Feb 27, 2026
87c797b
Add Cursor provider support across backend, contracts, and UI
juliusmarminge Feb 28, 2026
ebd44f9
Add Cursor ACP probe script and captured session logs
juliusmarminge Mar 1, 2026
5d42e4b
Revise Cursor provider plan for ACP JSON-RPC integration
juliusmarminge Mar 1, 2026
acd57a1
Document Cursor ACP mapping in canonical runtime event spec
juliusmarminge Mar 1, 2026
719c7dc
Introduce v2 provider runtime event schema and validation tests
juliusmarminge Mar 1, 2026
7ef6b20
Scope reasoning effort defaults and options by provider
juliusmarminge Mar 1, 2026
14865dc
Implement v2 canonical provider runtime adapters
cursoragent Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 49 additions & 46 deletions .plans/17-claude-code.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov

---

## Current constraints to design around
## Current constraints to design around (post-Stage 1)

1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.

Expand DownExpand Up@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:

This removes the implicit “Codex unless session already exists” behavior as the only path.

### 1.3 Provider session start input for Claude runtime knobs
### 1.3 Provider session start input for Claude runtime knobs (completed)

Update `packages/contracts/src/provider.ts`:

1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
2. Keep fields optional so current call sites remain valid.
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
1. Move provider-specific start fields into typed `providerOptions`:
- `providerOptions.codex`
- `providerOptions.claudeCode`
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
3. Deprecate/remove `resumeThreadId` from the generic start contract.
4. Treat `resumeCursor` as adapter-owned opaque state.

### 1.4 Contract tests
### 1.4 Contract tests (completed)

Update/add tests in `packages/contracts/src/*.test.ts` for:

1. New command payload shape.
2. Provider-aware model resolution behavior.
3. Backward compatibility of existing command/schema decoding.
3. Breaking-change expectations for removed top-level provider fields.

---

Expand All@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:

1. `cwd`
2. `model`
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
4. `permissionMode`
5. `maxThinkingTokens`
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
6. `resume`
7. `resumeSessionAt`
8. `includePartialMessages`
Expand All@@ -120,7 +123,7 @@ Required capabilities:
2. Multi-turn input queue.
3. Interrupt support.
4. Approval request/response bridge.
5. Resume support via `resumeThreadId` / `resumeCursor`.
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).

#### 2.2.a Agent SDK details to preserve

Expand All@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
2. Multi-turn input is supported via async-iterable prompt input.
3. Tool approval decisions are provided via `canUseTool`.
4. Resume support uses `resume` and optional `resumeSessionAt`.
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.

#### 2.2.b Effect-native session lifecycle skeleton
Expand All@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
Effect.acquireRelease(
Effect.tryPromise({
try: async () => {
const claudeOptions = input.providerOptions?.claudeCode;
const resumeState = readClaudeResumeState(input.resumeCursor);
const abortController = new AbortController();
const result = query({
prompt: makePromptAsyncIterable(input.sessionId),
prompt: makePromptAsyncIterable(),
options: {
cwd: input.cwd,
model: input.model,
permissionMode: input.permissionMode,
maxThinkingTokens: input.maxThinkingTokens,
pathToClaudeCodeExecutable: input.claudeBinaryPath,
resume: input.resumeThreadId,
resumeSessionAt: readResumeCursor(input.resumeCursor),
permissionMode: claudeOptions?.permissionMode,
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
resume: resumeState?.threadId,
resumeSessionAt: resumeState?.sessionAt,
signal: abortController.signal,
includePartialMessages: true,
canUseTool: makeCanUseTool(input.sessionId),
hooks: makeClaudeHooks(input.sessionId),
canUseTool: makeCanUseTool(),
hooks: makeClaudeHooks(),
},
});
return { abortController, result };
Expand DownExpand Up@@ -345,7 +350,8 @@ Define explicit adapter semantics:

1. `sessionId`: adapter-owned stable session id.
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.

### 2.5 Rollback/read strategy

Expand DownExpand Up@@ -402,11 +408,12 @@ Update integration tests to ensure:

## Phase 4: Orchestration command/reactor updates

### 4.1 Decider propagation
### 4.1 Decider propagation (completed)

Update `apps/server/src/orchestration/decider.ts`:

1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).

### 4.2 ProviderCommandReactor provider selection

Expand All@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
1. Prefer provider from turn-start event payload when starting a new session.
2. Fallback to existing thread session provider when payload omitted.
3. Fallback to default provider only when neither is present.
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).

Switch behavior policy (explicit in implementation):

Expand DownExpand Up@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter

## File checklist

Likely files to touch:

1. `packages/contracts/src/model.ts`
2. `packages/contracts/src/orchestration.ts`
3. `packages/contracts/src/provider.ts`
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
7. `apps/server/src/serverLayers.ts`
8. `apps/server/src/orchestration/decider.ts`
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
10. `apps/web/src/session-logic.ts`
11. `apps/web/src/components/ChatView.tsx`
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
Likely remaining files to touch:

1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
4. `apps/server/src/serverLayers.ts`
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
6. `apps/web/src/session-logic.ts`
7. `apps/web/src/components/ChatView.tsx`
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.

---

## Delivery order

1. Contracts for provider selection + models.
2. Claude adapter + unit tests.
3. Registry/layer wiring.
4. Reactor updates for provider-aware session start.
5. Web provider picker + provider-aware models.
6. Checkpoint/revert compatibility.
7. End-to-end integration tests and stabilization.
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
2. Registry/layer wiring.
3. Remaining reactor updates for provider-aware session selection/switching invariants.
4. Web provider picker + provider-aware models.
5. Checkpoint/revert compatibility.
6. End-to-end integration tests and stabilization.

This order keeps risk isolated and maintains a working orchestrated path at each stage.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
37eb492
Add provider-specific model resolution and defaults
juliusmarminge Feb 27, 2026
2ed16e5
redo contracts a bit
juliusmarminge Feb 27, 2026
310c763
revised plan
juliusmarminge Feb 27, 2026
f2e087c
Add Claude Code adapter live layer with error mapping tests
juliusmarminge Feb 27, 2026
b8e3b46
Wire Claude adapter into registry and server provider layer
juliusmarminge Feb 27, 2026
1fb3574
Support provider-aware session selection in reactor
juliusmarminge Feb 27, 2026
b8069d2
Enable Claude provider selection in chat composer
juliusmarminge Feb 27, 2026
fb62d21
Add Claude checkpoint and revert reactor coverage
juliusmarminge Feb 27, 2026
83b7200
Add Claude integration coverage across orchestration flows
juliusmarminge Feb 27, 2026
344d9b4
Make Claude runtime boundary Effect-native
juliusmarminge Feb 27, 2026
b03287e
Use typed errors for unavailable Claude runtime path
juliusmarminge Feb 27, 2026
fb1e7c1
unnecessary catch
juliusmarminge Feb 27, 2026
e45cd8f
Inline Claude adapter behavior into live layer
juliusmarminge Feb 27, 2026
8be8fcb
Use grouped provider/model select in chat composer
juliusmarminge Feb 27, 2026
600cfaf
Show provider logos in composer model trigger
juliusmarminge Feb 27, 2026
b6f93ea
Update Claude model catalog to latest 4.6/4.5 gen
juliusmarminge Feb 27, 2026
67eef99
Fix Claude model fallback in web store sync
juliusmarminge Feb 27, 2026
f00d414
Include all provider models in /model slash command
juliusmarminge Feb 27, 2026
e5f12e6
Integrate Claude agent SDK into server provider adapter
juliusmarminge Feb 27, 2026
6ff39f9
Refactor ClaudeCodeAdapter session flow and stream handling
juliusmarminge Feb 27, 2026
3e6ac44
Fix Claude resume cursor to only persist valid session UUIDs
juliusmarminge Feb 27, 2026
2113000
Align orchestration integration tests with latestTurn metadata
juliusmarminge Feb 27, 2026
8d23276
Ignore stale resume cursors and Claude placeholder thread IDs
juliusmarminge Feb 28, 2026
870096b
Fix ProviderService sendTurn recovery expectation after rebase
juliusmarminge Feb 28, 2026
02c89a5
Stabilize Claude turn event ordering and native event logging
juliusmarminge Feb 28, 2026
d75ca11
Align Claude permissions and provider-specific reasoning effort
juliusmarminge Feb 28, 2026
2c631e8
Track runtime event sequence and order thread activities by sequence
juliusmarminge Feb 28, 2026
f265f56
Add Cursor CLI stream event schemas and decoding tests
juliusmarminge Feb 27, 2026
87c797b
Add Cursor provider support across backend, contracts, and UI
juliusmarminge Feb 28, 2026
ebd44f9
Add Cursor ACP probe script and captured session logs
juliusmarminge Mar 1, 2026
5d42e4b
Revise Cursor provider plan for ACP JSON-RPC integration
juliusmarminge Mar 1, 2026
acd57a1
Document Cursor ACP mapping in canonical runtime event spec
juliusmarminge Mar 1, 2026
719c7dc
Introduce v2 provider runtime event schema and validation tests
juliusmarminge Mar 1, 2026
7ef6b20
Scope reasoning effort defaults and options by provider
juliusmarminge Mar 1, 2026
14865dc
Implement v2 canonical provider runtime adapters
cursoragent Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 49 additions & 46 deletions .plans/17-claude-code.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov

---

## Current constraints to design around
## Current constraints to design around (post-Stage 1)

1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.

Expand DownExpand Up@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:

This removes the implicit “Codex unless session already exists” behavior as the only path.

### 1.3 Provider session start input for Claude runtime knobs
### 1.3 Provider session start input for Claude runtime knobs (completed)

Update `packages/contracts/src/provider.ts`:

1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
2. Keep fields optional so current call sites remain valid.
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
1. Move provider-specific start fields into typed `providerOptions`:
- `providerOptions.codex`
- `providerOptions.claudeCode`
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
3. Deprecate/remove `resumeThreadId` from the generic start contract.
4. Treat `resumeCursor` as adapter-owned opaque state.

### 1.4 Contract tests
### 1.4 Contract tests (completed)

Update/add tests in `packages/contracts/src/*.test.ts` for:

1. New command payload shape.
2. Provider-aware model resolution behavior.
3. Backward compatibility of existing command/schema decoding.
3. Breaking-change expectations for removed top-level provider fields.

---

Expand All@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:

1. `cwd`
2. `model`
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
4. `permissionMode`
5. `maxThinkingTokens`
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
6. `resume`
7. `resumeSessionAt`
8. `includePartialMessages`
Expand All@@ -120,7 +123,7 @@ Required capabilities:
2. Multi-turn input queue.
3. Interrupt support.
4. Approval request/response bridge.
5. Resume support via `resumeThreadId` / `resumeCursor`.
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).

#### 2.2.a Agent SDK details to preserve

Expand All@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
2. Multi-turn input is supported via async-iterable prompt input.
3. Tool approval decisions are provided via `canUseTool`.
4. Resume support uses `resume` and optional `resumeSessionAt`.
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.

#### 2.2.b Effect-native session lifecycle skeleton
Expand All@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
Effect.acquireRelease(
Effect.tryPromise({
try: async () => {
const claudeOptions = input.providerOptions?.claudeCode;
const resumeState = readClaudeResumeState(input.resumeCursor);
const abortController = new AbortController();
const result = query({
prompt: makePromptAsyncIterable(input.sessionId),
prompt: makePromptAsyncIterable(),
options: {
cwd: input.cwd,
model: input.model,
permissionMode: input.permissionMode,
maxThinkingTokens: input.maxThinkingTokens,
pathToClaudeCodeExecutable: input.claudeBinaryPath,
resume: input.resumeThreadId,
resumeSessionAt: readResumeCursor(input.resumeCursor),
permissionMode: claudeOptions?.permissionMode,
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
resume: resumeState?.threadId,
resumeSessionAt: resumeState?.sessionAt,
signal: abortController.signal,
includePartialMessages: true,
canUseTool: makeCanUseTool(input.sessionId),
hooks: makeClaudeHooks(input.sessionId),
canUseTool: makeCanUseTool(),
hooks: makeClaudeHooks(),
},
});
return { abortController, result };
Expand DownExpand Up@@ -345,7 +350,8 @@ Define explicit adapter semantics:

1. `sessionId`: adapter-owned stable session id.
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.

### 2.5 Rollback/read strategy

Expand DownExpand Up@@ -402,11 +408,12 @@ Update integration tests to ensure:

## Phase 4: Orchestration command/reactor updates

### 4.1 Decider propagation
### 4.1 Decider propagation (completed)

Update `apps/server/src/orchestration/decider.ts`:

1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).

### 4.2 ProviderCommandReactor provider selection

Expand All@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
1. Prefer provider from turn-start event payload when starting a new session.
2. Fallback to existing thread session provider when payload omitted.
3. Fallback to default provider only when neither is present.
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).

Switch behavior policy (explicit in implementation):

Expand DownExpand Up@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter

## File checklist

Likely files to touch:

1. `packages/contracts/src/model.ts`
2. `packages/contracts/src/orchestration.ts`
3. `packages/contracts/src/provider.ts`
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
7. `apps/server/src/serverLayers.ts`
8. `apps/server/src/orchestration/decider.ts`
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
10. `apps/web/src/session-logic.ts`
11. `apps/web/src/components/ChatView.tsx`
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
Likely remaining files to touch:

1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
4. `apps/server/src/serverLayers.ts`
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
6. `apps/web/src/session-logic.ts`
7. `apps/web/src/components/ChatView.tsx`
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.

---

## Delivery order

1. Contracts for provider selection + models.
2. Claude adapter + unit tests.
3. Registry/layer wiring.
4. Reactor updates for provider-aware session start.
5. Web provider picker + provider-aware models.
6. Checkpoint/revert compatibility.
7. End-to-end integration tests and stabilization.
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
2. Registry/layer wiring.
3. Remaining reactor updates for provider-aware session selection/switching invariants.
4. Web provider picker + provider-aware models.
5. Checkpoint/revert compatibility.
6. End-to-end integration tests and stabilization.

This order keeps risk isolated and maintains a working orchestrated path at each stage.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
37eb492
Add provider-specific model resolution and defaults
juliusmarminge Feb 27, 2026
2ed16e5
redo contracts a bit
juliusmarminge Feb 27, 2026
310c763
revised plan
juliusmarminge Feb 27, 2026
f2e087c
Add Claude Code adapter live layer with error mapping tests
juliusmarminge Feb 27, 2026
b8e3b46
Wire Claude adapter into registry and server provider layer
juliusmarminge Feb 27, 2026
1fb3574
Support provider-aware session selection in reactor
juliusmarminge Feb 27, 2026
b8069d2
Enable Claude provider selection in chat composer
juliusmarminge Feb 27, 2026
fb62d21
Add Claude checkpoint and revert reactor coverage
juliusmarminge Feb 27, 2026
83b7200
Add Claude integration coverage across orchestration flows
juliusmarminge Feb 27, 2026
344d9b4
Make Claude runtime boundary Effect-native
juliusmarminge Feb 27, 2026
b03287e
Use typed errors for unavailable Claude runtime path
juliusmarminge Feb 27, 2026
fb1e7c1
unnecessary catch
juliusmarminge Feb 27, 2026
e45cd8f
Inline Claude adapter behavior into live layer
juliusmarminge Feb 27, 2026
8be8fcb
Use grouped provider/model select in chat composer
juliusmarminge Feb 27, 2026
600cfaf
Show provider logos in composer model trigger
juliusmarminge Feb 27, 2026
b6f93ea
Update Claude model catalog to latest 4.6/4.5 gen
juliusmarminge Feb 27, 2026
67eef99
Fix Claude model fallback in web store sync
juliusmarminge Feb 27, 2026
f00d414
Include all provider models in /model slash command
juliusmarminge Feb 27, 2026
e5f12e6
Integrate Claude agent SDK into server provider adapter
juliusmarminge Feb 27, 2026
6ff39f9
Refactor ClaudeCodeAdapter session flow and stream handling
juliusmarminge Feb 27, 2026
3e6ac44
Fix Claude resume cursor to only persist valid session UUIDs
juliusmarminge Feb 27, 2026
2113000
Align orchestration integration tests with latestTurn metadata
juliusmarminge Feb 27, 2026
8d23276
Ignore stale resume cursors and Claude placeholder thread IDs
juliusmarminge Feb 28, 2026
870096b
Fix ProviderService sendTurn recovery expectation after rebase
juliusmarminge Feb 28, 2026
02c89a5
Stabilize Claude turn event ordering and native event logging
juliusmarminge Feb 28, 2026
d75ca11
Align Claude permissions and provider-specific reasoning effort
juliusmarminge Feb 28, 2026
2c631e8
Track runtime event sequence and order thread activities by sequence
juliusmarminge Feb 28, 2026
f265f56
Add Cursor CLI stream event schemas and decoding tests
juliusmarminge Feb 27, 2026
87c797b
Add Cursor provider support across backend, contracts, and UI
juliusmarminge Feb 28, 2026
ebd44f9
Add Cursor ACP probe script and captured session logs
juliusmarminge Mar 1, 2026
5d42e4b
Revise Cursor provider plan for ACP JSON-RPC integration
juliusmarminge Mar 1, 2026
acd57a1
Document Cursor ACP mapping in canonical runtime event spec
juliusmarminge Mar 1, 2026
719c7dc
Introduce v2 provider runtime event schema and validation tests
juliusmarminge Mar 1, 2026
7ef6b20
Scope reasoning effort defaults and options by provider
juliusmarminge Mar 1, 2026
14865dc
Implement v2 canonical provider runtime adapters
cursoragent Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 49 additions & 46 deletions .plans/17-claude-code.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov

---

## Current constraints to design around
## Current constraints to design around (post-Stage 1)

1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.

Expand DownExpand Up@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:

This removes the implicit “Codex unless session already exists” behavior as the only path.

### 1.3 Provider session start input for Claude runtime knobs
### 1.3 Provider session start input for Claude runtime knobs (completed)

Update `packages/contracts/src/provider.ts`:

1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
2. Keep fields optional so current call sites remain valid.
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
1. Move provider-specific start fields into typed `providerOptions`:
- `providerOptions.codex`
- `providerOptions.claudeCode`
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
3. Deprecate/remove `resumeThreadId` from the generic start contract.
4. Treat `resumeCursor` as adapter-owned opaque state.

### 1.4 Contract tests
### 1.4 Contract tests (completed)

Update/add tests in `packages/contracts/src/*.test.ts` for:

1. New command payload shape.
2. Provider-aware model resolution behavior.
3. Backward compatibility of existing command/schema decoding.
3. Breaking-change expectations for removed top-level provider fields.

---

Expand All@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:

1. `cwd`
2. `model`
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
4. `permissionMode`
5. `maxThinkingTokens`
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
6. `resume`
7. `resumeSessionAt`
8. `includePartialMessages`
Expand All@@ -120,7 +123,7 @@ Required capabilities:
2. Multi-turn input queue.
3. Interrupt support.
4. Approval request/response bridge.
5. Resume support via `resumeThreadId` / `resumeCursor`.
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).

#### 2.2.a Agent SDK details to preserve

Expand All@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
2. Multi-turn input is supported via async-iterable prompt input.
3. Tool approval decisions are provided via `canUseTool`.
4. Resume support uses `resume` and optional `resumeSessionAt`.
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.

#### 2.2.b Effect-native session lifecycle skeleton
Expand All@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
Effect.acquireRelease(
Effect.tryPromise({
try: async () => {
const claudeOptions = input.providerOptions?.claudeCode;
const resumeState = readClaudeResumeState(input.resumeCursor);
const abortController = new AbortController();
const result = query({
prompt: makePromptAsyncIterable(input.sessionId),
prompt: makePromptAsyncIterable(),
options: {
cwd: input.cwd,
model: input.model,
permissionMode: input.permissionMode,
maxThinkingTokens: input.maxThinkingTokens,
pathToClaudeCodeExecutable: input.claudeBinaryPath,
resume: input.resumeThreadId,
resumeSessionAt: readResumeCursor(input.resumeCursor),
permissionMode: claudeOptions?.permissionMode,
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
resume: resumeState?.threadId,
resumeSessionAt: resumeState?.sessionAt,
signal: abortController.signal,
includePartialMessages: true,
canUseTool: makeCanUseTool(input.sessionId),
hooks: makeClaudeHooks(input.sessionId),
canUseTool: makeCanUseTool(),
hooks: makeClaudeHooks(),
},
});
return { abortController, result };
Expand DownExpand Up@@ -345,7 +350,8 @@ Define explicit adapter semantics:

1. `sessionId`: adapter-owned stable session id.
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.

### 2.5 Rollback/read strategy

Expand DownExpand Up@@ -402,11 +408,12 @@ Update integration tests to ensure:

## Phase 4: Orchestration command/reactor updates

### 4.1 Decider propagation
### 4.1 Decider propagation (completed)

Update `apps/server/src/orchestration/decider.ts`:

1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).

### 4.2 ProviderCommandReactor provider selection

Expand All@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
1. Prefer provider from turn-start event payload when starting a new session.
2. Fallback to existing thread session provider when payload omitted.
3. Fallback to default provider only when neither is present.
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).

Switch behavior policy (explicit in implementation):

Expand DownExpand Up@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter

## File checklist

Likely files to touch:

1. `packages/contracts/src/model.ts`
2. `packages/contracts/src/orchestration.ts`
3. `packages/contracts/src/provider.ts`
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
7. `apps/server/src/serverLayers.ts`
8. `apps/server/src/orchestration/decider.ts`
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
10. `apps/web/src/session-logic.ts`
11. `apps/web/src/components/ChatView.tsx`
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
Likely remaining files to touch:

1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
4. `apps/server/src/serverLayers.ts`
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
6. `apps/web/src/session-logic.ts`
7. `apps/web/src/components/ChatView.tsx`
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.

---

## Delivery order

1. Contracts for provider selection + models.
2. Claude adapter + unit tests.
3. Registry/layer wiring.
4. Reactor updates for provider-aware session start.
5. Web provider picker + provider-aware models.
6. Checkpoint/revert compatibility.
7. End-to-end integration tests and stabilization.
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
2. Registry/layer wiring.
3. Remaining reactor updates for provider-aware session selection/switching invariants.
4. Web provider picker + provider-aware models.
5. Checkpoint/revert compatibility.
6. End-to-end integration tests and stabilization.

This order keeps risk isolated and maintains a working orchestrated path at each stage.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
37eb492
Add provider-specific model resolution and defaults
juliusmarminge Feb 27, 2026
2ed16e5
redo contracts a bit
juliusmarminge Feb 27, 2026
310c763
revised plan
juliusmarminge Feb 27, 2026
f2e087c
Add Claude Code adapter live layer with error mapping tests
juliusmarminge Feb 27, 2026
b8e3b46
Wire Claude adapter into registry and server provider layer
juliusmarminge Feb 27, 2026
1fb3574
Support provider-aware session selection in reactor
juliusmarminge Feb 27, 2026
b8069d2
Enable Claude provider selection in chat composer
juliusmarminge Feb 27, 2026
fb62d21
Add Claude checkpoint and revert reactor coverage
juliusmarminge Feb 27, 2026
83b7200
Add Claude integration coverage across orchestration flows
juliusmarminge Feb 27, 2026
344d9b4
Make Claude runtime boundary Effect-native
juliusmarminge Feb 27, 2026
b03287e
Use typed errors for unavailable Claude runtime path
juliusmarminge Feb 27, 2026
fb1e7c1
unnecessary catch
juliusmarminge Feb 27, 2026
e45cd8f
Inline Claude adapter behavior into live layer
juliusmarminge Feb 27, 2026
8be8fcb
Use grouped provider/model select in chat composer
juliusmarminge Feb 27, 2026
600cfaf
Show provider logos in composer model trigger
juliusmarminge Feb 27, 2026
b6f93ea
Update Claude model catalog to latest 4.6/4.5 gen
juliusmarminge Feb 27, 2026
67eef99
Fix Claude model fallback in web store sync
juliusmarminge Feb 27, 2026
f00d414
Include all provider models in /model slash command
juliusmarminge Feb 27, 2026
e5f12e6
Integrate Claude agent SDK into server provider adapter
juliusmarminge Feb 27, 2026
6ff39f9
Refactor ClaudeCodeAdapter session flow and stream handling
juliusmarminge Feb 27, 2026
3e6ac44
Fix Claude resume cursor to only persist valid session UUIDs
juliusmarminge Feb 27, 2026
2113000
Align orchestration integration tests with latestTurn metadata
juliusmarminge Feb 27, 2026
8d23276
Ignore stale resume cursors and Claude placeholder thread IDs
juliusmarminge Feb 28, 2026
870096b
Fix ProviderService sendTurn recovery expectation after rebase
juliusmarminge Feb 28, 2026
02c89a5
Stabilize Claude turn event ordering and native event logging
juliusmarminge Feb 28, 2026
d75ca11
Align Claude permissions and provider-specific reasoning effort
juliusmarminge Feb 28, 2026
2c631e8
Track runtime event sequence and order thread activities by sequence
juliusmarminge Feb 28, 2026
f265f56
Add Cursor CLI stream event schemas and decoding tests
juliusmarminge Feb 27, 2026
87c797b
Add Cursor provider support across backend, contracts, and UI
juliusmarminge Feb 28, 2026
ebd44f9
Add Cursor ACP probe script and captured session logs
juliusmarminge Mar 1, 2026
5d42e4b
Revise Cursor provider plan for ACP JSON-RPC integration
juliusmarminge Mar 1, 2026
acd57a1
Document Cursor ACP mapping in canonical runtime event spec
juliusmarminge Mar 1, 2026
719c7dc
Introduce v2 provider runtime event schema and validation tests
juliusmarminge Mar 1, 2026
7ef6b20
Scope reasoning effort defaults and options by provider
juliusmarminge Mar 1, 2026
14865dc
Implement v2 canonical provider runtime adapters
cursoragent Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 49 additions & 46 deletions .plans/17-claude-code.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov

---

## Current constraints to design around
## Current constraints to design around (post-Stage 1)

1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.

Expand DownExpand Up@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:

This removes the implicit “Codex unless session already exists” behavior as the only path.

### 1.3 Provider session start input for Claude runtime knobs
### 1.3 Provider session start input for Claude runtime knobs (completed)

Update `packages/contracts/src/provider.ts`:

1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
2. Keep fields optional so current call sites remain valid.
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
1. Move provider-specific start fields into typed `providerOptions`:
- `providerOptions.codex`
- `providerOptions.claudeCode`
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
3. Deprecate/remove `resumeThreadId` from the generic start contract.
4. Treat `resumeCursor` as adapter-owned opaque state.

### 1.4 Contract tests
### 1.4 Contract tests (completed)

Update/add tests in `packages/contracts/src/*.test.ts` for:

1. New command payload shape.
2. Provider-aware model resolution behavior.
3. Backward compatibility of existing command/schema decoding.
3. Breaking-change expectations for removed top-level provider fields.

---

Expand All@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:

1. `cwd`
2. `model`
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
4. `permissionMode`
5. `maxThinkingTokens`
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
6. `resume`
7. `resumeSessionAt`
8. `includePartialMessages`
Expand All@@ -120,7 +123,7 @@ Required capabilities:
2. Multi-turn input queue.
3. Interrupt support.
4. Approval request/response bridge.
5. Resume support via `resumeThreadId` / `resumeCursor`.
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).

#### 2.2.a Agent SDK details to preserve

Expand All@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
2. Multi-turn input is supported via async-iterable prompt input.
3. Tool approval decisions are provided via `canUseTool`.
4. Resume support uses `resume` and optional `resumeSessionAt`.
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.

#### 2.2.b Effect-native session lifecycle skeleton
Expand All@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
Effect.acquireRelease(
Effect.tryPromise({
try: async () => {
const claudeOptions = input.providerOptions?.claudeCode;
const resumeState = readClaudeResumeState(input.resumeCursor);
const abortController = new AbortController();
const result = query({
prompt: makePromptAsyncIterable(input.sessionId),
prompt: makePromptAsyncIterable(),
options: {
cwd: input.cwd,
model: input.model,
permissionMode: input.permissionMode,
maxThinkingTokens: input.maxThinkingTokens,
pathToClaudeCodeExecutable: input.claudeBinaryPath,
resume: input.resumeThreadId,
resumeSessionAt: readResumeCursor(input.resumeCursor),
permissionMode: claudeOptions?.permissionMode,
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
resume: resumeState?.threadId,
resumeSessionAt: resumeState?.sessionAt,
signal: abortController.signal,
includePartialMessages: true,
canUseTool: makeCanUseTool(input.sessionId),
hooks: makeClaudeHooks(input.sessionId),
canUseTool: makeCanUseTool(),
hooks: makeClaudeHooks(),
},
});
return { abortController, result };
Expand DownExpand Up@@ -345,7 +350,8 @@ Define explicit adapter semantics:

1. `sessionId`: adapter-owned stable session id.
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.

### 2.5 Rollback/read strategy

Expand DownExpand Up@@ -402,11 +408,12 @@ Update integration tests to ensure:

## Phase 4: Orchestration command/reactor updates

### 4.1 Decider propagation
### 4.1 Decider propagation (completed)

Update `apps/server/src/orchestration/decider.ts`:

1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).

### 4.2 ProviderCommandReactor provider selection

Expand All@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
1. Prefer provider from turn-start event payload when starting a new session.
2. Fallback to existing thread session provider when payload omitted.
3. Fallback to default provider only when neither is present.
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).

Switch behavior policy (explicit in implementation):

Expand DownExpand Up@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter

## File checklist

Likely files to touch:

1. `packages/contracts/src/model.ts`
2. `packages/contracts/src/orchestration.ts`
3. `packages/contracts/src/provider.ts`
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
7. `apps/server/src/serverLayers.ts`
8. `apps/server/src/orchestration/decider.ts`
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
10. `apps/web/src/session-logic.ts`
11. `apps/web/src/components/ChatView.tsx`
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
Likely remaining files to touch:

1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
4. `apps/server/src/serverLayers.ts`
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
6. `apps/web/src/session-logic.ts`
7. `apps/web/src/components/ChatView.tsx`
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.

---

## Delivery order

1. Contracts for provider selection + models.
2. Claude adapter + unit tests.
3. Registry/layer wiring.
4. Reactor updates for provider-aware session start.
5. Web provider picker + provider-aware models.
6. Checkpoint/revert compatibility.
7. End-to-end integration tests and stabilization.
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
2. Registry/layer wiring.
3. Remaining reactor updates for provider-aware session selection/switching invariants.
4. Web provider picker + provider-aware models.
5. Checkpoint/revert compatibility.
6. End-to-end integration tests and stabilization.

This order keeps risk isolated and maintains a working orchestrated path at each stage.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
37eb492
Add provider-specific model resolution and defaults
juliusmarminge Feb 27, 2026
2ed16e5
redo contracts a bit
juliusmarminge Feb 27, 2026
310c763
revised plan
juliusmarminge Feb 27, 2026
f2e087c
Add Claude Code adapter live layer with error mapping tests
juliusmarminge Feb 27, 2026
b8e3b46
Wire Claude adapter into registry and server provider layer
juliusmarminge Feb 27, 2026
1fb3574
Support provider-aware session selection in reactor
juliusmarminge Feb 27, 2026
b8069d2
Enable Claude provider selection in chat composer
juliusmarminge Feb 27, 2026
fb62d21
Add Claude checkpoint and revert reactor coverage
juliusmarminge Feb 27, 2026
83b7200
Add Claude integration coverage across orchestration flows
juliusmarminge Feb 27, 2026
344d9b4
Make Claude runtime boundary Effect-native
juliusmarminge Feb 27, 2026
b03287e
Use typed errors for unavailable Claude runtime path
juliusmarminge Feb 27, 2026
fb1e7c1
unnecessary catch
juliusmarminge Feb 27, 2026
e45cd8f
Inline Claude adapter behavior into live layer
juliusmarminge Feb 27, 2026
8be8fcb
Use grouped provider/model select in chat composer
juliusmarminge Feb 27, 2026
600cfaf
Show provider logos in composer model trigger
juliusmarminge Feb 27, 2026
b6f93ea
Update Claude model catalog to latest 4.6/4.5 gen
juliusmarminge Feb 27, 2026
67eef99
Fix Claude model fallback in web store sync
juliusmarminge Feb 27, 2026
f00d414
Include all provider models in /model slash command
juliusmarminge Feb 27, 2026
e5f12e6
Integrate Claude agent SDK into server provider adapter
juliusmarminge Feb 27, 2026
6ff39f9
Refactor ClaudeCodeAdapter session flow and stream handling
juliusmarminge Feb 27, 2026
3e6ac44
Fix Claude resume cursor to only persist valid session UUIDs
juliusmarminge Feb 27, 2026
2113000
Align orchestration integration tests with latestTurn metadata
juliusmarminge Feb 27, 2026
8d23276
Ignore stale resume cursors and Claude placeholder thread IDs
juliusmarminge Feb 28, 2026
870096b
Fix ProviderService sendTurn recovery expectation after rebase
juliusmarminge Feb 28, 2026
02c89a5
Stabilize Claude turn event ordering and native event logging
juliusmarminge Feb 28, 2026
d75ca11
Align Claude permissions and provider-specific reasoning effort
juliusmarminge Feb 28, 2026
2c631e8
Track runtime event sequence and order thread activities by sequence
juliusmarminge Feb 28, 2026
f265f56
Add Cursor CLI stream event schemas and decoding tests
juliusmarminge Feb 27, 2026
87c797b
Add Cursor provider support across backend, contracts, and UI
juliusmarminge Feb 28, 2026
ebd44f9
Add Cursor ACP probe script and captured session logs
juliusmarminge Mar 1, 2026
5d42e4b
Revise Cursor provider plan for ACP JSON-RPC integration
juliusmarminge Mar 1, 2026
acd57a1
Document Cursor ACP mapping in canonical runtime event spec
juliusmarminge Mar 1, 2026
719c7dc
Introduce v2 provider runtime event schema and validation tests
juliusmarminge Mar 1, 2026
7ef6b20
Scope reasoning effort defaults and options by provider
juliusmarminge Mar 1, 2026
14865dc
Implement v2 canonical provider runtime adapters
cursoragent Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 49 additions & 46 deletions .plans/17-claude-code.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov

---

## Current constraints to design around
## Current constraints to design around (post-Stage 1)

1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.

Expand DownExpand Up@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:

This removes the implicit “Codex unless session already exists” behavior as the only path.

### 1.3 Provider session start input for Claude runtime knobs
### 1.3 Provider session start input for Claude runtime knobs (completed)

Update `packages/contracts/src/provider.ts`:

1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
2. Keep fields optional so current call sites remain valid.
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
1. Move provider-specific start fields into typed `providerOptions`:
- `providerOptions.codex`
- `providerOptions.claudeCode`
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
3. Deprecate/remove `resumeThreadId` from the generic start contract.
4. Treat `resumeCursor` as adapter-owned opaque state.

### 1.4 Contract tests
### 1.4 Contract tests (completed)

Update/add tests in `packages/contracts/src/*.test.ts` for:

1. New command payload shape.
2. Provider-aware model resolution behavior.
3. Backward compatibility of existing command/schema decoding.
3. Breaking-change expectations for removed top-level provider fields.

---

Expand All@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:

1. `cwd`
2. `model`
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
4. `permissionMode`
5. `maxThinkingTokens`
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
6. `resume`
7. `resumeSessionAt`
8. `includePartialMessages`
Expand All@@ -120,7 +123,7 @@ Required capabilities:
2. Multi-turn input queue.
3. Interrupt support.
4. Approval request/response bridge.
5. Resume support via `resumeThreadId` / `resumeCursor`.
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).

#### 2.2.a Agent SDK details to preserve

Expand All@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
2. Multi-turn input is supported via async-iterable prompt input.
3. Tool approval decisions are provided via `canUseTool`.
4. Resume support uses `resume` and optional `resumeSessionAt`.
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.

#### 2.2.b Effect-native session lifecycle skeleton
Expand All@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
Effect.acquireRelease(
Effect.tryPromise({
try: async () => {
const claudeOptions = input.providerOptions?.claudeCode;
const resumeState = readClaudeResumeState(input.resumeCursor);
const abortController = new AbortController();
const result = query({
prompt: makePromptAsyncIterable(input.sessionId),
prompt: makePromptAsyncIterable(),
options: {
cwd: input.cwd,
model: input.model,
permissionMode: input.permissionMode,
maxThinkingTokens: input.maxThinkingTokens,
pathToClaudeCodeExecutable: input.claudeBinaryPath,
resume: input.resumeThreadId,
resumeSessionAt: readResumeCursor(input.resumeCursor),
permissionMode: claudeOptions?.permissionMode,
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
resume: resumeState?.threadId,
resumeSessionAt: resumeState?.sessionAt,
signal: abortController.signal,
includePartialMessages: true,
canUseTool: makeCanUseTool(input.sessionId),
hooks: makeClaudeHooks(input.sessionId),
canUseTool: makeCanUseTool(),
hooks: makeClaudeHooks(),
},
});
return { abortController, result };
Expand DownExpand Up@@ -345,7 +350,8 @@ Define explicit adapter semantics:

1. `sessionId`: adapter-owned stable session id.
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.

### 2.5 Rollback/read strategy

Expand DownExpand Up@@ -402,11 +408,12 @@ Update integration tests to ensure:

## Phase 4: Orchestration command/reactor updates

### 4.1 Decider propagation
### 4.1 Decider propagation (completed)

Update `apps/server/src/orchestration/decider.ts`:

1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).

### 4.2 ProviderCommandReactor provider selection

Expand All@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
1. Prefer provider from turn-start event payload when starting a new session.
2. Fallback to existing thread session provider when payload omitted.
3. Fallback to default provider only when neither is present.
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).

Switch behavior policy (explicit in implementation):

Expand DownExpand Up@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter

## File checklist

Likely files to touch:

1. `packages/contracts/src/model.ts`
2. `packages/contracts/src/orchestration.ts`
3. `packages/contracts/src/provider.ts`
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
7. `apps/server/src/serverLayers.ts`
8. `apps/server/src/orchestration/decider.ts`
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
10. `apps/web/src/session-logic.ts`
11. `apps/web/src/components/ChatView.tsx`
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
Likely remaining files to touch:

1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
4. `apps/server/src/serverLayers.ts`
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
6. `apps/web/src/session-logic.ts`
7. `apps/web/src/components/ChatView.tsx`
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.

---

## Delivery order

1. Contracts for provider selection + models.
2. Claude adapter + unit tests.
3. Registry/layer wiring.
4. Reactor updates for provider-aware session start.
5. Web provider picker + provider-aware models.
6. Checkpoint/revert compatibility.
7. End-to-end integration tests and stabilization.
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
2. Registry/layer wiring.
3. Remaining reactor updates for provider-aware session selection/switching invariants.
4. Web provider picker + provider-aware models.
5. Checkpoint/revert compatibility.
6. End-to-end integration tests and stabilization.

This order keeps risk isolated and maintains a working orchestrated path at each stage.
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
37eb492
Add provider-specific model resolution and defaults
juliusmarminge Feb 27, 2026
2ed16e5
redo contracts a bit
juliusmarminge Feb 27, 2026
310c763
revised plan
juliusmarminge Feb 27, 2026
f2e087c
Add Claude Code adapter live layer with error mapping tests
juliusmarminge Feb 27, 2026
b8e3b46
Wire Claude adapter into registry and server provider layer
juliusmarminge Feb 27, 2026
1fb3574
Support provider-aware session selection in reactor
juliusmarminge Feb 27, 2026
b8069d2
Enable Claude provider selection in chat composer
juliusmarminge Feb 27, 2026
fb62d21
Add Claude checkpoint and revert reactor coverage
juliusmarminge Feb 27, 2026
83b7200
Add Claude integration coverage across orchestration flows
juliusmarminge Feb 27, 2026
344d9b4
Make Claude runtime boundary Effect-native
juliusmarminge Feb 27, 2026
b03287e
Use typed errors for unavailable Claude runtime path
juliusmarminge Feb 27, 2026
fb1e7c1
unnecessary catch
juliusmarminge Feb 27, 2026
e45cd8f
Inline Claude adapter behavior into live layer
juliusmarminge Feb 27, 2026
8be8fcb
Use grouped provider/model select in chat composer
juliusmarminge Feb 27, 2026
600cfaf
Show provider logos in composer model trigger
juliusmarminge Feb 27, 2026
b6f93ea
Update Claude model catalog to latest 4.6/4.5 gen
juliusmarminge Feb 27, 2026
67eef99
Fix Claude model fallback in web store sync
juliusmarminge Feb 27, 2026
f00d414
Include all provider models in /model slash command
juliusmarminge Feb 27, 2026
e5f12e6
Integrate Claude agent SDK into server provider adapter
juliusmarminge Feb 27, 2026
6ff39f9
Refactor ClaudeCodeAdapter session flow and stream handling
juliusmarminge Feb 27, 2026
3e6ac44
Fix Claude resume cursor to only persist valid session UUIDs
juliusmarminge Feb 27, 2026
2113000
Align orchestration integration tests with latestTurn metadata
juliusmarminge Feb 27, 2026
8d23276
Ignore stale resume cursors and Claude placeholder thread IDs
juliusmarminge Feb 28, 2026
870096b
Fix ProviderService sendTurn recovery expectation after rebase
juliusmarminge Feb 28, 2026
02c89a5
Stabilize Claude turn event ordering and native event logging
juliusmarminge Feb 28, 2026
d75ca11
Align Claude permissions and provider-specific reasoning effort
juliusmarminge Feb 28, 2026
2c631e8
Track runtime event sequence and order thread activities by sequence
juliusmarminge Feb 28, 2026
f265f56
Add Cursor CLI stream event schemas and decoding tests
juliusmarminge Feb 27, 2026
87c797b
Add Cursor provider support across backend, contracts, and UI
juliusmarminge Feb 28, 2026
ebd44f9
Add Cursor ACP probe script and captured session logs
juliusmarminge Mar 1, 2026
5d42e4b
Revise Cursor provider plan for ACP JSON-RPC integration
juliusmarminge Mar 1, 2026
acd57a1
Document Cursor ACP mapping in canonical runtime event spec
juliusmarminge Mar 1, 2026
719c7dc
Introduce v2 provider runtime event schema and validation tests
juliusmarminge Mar 1, 2026
7ef6b20
Scope reasoning effort defaults and options by provider
juliusmarminge Mar 1, 2026
14865dc
Implement v2 canonical provider runtime adapters
cursoragent Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 49 additions & 46 deletions .plans/17-claude-code.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov

---

## Current constraints to design around
## Current constraints to design around (post-Stage 1)

1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.

Expand DownExpand Up@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:

This removes the implicit “Codex unless session already exists” behavior as the only path.

### 1.3 Provider session start input for Claude runtime knobs
### 1.3 Provider session start input for Claude runtime knobs (completed)

Update `packages/contracts/src/provider.ts`:

1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
2. Keep fields optional so current call sites remain valid.
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
1. Move provider-specific start fields into typed `providerOptions`:
- `providerOptions.codex`
- `providerOptions.claudeCode`
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
3. Deprecate/remove `resumeThreadId` from the generic start contract.
4. Treat `resumeCursor` as adapter-owned opaque state.

### 1.4 Contract tests
### 1.4 Contract tests (completed)

Update/add tests in `packages/contracts/src/*.test.ts` for:

1. New command payload shape.
2. Provider-aware model resolution behavior.
3. Backward compatibility of existing command/schema decoding.
3. Breaking-change expectations for removed top-level provider fields.

---

Expand All@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:

1. `cwd`
2. `model`
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
4. `permissionMode`
5. `maxThinkingTokens`
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
6. `resume`
7. `resumeSessionAt`
8. `includePartialMessages`
Expand All@@ -120,7 +123,7 @@ Required capabilities:
2. Multi-turn input queue.
3. Interrupt support.
4. Approval request/response bridge.
5. Resume support via `resumeThreadId` / `resumeCursor`.
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).

#### 2.2.a Agent SDK details to preserve

Expand All@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
2. Multi-turn input is supported via async-iterable prompt input.
3. Tool approval decisions are provided via `canUseTool`.
4. Resume support uses `resume` and optional `resumeSessionAt`.
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.

#### 2.2.b Effect-native session lifecycle skeleton
Expand All@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
Effect.acquireRelease(
Effect.tryPromise({
try: async () => {
const claudeOptions = input.providerOptions?.claudeCode;
const resumeState = readClaudeResumeState(input.resumeCursor);
const abortController = new AbortController();
const result = query({
prompt: makePromptAsyncIterable(input.sessionId),
prompt: makePromptAsyncIterable(),
options: {
cwd: input.cwd,
model: input.model,
permissionMode: input.permissionMode,
maxThinkingTokens: input.maxThinkingTokens,
pathToClaudeCodeExecutable: input.claudeBinaryPath,
resume: input.resumeThreadId,
resumeSessionAt: readResumeCursor(input.resumeCursor),
permissionMode: claudeOptions?.permissionMode,
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
resume: resumeState?.threadId,
resumeSessionAt: resumeState?.sessionAt,
signal: abortController.signal,
includePartialMessages: true,
canUseTool: makeCanUseTool(input.sessionId),
hooks: makeClaudeHooks(input.sessionId),
canUseTool: makeCanUseTool(),
hooks: makeClaudeHooks(),
},
});
return { abortController, result };
Expand DownExpand Up@@ -345,7 +350,8 @@ Define explicit adapter semantics:

1. `sessionId`: adapter-owned stable session id.
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.

### 2.5 Rollback/read strategy

Expand DownExpand Up@@ -402,11 +408,12 @@ Update integration tests to ensure:

## Phase 4: Orchestration command/reactor updates

### 4.1 Decider propagation
### 4.1 Decider propagation (completed)

Update `apps/server/src/orchestration/decider.ts`:

1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).

### 4.2 ProviderCommandReactor provider selection

Expand All@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
1. Prefer provider from turn-start event payload when starting a new session.
2. Fallback to existing thread session provider when payload omitted.
3. Fallback to default provider only when neither is present.
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).

Switch behavior policy (explicit in implementation):

Expand DownExpand Up@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter

## File checklist

Likely files to touch:

1. `packages/contracts/src/model.ts`
2. `packages/contracts/src/orchestration.ts`
3. `packages/contracts/src/provider.ts`
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
7. `apps/server/src/serverLayers.ts`
8. `apps/server/src/orchestration/decider.ts`
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
10. `apps/web/src/session-logic.ts`
11. `apps/web/src/components/ChatView.tsx`
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
Likely remaining files to touch:

1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
4. `apps/server/src/serverLayers.ts`
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
6. `apps/web/src/session-logic.ts`
7. `apps/web/src/components/ChatView.tsx`
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.

---

## Delivery order

1. Contracts for provider selection + models.
2. Claude adapter + unit tests.
3. Registry/layer wiring.
4. Reactor updates for provider-aware session start.
5. Web provider picker + provider-aware models.
6. Checkpoint/revert compatibility.
7. End-to-end integration tests and stabilization.
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
2. Registry/layer wiring.
3. Remaining reactor updates for provider-aware session selection/switching invariants.
4. Web provider picker + provider-aware models.
5. Checkpoint/revert compatibility.
6. End-to-end integration tests and stabilization.

This order keeps risk isolated and maintains a working orchestrated path at each stage.
Loading