




















@@ -0,0 +1,83 @@
1+import { beforeEach, describe, expect, it, vi } from "vitest";
2+import type { CommitmentRecord } from "../commitments/types.js";
3+import type { RuntimeEnv } from "../runtime.js";
4+import { commitmentsListCommand } from "./commitments.js";
5+6+const mocks = vi.hoisted(() => ({
7+listCommitments: vi.fn(),
8+markCommitmentsStatus: vi.fn(),
9+resolveCommitmentStorePath: vi.fn(() => "/tmp/openclaw-commitments.json"),
10+loadConfig: vi.fn(() => ({
11+commitments: {
12+store: "/tmp/openclaw-commitments.json",
13+},
14+})),
15+}));
16+17+vi.mock("../commitments/store.js", () => ({
18+listCommitments: mocks.listCommitments,
19+markCommitmentsStatus: mocks.markCommitmentsStatus,
20+resolveCommitmentStorePath: mocks.resolveCommitmentStorePath,
21+}));
22+23+vi.mock("../config/config.js", () => ({
24+loadConfig: mocks.loadConfig,
25+}));
26+27+function createRuntime(): { runtime: RuntimeEnv; logs: string[] } {
28+const logs: string[] = [];
29+return {
30+ logs,
31+runtime: {
32+log: (message: unknown) => logs.push(String(message)),
33+error: vi.fn(),
34+exit: vi.fn(),
35+},
36+};
37+}
38+39+function commitment(overrides?: Partial<CommitmentRecord>): CommitmentRecord {
40+return {
41+id: "cm_escape",
42+agentId: "main\u001b[31m",
43+sessionKey: "agent:main:session\u001b]8;;https://example.test\u0007",
44+channel: "telegram",
45+to: "+15551234567\u001b[0m",
46+kind: "event_check_in",
47+sensitivity: "routine",
48+source: "inferred_user_context",
49+status: "pending",
50+reason: "The user mentioned an interview.",
51+suggestedText: "How did it go?\u001b]52;c;YWJj\u0007\nspoofed",
52+dedupeKey: "interview:2026-04-30",
53+confidence: 0.91,
54+dueWindow: {
55+earliestMs: Date.parse("2026-04-30T17:00:00.000Z"),
56+latestMs: Date.parse("2026-04-30T23:00:00.000Z"),
57+timezone: "America/Los_Angeles",
58+},
59+sourceUserText: "I have an interview tomorrow.",
60+createdAtMs: Date.parse("2026-04-29T16:00:00.000Z"),
61+updatedAtMs: Date.parse("2026-04-29T16:00:00.000Z"),
62+attempts: 0,
63+ ...overrides,
64+};
65+}
66+67+describe("commitments command", () => {
68+beforeEach(() => {
69+vi.clearAllMocks();
70+mocks.listCommitments.mockResolvedValue([commitment()]);
71+});
72+73+it("sanitizes untrusted commitment fields in table output", async () => {
74+const { runtime, logs } = createRuntime();
75+76+await commitmentsListCommand({}, runtime);
77+78+const output = logs.join("\n");
79+expect(output).not.toContain("\u001b");
80+expect(output).not.toContain("\u0007");
81+expect(output).toContain("\\nspoofed");
82+});
83+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。