mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-04 08:28:36 +00:00
66 lines
3.2 KiB
TypeScript
66 lines
3.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { describeTraceLine } from "@/components/thread/activity/trace-activity-model";
|
|
import type { GenericToolStatus } from "@/components/thread/activity/generic-tool-model";
|
|
|
|
function describeTrace(line: string, status: GenericToolStatus = "done") {
|
|
return describeTraceLine(line, status);
|
|
}
|
|
|
|
describe("trace activity semantics", () => {
|
|
it.each([
|
|
['web_search({"query":"nanobot latest release"})', "done", "Searched nanobot latest release", ""],
|
|
['web_fetch({"url":"https://example.com/docs?token=private"})', "done", "Read", "example.com/docs"],
|
|
['read_file({"path":"/Users/alice/project/README.md"})', "done", "Read", "~/project/README.md"],
|
|
['exec({"command":"date +%Y-%m-%d"})', "done", "Checked current time", ""],
|
|
['exec_command({"cmd":"API_KEY=secret npm test"})', "running", "Running command", "API_KEY=•••• npm test"],
|
|
['write_file({"path":"/home/alice/project/output.txt"})', "done", "Wrote file", "~/project/output.txt"],
|
|
['apply_patch({"file_path":"src/app.tsx","patch":"private"})', "error", "Could not edit file", "src/app.tsx"],
|
|
['third_party_sync({"token":"secret","payload":"private"})', "done", "Completed Third party sync", ""],
|
|
["Finished collecting results", "done", "Completed step", "Finished collecting results"],
|
|
] as const)("describes %s as one safe activity line", (line, status, label, detail) => {
|
|
const result = describeTrace(line, status);
|
|
expect(result).toMatchObject({ label, detail });
|
|
expect(`${result.label} ${result.detail}`).not.toMatch(/[{}]|private|\/Users\/alice|\/home\/alice/);
|
|
});
|
|
|
|
it.each([
|
|
["running", "Searching status test"],
|
|
["done", "Searched status test"],
|
|
["error", "Could not search status test"],
|
|
] as const)("uses status-aware search copy for %s", (status, label) => {
|
|
expect(describeTrace('web_search({"query":"status test"})', status).label).toBe(label);
|
|
});
|
|
|
|
it.each([
|
|
["running", "Searching X · status test"],
|
|
["done", "Searched X · status test"],
|
|
["error", "Could not search X · status test"],
|
|
] as const)("identifies hosted X search activity for %s", (status, label) => {
|
|
expect(describeTrace('x_search({"query":"status test"})', status).label).toBe(label);
|
|
});
|
|
|
|
it("never exposes URL credentials, query secrets, or private-network links", () => {
|
|
const publicResult = describeTrace(
|
|
'web_fetch({"url":"https://user:password@example.com/docs?api_key=secret#section"})',
|
|
);
|
|
expect(publicResult).toMatchObject({ detail: "example.com/docs", host: "example.com" });
|
|
expect(JSON.stringify(publicResult)).not.toMatch(/password|api_key|secret/);
|
|
|
|
const privateResult = describeTrace('web_fetch({"url":"http://127.0.0.1:8765/private"})');
|
|
expect(privateResult.url).toBeUndefined();
|
|
expect(privateResult.detail).not.toContain("127.0.0.1");
|
|
});
|
|
|
|
it("summarizes multi-line commands without exposing every script line", () => {
|
|
const result = describeTrace(
|
|
'exec({"command":"npm test\\necho second-secret-line\\necho third-line"})',
|
|
);
|
|
expect(result).toMatchObject({
|
|
label: "Ran command",
|
|
detail: "npm test · script, 3 lines",
|
|
});
|
|
expect(result.detail).not.toContain("second-secret-line");
|
|
});
|
|
});
|