@cachly-dev/mcp-server 0.10.74 → 0.10.76

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/src/index.js CHANGED
@@ -63,7 +63,7 @@ import { Redis } from 'ioredis';
63
63
  const API_URL = process.env.CACHLY_API_URL ?? 'https://api.cachly.dev';
64
64
  let JWT = process.env.CACHLY_JWT ?? '';
65
65
  const _EMBED_MODEL = process.env.CACHLY_EMBED_MODEL ?? '';
66
- const CURRENT_VERSION = '0.10.74';
66
+ const CURRENT_VERSION = '0.10.76';
67
67
  // Max time to wait for a freshly-provisioned instance to become "running" before
68
68
  // giving up. Free-tier provisioning in high-latency regions can take 45–90s, so the
69
69
  // old hard-coded 25s caused spurious "instance_not_reachable" on first run.
@@ -2294,9 +2294,17 @@ if (process.argv[2] === 'setup') {
2294
2294
  const { existsSync } = await import('node:fs');
2295
2295
  const { resolve, dirname } = await import('node:path');
2296
2296
  const { createInterface } = await import('node:readline');
2297
+ const setupStartMs = Date.now();
2297
2298
  sendFunnelEvent('setup_started');
2298
- // --yes / -y → non-interactive mode (skips all prompts, picks defaults)
2299
- const nonInteractive = process.argv.includes('--yes') || process.argv.includes('-y');
2299
+ // --yes / -y → non-interactive mode (skips all prompts, picks defaults).
2300
+ // Also auto-detect a non-interactive stdin (VSCode tasks, CI, piped input):
2301
+ // a readline question against a non-TTY stdin never resolves and hangs the
2302
+ // wizard forever. Treat that exactly like --yes so we never block.
2303
+ const stdinIsInteractive = process.stdin.isTTY === true;
2304
+ const nonInteractive = process.argv.includes('--yes') || process.argv.includes('-y') || !stdinIsInteractive;
2305
+ if (!stdinIsInteractive && !process.argv.includes('--yes') && !process.argv.includes('-y')) {
2306
+ console.log('ℹ️ Non-interactive terminal detected — running in automatic mode (no prompts).\n');
2307
+ }
2300
2308
  const rl = createInterface({ input: process.stdin, output: process.stdout });
2301
2309
  const ask = (q, defaultVal = '') => {
2302
2310
  if (nonInteractive) {
@@ -2443,6 +2451,17 @@ if (process.argv[2] === 'setup') {
2443
2451
  execSync(`${openCmd} "${signupUrl}"`, { stdio: 'ignore' });
2444
2452
  }
2445
2453
  catch { /* can't open browser — instructions shown above */ }
2454
+ // In a non-interactive terminal (VSCode task, CI) we cannot read a pasted
2455
+ // key — exit with clear, actionable instructions instead of hanging.
2456
+ if (nonInteractive) {
2457
+ sendFunnelEvent('device_flow_failed', { reason: 'non_interactive_no_key' });
2458
+ console.error('\n ⚠️ This terminal is non-interactive, so the key cannot be pasted here.');
2459
+ console.error(' Get your key at the URL above, then set it and re-run setup:\n');
2460
+ console.error(' \x1b[1mCACHLY_JWT=cky_live_xxx npx @cachly-dev/mcp-server@latest setup\x1b[0m\n');
2461
+ console.error(' Or add it to your editor\'s MCP config under env.CACHLY_JWT.\n');
2462
+ rl.close();
2463
+ process.exit(1);
2464
+ }
2446
2465
  token = await ask(' Paste API key (cky_live_...): ');
2447
2466
  if (!token) {
2448
2467
  console.error('\nAPI key is required. Aborting.\n');
@@ -2825,7 +2844,13 @@ if (process.argv[2] === 'setup') {
2825
2844
  catch { /* non-critical */ }
2826
2845
  // Setup reached the end successfully — close the funnel.
2827
2846
  JWT = token;
2828
- sendFunnelEvent('setup_completed', { instance_id: instance.id });
2847
+ const setupElapsedS = Math.round((Date.now() - setupStartMs) / 1000);
2848
+ sendFunnelEvent('setup_completed', { instance_id: instance.id, elapsed_s: setupElapsedS });
2849
+ console.log('\n╔══════════════════════════════════════════════════════╗');
2850
+ console.log('║ 🚀 Brain is ready. ║');
2851
+ console.log(`║ ⏱️ Setup completed in ${String(setupElapsedS + 's').padEnd(5)} — restart your editor ║`);
2852
+ console.log('║ and your AI arrives pre-briefed every session. ║');
2853
+ console.log('╚══════════════════════════════════════════════════════╝\n');
2829
2854
  rl.close();
2830
2855
  // Give the fire-and-forget telemetry a moment to flush before exit.
2831
2856
  await new Promise(r => setTimeout(r, 300));