源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
|
||||
import {
|
||||
COMPOSER_CONFIGURE_SECTION,
|
||||
LIBRARY_ROUTE_PATH,
|
||||
composerConfigureDestination,
|
||||
composerConfigureSectionForMenu,
|
||||
isLibraryAgent,
|
||||
isLibraryCommand,
|
||||
libraryAgentDetailId,
|
||||
libraryAgentsFromOpencode,
|
||||
libraryCommandDetailId,
|
||||
libraryCommandTriggers,
|
||||
libraryCommandsFromSlashOptions,
|
||||
libraryPathForSection,
|
||||
denLibraryPluginCreateRequest,
|
||||
libraryAddAction,
|
||||
libraryAddKindsForFilter,
|
||||
libraryPluginFileDisplayName,
|
||||
libraryPluginFileFallbackDetailId,
|
||||
libraryPluginFilePreferredDetailId,
|
||||
parseLibraryPluginFileDetailId,
|
||||
waitForListedLibraryPlugin,
|
||||
slugifyLibraryItemName,
|
||||
} from "../src/react-app/domains/settings/library";
|
||||
import { libraryAddKindLabel } from "../src/react-app/domains/settings/pages/library-add-control";
|
||||
|
||||
describe("library destination", () => {
|
||||
test("composer Configure opens the matching Library filter except for providers", () => {
|
||||
expect(composerConfigureDestination("agents")).toEqual({ kind: "library", path: "agents" });
|
||||
expect(composerConfigureDestination("commands")).toEqual({ kind: "library", path: "commands" });
|
||||
expect(composerConfigureDestination("skills")).toEqual({ kind: "library", path: "skills" });
|
||||
expect(composerConfigureDestination("mcps")).toEqual({ kind: "library", path: "mcps" });
|
||||
expect(composerConfigureDestination("plugins")).toEqual({ kind: "library", path: "plugins" });
|
||||
expect(composerConfigureDestination("connections")).toEqual({ kind: "library", path: "connections" });
|
||||
expect(composerConfigureDestination("extensions")).toEqual({
|
||||
kind: "library",
|
||||
path: LIBRARY_ROUTE_PATH,
|
||||
});
|
||||
expect(composerConfigureDestination("providers")).toEqual({
|
||||
kind: "settings",
|
||||
route: "/settings/ai",
|
||||
});
|
||||
expect(composerConfigureDestination(COMPOSER_CONFIGURE_SECTION)).toEqual({
|
||||
kind: "library",
|
||||
path: LIBRARY_ROUTE_PATH,
|
||||
});
|
||||
});
|
||||
|
||||
test("composer + menu panes map onto Library section URLs", () => {
|
||||
expect(composerConfigureSectionForMenu("skills")).toBe("skills");
|
||||
expect(composerConfigureSectionForMenu("commands")).toBe("commands");
|
||||
expect(composerConfigureSectionForMenu("agents")).toBe("agents");
|
||||
expect(composerConfigureSectionForMenu("plugin:recruiting")).toBe("plugins");
|
||||
expect(composerConfigureSectionForMenu("mcps")).toBe("connections");
|
||||
expect(composerConfigureSectionForMenu("plugins")).toBe("plugins");
|
||||
expect(composerConfigureSectionForMenu("connections")).toBe("connections");
|
||||
expect(libraryPathForSection(composerConfigureSectionForMenu("skills"))).toBe("skills");
|
||||
expect(libraryPathForSection(composerConfigureSectionForMenu("connections"))).toBe("connections");
|
||||
expect(libraryPathForSection(composerConfigureSectionForMenu("mcps"))).toBe("connections");
|
||||
});
|
||||
|
||||
test("Library commands exclude skill and MCP slash aliases", () => {
|
||||
expect(isLibraryCommand({ source: "command" })).toBe(true);
|
||||
expect(isLibraryCommand({})).toBe(true);
|
||||
expect(isLibraryCommand({ source: "skill" })).toBe(false);
|
||||
expect(isLibraryCommand({ source: "mcp" })).toBe(false);
|
||||
expect(
|
||||
libraryCommandsFromSlashOptions([
|
||||
{ id: "cmd:release", name: "release", source: "command" },
|
||||
{ id: "skill:brief", name: "brief", source: "skill" },
|
||||
]).map((command) => command.name),
|
||||
).toEqual(["release"]);
|
||||
});
|
||||
|
||||
test("Library agents exclude hidden and subagent entries", () => {
|
||||
expect(isLibraryAgent({ name: "openwork" })).toBe(true);
|
||||
expect(isLibraryAgent({ name: "reviewer", hidden: true })).toBe(false);
|
||||
expect(isLibraryAgent({ name: "explore", mode: "subagent" })).toBe(false);
|
||||
expect(
|
||||
libraryAgentsFromOpencode([
|
||||
{ name: "openwork" },
|
||||
{ name: "hidden", hidden: true },
|
||||
{ name: "explore", mode: "subagent" },
|
||||
{ name: "writer", description: "Drafts" },
|
||||
]).map((agent) => agent.name),
|
||||
).toEqual(["openwork", "writer"]);
|
||||
});
|
||||
|
||||
test("Library commands keep templates and slash triggers for detail", () => {
|
||||
const commands = libraryCommandsFromSlashOptions([
|
||||
{
|
||||
id: "cmd:release",
|
||||
name: "release",
|
||||
source: "command",
|
||||
template: "Ship the build",
|
||||
hints: ["ship it"],
|
||||
agent: "openwork",
|
||||
},
|
||||
]);
|
||||
expect(commands[0]?.template).toBe("Ship the build");
|
||||
expect(libraryCommandTriggers(commands[0]!)).toEqual(["/release", "ship it"]);
|
||||
expect(libraryCommandDetailId(commands[0]!)).toBe("command:cmd:release");
|
||||
});
|
||||
|
||||
test("Library agents keep prompt and mode for detail", () => {
|
||||
const agents = libraryAgentsFromOpencode([
|
||||
{ name: "writer", description: "Drafts", prompt: "Write clearly.", mode: "primary", native: true },
|
||||
]);
|
||||
expect(agents[0]?.prompt).toBe("Write clearly.");
|
||||
expect(libraryAgentDetailId(agents[0]!)).toBe("agent:writer");
|
||||
});
|
||||
|
||||
test("Library Add matches the active filter", () => {
|
||||
expect(libraryAddKindsForFilter("skill")).toEqual(["skill"]);
|
||||
expect(libraryAddKindsForFilter("command")).toEqual(["command"]);
|
||||
expect(libraryAddKindsForFilter("agent")).toEqual(["agent"]);
|
||||
expect(libraryAddKindsForFilter("mcp")).toEqual(["mcp", "workspace-mcp"]);
|
||||
expect(libraryAddKindsForFilter("plugin")).toEqual(["plugin"]);
|
||||
expect(libraryAddKindsForFilter("connection")).toEqual(["connection"]);
|
||||
expect(libraryAddKindsForFilter("app")).toEqual([]);
|
||||
expect(libraryAddKindsForFilter("all")).toEqual([
|
||||
"skill",
|
||||
"command",
|
||||
"agent",
|
||||
"mcp",
|
||||
"workspace-mcp",
|
||||
"plugin",
|
||||
"connection",
|
||||
]);
|
||||
});
|
||||
|
||||
test("Library Add slugs names to kebab-case", () => {
|
||||
expect(slugifyLibraryItemName("Briefing Notes", "skill")).toBe("briefing-notes");
|
||||
expect(slugifyLibraryItemName("/Release", "command")).toBe("release");
|
||||
expect(slugifyLibraryItemName(" ", "agent")).toBe("agent");
|
||||
});
|
||||
|
||||
test("Library Add creates on Den when signed in", () => {
|
||||
const signedIn = { cloudSignedIn: true, allowManageExtensions: true };
|
||||
expect(libraryAddAction("skill", signedIn)).toEqual({ type: "den-modal", kind: "skill" });
|
||||
expect(libraryAddAction("plugin", signedIn)).toEqual({ type: "den-modal", kind: "plugin" });
|
||||
expect(libraryAddAction("mcp", signedIn)).toEqual({ type: "den-modal", kind: "mcp" });
|
||||
expect(libraryAddAction("connection", signedIn)).toEqual({ type: "den-url", kind: "connection" });
|
||||
});
|
||||
|
||||
test("Library Add is unavailable when signed out", () => {
|
||||
const signedOut = { cloudSignedIn: false, allowManageExtensions: false };
|
||||
expect(libraryAddAction("skill", signedOut)).toBeNull();
|
||||
expect(libraryAddAction("mcp", signedOut)).toBeNull();
|
||||
expect(libraryAddAction("plugin", signedOut)).toBeNull();
|
||||
expect(libraryAddAction("connection", signedOut)).toBeNull();
|
||||
});
|
||||
|
||||
test("Library Add opens workspace MCP locally while signed out when policy allows", () => {
|
||||
const signedOut = { cloudSignedIn: false, allowManageExtensions: true };
|
||||
|
||||
expect(libraryAddAction("workspace-mcp", signedOut)).toEqual({ type: "workspace-mcp" });
|
||||
expect(libraryAddAction("mcp", signedOut)).toBeNull();
|
||||
});
|
||||
|
||||
test("extension policy gates workspace MCP without blocking organization MCP authoring", () => {
|
||||
const restricted = { cloudSignedIn: true, allowManageExtensions: false };
|
||||
|
||||
expect(libraryAddAction("workspace-mcp", restricted)).toBeNull();
|
||||
expect(libraryAddAction("mcp", restricted)).toEqual({ type: "den-modal", kind: "mcp" });
|
||||
});
|
||||
|
||||
test("Library Add distinguishes organization and workspace MCP labels", () => {
|
||||
expect(libraryAddKindLabel("mcp")).toBe("Add organization MCP");
|
||||
expect(libraryAddKindLabel("workspace-mcp")).toBe("Add workspace MCP");
|
||||
});
|
||||
|
||||
test("signed-in Library Add posts a Den plugin bundle", () => {
|
||||
const request = denLibraryPluginCreateRequest("skill", {
|
||||
name: "Briefing Notes",
|
||||
description: "Prepare a customer briefing.",
|
||||
instructions: "Look up the account first.",
|
||||
});
|
||||
expect(request.name).toBe("Briefing Notes");
|
||||
expect(request.marketplaceId).toBeUndefined();
|
||||
expect(request.orgWide).toBe(false);
|
||||
expect(request.components[0]?.type).toBe("skill");
|
||||
expect(request.components[0]?.input.metadata.name).toBe("briefing-notes");
|
||||
expect(request.components[0]?.input.rawSourceText).toContain("Look up the account first.");
|
||||
});
|
||||
|
||||
test("Library Add MCP posts a Den remote server, not a local config", () => {
|
||||
const request = denLibraryPluginCreateRequest("mcp", {
|
||||
name: "Linear",
|
||||
description: "",
|
||||
instructions: "https://mcp.linear.app/mcp",
|
||||
});
|
||||
expect(request.components[0]?.type).toBe("mcp");
|
||||
expect(request.components[0]?.input.normalizedPayloadJson).toEqual({
|
||||
mcpServers: { linear: { type: "remote", url: "https://mcp.linear.app/mcp" } },
|
||||
});
|
||||
});
|
||||
|
||||
test("Library Add plugin bundle keeps MCP servers and does not auto-publish", () => {
|
||||
const request = denLibraryPluginCreateRequest("plugin", {
|
||||
name: "Sales call prep",
|
||||
description: "Prep a call",
|
||||
instructions: "",
|
||||
components: [
|
||||
{ kind: "skill", name: "briefing", description: "Brief the account", content: "Look up the account." },
|
||||
{ kind: "mcp", name: "Linear", description: "", content: "https://mcp.linear.app/mcp" },
|
||||
],
|
||||
});
|
||||
expect(request.marketplaceId).toBeUndefined();
|
||||
expect(request.components.map((component) => component.type)).toEqual(["skill", "mcp"]);
|
||||
expect(request.components[1]?.input.normalizedPayloadJson).toEqual({
|
||||
mcpServers: { linear: { type: "remote", url: "https://mcp.linear.app/mcp" } },
|
||||
});
|
||||
});
|
||||
|
||||
test("plugin files map onto Library detail ids", () => {
|
||||
const skill = {
|
||||
configObjectId: "cfg_skill",
|
||||
objectType: "skill",
|
||||
title: "Customer research",
|
||||
skillName: "customer-research",
|
||||
};
|
||||
const command = {
|
||||
configObjectId: "cfg_cmd",
|
||||
objectType: "command",
|
||||
title: "brief",
|
||||
};
|
||||
const mcp = {
|
||||
configObjectId: "cfg_mcp",
|
||||
objectType: "mcp",
|
||||
title: "Linear",
|
||||
};
|
||||
expect(libraryPluginFileDisplayName(skill)).toBe("customer-research");
|
||||
expect(libraryPluginFilePreferredDetailId(skill)).toBe("skill:customer-research");
|
||||
expect(libraryPluginFilePreferredDetailId(command)).toBe("command:cmd:brief");
|
||||
expect(libraryPluginFilePreferredDetailId(mcp)).toBe("connect-mcp:Linear");
|
||||
expect(libraryPluginFileFallbackDetailId("plug_1", skill)).toBe("plugin:plug_1/file/cfg_skill");
|
||||
expect(parseLibraryPluginFileDetailId("plugin:plug_1/file/cfg_skill")).toEqual({
|
||||
pluginId: "plug_1",
|
||||
fileId: "cfg_skill",
|
||||
});
|
||||
expect(parseLibraryPluginFileDetailId("plugin:plug_1")).toBeNull();
|
||||
});
|
||||
|
||||
test("waits until a created plugin appears in My Library", async () => {
|
||||
let calls = 0;
|
||||
const found = await waitForListedLibraryPlugin(
|
||||
async () => {
|
||||
calls += 1;
|
||||
return calls >= 2 ? [{ id: "plug_new" }] : [];
|
||||
},
|
||||
"plug_new",
|
||||
{ attempts: 3, delayMs: 0 },
|
||||
);
|
||||
expect(found).toBe(true);
|
||||
expect(calls).toBe(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user