vesper-wizard 2.3.5 → 2.3.7

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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/package.json +1 -1
  3. package/wizard.js +58 -9
package/README.md CHANGED
@@ -14,6 +14,7 @@ That's it. The wizard handles everything:
14
14
  2. Initializes a local credentials vault in unified-key mode (no external API keys required)
15
15
  3. Installs `@vespermcp/mcp-server` and auto-configures MCP for all detected agents (Claude, Cursor, VS Code, Codex, Gemini CLI)
16
16
  4. Verifies the installation
17
+ 5. Prints a sign-in URL for manual browser login (no forced auto-open)
17
18
 
18
19
  ## What you get
19
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vesper-wizard",
3
- "version": "2.3.5",
3
+ "version": "2.3.7",
4
4
  "description": "Zero-friction setup wizard for Vesper — local MCP server, unified dataset API, and agent auto-config in 60 seconds",
5
5
  "bin": {
6
6
  "vesper-wizard": "wizard.js"
package/wizard.js CHANGED
@@ -18,6 +18,7 @@ const readline = require('readline');
18
18
  const HOME = os.homedir();
19
19
  const VESPER_DIR = path.join(HOME, '.vesper');
20
20
  const CONFIG_TOML = path.join(VESPER_DIR, 'config.toml');
21
+ const CONFIG_JSON = path.join(VESPER_DIR, 'config.json');
21
22
  const DATA_DIR = path.join(VESPER_DIR, 'data');
22
23
  const IS_WIN = process.platform === 'win32';
23
24
  const APPDATA = process.env.APPDATA || path.join(HOME, 'AppData', 'Roaming');
@@ -49,6 +50,32 @@ function writeToml(filePath, data) {
49
50
  fs.writeFileSync(filePath, lines.join('\n') + '\n', 'utf8');
50
51
  }
51
52
 
53
+ function readWizardState() {
54
+ if (!fs.existsSync(CONFIG_JSON)) return {};
55
+ try {
56
+ const content = fs.readFileSync(CONFIG_JSON, 'utf8').trim();
57
+ return content ? JSON.parse(content) : {};
58
+ } catch {
59
+ return {};
60
+ }
61
+ }
62
+
63
+ function writeWizardState(state) {
64
+ ensureDir(path.dirname(CONFIG_JSON));
65
+ fs.writeFileSync(CONFIG_JSON, JSON.stringify(state, null, 2), 'utf8');
66
+ }
67
+
68
+ function hasCompletedOnboarding() {
69
+ const state = readWizardState();
70
+ return state.onboardingCompleted === true;
71
+ }
72
+
73
+ function markOnboardingCompleted() {
74
+ const state = readWizardState();
75
+ state.onboardingCompleted = true;
76
+ writeWizardState(state);
77
+ }
78
+
52
79
  function dim(text) { return `\x1b[2m${text}\x1b[0m`; }
53
80
  function bold(text) { return `\x1b[1m${text}\x1b[0m`; }
54
81
  function green(text) { return `\x1b[32m${text}\x1b[0m`; }
@@ -155,6 +182,10 @@ function openBrowser(url) {
155
182
  } catch { /* browser open is best-effort */ }
156
183
  }
157
184
 
185
+ function isInteractiveTerminal() {
186
+ return Boolean(process.stdin && process.stdin.isTTY && process.stdout && process.stdout.isTTY);
187
+ }
188
+
158
189
  function askYesNo(question) {
159
190
  return new Promise((resolve) => {
160
191
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -282,8 +313,14 @@ async function deviceAuthFlow() {
282
313
  console.log(` │ │`);
283
314
  console.log(` └───────────────────────────────────────────────┘\n`);
284
315
 
285
- openBrowser(loginUrl);
286
- console.log(` ${dim('Browser opened automatically.')}`);
316
+ const shouldAutoOpenBrowser = process.env.VESPER_WIZARD_AUTO_OPEN === '1';
317
+ if (shouldAutoOpenBrowser && !hasCompletedOnboarding()) {
318
+ openBrowser(loginUrl);
319
+ markOnboardingCompleted();
320
+ console.log(` ${dim('Browser opened automatically (enabled via VESPER_WIZARD_AUTO_OPEN=1).')}`);
321
+ } else {
322
+ console.log(` ${dim('Browser auto-open disabled. Open the URL manually to continue.')}`);
323
+ }
287
324
  console.log(` ${dim('Waiting for you to sign in...')}\n`);
288
325
 
289
326
  // Step 3: Poll until confirmed or expired
@@ -437,6 +474,13 @@ async function checkServerHealth() {
437
474
 
438
475
  // ── Main Wizard ──────────────────────────────────────────────
439
476
  async function main() {
477
+ if (!isInteractiveTerminal()) {
478
+ console.error(red('vesper-wizard is interactive and cannot run in MCP stdio mode.'));
479
+ console.error(dim('Use this command for MCP server runtime instead:'));
480
+ console.error(cyan('npx -y -p @vespermcp/mcp-server@latest vespermcp'));
481
+ process.exit(2);
482
+ }
483
+
440
484
  printBanner();
441
485
 
442
486
  console.log(` ${green('→')} Setting up Vesper on ${bold(os.hostname())}\n`);
@@ -487,17 +531,22 @@ async function main() {
487
531
  console.log(` ${green('✓')}`);
488
532
  console.log(` ${dim('Mode:')} ${dim(vaultData.auth_mode === 'cloud' ? 'cloud (linked to Vesper account)' : 'single local Vesper key (no external keys required)')}`);
489
533
 
490
- // ─── Step 4: Install @vespermcp/mcp-server ─────────────────
491
- console.log(`\n ${dim('[')}${cyan('4/6')}${dim(']')} Installing Vesper MCP server...`);
534
+ // ─── Step 4: Verify @vespermcp/mcp-server command ───────────
535
+ console.log(`\n ${dim('[')}${cyan('4/6')}${dim(']')} Verifying Vesper MCP server command...`);
492
536
  try {
493
537
  const npmCmd = IS_WIN ? 'npx.cmd' : 'npx';
494
- spawnSync(npmCmd, ['-y', '@vespermcp/mcp-server@latest', '--setup', '--silent'], {
495
- stdio: 'inherit',
496
- timeout: 120000,
538
+ const verify = spawnSync(npmCmd, ['-y', '-p', '@vespermcp/mcp-server@latest', 'vespermcp', '--version'], {
539
+ stdio: 'pipe',
540
+ timeout: 30000,
541
+ encoding: 'utf8',
497
542
  });
498
- console.log(` ${green('✓')} @vespermcp/mcp-server installed`);
543
+ if (verify.status === 0) {
544
+ console.log(` ${green('✓')} @vespermcp/mcp-server command is available`);
545
+ } else {
546
+ console.log(` ${yellow('⚠')} Could not verify vespermcp binary. MCP clients will still install it on first run.`);
547
+ }
499
548
  } catch {
500
- console.log(` ${yellow('⚠')} Could not auto-install run manually: npx -y @vespermcp/mcp-server@latest --setup`);
549
+ console.log(` ${yellow('⚠')} Could not verify vespermcp binary. MCP clients will still install it on first run.`);
501
550
  }
502
551
 
503
552
  // ─── Step 5: Auto-configure all detected IDEs ──────────────