





















@@ -0,0 +1,86 @@
1+import fs from "node:fs";
2+import os from "node:os";
3+import path from "node:path";
4+import { afterAll, beforeAll, describe, expect, it } from "vitest";
5+import type { callGateway as gatewayCall } from "../../gateway/call.js";
6+7+type CallGatewayRequest = Parameters<typeof gatewayCall>[0];
8+9+let createSessionsHistoryTool: typeof import("./sessions-history-tool.js").createSessionsHistoryTool;
10+let previousConfigPath: string | undefined;
11+let tempDir: string | undefined;
12+13+function useLoggingConfig(name: string, logging: Record<string, unknown>): void {
14+if (!tempDir) {
15+throw new Error("tempDir not initialized");
16+}
17+const configPath = path.join(tempDir, name);
18+fs.writeFileSync(configPath, `${JSON.stringify({ logging })}\n`, "utf8");
19+process.env.OPENCLAW_CONFIG_PATH = configPath;
20+}
21+22+function createHistoryToolWithMessage(content: string) {
23+return createSessionsHistoryTool({
24+config: {},
25+callGateway: async <T = Record<string, unknown>>(request: CallGatewayRequest): Promise<T> => {
26+if (request.method === "chat.history") {
27+return {
28+messages: [
29+{
30+role: "user",
31+ content,
32+},
33+],
34+} as T;
35+}
36+return {} as T;
37+},
38+});
39+}
40+41+describe("sessions_history redaction", () => {
42+beforeAll(async () => {
43+previousConfigPath = process.env.OPENCLAW_CONFIG_PATH;
44+tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-sessions-history-redact-"));
45+useLoggingConfig("redaction-off.json", { redactSensitive: "off" });
46+({ createSessionsHistoryTool } = await import("./sessions-history-tool.js"));
47+});
48+49+afterAll(() => {
50+if (previousConfigPath === undefined) {
51+delete process.env.OPENCLAW_CONFIG_PATH;
52+} else {
53+process.env.OPENCLAW_CONFIG_PATH = previousConfigPath;
54+}
55+if (tempDir) {
56+fs.rmSync(tempDir, { recursive: true, force: true });
57+}
58+});
59+60+it("redacts recalled session text even when log redaction is disabled", async () => {
61+useLoggingConfig("redaction-off.json", { redactSensitive: "off" });
62+const tool = createHistoryToolWithMessage("OPENROUTER_API_KEY=sk-or-v1-abcdef0123456789");
63+64+const result = await tool.execute("call-1", { sessionKey: "main" });
65+const serialized = JSON.stringify(result.details);
66+67+expect(serialized).not.toContain("sk-or-v1-abcdef0123456789");
68+expect(serialized).toContain("OPENROUTER_API_KEY=");
69+expect(result.details).toMatchObject({ contentRedacted: true });
70+});
71+72+it("applies custom redaction patterns to recalled session text", async () => {
73+useLoggingConfig("custom-patterns.json", {
74+redactSensitive: "off",
75+redactPatterns: [String.raw`\binternal-ticket-[A-Za-z0-9]+\b`],
76+});
77+const tool = createHistoryToolWithMessage("follow up on internal-ticket-AbC12345");
78+79+const result = await tool.execute("call-1", { sessionKey: "main" });
80+const serialized = JSON.stringify(result.details);
81+82+expect(serialized).not.toContain("internal-ticket-AbC12345");
83+expect(serialized).toContain("intern");
84+expect(result.details).toMatchObject({ contentRedacted: true });
85+});
86+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。