@vibeframe/cli 0.91.3 → 0.91.4
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 +110 -20
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -31683,6 +31683,18 @@ var init_open_url = __esm({
|
|
|
31683
31683
|
// src/utils/tty.ts
|
|
31684
31684
|
import { createInterface as createInterface2 } from "node:readline";
|
|
31685
31685
|
import { ReadStream } from "node:tty";
|
|
31686
|
+
function splitTTYInput(chunk) {
|
|
31687
|
+
const tokens = [];
|
|
31688
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
31689
|
+
if (chunk[i] === "\x1B" && chunk[i + 1] === "[" && i + 2 < chunk.length) {
|
|
31690
|
+
tokens.push(chunk.slice(i, i + 3));
|
|
31691
|
+
i += 2;
|
|
31692
|
+
} else {
|
|
31693
|
+
tokens.push(chunk[i]);
|
|
31694
|
+
}
|
|
31695
|
+
}
|
|
31696
|
+
return tokens;
|
|
31697
|
+
}
|
|
31686
31698
|
function getTTYInputStream() {
|
|
31687
31699
|
if (process.stdin.isTTY) {
|
|
31688
31700
|
return process.stdin;
|
|
@@ -31736,14 +31748,16 @@ async function prompt2(question) {
|
|
|
31736
31748
|
async function promptHidden(question, opts = {}) {
|
|
31737
31749
|
const input = getTTYInputStream();
|
|
31738
31750
|
return new Promise((resolve64) => {
|
|
31739
|
-
process.stdout.write(question);
|
|
31740
31751
|
let value = "";
|
|
31741
31752
|
if (typeof input.setRawMode === "function") {
|
|
31742
31753
|
input.setRawMode(true);
|
|
31743
31754
|
input.resume();
|
|
31744
31755
|
input.setEncoding("utf8");
|
|
31745
|
-
|
|
31756
|
+
let finished = false;
|
|
31757
|
+
const handleChar = (char) => {
|
|
31758
|
+
if (finished) return;
|
|
31746
31759
|
if (char === "\n" || char === "\r" || char === "") {
|
|
31760
|
+
finished = true;
|
|
31747
31761
|
input.setRawMode(false);
|
|
31748
31762
|
input.removeListener("data", onData);
|
|
31749
31763
|
process.stdout.write("\n");
|
|
@@ -31764,10 +31778,14 @@ async function promptHidden(question, opts = {}) {
|
|
|
31764
31778
|
process.stdout.write("*".repeat(char.length));
|
|
31765
31779
|
}
|
|
31766
31780
|
};
|
|
31781
|
+
const onData = (chunk) => {
|
|
31782
|
+
for (const char of splitTTYInput(chunk)) handleChar(char);
|
|
31783
|
+
};
|
|
31767
31784
|
input.on("data", onData);
|
|
31785
|
+
process.stdout.write(question);
|
|
31768
31786
|
} else {
|
|
31769
31787
|
const rl = createInterface2({ input, output: process.stdout });
|
|
31770
|
-
rl.question(
|
|
31788
|
+
rl.question(question, (answer) => {
|
|
31771
31789
|
rl.close();
|
|
31772
31790
|
resolve64(answer);
|
|
31773
31791
|
});
|
|
@@ -31796,8 +31814,11 @@ async function promptSelect(_question, options, defaultIndex = 0) {
|
|
|
31796
31814
|
input.setRawMode(true);
|
|
31797
31815
|
input.resume();
|
|
31798
31816
|
input.setEncoding("utf8");
|
|
31799
|
-
|
|
31817
|
+
let finished = false;
|
|
31818
|
+
const handleChar = (char) => {
|
|
31819
|
+
if (finished) return;
|
|
31800
31820
|
if (char === "\r" || char === "\n") {
|
|
31821
|
+
finished = true;
|
|
31801
31822
|
input.setRawMode(false);
|
|
31802
31823
|
input.removeListener("data", onData);
|
|
31803
31824
|
process.stdout.write("\n");
|
|
@@ -31814,6 +31835,7 @@ async function promptSelect(_question, options, defaultIndex = 0) {
|
|
|
31814
31835
|
render();
|
|
31815
31836
|
} else if (char >= "1" && char <= String(options.length)) {
|
|
31816
31837
|
selected = parseInt(char, 10) - 1;
|
|
31838
|
+
finished = true;
|
|
31817
31839
|
input.setRawMode(false);
|
|
31818
31840
|
input.removeListener("data", onData);
|
|
31819
31841
|
render();
|
|
@@ -31821,6 +31843,9 @@ async function promptSelect(_question, options, defaultIndex = 0) {
|
|
|
31821
31843
|
resolve64(selected);
|
|
31822
31844
|
}
|
|
31823
31845
|
};
|
|
31846
|
+
const onData = (chunk) => {
|
|
31847
|
+
for (const char of splitTTYInput(chunk)) handleChar(char);
|
|
31848
|
+
};
|
|
31824
31849
|
input.on("data", onData);
|
|
31825
31850
|
});
|
|
31826
31851
|
}
|
|
@@ -31861,8 +31886,11 @@ async function promptConfirm(question, defaultYes = true) {
|
|
|
31861
31886
|
input.setRawMode(true);
|
|
31862
31887
|
input.resume();
|
|
31863
31888
|
input.setEncoding("utf8");
|
|
31864
|
-
|
|
31889
|
+
let finished = false;
|
|
31890
|
+
const handleChar = (char) => {
|
|
31891
|
+
if (finished) return;
|
|
31865
31892
|
if (char === "\r" || char === "\n") {
|
|
31893
|
+
finished = true;
|
|
31866
31894
|
input.setRawMode(false);
|
|
31867
31895
|
input.removeListener("data", onData);
|
|
31868
31896
|
resolve64(selected === 0);
|
|
@@ -31875,18 +31903,23 @@ async function promptConfirm(question, defaultYes = true) {
|
|
|
31875
31903
|
render();
|
|
31876
31904
|
} else if (char === "y" || char === "Y") {
|
|
31877
31905
|
selected = 0;
|
|
31906
|
+
finished = true;
|
|
31878
31907
|
input.setRawMode(false);
|
|
31879
31908
|
input.removeListener("data", onData);
|
|
31880
31909
|
render();
|
|
31881
31910
|
resolve64(true);
|
|
31882
31911
|
} else if (char === "n" || char === "N") {
|
|
31883
31912
|
selected = 1;
|
|
31913
|
+
finished = true;
|
|
31884
31914
|
input.setRawMode(false);
|
|
31885
31915
|
input.removeListener("data", onData);
|
|
31886
31916
|
render();
|
|
31887
31917
|
resolve64(false);
|
|
31888
31918
|
}
|
|
31889
31919
|
};
|
|
31920
|
+
const onData = (chunk) => {
|
|
31921
|
+
for (const char of splitTTYInput(chunk)) handleChar(char);
|
|
31922
|
+
};
|
|
31890
31923
|
input.on("data", onData);
|
|
31891
31924
|
});
|
|
31892
31925
|
}
|
|
@@ -31931,13 +31964,16 @@ async function promptMultiSelect(_question, options, defaultSelected = [], opts
|
|
|
31931
31964
|
}
|
|
31932
31965
|
resolve64(result);
|
|
31933
31966
|
};
|
|
31934
|
-
|
|
31967
|
+
let finished = false;
|
|
31968
|
+
const handleChar = (char) => {
|
|
31969
|
+
if (finished) return;
|
|
31935
31970
|
if (char === "\r" || char === "\n") {
|
|
31936
31971
|
if (pickFocused && !userToggled) {
|
|
31937
31972
|
for (let i = 0; i < selected.length; i++) selected[i] = false;
|
|
31938
31973
|
selected[cursor] = true;
|
|
31939
31974
|
render();
|
|
31940
31975
|
}
|
|
31976
|
+
finished = true;
|
|
31941
31977
|
finish();
|
|
31942
31978
|
} else if (char === "") {
|
|
31943
31979
|
input.setRawMode(false);
|
|
@@ -31965,6 +32001,9 @@ async function promptMultiSelect(_question, options, defaultSelected = [], opts
|
|
|
31965
32001
|
render();
|
|
31966
32002
|
}
|
|
31967
32003
|
};
|
|
32004
|
+
const onData = (chunk) => {
|
|
32005
|
+
for (const char of splitTTYInput(chunk)) handleChar(char);
|
|
32006
|
+
};
|
|
31968
32007
|
input.on("data", onData);
|
|
31969
32008
|
});
|
|
31970
32009
|
}
|
|
@@ -62920,7 +62959,7 @@ init_source();
|
|
|
62920
62959
|
// package.json
|
|
62921
62960
|
var package_default = {
|
|
62922
62961
|
name: "@vibeframe/cli",
|
|
62923
|
-
version: "0.91.
|
|
62962
|
+
version: "0.91.4",
|
|
62924
62963
|
description: "VibeFrame CLI - natural language video editing from the terminal",
|
|
62925
62964
|
private: false,
|
|
62926
62965
|
license: "MIT",
|
|
@@ -70110,6 +70149,15 @@ function applyProviderDefault(config2, choice) {
|
|
|
70110
70149
|
config2.defaults.videoProvider = choice.defaultFor.value;
|
|
70111
70150
|
}
|
|
70112
70151
|
}
|
|
70152
|
+
function mergeSelectedFeatures(current, next) {
|
|
70153
|
+
const merged = [...current];
|
|
70154
|
+
for (const feature of next) {
|
|
70155
|
+
if (!merged.some((f) => f.label === feature.label)) {
|
|
70156
|
+
merged.push(feature);
|
|
70157
|
+
}
|
|
70158
|
+
}
|
|
70159
|
+
return merged;
|
|
70160
|
+
}
|
|
70113
70161
|
async function runNonInteractiveSetup(opts) {
|
|
70114
70162
|
const scope = opts.scope ?? "user";
|
|
70115
70163
|
let config2 = await loadConfig({ scope });
|
|
@@ -70235,11 +70283,13 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
70235
70283
|
console.log();
|
|
70236
70284
|
if (topIndex === 0) {
|
|
70237
70285
|
await saveConfig(config2, { scope });
|
|
70238
|
-
await
|
|
70286
|
+
await completeOrContinue(config2, "vibe edit silence-cut video.mp4 -o clean.mp4", [], scope);
|
|
70239
70287
|
return;
|
|
70240
70288
|
}
|
|
70241
70289
|
if (topIndex === 3) {
|
|
70242
|
-
await runCustomSetup(config2, scope);
|
|
70290
|
+
await runCustomSetup(config2, scope, { showComplete: false });
|
|
70291
|
+
await saveConfig(config2, { scope });
|
|
70292
|
+
await completeOrContinue(config2, "vibe doctor --test-keys", [], scope);
|
|
70243
70293
|
return;
|
|
70244
70294
|
}
|
|
70245
70295
|
if (topIndex === 2) {
|
|
@@ -70256,9 +70306,44 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
70256
70306
|
console.log();
|
|
70257
70307
|
await collectKeys(config2, pipelineKeys);
|
|
70258
70308
|
await saveConfig(config2, { scope });
|
|
70259
|
-
await
|
|
70309
|
+
await completeOrContinue(config2, "vibe build my-story/ # see CONTRIBUTING.md for STORYBOARD.md format", [], scope);
|
|
70260
70310
|
return;
|
|
70261
70311
|
}
|
|
70312
|
+
const result = await runAIFeaturesSetup(config2, scope);
|
|
70313
|
+
await saveConfig(config2, { scope });
|
|
70314
|
+
await completeOrContinue(config2, result.tryCommand, result.selectedFeatures, scope);
|
|
70315
|
+
}
|
|
70316
|
+
async function completeOrContinue(config2, tryCommand, selectedFeatures, scope) {
|
|
70317
|
+
console.log(source_default.dim("Setup checkpoint"));
|
|
70318
|
+
console.log(source_default.bold("Anything else to configure?"));
|
|
70319
|
+
console.log();
|
|
70320
|
+
const action = await promptSelect(
|
|
70321
|
+
source_default.cyan(" Next: "),
|
|
70322
|
+
[
|
|
70323
|
+
`Add or update AI features ${source_default.dim("(images, videos, audio, editing)")}`,
|
|
70324
|
+
`Open full provider list ${source_default.dim("(every supported provider)")}`,
|
|
70325
|
+
"Finish setup"
|
|
70326
|
+
],
|
|
70327
|
+
2
|
|
70328
|
+
);
|
|
70329
|
+
console.log();
|
|
70330
|
+
if (action === 0) {
|
|
70331
|
+
const result = await runAIFeaturesSetup(config2, scope);
|
|
70332
|
+
const mergedFeatures = mergeSelectedFeatures(selectedFeatures, result.selectedFeatures);
|
|
70333
|
+
const mergedTryCommand = selectedFeatures.length > 0 ? tryCommand : result.tryCommand;
|
|
70334
|
+
await saveConfig(config2, { scope });
|
|
70335
|
+
await completeOrContinue(config2, mergedTryCommand, mergedFeatures, scope);
|
|
70336
|
+
return;
|
|
70337
|
+
}
|
|
70338
|
+
if (action === 1) {
|
|
70339
|
+
await runCustomSetup(config2, scope, { showComplete: false });
|
|
70340
|
+
await saveConfig(config2, { scope });
|
|
70341
|
+
await completeOrContinue(config2, tryCommand, selectedFeatures, scope);
|
|
70342
|
+
return;
|
|
70343
|
+
}
|
|
70344
|
+
await showComplete(config2, tryCommand, selectedFeatures, scope);
|
|
70345
|
+
}
|
|
70346
|
+
async function runAIFeaturesSetup(config2, _scope) {
|
|
70262
70347
|
console.log(source_default.dim("2. Features"));
|
|
70263
70348
|
console.log(source_default.bold("Which AI features do you need?"));
|
|
70264
70349
|
console.log(source_default.dim(` ${source_default.bold("Most users pick more than one.")} Press ${source_default.bold("space")} on each feature you want, then ${source_default.bold("enter")} to confirm.`));
|
|
@@ -70280,14 +70365,12 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
70280
70365
|
if (selectedFeatures.length === 0) {
|
|
70281
70366
|
console.log(source_default.dim(" No features selected. You can re-run setup anytime."));
|
|
70282
70367
|
console.log();
|
|
70283
|
-
|
|
70284
|
-
await showComplete(config2, "vibe --help", [], scope);
|
|
70285
|
-
return;
|
|
70368
|
+
return { tryCommand: "vibe --help", selectedFeatures: [] };
|
|
70286
70369
|
}
|
|
70287
70370
|
const plannedKeys = /* @__PURE__ */ new Map();
|
|
70288
70371
|
console.log(source_default.dim("3. Providers"));
|
|
70289
70372
|
console.log(source_default.bold("Choose providers for each selected feature"));
|
|
70290
|
-
console.log(source_default.dim(` Recommended default is highlighted. Press ${source_default.bold("enter")} to pick
|
|
70373
|
+
console.log(source_default.dim(` Recommended default is highlighted. Press ${source_default.bold("enter")} to pick the highlighted provider, or ${source_default.bold("space")} to choose multiple.`));
|
|
70291
70374
|
console.log();
|
|
70292
70375
|
for (const feature of selectedFeatures) {
|
|
70293
70376
|
const keysForFeature = [];
|
|
@@ -70298,10 +70381,16 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
70298
70381
|
console.log(source_default.dim(` Alternatives: ${feature.alsoAvailable}`));
|
|
70299
70382
|
}
|
|
70300
70383
|
console.log();
|
|
70301
|
-
const defaultSelected = feature.providerChoices.map((
|
|
70384
|
+
const defaultSelected = feature.providerChoices.map(() => false);
|
|
70302
70385
|
const providerLabels = feature.providerChoices.map((choice) => {
|
|
70303
70386
|
const keyHint = choice.keyless ? source_default.dim("no key") : choice.key ? source_default.dim(choice.key.envVar) : source_default.dim("no key");
|
|
70304
|
-
|
|
70387
|
+
const defaultHint = choice === feature.providerChoices?.[0] ? source_default.dim("recommended default") : "";
|
|
70388
|
+
return [
|
|
70389
|
+
choice.label,
|
|
70390
|
+
defaultHint,
|
|
70391
|
+
source_default.dim(`- ${choice.desc}`),
|
|
70392
|
+
keyHint
|
|
70393
|
+
].filter(Boolean).join(" ");
|
|
70305
70394
|
});
|
|
70306
70395
|
const pickedProviders = await promptMultiSelect(
|
|
70307
70396
|
source_default.cyan(" Providers (arrow + enter picks one, space adds more): "),
|
|
@@ -70388,8 +70477,7 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
70388
70477
|
console.log(source_default.dim(" No API keys needed for the selected provider(s)."));
|
|
70389
70478
|
console.log();
|
|
70390
70479
|
}
|
|
70391
|
-
|
|
70392
|
-
await showComplete(config2, selectedFeatures[0].tryCommand, selectedFeatures, scope);
|
|
70480
|
+
return { tryCommand: selectedFeatures[0].tryCommand, selectedFeatures };
|
|
70393
70481
|
}
|
|
70394
70482
|
async function collectKeys(config2, keys) {
|
|
70395
70483
|
loadEnv();
|
|
@@ -70425,7 +70513,7 @@ async function collectKeys(config2, keys) {
|
|
|
70425
70513
|
}
|
|
70426
70514
|
console.log();
|
|
70427
70515
|
}
|
|
70428
|
-
async function runCustomSetup(config2, scope = "user") {
|
|
70516
|
+
async function runCustomSetup(config2, scope = "user", opts = {}) {
|
|
70429
70517
|
console.log(source_default.bold("1. Agent LLM Provider") + source_default.dim(" (for vibe agent)"));
|
|
70430
70518
|
console.log(source_default.dim(" Only needed if you use the interactive Agent mode."));
|
|
70431
70519
|
console.log();
|
|
@@ -70496,7 +70584,9 @@ async function runCustomSetup(config2, scope = "user") {
|
|
|
70496
70584
|
}
|
|
70497
70585
|
console.log();
|
|
70498
70586
|
await saveConfig(config2, { scope });
|
|
70499
|
-
|
|
70587
|
+
if (opts.showComplete !== false) {
|
|
70588
|
+
await showComplete(config2, "vibe doctor", [], scope);
|
|
70589
|
+
}
|
|
70500
70590
|
}
|
|
70501
70591
|
async function showComplete(config2, defaultTryCommand, features = [], scope = "user") {
|
|
70502
70592
|
console.log(source_default.dim("\u2500".repeat(40)));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.91.
|
|
3
|
+
"version": "0.91.4",
|
|
4
4
|
"description": "VibeFrame CLI - natural language video editing from the terminal",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -183,8 +183,8 @@
|
|
|
183
183
|
"tsx": "^4.21.0",
|
|
184
184
|
"typescript": "^5.3.3",
|
|
185
185
|
"vitest": "^1.2.2",
|
|
186
|
-
"@vibeframe/ai-providers": "0.91.
|
|
187
|
-
"@vibeframe/core": "0.91.
|
|
186
|
+
"@vibeframe/ai-providers": "0.91.4",
|
|
187
|
+
"@vibeframe/core": "0.91.4"
|
|
188
188
|
},
|
|
189
189
|
"engines": {
|
|
190
190
|
"node": ">=20"
|