swarmkit 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -131
- package/dist/commands/add.js +45 -2
- package/dist/commands/init/phases/global-setup.js +1 -1
- package/dist/commands/init/phases/project.js +5 -3
- package/dist/commands/init/state.d.ts +2 -0
- package/dist/commands/init/state.js +1 -0
- package/dist/commands/init/state.test.js +1 -0
- package/dist/commands/init/wizard.d.ts +5 -1
- package/dist/commands/init/wizard.js +78 -8
- package/dist/commands/init.js +7 -2
- package/dist/commands/remove.js +6 -0
- package/dist/config/global.d.ts +12 -0
- package/dist/config/global.js +34 -1
- package/dist/config/global.test.js +48 -15
- package/dist/doctor/checks.d.ts +1 -1
- package/dist/doctor/checks.js +26 -10
- package/dist/doctor/checks.test.js +52 -27
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/packages/installer.d.ts +9 -0
- package/dist/packages/installer.js +43 -12
- package/dist/packages/installer.test.js +84 -1
- package/dist/packages/plugin.d.ts +13 -0
- package/dist/packages/plugin.js +33 -0
- package/dist/packages/plugin.test.d.ts +1 -0
- package/dist/packages/plugin.test.js +99 -0
- package/dist/packages/registry.d.ts +1 -1
- package/dist/packages/registry.js +25 -50
- package/dist/packages/registry.test.js +38 -49
- package/dist/packages/setup.d.ts +11 -4
- package/dist/packages/setup.js +208 -103
- package/dist/packages/setup.test.js +337 -246
- package/package.json +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
// Mock child_process.execFile
|
|
3
|
+
const mockExecFile = vi.fn();
|
|
4
|
+
vi.mock("node:child_process", () => ({
|
|
5
|
+
execFile: mockExecFile,
|
|
6
|
+
}));
|
|
7
|
+
vi.mock("node:util", async () => {
|
|
8
|
+
const actual = await vi.importActual("node:util");
|
|
9
|
+
return {
|
|
10
|
+
...actual,
|
|
11
|
+
promisify: () => mockExecFile,
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
// Mock fs.existsSync for isInstalledPlugin
|
|
15
|
+
const mockExistsSync = vi.fn();
|
|
16
|
+
vi.mock("node:fs", async () => {
|
|
17
|
+
const actual = await vi.importActual("node:fs");
|
|
18
|
+
return {
|
|
19
|
+
...actual,
|
|
20
|
+
existsSync: (...args) => mockExistsSync(...args),
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
const { isInstalledPlugin, registerPlugin } = await import("./plugin.js");
|
|
24
|
+
describe("plugin", () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
mockExecFile.mockReset();
|
|
27
|
+
mockExistsSync.mockReset();
|
|
28
|
+
});
|
|
29
|
+
describe("isInstalledPlugin", () => {
|
|
30
|
+
it("returns true when .claude-plugin/plugin.json exists", async () => {
|
|
31
|
+
// getGlobalPackagePath
|
|
32
|
+
mockExecFile.mockResolvedValueOnce({
|
|
33
|
+
stdout: "/usr/local/lib/node_modules\n/usr/local/lib/node_modules/claude-code-swarm\n",
|
|
34
|
+
});
|
|
35
|
+
mockExistsSync.mockReturnValue(true);
|
|
36
|
+
const result = await isInstalledPlugin("claude-code-swarm");
|
|
37
|
+
expect(result).toBe(true);
|
|
38
|
+
expect(mockExistsSync).toHaveBeenCalledWith(expect.stringContaining(".claude-plugin/plugin.json"));
|
|
39
|
+
});
|
|
40
|
+
it("returns false when package is not installed", async () => {
|
|
41
|
+
mockExecFile.mockRejectedValueOnce(new Error("not found"));
|
|
42
|
+
const result = await isInstalledPlugin("not-installed");
|
|
43
|
+
expect(result).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
it("returns false when package exists but has no .claude-plugin/", async () => {
|
|
46
|
+
mockExecFile.mockResolvedValueOnce({
|
|
47
|
+
stdout: "/usr/local/lib/node_modules\n/usr/local/lib/node_modules/minimem\n",
|
|
48
|
+
});
|
|
49
|
+
mockExistsSync.mockReturnValue(false);
|
|
50
|
+
const result = await isInstalledPlugin("minimem");
|
|
51
|
+
expect(result).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe("registerPlugin", () => {
|
|
55
|
+
it("calls claude plugin add with user scope by default", async () => {
|
|
56
|
+
// getGlobalPackagePath
|
|
57
|
+
mockExecFile.mockResolvedValueOnce({
|
|
58
|
+
stdout: "/usr/local/lib/node_modules\n/usr/local/lib/node_modules/claude-code-swarm\n",
|
|
59
|
+
});
|
|
60
|
+
// claude plugin add
|
|
61
|
+
mockExecFile.mockResolvedValueOnce({ stdout: "Plugin added\n" });
|
|
62
|
+
await registerPlugin("claude-code-swarm");
|
|
63
|
+
expect(mockExecFile).toHaveBeenCalledWith("claude", ["plugin", "add", "/usr/local/lib/node_modules/claude-code-swarm", "--scope", "user"], { timeout: 30_000 });
|
|
64
|
+
});
|
|
65
|
+
it("passes project scope to claude plugin add", async () => {
|
|
66
|
+
// getGlobalPackagePath
|
|
67
|
+
mockExecFile.mockResolvedValueOnce({
|
|
68
|
+
stdout: "/usr/local/lib/node_modules\n/usr/local/lib/node_modules/claude-code-swarm\n",
|
|
69
|
+
});
|
|
70
|
+
// claude plugin add
|
|
71
|
+
mockExecFile.mockResolvedValueOnce({ stdout: "" });
|
|
72
|
+
await registerPlugin("claude-code-swarm", "project");
|
|
73
|
+
expect(mockExecFile).toHaveBeenCalledWith("claude", ["plugin", "add", "/usr/local/lib/node_modules/claude-code-swarm", "--scope", "project"], { timeout: 30_000 });
|
|
74
|
+
});
|
|
75
|
+
it("passes local scope to claude plugin add", async () => {
|
|
76
|
+
// getGlobalPackagePath
|
|
77
|
+
mockExecFile.mockResolvedValueOnce({
|
|
78
|
+
stdout: "/usr/local/lib/node_modules\n/usr/local/lib/node_modules/claude-code-swarm\n",
|
|
79
|
+
});
|
|
80
|
+
// claude plugin add
|
|
81
|
+
mockExecFile.mockResolvedValueOnce({ stdout: "" });
|
|
82
|
+
await registerPlugin("claude-code-swarm", "local");
|
|
83
|
+
expect(mockExecFile).toHaveBeenCalledWith("claude", ["plugin", "add", "/usr/local/lib/node_modules/claude-code-swarm", "--scope", "local"], { timeout: 30_000 });
|
|
84
|
+
});
|
|
85
|
+
it("throws when global path cannot be resolved", async () => {
|
|
86
|
+
mockExecFile.mockRejectedValueOnce(new Error("not found"));
|
|
87
|
+
await expect(registerPlugin("not-installed")).rejects.toThrow("Could not resolve global install path");
|
|
88
|
+
});
|
|
89
|
+
it("throws when claude plugin add fails", async () => {
|
|
90
|
+
// getGlobalPackagePath
|
|
91
|
+
mockExecFile.mockResolvedValueOnce({
|
|
92
|
+
stdout: "/usr/local/lib/node_modules\n/usr/local/lib/node_modules/claude-code-swarm\n",
|
|
93
|
+
});
|
|
94
|
+
// claude plugin add fails
|
|
95
|
+
mockExecFile.mockRejectedValueOnce(new Error("registration failed"));
|
|
96
|
+
await expect(registerPlugin("claude-code-swarm")).rejects.toThrow("registration failed");
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -6,7 +6,7 @@ export interface PackageDefinition {
|
|
|
6
6
|
/** Short description */
|
|
7
7
|
description: string;
|
|
8
8
|
/** Layer in the stack */
|
|
9
|
-
category: "orchestration" | "protocol" | "tasks" | "
|
|
9
|
+
category: "orchestration" | "protocol" | "tasks" | "interface" | "learning" | "observability";
|
|
10
10
|
/** No per-project config — global only */
|
|
11
11
|
globalOnly?: boolean;
|
|
12
12
|
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
export const PACKAGES = {
|
|
2
|
-
"macro-agent": {
|
|
3
|
-
name: "macro-agent",
|
|
4
|
-
description: "Multi-agent orchestration for hierarchical Claude Code agents",
|
|
5
|
-
category: "orchestration",
|
|
6
|
-
},
|
|
7
2
|
"self-driving-repo": {
|
|
8
3
|
name: "self-driving-repo",
|
|
9
4
|
description: "Event-driven workflow engine for autonomous GitHub SDLC",
|
|
@@ -20,22 +15,6 @@ export const PACKAGES = {
|
|
|
20
15
|
description: "Cross-system graph for tasks, specs, and relationships",
|
|
21
16
|
category: "tasks",
|
|
22
17
|
},
|
|
23
|
-
"agent-iam": {
|
|
24
|
-
name: "agent-iam",
|
|
25
|
-
description: "Capability-based credential broker for AI agents",
|
|
26
|
-
category: "security",
|
|
27
|
-
globalOnly: true,
|
|
28
|
-
},
|
|
29
|
-
openswarm: {
|
|
30
|
-
name: "openswarm",
|
|
31
|
-
description: "Multi-agent terminal UI and MAP server host",
|
|
32
|
-
category: "interface",
|
|
33
|
-
},
|
|
34
|
-
openhive: {
|
|
35
|
-
name: "openhive",
|
|
36
|
-
description: "Self-hostable social network and coordination hub for agents",
|
|
37
|
-
category: "interface",
|
|
38
|
-
},
|
|
39
18
|
"cognitive-core": {
|
|
40
19
|
name: "cognitive-core",
|
|
41
20
|
description: "Learning system — trajectories to playbooks to guidance",
|
|
@@ -51,17 +30,25 @@ export const PACKAGES = {
|
|
|
51
30
|
description: "Versioned skill extraction, evolution, and serving",
|
|
52
31
|
category: "learning",
|
|
53
32
|
},
|
|
33
|
+
openhive: {
|
|
34
|
+
name: "openhive",
|
|
35
|
+
description: "Self-hostable social network and coordination hub for agents",
|
|
36
|
+
category: "interface",
|
|
37
|
+
},
|
|
54
38
|
openteams: {
|
|
55
39
|
name: "openteams",
|
|
56
40
|
description: "Team topology definitions and agent role generation",
|
|
57
41
|
category: "orchestration",
|
|
58
|
-
globalOnly: true,
|
|
59
42
|
},
|
|
60
43
|
sessionlog: {
|
|
61
44
|
name: "sessionlog",
|
|
62
45
|
description: "Git-integrated session capture with rewind and search",
|
|
63
46
|
category: "observability",
|
|
64
|
-
|
|
47
|
+
},
|
|
48
|
+
"claude-code-swarm": {
|
|
49
|
+
name: "claude-code-swarm",
|
|
50
|
+
description: "Claude Code plugin for agent team orchestration with openteams templates",
|
|
51
|
+
category: "orchestration",
|
|
65
52
|
},
|
|
66
53
|
};
|
|
67
54
|
export const BUNDLES = {
|
|
@@ -69,33 +56,29 @@ export const BUNDLES = {
|
|
|
69
56
|
name: "solo",
|
|
70
57
|
label: "Local agent development",
|
|
71
58
|
description: "Single developer running local agents",
|
|
72
|
-
packages: ["
|
|
59
|
+
packages: ["opentasks", "minimem"],
|
|
73
60
|
},
|
|
74
61
|
team: {
|
|
75
62
|
name: "team",
|
|
76
63
|
label: "Multi-agent team with learning",
|
|
77
64
|
description: "Agents that learn and share skills across a team",
|
|
78
65
|
packages: [
|
|
79
|
-
"macro-agent",
|
|
80
66
|
"opentasks",
|
|
81
67
|
"minimem",
|
|
82
|
-
"agent-iam",
|
|
83
68
|
"cognitive-core",
|
|
84
69
|
"skill-tree",
|
|
85
70
|
],
|
|
86
71
|
},
|
|
87
72
|
platform: {
|
|
88
73
|
name: "platform",
|
|
89
|
-
label: "Full
|
|
90
|
-
description: "Complete platform with
|
|
74
|
+
label: "Full platform with learning and workflows",
|
|
75
|
+
description: "Complete platform with learning, skills, and GitHub automation",
|
|
91
76
|
packages: [
|
|
92
|
-
"macro-agent",
|
|
93
77
|
"opentasks",
|
|
94
78
|
"minimem",
|
|
95
|
-
"agent-iam",
|
|
96
79
|
"cognitive-core",
|
|
97
80
|
"skill-tree",
|
|
98
|
-
"
|
|
81
|
+
"self-driving-repo",
|
|
99
82
|
"openhive",
|
|
100
83
|
],
|
|
101
84
|
},
|
|
@@ -103,26 +86,10 @@ export const BUNDLES = {
|
|
|
103
86
|
name: "github",
|
|
104
87
|
label: "Autonomous GitHub workflows",
|
|
105
88
|
description: "Event-driven agents for GitHub SDLC automation",
|
|
106
|
-
packages: ["self-driving-repo", "opentasks"
|
|
89
|
+
packages: ["self-driving-repo", "opentasks"],
|
|
107
90
|
},
|
|
108
91
|
};
|
|
109
92
|
export const INTEGRATIONS = [
|
|
110
|
-
{
|
|
111
|
-
packages: ["macro-agent", "opentasks"],
|
|
112
|
-
description: "macro-agent uses opentasks as task backend",
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
packages: ["macro-agent", "multi-agent-protocol"],
|
|
116
|
-
description: "macro-agent implements MAP for agent observation",
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
packages: ["openswarm", "macro-agent"],
|
|
120
|
-
description: "openswarm's macro-agent plugin provides TUI management",
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
packages: ["openhive", "openswarm"],
|
|
124
|
-
description: "openhive hosts openswarm instances and acts as MAP Hub",
|
|
125
|
-
},
|
|
126
93
|
{
|
|
127
94
|
packages: ["cognitive-core", "minimem"],
|
|
128
95
|
description: "cognitive-core uses minimem as search layer",
|
|
@@ -132,8 +99,16 @@ export const INTEGRATIONS = [
|
|
|
132
99
|
description: "skill-tree delegates to cognitive-core for batch learning",
|
|
133
100
|
},
|
|
134
101
|
{
|
|
135
|
-
packages: ["
|
|
136
|
-
description: "
|
|
102
|
+
packages: ["claude-code-swarm", "openteams"],
|
|
103
|
+
description: "claude-code-swarm uses openteams for team topology definitions",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
packages: ["claude-code-swarm", "multi-agent-protocol"],
|
|
107
|
+
description: "claude-code-swarm uses MAP for external agent observability",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
packages: ["claude-code-swarm", "sessionlog"],
|
|
111
|
+
description: "claude-code-swarm bridges sessionlog data to MAP via trajectory protocol",
|
|
137
112
|
},
|
|
138
113
|
];
|
|
139
114
|
/** Get all package names in a bundle */
|
|
@@ -2,8 +2,8 @@ import { describe, it, expect } from "vitest";
|
|
|
2
2
|
import { PACKAGES, BUNDLES, INTEGRATIONS, getBundlePackages, getActiveIntegrations, getNewIntegrations, getLostIntegrations, getNpmName, isKnownPackage, getAllPackageNames, } from "./registry.js";
|
|
3
3
|
describe("registry", () => {
|
|
4
4
|
describe("PACKAGES", () => {
|
|
5
|
-
it("contains all
|
|
6
|
-
expect(Object.keys(PACKAGES)).toHaveLength(
|
|
5
|
+
it("contains all 10 packages", () => {
|
|
6
|
+
expect(Object.keys(PACKAGES)).toHaveLength(10);
|
|
7
7
|
});
|
|
8
8
|
it("every package has name, description, and category", () => {
|
|
9
9
|
for (const [key, pkg] of Object.entries(PACKAGES)) {
|
|
@@ -12,23 +12,25 @@ describe("registry", () => {
|
|
|
12
12
|
expect(pkg.category).toBeTruthy();
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
|
-
it("
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
expect(PACKAGES["openteams"].globalOnly).toBe(true);
|
|
20
|
-
expect(PACKAGES["sessionlog"].globalOnly).toBe(true);
|
|
15
|
+
it("no packages are marked globalOnly", () => {
|
|
16
|
+
for (const pkg of Object.values(PACKAGES)) {
|
|
17
|
+
expect(pkg.globalOnly).toBeUndefined();
|
|
18
|
+
}
|
|
21
19
|
});
|
|
22
20
|
it("multi-agent-protocol has npmName override", () => {
|
|
23
21
|
expect(PACKAGES["multi-agent-protocol"].npmName).toBe("@multi-agent-protocol/sdk");
|
|
24
22
|
});
|
|
25
23
|
it("most packages do not have npmName", () => {
|
|
26
|
-
expect(PACKAGES["
|
|
24
|
+
expect(PACKAGES["opentasks"].npmName).toBeUndefined();
|
|
27
25
|
expect(PACKAGES["openteams"].npmName).toBeUndefined();
|
|
28
26
|
});
|
|
29
|
-
it("
|
|
30
|
-
expect(PACKAGES["
|
|
31
|
-
expect(PACKAGES["
|
|
27
|
+
it("openteams and sessionlog have project-level config", () => {
|
|
28
|
+
expect(PACKAGES["openteams"].globalOnly).toBeUndefined();
|
|
29
|
+
expect(PACKAGES["sessionlog"].globalOnly).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
it("claude-code-swarm is an orchestration package", () => {
|
|
32
|
+
expect(PACKAGES["claude-code-swarm"]).toBeDefined();
|
|
33
|
+
expect(PACKAGES["claude-code-swarm"].category).toBe("orchestration");
|
|
32
34
|
});
|
|
33
35
|
});
|
|
34
36
|
describe("BUNDLES", () => {
|
|
@@ -38,10 +40,8 @@ describe("registry", () => {
|
|
|
38
40
|
});
|
|
39
41
|
it("solo bundle has the right packages", () => {
|
|
40
42
|
expect(BUNDLES.solo.packages).toEqual([
|
|
41
|
-
"macro-agent",
|
|
42
43
|
"opentasks",
|
|
43
44
|
"minimem",
|
|
44
|
-
"agent-iam",
|
|
45
45
|
]);
|
|
46
46
|
});
|
|
47
47
|
it("team bundle is a superset of solo", () => {
|
|
@@ -55,13 +55,12 @@ describe("registry", () => {
|
|
|
55
55
|
for (const pkg of BUNDLES.team.packages) {
|
|
56
56
|
expect(BUNDLES.platform.packages).toContain(pkg);
|
|
57
57
|
}
|
|
58
|
-
expect(BUNDLES.platform.packages).toContain("
|
|
58
|
+
expect(BUNDLES.platform.packages).toContain("self-driving-repo");
|
|
59
59
|
expect(BUNDLES.platform.packages).toContain("openhive");
|
|
60
60
|
});
|
|
61
61
|
it("github bundle has self-driving-repo", () => {
|
|
62
62
|
expect(BUNDLES.github.packages).toContain("self-driving-repo");
|
|
63
63
|
expect(BUNDLES.github.packages).toContain("opentasks");
|
|
64
|
-
expect(BUNDLES.github.packages).toContain("agent-iam");
|
|
65
64
|
});
|
|
66
65
|
it("all bundle packages reference known packages", () => {
|
|
67
66
|
for (const bundle of Object.values(BUNDLES)) {
|
|
@@ -102,34 +101,24 @@ describe("registry", () => {
|
|
|
102
101
|
expect(getActiveIntegrations([])).toEqual([]);
|
|
103
102
|
});
|
|
104
103
|
it("returns nothing for single package", () => {
|
|
105
|
-
expect(getActiveIntegrations(["
|
|
104
|
+
expect(getActiveIntegrations(["opentasks"])).toEqual([]);
|
|
106
105
|
});
|
|
107
106
|
it("returns integration when both packages are installed", () => {
|
|
108
|
-
const result = getActiveIntegrations(["
|
|
107
|
+
const result = getActiveIntegrations(["cognitive-core", "minimem"]);
|
|
109
108
|
expect(result).toHaveLength(1);
|
|
110
|
-
expect(result[0].packages).toEqual(["
|
|
111
|
-
});
|
|
112
|
-
it("returns multiple integrations for the solo bundle", () => {
|
|
113
|
-
const result = getActiveIntegrations(BUNDLES.solo.packages);
|
|
114
|
-
expect(result.length).toBeGreaterThanOrEqual(2);
|
|
115
|
-
// Should include macro-agent+opentasks and agent-iam+macro-agent
|
|
116
|
-
const pairs = result.map((i) => i.packages.join("+"));
|
|
117
|
-
expect(pairs).toContain("macro-agent+opentasks");
|
|
118
|
-
expect(pairs).toContain("agent-iam+macro-agent");
|
|
109
|
+
expect(result[0].packages).toEqual(["cognitive-core", "minimem"]);
|
|
119
110
|
});
|
|
120
|
-
it("returns
|
|
111
|
+
it("returns multiple integrations for the platform bundle", () => {
|
|
121
112
|
const result = getActiveIntegrations(BUNDLES.platform.packages);
|
|
122
|
-
|
|
123
|
-
// so it should activate most integrations
|
|
124
|
-
expect(result.length).toBeGreaterThanOrEqual(5);
|
|
113
|
+
expect(result.length).toBeGreaterThanOrEqual(2);
|
|
125
114
|
});
|
|
126
115
|
});
|
|
127
116
|
describe("getNewIntegrations", () => {
|
|
128
117
|
it("returns integrations that would activate with a new package", () => {
|
|
129
|
-
const current = ["
|
|
130
|
-
const result = getNewIntegrations(current, "
|
|
118
|
+
const current = ["cognitive-core"];
|
|
119
|
+
const result = getNewIntegrations(current, "minimem");
|
|
131
120
|
expect(result).toHaveLength(1);
|
|
132
|
-
expect(result[0].packages).toEqual(["
|
|
121
|
+
expect(result[0].packages).toEqual(["cognitive-core", "minimem"]);
|
|
133
122
|
});
|
|
134
123
|
it("returns nothing if no new integrations would activate", () => {
|
|
135
124
|
const current = ["minimem"];
|
|
@@ -137,22 +126,22 @@ describe("registry", () => {
|
|
|
137
126
|
expect(result).toEqual([]);
|
|
138
127
|
});
|
|
139
128
|
it("returns multiple integrations when package connects to several", () => {
|
|
140
|
-
const current = ["
|
|
141
|
-
const result = getNewIntegrations(current, "
|
|
142
|
-
expect(result
|
|
129
|
+
const current = ["minimem", "skill-tree"];
|
|
130
|
+
const result = getNewIntegrations(current, "cognitive-core");
|
|
131
|
+
expect(result).toHaveLength(2);
|
|
143
132
|
});
|
|
144
133
|
it("works regardless of package order in integration definition", () => {
|
|
145
|
-
//
|
|
146
|
-
const current = ["
|
|
147
|
-
const result = getNewIntegrations(current, "
|
|
134
|
+
// cognitive-core+minimem is defined as ["cognitive-core", "minimem"]
|
|
135
|
+
const current = ["minimem"];
|
|
136
|
+
const result = getNewIntegrations(current, "cognitive-core");
|
|
148
137
|
expect(result).toHaveLength(1);
|
|
149
138
|
});
|
|
150
139
|
});
|
|
151
140
|
describe("getLostIntegrations", () => {
|
|
152
141
|
it("returns integrations that would break when removing a package", () => {
|
|
153
|
-
const current = ["
|
|
154
|
-
const result = getLostIntegrations(current, "
|
|
155
|
-
// Removing
|
|
142
|
+
const current = ["cognitive-core", "minimem", "skill-tree"];
|
|
143
|
+
const result = getLostIntegrations(current, "cognitive-core");
|
|
144
|
+
// Removing cognitive-core breaks cognitive-core+minimem and cognitive-core+skill-tree
|
|
156
145
|
expect(result).toHaveLength(2);
|
|
157
146
|
});
|
|
158
147
|
it("returns nothing if removing a package with no active integrations", () => {
|
|
@@ -163,9 +152,9 @@ describe("registry", () => {
|
|
|
163
152
|
});
|
|
164
153
|
describe("isKnownPackage", () => {
|
|
165
154
|
it("returns true for known packages", () => {
|
|
166
|
-
expect(isKnownPackage("
|
|
155
|
+
expect(isKnownPackage("opentasks")).toBe(true);
|
|
167
156
|
expect(isKnownPackage("minimem")).toBe(true);
|
|
168
|
-
expect(isKnownPackage("
|
|
157
|
+
expect(isKnownPackage("openhive")).toBe(true);
|
|
169
158
|
});
|
|
170
159
|
it("returns false for unknown packages", () => {
|
|
171
160
|
expect(isKnownPackage("not-a-package")).toBe(false);
|
|
@@ -177,7 +166,7 @@ describe("registry", () => {
|
|
|
177
166
|
expect(getNpmName("multi-agent-protocol")).toBe("@multi-agent-protocol/sdk");
|
|
178
167
|
});
|
|
179
168
|
it("returns registry key when npmName is not set", () => {
|
|
180
|
-
expect(getNpmName("
|
|
169
|
+
expect(getNpmName("opentasks")).toBe("opentasks");
|
|
181
170
|
expect(getNpmName("openteams")).toBe("openteams");
|
|
182
171
|
expect(getNpmName("sessionlog")).toBe("sessionlog");
|
|
183
172
|
});
|
|
@@ -186,14 +175,14 @@ describe("registry", () => {
|
|
|
186
175
|
});
|
|
187
176
|
});
|
|
188
177
|
describe("getAllPackageNames", () => {
|
|
189
|
-
it("returns all
|
|
178
|
+
it("returns all 10 package names", () => {
|
|
190
179
|
const names = getAllPackageNames();
|
|
191
|
-
expect(names).toHaveLength(
|
|
192
|
-
expect(names).toContain("macro-agent");
|
|
180
|
+
expect(names).toHaveLength(10);
|
|
193
181
|
expect(names).toContain("minimem");
|
|
194
182
|
expect(names).toContain("self-driving-repo");
|
|
195
183
|
expect(names).toContain("openteams");
|
|
196
184
|
expect(names).toContain("sessionlog");
|
|
185
|
+
expect(names).toContain("claude-code-swarm");
|
|
197
186
|
});
|
|
198
187
|
});
|
|
199
188
|
});
|
package/dist/packages/setup.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface InitContext {
|
|
|
7
7
|
embeddingProvider: "openai" | "gemini" | "local" | null;
|
|
8
8
|
/** Stored API keys (provider → key) */
|
|
9
9
|
apiKeys: Record<string, string>;
|
|
10
|
+
/** Whether to nest project configs under .swarm/ (default true) */
|
|
11
|
+
usePrefix: boolean;
|
|
10
12
|
}
|
|
11
13
|
export interface GlobalContext {
|
|
12
14
|
/** All selected packages */
|
|
@@ -28,15 +30,20 @@ export interface SetupResult {
|
|
|
28
30
|
success: boolean;
|
|
29
31
|
message?: string;
|
|
30
32
|
}
|
|
31
|
-
/**
|
|
33
|
+
/** Root directory for all swarmkit project-level config */
|
|
34
|
+
export declare const PROJECT_ROOT = ".swarm";
|
|
35
|
+
/** Config directories with .swarm/ prefix (default layout) */
|
|
32
36
|
export declare const PROJECT_CONFIG_DIRS: Record<string, string>;
|
|
37
|
+
/** Config directories without prefix (flat layout, --no-prefix) */
|
|
38
|
+
export declare const FLAT_PROJECT_CONFIG_DIRS: Record<string, string>;
|
|
39
|
+
/** Get config dirs for the given mode */
|
|
40
|
+
export declare function projectConfigDirs(usePrefix: boolean): Record<string, string>;
|
|
33
41
|
/**
|
|
34
42
|
* Project-level packages in correct init order.
|
|
35
|
-
* Order matters: minimem before cognitive-core (runtime detection)
|
|
36
|
-
* opentasks before macro-agent (task backend wiring).
|
|
43
|
+
* Order matters: minimem before cognitive-core (runtime detection).
|
|
37
44
|
*/
|
|
38
45
|
export declare const PROJECT_INIT_ORDER: string[];
|
|
39
|
-
/** Check whether a package is already initialized in a project */
|
|
46
|
+
/** Check whether a package is already initialized in a project (checks both layouts) */
|
|
40
47
|
export declare function isProjectInit(cwd: string, pkg: string): boolean;
|
|
41
48
|
/** Initialize a single project-level package */
|
|
42
49
|
export declare function initProjectPackage(pkg: string, ctx: InitContext): Promise<SetupResult>;
|