@swarmvaultai/cli 0.5.0 → 0.6.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 +10 -6
- package/dist/index.js +116 -18
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ swarmvault init --obsidian --profile personal-research
|
|
|
26
26
|
swarmvault source add https://github.com/karpathy/micrograd
|
|
27
27
|
swarmvault source add https://example.com/docs/getting-started
|
|
28
28
|
swarmvault source add ./exports/customer-call.srt --guide
|
|
29
|
+
swarmvault source session file-customer-call-srt-12345678
|
|
29
30
|
swarmvault source list
|
|
30
31
|
swarmvault source reload --all
|
|
31
32
|
sed -n '1,120p' swarmvault.schema.md
|
|
@@ -68,29 +69,31 @@ Create a workspace with:
|
|
|
68
69
|
|
|
69
70
|
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
71
|
|
|
71
|
-
### `swarmvault source add|list|reload|review|guide|delete`
|
|
72
|
+
### `swarmvault source add|list|reload|review|guide|session|delete`
|
|
72
73
|
|
|
73
74
|
Manage recurring source roots through a registry-backed workflow.
|
|
74
75
|
|
|
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
|
|
76
|
+
- `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
77
|
- 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
|
|
78
|
+
- add `--guide` when you want a resumable source session, source brief, source review, source guide, and approval-bundled `wiki/insights/` updates for one-source-at-a-time integration
|
|
78
79
|
- `source list` shows every managed source with its kind, status, and current brief path
|
|
79
80
|
- `source reload [id]` re-syncs one source, or use `--all` to refresh everything in the registry and compile once
|
|
80
81
|
- `source review <id>` stages a lighter source-scoped review artifact
|
|
81
|
-
- `source guide <id>`
|
|
82
|
+
- `source guide <id>` remains a compatibility alias for the guided session flow
|
|
83
|
+
- `source session <id>` resumes the latest guided session for a managed source id, raw source id, source scope id, or session id
|
|
82
84
|
- `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
85
|
|
|
84
86
|
Useful flags:
|
|
85
87
|
|
|
86
88
|
- `--all`
|
|
87
89
|
- `--guide`
|
|
90
|
+
- `--answers-file <path>`
|
|
88
91
|
- `--no-compile`
|
|
89
92
|
- `--no-brief`
|
|
90
93
|
- `--max-pages <n>`
|
|
91
94
|
- `--max-depth <n>`
|
|
92
95
|
|
|
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.
|
|
96
|
+
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
97
|
|
|
95
98
|
### `swarmvault ingest <path-or-url>`
|
|
96
99
|
|
|
@@ -102,12 +105,13 @@ Ingest a local file path, directory path, or URL into immutable source storage a
|
|
|
102
105
|
- use `source add` instead when the same local directory, public GitHub repo root, or docs hub should stay registered and reloadable
|
|
103
106
|
- URL ingest still localizes remote image references by default
|
|
104
107
|
- 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
|
|
108
|
+
- add `--guide` when you want a resumable source session, source brief, source review, source guide, and approval-bundled `wiki/insights/` updates after ingest
|
|
106
109
|
- 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
110
|
|
|
108
111
|
Useful flags:
|
|
109
112
|
|
|
110
113
|
- `--repo-root <path>`
|
|
114
|
+
- `--answers-file <path>`
|
|
111
115
|
- `--include <glob...>`
|
|
112
116
|
- `--exclude <glob...>`
|
|
113
117
|
- `--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.0";
|
|
230
232
|
} catch {
|
|
231
|
-
return "0.
|
|
233
|
+
return "0.6.0";
|
|
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;
|
|
@@ -306,8 +359,9 @@ program.command("init").description("Initialize a SwarmVault workspace in the cu
|
|
|
306
359
|
log("Initialized SwarmVault workspace.");
|
|
307
360
|
}
|
|
308
361
|
});
|
|
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(
|
|
362
|
+
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
363
|
async (input, options) => {
|
|
364
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
311
365
|
const maxAssetSize = typeof options.maxAssetSize === "string" && options.maxAssetSize.trim() ? parsePositiveInt(options.maxAssetSize, 0) || void 0 : void 0;
|
|
312
366
|
const maxFiles = typeof options.maxFiles === "string" && options.maxFiles.trim() ? parsePositiveInt(options.maxFiles, 0) || void 0 : void 0;
|
|
313
367
|
const extractClasses = [
|
|
@@ -354,10 +408,13 @@ program.command("ingest").description("Ingest a local file path, directory path,
|
|
|
354
408
|
})() : void 0;
|
|
355
409
|
const guide2 = shouldStage && options.guide ? await (async () => {
|
|
356
410
|
await compileVault(process2.cwd(), {});
|
|
357
|
-
return await guideSourceScope(process2.cwd(), scope2);
|
|
411
|
+
return await guideSourceScope(process2.cwd(), scope2, { answers: guideAnswers });
|
|
358
412
|
})() : void 0;
|
|
413
|
+
const completedGuide2 = guide2 && !options.answersFile ? await completeGuideInteractively(guide2, scope2?.id ?? input) : guide2;
|
|
359
414
|
if (isJson()) {
|
|
360
|
-
emitJson(
|
|
415
|
+
emitJson(
|
|
416
|
+
completedGuide2 ? { ingest: directoryResult, guide: completedGuide2 } : review3 ? { ingest: directoryResult, review: review3 } : directoryResult
|
|
417
|
+
);
|
|
361
418
|
} else {
|
|
362
419
|
log(
|
|
363
420
|
`Imported ${directoryResult.imported.length} file(s), updated ${directoryResult.updated.length}, skipped ${directoryResult.skipped.length}.`
|
|
@@ -365,8 +422,12 @@ program.command("ingest").description("Ingest a local file path, directory path,
|
|
|
365
422
|
if (review3) {
|
|
366
423
|
log(`Staged source review at ${review3.reviewPath}.`);
|
|
367
424
|
}
|
|
368
|
-
if (
|
|
369
|
-
log(
|
|
425
|
+
if (completedGuide2?.awaitingInput) {
|
|
426
|
+
log(
|
|
427
|
+
`Created guided session at ${completedGuide2.sessionPath}. Resume with \`swarmvault source session ${completedGuide2.sessionId}\`.`
|
|
428
|
+
);
|
|
429
|
+
} else if (completedGuide2?.guidePath) {
|
|
430
|
+
log(`Staged guided session at ${completedGuide2.guidePath}.`);
|
|
370
431
|
}
|
|
371
432
|
}
|
|
372
433
|
return;
|
|
@@ -379,10 +440,11 @@ program.command("ingest").description("Ingest a local file path, directory path,
|
|
|
379
440
|
})() : void 0;
|
|
380
441
|
const guide = options.guide && scope && (ingest.created.length || ingest.updated.length || ingest.unchanged.length) ? await (async () => {
|
|
381
442
|
await compileVault(process2.cwd(), {});
|
|
382
|
-
return await guideSourceScope(process2.cwd(), scope);
|
|
443
|
+
return await guideSourceScope(process2.cwd(), scope, { answers: guideAnswers });
|
|
383
444
|
})() : void 0;
|
|
445
|
+
const completedGuide = guide && !options.answersFile ? await completeGuideInteractively(guide, scope?.id ?? input) : guide;
|
|
384
446
|
if (isJson()) {
|
|
385
|
-
emitJson(
|
|
447
|
+
emitJson(completedGuide ? { ingest, guide: completedGuide } : review2 ? { ingest, review: review2 } : ingest);
|
|
386
448
|
} else {
|
|
387
449
|
const primary = [...ingest.created, ...ingest.updated, ...ingest.unchanged][0];
|
|
388
450
|
if (ingest.created.length + ingest.updated.length + ingest.removed.length <= 1 && primary) {
|
|
@@ -395,8 +457,12 @@ program.command("ingest").description("Ingest a local file path, directory path,
|
|
|
395
457
|
if (review2) {
|
|
396
458
|
log(`Staged source review at ${review2.reviewPath}.`);
|
|
397
459
|
}
|
|
398
|
-
if (
|
|
399
|
-
log(
|
|
460
|
+
if (completedGuide?.awaitingInput) {
|
|
461
|
+
log(
|
|
462
|
+
`Created guided session at ${completedGuide.sessionPath}. Resume with \`swarmvault source session ${completedGuide.sessionId}\`.`
|
|
463
|
+
);
|
|
464
|
+
} else if (completedGuide?.guidePath) {
|
|
465
|
+
log(`Staged guided session at ${completedGuide.guidePath}.`);
|
|
400
466
|
}
|
|
401
467
|
}
|
|
402
468
|
}
|
|
@@ -413,21 +479,26 @@ program.command("add").description("Capture supported URLs into normalized markd
|
|
|
413
479
|
}
|
|
414
480
|
});
|
|
415
481
|
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(
|
|
482
|
+
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
483
|
async (input, options) => {
|
|
484
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
418
485
|
const result = await addManagedSource(process2.cwd(), input, {
|
|
419
486
|
compile: options.compile,
|
|
420
487
|
brief: options.brief,
|
|
421
488
|
review: options.review,
|
|
422
489
|
guide: options.guide,
|
|
490
|
+
guideAnswers,
|
|
423
491
|
maxPages: options.maxPages ? parsePositiveInt(options.maxPages, 0) || void 0 : void 0,
|
|
424
492
|
maxDepth: options.maxDepth ? parsePositiveInt(options.maxDepth, 0) || void 0 : void 0
|
|
425
493
|
});
|
|
494
|
+
if (result.guide && !options.answersFile) {
|
|
495
|
+
result.guide = await completeGuideInteractively(result.guide, result.source.id);
|
|
496
|
+
}
|
|
426
497
|
if (isJson()) {
|
|
427
498
|
emitJson(result);
|
|
428
499
|
} else {
|
|
429
500
|
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}` : ""}`
|
|
501
|
+
`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
502
|
);
|
|
432
503
|
}
|
|
433
504
|
}
|
|
@@ -444,8 +515,9 @@ source.command("list").description("List managed sources registered in this vaul
|
|
|
444
515
|
}
|
|
445
516
|
}
|
|
446
517
|
});
|
|
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(
|
|
518
|
+
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
519
|
async (id, options) => {
|
|
520
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
449
521
|
const result = await reloadManagedSources(process2.cwd(), {
|
|
450
522
|
id,
|
|
451
523
|
all: options.all ?? false,
|
|
@@ -453,14 +525,18 @@ source.command("reload").description("Re-sync one managed source or all managed
|
|
|
453
525
|
brief: options.brief,
|
|
454
526
|
review: options.review,
|
|
455
527
|
guide: options.guide,
|
|
528
|
+
guideAnswers,
|
|
456
529
|
maxPages: options.maxPages ? parsePositiveInt(options.maxPages, 0) || void 0 : void 0,
|
|
457
530
|
maxDepth: options.maxDepth ? parsePositiveInt(options.maxDepth, 0) || void 0 : void 0
|
|
458
531
|
});
|
|
532
|
+
if (!options.answersFile && result.guides.length === 1) {
|
|
533
|
+
result.guides = [await completeGuideInteractively(result.guides[0], result.sources[0]?.id ?? id ?? "source")];
|
|
534
|
+
}
|
|
459
535
|
if (isJson()) {
|
|
460
536
|
emitJson(result);
|
|
461
537
|
} else {
|
|
462
538
|
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}.` : ""}`
|
|
539
|
+
`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
540
|
);
|
|
465
541
|
}
|
|
466
542
|
}
|
|
@@ -481,12 +557,34 @@ source.command("review").description("Stage a source review artifact for a manag
|
|
|
481
557
|
log(`Staged source review at ${result.reviewPath}.`);
|
|
482
558
|
}
|
|
483
559
|
});
|
|
484
|
-
source.command("guide").description("
|
|
485
|
-
const
|
|
560
|
+
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) => {
|
|
561
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
562
|
+
let result = await guideManagedSource(process2.cwd(), id, { answers: guideAnswers });
|
|
563
|
+
if (!options.answersFile) {
|
|
564
|
+
result = await completeGuideInteractively(result, id);
|
|
565
|
+
}
|
|
566
|
+
if (isJson()) {
|
|
567
|
+
emitJson(result);
|
|
568
|
+
} else {
|
|
569
|
+
if (result.awaitingInput) {
|
|
570
|
+
log(`Created guided session at ${result.sessionPath}. Resume with \`swarmvault source session ${result.sessionId}\`.`);
|
|
571
|
+
} else {
|
|
572
|
+
log(`Staged guided session at ${result.guidePath}.`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
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) => {
|
|
577
|
+
const guideAnswers = readGuideAnswersFile(options.answersFile);
|
|
578
|
+
let result = await resumeSourceSession(process2.cwd(), id, { answers: guideAnswers });
|
|
579
|
+
if (!options.answersFile) {
|
|
580
|
+
result = await completeGuideInteractively(result, id);
|
|
581
|
+
}
|
|
486
582
|
if (isJson()) {
|
|
487
583
|
emitJson(result);
|
|
584
|
+
} else if (result.awaitingInput) {
|
|
585
|
+
log(`Updated guided session at ${result.sessionPath}. Resume with \`swarmvault source session ${result.sessionId}\` when ready.`);
|
|
488
586
|
} else {
|
|
489
|
-
log(`Staged
|
|
587
|
+
log(`Staged guided session at ${result.guidePath}.`);
|
|
490
588
|
}
|
|
491
589
|
});
|
|
492
590
|
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.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": "0.
|
|
41
|
+
"@swarmvaultai/engine": "0.6.0",
|
|
42
42
|
"commander": "^14.0.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|