1import { describe, expect, it } from "vite-plus/test";
2
3import {
4 ACP_STDERR_TAIL_MAX_CHARS,
5 appendAcpStderrTail,
6 sanitizeAcpStderrExcerpt,
7} from "./stderr.ts";
8
9describe("AcpStderr", () => {
10 it("keeps a bounded tail of stderr chunks", () => {
11 const prefix = "x".repeat(ACP_STDERR_TAIL_MAX_CHARS);
12 expect(appendAcpStderrTail(prefix, "abc")).toBe(`${prefix.slice(3)}abc`);
13 });
14
15 it("redacts home paths, pairing URLs, and tokens from stderr excerpts", () => {
16 const excerpt = sanitizeAcpStderrExcerpt(
17 [
18 "Invalid project config at /Users/ada/.cursor/cli.json",
19 "Authorization: Bearer secret-token-value",
20 "Visit http://localhost:5733/pair#token=ABCDEF for pairing",
21 "key=sk-abcdefghijklmnopqrstuv",
22 ].join("\n"),
23 "/home/server",
24 { HOME: "/Users/ada" },
25 );
26
27 expect(excerpt).toContain("Invalid project config at ~/.cursor/cli.json");
28 expect(excerpt).toContain("Bearer [redacted]");
29 expect(excerpt).toContain("[pairing-url]");
30 expect(excerpt).toContain("[redacted]");
31 expect(excerpt).not.toContain("secret-token-value");
32 expect(excerpt).not.toContain("ABCDEF");
33 expect(excerpt).not.toContain("sk-abcdefghijklmnopqrstuv");
34 });
35
36 it("redacts hyphenated OpenAI project keys and header credentials", () => {
37 const excerpt = sanitizeAcpStderrExcerpt(
38 [
39 "openai=sk-proj-abcdefghijklmnopqrstuvwxyz012345",
40 "svc=sk-svcacct-abcdefghijklmnopqrstuvwxyz012345",
41 "anthropic=sk-ant-api03-abcdefghijklmnopqrstuvwxyz012345",
42 "Authorization: Basic dXNlcjpwYXNz",
43 "x-api-key: ant-api-key-value",
44 ].join("\n"),
45 "/Users/ada",
46 {},
47 );
48
49 expect(excerpt).toContain("[redacted]");
50 expect(excerpt).toContain("Authorization: Basic [redacted]");
51 expect(excerpt).toContain("x-api-key: [redacted]");
52 expect(excerpt).not.toContain("sk-proj-");
53 expect(excerpt).not.toContain("sk-svcacct-");
54 expect(excerpt).not.toContain("sk-ant-api03-");
55 expect(excerpt).not.toContain("abcdefghijklmnopqrstuvwxyz012345");
56 expect(excerpt).not.toContain("dXNlcjpwYXNz");
57 expect(excerpt).not.toContain("ant-api-key-value");
58 });
59});