import { describe, expect, it } from "bun:test"; import { buildToolProgressDetail, extractRequestReason, sanitizeToolProgressInput } from "../../src/routes/chatStreamEvents.js"; import { upsertBackendProgress } from "../../src/routes/chatUiState.js"; describe("browser tool progress metadata", () => { it("omits absent explanations and displays canonical or legacy reasons once", () => { const plain = buildToolProgressDetail("query", "running", { id: "n1" }, ""); expect(plain).not.toContain("说明:"); expect(plain).not.toContain("原因:"); expect(plain).toContain("id=n1"); for (const input of [{ reason: " 核验压力异常 " }, { request_reason: "核验压力异常" }]) { const detail = buildToolProgressDetail("query", "running", input, extractRequestReason(input)); expect(detail).toContain(";说明:核验压力异常"); expect(detail.match(/核验压力异常/g)).toHaveLength(1); } expect(extractRequestReason({ reason: "当前说明", purpose: "旧说明" })).toBe("当前说明"); }); it("preserves useful full inputs while redacting credentials", () => { const address = "完整地址".repeat(70); const input = sanitizeToolProgressInput({ address, point: { longitude: 121.5, latitude: 31.2 }, authorization: "private", nested: { api_key: "private", text: "Bearer abcdefghijklmnop12345" } }); expect(input).toEqual({ address, point: { longitude: 121.5, latitude: 31.2 }, authorization: "[redacted]", nested: { api_key: "[redacted]", text: "[redacted]" } }); const first = upsertBackendProgress([], { id: "call", phase: "tool", tool: { name: "mcp_tjwater_geocode", call_id: "native-call", input } }); const next = upsertBackendProgress(first, { id: "call", status: "completed" }); expect(next[0].tool).toEqual({ name: "mcp_tjwater_geocode", callId: "native-call", input }); }); it("keeps secrets out of the compatibility detail summary", () => { const detail = buildToolProgressDetail("query", "error", { api_key: "private-value", nested: { password: "nested-value" } }, "Bearer abcdefghijklmnop12345", "api_key=error-secret"); expect(detail).not.toContain("private-value"); expect(detail).not.toContain("nested-value"); expect(detail).not.toContain("abcdefghijklmnop12345"); expect(detail).not.toContain("error-secret"); }); it("bounds oversized inputs", () => { const input = sanitizeToolProgressInput({ text: "a".repeat(20_000), items: Array.from({ length: 100 }, () => "b".repeat(4_000)) }); expect(JSON.stringify(input).length).toBeLessThan(18_000); expect(JSON.stringify(input)).toContain("[truncated]"); }); });