@swarmvaultai/cli 1.0.1 → 1.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/dist/index.js +76 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
consolidateVault,
|
|
19
19
|
createSupersessionEdge,
|
|
20
20
|
deleteManagedSource,
|
|
21
|
+
downloadWhisperModel,
|
|
21
22
|
explainGraphVault,
|
|
22
23
|
exploreVault,
|
|
23
24
|
exportGraphFormat,
|
|
@@ -52,6 +53,7 @@ import {
|
|
|
52
53
|
queryGraphVault,
|
|
53
54
|
queryVault,
|
|
54
55
|
readApproval,
|
|
56
|
+
registerLocalWhisperProvider,
|
|
55
57
|
rejectApproval,
|
|
56
58
|
reloadManagedSources,
|
|
57
59
|
removeWatchedRoot,
|
|
@@ -65,6 +67,7 @@ import {
|
|
|
65
67
|
serveSchedules,
|
|
66
68
|
startGraphServer,
|
|
67
69
|
startMcpServer,
|
|
70
|
+
summarizeLocalWhisperSetup,
|
|
68
71
|
uninstallGitHooks,
|
|
69
72
|
watchVault
|
|
70
73
|
} from "@swarmvaultai/engine";
|
|
@@ -284,9 +287,9 @@ program.name("swarmvault").description("SwarmVault is a local-first knowledge co
|
|
|
284
287
|
function readCliVersion() {
|
|
285
288
|
try {
|
|
286
289
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
287
|
-
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "1.0
|
|
290
|
+
return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "1.1.0";
|
|
288
291
|
} catch {
|
|
289
|
-
return "1.0
|
|
292
|
+
return "1.1.0";
|
|
290
293
|
}
|
|
291
294
|
}
|
|
292
295
|
function parsePositiveInt(value, fallback) {
|
|
@@ -1141,6 +1144,77 @@ candidate.command("preview-scores").description("Show promotion scores for stage
|
|
|
1141
1144
|
log(`${verdict} ${decision.pageId} score=${decision.score.toFixed(2)} ${decision.reasons.join("; ")}`);
|
|
1142
1145
|
}
|
|
1143
1146
|
});
|
|
1147
|
+
var provider = program.command("provider").description("Configure provider adapters.");
|
|
1148
|
+
provider.command("setup").description("Interactive setup for a provider (currently: local-whisper). Checks for required binaries and downloads models.").option("--local-whisper", "Set up the local Whisper (whisper.cpp) provider", false).option("--model <model>", "Whisper model to install (e.g. tiny.en, base.en, small.en)", "base.en").option("--apply", "Skip confirmation prompts and download/install automatically", false).option("--set-audio-provider", "Force tasks.audioProvider to local-whisper even if another provider is already configured", false).action(async (options) => {
|
|
1149
|
+
if (!options.localWhisper) {
|
|
1150
|
+
throw new Error("Specify a provider to set up (currently: --local-whisper).");
|
|
1151
|
+
}
|
|
1152
|
+
const modelName = (options.model ?? "base.en").trim();
|
|
1153
|
+
if (!modelName) {
|
|
1154
|
+
throw new Error("Model name cannot be empty.");
|
|
1155
|
+
}
|
|
1156
|
+
const status = await summarizeLocalWhisperSetup({ modelName });
|
|
1157
|
+
if (isJson()) {
|
|
1158
|
+
emitJson({ ...status, apply: Boolean(options.apply), configWrite: null });
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
log(`whisper.cpp binary: ${status.binary.found ? status.binary.path : "NOT FOUND"}`);
|
|
1162
|
+
if (!status.binary.found) {
|
|
1163
|
+
log(status.binary.installHint);
|
|
1164
|
+
log("Re-run once whisper.cpp is on $PATH.");
|
|
1165
|
+
process2.exitCode = 1;
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
log(`Model "${modelName}": ${status.model.exists ? status.model.expectedPath : "missing"}`);
|
|
1169
|
+
if (!status.model.exists) {
|
|
1170
|
+
const sizeHint = status.model.approximateSize ? ` (~${status.model.approximateSize})` : "";
|
|
1171
|
+
log(`Download plan: ${status.model.downloadUrl}${sizeHint} -> ${status.model.expectedPath}`);
|
|
1172
|
+
const proceed = options.apply === true || await confirmInteractive(`Download ggml-${modelName}.bin now?`);
|
|
1173
|
+
if (!proceed) {
|
|
1174
|
+
log("Skipped download. Run with --apply (or confirm y) to download.");
|
|
1175
|
+
process2.exitCode = 1;
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
const downloaded = await downloadWhisperModel({
|
|
1179
|
+
modelName,
|
|
1180
|
+
onProgress: (progress) => {
|
|
1181
|
+
if (progress.totalBytes) {
|
|
1182
|
+
const percent = Math.floor(progress.downloadedBytes / progress.totalBytes * 100);
|
|
1183
|
+
process2.stderr.write(`\r[swarmvault] downloading ggml-${modelName}.bin: ${percent}%`);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
process2.stderr.write("\n");
|
|
1188
|
+
log(`Downloaded ${downloaded.bytes} bytes to ${downloaded.path}.`);
|
|
1189
|
+
}
|
|
1190
|
+
const registration = await registerLocalWhisperProvider({
|
|
1191
|
+
rootDir: process2.cwd(),
|
|
1192
|
+
model: modelName,
|
|
1193
|
+
setAsAudioProvider: options.setAudioProvider ? true : void 0
|
|
1194
|
+
});
|
|
1195
|
+
if (registration.providerWasAdded) {
|
|
1196
|
+
log(`Registered provider "local-whisper" in ${registration.configPath}.`);
|
|
1197
|
+
} else if (registration.providerWasUpdated) {
|
|
1198
|
+
log(`Updated existing "local-whisper" provider entry in ${registration.configPath}.`);
|
|
1199
|
+
} else {
|
|
1200
|
+
log(`Provider "local-whisper" already configured in ${registration.configPath}.`);
|
|
1201
|
+
}
|
|
1202
|
+
if (registration.audioProviderSet) {
|
|
1203
|
+
log(`Set tasks.audioProvider = "local-whisper".`);
|
|
1204
|
+
} else if (registration.previousAudioProvider && registration.previousAudioProvider !== "local-whisper") {
|
|
1205
|
+
log(`Left tasks.audioProvider = "${registration.previousAudioProvider}" untouched (use --set-audio-provider to override).`);
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
async function confirmInteractive(message) {
|
|
1209
|
+
if (!process2.stdin.isTTY) return false;
|
|
1210
|
+
const rl = createInterface({ input: process2.stdin, output: process2.stderr });
|
|
1211
|
+
try {
|
|
1212
|
+
const answer = (await rl.question(`${message} [y/N] `)).trim().toLowerCase();
|
|
1213
|
+
return answer === "y" || answer === "yes";
|
|
1214
|
+
} finally {
|
|
1215
|
+
rl.close();
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1144
1218
|
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, []).action(async (options) => {
|
|
1145
1219
|
const debounceMs = parsePositiveInt(options.debounce, 900);
|
|
1146
1220
|
const overrideRoots = options.root && options.root.length > 0 ? options.root : void 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmvaultai/cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.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": "1.0
|
|
47
|
+
"@swarmvaultai/engine": "1.1.0",
|
|
48
48
|
"commander": "^14.0.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|