@vibeframe/cli 0.88.0 → 0.90.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 +354 -70
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -25690,32 +25690,81 @@ var init_schema = __esm({
|
|
|
25690
25690
|
import { resolve as resolve4 } from "node:path";
|
|
25691
25691
|
import { homedir } from "node:os";
|
|
25692
25692
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, access as access2 } from "node:fs/promises";
|
|
25693
|
-
|
|
25693
|
+
function getProjectConfigDir(cwd = process.cwd()) {
|
|
25694
|
+
return resolve4(cwd, ".vibeframe");
|
|
25695
|
+
}
|
|
25696
|
+
function getProjectConfigPath(cwd = process.cwd()) {
|
|
25697
|
+
return resolve4(getProjectConfigDir(cwd), "config.yaml");
|
|
25698
|
+
}
|
|
25699
|
+
function getConfigPath(scope, cwd) {
|
|
25700
|
+
return scope === "project" ? getProjectConfigPath(cwd) : USER_CONFIG_PATH;
|
|
25701
|
+
}
|
|
25702
|
+
function getConfigDir(scope, cwd) {
|
|
25703
|
+
return scope === "project" ? getProjectConfigDir(cwd) : USER_CONFIG_DIR;
|
|
25704
|
+
}
|
|
25705
|
+
async function fileExists(path2) {
|
|
25694
25706
|
try {
|
|
25695
|
-
await access2(
|
|
25696
|
-
|
|
25697
|
-
|
|
25698
|
-
|
|
25699
|
-
|
|
25700
|
-
|
|
25701
|
-
|
|
25702
|
-
|
|
25703
|
-
|
|
25704
|
-
|
|
25705
|
-
|
|
25706
|
-
|
|
25707
|
+
await access2(path2);
|
|
25708
|
+
return true;
|
|
25709
|
+
} catch {
|
|
25710
|
+
return false;
|
|
25711
|
+
}
|
|
25712
|
+
}
|
|
25713
|
+
async function getActiveScope(cwd) {
|
|
25714
|
+
return await fileExists(getProjectConfigPath(cwd)) ? "project" : "user";
|
|
25715
|
+
}
|
|
25716
|
+
function applyDefaults(parsed) {
|
|
25717
|
+
const defaults = createDefaultConfig();
|
|
25718
|
+
return {
|
|
25719
|
+
...defaults,
|
|
25720
|
+
...parsed,
|
|
25721
|
+
llm: { ...defaults.llm, ...parsed.llm },
|
|
25722
|
+
providers: { ...defaults.providers, ...parsed.providers },
|
|
25723
|
+
defaults: { ...defaults.defaults, ...parsed.defaults },
|
|
25724
|
+
repl: { ...defaults.repl, ...parsed.repl }
|
|
25725
|
+
};
|
|
25726
|
+
}
|
|
25727
|
+
async function readConfigFile(path2) {
|
|
25728
|
+
if (!await fileExists(path2)) return null;
|
|
25729
|
+
try {
|
|
25730
|
+
const content = await readFile2(path2, "utf-8");
|
|
25731
|
+
const parsed = (0, import_yaml.parse)(content);
|
|
25732
|
+
return applyDefaults(parsed);
|
|
25707
25733
|
} catch {
|
|
25708
25734
|
return null;
|
|
25709
25735
|
}
|
|
25710
25736
|
}
|
|
25711
|
-
async function
|
|
25712
|
-
|
|
25713
|
-
|
|
25714
|
-
|
|
25715
|
-
|
|
25716
|
-
|
|
25717
|
-
|
|
25718
|
-
|
|
25737
|
+
async function loadConfig(options = {}) {
|
|
25738
|
+
const { scope, cwd, merge } = options;
|
|
25739
|
+
if (merge) {
|
|
25740
|
+
const user = await readConfigFile(USER_CONFIG_PATH);
|
|
25741
|
+
const project2 = await readConfigFile(getProjectConfigPath(cwd));
|
|
25742
|
+
if (!user && !project2) return null;
|
|
25743
|
+
if (!user) return project2;
|
|
25744
|
+
if (!project2) return user;
|
|
25745
|
+
return {
|
|
25746
|
+
...user,
|
|
25747
|
+
...project2,
|
|
25748
|
+
llm: { ...user.llm, ...project2.llm },
|
|
25749
|
+
providers: { ...user.providers, ...project2.providers },
|
|
25750
|
+
defaults: { ...user.defaults, ...project2.defaults },
|
|
25751
|
+
repl: { ...user.repl, ...project2.repl }
|
|
25752
|
+
};
|
|
25753
|
+
}
|
|
25754
|
+
if (scope) {
|
|
25755
|
+
return readConfigFile(getConfigPath(scope, cwd));
|
|
25756
|
+
}
|
|
25757
|
+
const project = await readConfigFile(getProjectConfigPath(cwd));
|
|
25758
|
+
if (project) return project;
|
|
25759
|
+
return readConfigFile(USER_CONFIG_PATH);
|
|
25760
|
+
}
|
|
25761
|
+
async function saveConfig(config2, options = {}) {
|
|
25762
|
+
const scope = options.scope ?? "user";
|
|
25763
|
+
const dir = getConfigDir(scope, options.cwd);
|
|
25764
|
+
const path2 = getConfigPath(scope, options.cwd);
|
|
25765
|
+
await mkdir2(dir, { recursive: true });
|
|
25766
|
+
const content = (0, import_yaml.stringify)(config2, { indent: 2, lineWidth: 0 });
|
|
25767
|
+
await writeFile2(path2, content, "utf-8");
|
|
25719
25768
|
}
|
|
25720
25769
|
async function isConfigured() {
|
|
25721
25770
|
const config2 = await loadConfig();
|
|
@@ -25737,20 +25786,19 @@ async function getApiKeyFromConfig(providerKey) {
|
|
|
25737
25786
|
return config2.providers[providerKey];
|
|
25738
25787
|
}
|
|
25739
25788
|
const envVar = PROVIDER_ENV_VARS[providerKey];
|
|
25740
|
-
if (envVar)
|
|
25741
|
-
return process.env[envVar];
|
|
25742
|
-
}
|
|
25789
|
+
if (envVar) return process.env[envVar];
|
|
25743
25790
|
return void 0;
|
|
25744
25791
|
}
|
|
25745
|
-
var import_yaml,
|
|
25792
|
+
var import_yaml, USER_CONFIG_DIR, USER_CONFIG_PATH, CONFIG_PATH;
|
|
25746
25793
|
var init_config = __esm({
|
|
25747
25794
|
"src/config/index.ts"() {
|
|
25748
25795
|
"use strict";
|
|
25749
25796
|
import_yaml = __toESM(require_dist(), 1);
|
|
25750
25797
|
init_schema();
|
|
25751
25798
|
init_schema();
|
|
25752
|
-
|
|
25753
|
-
|
|
25799
|
+
USER_CONFIG_DIR = resolve4(homedir(), ".vibeframe");
|
|
25800
|
+
USER_CONFIG_PATH = resolve4(USER_CONFIG_DIR, "config.yaml");
|
|
25801
|
+
CONFIG_PATH = USER_CONFIG_PATH;
|
|
25754
25802
|
}
|
|
25755
25803
|
});
|
|
25756
25804
|
|
|
@@ -26277,9 +26325,8 @@ vibe scene lint --json # structured output for agent loops
|
|
|
26277
26325
|
`;
|
|
26278
26326
|
}
|
|
26279
26327
|
function buildSceneGitignore() {
|
|
26280
|
-
return `# VibeFrame caches
|
|
26281
|
-
.vibeframe/
|
|
26282
|
-
.vibeframe/checkpoints/
|
|
26328
|
+
return `# VibeFrame \u2014 caches, checkpoints, and project-scope config.yaml (may contain API keys)
|
|
26329
|
+
.vibeframe/
|
|
26283
26330
|
|
|
26284
26331
|
# Render outputs
|
|
26285
26332
|
renders/*.mp4
|
|
@@ -62845,7 +62892,7 @@ init_source();
|
|
|
62845
62892
|
// package.json
|
|
62846
62893
|
var package_default = {
|
|
62847
62894
|
name: "@vibeframe/cli",
|
|
62848
|
-
version: "0.
|
|
62895
|
+
version: "0.90.0",
|
|
62849
62896
|
description: "VibeFrame CLI - natural language video editing from the terminal",
|
|
62850
62897
|
private: false,
|
|
62851
62898
|
license: "MIT",
|
|
@@ -69840,13 +69887,34 @@ var VALID_LLM_PROVIDERS = [
|
|
|
69840
69887
|
"xai",
|
|
69841
69888
|
"openrouter"
|
|
69842
69889
|
];
|
|
69843
|
-
var
|
|
69890
|
+
var VALID_SCOPES = ["user", "project"];
|
|
69891
|
+
function parseScope(raw) {
|
|
69892
|
+
const v = String(raw ?? "user");
|
|
69893
|
+
if (!VALID_SCOPES.includes(v)) {
|
|
69894
|
+
exitWithError(generalError(
|
|
69895
|
+
`Invalid --scope: ${v}`,
|
|
69896
|
+
`Must be one of: ${VALID_SCOPES.join(", ")}`
|
|
69897
|
+
));
|
|
69898
|
+
}
|
|
69899
|
+
return v;
|
|
69900
|
+
}
|
|
69901
|
+
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("-v, --verbose", "With --show: include unset providers + Resolution order + Defaults block").option("--claude-code", "Show Claude Code integration guide").option("-y, --yes", "Non-interactive: write config without prompting (CI / devcontainer)").option("--provider <id>", "Set the Agent LLM provider (claude | openai | gemini | xai | openrouter | ollama)").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(
|
|
69902
|
+
"--scope <scope>",
|
|
69903
|
+
"Where to save: 'user' (~/.vibeframe/config.yaml, shared) or 'project' (./.vibeframe/config.yaml, gitignored, this project only)",
|
|
69904
|
+
"user"
|
|
69905
|
+
).addHelpText(
|
|
69844
69906
|
"after",
|
|
69845
69907
|
`
|
|
69846
69908
|
Non-interactive examples (no TTY required):
|
|
69847
69909
|
vibe setup --yes --provider claude --import-env Bootstrap CI / devcontainer
|
|
69848
69910
|
vibe setup --yes --import-env --test Persist .env keys + verify each one
|
|
69849
69911
|
vibe setup --yes --provider openai Just switch the agent provider
|
|
69912
|
+
vibe setup --scope project --yes --import-env Project-only setup (./.vibeframe/config.yaml)
|
|
69913
|
+
|
|
69914
|
+
Scopes:
|
|
69915
|
+
user (default) ~/.vibeframe/config.yaml \u2014 shared across every project
|
|
69916
|
+
project ./.vibeframe/config.yaml \u2014 gitignored, isolates keys/defaults to this directory
|
|
69917
|
+
When a project config exists at the cwd, it is used and the user file is ignored.
|
|
69850
69918
|
|
|
69851
69919
|
Exit codes (non-interactive):
|
|
69852
69920
|
0 success 7 --test verification failed (one or more keys returned non-2xx)
|
|
@@ -69861,11 +69929,12 @@ Exit codes (non-interactive):
|
|
|
69861
69929
|
await showConfig({ verbose: Boolean(options.verbose) });
|
|
69862
69930
|
return;
|
|
69863
69931
|
}
|
|
69932
|
+
const scope = parseScope(options.scope);
|
|
69864
69933
|
if (options.reset) {
|
|
69865
69934
|
const config2 = createDefaultConfig();
|
|
69866
|
-
await saveConfig(config2);
|
|
69935
|
+
await saveConfig(config2, { scope });
|
|
69867
69936
|
console.log(source_default.green("\u2713 Configuration reset to defaults"));
|
|
69868
|
-
console.log(source_default.dim(` Saved to: ${
|
|
69937
|
+
console.log(source_default.dim(` Saved to: ${getConfigPath(scope)}`));
|
|
69869
69938
|
return;
|
|
69870
69939
|
}
|
|
69871
69940
|
const wantsNonInteractive = Boolean(options.yes) || !hasTTY() && (options.provider || options.importEnv);
|
|
@@ -69873,7 +69942,8 @@ Exit codes (non-interactive):
|
|
|
69873
69942
|
await runNonInteractiveSetup({
|
|
69874
69943
|
provider: options.provider,
|
|
69875
69944
|
importEnv: Boolean(options.importEnv),
|
|
69876
|
-
test: Boolean(options.test)
|
|
69945
|
+
test: Boolean(options.test),
|
|
69946
|
+
scope
|
|
69877
69947
|
});
|
|
69878
69948
|
return;
|
|
69879
69949
|
}
|
|
@@ -69884,7 +69954,7 @@ Exit codes (non-interactive):
|
|
|
69884
69954
|
));
|
|
69885
69955
|
}
|
|
69886
69956
|
try {
|
|
69887
|
-
await runSetupWizard(options.full);
|
|
69957
|
+
await runSetupWizard(options.full, scope);
|
|
69888
69958
|
closeTTYStream();
|
|
69889
69959
|
process.exit(0);
|
|
69890
69960
|
} catch (err) {
|
|
@@ -69930,7 +70000,8 @@ var AI_FEATURES = [
|
|
|
69930
70000
|
}
|
|
69931
70001
|
];
|
|
69932
70002
|
async function runNonInteractiveSetup(opts) {
|
|
69933
|
-
|
|
70003
|
+
const scope = opts.scope ?? "user";
|
|
70004
|
+
let config2 = await loadConfig({ scope });
|
|
69934
70005
|
if (!config2) {
|
|
69935
70006
|
config2 = createDefaultConfig();
|
|
69936
70007
|
}
|
|
@@ -69967,9 +70038,9 @@ async function runNonInteractiveSetup(opts) {
|
|
|
69967
70038
|
changes.push(`imported ${importedCount} key${importedCount === 1 ? "" : "s"} from env`);
|
|
69968
70039
|
}
|
|
69969
70040
|
}
|
|
69970
|
-
await saveConfig(config2);
|
|
69971
|
-
console.log(source_default.green(
|
|
69972
|
-
console.log(source_default.dim(` Config: ${
|
|
70041
|
+
await saveConfig(config2, { scope });
|
|
70042
|
+
console.log(source_default.green(`\u2713 Setup complete (non-interactive, ${scope} scope)`));
|
|
70043
|
+
console.log(source_default.dim(` Config: ${getConfigPath(scope)}`));
|
|
69973
70044
|
if (changes.length > 0) {
|
|
69974
70045
|
for (const c of changes) {
|
|
69975
70046
|
console.log(source_default.dim(` ${c}`));
|
|
@@ -70012,20 +70083,21 @@ async function runNonInteractiveSetup(opts) {
|
|
|
70012
70083
|
}
|
|
70013
70084
|
}
|
|
70014
70085
|
}
|
|
70015
|
-
async function runSetupWizard(fullSetup = false) {
|
|
70086
|
+
async function runSetupWizard(fullSetup = false, scope = "user") {
|
|
70016
70087
|
console.log();
|
|
70017
|
-
|
|
70088
|
+
const scopeLabel = scope === "project" ? source_default.dim(` \u2014 project scope (${getConfigPath("project")})`) : source_default.dim(" \u2014 user scope");
|
|
70089
|
+
console.log(source_default.bold.magenta("VibeFrame Setup") + scopeLabel);
|
|
70018
70090
|
console.log(source_default.dim("\u2500".repeat(40)));
|
|
70019
70091
|
console.log();
|
|
70020
70092
|
const hosts = detectedAgentHosts();
|
|
70021
70093
|
console.log(source_default.dim(`Agent hosts: ${summariseAgentHosts(hosts)}`));
|
|
70022
70094
|
console.log();
|
|
70023
|
-
let config2 = await loadConfig();
|
|
70095
|
+
let config2 = await loadConfig({ scope });
|
|
70024
70096
|
if (!config2) {
|
|
70025
70097
|
config2 = createDefaultConfig();
|
|
70026
70098
|
}
|
|
70027
70099
|
if (fullSetup) {
|
|
70028
|
-
await runCustomSetup(config2);
|
|
70100
|
+
await runCustomSetup(config2, scope);
|
|
70029
70101
|
return;
|
|
70030
70102
|
}
|
|
70031
70103
|
console.log(source_default.dim("1. Goal"));
|
|
@@ -70040,12 +70112,12 @@ async function runSetupWizard(fullSetup = false) {
|
|
|
70040
70112
|
const topIndex = await promptSelect(source_default.cyan(" Select [1-4]: "), topLabels, 0);
|
|
70041
70113
|
console.log();
|
|
70042
70114
|
if (topIndex === 0) {
|
|
70043
|
-
await saveConfig(config2);
|
|
70044
|
-
await showComplete(config2, "vibe edit silence-cut video.mp4 -o clean.mp4");
|
|
70115
|
+
await saveConfig(config2, { scope });
|
|
70116
|
+
await showComplete(config2, "vibe edit silence-cut video.mp4 -o clean.mp4", [], scope);
|
|
70045
70117
|
return;
|
|
70046
70118
|
}
|
|
70047
70119
|
if (topIndex === 3) {
|
|
70048
|
-
await runCustomSetup(config2);
|
|
70120
|
+
await runCustomSetup(config2, scope);
|
|
70049
70121
|
return;
|
|
70050
70122
|
}
|
|
70051
70123
|
if (topIndex === 2) {
|
|
@@ -70061,8 +70133,8 @@ async function runSetupWizard(fullSetup = false) {
|
|
|
70061
70133
|
console.log(source_default.dim(" Saved locally, never shared. Press Enter to skip."));
|
|
70062
70134
|
console.log();
|
|
70063
70135
|
await collectKeys(config2, pipelineKeys);
|
|
70064
|
-
await saveConfig(config2);
|
|
70065
|
-
await showComplete(config2, "vibe build my-story/ # see CONTRIBUTING.md for STORYBOARD.md format");
|
|
70136
|
+
await saveConfig(config2, { scope });
|
|
70137
|
+
await showComplete(config2, "vibe build my-story/ # see CONTRIBUTING.md for STORYBOARD.md format", [], scope);
|
|
70066
70138
|
return;
|
|
70067
70139
|
}
|
|
70068
70140
|
console.log(source_default.dim("2. Features"));
|
|
@@ -70083,8 +70155,8 @@ async function runSetupWizard(fullSetup = false) {
|
|
|
70083
70155
|
if (selectedFeatures.length === 0) {
|
|
70084
70156
|
console.log(source_default.dim(" No features selected. You can re-run setup anytime."));
|
|
70085
70157
|
console.log();
|
|
70086
|
-
await saveConfig(config2);
|
|
70087
|
-
await showComplete(config2, "vibe --help", []);
|
|
70158
|
+
await saveConfig(config2, { scope });
|
|
70159
|
+
await showComplete(config2, "vibe --help", [], scope);
|
|
70088
70160
|
return;
|
|
70089
70161
|
}
|
|
70090
70162
|
console.log(source_default.dim("3. API keys"));
|
|
@@ -70136,8 +70208,8 @@ async function runSetupWizard(fullSetup = false) {
|
|
|
70136
70208
|
}
|
|
70137
70209
|
console.log();
|
|
70138
70210
|
}
|
|
70139
|
-
await saveConfig(config2);
|
|
70140
|
-
await showComplete(config2, selectedFeatures[0].tryCommand, selectedFeatures);
|
|
70211
|
+
await saveConfig(config2, { scope });
|
|
70212
|
+
await showComplete(config2, selectedFeatures[0].tryCommand, selectedFeatures, scope);
|
|
70141
70213
|
}
|
|
70142
70214
|
async function collectKeys(config2, keys) {
|
|
70143
70215
|
loadEnv();
|
|
@@ -70173,7 +70245,7 @@ async function collectKeys(config2, keys) {
|
|
|
70173
70245
|
}
|
|
70174
70246
|
console.log();
|
|
70175
70247
|
}
|
|
70176
|
-
async function runCustomSetup(config2) {
|
|
70248
|
+
async function runCustomSetup(config2, scope = "user") {
|
|
70177
70249
|
console.log(source_default.bold("1. Agent LLM Provider") + source_default.dim(" (for vibe agent)"));
|
|
70178
70250
|
console.log(source_default.dim(" Only needed if you use the interactive Agent mode."));
|
|
70179
70251
|
console.log();
|
|
@@ -70243,14 +70315,15 @@ async function runCustomSetup(config2) {
|
|
|
70243
70315
|
}
|
|
70244
70316
|
}
|
|
70245
70317
|
console.log();
|
|
70246
|
-
await saveConfig(config2);
|
|
70247
|
-
await showComplete(config2, "vibe doctor");
|
|
70318
|
+
await saveConfig(config2, { scope });
|
|
70319
|
+
await showComplete(config2, "vibe doctor", [], scope);
|
|
70248
70320
|
}
|
|
70249
|
-
async function showComplete(config2, defaultTryCommand, features = []) {
|
|
70321
|
+
async function showComplete(config2, defaultTryCommand, features = [], scope = "user") {
|
|
70250
70322
|
console.log(source_default.dim("\u2500".repeat(40)));
|
|
70251
70323
|
console.log(source_default.green.bold("\u2713 Setup complete!"));
|
|
70252
70324
|
console.log();
|
|
70253
|
-
|
|
70325
|
+
const scopeNote = scope === "project" ? source_default.dim(" (project scope)") : source_default.dim(" (user scope)");
|
|
70326
|
+
console.log(source_default.dim(` Config: ${getConfigPath(scope)}${scopeNote}`));
|
|
70254
70327
|
console.log();
|
|
70255
70328
|
const primaryTry = features.length > 1 ? features[0].tryCommand : defaultTryCommand;
|
|
70256
70329
|
if (features.length > 1) {
|
|
@@ -70280,6 +70353,12 @@ async function showComplete(config2, defaultTryCommand, features = []) {
|
|
|
70280
70353
|
console.log(source_default.dim(" vibe doctor Check system health + available commands"));
|
|
70281
70354
|
console.log(source_default.dim(" vibe schema --list Discover every command"));
|
|
70282
70355
|
console.log(source_default.dim(" vibe setup Re-run user-scope setup anytime"));
|
|
70356
|
+
const shellHint = pickCompletionHint(process.env.SHELL);
|
|
70357
|
+
if (shellHint) {
|
|
70358
|
+
console.log();
|
|
70359
|
+
console.log(source_default.bold(" Tab completion:"));
|
|
70360
|
+
console.log(source_default.dim(` ${shellHint}`));
|
|
70361
|
+
}
|
|
70283
70362
|
const hosts = detectedAgentHosts();
|
|
70284
70363
|
const primary = hosts[0];
|
|
70285
70364
|
if (primary) {
|
|
@@ -70334,13 +70413,22 @@ async function showConfig(opts = { verbose: false }) {
|
|
|
70334
70413
|
hasCwdEnv = true;
|
|
70335
70414
|
} catch {
|
|
70336
70415
|
}
|
|
70416
|
+
const activeScope = await getActiveScope();
|
|
70417
|
+
const userPath = USER_CONFIG_PATH;
|
|
70418
|
+
const projectPath = getConfigPath("project");
|
|
70419
|
+
const userExists = await loadConfig({ scope: "user" }) !== null;
|
|
70420
|
+
const projectExists = await loadConfig({ scope: "project" }) !== null;
|
|
70337
70421
|
console.log();
|
|
70338
70422
|
console.log(source_default.bold.magenta("VibeFrame Configuration"));
|
|
70339
70423
|
console.log(source_default.dim("\u2500".repeat(40)));
|
|
70340
70424
|
console.log();
|
|
70341
|
-
|
|
70425
|
+
const userMark = activeScope === "user" && userExists ? source_default.cyan("\u2190 active") : userExists ? source_default.dim("(present)") : source_default.dim("(missing)");
|
|
70426
|
+
const projectMark = activeScope === "project" ? source_default.cyan("\u2190 active") : projectExists ? source_default.dim("(present)") : source_default.dim("(missing)");
|
|
70427
|
+
console.log(source_default.dim(`Scopes:`));
|
|
70428
|
+
console.log(source_default.dim(` user ${userPath} ${userMark}`));
|
|
70429
|
+
console.log(source_default.dim(` project ${projectPath} ${projectMark}`));
|
|
70342
70430
|
if (hasCwdEnv) {
|
|
70343
|
-
console.log(source_default.dim(`
|
|
70431
|
+
console.log(source_default.dim(` .env ${cwdEnvPath} ${source_default.dim("(env vars override config)")}`));
|
|
70344
70432
|
}
|
|
70345
70433
|
console.log();
|
|
70346
70434
|
const config2 = await loadConfig();
|
|
@@ -70408,12 +70496,26 @@ async function showConfig(opts = { verbose: false }) {
|
|
|
70408
70496
|
}
|
|
70409
70497
|
console.log(source_default.bold("Resolution order:"));
|
|
70410
70498
|
console.log(source_default.dim(" 1. --api-key CLI option"));
|
|
70411
|
-
console.log(source_default.dim(` 2. ${
|
|
70412
|
-
console.log(source_default.dim(
|
|
70413
|
-
console.log(source_default.dim("
|
|
70499
|
+
console.log(source_default.dim(` 2. Active config scope: ${activeScope === "project" ? projectPath : userPath}`));
|
|
70500
|
+
console.log(source_default.dim(` (project takes priority when present at cwd; user is ignored in that case)`));
|
|
70501
|
+
console.log(source_default.dim(" 3. .env / shell environment variables (process.env)"));
|
|
70414
70502
|
console.log();
|
|
70415
70503
|
}
|
|
70416
70504
|
}
|
|
70505
|
+
function pickCompletionHint(shellPath) {
|
|
70506
|
+
if (!shellPath) return void 0;
|
|
70507
|
+
const shell = shellPath.split("/").pop() ?? "";
|
|
70508
|
+
if (shell.includes("zsh")) {
|
|
70509
|
+
return `echo 'eval "$(vibe completion zsh)"' >> ~/.zshrc`;
|
|
70510
|
+
}
|
|
70511
|
+
if (shell.includes("bash")) {
|
|
70512
|
+
return `echo 'eval "$(vibe completion bash)"' >> ~/.bashrc`;
|
|
70513
|
+
}
|
|
70514
|
+
if (shell.includes("fish")) {
|
|
70515
|
+
return `vibe completion fish > ~/.config/fish/completions/vibe.fish`;
|
|
70516
|
+
}
|
|
70517
|
+
return void 0;
|
|
70518
|
+
}
|
|
70417
70519
|
|
|
70418
70520
|
// src/commands/init.ts
|
|
70419
70521
|
init_esm();
|
|
@@ -71531,6 +71633,9 @@ async function runDiagnostics() {
|
|
|
71531
71633
|
exists: existsSync36(resolve50(cwd, rel))
|
|
71532
71634
|
}));
|
|
71533
71635
|
const projectInitialized = projectFiles.some((f) => f.exists);
|
|
71636
|
+
const projectConfigPath = getProjectConfigPath(cwd);
|
|
71637
|
+
const projectConfigExists = existsSync36(projectConfigPath);
|
|
71638
|
+
const activeScope = await getActiveScope(cwd);
|
|
71534
71639
|
const hosts = detectAgentHosts();
|
|
71535
71640
|
const detectedNames = hosts.filter((h) => h.detected).map((h) => h.label);
|
|
71536
71641
|
const recommendedMode = resolveSceneBuildMode({});
|
|
@@ -71553,8 +71658,15 @@ async function runDiagnostics() {
|
|
|
71553
71658
|
...Object.keys(optionalTools).length > 0 ? { optionalTools } : {}
|
|
71554
71659
|
},
|
|
71555
71660
|
scope: {
|
|
71661
|
+
activeScope,
|
|
71556
71662
|
user: { configured: configExists, configPath: CONFIG_PATH },
|
|
71557
|
-
project: {
|
|
71663
|
+
project: {
|
|
71664
|
+
cwd,
|
|
71665
|
+
initialized: projectInitialized,
|
|
71666
|
+
files: projectFiles,
|
|
71667
|
+
configPath: projectConfigPath,
|
|
71668
|
+
configFileExists: projectConfigExists
|
|
71669
|
+
},
|
|
71558
71670
|
agentHosts: { detected: detectedNames, summary: summariseAgentHosts(hosts) },
|
|
71559
71671
|
sceneComposer: {
|
|
71560
71672
|
recommendedMode,
|
|
@@ -71627,16 +71739,30 @@ function printReport(results, opts = { verbose: false }) {
|
|
|
71627
71739
|
}
|
|
71628
71740
|
console.log();
|
|
71629
71741
|
console.log(source_default.bold(" Scope"));
|
|
71742
|
+
const userActive = results.scope.activeScope === "user" && results.scope.user.configured;
|
|
71743
|
+
const projectActive = results.scope.activeScope === "project";
|
|
71744
|
+
const activeMark = source_default.cyan(" \u2190 active");
|
|
71630
71745
|
if (results.scope.user.configured) {
|
|
71631
|
-
console.log(
|
|
71746
|
+
console.log(
|
|
71747
|
+
` Cfg(user) ${source_default.green("OK")} ${source_default.dim(results.scope.user.configPath)}${userActive ? activeMark : ""}`
|
|
71748
|
+
);
|
|
71749
|
+
} else {
|
|
71750
|
+
console.log(` Cfg(user) ${source_default.yellow("NOT SET")} ${source_default.dim("Run: vibe setup")}`);
|
|
71751
|
+
}
|
|
71752
|
+
if (results.scope.project.configFileExists) {
|
|
71753
|
+
console.log(
|
|
71754
|
+
` Cfg(proj) ${source_default.green("OK")} ${source_default.dim(results.scope.project.configPath)}${projectActive ? activeMark : ""}`
|
|
71755
|
+
);
|
|
71632
71756
|
} else {
|
|
71633
|
-
console.log(
|
|
71757
|
+
console.log(
|
|
71758
|
+
` Cfg(proj) ${source_default.dim("none")} ${source_default.dim(`Run: vibe setup --scope project (cwd: ${results.scope.project.cwd})`)}`
|
|
71759
|
+
);
|
|
71634
71760
|
}
|
|
71635
71761
|
if (results.scope.project.initialized) {
|
|
71636
71762
|
const present = results.scope.project.files.filter((f) => f.exists).map((f) => f.path);
|
|
71637
|
-
console.log(`
|
|
71763
|
+
console.log(` Init ${source_default.green("OK")} ${source_default.dim(present.join(", "))}`);
|
|
71638
71764
|
} else {
|
|
71639
|
-
console.log(`
|
|
71765
|
+
console.log(` Init ${source_default.yellow("NOT INIT")} ${source_default.dim(`Run: vibe init (cwd: ${results.scope.project.cwd})`)}`);
|
|
71640
71766
|
}
|
|
71641
71767
|
console.log(` Agents ${source_default.dim(results.scope.agentHosts.summary)}`);
|
|
71642
71768
|
if (verbose) {
|
|
@@ -71792,8 +71918,9 @@ async function runLiveKeyTests(results) {
|
|
|
71792
71918
|
console.log();
|
|
71793
71919
|
}
|
|
71794
71920
|
function pickNextStep(results, hasMissingProviders) {
|
|
71795
|
-
|
|
71796
|
-
|
|
71921
|
+
const anyConfigured = results.scope.user.configured || results.scope.project.configFileExists;
|
|
71922
|
+
if (!anyConfigured) {
|
|
71923
|
+
return "Next: run 'vibe setup' (or 'vibe setup --scope project' to keep config inside the project) to configure API keys + LLM provider.";
|
|
71797
71924
|
}
|
|
71798
71925
|
if (!results.scope.project.initialized) {
|
|
71799
71926
|
return "Next: run 'vibe init' in your project directory to scaffold AGENTS.md / CLAUDE.md / .env.example.";
|
|
@@ -73146,6 +73273,162 @@ var walkthroughCommand = new Command("walkthrough").description("Step-by-step au
|
|
|
73146
73273
|
console.log();
|
|
73147
73274
|
});
|
|
73148
73275
|
|
|
73276
|
+
// src/commands/completion.ts
|
|
73277
|
+
init_esm();
|
|
73278
|
+
init_output();
|
|
73279
|
+
init_cost_tier();
|
|
73280
|
+
var completionCommand = new Command("completion").description("Print a shell completion script for `vibe`").argument("<shell>", "Target shell: zsh | bash | fish").addHelpText(
|
|
73281
|
+
"after",
|
|
73282
|
+
`
|
|
73283
|
+
Examples:
|
|
73284
|
+
$ vibe completion zsh >> ~/.zsh/completions/_vibe # then ensure that dir is in fpath
|
|
73285
|
+
$ echo 'eval "$(vibe completion bash)"' >> ~/.bashrc
|
|
73286
|
+
$ vibe completion fish > ~/.config/fish/completions/vibe.fish
|
|
73287
|
+
|
|
73288
|
+
The output is generated from the live command tree, so it stays in
|
|
73289
|
+
sync with the CLI surface. Re-run after upgrades.
|
|
73290
|
+
`
|
|
73291
|
+
).action((shell) => {
|
|
73292
|
+
const program3 = completionCommand.parent;
|
|
73293
|
+
if (!program3) {
|
|
73294
|
+
exitWithError(usageError("completion: program tree not available"));
|
|
73295
|
+
}
|
|
73296
|
+
const valid = /* @__PURE__ */ new Set(["zsh", "bash", "fish"]);
|
|
73297
|
+
if (!valid.has(shell)) {
|
|
73298
|
+
exitWithError(usageError(`Unknown shell: ${shell}`, "Supported: zsh, bash, fish"));
|
|
73299
|
+
}
|
|
73300
|
+
if (shell === "zsh") console.log(generateZsh(program3));
|
|
73301
|
+
else if (shell === "bash") console.log(generateBash(program3));
|
|
73302
|
+
else console.log(generateFish(program3));
|
|
73303
|
+
});
|
|
73304
|
+
function collectCommandTree(program3) {
|
|
73305
|
+
const skipTopLevel = /* @__PURE__ */ new Set(["help"]);
|
|
73306
|
+
const nodes = [];
|
|
73307
|
+
for (const top of program3.commands) {
|
|
73308
|
+
const name = top.name();
|
|
73309
|
+
if (skipTopLevel.has(name)) continue;
|
|
73310
|
+
const desc = top.description() || "";
|
|
73311
|
+
if (desc.toLowerCase().includes("deprecated")) continue;
|
|
73312
|
+
const subs = top.commands.filter((s) => !(s.description() || "").toLowerCase().includes("deprecated")).map((s) => ({
|
|
73313
|
+
name: s.name(),
|
|
73314
|
+
description: s.description() || "",
|
|
73315
|
+
cost: getCostTier(s)
|
|
73316
|
+
}));
|
|
73317
|
+
nodes.push({ name, description: desc, cost: getCostTier(top), subcommands: subs });
|
|
73318
|
+
}
|
|
73319
|
+
return nodes;
|
|
73320
|
+
}
|
|
73321
|
+
function tierBadge(cost) {
|
|
73322
|
+
if (!cost) return "";
|
|
73323
|
+
return `[${cost.toUpperCase()}] `;
|
|
73324
|
+
}
|
|
73325
|
+
function shellEscape(s) {
|
|
73326
|
+
return s.replace(/\n/g, " ").replace(/\s+/g, " ").trim().replace(/'/g, `'"'"'`);
|
|
73327
|
+
}
|
|
73328
|
+
function generateZsh(program3) {
|
|
73329
|
+
const nodes = collectCommandTree(program3);
|
|
73330
|
+
const topLines = nodes.map((n) => `'${n.name}:${shellEscape(tierBadge(n.cost) + n.description)}'`).join(" \\\n ");
|
|
73331
|
+
const subBlocks = nodes.filter((n) => n.subcommands.length > 0).map((n) => {
|
|
73332
|
+
const subs = n.subcommands.map((s) => `'${s.name}:${shellEscape(tierBadge(s.cost) + s.description)}'`).join(" \\\n ");
|
|
73333
|
+
return ` ${n.name})
|
|
73334
|
+
local -a subcommands
|
|
73335
|
+
subcommands=(
|
|
73336
|
+
${subs}
|
|
73337
|
+
)
|
|
73338
|
+
_describe 'subcommand' subcommands
|
|
73339
|
+
;;`;
|
|
73340
|
+
}).join("\n");
|
|
73341
|
+
return `#compdef vibe
|
|
73342
|
+
# vibe shell completion for zsh \u2014 generated by \`vibe completion zsh\`.
|
|
73343
|
+
# Re-run after upgrades; the script reflects the live command tree.
|
|
73344
|
+
|
|
73345
|
+
_vibe() {
|
|
73346
|
+
local -a commands
|
|
73347
|
+
commands=(
|
|
73348
|
+
${topLines}
|
|
73349
|
+
)
|
|
73350
|
+
|
|
73351
|
+
_arguments -C \\
|
|
73352
|
+
'1: :->cmd' \\
|
|
73353
|
+
'*:: :->args'
|
|
73354
|
+
|
|
73355
|
+
case $state in
|
|
73356
|
+
cmd)
|
|
73357
|
+
_describe 'command' commands
|
|
73358
|
+
;;
|
|
73359
|
+
args)
|
|
73360
|
+
case $words[1] in
|
|
73361
|
+
${subBlocks}
|
|
73362
|
+
esac
|
|
73363
|
+
;;
|
|
73364
|
+
esac
|
|
73365
|
+
}
|
|
73366
|
+
|
|
73367
|
+
_vibe "$@"
|
|
73368
|
+
`;
|
|
73369
|
+
}
|
|
73370
|
+
function generateBash(program3) {
|
|
73371
|
+
const nodes = collectCommandTree(program3);
|
|
73372
|
+
const topNames = nodes.map((n) => n.name).join(" ");
|
|
73373
|
+
const subCases = nodes.filter((n) => n.subcommands.length > 0).map((n) => {
|
|
73374
|
+
const names = n.subcommands.map((s) => s.name).join(" ");
|
|
73375
|
+
return ` ${n.name})
|
|
73376
|
+
COMPREPLY=( $(compgen -W "${names}" -- "$cur") )
|
|
73377
|
+
;;`;
|
|
73378
|
+
}).join("\n");
|
|
73379
|
+
return `# vibe shell completion for bash \u2014 generated by \`vibe completion bash\`.
|
|
73380
|
+
# Re-run after upgrades; the script reflects the live command tree.
|
|
73381
|
+
# Bash completions are word-only \u2014 no description hints \u2014 so consider
|
|
73382
|
+
# zsh or fish for richer feedback.
|
|
73383
|
+
|
|
73384
|
+
_vibe_complete() {
|
|
73385
|
+
local cur prev cmd
|
|
73386
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
73387
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
73388
|
+
cmd="\${COMP_WORDS[1]}"
|
|
73389
|
+
|
|
73390
|
+
if [[ $COMP_CWORD == 1 ]]; then
|
|
73391
|
+
COMPREPLY=( $(compgen -W "${topNames}" -- "$cur") )
|
|
73392
|
+
return 0
|
|
73393
|
+
fi
|
|
73394
|
+
|
|
73395
|
+
case "$cmd" in
|
|
73396
|
+
${subCases}
|
|
73397
|
+
*)
|
|
73398
|
+
COMPREPLY=()
|
|
73399
|
+
;;
|
|
73400
|
+
esac
|
|
73401
|
+
}
|
|
73402
|
+
|
|
73403
|
+
complete -F _vibe_complete vibe
|
|
73404
|
+
`;
|
|
73405
|
+
}
|
|
73406
|
+
function generateFish(program3) {
|
|
73407
|
+
const nodes = collectCommandTree(program3);
|
|
73408
|
+
const lines = [
|
|
73409
|
+
"# vibe shell completion for fish \u2014 generated by `vibe completion fish`.",
|
|
73410
|
+
"# Re-run after upgrades; the script reflects the live command tree.",
|
|
73411
|
+
"",
|
|
73412
|
+
"complete -c vibe -f",
|
|
73413
|
+
""
|
|
73414
|
+
];
|
|
73415
|
+
for (const n of nodes) {
|
|
73416
|
+
const desc = shellEscape(tierBadge(n.cost) + n.description);
|
|
73417
|
+
lines.push(`complete -c vibe -n '__fish_use_subcommand' -a '${n.name}' -d '${desc}'`);
|
|
73418
|
+
}
|
|
73419
|
+
lines.push("");
|
|
73420
|
+
for (const n of nodes) {
|
|
73421
|
+
if (n.subcommands.length === 0) continue;
|
|
73422
|
+
for (const s of n.subcommands) {
|
|
73423
|
+
const desc = shellEscape(tierBadge(s.cost) + s.description);
|
|
73424
|
+
lines.push(
|
|
73425
|
+
`complete -c vibe -n '__fish_seen_subcommand_from ${n.name}' -a '${s.name}' -d '${desc}'`
|
|
73426
|
+
);
|
|
73427
|
+
}
|
|
73428
|
+
}
|
|
73429
|
+
return lines.join("\n") + "\n";
|
|
73430
|
+
}
|
|
73431
|
+
|
|
73149
73432
|
// src/index.ts
|
|
73150
73433
|
init_api_key();
|
|
73151
73434
|
|
|
@@ -73372,6 +73655,7 @@ program2.addCommand(batchCommand);
|
|
|
73372
73655
|
program2.addCommand(schemaCommand);
|
|
73373
73656
|
program2.addCommand(contextCommand);
|
|
73374
73657
|
program2.addCommand(walkthroughCommand);
|
|
73658
|
+
program2.addCommand(completionCommand);
|
|
73375
73659
|
program2.addCommand(mediaCommand, { hidden: true });
|
|
73376
73660
|
function propagateErrorHandling(cmd) {
|
|
73377
73661
|
for (const sub of cmd.commands) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.90.0",
|
|
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.
|
|
187
|
-
"@vibeframe/core": "0.
|
|
186
|
+
"@vibeframe/ai-providers": "0.90.0",
|
|
187
|
+
"@vibeframe/core": "0.90.0"
|
|
188
188
|
},
|
|
189
189
|
"engines": {
|
|
190
190
|
"node": ">=20"
|