



























@@ -4,8 +4,11 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
44import { callGatewayHandler } from "./skills.test-helpers.js";
5566const loadConfigMock = vi.fn(() => ({}));
7+const listAgentIdsMock = vi.fn<(_cfg: unknown) => string[]>(() => ["main"]);
78const resolveDefaultAgentIdMock = vi.fn(() => "main");
8-const resolveAgentWorkspaceDirMock = vi.fn(() => "/tmp/workspace");
9+const resolveAgentWorkspaceDirMock = vi.fn<(_cfg: unknown, _agentId: string) => string>(
10+() => "/tmp/workspace",
11+);
912const buildWorkspaceSkillStatusMock = vi.fn();
1013const readLocalSkillCardContentSyncMock = vi.fn();
1114const fetchClawHubSkillSecurityVerdictsMock = vi.fn();
@@ -19,10 +22,11 @@ vi.mock("../../config/config.js", () => ({
1922}));
20232124vi.mock("../../agents/agent-scope.js", () => ({
22-listAgentIds: vi.fn(() => ["main"]),
25+listAgentIds: (cfg: unknown) => listAgentIdsMock(cfg),
2326resolveAgentConfig: vi.fn(() => undefined),
2427resolveDefaultAgentId: () => resolveDefaultAgentIdMock(),
25-resolveAgentWorkspaceDir: () => resolveAgentWorkspaceDirMock(),
28+resolveAgentWorkspaceDir: (cfg: unknown, agentId: string) =>
29+resolveAgentWorkspaceDirMock(cfg, agentId),
2630resolveSessionAgentId: vi.fn(() => undefined),
2731}));
2832@@ -82,6 +86,7 @@ async function expectEmptySecurityVerdictsWithoutFetch(): Promise<void> {
8286describe("skills gateway handlers (clawhub)", () => {
8387beforeEach(() => {
8488loadConfigMock.mockReset();
89+listAgentIdsMock.mockReset();
8590resolveDefaultAgentIdMock.mockReset();
8691resolveAgentWorkspaceDirMock.mockReset();
8792buildWorkspaceSkillStatusMock.mockReset();
@@ -92,6 +97,7 @@ describe("skills gateway handlers (clawhub)", () => {
9297updateSkillsFromClawHubMock.mockReset();
93989499loadConfigMock.mockReturnValue({});
100+listAgentIdsMock.mockReturnValue(["main"]);
95101resolveDefaultAgentIdMock.mockReturnValue("main");
96102resolveAgentWorkspaceDirMock.mockReturnValue("/tmp/workspace");
97103buildWorkspaceSkillStatusMock.mockReturnValue(emptySkillStatusReport());
@@ -101,6 +107,26 @@ describe("skills gateway handlers (clawhub)", () => {
101107await expectEmptySecurityVerdictsWithoutFetch();
102108});
103109110+it("builds status with the selected agent filter", async () => {
111+listAgentIdsMock.mockReturnValue(["main", "research"]);
112+resolveAgentWorkspaceDirMock.mockImplementation((_cfg, agentId) =>
113+agentId === "research" ? "/tmp/research-workspace" : "/tmp/workspace",
114+);
115+116+const { ok, error } = await callSkillsHandler("skills.status", { agentId: "research" });
117+118+expect(ok).toBe(true);
119+expect(error).toBeUndefined();
120+expect(buildWorkspaceSkillStatusMock).toHaveBeenCalledWith(
121+"/tmp/research-workspace",
122+expect.objectContaining({
123+agentId: "research",
124+config: {},
125+eligibility: expect.any(Object),
126+}),
127+);
128+});
129+104130it("fetches one bulk ClawHub verdict batch for linked installed skills", async () => {
105131buildWorkspaceSkillStatusMock.mockReturnValue({
106132workspaceDir: "/tmp/workspace",
@@ -262,6 +288,37 @@ describe("skills gateway handlers (clawhub)", () => {
262288expect(result?.version).toBe("1.2.3");
263289});
264290291+it("routes explicit agent ClawHub installs through that agent workspace", async () => {
292+listAgentIdsMock.mockReturnValue(["main", "research"]);
293+resolveAgentWorkspaceDirMock.mockImplementation((_cfg, agentId) =>
294+agentId === "research" ? "/tmp/research-workspace" : "/tmp/workspace",
295+);
296+installSkillFromClawHubMock.mockResolvedValue({
297+ok: true,
298+slug: "calendar",
299+version: "1.2.3",
300+targetDir: "/tmp/research-workspace/skills/calendar",
301+});
302+303+const { ok, error } = await callSkillsHandler("skills.install", {
304+agentId: "research",
305+source: "clawhub",
306+slug: "calendar",
307+version: "1.2.3",
308+});
309+310+expect(resolveAgentWorkspaceDirMock).toHaveBeenCalledWith({}, "research");
311+expect(installSkillFromClawHubMock).toHaveBeenCalledWith({
312+workspaceDir: "/tmp/research-workspace",
313+slug: "calendar",
314+version: "1.2.3",
315+force: false,
316+config: {},
317+});
318+expect(ok).toBe(true);
319+expect(error).toBeUndefined();
320+});
321+265322it("accepts deprecated unsafe override without forwarding it to skill installs", async () => {
266323installSkillMock.mockResolvedValue({
267324ok: true,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。