claude-code-swarm 0.3.3 → 0.3.5
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +22 -1
- package/.claude-plugin/run-agent-inbox-mcp.sh +76 -0
- package/.claude-plugin/run-minimem-mcp.sh +98 -0
- package/.claude-plugin/run-opentasks-mcp.sh +65 -0
- package/CLAUDE.md +200 -36
- package/README.md +65 -0
- package/e2e/helpers/cleanup.mjs +17 -3
- package/e2e/helpers/map-mock-server.mjs +201 -25
- package/e2e/helpers/sidecar.mjs +222 -0
- package/e2e/helpers/workspace.mjs +2 -1
- package/e2e/tier5-sidecar-inbox.test.mjs +900 -0
- package/e2e/tier6-inbox-mcp.test.mjs +173 -0
- package/e2e/tier6-live-agent.test.mjs +759 -0
- package/e2e/vitest.config.e2e.mjs +1 -1
- package/hooks/hooks.json +15 -8
- package/package.json +13 -1
- package/references/agent-inbox/CLAUDE.md +151 -0
- package/references/agent-inbox/README.md +238 -0
- package/references/agent-inbox/docs/CLAUDE-CODE-SWARM-PROPOSAL.md +137 -0
- package/references/agent-inbox/docs/DESIGN.md +1156 -0
- package/references/agent-inbox/hooks/inbox-hook.mjs +119 -0
- package/references/agent-inbox/hooks/register-hook.mjs +69 -0
- package/references/agent-inbox/package-lock.json +3347 -0
- package/references/agent-inbox/package.json +58 -0
- package/references/agent-inbox/rules/agent-inbox.md +78 -0
- package/references/agent-inbox/src/federation/address.ts +61 -0
- package/references/agent-inbox/src/federation/connection-manager.ts +573 -0
- package/references/agent-inbox/src/federation/delivery-queue.ts +222 -0
- package/references/agent-inbox/src/federation/index.ts +6 -0
- package/references/agent-inbox/src/federation/routing-engine.ts +188 -0
- package/references/agent-inbox/src/federation/trust.ts +71 -0
- package/references/agent-inbox/src/index.ts +390 -0
- package/references/agent-inbox/src/ipc/ipc-server.ts +207 -0
- package/references/agent-inbox/src/jsonrpc/mail-server.ts +382 -0
- package/references/agent-inbox/src/map/map-client.ts +414 -0
- package/references/agent-inbox/src/mcp/mcp-server.ts +272 -0
- package/references/agent-inbox/src/mesh/delivery-bridge.ts +110 -0
- package/references/agent-inbox/src/mesh/mesh-connector.ts +41 -0
- package/references/agent-inbox/src/mesh/mesh-transport.ts +157 -0
- package/references/agent-inbox/src/mesh/type-mapper.ts +239 -0
- package/references/agent-inbox/src/push/notifier.ts +233 -0
- package/references/agent-inbox/src/registry/warm-registry.ts +255 -0
- package/references/agent-inbox/src/router/message-router.ts +175 -0
- package/references/agent-inbox/src/storage/interface.ts +48 -0
- package/references/agent-inbox/src/storage/memory.ts +145 -0
- package/references/agent-inbox/src/storage/sqlite.ts +671 -0
- package/references/agent-inbox/src/traceability/traceability.ts +183 -0
- package/references/agent-inbox/src/types.ts +303 -0
- package/references/agent-inbox/test/federation/address.test.ts +101 -0
- package/references/agent-inbox/test/federation/connection-manager.test.ts +546 -0
- package/references/agent-inbox/test/federation/delivery-queue.test.ts +159 -0
- package/references/agent-inbox/test/federation/integration.test.ts +857 -0
- package/references/agent-inbox/test/federation/routing-engine.test.ts +117 -0
- package/references/agent-inbox/test/federation/sdk-integration.test.ts +744 -0
- package/references/agent-inbox/test/federation/trust.test.ts +89 -0
- package/references/agent-inbox/test/ipc-jsonrpc.test.ts +113 -0
- package/references/agent-inbox/test/ipc-server.test.ts +197 -0
- package/references/agent-inbox/test/mail-server.test.ts +285 -0
- package/references/agent-inbox/test/map-client.test.ts +408 -0
- package/references/agent-inbox/test/mesh/delivery-bridge.test.ts +178 -0
- package/references/agent-inbox/test/mesh/e2e-mesh.test.ts +527 -0
- package/references/agent-inbox/test/mesh/e2e-real-meshpeer.test.ts +629 -0
- package/references/agent-inbox/test/mesh/federation-mesh.test.ts +269 -0
- package/references/agent-inbox/test/mesh/mesh-connector.test.ts +66 -0
- package/references/agent-inbox/test/mesh/mesh-transport.test.ts +191 -0
- package/references/agent-inbox/test/mesh/meshpeer-integration.test.ts +442 -0
- package/references/agent-inbox/test/mesh/mock-mesh.ts +125 -0
- package/references/agent-inbox/test/mesh/mock-meshpeer.ts +266 -0
- package/references/agent-inbox/test/mesh/type-mapper.test.ts +226 -0
- package/references/agent-inbox/test/message-router.test.ts +184 -0
- package/references/agent-inbox/test/push-notifier.test.ts +139 -0
- package/references/agent-inbox/test/registry/warm-registry.test.ts +171 -0
- package/references/agent-inbox/test/sqlite-prefix.test.ts +192 -0
- package/references/agent-inbox/test/sqlite-storage.test.ts +243 -0
- package/references/agent-inbox/test/storage.test.ts +196 -0
- package/references/agent-inbox/test/traceability.test.ts +123 -0
- package/references/agent-inbox/test/wake.test.ts +330 -0
- package/references/agent-inbox/tsconfig.json +20 -0
- package/references/agent-inbox/tsup.config.ts +10 -0
- package/references/agent-inbox/vitest.config.ts +8 -0
- package/references/minimem/.claude/settings.json +7 -0
- package/references/minimem/.sudocode/issues.jsonl +18 -0
- package/references/minimem/.sudocode/specs.jsonl +1 -0
- package/references/minimem/CLAUDE.md +329 -0
- package/references/minimem/README.md +565 -0
- package/references/minimem/claude-plugin/.claude-plugin/plugin.json +10 -0
- package/references/minimem/claude-plugin/.mcp.json +7 -0
- package/references/minimem/claude-plugin/README.md +158 -0
- package/references/minimem/claude-plugin/commands/recall.md +47 -0
- package/references/minimem/claude-plugin/commands/remember.md +41 -0
- package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +272 -0
- package/references/minimem/claude-plugin/hooks/hooks.json +27 -0
- package/references/minimem/claude-plugin/hooks/session-end.sh +86 -0
- package/references/minimem/claude-plugin/hooks/session-start.sh +85 -0
- package/references/minimem/claude-plugin/skills/memory/SKILL.md +108 -0
- package/references/minimem/media/banner.png +0 -0
- package/references/minimem/package-lock.json +5373 -0
- package/references/minimem/package.json +76 -0
- package/references/minimem/scripts/postbuild.js +49 -0
- package/references/minimem/src/__tests__/edge-cases.test.ts +371 -0
- package/references/minimem/src/__tests__/errors.test.ts +265 -0
- package/references/minimem/src/__tests__/helpers.ts +199 -0
- package/references/minimem/src/__tests__/internal.test.ts +407 -0
- package/references/minimem/src/__tests__/knowledge-frontmatter.test.ts +148 -0
- package/references/minimem/src/__tests__/knowledge.test.ts +148 -0
- package/references/minimem/src/__tests__/minimem.integration.test.ts +1127 -0
- package/references/minimem/src/__tests__/session.test.ts +190 -0
- package/references/minimem/src/cli/__tests__/commands.test.ts +760 -0
- package/references/minimem/src/cli/__tests__/contained-layout.test.ts +286 -0
- package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +141 -0
- package/references/minimem/src/cli/commands/append.ts +76 -0
- package/references/minimem/src/cli/commands/config.ts +262 -0
- package/references/minimem/src/cli/commands/conflicts.ts +415 -0
- package/references/minimem/src/cli/commands/daemon.ts +169 -0
- package/references/minimem/src/cli/commands/index.ts +12 -0
- package/references/minimem/src/cli/commands/init.ts +166 -0
- package/references/minimem/src/cli/commands/mcp.ts +221 -0
- package/references/minimem/src/cli/commands/push-pull.ts +213 -0
- package/references/minimem/src/cli/commands/search.ts +223 -0
- package/references/minimem/src/cli/commands/status.ts +84 -0
- package/references/minimem/src/cli/commands/store.ts +189 -0
- package/references/minimem/src/cli/commands/sync-init.ts +290 -0
- package/references/minimem/src/cli/commands/sync.ts +70 -0
- package/references/minimem/src/cli/commands/upsert.ts +197 -0
- package/references/minimem/src/cli/config.ts +611 -0
- package/references/minimem/src/cli/index.ts +299 -0
- package/references/minimem/src/cli/shared.ts +189 -0
- package/references/minimem/src/cli/sync/__tests__/central.test.ts +152 -0
- package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +209 -0
- package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +118 -0
- package/references/minimem/src/cli/sync/__tests__/detection.test.ts +207 -0
- package/references/minimem/src/cli/sync/__tests__/integration.test.ts +476 -0
- package/references/minimem/src/cli/sync/__tests__/registry.test.ts +363 -0
- package/references/minimem/src/cli/sync/__tests__/state.test.ts +255 -0
- package/references/minimem/src/cli/sync/__tests__/validation.test.ts +193 -0
- package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +178 -0
- package/references/minimem/src/cli/sync/central.ts +292 -0
- package/references/minimem/src/cli/sync/conflicts.ts +205 -0
- package/references/minimem/src/cli/sync/daemon.ts +407 -0
- package/references/minimem/src/cli/sync/detection.ts +138 -0
- package/references/minimem/src/cli/sync/index.ts +107 -0
- package/references/minimem/src/cli/sync/operations.ts +373 -0
- package/references/minimem/src/cli/sync/registry.ts +279 -0
- package/references/minimem/src/cli/sync/state.ts +358 -0
- package/references/minimem/src/cli/sync/validation.ts +206 -0
- package/references/minimem/src/cli/sync/watcher.ts +237 -0
- package/references/minimem/src/cli/version.ts +34 -0
- package/references/minimem/src/core/index.ts +9 -0
- package/references/minimem/src/core/indexer.ts +628 -0
- package/references/minimem/src/core/searcher.ts +221 -0
- package/references/minimem/src/db/schema.ts +183 -0
- package/references/minimem/src/db/sqlite-vec.ts +24 -0
- package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +431 -0
- package/references/minimem/src/embeddings/batch-gemini.ts +392 -0
- package/references/minimem/src/embeddings/batch-openai.ts +409 -0
- package/references/minimem/src/embeddings/embeddings.ts +434 -0
- package/references/minimem/src/index.ts +132 -0
- package/references/minimem/src/internal.ts +299 -0
- package/references/minimem/src/minimem.ts +1291 -0
- package/references/minimem/src/search/__tests__/hybrid.test.ts +247 -0
- package/references/minimem/src/search/graph.ts +234 -0
- package/references/minimem/src/search/hybrid.ts +151 -0
- package/references/minimem/src/search/search.ts +256 -0
- package/references/minimem/src/server/__tests__/mcp.test.ts +347 -0
- package/references/minimem/src/server/__tests__/tools.test.ts +364 -0
- package/references/minimem/src/server/mcp.ts +326 -0
- package/references/minimem/src/server/tools.ts +720 -0
- package/references/minimem/src/session.ts +460 -0
- package/references/minimem/src/store/__tests__/manifest.test.ts +177 -0
- package/references/minimem/src/store/__tests__/materialize.test.ts +52 -0
- package/references/minimem/src/store/__tests__/store-graph.test.ts +228 -0
- package/references/minimem/src/store/index.ts +27 -0
- package/references/minimem/src/store/manifest.ts +203 -0
- package/references/minimem/src/store/materialize.ts +185 -0
- package/references/minimem/src/store/store-graph.ts +252 -0
- package/references/minimem/tsconfig.json +19 -0
- package/references/minimem/tsup.config.ts +26 -0
- package/references/minimem/vitest.config.ts +29 -0
- package/references/openteams/src/cli/generate.ts +23 -1
- package/references/openteams/src/generators/agent-prompt-generator.test.ts +94 -0
- package/references/openteams/src/generators/agent-prompt-generator.ts +42 -13
- package/references/openteams/src/generators/package-generator.ts +9 -1
- package/references/openteams/src/generators/skill-generator.test.ts +28 -0
- package/references/openteams/src/generators/skill-generator.ts +10 -4
- package/references/skill-tree/.claude/settings.json +6 -0
- package/references/skill-tree/.sudocode/issues.jsonl +19 -0
- package/references/skill-tree/.sudocode/specs.jsonl +3 -0
- package/references/skill-tree/CLAUDE.md +132 -0
- package/references/skill-tree/README.md +396 -0
- package/references/skill-tree/docs/GAPS_v1.md +221 -0
- package/references/skill-tree/docs/INTEGRATION_PLAN.md +467 -0
- package/references/skill-tree/docs/TODOS.md +91 -0
- package/references/skill-tree/docs/anthropic_skill_guide.md +1364 -0
- package/references/skill-tree/docs/design/federated-skill-trees.md +524 -0
- package/references/skill-tree/docs/design/multi-agent-sync.md +759 -0
- package/references/skill-tree/docs/scraper/BRAINSTORM.md +583 -0
- package/references/skill-tree/docs/scraper/POC_PLAN.md +420 -0
- package/references/skill-tree/docs/scraper/README.md +170 -0
- package/references/skill-tree/examples/basic-usage.ts +157 -0
- package/references/skill-tree/package-lock.json +1852 -0
- package/references/skill-tree/package.json +66 -0
- package/references/skill-tree/plan.md +78 -0
- package/references/skill-tree/scraper/README.md +123 -0
- package/references/skill-tree/scraper/docs/DESIGN.md +683 -0
- package/references/skill-tree/scraper/docs/PLAN.md +336 -0
- package/references/skill-tree/scraper/drizzle.config.ts +10 -0
- package/references/skill-tree/scraper/package-lock.json +6329 -0
- package/references/skill-tree/scraper/package.json +68 -0
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +7 -0
- package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +7 -0
- package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +27 -0
- package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +21 -0
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +54 -0
- package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +24 -0
- package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +93 -0
- package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +22 -0
- package/references/skill-tree/scraper/tsup.config.ts +14 -0
- package/references/skill-tree/scraper/vitest.config.ts +17 -0
- package/references/skill-tree/scripts/convert-to-vitest.ts +166 -0
- package/references/skill-tree/skills/skill-writer/SKILL.md +339 -0
- package/references/skill-tree/skills/skill-writer/references/examples.md +326 -0
- package/references/skill-tree/skills/skill-writer/references/patterns.md +210 -0
- package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +123 -0
- package/references/skill-tree/test/run-all.ts +106 -0
- package/references/skill-tree/test/utils.ts +128 -0
- package/references/skill-tree/vitest.config.ts +16 -0
- package/references/swarmkit/src/commands/init/phases/configure.ts +0 -22
- package/references/swarmkit/src/commands/init/phases/global-setup.ts +5 -3
- package/references/swarmkit/src/commands/init/wizard.ts +2 -2
- package/references/swarmkit/src/packages/setup.test.ts +53 -7
- package/references/swarmkit/src/packages/setup.ts +37 -1
- package/scripts/bootstrap.mjs +26 -1
- package/scripts/generate-agents.mjs +5 -1
- package/scripts/map-hook.mjs +97 -64
- package/scripts/map-sidecar.mjs +179 -25
- package/scripts/team-loader.mjs +12 -41
- package/skills/swarm/SKILL.md +89 -25
- package/src/__tests__/agent-generator.test.mjs +6 -13
- package/src/__tests__/bootstrap.test.mjs +124 -1
- package/src/__tests__/config.test.mjs +200 -27
- package/src/__tests__/e2e-live-map.test.mjs +536 -0
- package/src/__tests__/e2e-mesh-sidecar.test.mjs +570 -0
- package/src/__tests__/e2e-native-task-hooks.test.mjs +376 -0
- package/src/__tests__/e2e-sidecar-bridge.test.mjs +477 -0
- package/src/__tests__/helpers.mjs +13 -0
- package/src/__tests__/inbox.test.mjs +22 -89
- package/src/__tests__/index.test.mjs +35 -9
- package/src/__tests__/integration.test.mjs +513 -0
- package/src/__tests__/map-events.test.mjs +514 -150
- package/src/__tests__/mesh-connection.test.mjs +308 -0
- package/src/__tests__/opentasks-client.test.mjs +517 -0
- package/src/__tests__/paths.test.mjs +185 -41
- package/src/__tests__/sidecar-client.test.mjs +35 -0
- package/src/__tests__/sidecar-server.test.mjs +124 -0
- package/src/__tests__/skilltree-client.test.mjs +80 -0
- package/src/agent-generator.mjs +104 -33
- package/src/bootstrap.mjs +150 -10
- package/src/config.mjs +81 -17
- package/src/context-output.mjs +58 -8
- package/src/inbox.mjs +9 -54
- package/src/index.mjs +39 -8
- package/src/map-connection.mjs +4 -3
- package/src/map-events.mjs +350 -80
- package/src/mesh-connection.mjs +148 -0
- package/src/opentasks-client.mjs +269 -0
- package/src/paths.mjs +182 -27
- package/src/sessionlog.mjs +14 -9
- package/src/sidecar-client.mjs +81 -27
- package/src/sidecar-server.mjs +175 -16
- package/src/skilltree-client.mjs +173 -0
- package/src/template.mjs +68 -4
- package/vitest.config.mjs +1 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StoreGraph: meta-layer above Minimem for managing linked stores.
|
|
3
|
+
*
|
|
4
|
+
* A StoreGraph resolves a store and its dependencies (depth 1),
|
|
5
|
+
* materializes them as needed, and produces an array of MemoryInstance
|
|
6
|
+
* objects that can be passed to MemoryToolExecutor or used directly.
|
|
7
|
+
*
|
|
8
|
+
* The Minimem class is unchanged — StoreGraph just orchestrates
|
|
9
|
+
* multiple independent Minimem instances.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
|
|
14
|
+
import { Minimem, type MinimemConfig } from "../minimem.js";
|
|
15
|
+
import type { MemoryInstance } from "../server/tools.js";
|
|
16
|
+
import {
|
|
17
|
+
loadManifest,
|
|
18
|
+
getLinkedStoreNames,
|
|
19
|
+
resolveStore,
|
|
20
|
+
resolveStoreName,
|
|
21
|
+
type StoreManifest,
|
|
22
|
+
type StoreDefinition,
|
|
23
|
+
} from "./manifest.js";
|
|
24
|
+
import { materializeStore, type MaterializeResult } from "./materialize.js";
|
|
25
|
+
|
|
26
|
+
export type StoreGraphOptions = {
|
|
27
|
+
/** Path to the global manifest file (default: ~/.config/minimem/stores.json) */
|
|
28
|
+
manifestPath?: string;
|
|
29
|
+
/** Factory to create a MinimemConfig for a given store directory */
|
|
30
|
+
configFactory?: (memoryDir: string, storeName: string) => Promise<MinimemConfig>;
|
|
31
|
+
/** Debug logging */
|
|
32
|
+
debug?: (message: string) => void;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type ResolvedStore = {
|
|
36
|
+
name: string;
|
|
37
|
+
definition: StoreDefinition;
|
|
38
|
+
materialization: MaterializeResult;
|
|
39
|
+
instance: Minimem;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export class StoreGraph {
|
|
43
|
+
private manifest: StoreManifest;
|
|
44
|
+
private resolved: Map<string, ResolvedStore> = new Map();
|
|
45
|
+
private configFactory: (memoryDir: string, storeName: string) => Promise<MinimemConfig>;
|
|
46
|
+
private debug?: (message: string) => void;
|
|
47
|
+
|
|
48
|
+
private constructor(
|
|
49
|
+
manifest: StoreManifest,
|
|
50
|
+
opts?: StoreGraphOptions,
|
|
51
|
+
) {
|
|
52
|
+
this.manifest = manifest;
|
|
53
|
+
this.debug = opts?.debug;
|
|
54
|
+
this.configFactory = opts?.configFactory ?? defaultConfigFactory;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Create a StoreGraph from the global manifest.
|
|
59
|
+
*/
|
|
60
|
+
static async create(opts?: StoreGraphOptions): Promise<StoreGraph> {
|
|
61
|
+
const manifest = await loadManifest(opts?.manifestPath);
|
|
62
|
+
return new StoreGraph(manifest, opts);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Create a StoreGraph from an explicit manifest object (useful for testing).
|
|
67
|
+
*/
|
|
68
|
+
static fromManifest(
|
|
69
|
+
manifest: StoreManifest,
|
|
70
|
+
opts?: StoreGraphOptions,
|
|
71
|
+
): StoreGraph {
|
|
72
|
+
return new StoreGraph(manifest, opts);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get the loaded manifest.
|
|
77
|
+
*/
|
|
78
|
+
getManifest(): StoreManifest {
|
|
79
|
+
return this.manifest;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Resolve a store by name: materialize it and all its linked stores (depth 1).
|
|
84
|
+
* Returns an array of MemoryInstance objects ready for search.
|
|
85
|
+
*
|
|
86
|
+
* Linked stores that fail to materialize are skipped with a warning.
|
|
87
|
+
*/
|
|
88
|
+
async resolve(storeName: string): Promise<MemoryInstance[]> {
|
|
89
|
+
const instances: MemoryInstance[] = [];
|
|
90
|
+
|
|
91
|
+
// Resolve the primary store
|
|
92
|
+
const primary = await this.resolveOne(storeName);
|
|
93
|
+
if (!primary) {
|
|
94
|
+
throw new Error(`Store "${storeName}" not found or unavailable`);
|
|
95
|
+
}
|
|
96
|
+
instances.push({
|
|
97
|
+
minimem: primary.instance,
|
|
98
|
+
memoryDir: primary.materialization.path,
|
|
99
|
+
name: storeName,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Resolve linked stores (depth 1)
|
|
103
|
+
const linkedNames = await getLinkedStoreNames(this.manifest, storeName);
|
|
104
|
+
for (const linkedName of linkedNames) {
|
|
105
|
+
if (linkedName === storeName) continue; // skip self-links
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const linked = await this.resolveOne(linkedName);
|
|
109
|
+
if (linked) {
|
|
110
|
+
instances.push({
|
|
111
|
+
minimem: linked.instance,
|
|
112
|
+
memoryDir: linked.materialization.path,
|
|
113
|
+
name: linkedName,
|
|
114
|
+
});
|
|
115
|
+
} else {
|
|
116
|
+
this.debug?.(`Linked store "${linkedName}" unavailable, skipping`);
|
|
117
|
+
}
|
|
118
|
+
} catch (err) {
|
|
119
|
+
this.debug?.(
|
|
120
|
+
`Failed to resolve linked store "${linkedName}": ${String(err)}`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return instances;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Resolve a store by directory path (looks up the store name in the manifest).
|
|
130
|
+
* Falls back to creating a standalone instance if the directory isn't in the manifest.
|
|
131
|
+
*/
|
|
132
|
+
async resolveByPath(dirPath: string): Promise<MemoryInstance[]> {
|
|
133
|
+
const storeName = resolveStoreName(this.manifest, dirPath);
|
|
134
|
+
if (storeName) {
|
|
135
|
+
return this.resolve(storeName);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Not in manifest — return standalone instance with no links
|
|
139
|
+
this.debug?.(`Directory "${dirPath}" not in manifest, using standalone`);
|
|
140
|
+
const config = await this.configFactory(dirPath, path.basename(dirPath));
|
|
141
|
+
const instance = await Minimem.create(config);
|
|
142
|
+
return [
|
|
143
|
+
{
|
|
144
|
+
minimem: instance,
|
|
145
|
+
memoryDir: dirPath,
|
|
146
|
+
name: path.basename(dirPath),
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* List all known stores from the manifest with their link info.
|
|
153
|
+
*/
|
|
154
|
+
async listStores(): Promise<
|
|
155
|
+
Array<{
|
|
156
|
+
name: string;
|
|
157
|
+
path: string;
|
|
158
|
+
remote?: string;
|
|
159
|
+
links: string[];
|
|
160
|
+
available: boolean;
|
|
161
|
+
}>
|
|
162
|
+
> {
|
|
163
|
+
const result: Array<{
|
|
164
|
+
name: string;
|
|
165
|
+
path: string;
|
|
166
|
+
remote?: string;
|
|
167
|
+
links: string[];
|
|
168
|
+
available: boolean;
|
|
169
|
+
}> = [];
|
|
170
|
+
|
|
171
|
+
for (const [name, def] of Object.entries(this.manifest.stores)) {
|
|
172
|
+
const links = await getLinkedStoreNames(this.manifest, name);
|
|
173
|
+
const { existsSync } = await import("node:fs");
|
|
174
|
+
const available = existsSync(def.path) || !!def.remote;
|
|
175
|
+
|
|
176
|
+
result.push({
|
|
177
|
+
name,
|
|
178
|
+
path: def.path,
|
|
179
|
+
remote: def.remote,
|
|
180
|
+
links,
|
|
181
|
+
available,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Close all resolved Minimem instances and clean up materializations.
|
|
190
|
+
*/
|
|
191
|
+
async close(): Promise<void> {
|
|
192
|
+
for (const [, store] of this.resolved) {
|
|
193
|
+
try {
|
|
194
|
+
store.instance.close();
|
|
195
|
+
} catch {
|
|
196
|
+
// best effort
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
await store.materialization.cleanup();
|
|
200
|
+
} catch {
|
|
201
|
+
// best effort
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
this.resolved.clear();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Resolve a single store by name.
|
|
209
|
+
* Returns cached instance if already resolved.
|
|
210
|
+
*/
|
|
211
|
+
private async resolveOne(storeName: string): Promise<ResolvedStore | null> {
|
|
212
|
+
// Return cached if available
|
|
213
|
+
const cached = this.resolved.get(storeName);
|
|
214
|
+
if (cached) return cached;
|
|
215
|
+
|
|
216
|
+
const def = resolveStore(this.manifest, storeName);
|
|
217
|
+
if (!def) return null;
|
|
218
|
+
|
|
219
|
+
// Materialize
|
|
220
|
+
const materialization = await materializeStore(storeName, def);
|
|
221
|
+
if (!materialization) return null;
|
|
222
|
+
|
|
223
|
+
// Create Minimem instance
|
|
224
|
+
const config = await this.configFactory(materialization.path, storeName);
|
|
225
|
+
const instance = await Minimem.create(config);
|
|
226
|
+
|
|
227
|
+
const resolved: ResolvedStore = {
|
|
228
|
+
name: storeName,
|
|
229
|
+
definition: def,
|
|
230
|
+
materialization,
|
|
231
|
+
instance,
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
this.resolved.set(storeName, resolved);
|
|
235
|
+
return resolved;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Default config factory: creates a minimal config with auto embedding.
|
|
241
|
+
* In practice, the CLI will provide a factory that respects per-store configs.
|
|
242
|
+
*/
|
|
243
|
+
async function defaultConfigFactory(
|
|
244
|
+
memoryDir: string,
|
|
245
|
+
_storeName: string,
|
|
246
|
+
): Promise<MinimemConfig> {
|
|
247
|
+
return {
|
|
248
|
+
memoryDir,
|
|
249
|
+
embedding: { provider: "auto" },
|
|
250
|
+
watch: { enabled: false },
|
|
251
|
+
};
|
|
252
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2023",
|
|
4
|
+
"lib": ["ES2023"],
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
"moduleResolution": "NodeNext",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"outDir": "dist",
|
|
14
|
+
"rootDir": "src",
|
|
15
|
+
"types": ["node"]
|
|
16
|
+
},
|
|
17
|
+
"include": ["src"],
|
|
18
|
+
"exclude": ["node_modules", "dist"]
|
|
19
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineConfig } from "tsup";
|
|
2
|
+
|
|
3
|
+
export default defineConfig([
|
|
4
|
+
// Library build
|
|
5
|
+
{
|
|
6
|
+
entry: ["src/index.ts", "src/session.ts", "src/internal.ts"],
|
|
7
|
+
format: ["esm", "cjs"],
|
|
8
|
+
dts: true,
|
|
9
|
+
clean: true,
|
|
10
|
+
sourcemap: true,
|
|
11
|
+
target: "node22",
|
|
12
|
+
external: ["node-llama-cpp"],
|
|
13
|
+
},
|
|
14
|
+
// CLI build - bundle everything into single file
|
|
15
|
+
{
|
|
16
|
+
entry: ["src/cli/index.ts"],
|
|
17
|
+
format: ["esm"],
|
|
18
|
+
outDir: "dist/cli",
|
|
19
|
+
sourcemap: true,
|
|
20
|
+
target: "node22",
|
|
21
|
+
external: ["node-llama-cpp", "commander"],
|
|
22
|
+
banner: {
|
|
23
|
+
js: "#!/usr/bin/env node",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
]);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
test: {
|
|
5
|
+
watch: false,
|
|
6
|
+
include: ["src/**/*.test.ts"],
|
|
7
|
+
exclude: [
|
|
8
|
+
"**/node_modules/**",
|
|
9
|
+
"**/clawdbot/**",
|
|
10
|
+
"**/dist/**",
|
|
11
|
+
// These tests use node:sqlite which Vite can't handle
|
|
12
|
+
// Run with: npm run test:integration or npm run test:cli
|
|
13
|
+
"**/*.integration.test.ts",
|
|
14
|
+
"**/cli/__tests__/commands.test.ts",
|
|
15
|
+
// knowledge.test.ts uses node:sqlite for graph tests — run via test:knowledge
|
|
16
|
+
// Frontmatter tests are in knowledge-frontmatter.test.ts (vitest-compatible)
|
|
17
|
+
"src/__tests__/knowledge.test.ts",
|
|
18
|
+
// store-graph tests use Minimem (node:sqlite) — run via test:integration
|
|
19
|
+
"src/store/__tests__/store-graph.test.ts",
|
|
20
|
+
],
|
|
21
|
+
// Run tests sequentially to avoid XDG_CONFIG_HOME conflicts
|
|
22
|
+
pool: "forks",
|
|
23
|
+
poolOptions: {
|
|
24
|
+
forks: {
|
|
25
|
+
singleFork: true,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -26,6 +26,7 @@ export function createGenerateCommands(): Command {
|
|
|
26
26
|
"Output path (default: <dir>/SKILL.md)"
|
|
27
27
|
)
|
|
28
28
|
.option("--no-cli-examples", "Omit CLI usage examples")
|
|
29
|
+
.option("--no-spawn-rules", "Omit spawn rules section")
|
|
29
30
|
.action((dir: string, opts) => {
|
|
30
31
|
try {
|
|
31
32
|
const template = TemplateLoader.load(dir);
|
|
@@ -33,6 +34,7 @@ export function createGenerateCommands(): Command {
|
|
|
33
34
|
const content = generateSkillMd(template, {
|
|
34
35
|
teamName,
|
|
35
36
|
includeCliExamples: opts.cliExamples !== false,
|
|
37
|
+
includeSpawnRules: opts.spawnRules !== false,
|
|
36
38
|
});
|
|
37
39
|
|
|
38
40
|
const outputPath = opts.output ?? path.join(dir, "SKILL.md");
|
|
@@ -55,6 +57,8 @@ export function createGenerateCommands(): Command {
|
|
|
55
57
|
"Output directory for prompt files (default: <dir>/agents/)"
|
|
56
58
|
)
|
|
57
59
|
.option("--preamble <text>", "Additional context to prepend to every prompt")
|
|
60
|
+
.option("--no-spawn-section", "Omit spawn permissions from agent prompts")
|
|
61
|
+
.option("--no-cli-section", "Omit CLI quick reference from agent prompts")
|
|
58
62
|
.action((dir: string, opts) => {
|
|
59
63
|
try {
|
|
60
64
|
const template = TemplateLoader.load(dir);
|
|
@@ -62,6 +66,8 @@ export function createGenerateCommands(): Command {
|
|
|
62
66
|
const prompts = generateAgentPrompts(template, {
|
|
63
67
|
teamName,
|
|
64
68
|
preamble: opts.preamble,
|
|
69
|
+
includeSpawnSection: opts.spawnSection !== false,
|
|
70
|
+
includeCliSection: opts.cliSection !== false,
|
|
65
71
|
});
|
|
66
72
|
|
|
67
73
|
const outputDir = opts.output ?? path.join(dir, "agents");
|
|
@@ -92,6 +98,9 @@ export function createGenerateCommands(): Command {
|
|
|
92
98
|
"Output base directory (default: <dir>)"
|
|
93
99
|
)
|
|
94
100
|
.option("--preamble <text>", "Additional context for agent prompts")
|
|
101
|
+
.option("--no-spawn-rules", "Omit spawn rules from SKILL.md")
|
|
102
|
+
.option("--no-spawn-section", "Omit spawn permissions from agent prompts")
|
|
103
|
+
.option("--no-cli-section", "Omit CLI quick reference from agent prompts")
|
|
95
104
|
.action((dir: string, opts) => {
|
|
96
105
|
try {
|
|
97
106
|
const template = TemplateLoader.load(dir);
|
|
@@ -99,7 +108,10 @@ export function createGenerateCommands(): Command {
|
|
|
99
108
|
const baseDir = opts.output ?? dir;
|
|
100
109
|
|
|
101
110
|
// Generate SKILL.md
|
|
102
|
-
const skillContent = generateSkillMd(template, {
|
|
111
|
+
const skillContent = generateSkillMd(template, {
|
|
112
|
+
teamName,
|
|
113
|
+
includeSpawnRules: opts.spawnRules !== false,
|
|
114
|
+
});
|
|
103
115
|
const skillPath = path.join(baseDir, "SKILL.md");
|
|
104
116
|
fs.writeFileSync(skillPath, skillContent, "utf-8");
|
|
105
117
|
console.log(`Generated ${skillPath}`);
|
|
@@ -108,6 +120,8 @@ export function createGenerateCommands(): Command {
|
|
|
108
120
|
const prompts = generateAgentPrompts(template, {
|
|
109
121
|
teamName,
|
|
110
122
|
preamble: opts.preamble,
|
|
123
|
+
includeSpawnSection: opts.spawnSection !== false,
|
|
124
|
+
includeCliSection: opts.cliSection !== false,
|
|
111
125
|
});
|
|
112
126
|
const agentsDir = path.join(baseDir, "agents");
|
|
113
127
|
fs.mkdirSync(agentsDir, { recursive: true });
|
|
@@ -136,6 +150,8 @@ export function createGenerateCommands(): Command {
|
|
|
136
150
|
"-o, --output <path>",
|
|
137
151
|
"Output directory (default: <dir>/package/)"
|
|
138
152
|
)
|
|
153
|
+
.option("--no-spawn-section", "Omit spawn permissions from role SKILL.md files")
|
|
154
|
+
.option("--no-cli-section", "Omit CLI quick reference from role SKILL.md files")
|
|
139
155
|
.action((dir: string, opts) => {
|
|
140
156
|
try {
|
|
141
157
|
const template = TemplateLoader.load(dir);
|
|
@@ -145,6 +161,8 @@ export function createGenerateCommands(): Command {
|
|
|
145
161
|
const result = generatePackage(template, {
|
|
146
162
|
teamName,
|
|
147
163
|
outputDir,
|
|
164
|
+
includeSpawnSection: opts.spawnSection !== false,
|
|
165
|
+
includeCliSection: opts.cliSection !== false,
|
|
148
166
|
});
|
|
149
167
|
|
|
150
168
|
console.log(`Generated skill package in ${outputDir}`);
|
|
@@ -194,12 +212,16 @@ export function createGenerateCommands(): Command {
|
|
|
194
212
|
.requiredOption("-r, --role <role>", "Role name")
|
|
195
213
|
.option("-n, --name <name>", "Override the team name")
|
|
196
214
|
.option("-o, --output <path>", "Output path (default: stdout)")
|
|
215
|
+
.option("--no-spawn-section", "Omit spawn permissions section")
|
|
216
|
+
.option("--no-cli-section", "Omit CLI quick reference section")
|
|
197
217
|
.action((dir: string, opts) => {
|
|
198
218
|
try {
|
|
199
219
|
const template = TemplateLoader.load(dir);
|
|
200
220
|
const teamName = opts.name ?? template.manifest.name;
|
|
201
221
|
const result = generateRoleSkillMd(template, opts.role, {
|
|
202
222
|
teamName,
|
|
223
|
+
includeSpawnSection: opts.spawnSection !== false,
|
|
224
|
+
includeCliSection: opts.cliSection !== false,
|
|
203
225
|
});
|
|
204
226
|
|
|
205
227
|
if (opts.output) {
|
|
@@ -311,6 +311,100 @@ describe("generateRoleSkillMd", () => {
|
|
|
311
311
|
});
|
|
312
312
|
});
|
|
313
313
|
|
|
314
|
+
describe("section exclusion options (generateAgentPrompts)", () => {
|
|
315
|
+
it("includes spawn and CLI sections by default", () => {
|
|
316
|
+
const prompts = generateAgentPrompts(makeFullTemplate());
|
|
317
|
+
const planner = prompts.find((p) => p.role === "planner")!;
|
|
318
|
+
expect(planner.prompt).toContain("## Spawn Permissions");
|
|
319
|
+
expect(planner.prompt).toContain("## CLI Quick Reference");
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("excludes spawn section when includeSpawnSection is false", () => {
|
|
323
|
+
const prompts = generateAgentPrompts(makeFullTemplate(), {
|
|
324
|
+
includeSpawnSection: false,
|
|
325
|
+
});
|
|
326
|
+
for (const prompt of prompts) {
|
|
327
|
+
expect(prompt.prompt).not.toContain("## Spawn Permissions");
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it("excludes CLI section when includeCliSection is false", () => {
|
|
332
|
+
const prompts = generateAgentPrompts(makeFullTemplate(), {
|
|
333
|
+
includeCliSection: false,
|
|
334
|
+
});
|
|
335
|
+
for (const prompt of prompts) {
|
|
336
|
+
expect(prompt.prompt).not.toContain("## CLI Quick Reference");
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it("excludes both sections when both are false", () => {
|
|
341
|
+
const prompts = generateAgentPrompts(makeFullTemplate(), {
|
|
342
|
+
includeSpawnSection: false,
|
|
343
|
+
includeCliSection: false,
|
|
344
|
+
});
|
|
345
|
+
for (const prompt of prompts) {
|
|
346
|
+
expect(prompt.prompt).not.toContain("## Spawn Permissions");
|
|
347
|
+
expect(prompt.prompt).not.toContain("## CLI Quick Reference");
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
describe("section exclusion options (generateAgentPrompt single)", () => {
|
|
353
|
+
it("excludes spawn section when includeSpawnSection is false", () => {
|
|
354
|
+
const prompt = generateAgentPrompt(makeFullTemplate(), "planner", {
|
|
355
|
+
includeSpawnSection: false,
|
|
356
|
+
});
|
|
357
|
+
expect(prompt.prompt).not.toContain("## Spawn Permissions");
|
|
358
|
+
expect(prompt.prompt).toContain("## CLI Quick Reference");
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it("excludes CLI section when includeCliSection is false", () => {
|
|
362
|
+
const prompt = generateAgentPrompt(makeFullTemplate(), "planner", {
|
|
363
|
+
includeCliSection: false,
|
|
364
|
+
});
|
|
365
|
+
expect(prompt.prompt).toContain("## Spawn Permissions");
|
|
366
|
+
expect(prompt.prompt).not.toContain("## CLI Quick Reference");
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
describe("section exclusion options (generateRoleSkillMd)", () => {
|
|
371
|
+
it("includes spawn and CLI sections by default", () => {
|
|
372
|
+
const result = generateRoleSkillMd(makeFullTemplate(), "planner");
|
|
373
|
+
expect(result.content).toContain("## Spawn Permissions");
|
|
374
|
+
expect(result.content).toContain("## CLI Quick Reference");
|
|
375
|
+
expect(result.content).toContain("can_spawn: [grinder, planner]");
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it("excludes spawn section and can_spawn frontmatter when includeSpawnSection is false", () => {
|
|
379
|
+
const result = generateRoleSkillMd(makeFullTemplate(), "planner", {
|
|
380
|
+
includeSpawnSection: false,
|
|
381
|
+
});
|
|
382
|
+
expect(result.content).not.toContain("## Spawn Permissions");
|
|
383
|
+
expect(result.content).not.toContain("can_spawn:");
|
|
384
|
+
// CLI should still be included
|
|
385
|
+
expect(result.content).toContain("## CLI Quick Reference");
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it("excludes CLI section when includeCliSection is false", () => {
|
|
389
|
+
const result = generateRoleSkillMd(makeFullTemplate(), "planner", {
|
|
390
|
+
includeCliSection: false,
|
|
391
|
+
});
|
|
392
|
+
expect(result.content).not.toContain("## CLI Quick Reference");
|
|
393
|
+
// Spawn should still be included
|
|
394
|
+
expect(result.content).toContain("## Spawn Permissions");
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it("excludes both sections when both are false", () => {
|
|
398
|
+
const result = generateRoleSkillMd(makeFullTemplate(), "planner", {
|
|
399
|
+
includeSpawnSection: false,
|
|
400
|
+
includeCliSection: false,
|
|
401
|
+
});
|
|
402
|
+
expect(result.content).not.toContain("## Spawn Permissions");
|
|
403
|
+
expect(result.content).not.toContain("## CLI Quick Reference");
|
|
404
|
+
expect(result.content).not.toContain("can_spawn:");
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
314
408
|
describe("generateAllRoleSkillMds", () => {
|
|
315
409
|
it("generates a skill md for each role", () => {
|
|
316
410
|
const results = generateAllRoleSkillMds(makeFullTemplate());
|
|
@@ -16,6 +16,10 @@ export interface AgentPromptGeneratorOptions {
|
|
|
16
16
|
teamName?: string;
|
|
17
17
|
/** Additional context to prepend to every agent prompt */
|
|
18
18
|
preamble?: string;
|
|
19
|
+
/** Whether to include the "Spawn Permissions" section. Defaults to true. */
|
|
20
|
+
includeSpawnSection?: boolean;
|
|
21
|
+
/** Whether to include the "CLI Quick Reference" section. Defaults to true. */
|
|
22
|
+
includeCliSection?: boolean;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
export interface RoleSkillMd {
|
|
@@ -26,6 +30,10 @@ export interface RoleSkillMd {
|
|
|
26
30
|
export interface RoleSkillMdOptions {
|
|
27
31
|
/** Team name override */
|
|
28
32
|
teamName?: string;
|
|
33
|
+
/** Whether to include the "Spawn Permissions" section. Defaults to true. */
|
|
34
|
+
includeSpawnSection?: boolean;
|
|
35
|
+
/** Whether to include the "CLI Quick Reference" section. Defaults to true. */
|
|
36
|
+
includeCliSection?: boolean;
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
/**
|
|
@@ -46,8 +54,10 @@ export function generateAgentPrompts(
|
|
|
46
54
|
options: AgentPromptGeneratorOptions = {}
|
|
47
55
|
): AgentPrompt[] {
|
|
48
56
|
const teamName = options.teamName ?? template.manifest.name;
|
|
57
|
+
const includeSpawn = options.includeSpawnSection ?? true;
|
|
58
|
+
const includeCli = options.includeCliSection ?? true;
|
|
49
59
|
return template.manifest.roles.map((roleName) =>
|
|
50
|
-
generateSingleAgentPrompt(template, roleName, teamName, options.preamble)
|
|
60
|
+
generateSingleAgentPrompt(template, roleName, teamName, options.preamble, includeSpawn, includeCli)
|
|
51
61
|
);
|
|
52
62
|
}
|
|
53
63
|
|
|
@@ -60,11 +70,15 @@ export function generateAgentPrompt(
|
|
|
60
70
|
options: AgentPromptGeneratorOptions = {}
|
|
61
71
|
): AgentPrompt {
|
|
62
72
|
const teamName = options.teamName ?? template.manifest.name;
|
|
73
|
+
const includeSpawn = options.includeSpawnSection ?? true;
|
|
74
|
+
const includeCli = options.includeCliSection ?? true;
|
|
63
75
|
return generateSingleAgentPrompt(
|
|
64
76
|
template,
|
|
65
77
|
roleName,
|
|
66
78
|
teamName,
|
|
67
|
-
options.preamble
|
|
79
|
+
options.preamble,
|
|
80
|
+
includeSpawn,
|
|
81
|
+
includeCli,
|
|
68
82
|
);
|
|
69
83
|
}
|
|
70
84
|
|
|
@@ -81,6 +95,8 @@ export function generateRoleSkillMd(
|
|
|
81
95
|
options: RoleSkillMdOptions = {}
|
|
82
96
|
): RoleSkillMd {
|
|
83
97
|
const teamName = options.teamName ?? template.manifest.name;
|
|
98
|
+
const includeSpawn = options.includeSpawnSection ?? true;
|
|
99
|
+
const includeCli = options.includeCliSection ?? true;
|
|
84
100
|
const m = template.manifest;
|
|
85
101
|
const role = template.roles.get(roleName);
|
|
86
102
|
const rolePrompts = template.prompts.get(roleName);
|
|
@@ -88,7 +104,7 @@ export function generateRoleSkillMd(
|
|
|
88
104
|
const sections: string[] = [];
|
|
89
105
|
|
|
90
106
|
// YAML frontmatter
|
|
91
|
-
sections.push(generateRoleFrontmatter(template, roleName, teamName));
|
|
107
|
+
sections.push(generateRoleFrontmatter(template, roleName, teamName, includeSpawn));
|
|
92
108
|
|
|
93
109
|
// Identity header
|
|
94
110
|
sections.push(`# Role: ${roleName}`);
|
|
@@ -133,10 +149,14 @@ export function generateRoleSkillMd(
|
|
|
133
149
|
}
|
|
134
150
|
|
|
135
151
|
// Spawn permissions
|
|
136
|
-
|
|
152
|
+
if (includeSpawn) {
|
|
153
|
+
sections.push(generateRoleSpawnSection(template, roleName));
|
|
154
|
+
}
|
|
137
155
|
|
|
138
156
|
// CLI reference
|
|
139
|
-
|
|
157
|
+
if (includeCli) {
|
|
158
|
+
sections.push(generateRoleCliSection(roleName, teamName, template));
|
|
159
|
+
}
|
|
140
160
|
|
|
141
161
|
return {
|
|
142
162
|
role: roleName,
|
|
@@ -159,7 +179,8 @@ export function generateAllRoleSkillMds(
|
|
|
159
179
|
function generateRoleFrontmatter(
|
|
160
180
|
template: ResolvedTemplate,
|
|
161
181
|
roleName: string,
|
|
162
|
-
teamName: string
|
|
182
|
+
teamName: string,
|
|
183
|
+
includeSpawn: boolean = true,
|
|
163
184
|
): string {
|
|
164
185
|
const m = template.manifest;
|
|
165
186
|
const role = template.roles.get(roleName);
|
|
@@ -198,10 +219,12 @@ function generateRoleFrontmatter(
|
|
|
198
219
|
lines.push(`emits: [${emissions.join(", ")}]`);
|
|
199
220
|
}
|
|
200
221
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
222
|
+
if (includeSpawn) {
|
|
223
|
+
const spawnRules = m.topology.spawn_rules?.[roleName];
|
|
224
|
+
if (spawnRules && spawnRules.length > 0) {
|
|
225
|
+
const names = spawnRules.map((e) => typeof e === "string" ? e : e.role);
|
|
226
|
+
lines.push(`can_spawn: [${names.join(", ")}]`);
|
|
227
|
+
}
|
|
205
228
|
}
|
|
206
229
|
|
|
207
230
|
lines.push("---");
|
|
@@ -275,7 +298,9 @@ function generateSingleAgentPrompt(
|
|
|
275
298
|
template: ResolvedTemplate,
|
|
276
299
|
roleName: string,
|
|
277
300
|
teamName: string,
|
|
278
|
-
preamble?: string
|
|
301
|
+
preamble?: string,
|
|
302
|
+
includeSpawn: boolean = true,
|
|
303
|
+
includeCli: boolean = true,
|
|
279
304
|
): AgentPrompt {
|
|
280
305
|
const m = template.manifest;
|
|
281
306
|
const role = template.roles.get(roleName);
|
|
@@ -318,10 +343,14 @@ function generateSingleAgentPrompt(
|
|
|
318
343
|
}
|
|
319
344
|
|
|
320
345
|
// Spawn permissions
|
|
321
|
-
|
|
346
|
+
if (includeSpawn) {
|
|
347
|
+
sections.push(generateRoleSpawnSection(template, roleName));
|
|
348
|
+
}
|
|
322
349
|
|
|
323
350
|
// CLI reference
|
|
324
|
-
|
|
351
|
+
if (includeCli) {
|
|
352
|
+
sections.push(generateRoleCliSection(roleName, teamName, template));
|
|
353
|
+
}
|
|
325
354
|
|
|
326
355
|
return {
|
|
327
356
|
role: roleName,
|
|
@@ -10,6 +10,10 @@ export interface PackageGeneratorOptions {
|
|
|
10
10
|
teamName?: string;
|
|
11
11
|
/** Output directory for the package */
|
|
12
12
|
outputDir: string;
|
|
13
|
+
/** Whether to include spawn permissions in per-role SKILL.md. Defaults to true. */
|
|
14
|
+
includeSpawnSection?: boolean;
|
|
15
|
+
/** Whether to include CLI quick reference in per-role SKILL.md. Defaults to true. */
|
|
16
|
+
includeCliSection?: boolean;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
export interface PackageResult {
|
|
@@ -51,7 +55,11 @@ export function generatePackage(
|
|
|
51
55
|
fs.writeFileSync(catalogPath, catalogContent, "utf-8");
|
|
52
56
|
|
|
53
57
|
// 2. Generate per-role SKILL.md files
|
|
54
|
-
const roleSkills = generateAllRoleSkillMds(template, {
|
|
58
|
+
const roleSkills = generateAllRoleSkillMds(template, {
|
|
59
|
+
teamName,
|
|
60
|
+
includeSpawnSection: options.includeSpawnSection,
|
|
61
|
+
includeCliSection: options.includeCliSection,
|
|
62
|
+
});
|
|
55
63
|
const rolePaths: { role: string; path: string }[] = [];
|
|
56
64
|
|
|
57
65
|
for (const roleSkill of roleSkills) {
|