返回 DeepSeek-Reasonix
provider-failure-meta.test.ts
根目录 / desktop / frontend / src / __tests__ / provider-failure-meta.test.ts
1 // Run: pnpm exec tsx src/__tests__/provider-failure-meta.test.ts
2 import assert from "node:assert/strict";
3
4 import { initialState, reducer } from "../lib/useController";
5 import { historyMessagesToItems } from "../lib/historyItems";
6 import { historyNoticeItems } from "../lib/controllerNotices";
7 import { presentError } from "../lib/errorPresentation";
8 import { en } from "../locales/en";
9 import type { HistoryMessage } from "../lib/types";
10
11 const started = reducer(initialState, { type: "event", e: { kind: "turn_started" } });
12 const failed = reducer(started, {
13 type: "event",
14 e: {
15 kind: "turn_done",
16 err: "Deepseek2 · Chat Completions: Request endpoint not found (HTTP 404).",
17 detail: "Connection ID: deepseek-anthropic\nRequest path: /anthropic/v1/chat/completions",
18 diagnostic: { kind: "request", status: 404, providerId: "deepseek-anthropic", providerDisplayName: "Deepseek2", protocol: "openai", requestPath: "/anthropic/v1/chat/completions" },
19 },
20 });
21 const notice = failed.items.find((item) => item.kind === "notice" && item.level === "warn");
22
23 assert.equal(
24 notice?.kind === "notice" ? notice.text : "",
25 "Deepseek2 · Chat Completions: Request endpoint not found (HTTP 404).",
26 "provider display identity stays in the primary live error",
27 );
28 assert.equal(
29 notice?.kind === "notice" ? notice.detail : "",
30 "Connection ID: deepseek-anthropic\nRequest path: /anthropic/v1/chat/completions",
31 "stable provider id and sanitized path stay in live diagnostic details",
32 );
33
34 const diagnostic = { kind: "transport_protocol", transportCode: "PROTOCOL_ERROR" };
35 const history: HistoryMessage = { role: "notice", content: "opaque provider failure", level: "warn", diagnostic };
36 const live = reducer(started, { type: "event", e: { kind: "turn_done", err: history.content, diagnostic } });
37 const interrupted = reducer(started, { type: "event", e: { kind: "turn_done", status: "interrupted", err: history.content, diagnostic } });
38 const liveNotice = reducer(started, { type: "event", e: { kind: "notice", level: "warn", text: history.content, diagnostic } });
39 for (const items of [live.items, interrupted.items, liveNotice.items, historyMessagesToItems([history], "full").items, historyNoticeItems(history, "windowed")]) {
40 const item = items.find(item => item.kind === "notice" && item.level === "warn");
41 assert.ok(item?.kind === "notice");
42 assert.deepEqual(item.diagnostic, diagnostic, "live and both history projections retain structured evidence");
43 const presentation = presentError(item.text, key => en[key], "en", item.diagnostic);
44 assert.equal(presentation.summary, en["error.transportProtocol"]);
45 assert.match(presentation.detail, /PROTOCOL_ERROR/);
46 }
47
47 lines TYPESCRIPT