
















11import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2-import type { SessionEntry } from "../../config/sessions.js";
3243const TEST_WORKSPACE_DIR = "/tmp/workspace";
5-type TestSkillSnapshot = NonNullable<SessionEntry["skillsSnapshot"]>;
6-7-function strippedSnapshot(skillName = "test"): TestSkillSnapshot {
8-return {
9-prompt: "skills prompt",
10-skills: [{ name: skillName }],
11-version: 0,
12-};
13-}
14-15-function testSessionEntry(sessionId: string, skillsSnapshot: TestSkillSnapshot): SessionEntry {
16-return {
17- sessionId,
18-updatedAt: Date.now(),
19- skillsSnapshot,
20-};
21-}
224235const {
246 buildWorkspaceSkillSnapshotMock,
@@ -82,13 +64,11 @@ vi.mock("../../routing/session-key.js", () => ({
8264resolveAgentIdFromSessionKey: resolveAgentIdFromSessionKeyMock,
8365}));
846685-const { ensureSkillSnapshot, resetResolvedSkillsCacheForTests } =
86-await import("./session-updates.js");
67+const { ensureSkillSnapshot } = await import("./session-updates.js");
87688869describe("ensureSkillSnapshot", () => {
8970beforeEach(() => {
9071vi.clearAllMocks();
91-resetResolvedSkillsCacheForTests();
9272buildWorkspaceSkillSnapshotMock.mockReturnValue({ prompt: "", skills: [], resolvedSkills: [] });
9373getSkillsSnapshotVersionMock.mockReturnValue(0);
9474shouldRefreshSnapshotForVersionMock.mockReturnValue(false);
@@ -135,164 +115,4 @@ describe("ensureSkillSnapshot", () => {
135115expect(snapshotParams.agentId).toBe("writer");
136116expect(resolveAgentIdFromSessionKeyMock).not.toHaveBeenCalled();
137117});
138-139-it("reuses cached resolvedSkills across calls with same workspaceDir/version/filter", async () => {
140-vi.stubEnv("OPENCLAW_TEST_FAST", "0");
141-142-const sessionStore: Record<string, SessionEntry> = {};
143-const sessionKey = "main";
144-const snapshot = strippedSnapshot();
145-const sessionEntry = testSessionEntry("sess-1", snapshot);
146-147-await ensureSkillSnapshot({
148- sessionEntry,
149- sessionStore,
150- sessionKey,
151-isFirstTurnInSession: true,
152-workspaceDir: TEST_WORKSPACE_DIR,
153-cfg: {},
154-});
155-expect(buildWorkspaceSkillSnapshotMock).toHaveBeenCalledTimes(1);
156-157-const sessionEntry2 = testSessionEntry("sess-2", { ...snapshot });
158-await ensureSkillSnapshot({
159-sessionEntry: sessionEntry2,
160-sessionStore: {},
161-sessionKey: "other",
162-isFirstTurnInSession: false,
163-workspaceDir: TEST_WORKSPACE_DIR,
164-cfg: {},
165-});
166-expect(buildWorkspaceSkillSnapshotMock).toHaveBeenCalledTimes(1);
167-});
168-169-it("invalidates cache when skillFilter changes", async () => {
170-vi.stubEnv("OPENCLAW_TEST_FAST", "0");
171-172-const sessionStore: Record<string, SessionEntry> = {};
173-const sessionKey = "main";
174-const snapshot = strippedSnapshot();
175-const sessionEntry = testSessionEntry("sess-1", snapshot);
176-177-await ensureSkillSnapshot({
178- sessionEntry,
179- sessionStore,
180- sessionKey,
181-isFirstTurnInSession: true,
182-workspaceDir: TEST_WORKSPACE_DIR,
183-cfg: {},
184-});
185-expect(buildWorkspaceSkillSnapshotMock).toHaveBeenCalledTimes(1);
186-187-const sessionEntry2 = testSessionEntry("sess-2", {
188- ...snapshot,
189-skillFilter: ["old-filter"],
190-});
191-await ensureSkillSnapshot({
192-sessionEntry: sessionEntry2,
193-sessionStore: {},
194-sessionKey: "other",
195-isFirstTurnInSession: false,
196-workspaceDir: TEST_WORKSPACE_DIR,
197-skillFilter: ["new-filter"],
198-cfg: {},
199-});
200-expect(buildWorkspaceSkillSnapshotMock).toHaveBeenCalledTimes(2);
201-});
202-203-it("reads the skills snapshot version after watcher-side invalidation", async () => {
204-vi.stubEnv("OPENCLAW_TEST_FAST", "0");
205-getSkillsSnapshotVersionMock.mockReturnValue(0);
206-ensureSkillsWatcherMock.mockImplementation(() => {
207-getSkillsSnapshotVersionMock.mockReturnValue(5);
208-});
209-shouldRefreshSnapshotForVersionMock.mockImplementation((cached = 0, next = 0) => cached < next);
210-211-await ensureSkillSnapshot({
212-sessionEntry: testSessionEntry("sess-1", strippedSnapshot()),
213-sessionStore: {},
214-sessionKey: "main",
215-isFirstTurnInSession: false,
216-workspaceDir: TEST_WORKSPACE_DIR,
217-cfg: { skills: { load: { extraDirs: ["/tmp/shared-skills"] } } },
218-});
219-220-expect(shouldRefreshSnapshotForVersionMock).toHaveBeenCalledWith(0, 5);
221-expect(buildWorkspaceSkillSnapshotMock).toHaveBeenCalledTimes(1);
222-const [[, snapshotParams]] = buildWorkspaceSkillSnapshotMock.mock.calls as unknown as Array<
223-[string, { snapshotVersion?: number }]
224->;
225-expect(snapshotParams.snapshotVersion).toBe(5);
226-});
227-228-it("invalidates cache when non-skills config gates change", async () => {
229-vi.stubEnv("OPENCLAW_TEST_FAST", "0");
230-231-buildWorkspaceSkillSnapshotMock.mockImplementation((_workspaceDir, opts) => {
232-const config = (opts as { config?: { channels?: { discord?: { token?: string } } } }).config;
233-return {
234-prompt: "",
235-skills: [],
236-resolvedSkills: config?.channels?.discord?.token ? [{ name: "discord" }] : [],
237-};
238-});
239-240-const snapshot = strippedSnapshot("discord");
241-242-const first = await ensureSkillSnapshot({
243-sessionEntry: testSessionEntry("sess-1", snapshot),
244-sessionStore: {},
245-sessionKey: "main",
246-isFirstTurnInSession: true,
247-workspaceDir: TEST_WORKSPACE_DIR,
248-cfg: { channels: { discord: { token: "enabled" } } },
249-});
250-251-expect(first.skillsSnapshot?.resolvedSkills).toEqual([{ name: "discord" }]);
252-expect(buildWorkspaceSkillSnapshotMock).toHaveBeenCalledTimes(1);
253-254-const second = await ensureSkillSnapshot({
255-sessionEntry: testSessionEntry("sess-2", { ...snapshot }),
256-sessionStore: {},
257-sessionKey: "other",
258-isFirstTurnInSession: false,
259-workspaceDir: TEST_WORKSPACE_DIR,
260-cfg: { channels: { discord: {} } },
261-});
262-263-expect(second.skillsSnapshot?.resolvedSkills).toEqual([]);
264-expect(buildWorkspaceSkillSnapshotMock).toHaveBeenCalledTimes(2);
265-});
266-267-it("redacts secret values in the cache key while preserving eligibility presence", async () => {
268-vi.stubEnv("OPENCLAW_TEST_FAST", "0");
269-270-buildWorkspaceSkillSnapshotMock.mockReturnValue({
271-prompt: "",
272-skills: [],
273-resolvedSkills: [{ name: "discord" }],
274-});
275-276-const snapshot = strippedSnapshot("discord");
277-278-await ensureSkillSnapshot({
279-sessionEntry: testSessionEntry("sess-1", snapshot),
280-sessionStore: {},
281-sessionKey: "main",
282-isFirstTurnInSession: true,
283-workspaceDir: TEST_WORKSPACE_DIR,
284-cfg: { channels: { discord: { token: "first-secret" } } },
285-});
286-287-await ensureSkillSnapshot({
288-sessionEntry: testSessionEntry("sess-2", { ...snapshot }),
289-sessionStore: {},
290-sessionKey: "other",
291-isFirstTurnInSession: false,
292-workspaceDir: TEST_WORKSPACE_DIR,
293-cfg: { channels: { discord: { token: "rotated-secret" } } },
294-});
295-296-expect(buildWorkspaceSkillSnapshotMock).toHaveBeenCalledTimes(1);
297-});
298118});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。