@vibeframe/cli 0.91.7 → 0.91.9
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 +401 -180
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -31792,7 +31792,7 @@ async function promptHidden(question, opts = {}) {
|
|
|
31792
31792
|
}
|
|
31793
31793
|
});
|
|
31794
31794
|
}
|
|
31795
|
-
async function promptSelect(_question, options, defaultIndex = 0) {
|
|
31795
|
+
async function promptSelect(_question, options, defaultIndex = 0, opts = {}) {
|
|
31796
31796
|
const input = getTTYInputStream();
|
|
31797
31797
|
if (typeof input.setRawMode === "function") {
|
|
31798
31798
|
return new Promise((resolve64) => {
|
|
@@ -31827,6 +31827,12 @@ async function promptSelect(_question, options, defaultIndex = 0) {
|
|
|
31827
31827
|
input.setRawMode(false);
|
|
31828
31828
|
process.stdout.write("\n");
|
|
31829
31829
|
process.exit(1);
|
|
31830
|
+
} else if (opts.backIndex !== void 0 && (char === "\x1B" || char === "\x1B[D")) {
|
|
31831
|
+
finished = true;
|
|
31832
|
+
input.setRawMode(false);
|
|
31833
|
+
input.removeListener("data", onData);
|
|
31834
|
+
process.stdout.write("\n");
|
|
31835
|
+
resolve64(opts.backIndex);
|
|
31830
31836
|
} else if (char === "\x1B[A" || char === "k") {
|
|
31831
31837
|
selected = (selected - 1 + options.length) % options.length;
|
|
31832
31838
|
render();
|
|
@@ -31982,6 +31988,11 @@ async function promptMultiSelect(_question, options, defaultSelected = [], opts
|
|
|
31982
31988
|
input.setRawMode(false);
|
|
31983
31989
|
process.stdout.write("\n");
|
|
31984
31990
|
process.exit(1);
|
|
31991
|
+
} else if (opts.backIndex !== void 0 && (char === "\x1B" || char === "\x1B[D")) {
|
|
31992
|
+
for (let i = 0; i < selected.length; i++) selected[i] = false;
|
|
31993
|
+
selected[opts.backIndex] = true;
|
|
31994
|
+
finished = true;
|
|
31995
|
+
finish();
|
|
31985
31996
|
} else if (char === " ") {
|
|
31986
31997
|
selected[cursor] = !selected[cursor];
|
|
31987
31998
|
userToggled = true;
|
|
@@ -62962,7 +62973,7 @@ init_source();
|
|
|
62962
62973
|
// package.json
|
|
62963
62974
|
var package_default = {
|
|
62964
62975
|
name: "@vibeframe/cli",
|
|
62965
|
-
version: "0.91.
|
|
62976
|
+
version: "0.91.9",
|
|
62966
62977
|
description: "VibeFrame CLI - natural language video editing from the terminal",
|
|
62967
62978
|
private: false,
|
|
62968
62979
|
license: "MIT",
|
|
@@ -69963,14 +69974,19 @@ var VALID_SCOPES = ["user", "project"];
|
|
|
69963
69974
|
function parseScope(raw) {
|
|
69964
69975
|
const v = String(raw ?? "user");
|
|
69965
69976
|
if (!VALID_SCOPES.includes(v)) {
|
|
69966
|
-
exitWithError(
|
|
69967
|
-
`Invalid --scope: ${v}`,
|
|
69968
|
-
|
|
69969
|
-
));
|
|
69977
|
+
exitWithError(
|
|
69978
|
+
generalError(`Invalid --scope: ${v}`, `Must be one of: ${VALID_SCOPES.join(", ")}`)
|
|
69979
|
+
);
|
|
69970
69980
|
}
|
|
69971
69981
|
return v;
|
|
69972
69982
|
}
|
|
69973
|
-
var setupCommand = new Command("setup").description("Configure VibeFrame (LLM provider, API keys)").option("--reset", "Reset configuration to defaults").option("--full", "Run full setup with all optional providers").option("--show", "Show current configuration (for debugging)").option(
|
|
69983
|
+
var setupCommand = new Command("setup").description("Configure VibeFrame (LLM provider, API keys)").option("--reset", "Reset configuration to defaults").option("--full", "Run full setup with all optional providers").option("--show", "Show current configuration (for debugging)").option(
|
|
69984
|
+
"-v, --verbose",
|
|
69985
|
+
"With --show: include unset providers + Resolution order + Defaults block"
|
|
69986
|
+
).option("--claude-code", "Show Claude Code integration guide").option("-y, --yes", "Non-interactive: write config without prompting (CI / devcontainer)").option(
|
|
69987
|
+
"--provider <id>",
|
|
69988
|
+
"Set the Agent LLM provider (claude | openai | gemini | xai | openrouter | ollama)"
|
|
69989
|
+
).option("--import-env", "Promote API keys from .env / shell env into config.yaml").option("--test", "After save, live-test each configured key (exits 7 if any FAIL)").option(
|
|
69974
69990
|
"--scope <scope>",
|
|
69975
69991
|
"Where to save: 'user' (~/.vibeframe/config.yaml, shared) or 'project' (./.vibeframe/config.yaml, gitignored, this project only)",
|
|
69976
69992
|
"user"
|
|
@@ -70020,10 +70036,12 @@ Exit codes (non-interactive):
|
|
|
70020
70036
|
return;
|
|
70021
70037
|
}
|
|
70022
70038
|
if (!hasTTY()) {
|
|
70023
|
-
exitWithError(
|
|
70024
|
-
|
|
70025
|
-
|
|
70026
|
-
|
|
70039
|
+
exitWithError(
|
|
70040
|
+
generalError(
|
|
70041
|
+
"Interactive setup requires a terminal.",
|
|
70042
|
+
"Run 'vibe setup' directly from your terminal, or use 'vibe setup --yes --provider <id> --import-env' for CI."
|
|
70043
|
+
)
|
|
70044
|
+
);
|
|
70027
70045
|
}
|
|
70028
70046
|
try {
|
|
70029
70047
|
await runSetupWizard(options.full, scope);
|
|
@@ -70040,24 +70058,50 @@ var AI_FEATURES = [
|
|
|
70040
70058
|
desc: "generate + edit",
|
|
70041
70059
|
defaultProvider: "OpenAI gpt-image-2 (Artificial Analysis #1, since v0.56)",
|
|
70042
70060
|
alsoAvailable: "Gemini Nano Banana, Grok Imagine",
|
|
70043
|
-
keys: [
|
|
70061
|
+
keys: [
|
|
70062
|
+
{
|
|
70063
|
+
configKey: "openai",
|
|
70064
|
+
envVar: "OPENAI_API_KEY",
|
|
70065
|
+
name: "OpenAI",
|
|
70066
|
+
url: "https://platform.openai.com/api-keys",
|
|
70067
|
+
what: "gpt-image-2 image generation + editing (also Whisper, Agent)"
|
|
70068
|
+
}
|
|
70069
|
+
],
|
|
70044
70070
|
providerChoices: [
|
|
70045
70071
|
{
|
|
70046
70072
|
label: "OpenAI gpt-image-2",
|
|
70047
70073
|
desc: "recommended default, image generation + editing",
|
|
70048
|
-
key: {
|
|
70074
|
+
key: {
|
|
70075
|
+
configKey: "openai",
|
|
70076
|
+
envVar: "OPENAI_API_KEY",
|
|
70077
|
+
name: "OpenAI",
|
|
70078
|
+
url: "https://platform.openai.com/api-keys",
|
|
70079
|
+
what: "gpt-image-2 image generation + editing (also Whisper, Agent)"
|
|
70080
|
+
},
|
|
70049
70081
|
defaultFor: { kind: "image", value: "openai" }
|
|
70050
70082
|
},
|
|
70051
70083
|
{
|
|
70052
70084
|
label: "Gemini",
|
|
70053
70085
|
desc: "Google image generation + multimodal analysis",
|
|
70054
|
-
key: {
|
|
70086
|
+
key: {
|
|
70087
|
+
configKey: "google",
|
|
70088
|
+
envVar: "GOOGLE_API_KEY",
|
|
70089
|
+
name: "Google",
|
|
70090
|
+
url: "https://aistudio.google.com/apikey",
|
|
70091
|
+
what: "Gemini image generation and multimodal analysis"
|
|
70092
|
+
},
|
|
70055
70093
|
defaultFor: { kind: "image", value: "gemini" }
|
|
70056
70094
|
},
|
|
70057
70095
|
{
|
|
70058
70096
|
label: "Grok",
|
|
70059
70097
|
desc: "xAI image generation",
|
|
70060
|
-
key: {
|
|
70098
|
+
key: {
|
|
70099
|
+
configKey: "xai",
|
|
70100
|
+
envVar: "XAI_API_KEY",
|
|
70101
|
+
name: "xAI",
|
|
70102
|
+
url: "https://console.x.ai/",
|
|
70103
|
+
what: "Grok image generation and Agent"
|
|
70104
|
+
},
|
|
70061
70105
|
defaultFor: { kind: "image", value: "grok" }
|
|
70062
70106
|
}
|
|
70063
70107
|
],
|
|
@@ -70068,36 +70112,74 @@ var AI_FEATURES = [
|
|
|
70068
70112
|
desc: "generate + extend",
|
|
70069
70113
|
defaultProvider: "Seedance 2.0 via fal.ai (Artificial Analysis #2 t2v + i2v, since v0.57)",
|
|
70070
70114
|
alsoAvailable: "Grok Imagine, Kling, Runway Gen-4.5, Google Veo",
|
|
70071
|
-
keys: [
|
|
70115
|
+
keys: [
|
|
70116
|
+
{
|
|
70117
|
+
configKey: "fal",
|
|
70118
|
+
envVar: "FAL_KEY",
|
|
70119
|
+
name: "Seedance 2.0 (via fal.ai)",
|
|
70120
|
+
url: "https://fal.ai/dashboard/keys",
|
|
70121
|
+
what: "ByteDance Seedance 2.0 text-to-video and image-to-video"
|
|
70122
|
+
}
|
|
70123
|
+
],
|
|
70072
70124
|
providerChoices: [
|
|
70073
70125
|
{
|
|
70074
70126
|
label: "Seedance 2.0 via fal.ai",
|
|
70075
70127
|
desc: "recommended default, text-to-video + image-to-video",
|
|
70076
|
-
key: {
|
|
70128
|
+
key: {
|
|
70129
|
+
configKey: "fal",
|
|
70130
|
+
envVar: "FAL_KEY",
|
|
70131
|
+
name: "Seedance 2.0 (via fal.ai)",
|
|
70132
|
+
url: "https://fal.ai/dashboard/keys",
|
|
70133
|
+
what: "ByteDance Seedance 2.0 text-to-video and image-to-video"
|
|
70134
|
+
},
|
|
70077
70135
|
defaultFor: { kind: "video", value: "seedance" }
|
|
70078
70136
|
},
|
|
70079
70137
|
{
|
|
70080
70138
|
label: "Grok",
|
|
70081
70139
|
desc: "xAI video generation with audio",
|
|
70082
|
-
key: {
|
|
70140
|
+
key: {
|
|
70141
|
+
configKey: "xai",
|
|
70142
|
+
envVar: "XAI_API_KEY",
|
|
70143
|
+
name: "xAI",
|
|
70144
|
+
url: "https://console.x.ai/",
|
|
70145
|
+
what: "Grok video generation and Agent"
|
|
70146
|
+
},
|
|
70083
70147
|
defaultFor: { kind: "video", value: "grok" }
|
|
70084
70148
|
},
|
|
70085
70149
|
{
|
|
70086
70150
|
label: "Kling",
|
|
70087
70151
|
desc: "Kling v2.5/v3 video generation",
|
|
70088
|
-
key: {
|
|
70152
|
+
key: {
|
|
70153
|
+
configKey: "kling",
|
|
70154
|
+
envVar: "KLING_API_KEY",
|
|
70155
|
+
name: "Kling",
|
|
70156
|
+
url: "https://platform.klingai.com/",
|
|
70157
|
+
what: "Kling video generation"
|
|
70158
|
+
},
|
|
70089
70159
|
defaultFor: { kind: "video", value: "kling" }
|
|
70090
70160
|
},
|
|
70091
70161
|
{
|
|
70092
70162
|
label: "Runway",
|
|
70093
70163
|
desc: "Runway Gen-4.5 video generation",
|
|
70094
|
-
key: {
|
|
70164
|
+
key: {
|
|
70165
|
+
configKey: "runway",
|
|
70166
|
+
envVar: "RUNWAY_API_SECRET",
|
|
70167
|
+
name: "Runway",
|
|
70168
|
+
url: "https://app.runwayml.com/settings/api-keys",
|
|
70169
|
+
what: "Runway Gen-4.5 video generation"
|
|
70170
|
+
},
|
|
70095
70171
|
defaultFor: { kind: "video", value: "runway" }
|
|
70096
70172
|
},
|
|
70097
70173
|
{
|
|
70098
70174
|
label: "Veo",
|
|
70099
70175
|
desc: "Google Veo video generation",
|
|
70100
|
-
key: {
|
|
70176
|
+
key: {
|
|
70177
|
+
configKey: "google",
|
|
70178
|
+
envVar: "GOOGLE_API_KEY",
|
|
70179
|
+
name: "Google",
|
|
70180
|
+
url: "https://aistudio.google.com/apikey",
|
|
70181
|
+
what: "Google Veo video generation"
|
|
70182
|
+
},
|
|
70101
70183
|
defaultFor: { kind: "video", value: "veo" }
|
|
70102
70184
|
}
|
|
70103
70185
|
],
|
|
@@ -70108,12 +70190,26 @@ var AI_FEATURES = [
|
|
|
70108
70190
|
desc: "TTS, SFX, music, voice clone",
|
|
70109
70191
|
defaultProvider: "ElevenLabs (paid, premium quality) \u2014 falls back to local Kokoro when no key (free, since v0.54)",
|
|
70110
70192
|
alsoAvailable: "Replicate MusicGen (music only)",
|
|
70111
|
-
keys: [
|
|
70193
|
+
keys: [
|
|
70194
|
+
{
|
|
70195
|
+
configKey: "elevenlabs",
|
|
70196
|
+
envVar: "ELEVENLABS_API_KEY",
|
|
70197
|
+
name: "ElevenLabs",
|
|
70198
|
+
url: "https://elevenlabs.io/app/settings/api-keys",
|
|
70199
|
+
what: "Text-to-speech, sound effects, music, voice cloning (skip to use local Kokoro)"
|
|
70200
|
+
}
|
|
70201
|
+
],
|
|
70112
70202
|
providerChoices: [
|
|
70113
70203
|
{
|
|
70114
70204
|
label: "ElevenLabs",
|
|
70115
70205
|
desc: "premium TTS, SFX, music, voice clone",
|
|
70116
|
-
key: {
|
|
70206
|
+
key: {
|
|
70207
|
+
configKey: "elevenlabs",
|
|
70208
|
+
envVar: "ELEVENLABS_API_KEY",
|
|
70209
|
+
name: "ElevenLabs",
|
|
70210
|
+
url: "https://elevenlabs.io/app/settings/api-keys",
|
|
70211
|
+
what: "Text-to-speech, sound effects, music, voice cloning"
|
|
70212
|
+
}
|
|
70117
70213
|
},
|
|
70118
70214
|
{
|
|
70119
70215
|
label: "Kokoro local",
|
|
@@ -70123,7 +70219,13 @@ var AI_FEATURES = [
|
|
|
70123
70219
|
{
|
|
70124
70220
|
label: "Replicate MusicGen",
|
|
70125
70221
|
desc: "background music generation",
|
|
70126
|
-
key: {
|
|
70222
|
+
key: {
|
|
70223
|
+
configKey: "replicate",
|
|
70224
|
+
envVar: "REPLICATE_API_TOKEN",
|
|
70225
|
+
name: "Replicate",
|
|
70226
|
+
url: "https://replicate.com/account/api-tokens",
|
|
70227
|
+
what: "MusicGen background music"
|
|
70228
|
+
}
|
|
70127
70229
|
}
|
|
70128
70230
|
],
|
|
70129
70231
|
tryCommand: 'vibe generate speech "Hello world" -o hello.mp3'
|
|
@@ -70134,8 +70236,20 @@ var AI_FEATURES = [
|
|
|
70134
70236
|
defaultProvider: "Whisper (transcription) + Claude (reasoning)",
|
|
70135
70237
|
alsoAvailable: "",
|
|
70136
70238
|
keys: [
|
|
70137
|
-
{
|
|
70138
|
-
|
|
70239
|
+
{
|
|
70240
|
+
configKey: "openai",
|
|
70241
|
+
envVar: "OPENAI_API_KEY",
|
|
70242
|
+
name: "OpenAI",
|
|
70243
|
+
url: "https://platform.openai.com/api-keys",
|
|
70244
|
+
what: "Whisper transcription (captions, jump-cut)"
|
|
70245
|
+
},
|
|
70246
|
+
{
|
|
70247
|
+
configKey: "anthropic",
|
|
70248
|
+
envVar: "ANTHROPIC_API_KEY",
|
|
70249
|
+
name: "Anthropic",
|
|
70250
|
+
url: "https://console.anthropic.com/settings/keys",
|
|
70251
|
+
what: "Claude (color grade, reframe, motion graphics)"
|
|
70252
|
+
}
|
|
70139
70253
|
],
|
|
70140
70254
|
tryCommand: "vibe edit caption video.mp4 -o captioned.mp4"
|
|
70141
70255
|
}
|
|
@@ -70166,6 +70280,14 @@ function isProviderChoiceConfigured(config2, choice) {
|
|
|
70166
70280
|
}
|
|
70167
70281
|
return false;
|
|
70168
70282
|
}
|
|
70283
|
+
function isFeatureConfigured(config2, feature) {
|
|
70284
|
+
if (feature.providerChoices?.some((choice) => isProviderChoiceConfigured(config2, choice))) {
|
|
70285
|
+
return true;
|
|
70286
|
+
}
|
|
70287
|
+
return feature.keys.some(
|
|
70288
|
+
(keyDef) => Boolean(config2.providers[keyDef.configKey])
|
|
70289
|
+
);
|
|
70290
|
+
}
|
|
70169
70291
|
function mergeSelectedFeatures(current, next) {
|
|
70170
70292
|
const merged = [...current];
|
|
70171
70293
|
for (const feature of next) {
|
|
@@ -70184,10 +70306,12 @@ async function runNonInteractiveSetup(opts) {
|
|
|
70184
70306
|
const changes = [];
|
|
70185
70307
|
if (opts.provider) {
|
|
70186
70308
|
if (!VALID_LLM_PROVIDERS.includes(opts.provider)) {
|
|
70187
|
-
exitWithError(
|
|
70188
|
-
|
|
70189
|
-
|
|
70190
|
-
|
|
70309
|
+
exitWithError(
|
|
70310
|
+
generalError(
|
|
70311
|
+
`Invalid --provider: ${opts.provider}`,
|
|
70312
|
+
`Must be one of: ${VALID_LLM_PROVIDERS.join(", ")}`
|
|
70313
|
+
)
|
|
70314
|
+
);
|
|
70191
70315
|
}
|
|
70192
70316
|
if (config2.llm.provider !== opts.provider) {
|
|
70193
70317
|
config2.llm.provider = opts.provider;
|
|
@@ -70254,7 +70378,11 @@ async function runNonInteractiveSetup(opts) {
|
|
|
70254
70378
|
}
|
|
70255
70379
|
if (failures > 0) {
|
|
70256
70380
|
console.error();
|
|
70257
|
-
console.error(
|
|
70381
|
+
console.error(
|
|
70382
|
+
source_default.red(
|
|
70383
|
+
`Verification failed: ${failures} key${failures === 1 ? "" : "s"} returned non-2xx.`
|
|
70384
|
+
)
|
|
70385
|
+
);
|
|
70258
70386
|
process.exit(7);
|
|
70259
70387
|
}
|
|
70260
70388
|
}
|
|
@@ -70263,15 +70391,11 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
70263
70391
|
console.log();
|
|
70264
70392
|
const cfgPath = getConfigPath(scope).replace(homedir5(), "~");
|
|
70265
70393
|
const scopeNote = scope === "project" ? "applies to this project only \xB7 add .vibeframe/ to .gitignore" : "applies to every project for this user";
|
|
70266
|
-
console.log(
|
|
70267
|
-
source_default.bold.magenta("VibeFrame Setup") + source_default.bold(` \u2014 ${scope} scope`)
|
|
70268
|
-
);
|
|
70394
|
+
console.log(source_default.bold.magenta("VibeFrame Setup") + source_default.bold(` \u2014 ${scope} scope`));
|
|
70269
70395
|
console.log(source_default.dim(`${cfgPath} \xB7 ${scopeNote}`));
|
|
70270
70396
|
if (scope === "user") {
|
|
70271
70397
|
console.log(
|
|
70272
|
-
source_default.dim(
|
|
70273
|
-
"Tip: for per-project keys, cd into a project and run: vibe setup --scope project"
|
|
70274
|
-
)
|
|
70398
|
+
source_default.dim("Tip: for per-project keys, cd into a project and run: vibe setup --scope project")
|
|
70275
70399
|
);
|
|
70276
70400
|
}
|
|
70277
70401
|
console.log(source_default.dim("\u2500".repeat(40)));
|
|
@@ -70312,10 +70436,34 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
70312
70436
|
if (topIndex === 2) {
|
|
70313
70437
|
config2.llm.provider = "claude";
|
|
70314
70438
|
const pipelineKeys = [
|
|
70315
|
-
{
|
|
70316
|
-
|
|
70317
|
-
|
|
70318
|
-
|
|
70439
|
+
{
|
|
70440
|
+
configKey: "anthropic",
|
|
70441
|
+
envVar: "ANTHROPIC_API_KEY",
|
|
70442
|
+
name: "Anthropic",
|
|
70443
|
+
url: "https://console.anthropic.com/settings/keys",
|
|
70444
|
+
what: "Claude \u2014 storyboard generation + reasoning"
|
|
70445
|
+
},
|
|
70446
|
+
{
|
|
70447
|
+
configKey: "openai",
|
|
70448
|
+
envVar: "OPENAI_API_KEY",
|
|
70449
|
+
name: "OpenAI",
|
|
70450
|
+
url: "https://platform.openai.com/api-keys",
|
|
70451
|
+
what: "gpt-image-2 image generation (default since v0.56) + Whisper word-level transcribe"
|
|
70452
|
+
},
|
|
70453
|
+
{
|
|
70454
|
+
configKey: "fal",
|
|
70455
|
+
envVar: "FAL_KEY",
|
|
70456
|
+
name: "fal.ai",
|
|
70457
|
+
url: "https://fal.ai/dashboard/keys",
|
|
70458
|
+
what: "Seedance 2.0 \u2014 video generation, default since v0.57"
|
|
70459
|
+
},
|
|
70460
|
+
{
|
|
70461
|
+
configKey: "elevenlabs",
|
|
70462
|
+
envVar: "ELEVENLABS_API_KEY",
|
|
70463
|
+
name: "ElevenLabs",
|
|
70464
|
+
url: "https://elevenlabs.io/app/settings/api-keys",
|
|
70465
|
+
what: "Text-to-speech narration + music (skip to use local Kokoro)"
|
|
70466
|
+
}
|
|
70319
70467
|
];
|
|
70320
70468
|
console.log(source_default.dim("2. API keys"));
|
|
70321
70469
|
console.log(source_default.bold("Pipeline requires these API keys:"));
|
|
@@ -70323,10 +70471,19 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
|
70323
70471
|
console.log();
|
|
70324
70472
|
await collectKeys(config2, pipelineKeys);
|
|
70325
70473
|
await saveConfig(config2, { scope });
|
|
70326
|
-
await completeOrContinue(
|
|
70474
|
+
await completeOrContinue(
|
|
70475
|
+
config2,
|
|
70476
|
+
"vibe build my-story/ # see CONTRIBUTING.md for STORYBOARD.md format",
|
|
70477
|
+
[],
|
|
70478
|
+
scope
|
|
70479
|
+
);
|
|
70327
70480
|
return;
|
|
70328
70481
|
}
|
|
70329
70482
|
const result = await runAIFeaturesSetup(config2, scope);
|
|
70483
|
+
if (result.back) {
|
|
70484
|
+
await completeOrContinue(config2, "vibe --help", [], scope);
|
|
70485
|
+
return;
|
|
70486
|
+
}
|
|
70330
70487
|
await saveConfig(config2, { scope });
|
|
70331
70488
|
await completeOrContinue(config2, result.tryCommand, result.selectedFeatures, scope);
|
|
70332
70489
|
}
|
|
@@ -70346,6 +70503,10 @@ async function completeOrContinue(config2, tryCommand, selectedFeatures, scope)
|
|
|
70346
70503
|
console.log();
|
|
70347
70504
|
if (action === 0) {
|
|
70348
70505
|
const result = await runAIFeaturesSetup(config2, scope);
|
|
70506
|
+
if (result.back) {
|
|
70507
|
+
await completeOrContinue(config2, tryCommand, selectedFeatures, scope);
|
|
70508
|
+
return;
|
|
70509
|
+
}
|
|
70349
70510
|
const mergedFeatures = mergeSelectedFeatures(selectedFeatures, result.selectedFeatures);
|
|
70350
70511
|
const mergedTryCommand = selectedFeatures.length > 0 ? tryCommand : result.tryCommand;
|
|
70351
70512
|
await saveConfig(config2, { scope });
|
|
@@ -70361,142 +70522,176 @@ async function completeOrContinue(config2, tryCommand, selectedFeatures, scope)
|
|
|
70361
70522
|
await showComplete(config2, tryCommand, selectedFeatures, scope);
|
|
70362
70523
|
}
|
|
70363
70524
|
async function runAIFeaturesSetup(config2, _scope) {
|
|
70364
|
-
|
|
70365
|
-
|
|
70366
|
-
|
|
70367
|
-
|
|
70368
|
-
|
|
70369
|
-
|
|
70370
|
-
|
|
70371
|
-
|
|
70372
|
-
|
|
70373
|
-
|
|
70374
|
-
|
|
70375
|
-
|
|
70376
|
-
|
|
70377
|
-
|
|
70378
|
-
{ pickFocusedOnEnter: true }
|
|
70379
|
-
);
|
|
70380
|
-
const selectedFeatures = picked.map((i) => AI_FEATURES[i]);
|
|
70381
|
-
console.log();
|
|
70382
|
-
if (selectedFeatures.length === 0) {
|
|
70383
|
-
console.log(source_default.dim(" No features selected. You can re-run setup anytime."));
|
|
70525
|
+
featureSelection: for (; ; ) {
|
|
70526
|
+
console.log(source_default.dim("2. Features"));
|
|
70527
|
+
console.log(source_default.bold("Which AI features do you need?"));
|
|
70528
|
+
console.log(
|
|
70529
|
+
source_default.dim(
|
|
70530
|
+
` ${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.`
|
|
70531
|
+
)
|
|
70532
|
+
);
|
|
70533
|
+
console.log(source_default.dim(" Shortcut: enter alone picks only the highlighted feature."));
|
|
70534
|
+
console.log(
|
|
70535
|
+
source_default.dim(
|
|
70536
|
+
` Select ${source_default.bold("Back")} or press ${source_default.bold("Esc/\u2190")} to return to the setup checkpoint.`
|
|
70537
|
+
)
|
|
70538
|
+
);
|
|
70384
70539
|
console.log();
|
|
70385
|
-
|
|
70386
|
-
|
|
70387
|
-
|
|
70388
|
-
|
|
70389
|
-
|
|
70390
|
-
|
|
70391
|
-
|
|
70392
|
-
|
|
70393
|
-
|
|
70394
|
-
|
|
70395
|
-
|
|
70396
|
-
|
|
70397
|
-
|
|
70398
|
-
|
|
70399
|
-
}
|
|
70540
|
+
const backIndex = AI_FEATURES.length;
|
|
70541
|
+
const featureLabels = [
|
|
70542
|
+
...AI_FEATURES.map((f) => {
|
|
70543
|
+
const keyCount = f.keys.length;
|
|
70544
|
+
const tag = source_default.dim(`${keyCount} key${keyCount > 1 ? "s" : ""}`);
|
|
70545
|
+
return `${f.label} ${source_default.dim(`(${f.desc})`)} ${tag}`;
|
|
70546
|
+
}),
|
|
70547
|
+
`Back ${source_default.dim("(return to setup checkpoint)")}`
|
|
70548
|
+
];
|
|
70549
|
+
const configuredFeatures = AI_FEATURES.map((feature) => isFeatureConfigured(config2, feature));
|
|
70550
|
+
const picked = await promptMultiSelect(
|
|
70551
|
+
source_default.cyan(" Pick (e.g. 1,3 or 'all'): "),
|
|
70552
|
+
featureLabels,
|
|
70553
|
+
[...configuredFeatures, false],
|
|
70554
|
+
{ pickFocusedOnEnter: true, backIndex }
|
|
70555
|
+
);
|
|
70556
|
+
if (picked.includes(backIndex)) {
|
|
70400
70557
|
console.log();
|
|
70401
|
-
|
|
70402
|
-
|
|
70403
|
-
|
|
70404
|
-
|
|
70405
|
-
|
|
70406
|
-
|
|
70407
|
-
return [
|
|
70408
|
-
choice.label,
|
|
70409
|
-
defaultHint,
|
|
70410
|
-
source_default.dim(`- ${choice.desc}`),
|
|
70411
|
-
keyHint
|
|
70412
|
-
].filter(Boolean).join(" ");
|
|
70413
|
-
});
|
|
70414
|
-
const pickedProviders = await promptMultiSelect(
|
|
70415
|
-
source_default.cyan(" Providers (arrow + enter picks one, space adds more): "),
|
|
70416
|
-
providerLabels,
|
|
70417
|
-
defaultSelected,
|
|
70418
|
-
{ pickFocusedOnEnter: true, preserveDefaultSelectionOnEnter: true }
|
|
70419
|
-
);
|
|
70420
|
-
const selectedChoices = pickedProviders.map((i) => feature.providerChoices[i]);
|
|
70421
|
-
const defaultChoice = selectedChoices.find((choice) => choice.defaultFor);
|
|
70422
|
-
if (defaultChoice) {
|
|
70423
|
-
applyProviderDefault(config2, defaultChoice);
|
|
70424
|
-
}
|
|
70425
|
-
for (const choice of selectedChoices) {
|
|
70426
|
-
if (choice.key) addUniqueKey(keysForFeature, choice.key);
|
|
70427
|
-
}
|
|
70428
|
-
if (selectedChoices.some((choice) => choice.keyless)) {
|
|
70429
|
-
console.log(source_default.dim(" No API key needed for selected local provider(s)."));
|
|
70430
|
-
}
|
|
70558
|
+
return { tryCommand: "vibe --help", selectedFeatures: [], back: true };
|
|
70559
|
+
}
|
|
70560
|
+
const selectedFeatures = picked.filter((i) => i < AI_FEATURES.length).map((i) => AI_FEATURES[i]);
|
|
70561
|
+
console.log();
|
|
70562
|
+
if (selectedFeatures.length === 0) {
|
|
70563
|
+
console.log(source_default.dim(" No features selected. You can re-run setup anytime."));
|
|
70431
70564
|
console.log();
|
|
70432
|
-
|
|
70433
|
-
for (const keyDef of feature.keys) {
|
|
70434
|
-
addUniqueKey(keysForFeature, keyDef);
|
|
70435
|
-
}
|
|
70565
|
+
return { tryCommand: "vibe --help", selectedFeatures: [] };
|
|
70436
70566
|
}
|
|
70437
|
-
plannedKeys
|
|
70438
|
-
|
|
70439
|
-
|
|
70440
|
-
|
|
70441
|
-
|
|
70442
|
-
|
|
70443
|
-
|
|
70567
|
+
const plannedKeys = /* @__PURE__ */ new Map();
|
|
70568
|
+
console.log(source_default.dim("3. Providers"));
|
|
70569
|
+
console.log(source_default.bold("Choose providers for each selected feature"));
|
|
70570
|
+
console.log(
|
|
70571
|
+
source_default.dim(
|
|
70572
|
+
` Recommended default is highlighted. Press ${source_default.bold("enter")} to pick the highlighted provider, ${source_default.bold("space")} to choose multiple, or ${source_default.bold("Esc/\u2190")} to go back.`
|
|
70573
|
+
)
|
|
70574
|
+
);
|
|
70444
70575
|
console.log();
|
|
70445
|
-
const collectedKeys = /* @__PURE__ */ new Set();
|
|
70446
70576
|
for (const feature of selectedFeatures) {
|
|
70447
|
-
const keysForFeature =
|
|
70448
|
-
if (
|
|
70449
|
-
|
|
70450
|
-
|
|
70451
|
-
|
|
70452
|
-
|
|
70453
|
-
|
|
70454
|
-
console.log(
|
|
70577
|
+
const keysForFeature = [];
|
|
70578
|
+
if (feature.providerChoices && feature.providerChoices.length > 0) {
|
|
70579
|
+
console.log(source_default.bold.cyan(` ${feature.label}`));
|
|
70580
|
+
console.log(source_default.dim(` Default path: ${feature.defaultProvider}`));
|
|
70581
|
+
if (feature.alsoAvailable) {
|
|
70582
|
+
console.log(source_default.dim(` Alternatives: ${feature.alsoAvailable}`));
|
|
70583
|
+
}
|
|
70584
|
+
console.log();
|
|
70585
|
+
const defaultSelected = feature.providerChoices.map(
|
|
70586
|
+
(choice) => isProviderChoiceConfigured(config2, choice)
|
|
70587
|
+
);
|
|
70588
|
+
const providerLabels = feature.providerChoices.map((choice) => {
|
|
70589
|
+
const keyHint = choice.keyless ? source_default.dim("no key") : choice.key ? source_default.dim(choice.key.envVar) : source_default.dim("no key");
|
|
70590
|
+
const defaultHint = choice === feature.providerChoices?.[0] ? source_default.dim("recommended default") : "";
|
|
70591
|
+
return [choice.label, defaultHint, source_default.dim(`- ${choice.desc}`), keyHint].filter(Boolean).join(" ");
|
|
70592
|
+
});
|
|
70593
|
+
const backProviderIndex = providerLabels.length;
|
|
70594
|
+
const pickedProviders = await promptMultiSelect(
|
|
70595
|
+
source_default.cyan(" Providers (arrow + enter picks one, space adds more): "),
|
|
70596
|
+
[...providerLabels, `Back ${source_default.dim("(choose different features)")}`],
|
|
70597
|
+
[...defaultSelected, false],
|
|
70598
|
+
{
|
|
70599
|
+
pickFocusedOnEnter: true,
|
|
70600
|
+
preserveDefaultSelectionOnEnter: true,
|
|
70601
|
+
backIndex: backProviderIndex
|
|
70602
|
+
}
|
|
70603
|
+
);
|
|
70604
|
+
if (pickedProviders.includes(backProviderIndex)) {
|
|
70605
|
+
console.log();
|
|
70606
|
+
continue featureSelection;
|
|
70607
|
+
}
|
|
70608
|
+
const selectedChoices = pickedProviders.filter((i) => i < feature.providerChoices.length).map((i) => feature.providerChoices[i]);
|
|
70609
|
+
const defaultChoice = selectedChoices.find((choice) => choice.defaultFor);
|
|
70610
|
+
if (defaultChoice) {
|
|
70611
|
+
applyProviderDefault(config2, defaultChoice);
|
|
70612
|
+
}
|
|
70613
|
+
for (const choice of selectedChoices) {
|
|
70614
|
+
if (choice.key) addUniqueKey(keysForFeature, choice.key);
|
|
70615
|
+
}
|
|
70616
|
+
if (selectedChoices.some((choice) => choice.keyless)) {
|
|
70617
|
+
console.log(source_default.dim(" No API key needed for selected local provider(s)."));
|
|
70618
|
+
}
|
|
70619
|
+
console.log();
|
|
70620
|
+
} else {
|
|
70621
|
+
for (const keyDef of feature.keys) {
|
|
70622
|
+
addUniqueKey(keysForFeature, keyDef);
|
|
70623
|
+
}
|
|
70455
70624
|
}
|
|
70625
|
+
plannedKeys.set(feature.label, keysForFeature);
|
|
70626
|
+
}
|
|
70627
|
+
const needsKeys = [...plannedKeys.values()].some((keys) => keys.length > 0);
|
|
70628
|
+
if (needsKeys) {
|
|
70629
|
+
console.log(source_default.dim("4. API keys"));
|
|
70630
|
+
console.log(source_default.bold("API Keys"));
|
|
70631
|
+
console.log(source_default.dim(" Saved locally, never shared. Press Enter to skip."));
|
|
70456
70632
|
console.log();
|
|
70457
|
-
|
|
70458
|
-
|
|
70459
|
-
|
|
70633
|
+
const collectedKeys = /* @__PURE__ */ new Set();
|
|
70634
|
+
for (const feature of selectedFeatures) {
|
|
70635
|
+
const keysForFeature = plannedKeys.get(feature.label) ?? [];
|
|
70636
|
+
if (keysForFeature.length === 0) {
|
|
70460
70637
|
continue;
|
|
70461
70638
|
}
|
|
70462
|
-
|
|
70463
|
-
|
|
70464
|
-
|
|
70465
|
-
|
|
70466
|
-
const value = configValue || envValue;
|
|
70467
|
-
const source = configValue ? "config" : ".env";
|
|
70468
|
-
console.log(` ${source_default.green("\u2713")} ${keyDef.name.padEnd(14)} ${maskApiKey(value)} ${source_default.dim(`(${source})`)}`);
|
|
70469
|
-
collectedKeys.add(keyDef.configKey);
|
|
70470
|
-
continue;
|
|
70639
|
+
console.log(source_default.bold.cyan(` ${feature.label}`));
|
|
70640
|
+
console.log(source_default.dim(` Default: ${feature.defaultProvider}`));
|
|
70641
|
+
if (feature.alsoAvailable) {
|
|
70642
|
+
console.log(source_default.dim(` Also available: ${feature.alsoAvailable}`));
|
|
70471
70643
|
}
|
|
70472
|
-
console.log(
|
|
70473
|
-
|
|
70474
|
-
|
|
70475
|
-
|
|
70476
|
-
|
|
70477
|
-
|
|
70478
|
-
|
|
70479
|
-
const
|
|
70480
|
-
|
|
70481
|
-
|
|
70482
|
-
|
|
70483
|
-
|
|
70644
|
+
console.log();
|
|
70645
|
+
for (const keyDef of keysForFeature) {
|
|
70646
|
+
if (collectedKeys.has(keyDef.configKey)) {
|
|
70647
|
+
console.log(` ${source_default.green("\u2713")} ${keyDef.name.padEnd(14)} (already set above)`);
|
|
70648
|
+
continue;
|
|
70649
|
+
}
|
|
70650
|
+
loadEnv();
|
|
70651
|
+
const configValue = config2.providers[keyDef.configKey];
|
|
70652
|
+
const envValue = process.env[keyDef.envVar];
|
|
70653
|
+
if (configValue || envValue) {
|
|
70654
|
+
const value = configValue || envValue;
|
|
70655
|
+
const source = configValue ? "config" : ".env";
|
|
70656
|
+
console.log(
|
|
70657
|
+
` ${source_default.green("\u2713")} ${keyDef.name.padEnd(14)} ${maskApiKey(value)} ${source_default.dim(`(${source})`)}`
|
|
70658
|
+
);
|
|
70659
|
+
collectedKeys.add(keyDef.configKey);
|
|
70660
|
+
continue;
|
|
70661
|
+
}
|
|
70662
|
+
console.log(source_default.dim(` ${keyDef.what}`));
|
|
70663
|
+
console.log(source_default.dim(` Get key: ${keyDef.url} [o] open in browser`));
|
|
70664
|
+
const newKey = await promptHidden(
|
|
70665
|
+
source_default.cyan(` ${keyDef.name.padEnd(14)} ${source_default.dim(keyDef.envVar)}: `),
|
|
70666
|
+
{ openHotkeyUrl: keyDef.url }
|
|
70667
|
+
);
|
|
70668
|
+
if (newKey.trim()) {
|
|
70669
|
+
const trimmed = newKey.trim();
|
|
70670
|
+
config2.providers[keyDef.configKey] = trimmed;
|
|
70671
|
+
const fmt = validateKeyFormat(keyDef.configKey, trimmed);
|
|
70672
|
+
if (!fmt.ok && fmt.expected) {
|
|
70673
|
+
console.log(
|
|
70674
|
+
` ${source_default.yellow("\u26A0")} Saved, but format looks unusual ${source_default.dim(`(expected ${fmt.expected})`)}`
|
|
70675
|
+
);
|
|
70676
|
+
} else {
|
|
70677
|
+
console.log(` ${source_default.green("\u2713")} Saved`);
|
|
70678
|
+
}
|
|
70679
|
+
collectedKeys.add(keyDef.configKey);
|
|
70484
70680
|
} else {
|
|
70485
|
-
console.log(
|
|
70681
|
+
console.log(
|
|
70682
|
+
` ${source_default.yellow("\u26A0")} Skipped ${source_default.dim(`(set ${keyDef.envVar} in .env later)`)}`
|
|
70683
|
+
);
|
|
70486
70684
|
}
|
|
70487
|
-
collectedKeys.add(keyDef.configKey);
|
|
70488
|
-
} else {
|
|
70489
|
-
console.log(` ${source_default.yellow("\u26A0")} Skipped ${source_default.dim(`(set ${keyDef.envVar} in .env later)`)}`);
|
|
70490
70685
|
}
|
|
70686
|
+
console.log();
|
|
70491
70687
|
}
|
|
70688
|
+
} else {
|
|
70689
|
+
console.log(source_default.dim("4. API keys"));
|
|
70690
|
+
console.log(source_default.dim(" No API keys needed for the selected provider(s)."));
|
|
70492
70691
|
console.log();
|
|
70493
70692
|
}
|
|
70494
|
-
|
|
70495
|
-
console.log(source_default.dim("4. API keys"));
|
|
70496
|
-
console.log(source_default.dim(" No API keys needed for the selected provider(s)."));
|
|
70497
|
-
console.log();
|
|
70693
|
+
return { tryCommand: selectedFeatures[0].tryCommand, selectedFeatures };
|
|
70498
70694
|
}
|
|
70499
|
-
return { tryCommand: selectedFeatures[0].tryCommand, selectedFeatures };
|
|
70500
70695
|
}
|
|
70501
70696
|
async function collectKeys(config2, keys) {
|
|
70502
70697
|
loadEnv();
|
|
@@ -70504,11 +70699,15 @@ async function collectKeys(config2, keys) {
|
|
|
70504
70699
|
const configValue = config2.providers[keyDef.configKey];
|
|
70505
70700
|
const envValue = process.env[keyDef.envVar];
|
|
70506
70701
|
if (configValue) {
|
|
70507
|
-
console.log(
|
|
70702
|
+
console.log(
|
|
70703
|
+
` ${source_default.green("\u2713")} ${keyDef.name.padEnd(14)} ${maskApiKey(configValue)} ${source_default.dim("(config)")}`
|
|
70704
|
+
);
|
|
70508
70705
|
continue;
|
|
70509
70706
|
}
|
|
70510
70707
|
if (envValue) {
|
|
70511
|
-
console.log(
|
|
70708
|
+
console.log(
|
|
70709
|
+
` ${source_default.green("\u2713")} ${keyDef.name.padEnd(14)} ${maskApiKey(envValue)} ${source_default.dim("(.env)")}`
|
|
70710
|
+
);
|
|
70512
70711
|
continue;
|
|
70513
70712
|
}
|
|
70514
70713
|
console.log(source_default.dim(` ${keyDef.what}`));
|
|
@@ -70522,12 +70721,16 @@ async function collectKeys(config2, keys) {
|
|
|
70522
70721
|
config2.providers[keyDef.configKey] = trimmed;
|
|
70523
70722
|
const fmt = validateKeyFormat(keyDef.configKey, trimmed);
|
|
70524
70723
|
if (!fmt.ok && fmt.expected) {
|
|
70525
|
-
console.log(
|
|
70724
|
+
console.log(
|
|
70725
|
+
` ${source_default.yellow("\u26A0")} Saved, but format looks unusual ${source_default.dim(`(expected ${fmt.expected})`)}`
|
|
70726
|
+
);
|
|
70526
70727
|
} else {
|
|
70527
70728
|
console.log(` ${source_default.green("\u2713")} Saved`);
|
|
70528
70729
|
}
|
|
70529
70730
|
} else {
|
|
70530
|
-
console.log(
|
|
70731
|
+
console.log(
|
|
70732
|
+
` ${source_default.yellow("\u26A0")} Skipped ${source_default.dim(`(set ${keyDef.envVar} in .env later)`)}`
|
|
70733
|
+
);
|
|
70531
70734
|
}
|
|
70532
70735
|
}
|
|
70533
70736
|
console.log();
|
|
@@ -70564,37 +70767,41 @@ async function runCustomSetup(config2, scope = "user", opts = {}) {
|
|
|
70564
70767
|
for (const p of allProviders) {
|
|
70565
70768
|
const existing = config2.providers[p.key];
|
|
70566
70769
|
if (existing) {
|
|
70567
|
-
console.log(
|
|
70770
|
+
console.log(
|
|
70771
|
+
` ${source_default.green("\u2713")} ${p.name.padEnd(12)} ${maskApiKey(existing)} ${source_default.dim(p.desc)}`
|
|
70772
|
+
);
|
|
70568
70773
|
const change = await promptConfirm(source_default.cyan(" Update?"), false);
|
|
70569
70774
|
if (change) {
|
|
70570
70775
|
console.log(source_default.dim(` Get key: ${p.url} [o] open in browser`));
|
|
70571
|
-
const newKey = await promptHidden(
|
|
70572
|
-
source_default.cyan(" New key: "),
|
|
70573
|
-
{ openHotkeyUrl: p.url }
|
|
70574
|
-
);
|
|
70776
|
+
const newKey = await promptHidden(source_default.cyan(" New key: "), { openHotkeyUrl: p.url });
|
|
70575
70777
|
if (newKey.trim()) {
|
|
70576
70778
|
const trimmed = newKey.trim();
|
|
70577
70779
|
config2.providers[p.key] = trimmed;
|
|
70578
70780
|
const fmt = validateKeyFormat(p.key, trimmed);
|
|
70579
70781
|
if (!fmt.ok && fmt.expected) {
|
|
70580
|
-
console.log(
|
|
70782
|
+
console.log(
|
|
70783
|
+
source_default.yellow(` \u26A0 Updated, but format looks unusual (expected ${fmt.expected})`)
|
|
70784
|
+
);
|
|
70581
70785
|
} else {
|
|
70582
70786
|
console.log(source_default.green(" \u2713 Updated"));
|
|
70583
70787
|
}
|
|
70584
70788
|
}
|
|
70585
70789
|
}
|
|
70586
70790
|
} else {
|
|
70587
|
-
console.log(
|
|
70588
|
-
|
|
70589
|
-
|
|
70590
|
-
|
|
70791
|
+
console.log(
|
|
70792
|
+
source_default.dim(
|
|
70793
|
+
` ${source_default.dim("\u25CB")} ${p.name.padEnd(12)} ${source_default.dim(p.desc)} Get key: ${p.url} [o] open`
|
|
70794
|
+
)
|
|
70591
70795
|
);
|
|
70796
|
+
const newKey = await promptHidden(source_default.cyan(` ${p.env}: `), { openHotkeyUrl: p.url });
|
|
70592
70797
|
if (newKey.trim()) {
|
|
70593
70798
|
const trimmed = newKey.trim();
|
|
70594
70799
|
config2.providers[p.key] = trimmed;
|
|
70595
70800
|
const fmt = validateKeyFormat(p.key, trimmed);
|
|
70596
70801
|
if (!fmt.ok && fmt.expected) {
|
|
70597
|
-
console.log(
|
|
70802
|
+
console.log(
|
|
70803
|
+
` ${source_default.yellow("\u26A0")} Saved, but format looks unusual ${source_default.dim(`(expected ${fmt.expected})`)}`
|
|
70804
|
+
);
|
|
70598
70805
|
} else {
|
|
70599
70806
|
console.log(` ${source_default.green("\u2713")} Saved`);
|
|
70600
70807
|
}
|
|
@@ -70631,14 +70838,20 @@ async function showComplete(config2, defaultTryCommand, features = [], scope = "
|
|
|
70631
70838
|
}
|
|
70632
70839
|
console.log();
|
|
70633
70840
|
console.log(source_default.bold(" Next steps:"));
|
|
70634
|
-
console.log(
|
|
70841
|
+
console.log(
|
|
70842
|
+
source_default.dim(
|
|
70843
|
+
" cd <project>; vibe init Scaffold AGENTS.md / CLAUDE.md / .env.example (project scope)"
|
|
70844
|
+
)
|
|
70845
|
+
);
|
|
70635
70846
|
const hostDetected = detectedAgentHosts().length > 0;
|
|
70636
70847
|
for (const w of listWalkthroughs()) {
|
|
70637
70848
|
const cmd = `vibe walkthrough ${w.topic}`.padEnd(26);
|
|
70638
70849
|
const tag = hostDetected && w.topic === "scene" ? source_default.cyan(" (recommended)") : "";
|
|
70639
70850
|
console.log(source_default.dim(` ${cmd}${w.summary}${tag}`));
|
|
70640
70851
|
}
|
|
70641
|
-
console.log(
|
|
70852
|
+
console.log(
|
|
70853
|
+
source_default.dim(" vibe doctor --test-keys Live-check each provider key against its API")
|
|
70854
|
+
);
|
|
70642
70855
|
console.log(source_default.dim(" vibe doctor Check system health + available commands"));
|
|
70643
70856
|
console.log(source_default.dim(" vibe schema --list Discover every command"));
|
|
70644
70857
|
console.log(source_default.dim(" vibe setup Re-run user-scope setup anytime"));
|
|
@@ -70773,7 +70986,11 @@ async function showConfig(opts = { verbose: false }) {
|
|
|
70773
70986
|
}
|
|
70774
70987
|
}
|
|
70775
70988
|
if (!verbose && unsetCount > 0) {
|
|
70776
|
-
console.log(
|
|
70989
|
+
console.log(
|
|
70990
|
+
source_default.dim(
|
|
70991
|
+
` (${unsetCount} provider${unsetCount === 1 ? "" : "s"} unset \u2014 run with --verbose to list)`
|
|
70992
|
+
)
|
|
70993
|
+
);
|
|
70777
70994
|
}
|
|
70778
70995
|
console.log();
|
|
70779
70996
|
if (verbose) {
|
|
@@ -70785,8 +71002,12 @@ async function showConfig(opts = { verbose: false }) {
|
|
|
70785
71002
|
}
|
|
70786
71003
|
console.log(source_default.bold("Resolution order:"));
|
|
70787
71004
|
console.log(source_default.dim(" 1. --api-key CLI option"));
|
|
70788
|
-
console.log(
|
|
70789
|
-
|
|
71005
|
+
console.log(
|
|
71006
|
+
source_default.dim(` 2. Active config scope: ${activeScope === "project" ? projectPath : userPath}`)
|
|
71007
|
+
);
|
|
71008
|
+
console.log(
|
|
71009
|
+
source_default.dim(` (project takes priority when present at cwd; user is ignored in that case)`)
|
|
71010
|
+
);
|
|
70790
71011
|
console.log(source_default.dim(" 3. .env / shell environment variables (process.env)"));
|
|
70791
71012
|
console.log();
|
|
70792
71013
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.91.
|
|
3
|
+
"version": "0.91.9",
|
|
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.9",
|
|
187
|
+
"@vibeframe/core": "0.91.9"
|
|
188
188
|
},
|
|
189
189
|
"engines": {
|
|
190
190
|
"node": ">=20"
|