| ... | @@ -87,13 +87,20 @@ describe("ProviderCommandReactor", () => { | ... | @@ -87,13 +87,20 @@ describe("ProviderCommandReactor", () => { |
| 87 | const runtimeSessions: Array<ProviderSession> = []; | 87 | const runtimeSessions: Array<ProviderSession> = []; |
| 88 | const startSession = vi.fn((_: unknown, input: unknown) => { | 88 | const startSession = vi.fn((_: unknown, input: unknown) => { |
| 89 | const sessionIndex = nextSessionIndex++; | 89 | const sessionIndex = nextSessionIndex++; |
| | 90 | const provider = |
| | 91 | typeof input === "object" && |
| | 92 | input !== null && |
| | 93 | "provider" in input && |
| | 94 | (input.provider === "codex" || input.provider === "claudeCode") |
| | 95 | ? input.provider |
| | 96 | : "codex"; |
| 90 | const resumeCursor = | 97 | const resumeCursor = |
| 91 | typeof input === "object" && input !== null && "resumeCursor" in input | 98 | typeof input === "object" && input !== null && "resumeCursor" in input |
| 92 | ? input.resumeCursor | 99 | ? input.resumeCursor |
| 93 | : undefined; | 100 | : undefined; |
| 94 | const session: ProviderSession = { | 101 | const session: ProviderSession = { |
| 95 | sessionId: asSessionId(`sess-${sessionIndex}`), | 102 | sessionId: asSessionId(`sess-${sessionIndex}`), |
| 96 | provider: "codex" as const, | 103 | provider, |
| 97 | status: "ready" as const, | 104 | status: "ready" as const, |
| 98 | threadId: ProviderThreadId.makeUnsafe(`provider-thread-${sessionIndex}`), | 105 | threadId: ProviderThreadId.makeUnsafe(`provider-thread-${sessionIndex}`), |
| 99 | resumeCursor: resumeCursor ?? { opaque: `cursor-${sessionIndex}` }, | 106 | resumeCursor: resumeCursor ?? { opaque: `cursor-${sessionIndex}` }, |
| ... | @@ -240,165 +247,55 @@ describe("ProviderCommandReactor", () => { | ... | @@ -240,165 +247,55 @@ describe("ProviderCommandReactor", () => { |
| 240 | expect(thread?.session?.sandboxMode).toBe("workspace-write"); | 247 | expect(thread?.session?.sandboxMode).toBe("workspace-write"); |
| 241 | }); | 248 | }); |
| 242 | | 249 | |
| 243 | it("generates and renames temporary worktree branch on first turn", async () => { | 250 | it("starts first turn with requested provider when provider is specified", async () => { |
| 244 | const harness = await createHarness(); | 251 | const harness = await createHarness(); |
| 245 | const now = new Date().toISOString(); | 252 | const now = new Date().toISOString(); |
| 246 | | 253 | |
| 247 | await Effect.runPromise( | | |
| 248 | harness.engine.dispatch({ | | |
| 249 | type: "thread.meta.update", | | |
| 250 | commandId: CommandId.makeUnsafe("cmd-thread-meta-set-temp-branch"), | | |
| 251 | threadId: ThreadId.makeUnsafe("thread-1"), | | |
| 252 | branch: "t3code/89abc123", | | |
| 253 | worktreePath: "/tmp/provider-project/.t3/worktrees/t3code-89abc123", | | |
| 254 | }), | | |
| 255 | ); | | |
| 256 | | | |
| 257 | await Effect.runPromise( | | |
| 258 | harness.engine.dispatch({ | | |
| 259 | type: "thread.turn.start", | | |
| 260 | commandId: CommandId.makeUnsafe("cmd-turn-start-worktree-rename"), | | |
| 261 | threadId: ThreadId.makeUnsafe("thread-1"), | | |
| 262 | message: { | | |
| 263 | messageId: asMessageId("user-message-worktree-rename"), | | |
| 264 | role: "user", | | |
| 265 | text: "Fix visual bug from screenshot", | | |
| 266 | attachments: [ | | |
| 267 | { | | |
| 268 | type: "image", | | |
| 269 | id: "thread-1-att-rename", | | |
| 270 | name: "bug.png", | | |
| 271 | mimeType: "image/png", | | |
| 272 | sizeBytes: 5, | | |
| 273 | }, | | |
| 274 | ], | | |
| 275 | }, | | |
| 276 | approvalPolicy: "on-request", | | |
| 277 | sandboxMode: "workspace-write", | | |
| 278 | createdAt: now, | | |
| 279 | }), | | |
| 280 | ); | | |
| 281 | | | |
| 282 | await waitFor(() => harness.generateBranchName.mock.calls.length === 1); | | |
| 283 | await waitFor(() => harness.renameBranch.mock.calls.length === 1); | | |
| 284 | | | |
| 285 | expect(harness.generateBranchName.mock.calls[0]?.[0]).toEqual({ | | |
| 286 | cwd: "/tmp/provider-project/.t3/worktrees/t3code-89abc123", | | |
| 287 | message: "Fix visual bug from screenshot", | | |
| 288 | attachments: [ | | |
| 289 | { | | |
| 290 | type: "image", | | |
| 291 | id: "thread-1-att-rename", | | |
| 292 | name: "bug.png", | | |
| 293 | mimeType: "image/png", | | |
| 294 | sizeBytes: 5, | | |
| 295 | }, | | |
| 296 | ], | | |
| 297 | }); | | |
| 298 | expect(harness.renameBranch.mock.calls[0]?.[0]).toEqual({ | | |
| 299 | cwd: "/tmp/provider-project/.t3/worktrees/t3code-89abc123", | | |
| 300 | oldBranch: "t3code/89abc123", | | |
| 301 | newBranch: "t3code/generated-name", | | |
| 302 | }); | | |
| 303 | | | |
| 304 | await waitFor(() => { | | |
| 305 | const readModel = Effect.runSync(harness.engine.getReadModel()); | | |
| 306 | const thread = readModel.threads.find( | | |
| 307 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | | |
| 308 | ); | | |
| 309 | return thread?.branch === "t3code/generated-name"; | | |
| 310 | }); | | |
| 311 | }); | | |
| 312 | | | |
| 313 | it("passes persisted attachment references to branch generation and turn start", async () => { | | |
| 314 | const harness = await createHarness(); | | |
| 315 | const now = new Date().toISOString(); | | |
| 316 | | | |
| 317 | await Effect.runPromise( | | |
| 318 | harness.engine.dispatch({ | | |
| 319 | type: "thread.meta.update", | | |
| 320 | commandId: CommandId.makeUnsafe("cmd-thread-meta-set-temp-branch-persisted"), | | |
| 321 | threadId: ThreadId.makeUnsafe("thread-1"), | | |
| 322 | branch: "t3code/abcdef12", | | |
| 323 | worktreePath: "/tmp/provider-project/.t3/worktrees/t3code-abcdef12", | | |
| 324 | }), | | |
| 325 | ); | | |
| 326 | | | |
| 327 | await Effect.runPromise( | 254 | await Effect.runPromise( |
| 328 | harness.engine.dispatch({ | 255 | harness.engine.dispatch({ |
| 329 | type: "thread.turn.start", | 256 | type: "thread.turn.start", |
| 330 | commandId: CommandId.makeUnsafe("cmd-turn-start-persisted-attachments"), | 257 | commandId: CommandId.makeUnsafe("cmd-turn-start-provider-first"), |
| 331 | threadId: ThreadId.makeUnsafe("thread-1"), | 258 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 332 | message: { | 259 | message: { |
| 333 | messageId: asMessageId("user-message-persisted-attachments"), | 260 | messageId: asMessageId("user-message-provider-first"), |
| 334 | role: "user", | 261 | role: "user", |
| 335 | text: "Fix visual bug from screenshot", | 262 | text: "hello claude", |
| 336 | attachments: [ | 263 | attachments: [], |
| 337 | { | | |
| 338 | type: "image", | | |
| 339 | id: "thread-1-att-persisted", | | |
| 340 | name: "bug.png", | | |
| 341 | mimeType: "image/png", | | |
| 342 | sizeBytes: 5, | | |
| 343 | }, | | |
| 344 | ], | | |
| 345 | }, | 264 | }, |
| | 265 | provider: "claudeCode", |
| 346 | approvalPolicy: "on-request", | 266 | approvalPolicy: "on-request", |
| 347 | sandboxMode: "workspace-write", | 267 | sandboxMode: "workspace-write", |
| 348 | createdAt: now, | 268 | createdAt: now, |
| 349 | }), | 269 | }), |
| 350 | ); | 270 | ); |
| 351 | | 271 | |
| 352 | await waitFor(() => harness.generateBranchName.mock.calls.length === 1); | 272 | await waitFor(() => harness.startSession.mock.calls.length === 1); |
| 353 | await waitFor(() => harness.sendTurn.mock.calls.length === 1); | 273 | await waitFor(() => harness.sendTurn.mock.calls.length === 1); |
| 354 | | 274 | expect(harness.startSession.mock.calls[0]?.[1]).toMatchObject({ |
| 355 | expect(harness.generateBranchName.mock.calls[0]?.[0]).toEqual({ | 275 | provider: "claudeCode", |
| 356 | cwd: "/tmp/provider-project/.t3/worktrees/t3code-abcdef12", | 276 | cwd: "/tmp/provider-project", |
| 357 | message: "Fix visual bug from screenshot", | 277 | model: "gpt-5-codex", |
| 358 | attachments: [ | 278 | approvalPolicy: "on-request", |
| 359 | { | 279 | sandboxMode: "workspace-write", |
| 360 | type: "image", | | |
| 361 | id: "thread-1-att-persisted", | | |
| 362 | name: "bug.png", | | |
| 363 | mimeType: "image/png", | | |
| 364 | sizeBytes: 5, | | |
| 365 | }, | | |
| 366 | ], | | |
| 367 | }); | | |
| 368 | expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({ | | |
| 369 | attachments: [ | | |
| 370 | { | | |
| 371 | type: "image", | | |
| 372 | id: "thread-1-att-persisted", | | |
| 373 | name: "bug.png", | | |
| 374 | mimeType: "image/png", | | |
| 375 | sizeBytes: 5, | | |
| 376 | }, | | |
| 377 | ], | | |
| 378 | }); | 280 | }); |
| | 281 | |
| | 282 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| | 283 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); |
| | 284 | expect(thread?.session?.providerName).toBe("claudeCode"); |
| | 285 | expect(thread?.session?.providerSessionId).toBe("sess-1"); |
| 379 | }); | 286 | }); |
| 380 | | 287 | |
| 381 | it("skips worktree branch generation after the first user turn", async () => { | 288 | it("reuses the same provider session when runtime mode is unchanged", async () => { |
| 382 | const harness = await createHarness(); | 289 | const harness = await createHarness(); |
| 383 | const now = new Date().toISOString(); | 290 | const now = new Date().toISOString(); |
| 384 | | 291 | |
| 385 | await Effect.runPromise( | | |
| 386 | harness.engine.dispatch({ | | |
| 387 | type: "thread.meta.update", | | |
| 388 | commandId: CommandId.makeUnsafe("cmd-thread-meta-set-temp-branch-2"), | | |
| 389 | threadId: ThreadId.makeUnsafe("thread-1"), | | |
| 390 | branch: "t3code/1234abcd", | | |
| 391 | worktreePath: "/tmp/provider-project/.t3/worktrees/t3code-1234abcd", | | |
| 392 | }), | | |
| 393 | ); | | |
| 394 | | | |
| 395 | await Effect.runPromise( | 292 | await Effect.runPromise( |
| 396 | harness.engine.dispatch({ | 293 | harness.engine.dispatch({ |
| 397 | type: "thread.turn.start", | 294 | type: "thread.turn.start", |
| 398 | commandId: CommandId.makeUnsafe("cmd-turn-start-first"), | 295 | commandId: CommandId.makeUnsafe("cmd-turn-start-unchanged-1"), |
| 399 | threadId: ThreadId.makeUnsafe("thread-1"), | 296 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 400 | message: { | 297 | message: { |
| 401 | messageId: asMessageId("user-message-first"), | 298 | messageId: asMessageId("user-message-unchanged-1"), |
| 402 | role: "user", | 299 | role: "user", |
| 403 | text: "first", | 300 | text: "first", |
| 404 | attachments: [], | 301 | attachments: [], |
| ... | @@ -409,15 +306,16 @@ describe("ProviderCommandReactor", () => { | ... | @@ -409,15 +306,16 @@ describe("ProviderCommandReactor", () => { |
| 409 | }), | 306 | }), |
| 410 | ); | 307 | ); |
| 411 | | 308 | |
| 412 | await waitFor(() => harness.generateBranchName.mock.calls.length === 1); | 309 | await waitFor(() => harness.startSession.mock.calls.length === 1); |
| | 310 | await waitFor(() => harness.sendTurn.mock.calls.length === 1); |
| 413 | | 311 | |
| 414 | await Effect.runPromise( | 312 | await Effect.runPromise( |
| 415 | harness.engine.dispatch({ | 313 | harness.engine.dispatch({ |
| 416 | type: "thread.turn.start", | 314 | type: "thread.turn.start", |
| 417 | commandId: CommandId.makeUnsafe("cmd-turn-start-second"), | 315 | commandId: CommandId.makeUnsafe("cmd-turn-start-unchanged-2"), |
| 418 | threadId: ThreadId.makeUnsafe("thread-1"), | 316 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 419 | message: { | 317 | message: { |
| 420 | messageId: asMessageId("user-message-second"), | 318 | messageId: asMessageId("user-message-unchanged-2"), |
| 421 | role: "user", | 319 | role: "user", |
| 422 | text: "second", | 320 | text: "second", |
| 423 | attachments: [], | 321 | attachments: [], |
| ... | @@ -429,75 +327,27 @@ describe("ProviderCommandReactor", () => { | ... | @@ -429,75 +327,27 @@ describe("ProviderCommandReactor", () => { |
| 429 | ); | 327 | ); |
| 430 | | 328 | |
| 431 | await waitFor(() => harness.sendTurn.mock.calls.length === 2); | 329 | await waitFor(() => harness.sendTurn.mock.calls.length === 2); |
| 432 | expect(harness.generateBranchName.mock.calls.length).toBe(1); | 330 | expect(harness.startSession.mock.calls.length).toBe(1); |
| 433 | expect(harness.renameBranch.mock.calls.length).toBe(1); | 331 | expect(harness.stopSession.mock.calls.length).toBe(0); |
| 434 | }); | | |
| 435 | | | |
| 436 | it("skips worktree rename when branch-name generation fails", async () => { | | |
| 437 | const harness = await createHarness(); | | |
| 438 | const now = new Date().toISOString(); | | |
| 439 | harness.generateBranchName.mockImplementationOnce(() => | | |
| 440 | Effect.fail( | | |
| 441 | new TextGenerationError({ | | |
| 442 | operation: "generateBranchName", | | |
| 443 | detail: "model returned invalid payload", | | |
| 444 | }), | | |
| 445 | ), | | |
| 446 | ); | | |
| 447 | | | |
| 448 | await Effect.runPromise( | | |
| 449 | harness.engine.dispatch({ | | |
| 450 | type: "thread.meta.update", | | |
| 451 | commandId: CommandId.makeUnsafe("cmd-thread-meta-set-temp-branch-null"), | | |
| 452 | threadId: ThreadId.makeUnsafe("thread-1"), | | |
| 453 | branch: "t3code/0000abcd", | | |
| 454 | worktreePath: "/tmp/provider-project/.t3/worktrees/t3code-0000abcd", | | |
| 455 | }), | | |
| 456 | ); | | |
| 457 | | | |
| 458 | await Effect.runPromise( | | |
| 459 | harness.engine.dispatch({ | | |
| 460 | type: "thread.turn.start", | | |
| 461 | commandId: CommandId.makeUnsafe("cmd-turn-start-null-branch"), | | |
| 462 | threadId: ThreadId.makeUnsafe("thread-1"), | | |
| 463 | message: { | | |
| 464 | messageId: asMessageId("user-message-null-branch"), | | |
| 465 | role: "user", | | |
| 466 | text: "Fix visual regression", | | |
| 467 | attachments: [], | | |
| 468 | }, | | |
| 469 | approvalPolicy: "on-request", | | |
| 470 | sandboxMode: "workspace-write", | | |
| 471 | createdAt: now, | | |
| 472 | }), | | |
| 473 | ); | | |
| 474 | | | |
| 475 | await waitFor(() => harness.generateBranchName.mock.calls.length === 1); | | |
| 476 | await Effect.runPromise(Effect.sleep("20 millis")); | | |
| 477 | expect(harness.renameBranch.mock.calls.length).toBe(0); | | |
| 478 | | | |
| 479 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); | | |
| 480 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | | |
| 481 | expect(thread?.branch).toBe("t3code/0000abcd"); | | |
| 482 | }); | 332 | }); |
| 483 | | 333 | |
| 484 | it("reuses the same provider session when runtime mode is unchanged", async () => { | 334 | it("restarts the provider session when runtime mode changes", async () => { |
| 485 | const harness = await createHarness(); | 335 | const harness = await createHarness(); |
| 486 | const now = new Date().toISOString(); | 336 | const now = new Date().toISOString(); |
| 487 | | 337 | |
| 488 | await Effect.runPromise( | 338 | await Effect.runPromise( |
| 489 | harness.engine.dispatch({ | 339 | harness.engine.dispatch({ |
| 490 | type: "thread.turn.start", | 340 | type: "thread.turn.start", |
| 491 | commandId: CommandId.makeUnsafe("cmd-turn-start-unchanged-1"), | 341 | commandId: CommandId.makeUnsafe("cmd-turn-start-runtime-mode-1"), |
| 492 | threadId: ThreadId.makeUnsafe("thread-1"), | 342 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 493 | message: { | 343 | message: { |
| 494 | messageId: asMessageId("user-message-unchanged-1"), | 344 | messageId: asMessageId("user-message-runtime-mode-1"), |
| 495 | role: "user", | 345 | role: "user", |
| 496 | text: "first", | 346 | text: "first", |
| 497 | attachments: [], | 347 | attachments: [], |
| 498 | }, | 348 | }, |
| 499 | approvalPolicy: "on-request", | 349 | approvalPolicy: "never", |
| 500 | sandboxMode: "workspace-write", | 350 | sandboxMode: "danger-full-access", |
| 501 | createdAt: now, | 351 | createdAt: now, |
| 502 | }), | 352 | }), |
| 503 | ); | 353 | ); |
| ... | @@ -508,10 +358,10 @@ describe("ProviderCommandReactor", () => { | ... | @@ -508,10 +358,10 @@ describe("ProviderCommandReactor", () => { |
| 508 | await Effect.runPromise( | 358 | await Effect.runPromise( |
| 509 | harness.engine.dispatch({ | 359 | harness.engine.dispatch({ |
| 510 | type: "thread.turn.start", | 360 | type: "thread.turn.start", |
| 511 | commandId: CommandId.makeUnsafe("cmd-turn-start-unchanged-2"), | 361 | commandId: CommandId.makeUnsafe("cmd-turn-start-runtime-mode-2"), |
| 512 | threadId: ThreadId.makeUnsafe("thread-1"), | 362 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 513 | message: { | 363 | message: { |
| 514 | messageId: asMessageId("user-message-unchanged-2"), | 364 | messageId: asMessageId("user-message-runtime-mode-2"), |
| 515 | role: "user", | 365 | role: "user", |
| 516 | text: "second", | 366 | text: "second", |
| 517 | attachments: [], | 367 | attachments: [], |
| ... | @@ -522,28 +372,44 @@ describe("ProviderCommandReactor", () => { | ... | @@ -522,28 +372,44 @@ describe("ProviderCommandReactor", () => { |
| 522 | }), | 372 | }), |
| 523 | ); | 373 | ); |
| 524 | | 374 | |
| | 375 | await waitFor(() => harness.stopSession.mock.calls.length === 1); |
| | 376 | await waitFor(() => harness.startSession.mock.calls.length === 2); |
| 525 | await waitFor(() => harness.sendTurn.mock.calls.length === 2); | 377 | await waitFor(() => harness.sendTurn.mock.calls.length === 2); |
| 526 | expect(harness.startSession.mock.calls.length).toBe(1); | 378 | |
| 527 | expect(harness.stopSession.mock.calls.length).toBe(0); | 379 | expect(harness.stopSession.mock.calls[0]?.[0]).toEqual({ sessionId: asSessionId("sess-1") }); |
| | 380 | expect(harness.startSession.mock.calls[1]?.[1]).toMatchObject({ |
| | 381 | resumeCursor: { opaque: "cursor-1" }, |
| | 382 | approvalPolicy: "on-request", |
| | 383 | sandboxMode: "workspace-write", |
| | 384 | }); |
| | 385 | expect(harness.sendTurn.mock.calls[1]?.[0]).toMatchObject({ |
| | 386 | sessionId: asSessionId("sess-2"), |
| | 387 | }); |
| | 388 | |
| | 389 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| | 390 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); |
| | 391 | expect(thread?.session?.providerSessionId).toBe("sess-2"); |
| | 392 | expect(thread?.session?.approvalPolicy).toBe("on-request"); |
| | 393 | expect(thread?.session?.sandboxMode).toBe("workspace-write"); |
| 528 | }); | 394 | }); |
| 529 | | 395 | |
| 530 | it("restarts the provider session when runtime mode changes", async () => { | 396 | it("switches provider by restarting the session when turn request provider changes", async () => { |
| 531 | const harness = await createHarness(); | 397 | const harness = await createHarness(); |
| 532 | const now = new Date().toISOString(); | 398 | const now = new Date().toISOString(); |
| 533 | | 399 | |
| 534 | await Effect.runPromise( | 400 | await Effect.runPromise( |
| 535 | harness.engine.dispatch({ | 401 | harness.engine.dispatch({ |
| 536 | type: "thread.turn.start", | 402 | type: "thread.turn.start", |
| 537 | commandId: CommandId.makeUnsafe("cmd-turn-start-runtime-mode-1"), | 403 | commandId: CommandId.makeUnsafe("cmd-turn-start-provider-switch-1"), |
| 538 | threadId: ThreadId.makeUnsafe("thread-1"), | 404 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 539 | message: { | 405 | message: { |
| 540 | messageId: asMessageId("user-message-runtime-mode-1"), | 406 | messageId: asMessageId("user-message-provider-switch-1"), |
| 541 | role: "user", | 407 | role: "user", |
| 542 | text: "first", | 408 | text: "first", |
| 543 | attachments: [], | 409 | attachments: [], |
| 544 | }, | 410 | }, |
| 545 | approvalPolicy: "never", | 411 | approvalPolicy: "on-request", |
| 546 | sandboxMode: "danger-full-access", | 412 | sandboxMode: "workspace-write", |
| 547 | createdAt: now, | 413 | createdAt: now, |
| 548 | }), | 414 | }), |
| 549 | ); | 415 | ); |
| ... | @@ -554,14 +420,15 @@ describe("ProviderCommandReactor", () => { | ... | @@ -554,14 +420,15 @@ describe("ProviderCommandReactor", () => { |
| 554 | await Effect.runPromise( | 420 | await Effect.runPromise( |
| 555 | harness.engine.dispatch({ | 421 | harness.engine.dispatch({ |
| 556 | type: "thread.turn.start", | 422 | type: "thread.turn.start", |
| 557 | commandId: CommandId.makeUnsafe("cmd-turn-start-runtime-mode-2"), | 423 | commandId: CommandId.makeUnsafe("cmd-turn-start-provider-switch-2"), |
| 558 | threadId: ThreadId.makeUnsafe("thread-1"), | 424 | threadId: ThreadId.makeUnsafe("thread-1"), |
| 559 | message: { | 425 | message: { |
| 560 | messageId: asMessageId("user-message-runtime-mode-2"), | 426 | messageId: asMessageId("user-message-provider-switch-2"), |
| 561 | role: "user", | 427 | role: "user", |
| 562 | text: "second", | 428 | text: "second", |
| 563 | attachments: [], | 429 | attachments: [], |
| 564 | }, | 430 | }, |
| | 431 | provider: "claudeCode", |
| 565 | approvalPolicy: "on-request", | 432 | approvalPolicy: "on-request", |
| 566 | sandboxMode: "workspace-write", | 433 | sandboxMode: "workspace-write", |
| 567 | createdAt: now, | 434 | createdAt: now, |
| ... | @@ -574,17 +441,16 @@ describe("ProviderCommandReactor", () => { | ... | @@ -574,17 +441,16 @@ describe("ProviderCommandReactor", () => { |
| 574 | | 441 | |
| 575 | expect(harness.stopSession.mock.calls[0]?.[0]).toEqual({ sessionId: asSessionId("sess-1") }); | 442 | expect(harness.stopSession.mock.calls[0]?.[0]).toEqual({ sessionId: asSessionId("sess-1") }); |
| 576 | expect(harness.startSession.mock.calls[1]?.[1]).toMatchObject({ | 443 | expect(harness.startSession.mock.calls[1]?.[1]).toMatchObject({ |
| | 444 | provider: "claudeCode", |
| 577 | resumeCursor: { opaque: "cursor-1" }, | 445 | resumeCursor: { opaque: "cursor-1" }, |
| 578 | approvalPolicy: "on-request", | 446 | approvalPolicy: "on-request", |
| 579 | sandboxMode: "workspace-write", | 447 | sandboxMode: "workspace-write", |
| 580 | }); | 448 | }); |
| 581 | expect(harness.sendTurn.mock.calls[1]?.[0]).toMatchObject({ | | |
| 582 | sessionId: asSessionId("sess-2"), | | |
| 583 | }); | | |
| 584 | | 449 | |
| 585 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); | 450 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 586 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | 451 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); |
| 587 | expect(thread?.session?.providerSessionId).toBe("sess-2"); | 452 | expect(thread?.session?.providerSessionId).toBe("sess-2"); |
| | 453 | expect(thread?.session?.providerName).toBe("claudeCode"); |
| 588 | expect(thread?.session?.approvalPolicy).toBe("on-request"); | 454 | expect(thread?.session?.approvalPolicy).toBe("on-request"); |
| 589 | expect(thread?.session?.sandboxMode).toBe("workspace-write"); | 455 | expect(thread?.session?.sandboxMode).toBe("workspace-write"); |
| 590 | }); | 456 | }); |