返回 DeepSeek-Reasonix
interrupted-turn-provider-error.test.ts
根目录 / desktop / frontend / src / __tests__ / interrupted-turn-provider-error.test.ts
1 // Run: pnpm exec tsx src/__tests__/interrupted-turn-provider-error.test.ts
2 import assert from "node:assert/strict";
3
4 import { initialState, reducer } from "../lib/useController";
5
6 function finish(e: Record<string, unknown>) {
7 const started = reducer(initialState, { type: "event", e: { kind: "turn_started" } });
8 return reducer(started, { type: "event", e: { kind: "turn_done", ...e } });
9 }
10
11 const quota = finish({
12 status: "recovery_required",
13 err: "relay · Chat Completions: provider balance or plan quota insufficient (HTTP 402)",
14 detail: "Connection ID: relay",
15 diagnostic: { kind: "quota", status: 402, protocol: "openai" },
16 recovery: { state: "recovery_required", reason: "silent_interruption" },
17 });
18 const notices = quota.items.filter((item) => item.kind === "notice");
19 const failure = notices.find((item) => item.kind === "notice" && item.level === "warn");
20 assert.ok(failure?.kind === "notice" && failure.text.includes("HTTP 402"), "provider error stays visible on a recovery_required turn");
21 assert.equal(failure?.kind === "notice" ? failure.detail : "", "Connection ID: relay");
22 assert.ok(notices.some((item) => item.kind === "notice" && item.level === "info"), "interrupted guidance stays alongside the error");
23 assert.equal(new Set(quota.items.map((item) => item.id)).size, quota.items.length, "notice ids stay unique");
24
25 const cancelled = finish({ status: "interrupted", err: "context canceled", diagnostic: { kind: "cancelled" } });
26 assert.ok(!cancelled.items.some((item) => item.kind === "notice" && item.level === "warn"), "a user stop is not reported as a provider failure");
27
28 console.log("interrupted-turn-provider-error: ok");
29
29 lines TYPESCRIPT