@swarmvaultai/cli 3.6.0 → 3.7.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 +30 -4
- package/dist/index.js +95 -40
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ swarmvault init --obsidian --profile personal-research
|
|
|
26
26
|
swarmvault init --obsidian --profile reader,timeline
|
|
27
27
|
swarmvault demo
|
|
28
28
|
swarmvault source add https://github.com/karpathy/micrograd
|
|
29
|
+
swarmvault source add https://github.com/owner/repo --branch main --checkout-dir .swarmvault-checkouts/repo
|
|
29
30
|
swarmvault source add https://example.com/docs/getting-started
|
|
30
31
|
swarmvault source add ./exports/customer-call.srt --guide
|
|
31
32
|
swarmvault source session file-customer-call-srt-12345678
|
|
@@ -56,6 +57,7 @@ swarmvault graph blast ./src/index.ts
|
|
|
56
57
|
swarmvault graph status ./src
|
|
57
58
|
swarmvault graph update .
|
|
58
59
|
swarmvault graph cluster
|
|
60
|
+
swarmvault graph tree --output ./exports/tree.html
|
|
59
61
|
swarmvault graph query "Which nodes bridge the biggest clusters?"
|
|
60
62
|
swarmvault graph explain "concept:drift"
|
|
61
63
|
swarmvault watch status
|
|
@@ -65,6 +67,7 @@ swarmvault graph serve
|
|
|
65
67
|
swarmvault graph export --report ./exports/report.html
|
|
66
68
|
swarmvault graph export --html ./exports/graph.html
|
|
67
69
|
swarmvault graph export --cypher ./exports/graph.cypher
|
|
70
|
+
swarmvault graph merge ./exports/graph.json ./other-graph.json --out ./exports/merged-graph.json
|
|
68
71
|
swarmvault graph push neo4j --dry-run
|
|
69
72
|
```
|
|
70
73
|
|
|
@@ -91,16 +94,17 @@ Set `SWARMVAULT_OUT=<dir>` when generated artifacts should be isolated from the
|
|
|
91
94
|
|
|
92
95
|
`--profile` accepts `default`, `personal-research`, or a comma-separated preset list such as `reader,timeline`. For fully custom vault behavior, edit the `profile` block in `swarmvault.config.json`; that deterministic profile layer works alongside the human-written `swarmvault.schema.md`. The `personal-research` preset also sets `profile.guidedIngestDefault: true` and `profile.deepLintDefault: true`, so guided ingest/source and lint flows are on by default until you override them with `--no-guide` or `--no-deep`.
|
|
93
96
|
|
|
94
|
-
### `swarmvault scan <directory> [--port <port>] [--no-serve]`
|
|
97
|
+
### `swarmvault scan <directory|github-url> [--port <port>] [--no-serve] [--branch <name>] [--ref <ref>] [--checkout-dir <path>]`
|
|
95
98
|
|
|
96
|
-
Quick-start a scratch vault from a local directory in one command.
|
|
99
|
+
Quick-start a scratch vault from a local directory or public GitHub repo root URL in one command.
|
|
97
100
|
|
|
98
101
|
- initializes the current directory as a SwarmVault workspace
|
|
99
|
-
- ingests the supplied directory as local sources
|
|
102
|
+
- ingests the supplied directory as local sources, or registers/syncs the supplied public GitHub repo root URL
|
|
100
103
|
- compiles the vault immediately
|
|
101
104
|
- writes `wiki/graph/share-card.md`, `wiki/graph/share-card.svg`, and `wiki/graph/share-kit/`, then prints the paths
|
|
102
105
|
- starts `graph serve` unless you pass `--no-serve`
|
|
103
106
|
- respects `--port` when you want a specific viewer port
|
|
107
|
+
- for GitHub repo URLs, supports `--branch`, `--ref`, and `--checkout-dir`
|
|
104
108
|
|
|
105
109
|
Use this when you want the fastest repo or docs-tree walkthrough without first deciding on managed-source registration.
|
|
106
110
|
|
|
@@ -139,6 +143,7 @@ Run a whole-vault health check before handing the workspace to an agent or openi
|
|
|
139
143
|
Manage recurring source roots through a registry-backed workflow.
|
|
140
144
|
|
|
141
145
|
- `source add <input>` supports local files, local directories, public GitHub repo root URLs such as `https://github.com/karpathy/micrograd`, and docs/wiki/help/reference/tutorial hubs
|
|
146
|
+
- for public GitHub repo roots, `source add` supports `--branch <name>`, `--ref <ref>`, and `--checkout-dir <path>` so recurring sources can pin a branch, tag, commit, or reusable checkout directory
|
|
142
147
|
- by default `source add` registers the source, syncs it into the vault, runs one compile, and writes a source brief to `wiki/outputs/source-briefs/<source-id>.md`
|
|
143
148
|
- add `--guide` when you want a resumable source session, source brief, source review, source guide, and approval-bundled canonical page edits when `profile.guidedSessionMode` is `canonical_review`, with `wiki/insights/` fallback for `insights_only`
|
|
144
149
|
- set `profile.guidedIngestDefault: true` when guided mode should be the default for `source add` and `source reload`, and use `--no-guide` for individual light-path runs
|
|
@@ -185,7 +190,7 @@ Ingest a local file path, directory path, or URL into immutable source storage a
|
|
|
185
190
|
- local file and archive ingest supports markdown, text, reStructuredText, HTML, PDF, Word, RTF, OpenDocument, EPUB, CSV/TSV, Excel, PowerPoint, Jupyter notebooks, BibTeX, Org-mode, AsciiDoc, transcripts, Slack exports, email, calendar, audio, video, structured config/data, developer manifests, images, and code
|
|
186
191
|
- add `--guide` when you want a resumable source session, source brief, source review, source guide, and approval-bundled canonical page edits when `profile.guidedSessionMode` is `canonical_review`, with `wiki/insights/` fallback for `insights_only`
|
|
187
192
|
- set `profile.guidedIngestDefault: true` when guided mode should be the default for `ingest`, and use `--no-guide` to force a plain ingest for one run
|
|
188
|
-
- code-aware directory ingest currently covers JavaScript, JSX, TypeScript, TSX, Bash/shell scripts, Python, Go, Rust, Java, Kotlin, Scala, Dart, Lua, Zig, C#, C, C++, PHP, Ruby, PowerShell, Elixir, OCaml, Objective-C, ReScript, Solidity, HTML, CSS, Vue single-file components, and SQL files with table/view graph relations
|
|
193
|
+
- code-aware directory ingest currently covers JavaScript, JSX, TypeScript, TSX, Bash/shell scripts, Python, Go, Rust, Java, Kotlin, Scala, Dart, Lua, Zig, C#, C, C++, PHP, Ruby, PowerShell, Elixir, OCaml, Objective-C, ReScript, Solidity, HTML, CSS, Vue single-file components, Svelte single-file components, and SQL files with table/view graph relations. Julia, Verilog/SystemVerilog, and R files are detected as code sources and emit explicit parser-asset diagnostics until packaged WASM grammars are available.
|
|
189
194
|
|
|
190
195
|
Useful flags:
|
|
191
196
|
|
|
@@ -390,8 +395,29 @@ Refresh code-derived graph artifacts from tracked repo roots or one explicit rep
|
|
|
390
395
|
- runs the same code-only repo refresh path as `swarmvault watch --repo --code-only --once`
|
|
391
396
|
- without `path`, uses configured or auto-discovered watched repo roots
|
|
392
397
|
- with `path`, refreshes that repo root instead of the tracked set
|
|
398
|
+
- aborts if nodes or edges drop by more than 25% compared with the existing graph; pass `--force` or set `SWARMVAULT_FORCE_UPDATE=1` when the shrink is expected
|
|
393
399
|
- `--json` returns the same one-shot watch result shape, including repo import/update/remove counts and pending semantic refresh entries
|
|
394
400
|
|
|
401
|
+
### `swarmvault graph tree [--output <html>] [--root <path>] [--label <name>] [--max-children <n>]`
|
|
402
|
+
|
|
403
|
+
Write a collapsible HTML source tree for the current `state/graph.json`.
|
|
404
|
+
|
|
405
|
+
- groups sources by path, then shows module, symbol, and rationale nodes underneath each source
|
|
406
|
+
- defaults to `wiki/graph/tree.html`
|
|
407
|
+
- `--root` reads a different vault root without changing directories
|
|
408
|
+
- `--max-children` caps very wide folders or modules with a `+N more` row
|
|
409
|
+
- `--json` returns the output path, source count, node count, and tree payload
|
|
410
|
+
|
|
411
|
+
### `swarmvault graph merge <graph...> --out <path> [--label <name>]`
|
|
412
|
+
|
|
413
|
+
Merge multiple graph JSON files into one namespaced graph artifact.
|
|
414
|
+
|
|
415
|
+
- accepts native SwarmVault `state/graph.json` payloads
|
|
416
|
+
- accepts NetworkX/node-link style JSON with `nodes` plus `links` or `edges`
|
|
417
|
+
- prefixes ids from every input to avoid collisions
|
|
418
|
+
- maps explicit extracted/inferred/ambiguous edge evidence into SwarmVault edge semantics
|
|
419
|
+
- `--json` returns the merged graph, input summaries, and warnings
|
|
420
|
+
|
|
395
421
|
### `swarmvault graph status [path]`
|
|
396
422
|
|
|
397
423
|
Read-only graph freshness check for tracked repo roots or one explicit repo path.
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
exportGraphFormat,
|
|
31
31
|
exportGraphHtml,
|
|
32
32
|
exportGraphReportHtml,
|
|
33
|
+
exportGraphTree,
|
|
33
34
|
exportObsidianCanvas,
|
|
34
35
|
exportObsidianVault,
|
|
35
36
|
finishMemoryTask,
|
|
@@ -57,6 +58,7 @@ import {
|
|
|
57
58
|
listSchedules,
|
|
58
59
|
listWatchedRoots,
|
|
59
60
|
loadVaultConfig,
|
|
61
|
+
mergeGraphFiles,
|
|
60
62
|
pathGraphVault,
|
|
61
63
|
previewCandidatePromotions,
|
|
62
64
|
promoteCandidate,
|
|
@@ -311,9 +313,9 @@ program.name("swarmvault").description("SwarmVault is a local-first knowledge co
|
|
|
311
313
|
function readCliVersion() {
|
|
312
314
|
try {
|
|
313
315
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
314
|
-
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "3.
|
|
316
|
+
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "3.7.0";
|
|
315
317
|
} catch {
|
|
316
|
-
return "3.
|
|
318
|
+
return "3.7.0";
|
|
317
319
|
}
|
|
318
320
|
}
|
|
319
321
|
function parsePositiveInt(value, fallback) {
|
|
@@ -329,6 +331,9 @@ function parsePositiveNumber(value) {
|
|
|
329
331
|
function collectRepeated(value, previous) {
|
|
330
332
|
return [...previous, value];
|
|
331
333
|
}
|
|
334
|
+
function isHttpUrlInput(input) {
|
|
335
|
+
return input.startsWith("http://") || input.startsWith("https://");
|
|
336
|
+
}
|
|
332
337
|
function sourceScopeFromManifests(input, manifests) {
|
|
333
338
|
if (!manifests.length) {
|
|
334
339
|
return null;
|
|
@@ -666,7 +671,7 @@ program.command("add").description("Capture supported URLs into normalized markd
|
|
|
666
671
|
}
|
|
667
672
|
});
|
|
668
673
|
var source = program.command("source").description("Manage recurring local files, directories, public repos, and docs sources.");
|
|
669
|
-
source.command("add").description("Register and sync a managed source from a local file, directory, public GitHub repo root URL, or docs hub URL.").argument("<input>", "Local file path, directory path, public GitHub repo root URL, or docs hub URL").option("--no-compile", "Register and sync without compiling the vault").option("--no-brief", "Skip source brief generation after sync").option("--review", "Stage a source review artifact after sync and compile", false).option("--guide", "Stage a guided source integration bundle after sync and compile (default: from config)").option("--no-guide", "Skip guided mode even if enabled in config").option("--answers-file <path>", "JSON file with guided-session answers keyed by question id or listed in prompt order").option("--max-pages <n>", "Maximum number of pages to crawl for docs sources").option("--max-depth <n>", "Maximum crawl depth for docs sources").action(
|
|
674
|
+
source.command("add").description("Register and sync a managed source from a local file, directory, public GitHub repo root URL, or docs hub URL.").argument("<input>", "Local file path, directory path, public GitHub repo root URL, or docs hub URL").option("--no-compile", "Register and sync without compiling the vault").option("--no-brief", "Skip source brief generation after sync").option("--review", "Stage a source review artifact after sync and compile", false).option("--guide", "Stage a guided source integration bundle after sync and compile (default: from config)").option("--no-guide", "Skip guided mode even if enabled in config").option("--answers-file <path>", "JSON file with guided-session answers keyed by question id or listed in prompt order").option("--max-pages <n>", "Maximum number of pages to crawl for docs sources").option("--max-depth <n>", "Maximum crawl depth for docs sources").option("--branch <name>", "GitHub branch to clone for public repo sources").option("--ref <ref>", "Git ref, tag, or commit to check out after cloning a public repo source").option("--checkout-dir <path>", "Persistent checkout directory for a public GitHub repo source").action(
|
|
670
675
|
async (input, options) => {
|
|
671
676
|
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
672
677
|
const addConfig = await loadVaultConfig(process2.cwd()).catch(() => null);
|
|
@@ -678,7 +683,10 @@ source.command("add").description("Register and sync a managed source from a loc
|
|
|
678
683
|
guide: guideEnabled,
|
|
679
684
|
guideAnswers,
|
|
680
685
|
maxPages: options.maxPages ? parsePositiveInt(options.maxPages, 0) || void 0 : void 0,
|
|
681
|
-
maxDepth: options.maxDepth ? parsePositiveInt(options.maxDepth, 0) || void 0 : void 0
|
|
686
|
+
maxDepth: options.maxDepth ? parsePositiveInt(options.maxDepth, 0) || void 0 : void 0,
|
|
687
|
+
branch: options.branch,
|
|
688
|
+
ref: options.ref,
|
|
689
|
+
checkoutDir: options.checkoutDir
|
|
682
690
|
});
|
|
683
691
|
if (result.guide && !options.answersFile) {
|
|
684
692
|
result.guide = await completeGuideInteractively(result.guide, result.source.id);
|
|
@@ -1144,12 +1152,13 @@ program.command("lint").description("Run anti-drift and wiki-health checks.").op
|
|
|
1144
1152
|
});
|
|
1145
1153
|
var graph = program.command("graph").description("Graph-related commands.").enablePositionalOptions();
|
|
1146
1154
|
var graphPush = graph.command("push").description("Push the compiled graph into external sinks.");
|
|
1147
|
-
graph.command("update").alias("refresh").description("Refresh code-derived graph artifacts from tracked repo roots or one explicit repo path.").argument("[path]", "Optional repo root to refresh instead of configured/tracked roots").option("--lint", "Run lint after the refresh cycle", false).action(async (targetPath, options) => {
|
|
1155
|
+
graph.command("update").alias("refresh").description("Refresh code-derived graph artifacts from tracked repo roots or one explicit repo path.").argument("[path]", "Optional repo root to refresh instead of configured/tracked roots").option("--lint", "Run lint after the refresh cycle", false).option("--force", "Allow graph updates even when node or edge counts shrink sharply", false).action(async (targetPath, options) => {
|
|
1148
1156
|
const overrideRoots = targetPath ? [path2.resolve(process2.cwd(), targetPath)] : void 0;
|
|
1149
1157
|
const result = await runWatchCycle(process2.cwd(), {
|
|
1150
1158
|
repo: true,
|
|
1151
1159
|
codeOnly: true,
|
|
1152
1160
|
lint: options.lint ?? false,
|
|
1161
|
+
force: options.force ?? false,
|
|
1153
1162
|
overrideRoots
|
|
1154
1163
|
});
|
|
1155
1164
|
if (isJson()) {
|
|
@@ -1160,6 +1169,36 @@ graph.command("update").alias("refresh").description("Refresh code-derived graph
|
|
|
1160
1169
|
`Updated graph from ${result.watchedRepoRoots.length} repo root${result.watchedRepoRoots.length === 1 ? "" : "s"}. Imported ${result.repoImportedCount}, updated ${result.repoUpdatedCount}, removed ${result.repoRemovedCount}, pending semantic refresh ${result.pendingSemanticRefreshCount}.`
|
|
1161
1170
|
);
|
|
1162
1171
|
});
|
|
1172
|
+
graph.command("tree").description("Write a collapsible source/module/symbol tree for the compiled graph.").option("--output <html>", "Output HTML path (default: wiki/graph/tree.html)").option("--root <path>", "Vault root to read instead of the current directory").option("--label <name>", "Tree title").option("--max-children <n>", "Maximum children to render per tree node", "250").action(async (options) => {
|
|
1173
|
+
const rootDir = options.root ? path2.resolve(process2.cwd(), options.root) : process2.cwd();
|
|
1174
|
+
const result = await exportGraphTree(rootDir, options.output, {
|
|
1175
|
+
label: options.label,
|
|
1176
|
+
maxChildren: parsePositiveInt(options.maxChildren, 250)
|
|
1177
|
+
});
|
|
1178
|
+
if (isJson()) {
|
|
1179
|
+
emitJson(result);
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
log(`Graph tree: ${result.outputPath}`);
|
|
1183
|
+
log(`Sources: ${result.sourceCount}; nodes: ${result.nodeCount}.`);
|
|
1184
|
+
});
|
|
1185
|
+
graph.command("merge").description("Merge SwarmVault or node-link JSON graph files into one namespaced graph artifact.").argument("<graphs...>", "Graph JSON files to merge").requiredOption("--out <path>", "Output graph JSON path").option("--label <name>", "Label/prefix to use when merging one graph").action(async (graphPaths, options) => {
|
|
1186
|
+
const result = await mergeGraphFiles(
|
|
1187
|
+
graphPaths.map((inputPath) => path2.resolve(process2.cwd(), inputPath)),
|
|
1188
|
+
path2.resolve(process2.cwd(), options.out),
|
|
1189
|
+
{ label: options.label }
|
|
1190
|
+
);
|
|
1191
|
+
if (isJson()) {
|
|
1192
|
+
emitJson(result);
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
log(
|
|
1196
|
+
`Merged ${result.inputGraphs.length} graph${result.inputGraphs.length === 1 ? "" : "s"} into ${result.outputPath}. Nodes ${result.graph.nodes.length}, edges ${result.graph.edges.length}.`
|
|
1197
|
+
);
|
|
1198
|
+
for (const warning of result.warnings) {
|
|
1199
|
+
log(`Warning: ${warning}`);
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1163
1202
|
graph.command("status").description("Read-only check for graph/report presence and tracked repo changes.").argument("[path]", "Optional repo root to check instead of configured/tracked roots").action(async (targetPath) => {
|
|
1164
1203
|
const overrideRoots = targetPath ? [path2.resolve(process2.cwd(), targetPath)] : void 0;
|
|
1165
1204
|
const status = await getGraphStatus(process2.cwd(), { repoRoots: overrideRoots });
|
|
@@ -1588,47 +1627,51 @@ async function confirmInteractive(message) {
|
|
|
1588
1627
|
rl.close();
|
|
1589
1628
|
}
|
|
1590
1629
|
}
|
|
1591
|
-
var watch = program.command("watch").description("Watch the inbox directory and optionally tracked repos, or run one refresh cycle immediately.").option("--lint", "Run lint after each compile cycle", false).option("--repo", "Also refresh tracked repo sources and watch their repo roots", false).option("--once", "Run one import/refresh cycle immediately instead of starting a watcher", false).option("--code-only", "Only re-extract code sources (AST-only, no LLM re-analysis)", false).option("--debounce <ms>", "Debounce window in milliseconds", "900").option("--root <path>", "Watch this repo root instead of config/auto-discovery (repeat for multiple)", collectRepeated, []).
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1630
|
+
var watch = program.command("watch").description("Watch the inbox directory and optionally tracked repos, or run one refresh cycle immediately.").option("--lint", "Run lint after each compile cycle", false).option("--repo", "Also refresh tracked repo sources and watch their repo roots", false).option("--once", "Run one import/refresh cycle immediately instead of starting a watcher", false).option("--code-only", "Only re-extract code sources (AST-only, no LLM re-analysis)", false).option("--debounce <ms>", "Debounce window in milliseconds", "900").option("--root <path>", "Watch this repo root instead of config/auto-discovery (repeat for multiple)", collectRepeated, []).option("--force", "Allow graph updates even when node or edge counts shrink sharply", false).action(
|
|
1631
|
+
async (options) => {
|
|
1632
|
+
const debounceMs = parsePositiveInt(options.debounce, 900);
|
|
1633
|
+
const overrideRoots = options.root && options.root.length > 0 ? options.root : void 0;
|
|
1634
|
+
if (options.once) {
|
|
1635
|
+
const result = await runWatchCycle(process2.cwd(), {
|
|
1636
|
+
lint: options.lint ?? false,
|
|
1637
|
+
repo: options.repo ?? false,
|
|
1638
|
+
codeOnly: options.codeOnly ?? false,
|
|
1639
|
+
debounceMs,
|
|
1640
|
+
force: options.force ?? false,
|
|
1641
|
+
overrideRoots
|
|
1642
|
+
});
|
|
1643
|
+
if (isJson()) {
|
|
1644
|
+
emitJson(result);
|
|
1645
|
+
} else {
|
|
1646
|
+
log(
|
|
1647
|
+
`Refreshed inbox${options.repo ? " and tracked repos" : ""}. Imported ${result.importedCount}, repo imported ${result.repoImportedCount}, repo updated ${result.repoUpdatedCount}, repo removed ${result.repoRemovedCount}.`
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
const { paths } = await loadVaultConfig(process2.cwd());
|
|
1653
|
+
const controller = await watchVault(process2.cwd(), {
|
|
1596
1654
|
lint: options.lint ?? false,
|
|
1597
1655
|
repo: options.repo ?? false,
|
|
1598
1656
|
codeOnly: options.codeOnly ?? false,
|
|
1599
1657
|
debounceMs,
|
|
1658
|
+
force: options.force ?? false,
|
|
1600
1659
|
overrideRoots
|
|
1601
1660
|
});
|
|
1602
1661
|
if (isJson()) {
|
|
1603
|
-
emitJson(
|
|
1662
|
+
emitJson({ status: "watching", inboxDir: paths.inboxDir, repo: options.repo ?? false });
|
|
1604
1663
|
} else {
|
|
1605
|
-
log(
|
|
1606
|
-
`Refreshed inbox${options.repo ? " and tracked repos" : ""}. Imported ${result.importedCount}, repo imported ${result.repoImportedCount}, repo updated ${result.repoUpdatedCount}, repo removed ${result.repoRemovedCount}.`
|
|
1607
|
-
);
|
|
1664
|
+
log(`Watching inbox${options.repo ? " and tracked repos" : ""} for changes. Press Ctrl+C to stop.`);
|
|
1608
1665
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
debounceMs,
|
|
1617
|
-
overrideRoots
|
|
1618
|
-
});
|
|
1619
|
-
if (isJson()) {
|
|
1620
|
-
emitJson({ status: "watching", inboxDir: paths.inboxDir, repo: options.repo ?? false });
|
|
1621
|
-
} else {
|
|
1622
|
-
log(`Watching inbox${options.repo ? " and tracked repos" : ""} for changes. Press Ctrl+C to stop.`);
|
|
1666
|
+
process2.on("SIGINT", async () => {
|
|
1667
|
+
try {
|
|
1668
|
+
await controller.close();
|
|
1669
|
+
} catch {
|
|
1670
|
+
}
|
|
1671
|
+
process2.exit(0);
|
|
1672
|
+
});
|
|
1623
1673
|
}
|
|
1624
|
-
|
|
1625
|
-
try {
|
|
1626
|
-
await controller.close();
|
|
1627
|
-
} catch {
|
|
1628
|
-
}
|
|
1629
|
-
process2.exit(0);
|
|
1630
|
-
});
|
|
1631
|
-
});
|
|
1674
|
+
);
|
|
1632
1675
|
watch.command("list-roots").description("Print the effective watched repo roots resolved from config and auto-discovery.").action(async () => {
|
|
1633
1676
|
const roots = await listWatchedRoots(process2.cwd());
|
|
1634
1677
|
if (isJson()) {
|
|
@@ -2153,17 +2196,29 @@ retrieval.command("doctor").description("Diagnose retrieval index problems and o
|
|
|
2153
2196
|
log(`Warning: ${warning}`);
|
|
2154
2197
|
}
|
|
2155
2198
|
});
|
|
2156
|
-
program.command("scan").description("Quick-start: initialize, ingest, compile, and serve a graph viewer in one command.").argument("<
|
|
2199
|
+
program.command("scan").description("Quick-start: initialize, ingest, compile, and serve a graph viewer in one command.").argument("<input>", "Directory or public GitHub repo root URL to scan").option("--port <port>", "Port for the graph viewer").option("--no-serve", "Skip launching the graph viewer after compile").option("--branch <name>", "GitHub branch to clone when scanning a public repo URL").option("--ref <ref>", "Git ref, tag, or commit to check out when scanning a public repo URL").option("--checkout-dir <path>", "Persistent checkout directory for a public GitHub repo scan").action(async (input, options) => {
|
|
2157
2200
|
const rootDir = process2.cwd();
|
|
2158
2201
|
await initVault(rootDir, {});
|
|
2159
2202
|
if (!isJson()) {
|
|
2160
2203
|
log("Initialized workspace.");
|
|
2161
2204
|
}
|
|
2162
|
-
const result = await
|
|
2205
|
+
const result = isHttpUrlInput(input) ? await addManagedSource(rootDir, input, {
|
|
2206
|
+
compile: true,
|
|
2207
|
+
brief: false,
|
|
2208
|
+
branch: options.branch,
|
|
2209
|
+
ref: options.ref,
|
|
2210
|
+
checkoutDir: options.checkoutDir
|
|
2211
|
+
}) : await ingestDirectory(rootDir, input, {});
|
|
2163
2212
|
if (!isJson()) {
|
|
2164
|
-
|
|
2213
|
+
if ("source" in result) {
|
|
2214
|
+
log(
|
|
2215
|
+
`Registered ${result.source.kind} source ${result.source.id}. Imported ${result.source.lastSyncCounts?.importedCount ?? 0}, updated ${result.source.lastSyncCounts?.updatedCount ?? 0}.`
|
|
2216
|
+
);
|
|
2217
|
+
} else {
|
|
2218
|
+
log(`Ingested ${result.imported.length} file(s).`);
|
|
2219
|
+
}
|
|
2165
2220
|
}
|
|
2166
|
-
const compiled = await compileVault(rootDir, {});
|
|
2221
|
+
const compiled = "compile" in result && result.compile ? result.compile : await compileVault(rootDir, {});
|
|
2167
2222
|
const { paths } = await loadVaultConfig(rootDir);
|
|
2168
2223
|
const shareCardPath = path2.join(paths.wikiDir, "graph", "share-card.md");
|
|
2169
2224
|
const shareCardSvgPath = path2.join(paths.wikiDir, "graph", "share-card.svg");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmvaultai/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "Global CLI for SwarmVault.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"prepublishOnly": "node ../../scripts/check-release-sync.mjs && node ../../scripts/check-published-manifests.mjs"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@swarmvaultai/engine": "3.
|
|
47
|
+
"@swarmvaultai/engine": "3.7.0",
|
|
48
48
|
"commander": "^14.0.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|