@swarmvaultai/cli 1.4.0 → 3.1.0
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 +68 -10
- package/dist/index.js +297 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -44,6 +44,9 @@ swarmvault graph share --svg ./share-card.svg
|
|
|
44
44
|
swarmvault graph share --bundle ./share-kit
|
|
45
45
|
swarmvault benchmark
|
|
46
46
|
swarmvault query "What keeps recurring?" --commit
|
|
47
|
+
swarmvault context build "Ship this feature safely" --target ./src --budget 8000
|
|
48
|
+
swarmvault task start "Ship this feature safely" --target ./src --agent codex
|
|
49
|
+
swarmvault retrieval status
|
|
47
50
|
swarmvault query "Turn this into slides" --format slides
|
|
48
51
|
swarmvault explore "What should I research next?" --steps 3
|
|
49
52
|
swarmvault lint --deep
|
|
@@ -211,7 +214,7 @@ Compile the current manifests into:
|
|
|
211
214
|
|
|
212
215
|
- generated markdown in `wiki/`
|
|
213
216
|
- structured graph data in `state/graph.json`
|
|
214
|
-
- local
|
|
217
|
+
- local retrieval data in `state/retrieval/`
|
|
215
218
|
- share cards at `wiki/graph/share-card.md` and `wiki/graph/share-card.svg`, plus a portable share kit at `wiki/graph/share-kit/`
|
|
216
219
|
|
|
217
220
|
The compiler also reads `swarmvault.schema.md` and records a `schema_hash` plus lifecycle metadata such as `status`, `created_at`, `updated_at`, `compiled_from`, and `managed_by` in generated pages so schema edits can mark pages stale without losing lifecycle state.
|
|
@@ -270,13 +273,47 @@ By default, the answer is written into `wiki/outputs/` and immediately registere
|
|
|
270
273
|
- `wiki/index.md`
|
|
271
274
|
- `wiki/outputs/index.md`
|
|
272
275
|
- `state/graph.json`
|
|
273
|
-
- `state/
|
|
276
|
+
- `state/retrieval/`
|
|
274
277
|
|
|
275
278
|
Saved outputs also carry related page, node, and source metadata so SwarmVault can refresh related source, concept, and entity pages immediately.
|
|
276
279
|
|
|
277
280
|
Human-authored pages in `wiki/insights/` are also indexed into search and query context, but SwarmVault does not rewrite them after initialization.
|
|
278
281
|
|
|
279
|
-
By default, query uses the local SQLite
|
|
282
|
+
By default, query uses the local SQLite retrieval index. When an embedding-capable provider is available and `retrieval.hybrid` is not disabled, semantic page matches are fused into the same candidate set before answer generation. `tasks.embeddingProvider` is the explicit way to choose that backend, but SwarmVault can also fall back to a `queryProvider` with embeddings support. Set `retrieval.rerank: true` when you want the configured `queryProvider` to rerank the merged top hits. `--commit` immediately commits saved `wiki/` and `state/` changes when the vault root is inside a git repo.
|
|
283
|
+
|
|
284
|
+
### `swarmvault context build|list|show|delete`
|
|
285
|
+
|
|
286
|
+
Build and manage agent-ready context packs from the compiled vault.
|
|
287
|
+
|
|
288
|
+
- `context build "<goal>"` assembles relevant pages, graph nodes, edges, hyperedges, citations, and explicit omitted entries into a bounded bundle
|
|
289
|
+
- `--target <path-or-node>` anchors the pack around a file, page id, node id, or graph label
|
|
290
|
+
- `--task <id>` links the newly built context pack to an active task
|
|
291
|
+
- `--memory <id>` remains a compatibility alias for `--task`
|
|
292
|
+
- `--budget <tokens>` caps the estimated token budget; over-budget candidates are listed in `omittedItems`
|
|
293
|
+
- `--format markdown|json|llms` controls the printed output shape, while every pack is still saved as JSON
|
|
294
|
+
- saved artifacts live under `state/context-packs/`, with companion markdown pages under `wiki/context/`
|
|
295
|
+
- `context list`, `context show <id>`, and `context delete <id>` manage saved packs
|
|
296
|
+
|
|
297
|
+
Use this before handing work to an agent, starting a PR review, or preserving the evidence bundle behind a design/debugging decision.
|
|
298
|
+
|
|
299
|
+
### `swarmvault task start|update|finish|list|show|resume`
|
|
300
|
+
|
|
301
|
+
Record a durable local task ledger for agent work.
|
|
302
|
+
|
|
303
|
+
- `task start "<goal>" --target <path-or-node>` creates `state/memory/tasks/<id>.json`, `wiki/memory/tasks/<id>.md`, updates `wiki/memory/index.md`, and builds an initial context pack
|
|
304
|
+
- `task update <id>` records notes, decisions, changed paths, context packs, sessions, sources, pages, nodes, git refs, or status changes
|
|
305
|
+
- `task finish <id> --outcome <text>` marks the task completed and can add one or more `--follow-up` entries
|
|
306
|
+
- `task list`, `task show <id>`, and `task resume <id> --format markdown|json|llms` expose the task history for the next agent
|
|
307
|
+
|
|
308
|
+
`query`, `explore`, and `context build` accept `--task <id>` so saved outputs and context packs can attach to an active task. The 2.0 `memory` command group and `--memory <id>` flag remain compatibility aliases.
|
|
309
|
+
|
|
310
|
+
### `swarmvault retrieval status|rebuild|doctor`
|
|
311
|
+
|
|
312
|
+
Inspect and maintain the local retrieval index under `state/retrieval/`.
|
|
313
|
+
|
|
314
|
+
- `retrieval status` reports backend, configured hybrid/rerank behavior, manifest freshness, page count, and the current SQLite shard path
|
|
315
|
+
- `retrieval rebuild` rebuilds the local shard from current wiki pages and refreshes `state/retrieval/manifest.json`
|
|
316
|
+
- `retrieval doctor` checks for stale or missing retrieval artifacts; add `--repair` to rebuild missing or stale artifacts immediately
|
|
280
317
|
|
|
281
318
|
### `swarmvault explore "<question>" [--steps <n>] [--format markdown|report|slides|chart|image]`
|
|
282
319
|
|
|
@@ -345,10 +382,28 @@ Run SwarmVault as a local MCP server over stdio. This exposes the vault to compa
|
|
|
345
382
|
- `compile_vault`
|
|
346
383
|
- `lint_vault`
|
|
347
384
|
- `blast_radius`
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
385
|
+
- `build_context_pack`
|
|
386
|
+
- `list_context_packs`
|
|
387
|
+
- `read_context_pack`
|
|
388
|
+
- `start_task`
|
|
389
|
+
- `update_task`
|
|
390
|
+
- `finish_task`
|
|
391
|
+
- `list_tasks`
|
|
392
|
+
- `read_task`
|
|
393
|
+
- `resume_task`
|
|
394
|
+
- `start_memory_task`
|
|
395
|
+
- `update_memory_task`
|
|
396
|
+
- `finish_memory_task`
|
|
397
|
+
- `list_memory_tasks`
|
|
398
|
+
- `read_memory_task`
|
|
399
|
+
- `resume_memory_task`
|
|
400
|
+
- `retrieval_status`
|
|
401
|
+
- `rebuild_retrieval`
|
|
402
|
+
- `doctor_retrieval`
|
|
403
|
+
|
|
404
|
+
`compile_vault` also accepts `maxTokens` for bounded wiki output, `blast_radius` traces reverse import impact for a file or module target, `build_context_pack` creates the same bounded agent evidence bundles as `swarmvault context build`, the task tools mirror `swarmvault task`, the memory tools mirror the compatibility command group, and retrieval tools inspect or repair the local index.
|
|
405
|
+
|
|
406
|
+
The MCP surface also exposes `swarmvault://schema`, `swarmvault://sessions`, `swarmvault://sessions/{path}`, `swarmvault://context-packs`, `swarmvault://tasks`, `swarmvault://memory-tasks`, and includes `schemaPath` in `workspace_info`.
|
|
352
407
|
|
|
353
408
|
### `swarmvault graph serve`
|
|
354
409
|
|
|
@@ -539,15 +594,18 @@ Search behavior is configurable separately from provider routing:
|
|
|
539
594
|
|
|
540
595
|
```json
|
|
541
596
|
{
|
|
542
|
-
"
|
|
597
|
+
"retrieval": {
|
|
598
|
+
"backend": "sqlite",
|
|
599
|
+
"shardSize": 25000,
|
|
543
600
|
"hybrid": true,
|
|
544
601
|
"rerank": false
|
|
545
602
|
}
|
|
546
603
|
}
|
|
547
604
|
```
|
|
548
605
|
|
|
549
|
-
- `
|
|
550
|
-
- `
|
|
606
|
+
- `retrieval.hybrid` defaults to enabled and merges full-text hits with semantic page matches when an embedding-capable provider is available
|
|
607
|
+
- `retrieval.rerank` optionally asks the current `queryProvider` to rerank the merged top hits before query answers are generated
|
|
608
|
+
- `retrieval.backend` currently supports the local SQLite backend
|
|
551
609
|
|
|
552
610
|
## Troubleshooting
|
|
553
611
|
|
package/dist/index.js
CHANGED
|
@@ -15,11 +15,14 @@ import {
|
|
|
15
15
|
autoCommitWikiChanges,
|
|
16
16
|
benchmarkVault,
|
|
17
17
|
blastRadiusVault,
|
|
18
|
+
buildContextPack,
|
|
18
19
|
buildGraphShareArtifact,
|
|
19
20
|
compileVault,
|
|
20
21
|
consolidateVault,
|
|
21
22
|
createSupersessionEdge,
|
|
23
|
+
deleteContextPack,
|
|
22
24
|
deleteManagedSource,
|
|
25
|
+
doctorRetrieval,
|
|
23
26
|
downloadWhisperModel,
|
|
24
27
|
explainGraphVault,
|
|
25
28
|
exploreVault,
|
|
@@ -28,7 +31,9 @@ import {
|
|
|
28
31
|
exportGraphReportHtml,
|
|
29
32
|
exportObsidianCanvas,
|
|
30
33
|
exportObsidianVault,
|
|
34
|
+
finishMemoryTask,
|
|
31
35
|
getGitHookStatus,
|
|
36
|
+
getRetrievalStatus,
|
|
32
37
|
getWatchStatus,
|
|
33
38
|
graphDiff,
|
|
34
39
|
guideManagedSource,
|
|
@@ -42,9 +47,11 @@ import {
|
|
|
42
47
|
lintVault,
|
|
43
48
|
listApprovals,
|
|
44
49
|
listCandidates,
|
|
50
|
+
listContextPacks,
|
|
45
51
|
listGodNodes,
|
|
46
52
|
listManagedSourceRecords,
|
|
47
53
|
listManifests,
|
|
54
|
+
listMemoryTasks,
|
|
48
55
|
listSchedules,
|
|
49
56
|
listWatchedRoots,
|
|
50
57
|
loadVaultConfig,
|
|
@@ -55,14 +62,20 @@ import {
|
|
|
55
62
|
queryGraphVault,
|
|
56
63
|
queryVault,
|
|
57
64
|
readApproval,
|
|
65
|
+
readContextPack,
|
|
58
66
|
readGraphReport,
|
|
67
|
+
readMemoryTask,
|
|
68
|
+
rebuildRetrievalIndex,
|
|
59
69
|
registerLocalWhisperProvider,
|
|
60
70
|
rejectApproval,
|
|
61
71
|
reloadManagedSources,
|
|
62
72
|
removeWatchedRoot,
|
|
73
|
+
renderContextPackLlms,
|
|
74
|
+
renderContextPackMarkdown,
|
|
63
75
|
renderGraphShareBundleFiles,
|
|
64
76
|
renderGraphShareMarkdown,
|
|
65
77
|
renderGraphShareSvg,
|
|
78
|
+
resumeMemoryTask,
|
|
66
79
|
resumeSourceSession,
|
|
67
80
|
reviewManagedSource,
|
|
68
81
|
reviewSourceScope,
|
|
@@ -73,8 +86,10 @@ import {
|
|
|
73
86
|
serveSchedules,
|
|
74
87
|
startGraphServer,
|
|
75
88
|
startMcpServer,
|
|
89
|
+
startMemoryTask,
|
|
76
90
|
summarizeLocalWhisperSetup,
|
|
77
91
|
uninstallGitHooks,
|
|
92
|
+
updateMemoryTask,
|
|
78
93
|
watchVault
|
|
79
94
|
} from "@swarmvaultai/engine";
|
|
80
95
|
import { Command, Option } from "commander";
|
|
@@ -293,9 +308,9 @@ program.name("swarmvault").description("SwarmVault is a local-first knowledge co
|
|
|
293
308
|
function readCliVersion() {
|
|
294
309
|
try {
|
|
295
310
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
296
|
-
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "1.
|
|
311
|
+
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "3.1.0";
|
|
297
312
|
} catch {
|
|
298
|
-
return "1.
|
|
313
|
+
return "3.1.0";
|
|
299
314
|
}
|
|
300
315
|
}
|
|
301
316
|
function parsePositiveInt(value, fallback) {
|
|
@@ -374,8 +389,8 @@ async function maybeEmitHeuristicNotice(commandPath) {
|
|
|
374
389
|
try {
|
|
375
390
|
const { config } = await loadVaultConfig(process2.cwd());
|
|
376
391
|
const analysisTaskKeys = ["compileProvider", "queryProvider", "lintProvider"];
|
|
377
|
-
const usingHeuristic = analysisTaskKeys.every((
|
|
378
|
-
const providerId = config.tasks[
|
|
392
|
+
const usingHeuristic = analysisTaskKeys.every((task2) => {
|
|
393
|
+
const providerId = config.tasks[task2];
|
|
379
394
|
const providerConfig = config.providers[providerId];
|
|
380
395
|
return !providerConfig || providerConfig.type === "heuristic";
|
|
381
396
|
});
|
|
@@ -801,7 +816,7 @@ program.command("consolidate").description("Roll working-tier insights up into e
|
|
|
801
816
|
log(decision);
|
|
802
817
|
}
|
|
803
818
|
});
|
|
804
|
-
program.command("query").description("Query the compiled SwarmVault wiki.").argument("<question>", "Question to ask SwarmVault").option("--no-save", "Do not persist the answer to wiki/outputs").option("--commit", "Auto-commit wiki changes after query").option("--gap-fill", "Pull external web-search evidence when the local wiki has gaps (requires webSearch.tasks.queryProvider).").addOption(
|
|
819
|
+
program.command("query").description("Query the compiled SwarmVault wiki.").argument("<question>", "Question to ask SwarmVault").option("--no-save", "Do not persist the answer to wiki/outputs").option("--commit", "Auto-commit wiki changes after query").option("--gap-fill", "Pull external web-search evidence when the local wiki has gaps (requires webSearch.tasks.queryProvider).").option("--task <id>", "Attach this query output to an agent task").option("--memory <id>", "Compatibility alias for --task").addOption(
|
|
805
820
|
new Option("--format <format>", "Output format").choices(["markdown", "report", "slides", "chart", "image"]).default("markdown")
|
|
806
821
|
).action(
|
|
807
822
|
async (question, options) => {
|
|
@@ -809,7 +824,8 @@ program.command("query").description("Query the compiled SwarmVault wiki.").argu
|
|
|
809
824
|
question,
|
|
810
825
|
save: options.save ?? true,
|
|
811
826
|
format: options.format,
|
|
812
|
-
gapFill: options.gapFill ?? false
|
|
827
|
+
gapFill: options.gapFill ?? false,
|
|
828
|
+
memoryTaskId: options.task ?? options.memory
|
|
813
829
|
});
|
|
814
830
|
if (isJson()) {
|
|
815
831
|
emitJson(result);
|
|
@@ -826,7 +842,235 @@ program.command("query").description("Query the compiled SwarmVault wiki.").argu
|
|
|
826
842
|
await maybeEmitHeuristicNotice(["query"]);
|
|
827
843
|
}
|
|
828
844
|
);
|
|
829
|
-
program.command("
|
|
845
|
+
var context = program.command("context").description("Build and manage token-bounded agent context packs.");
|
|
846
|
+
context.command("build").description("Build a cited, token-bounded context pack for an agent task.").argument("<goal>", "Task, question, or goal the agent needs context for").option("--target <target>", "Optional page, node, path, project, or label to anchor the pack").option("--budget <tokens>", "Approximate token budget for included context", String(8e3)).option("--task <id>", "Attach the context pack to an agent task").option("--memory <id>", "Compatibility alias for --task").addOption(new Option("--format <format>", "Output format").choices(["markdown", "json", "llms"]).default("markdown")).action(
|
|
847
|
+
async (goal, options) => {
|
|
848
|
+
const budgetTokens = parsePositiveInt(options.budget, 8e3);
|
|
849
|
+
const result = await buildContextPack(process2.cwd(), {
|
|
850
|
+
goal,
|
|
851
|
+
target: options.target,
|
|
852
|
+
budgetTokens,
|
|
853
|
+
format: options.format,
|
|
854
|
+
memoryTaskId: options.task ?? options.memory
|
|
855
|
+
});
|
|
856
|
+
if (isJson()) {
|
|
857
|
+
emitJson(result);
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
log(result.rendered);
|
|
861
|
+
log(`Saved context pack to ${result.markdownPath}`);
|
|
862
|
+
log(`Saved context artifact to ${result.artifactPath}`);
|
|
863
|
+
}
|
|
864
|
+
);
|
|
865
|
+
context.command("list").description("List saved context packs.").action(async () => {
|
|
866
|
+
const packs = await listContextPacks(process2.cwd());
|
|
867
|
+
if (isJson()) {
|
|
868
|
+
emitJson(packs);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
if (!packs.length) {
|
|
872
|
+
log("No context packs.");
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
for (const pack of packs) {
|
|
876
|
+
log(`${pack.id} \u2014 ${pack.goal} (${pack.itemCount} item(s), ${pack.omittedCount} omitted)`);
|
|
877
|
+
}
|
|
878
|
+
});
|
|
879
|
+
context.command("show").description("Print a saved context pack.").argument("<id>", "Context pack id").addOption(new Option("--format <format>", "Output format").choices(["markdown", "json", "llms"]).default("markdown")).action(async (id, options) => {
|
|
880
|
+
const pack = await readContextPack(process2.cwd(), id);
|
|
881
|
+
if (!pack) {
|
|
882
|
+
throw new Error(`Context pack not found: ${id}`);
|
|
883
|
+
}
|
|
884
|
+
if (isJson() || options.format === "json") {
|
|
885
|
+
emitJson(pack);
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
log(options.format === "llms" ? renderContextPackLlms(pack) : renderContextPackMarkdown(pack));
|
|
889
|
+
});
|
|
890
|
+
context.command("delete").description("Delete a saved context pack artifact and markdown page.").argument("<id>", "Context pack id").action(async (id) => {
|
|
891
|
+
const deleted = await deleteContextPack(process2.cwd(), id);
|
|
892
|
+
if (!deleted) {
|
|
893
|
+
throw new Error(`Context pack not found: ${id}`);
|
|
894
|
+
}
|
|
895
|
+
if (isJson()) {
|
|
896
|
+
emitJson(deleted);
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
log(`Deleted context pack ${deleted.id}.`);
|
|
900
|
+
});
|
|
901
|
+
var memory = program.command("memory").description("Manage git-backed agent memory task ledger entries.");
|
|
902
|
+
memory.command("start").description("Start a durable agent memory task and build its initial context pack.").argument("<goal>", "Task goal to preserve in agent memory").option("--target <target>", "Optional page, node, path, project, or label to anchor the initial context pack").option("--budget <tokens>", "Approximate token budget for the initial context pack", String(8e3)).option("--agent <name>", "Agent name to record on the task").option("--context-pack <id>", "Attach an existing context pack instead of building a new one").action(async (goal, options) => {
|
|
903
|
+
const result = await startMemoryTask(process2.cwd(), {
|
|
904
|
+
goal,
|
|
905
|
+
target: options.target,
|
|
906
|
+
budgetTokens: parsePositiveInt(options.budget, 8e3),
|
|
907
|
+
agent: options.agent,
|
|
908
|
+
contextPackId: options.contextPack
|
|
909
|
+
});
|
|
910
|
+
if (isJson()) {
|
|
911
|
+
emitJson(result);
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
log(result.task.id);
|
|
915
|
+
log(`Saved memory task to ${result.markdownPath}`);
|
|
916
|
+
});
|
|
917
|
+
memory.command("update").description("Append a note, decision, path, context pack, or status change to a memory task.").argument("<id>", "Memory task id").option("--note <text>", "Append a task note").option("--decision <text>", "Append a decision").option("--changed-path <path>", "Record a changed file or wiki path").option("--context-pack <id>", "Attach a context pack").option("--session <id>", "Attach a session id").option("--source <id>", "Attach a source id").option("--page <id>", "Attach a page id").option("--node <id>", "Attach a graph node id").option("--git-ref <ref>", "Attach a git ref").addOption(new Option("--status <status>", "Task status").choices(["active", "blocked", "completed", "archived"])).action(
|
|
918
|
+
async (id, options) => {
|
|
919
|
+
const result = await updateMemoryTask(process2.cwd(), id, {
|
|
920
|
+
note: options.note,
|
|
921
|
+
decision: options.decision,
|
|
922
|
+
changedPath: options.changedPath,
|
|
923
|
+
contextPackId: options.contextPack,
|
|
924
|
+
sessionId: options.session,
|
|
925
|
+
sourceId: options.source,
|
|
926
|
+
pageId: options.page,
|
|
927
|
+
nodeId: options.node,
|
|
928
|
+
gitRef: options.gitRef,
|
|
929
|
+
status: options.status
|
|
930
|
+
});
|
|
931
|
+
if (isJson()) {
|
|
932
|
+
emitJson(result);
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
log(`Updated memory task ${result.task.id}.`);
|
|
936
|
+
}
|
|
937
|
+
);
|
|
938
|
+
memory.command("finish").description("Finish a memory task with an outcome and optional follow-up.").argument("<id>", "Memory task id").requiredOption("--outcome <text>", "Outcome to record").option("--follow-up <text>", "Follow-up to preserve for the next agent").action(async (id, options) => {
|
|
939
|
+
const result = await finishMemoryTask(process2.cwd(), id, {
|
|
940
|
+
outcome: options.outcome,
|
|
941
|
+
followUp: options.followUp
|
|
942
|
+
});
|
|
943
|
+
if (isJson()) {
|
|
944
|
+
emitJson(result);
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
log(`Finished memory task ${result.task.id}.`);
|
|
948
|
+
});
|
|
949
|
+
memory.command("list").description("List saved agent memory tasks.").action(async () => {
|
|
950
|
+
const tasks = await listMemoryTasks(process2.cwd());
|
|
951
|
+
if (isJson()) {
|
|
952
|
+
emitJson(tasks);
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
if (!tasks.length) {
|
|
956
|
+
log("No memory tasks.");
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
for (const task2 of tasks) {
|
|
960
|
+
log(`${task2.id} \u2014 ${task2.status} \u2014 ${task2.goal}`);
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
memory.command("show").description("Print a saved agent memory task.").argument("<id>", "Memory task id").action(async (id) => {
|
|
964
|
+
const task2 = await readMemoryTask(process2.cwd(), id);
|
|
965
|
+
if (!task2) {
|
|
966
|
+
throw new Error(`Memory task not found: ${id}`);
|
|
967
|
+
}
|
|
968
|
+
if (isJson()) {
|
|
969
|
+
emitJson(task2);
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
log(`Task: ${task2.title}`);
|
|
973
|
+
log(`Status: ${task2.status}`);
|
|
974
|
+
log(`Goal: ${task2.goal}`);
|
|
975
|
+
if (task2.outcome) log(`Outcome: ${task2.outcome}`);
|
|
976
|
+
if (task2.followUps.length) log(`Follow-ups: ${task2.followUps.join("; ")}`);
|
|
977
|
+
log(`Markdown: ${task2.markdownPath}`);
|
|
978
|
+
});
|
|
979
|
+
memory.command("resume").description("Render a memory task handoff for the next agent.").argument("<id>", "Memory task id").addOption(new Option("--format <format>", "Output format").choices(["markdown", "json", "llms"]).default("markdown")).action(async (id, options) => {
|
|
980
|
+
const result = await resumeMemoryTask(process2.cwd(), id, { format: options.format });
|
|
981
|
+
if (isJson() || options.format === "json") {
|
|
982
|
+
emitJson(result);
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
log(result.rendered);
|
|
986
|
+
});
|
|
987
|
+
var task = program.command("task").description("Manage git-backed agent task ledger entries.");
|
|
988
|
+
task.command("start").description("Start a durable agent task and build its initial context pack.").argument("<goal>", "Task goal to preserve").option("--target <target>", "Optional page, node, path, project, or label to anchor the initial context pack").option("--budget <tokens>", "Approximate token budget for the initial context pack", String(8e3)).option("--agent <name>", "Agent name to record on the task").option("--context-pack <id>", "Attach an existing context pack instead of building a new one").action(async (goal, options) => {
|
|
989
|
+
const result = await startMemoryTask(process2.cwd(), {
|
|
990
|
+
goal,
|
|
991
|
+
target: options.target,
|
|
992
|
+
budgetTokens: parsePositiveInt(options.budget, 8e3),
|
|
993
|
+
agent: options.agent,
|
|
994
|
+
contextPackId: options.contextPack
|
|
995
|
+
});
|
|
996
|
+
if (isJson()) {
|
|
997
|
+
emitJson(result);
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
log(result.task.id);
|
|
1001
|
+
log(`Saved task to ${result.markdownPath}`);
|
|
1002
|
+
});
|
|
1003
|
+
task.command("update").description("Append a note, decision, path, context pack, or status change to a task.").argument("<id>", "Task id").option("--note <text>", "Append a task note").option("--decision <text>", "Append a decision").option("--changed-path <path>", "Record a changed file or wiki path").option("--context-pack <id>", "Attach a context pack").option("--session <id>", "Attach a session id").option("--source <id>", "Attach a source id").option("--page <id>", "Attach a page id").option("--node <id>", "Attach a graph node id").option("--git-ref <ref>", "Attach a git ref").addOption(new Option("--status <status>", "Task status").choices(["active", "blocked", "completed", "archived"])).action(
|
|
1004
|
+
async (id, options) => {
|
|
1005
|
+
const result = await updateMemoryTask(process2.cwd(), id, {
|
|
1006
|
+
note: options.note,
|
|
1007
|
+
decision: options.decision,
|
|
1008
|
+
changedPath: options.changedPath,
|
|
1009
|
+
contextPackId: options.contextPack,
|
|
1010
|
+
sessionId: options.session,
|
|
1011
|
+
sourceId: options.source,
|
|
1012
|
+
pageId: options.page,
|
|
1013
|
+
nodeId: options.node,
|
|
1014
|
+
gitRef: options.gitRef,
|
|
1015
|
+
status: options.status
|
|
1016
|
+
});
|
|
1017
|
+
if (isJson()) {
|
|
1018
|
+
emitJson(result);
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
log(`Updated task ${result.task.id}.`);
|
|
1022
|
+
}
|
|
1023
|
+
);
|
|
1024
|
+
task.command("finish").description("Finish a task with an outcome and optional follow-up.").argument("<id>", "Task id").requiredOption("--outcome <text>", "Outcome to record").option("--follow-up <text>", "Follow-up to preserve for the next agent").action(async (id, options) => {
|
|
1025
|
+
const result = await finishMemoryTask(process2.cwd(), id, {
|
|
1026
|
+
outcome: options.outcome,
|
|
1027
|
+
followUp: options.followUp
|
|
1028
|
+
});
|
|
1029
|
+
if (isJson()) {
|
|
1030
|
+
emitJson(result);
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
log(`Finished task ${result.task.id}.`);
|
|
1034
|
+
});
|
|
1035
|
+
task.command("list").description("List saved agent tasks.").action(async () => {
|
|
1036
|
+
const tasks = await listMemoryTasks(process2.cwd());
|
|
1037
|
+
if (isJson()) {
|
|
1038
|
+
emitJson(tasks);
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
if (!tasks.length) {
|
|
1042
|
+
log("No tasks.");
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
for (const entry of tasks) {
|
|
1046
|
+
log(`${entry.id} \u2014 ${entry.status} \u2014 ${entry.goal}`);
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
task.command("show").description("Print a saved agent task.").argument("<id>", "Task id").action(async (id) => {
|
|
1050
|
+
const entry = await readMemoryTask(process2.cwd(), id);
|
|
1051
|
+
if (!entry) {
|
|
1052
|
+
throw new Error(`Task not found: ${id}`);
|
|
1053
|
+
}
|
|
1054
|
+
if (isJson()) {
|
|
1055
|
+
emitJson(entry);
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
log(`Task: ${entry.title}`);
|
|
1059
|
+
log(`Status: ${entry.status}`);
|
|
1060
|
+
log(`Goal: ${entry.goal}`);
|
|
1061
|
+
if (entry.outcome) log(`Outcome: ${entry.outcome}`);
|
|
1062
|
+
if (entry.followUps.length) log(`Follow-ups: ${entry.followUps.join("; ")}`);
|
|
1063
|
+
log(`Markdown: ${entry.markdownPath}`);
|
|
1064
|
+
});
|
|
1065
|
+
task.command("resume").description("Render a task handoff for the next agent.").argument("<id>", "Task id").addOption(new Option("--format <format>", "Output format").choices(["markdown", "json", "llms"]).default("markdown")).action(async (id, options) => {
|
|
1066
|
+
const result = await resumeMemoryTask(process2.cwd(), id, { format: options.format });
|
|
1067
|
+
if (isJson() || options.format === "json") {
|
|
1068
|
+
emitJson(result);
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
1071
|
+
log(result.rendered);
|
|
1072
|
+
});
|
|
1073
|
+
program.command("explore").description("Run a save-first multi-step exploration loop against the vault.").argument("<question>", "Root question to explore").option("--steps <n>", "Maximum number of exploration steps", "3").option("--gap-fill", "Pull external web-search evidence when the local wiki has gaps (requires webSearch.tasks.exploreProvider).").option("--task <id>", "Attach this exploration to an agent task").option("--memory <id>", "Compatibility alias for --task").addOption(
|
|
830
1074
|
new Option("--format <format>", "Output format for step pages").choices(["markdown", "report", "slides", "chart", "image"]).default("markdown")
|
|
831
1075
|
).action(
|
|
832
1076
|
async (question, options) => {
|
|
@@ -835,7 +1079,8 @@ program.command("explore").description("Run a save-first multi-step exploration
|
|
|
835
1079
|
question,
|
|
836
1080
|
steps: stepCount,
|
|
837
1081
|
format: options.format,
|
|
838
|
-
gapFill: options.gapFill ?? false
|
|
1082
|
+
gapFill: options.gapFill ?? false,
|
|
1083
|
+
memoryTaskId: options.task ?? options.memory
|
|
839
1084
|
});
|
|
840
1085
|
if (isJson()) {
|
|
841
1086
|
emitJson(result);
|
|
@@ -1468,7 +1713,7 @@ program.command("mcp").description("Run SwarmVault as a local MCP server over st
|
|
|
1468
1713
|
});
|
|
1469
1714
|
program.command("install").description("Install SwarmVault instructions for an agent in the current project.").requiredOption(
|
|
1470
1715
|
"--agent <agent>",
|
|
1471
|
-
"
|
|
1716
|
+
"claude, codex, cursor, gemini, goose, opencode, copilot, aider, droid, pi, trae, claw, kiro, hermes, antigravity, vscode, amp, augment, adal, bob, cline, codebuddy, command-code, continue, cortex, crush, deepagents, firebender, iflow, junie, kilo-code, kimi, kode, mcpjam, mistral-vibe, mux, neovate, openclaw, openhands, pochi, qoder, qwen-code, replit, roo-code, trae-cn, warp, windsurf, or zencoder"
|
|
1472
1717
|
).option("--hook", "Also install hook/plugin guidance when the target agent supports it", false).action(
|
|
1473
1718
|
async (options) => {
|
|
1474
1719
|
const hookCapableAgents = /* @__PURE__ */ new Set(["claude", "opencode", "gemini", "copilot"]);
|
|
@@ -1768,6 +2013,49 @@ program.command("diff").description("Show what changed in the knowledge graph si
|
|
|
1768
2013
|
}
|
|
1769
2014
|
}
|
|
1770
2015
|
});
|
|
2016
|
+
var retrieval = program.command("retrieval").description("Inspect and repair the local retrieval index.");
|
|
2017
|
+
retrieval.command("status").description("Show retrieval index health and configuration.").action(async () => {
|
|
2018
|
+
const status = await getRetrievalStatus(process2.cwd());
|
|
2019
|
+
if (isJson()) {
|
|
2020
|
+
emitJson(status);
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
2023
|
+
log(`Retrieval backend: ${status.configured.backend}`);
|
|
2024
|
+
log(`Index: ${status.indexExists ? "present" : "missing"} (${status.indexPath})`);
|
|
2025
|
+
log(`Manifest: ${status.manifestExists ? "present" : "missing"} (${status.manifestPath})`);
|
|
2026
|
+
log(`Graph: ${status.graphExists ? "present" : "missing"}`);
|
|
2027
|
+
log(`Pages indexed: ${status.pageCount}`);
|
|
2028
|
+
log(`State: ${status.stale ? "stale" : "fresh"}`);
|
|
2029
|
+
for (const warning of status.warnings) {
|
|
2030
|
+
log(`Warning: ${warning}`);
|
|
2031
|
+
}
|
|
2032
|
+
});
|
|
2033
|
+
retrieval.command("rebuild").description("Rebuild the local retrieval index from the current graph.").action(async () => {
|
|
2034
|
+
const status = await rebuildRetrievalIndex(process2.cwd());
|
|
2035
|
+
if (isJson()) {
|
|
2036
|
+
emitJson(status);
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
log(`Rebuilt retrieval index at ${status.indexPath}`);
|
|
2040
|
+
log(`Pages indexed: ${status.pageCount}`);
|
|
2041
|
+
});
|
|
2042
|
+
retrieval.command("doctor").description("Diagnose retrieval index problems and optionally repair them.").option("--repair", "Rebuild stale or missing retrieval artifacts", false).action(async (options) => {
|
|
2043
|
+
const result = await doctorRetrieval(process2.cwd(), { repair: options.repair });
|
|
2044
|
+
if (isJson()) {
|
|
2045
|
+
emitJson(result);
|
|
2046
|
+
return;
|
|
2047
|
+
}
|
|
2048
|
+
log(`Retrieval health: ${result.ok ? "ok" : "needs attention"}`);
|
|
2049
|
+
if (result.repaired) {
|
|
2050
|
+
log("Repaired retrieval index.");
|
|
2051
|
+
}
|
|
2052
|
+
if (result.actions.length) {
|
|
2053
|
+
log(`Suggested action(s): ${result.actions.join(", ")}`);
|
|
2054
|
+
}
|
|
2055
|
+
for (const warning of result.status.warnings) {
|
|
2056
|
+
log(`Warning: ${warning}`);
|
|
2057
|
+
}
|
|
2058
|
+
});
|
|
1771
2059
|
program.command("scan").description("Quick-start: initialize, ingest, compile, and serve a graph viewer in one command.").argument("<directory>", "Directory to scan").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").action(async (directory, options) => {
|
|
1772
2060
|
const rootDir = process2.cwd();
|
|
1773
2061
|
await initVault(rootDir, {});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmvaultai/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Global CLI for SwarmVault.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"node": ">=24.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@swarmvaultai/engine": "1.
|
|
41
|
+
"@swarmvaultai/engine": "3.1.0",
|
|
42
42
|
"commander": "^14.0.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|