@swarmvaultai/cli 0.5.0 → 0.6.1
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 +14 -7
- package/dist/index.js +120 -19
- package/package.json +8 -8
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -23,9 +23,11 @@ Installed commands:
|
|
|
23
23
|
mkdir my-vault
|
|
24
24
|
cd my-vault
|
|
25
25
|
swarmvault init --obsidian --profile personal-research
|
|
26
|
+
swarmvault init --obsidian --profile reader,timeline
|
|
26
27
|
swarmvault source add https://github.com/karpathy/micrograd
|
|
27
28
|
swarmvault source add https://example.com/docs/getting-started
|
|
28
29
|
swarmvault source add ./exports/customer-call.srt --guide
|
|
30
|
+
swarmvault source session file-customer-call-srt-12345678
|
|
29
31
|
swarmvault source list
|
|
30
32
|
swarmvault source reload --all
|
|
31
33
|
sed -n '1,120p' swarmvault.schema.md
|
|
@@ -51,7 +53,7 @@ swarmvault graph push neo4j --dry-run
|
|
|
51
53
|
|
|
52
54
|
## Commands
|
|
53
55
|
|
|
54
|
-
### `swarmvault init [--obsidian] [--profile
|
|
56
|
+
### `swarmvault init [--obsidian] [--profile <alias-or-presets>]`
|
|
55
57
|
|
|
56
58
|
Create a workspace with:
|
|
57
59
|
|
|
@@ -68,29 +70,33 @@ Create a workspace with:
|
|
|
68
70
|
|
|
69
71
|
The schema file is the vault-specific instruction layer. Edit it to define naming rules, categories, grounding expectations, and exclusions before a serious compile.
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
`--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`.
|
|
74
|
+
|
|
75
|
+
### `swarmvault source add|list|reload|review|guide|session|delete`
|
|
72
76
|
|
|
73
77
|
Manage recurring source roots through a registry-backed workflow.
|
|
74
78
|
|
|
75
|
-
- `source add <input>` supports local directories, public GitHub repo root URLs such as `https://github.com/karpathy/micrograd`, and docs/wiki/help/reference/tutorial hubs
|
|
79
|
+
- `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
|
|
76
80
|
- 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`
|
|
77
|
-
- add `--guide` when you want a source brief, source review, source guide, and approval
|
|
81
|
+
- 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`
|
|
78
82
|
- `source list` shows every managed source with its kind, status, and current brief path
|
|
79
83
|
- `source reload [id]` re-syncs one source, or use `--all` to refresh everything in the registry and compile once
|
|
80
84
|
- `source review <id>` stages a lighter source-scoped review artifact
|
|
81
|
-
- `source guide <id>`
|
|
85
|
+
- `source guide <id>` remains a compatibility alias for the guided session flow
|
|
86
|
+
- `source session <id>` resumes the latest guided session for a managed source id, raw source id, source scope id, or session id
|
|
82
87
|
- `source delete <id>` unregisters the source and removes transient sync state under `state/sources/<id>/`, but leaves canonical `raw/`, `wiki/`, and saved output artifacts intact
|
|
83
88
|
|
|
84
89
|
Useful flags:
|
|
85
90
|
|
|
86
91
|
- `--all`
|
|
87
92
|
- `--guide`
|
|
93
|
+
- `--answers-file <path>`
|
|
88
94
|
- `--no-compile`
|
|
89
95
|
- `--no-brief`
|
|
90
96
|
- `--max-pages <n>`
|
|
91
97
|
- `--max-depth <n>`
|
|
92
98
|
|
|
93
|
-
Managed sources write registry state to `state/sources.json`. Local directory entries remain compatible with `watch --repo`; remote GitHub and docs-crawl sources are manual `source reload` sources in this release.
|
|
99
|
+
Managed sources write registry state to `state/sources.json`. Guided sessions write durable anchors to `wiki/outputs/source-sessions/` and session state to `state/source-sessions/`. In an interactive TTY, `--guide` can ask the session questions immediately; otherwise use `source session <id>` or `--answers-file <path>` to resume and stage the approval bundle later. Local directory entries remain compatible with `watch --repo`; remote GitHub and docs-crawl sources are manual `source reload` sources in this release.
|
|
94
100
|
|
|
95
101
|
### `swarmvault ingest <path-or-url>`
|
|
96
102
|
|
|
@@ -102,12 +108,13 @@ Ingest a local file path, directory path, or URL into immutable source storage a
|
|
|
102
108
|
- use `source add` instead when the same local directory, public GitHub repo root, or docs hub should stay registered and reloadable
|
|
103
109
|
- URL ingest still localizes remote image references by default
|
|
104
110
|
- local file ingest supports markdown, text, reStructuredText, HTML, PDF, DOCX, images, and code
|
|
105
|
-
- add `--guide` when you want a source brief, source review, source guide, and approval
|
|
111
|
+
- 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`
|
|
106
112
|
- code-aware directory ingest currently covers JavaScript, JSX, TypeScript, TSX, Python, Go, Rust, Java, Kotlin, Scala, Lua, Zig, C#, C, C++, PHP, Ruby, and PowerShell
|
|
107
113
|
|
|
108
114
|
Useful flags:
|
|
109
115
|
|
|
110
116
|
- `--repo-root <path>`
|
|
117
|
+
- `--answers-file <path>`
|
|
111
118
|
- `--include <glob...>`
|
|
112
119
|
- `--exclude <glob...>`
|
|
113
120
|
- `--max-files <n>`
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { readFileSync } from "fs";
|
|
5
5
|
import process2 from "process";
|
|
6
|
+
import { createInterface } from "readline/promises";
|
|
6
7
|
import {
|
|
7
8
|
acceptApproval,
|
|
8
9
|
addInput,
|
|
@@ -41,6 +42,7 @@ import {
|
|
|
41
42
|
readApproval,
|
|
42
43
|
rejectApproval,
|
|
43
44
|
reloadManagedSources,
|
|
45
|
+
resumeSourceSession,
|
|
44
46
|
reviewManagedSource,
|
|
45
47
|
reviewSourceScope,
|
|
46
48
|
runSchedule,
|
|
@@ -226,9 +228,9 @@ program.name("swarmvault").description("SwarmVault is a local-first knowledge co
|
|
|
226
228
|
function readCliVersion() {
|
|
227
229
|
try {
|
|
228
230
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
229
|
-
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "0.
|
|
231
|
+
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "0.6.1";
|
|
230
232
|
} catch {
|
|
231
|
-
return "0.
|
|
233
|
+
return "0.6.1";
|
|
232
234
|
}
|
|
233
235
|
}
|
|
234
236
|
function parsePositiveInt(value, fallback) {
|
|
@@ -271,6 +273,57 @@ function emitNotice(message) {
|
|
|
271
273
|
process2.stderr.write(`[swarmvault] ${message}
|
|
272
274
|
`);
|
|
273
275
|
}
|
|
276
|
+
function canPromptGuide() {
|
|
277
|
+
return Boolean(process2.stdin.isTTY && process2.stdout.isTTY && !isJson());
|
|
278
|
+
}
|
|
279
|
+
function readGuideAnswersFile(filePath) {
|
|
280
|
+
if (!filePath) {
|
|
281
|
+
return void 0;
|
|
282
|
+
}
|
|
283
|
+
const raw = JSON.parse(readFileSync(filePath, "utf8"));
|
|
284
|
+
if (Array.isArray(raw)) {
|
|
285
|
+
return raw.filter((value) => typeof value === "string");
|
|
286
|
+
}
|
|
287
|
+
if (raw && typeof raw === "object") {
|
|
288
|
+
return Object.fromEntries(
|
|
289
|
+
Object.entries(raw).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string")
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
throw new Error("Guide answers files must contain either a JSON object keyed by question id or a JSON array of answers.");
|
|
293
|
+
}
|
|
294
|
+
async function promptGuideAnswers(questions) {
|
|
295
|
+
const rl = createInterface({
|
|
296
|
+
input: process2.stdin,
|
|
297
|
+
output: process2.stdout
|
|
298
|
+
});
|
|
299
|
+
try {
|
|
300
|
+
const answers = {};
|
|
301
|
+
for (const question of questions) {
|
|
302
|
+
const promptLines = [question.prompt];
|
|
303
|
+
if (question.answer) {
|
|
304
|
+
promptLines.push(`Current: ${question.answer}`);
|
|
305
|
+
promptLines.push("Press Enter to keep the current answer.");
|
|
306
|
+
}
|
|
307
|
+
const answer = (await rl.question(`${promptLines.join("\n")}
|
|
308
|
+
> `)).trim();
|
|
309
|
+
if (answer) {
|
|
310
|
+
answers[question.id] = answer;
|
|
311
|
+
} else if (question.answer) {
|
|
312
|
+
answers[question.id] = question.answer;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return answers;
|
|
316
|
+
} finally {
|
|
317
|
+
rl.close();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async function completeGuideInteractively(guide, fallbackTarget) {
|
|
321
|
+
if (!guide.awaitingInput || !canPromptGuide()) {
|
|
322
|
+
return guide;
|
|
323
|
+
}
|
|
324
|
+
const answers = await promptGuideAnswers(guide.questions);
|
|
325
|
+
return await resumeSourceSession(process2.cwd(), guide.sessionId || fallbackTarget, { answers });
|
|
326
|
+
}
|
|
274
327
|
function getCommandPath(command) {
|
|
275
328
|
const names = [];
|
|
276
329
|
let current = command;
|
|
@@ -293,7 +346,10 @@ program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
|
293
346
|
emitNotice(notice);
|
|
294
347
|
}
|
|
295
348
|
});
|
|
296
|
-
program.command("init").description("Initialize a SwarmVault workspace in the current directory.").option("--obsidian", "Generate a minimal .obsidian workspace alongside the vault", false).
|
|
349
|
+
program.command("init").description("Initialize a SwarmVault workspace in the current directory.").option("--obsidian", "Generate a minimal .obsidian workspace alongside the vault", false).option(
|
|
350
|
+
"--profile <profile>",
|
|
351
|
+
"Starter workspace profile or comma-separated preset list (for example: personal-research or reader,timeline)"
|
|
352
|
+
).action(async (options) => {
|
|
297
353
|
await initVault(process2.cwd(), { obsidian: options.obsidian ?? false, profile: options.profile });
|
|
298
354
|
if (isJson()) {
|
|
299
355
|
emitJson({
|
|
@@ -306,8 +362,9 @@ program.command("init").description("Initialize a SwarmVault workspace in the cu
|
|
|
306
362
|
log("Initialized SwarmVault workspace.");
|
|
307
363
|
}
|
|
308
364
|
});
|
|
309
|
-
program.command("ingest").description("Ingest a local file path, directory path, or URL into the raw SwarmVault workspace.").argument("<input>", "Local file path, directory path, or URL").option("--review", "Stage a source review artifact after ingest and compile", false).option("--guide", "Stage a guided source integration bundle after ingest and compile", false).option("--include-assets", "Download remote image assets when ingesting URLs", true).option("--no-include-assets", "Skip downloading remote image assets when ingesting URLs").option("--max-asset-size <bytes>", "Maximum number of bytes to fetch for a single remote image asset").option("--repo-root <path>", "Override the detected repo root when ingesting a directory").option("--include <glob...>", "Only ingest files matching one or more glob patterns").option("--exclude <glob...>", "Skip files matching one or more glob patterns").option("--max-files <n>", "Maximum number of files to ingest from a directory").option("--include-third-party", "Also ingest repo files classified as third-party", false).option("--include-resources", "Also ingest repo files classified as resources", false).option("--include-generated", "Also ingest repo files classified as generated output", false).option("--no-gitignore", "Ignore .gitignore rules when ingesting a directory").action(
|
|
365
|
+
program.command("ingest").description("Ingest a local file path, directory path, or URL into the raw SwarmVault workspace.").argument("<input>", "Local file path, directory path, or URL").option("--review", "Stage a source review artifact after ingest and compile", false).option("--guide", "Stage a guided source integration bundle after ingest and compile", false).option("--answers-file <path>", "JSON file with guided-session answers keyed by question id or listed in prompt order").option("--include-assets", "Download remote image assets when ingesting URLs", true).option("--no-include-assets", "Skip downloading remote image assets when ingesting URLs").option("--max-asset-size <bytes>", "Maximum number of bytes to fetch for a single remote image asset").option("--repo-root <path>", "Override the detected repo root when ingesting a directory").option("--include <glob...>", "Only ingest files matching one or more glob patterns").option("--exclude <glob...>", "Skip files matching one or more glob patterns").option("--max-files <n>", "Maximum number of files to ingest from a directory").option("--include-third-party", "Also ingest repo files classified as third-party", false).option("--include-resources", "Also ingest repo files classified as resources", false).option("--include-generated", "Also ingest repo files classified as generated output", false).option("--no-gitignore", "Ignore .gitignore rules when ingesting a directory").action(
|
|
310
366
|
async (input, options) => {
|
|
367
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
311
368
|
const maxAssetSize = typeof options.maxAssetSize === "string" && options.maxAssetSize.trim() ? parsePositiveInt(options.maxAssetSize, 0) || void 0 : void 0;
|
|
312
369
|
const maxFiles = typeof options.maxFiles === "string" && options.maxFiles.trim() ? parsePositiveInt(options.maxFiles, 0) || void 0 : void 0;
|
|
313
370
|
const extractClasses = [
|
|
@@ -354,10 +411,13 @@ program.command("ingest").description("Ingest a local file path, directory path,
|
|
|
354
411
|
})() : void 0;
|
|
355
412
|
const guide2 = shouldStage && options.guide ? await (async () => {
|
|
356
413
|
await compileVault(process2.cwd(), {});
|
|
357
|
-
return await guideSourceScope(process2.cwd(), scope2);
|
|
414
|
+
return await guideSourceScope(process2.cwd(), scope2, { answers: guideAnswers });
|
|
358
415
|
})() : void 0;
|
|
416
|
+
const completedGuide2 = guide2 && !options.answersFile ? await completeGuideInteractively(guide2, scope2?.id ?? input) : guide2;
|
|
359
417
|
if (isJson()) {
|
|
360
|
-
emitJson(
|
|
418
|
+
emitJson(
|
|
419
|
+
completedGuide2 ? { ingest: directoryResult, guide: completedGuide2 } : review3 ? { ingest: directoryResult, review: review3 } : directoryResult
|
|
420
|
+
);
|
|
361
421
|
} else {
|
|
362
422
|
log(
|
|
363
423
|
`Imported ${directoryResult.imported.length} file(s), updated ${directoryResult.updated.length}, skipped ${directoryResult.skipped.length}.`
|
|
@@ -365,8 +425,12 @@ program.command("ingest").description("Ingest a local file path, directory path,
|
|
|
365
425
|
if (review3) {
|
|
366
426
|
log(`Staged source review at ${review3.reviewPath}.`);
|
|
367
427
|
}
|
|
368
|
-
if (
|
|
369
|
-
log(
|
|
428
|
+
if (completedGuide2?.awaitingInput) {
|
|
429
|
+
log(
|
|
430
|
+
`Created guided session at ${completedGuide2.sessionPath}. Resume with \`swarmvault source session ${completedGuide2.sessionId}\`.`
|
|
431
|
+
);
|
|
432
|
+
} else if (completedGuide2?.guidePath) {
|
|
433
|
+
log(`Staged guided session at ${completedGuide2.guidePath}.`);
|
|
370
434
|
}
|
|
371
435
|
}
|
|
372
436
|
return;
|
|
@@ -379,10 +443,11 @@ program.command("ingest").description("Ingest a local file path, directory path,
|
|
|
379
443
|
})() : void 0;
|
|
380
444
|
const guide = options.guide && scope && (ingest.created.length || ingest.updated.length || ingest.unchanged.length) ? await (async () => {
|
|
381
445
|
await compileVault(process2.cwd(), {});
|
|
382
|
-
return await guideSourceScope(process2.cwd(), scope);
|
|
446
|
+
return await guideSourceScope(process2.cwd(), scope, { answers: guideAnswers });
|
|
383
447
|
})() : void 0;
|
|
448
|
+
const completedGuide = guide && !options.answersFile ? await completeGuideInteractively(guide, scope?.id ?? input) : guide;
|
|
384
449
|
if (isJson()) {
|
|
385
|
-
emitJson(
|
|
450
|
+
emitJson(completedGuide ? { ingest, guide: completedGuide } : review2 ? { ingest, review: review2 } : ingest);
|
|
386
451
|
} else {
|
|
387
452
|
const primary = [...ingest.created, ...ingest.updated, ...ingest.unchanged][0];
|
|
388
453
|
if (ingest.created.length + ingest.updated.length + ingest.removed.length <= 1 && primary) {
|
|
@@ -395,8 +460,12 @@ program.command("ingest").description("Ingest a local file path, directory path,
|
|
|
395
460
|
if (review2) {
|
|
396
461
|
log(`Staged source review at ${review2.reviewPath}.`);
|
|
397
462
|
}
|
|
398
|
-
if (
|
|
399
|
-
log(
|
|
463
|
+
if (completedGuide?.awaitingInput) {
|
|
464
|
+
log(
|
|
465
|
+
`Created guided session at ${completedGuide.sessionPath}. Resume with \`swarmvault source session ${completedGuide.sessionId}\`.`
|
|
466
|
+
);
|
|
467
|
+
} else if (completedGuide?.guidePath) {
|
|
468
|
+
log(`Staged guided session at ${completedGuide.guidePath}.`);
|
|
400
469
|
}
|
|
401
470
|
}
|
|
402
471
|
}
|
|
@@ -413,21 +482,26 @@ program.command("add").description("Capture supported URLs into normalized markd
|
|
|
413
482
|
}
|
|
414
483
|
});
|
|
415
484
|
var source = program.command("source").description("Manage recurring local files, directories, public repos, and docs sources.");
|
|
416
|
-
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", false).option("--max-pages <n>", "Maximum number of pages to crawl for docs sources").option("--max-depth <n>", "Maximum crawl depth for docs sources").action(
|
|
485
|
+
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", false).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(
|
|
417
486
|
async (input, options) => {
|
|
487
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
418
488
|
const result = await addManagedSource(process2.cwd(), input, {
|
|
419
489
|
compile: options.compile,
|
|
420
490
|
brief: options.brief,
|
|
421
491
|
review: options.review,
|
|
422
492
|
guide: options.guide,
|
|
493
|
+
guideAnswers,
|
|
423
494
|
maxPages: options.maxPages ? parsePositiveInt(options.maxPages, 0) || void 0 : void 0,
|
|
424
495
|
maxDepth: options.maxDepth ? parsePositiveInt(options.maxDepth, 0) || void 0 : void 0
|
|
425
496
|
});
|
|
497
|
+
if (result.guide && !options.answersFile) {
|
|
498
|
+
result.guide = await completeGuideInteractively(result.guide, result.source.id);
|
|
499
|
+
}
|
|
426
500
|
if (isJson()) {
|
|
427
501
|
emitJson(result);
|
|
428
502
|
} else {
|
|
429
503
|
log(
|
|
430
|
-
`Registered ${result.source.kind} source ${result.source.id}. Status: ${result.source.status}.${result.compile ? ` Compiled ${result.compile.sourceCount} source(s).` : ""}${result.briefGenerated ? ` Brief: ${result.source.briefPath}` : ""}${result.review ? ` Review: ${result.review.reviewPath}` : ""}${result.guide ? ` Guide: ${result.guide.guidePath}` : ""}`
|
|
504
|
+
`Registered ${result.source.kind} source ${result.source.id}. Status: ${result.source.status}.${result.compile ? ` Compiled ${result.compile.sourceCount} source(s).` : ""}${result.briefGenerated ? ` Brief: ${result.source.briefPath}` : ""}${result.review ? ` Review: ${result.review.reviewPath}` : ""}${result.guide?.awaitingInput ? ` Session: ${result.guide.sessionPath}. Resume with \`swarmvault source session ${result.guide.sessionId}\`.` : result.guide?.guidePath ? ` Guide: ${result.guide.guidePath}` : ""}`
|
|
431
505
|
);
|
|
432
506
|
}
|
|
433
507
|
}
|
|
@@ -444,8 +518,9 @@ source.command("list").description("List managed sources registered in this vaul
|
|
|
444
518
|
}
|
|
445
519
|
}
|
|
446
520
|
});
|
|
447
|
-
source.command("reload").description("Re-sync one managed source or all managed sources, then optionally compile and refresh briefs.").argument("[id]", "Managed source id").option("--all", "Reload all managed sources", false).option("--no-compile", "Re-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", false).option("--max-pages <n>", "Maximum number of pages to crawl for docs sources").option("--max-depth <n>", "Maximum crawl depth for docs sources").action(
|
|
521
|
+
source.command("reload").description("Re-sync one managed source or all managed sources, then optionally compile and refresh briefs.").argument("[id]", "Managed source id").option("--all", "Reload all managed sources", false).option("--no-compile", "Re-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", false).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(
|
|
448
522
|
async (id, options) => {
|
|
523
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
449
524
|
const result = await reloadManagedSources(process2.cwd(), {
|
|
450
525
|
id,
|
|
451
526
|
all: options.all ?? false,
|
|
@@ -453,14 +528,18 @@ source.command("reload").description("Re-sync one managed source or all managed
|
|
|
453
528
|
brief: options.brief,
|
|
454
529
|
review: options.review,
|
|
455
530
|
guide: options.guide,
|
|
531
|
+
guideAnswers,
|
|
456
532
|
maxPages: options.maxPages ? parsePositiveInt(options.maxPages, 0) || void 0 : void 0,
|
|
457
533
|
maxDepth: options.maxDepth ? parsePositiveInt(options.maxDepth, 0) || void 0 : void 0
|
|
458
534
|
});
|
|
535
|
+
if (!options.answersFile && result.guides.length === 1) {
|
|
536
|
+
result.guides = [await completeGuideInteractively(result.guides[0], result.sources[0]?.id ?? id ?? "source")];
|
|
537
|
+
}
|
|
459
538
|
if (isJson()) {
|
|
460
539
|
emitJson(result);
|
|
461
540
|
} else {
|
|
462
541
|
log(
|
|
463
|
-
`Reloaded ${result.sources.length} source(s).${result.compile ? ` Compiled ${result.compile.sourceCount} source(s).` : ""}${result.briefPaths.length ? ` Briefs: ${result.briefPaths.length}.` : ""}${result.reviews.length ? ` Reviews: ${result.reviews.length}.` : ""}${result.guides.length ? ` Guides: ${result.guides.length}.` : ""}`
|
|
542
|
+
`Reloaded ${result.sources.length} source(s).${result.compile ? ` Compiled ${result.compile.sourceCount} source(s).` : ""}${result.briefPaths.length ? ` Briefs: ${result.briefPaths.length}.` : ""}${result.reviews.length ? ` Reviews: ${result.reviews.length}.` : ""}${result.guides.length ? ` Guides/Sessions: ${result.guides.length}.` : ""}`
|
|
464
543
|
);
|
|
465
544
|
}
|
|
466
545
|
}
|
|
@@ -481,12 +560,34 @@ source.command("review").description("Stage a source review artifact for a manag
|
|
|
481
560
|
log(`Staged source review at ${result.reviewPath}.`);
|
|
482
561
|
}
|
|
483
562
|
});
|
|
484
|
-
source.command("guide").description("
|
|
485
|
-
const
|
|
563
|
+
source.command("guide").description("Create or resume a guided source session for a managed source id or raw source id.").argument("<id>", "Managed source id or raw source id").option("--answers-file <path>", "JSON file with guided-session answers keyed by question id or listed in prompt order").action(async (id, options) => {
|
|
564
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
565
|
+
let result = await guideManagedSource(process2.cwd(), id, { answers: guideAnswers });
|
|
566
|
+
if (!options.answersFile) {
|
|
567
|
+
result = await completeGuideInteractively(result, id);
|
|
568
|
+
}
|
|
569
|
+
if (isJson()) {
|
|
570
|
+
emitJson(result);
|
|
571
|
+
} else {
|
|
572
|
+
if (result.awaitingInput) {
|
|
573
|
+
log(`Created guided session at ${result.sessionPath}. Resume with \`swarmvault source session ${result.sessionId}\`.`);
|
|
574
|
+
} else {
|
|
575
|
+
log(`Staged guided session at ${result.guidePath}.`);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
source.command("session").description("Resume the latest guided source session for a managed source id, raw source id, source scope id, or session id.").argument("<id>", "Managed source id, raw source id, source scope id, or guided session id").option("--answers-file <path>", "JSON file with guided-session answers keyed by question id or listed in prompt order").action(async (id, options) => {
|
|
580
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
581
|
+
let result = await resumeSourceSession(process2.cwd(), id, { answers: guideAnswers });
|
|
582
|
+
if (!options.answersFile) {
|
|
583
|
+
result = await completeGuideInteractively(result, id);
|
|
584
|
+
}
|
|
486
585
|
if (isJson()) {
|
|
487
586
|
emitJson(result);
|
|
587
|
+
} else if (result.awaitingInput) {
|
|
588
|
+
log(`Updated guided session at ${result.sessionPath}. Resume with \`swarmvault source session ${result.sessionId}\` when ready.`);
|
|
488
589
|
} else {
|
|
489
|
-
log(`Staged
|
|
590
|
+
log(`Staged guided session at ${result.guidePath}.`);
|
|
490
591
|
}
|
|
491
592
|
});
|
|
492
593
|
var inbox = program.command("inbox").description("Inbox and capture workflows.");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmvaultai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Global CLI for SwarmVault.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -37,18 +37,18 @@
|
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": ">=24.0.0"
|
|
39
39
|
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsup src/index.ts --format esm --dts",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"typecheck": "tsc --noEmit"
|
|
44
|
+
},
|
|
40
45
|
"dependencies": {
|
|
41
|
-
"@swarmvaultai/engine": "0.
|
|
46
|
+
"@swarmvaultai/engine": "0.6.1",
|
|
42
47
|
"commander": "^14.0.1"
|
|
43
48
|
},
|
|
44
49
|
"devDependencies": {
|
|
45
50
|
"@types/node": "^24.6.0",
|
|
46
51
|
"tsup": "^8.5.0",
|
|
47
52
|
"vitest": "^3.2.4"
|
|
48
|
-
},
|
|
49
|
-
"scripts": {
|
|
50
|
-
"build": "tsup src/index.ts --format esm --dts",
|
|
51
|
-
"test": "vitest run",
|
|
52
|
-
"typecheck": "tsc --noEmit"
|
|
53
53
|
}
|
|
54
|
-
}
|
|
54
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 SwarmVault
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|