| ... | ... | @@ -3355,6 +3355,74 @@ describe("ClaudeAdapterV2 background wake turns", () => { |
| 3355 | 3355 | ), |
| 3356 | 3356 | ); |
| 3357 | 3357 | |
| 3358 | it.effect("keeps the measured context when a usage limit ends the turn", () => |
| 3359 | Effect.gen(function* () { |
| 3360 | const harness = yield* makeWakeHarness; |
| 3361 | yield* harness.runtime.startTurn( |
| 3362 | makeClaudeTestTurnInput({ |
| 3363 | threadId: harness.threadId, |
| 3364 | providerThread: harness.providerThread, |
| 3365 | now: yield* DateTime.now, |
| 3366 | attemptId: RunAttemptId.make("attempt-limit-context"), |
| 3367 | text: "Continue.", |
| 3368 | attachments: [], |
| 3369 | }), |
| 3370 | ); |
| 3371 | yield* Queue.offer( |
| 3372 | harness.sdkMessages, |
| 3373 | makeAssistantTextFrame({ uuid: "00000000-0000-4000-8000-000000000660", text: "Working." }), |
| 3374 | ); |
| 3375 | // The CLI answers a 429 with a locally generated frame that reports no usage. |
| 3376 | yield* Queue.offer( |
| 3377 | harness.sdkMessages, |
| 3378 | claudeSdkFrame({ |
| 3379 | type: "assistant", |
| 3380 | message: { |
| 3381 | model: "<synthetic>", |
| 3382 | id: "00000000-0000-4000-8000-000000000661", |
| 3383 | type: "message", |
| 3384 | role: "assistant", |
| 3385 | content: [{ type: "text", text: "You've hit your session limit" }], |
| 3386 | stop_reason: "stop_sequence", |
| 3387 | stop_sequence: "", |
| 3388 | usage: { |
| 3389 | input_tokens: 0, |
| 3390 | output_tokens: 0, |
| 3391 | cache_creation_input_tokens: 0, |
| 3392 | cache_read_input_tokens: 0, |
| 3393 | }, |
| 3394 | }, |
| 3395 | parent_tool_use_id: null, |
| 3396 | error: "rate_limit", |
| 3397 | uuid: "00000000-0000-4000-8000-000000000661", |
| 3398 | session_id: WAKE_NATIVE_SESSION, |
| 3399 | }), |
| 3400 | ); |
| 3401 | yield* Queue.offer( |
| 3402 | harness.sdkMessages, |
| 3403 | makeResultFrame({ |
| 3404 | uuid: "00000000-0000-4000-8000-000000000662", |
| 3405 | result: "You've hit your session limit", |
| 3406 | terminalReason: "api_error", |
| 3407 | isError: true, |
| 3408 | apiErrorStatus: 429, |
| 3409 | }), |
| 3410 | ); |
| 3411 | const terminal = yield* Queue.take(harness.terminalReceipts); |
| 3412 | assert.equal(terminal.status, "failed"); |
| 3413 | const reportedContext = harness.events.flatMap((event) => |
| 3414 | event.type === "provider_turn.updated" && event.providerTurn.tokenUsage |
| 3415 | ? [event.providerTurn.tokenUsage.usedTokens] |
| 3416 | : [], |
| 3417 | ); |
| 3418 | assert.deepEqual(reportedContext, [2]); |
| 3419 | }).pipe( |
| 3420 | Effect.provide( |
| 3421 | Layer.mergeAll(IdAllocator.layer, McpProviderSessions.layer, NodeServices.layer), |
| 3422 | ), |
| 3423 | ), |
| 3424 | ); |
| 3425 | |
| 3358 | 3426 | it.effect("surfaces a Claude safety model fallback without failing the turn", () => |
| 3359 | 3427 | Effect.gen(function* () { |
| 3360 | 3428 | const harness = yield* makeWakeHarness; |