| ... | ... | @@ -1450,6 +1450,67 @@ describe("ClaudeAdapterLive", () => { |
| 1450 | 1450 | ); |
| 1451 | 1451 | }); |
| 1452 | 1452 | |
| 1453 | it.effect("treats aborted_tools results as interrupted and hides ede_diagnostic errors", () => { |
| 1454 | const harness = makeHarness(); |
| 1455 | return Effect.gen(function* () { |
| 1456 | const adapter = yield* ClaudeAdapter; |
| 1457 | |
| 1458 | const runtimeEventsFiber = yield* Stream.take(adapter.streamEvents, 6).pipe( |
| 1459 | Stream.runCollect, |
| 1460 | Effect.forkChild, |
| 1461 | ); |
| 1462 | |
| 1463 | const session = yield* adapter.startSession({ |
| 1464 | threadId: THREAD_ID, |
| 1465 | provider: ProviderDriverKind.make("claudeAgent"), |
| 1466 | runtimeMode: "full-access", |
| 1467 | }); |
| 1468 | |
| 1469 | const turn = yield* adapter.sendTurn({ |
| 1470 | threadId: session.threadId, |
| 1471 | input: "hello", |
| 1472 | attachments: [], |
| 1473 | }); |
| 1474 | |
| 1475 | // Exact shape the CLI emits when Stop lands mid-tool-call: is_error |
| 1476 | // is true and the only error is internal diagnostic telemetry. |
| 1477 | harness.query.emit({ |
| 1478 | type: "result", |
| 1479 | subtype: "error_during_execution", |
| 1480 | is_error: true, |
| 1481 | errors: ["[ede_diagnostic] result_type=user last_content_type=n/a stop_reason=tool_use"], |
| 1482 | stop_reason: "tool_use", |
| 1483 | terminal_reason: "aborted_tools", |
| 1484 | session_id: "sdk-session-abort-tools", |
| 1485 | uuid: "result-abort-tools", |
| 1486 | } as unknown as SDKMessage); |
| 1487 | |
| 1488 | const runtimeEvents = Array.from(yield* Fiber.join(runtimeEventsFiber)); |
| 1489 | assert.deepEqual( |
| 1490 | runtimeEvents.map((event) => event.type), |
| 1491 | [ |
| 1492 | "session.started", |
| 1493 | "session.configured", |
| 1494 | "session.state.changed", |
| 1495 | "turn.started", |
| 1496 | "thread.started", |
| 1497 | "turn.completed", |
| 1498 | ], |
| 1499 | ); |
| 1500 | |
| 1501 | const turnCompleted = runtimeEvents[runtimeEvents.length - 1]; |
| 1502 | assert.equal(turnCompleted?.type, "turn.completed"); |
| 1503 | if (turnCompleted?.type === "turn.completed") { |
| 1504 | assert.equal(String(turnCompleted.turnId), String(turn.turnId)); |
| 1505 | assert.equal(turnCompleted.payload.state, "interrupted"); |
| 1506 | assert.equal(turnCompleted.payload.errorMessage, undefined); |
| 1507 | } |
| 1508 | }).pipe( |
| 1509 | Effect.provideService(Random.Random, makeDeterministicRandomService()), |
| 1510 | Effect.provide(harness.layer), |
| 1511 | ); |
| 1512 | }); |
| 1513 | |
| 1453 | 1514 | it.effect("interruptTurn stops every live task before interrupting the turn", () => { |
| 1454 | 1515 | const harness = makeHarness(); |
| 1455 | 1516 | return Effect.gen(function* () { |