ventureos 1.0.5 → 1.0.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 (2) hide show
  1. package/install.js +85 -15
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -15,11 +15,14 @@ import { stdin as input, stdout as output } from 'process';
15
15
  import fs from 'fs';
16
16
  import path from 'path';
17
17
  import { fileURLToPath } from 'url';
18
+ import { spawnSync } from 'child_process';
18
19
 
19
20
  const __filename = fileURLToPath(import.meta.url);
20
21
  const PACKAGE_ROOT = path.dirname(__filename);
21
22
 
22
23
  // Must be defined before startChat() runs (accessed synchronously before first await)
24
+ let _spinner;
25
+
23
26
  const PROVIDERS = {
24
27
  anthropic: {
25
28
  label: 'Claude (Anthropic)',
@@ -38,6 +41,11 @@ const PROVIDERS = {
38
41
  },
39
42
  };
40
43
 
44
+ // CLI tools that can be used instead of an API key
45
+ const CLI_TOOLS = {
46
+ anthropic: { cmd: 'claude', label: 'Claude CLI' },
47
+ };
48
+
41
49
  const cmd = process.argv[2];
42
50
 
43
51
  if (cmd === 'start') {
@@ -281,17 +289,41 @@ async function startChat() {
281
289
  const providerKey = PROVIDERS[config.llm] ? config.llm : 'anthropic';
282
290
  const provider = PROVIDERS[providerKey];
283
291
 
284
- // ── Get API key ────────────────────────────────────────────────────────────
292
+ // ── Get API key or use CLI mode ────────────────────────────────────────────
285
293
  let apiKey = process.env[provider.envVar];
294
+ let useCLI = false;
295
+ let cliCmd = null;
296
+
286
297
  if (!apiKey) {
287
- console.log(`\n 🔑 ${provider.envVar} not set in environment.`);
288
- apiKey = (await rl.question(` Enter your ${provider.label} API key: `)).trim();
289
- if (!apiKey) {
290
- console.error('\n ❌ No API key provided.\n');
291
- rl.close();
292
- process.exit(1);
298
+ const cli = detectCLI(providerKey);
299
+ if (cli) {
300
+ console.log(`\n 🔑 ${provider.envVar} not set in environment.\n`);
301
+ console.log(` How would you like to connect?\n`);
302
+ console.log(` 1. Enter API key`);
303
+ console.log(` 2. Use ${cli.label} (detected on your system)\n`);
304
+ const choice = (await rl.question(' Select [1-2]: ')).trim();
305
+ if (choice === '2') {
306
+ useCLI = true;
307
+ cliCmd = cli.cmd;
308
+ } else {
309
+ apiKey = (await rl.question(`\n Enter your ${provider.label} API key: `)).trim();
310
+ if (!apiKey) {
311
+ console.error('\n ❌ No API key provided.\n');
312
+ rl.close();
313
+ process.exit(1);
314
+ }
315
+ console.log(`\n 💡 Tip: export ${provider.envVar}=your-key to skip this next time.\n`);
316
+ }
317
+ } else {
318
+ console.log(`\n 🔑 ${provider.envVar} not set in environment.`);
319
+ apiKey = (await rl.question(` Enter your ${provider.label} API key: `)).trim();
320
+ if (!apiKey) {
321
+ console.error('\n ❌ No API key provided.\n');
322
+ rl.close();
323
+ process.exit(1);
324
+ }
325
+ console.log(`\n 💡 Tip: export ${provider.envVar}=your-key to skip this next time.\n`);
293
326
  }
294
- console.log(`\n 💡 Tip: export ${provider.envVar}=your-key to skip this next time.\n`);
295
327
  }
296
328
 
297
329
  // ── Load system prompt ─────────────────────────────────────────────────────
@@ -318,7 +350,7 @@ async function startChat() {
318
350
  `--- ventureOS/_memory/venture-state.yaml ---\n${stateContent}`;
319
351
 
320
352
  console.log(line());
321
- console.log(` ✓ Connected to ${provider.label}`);
353
+ console.log(` ✓ Connected ${useCLI ? `via ${cliCmd} CLI` : `to ${provider.label}`}`);
322
354
  console.log(` ✓ Type your message and press Enter. Type "exit" or Ctrl+C to quit.`);
323
355
  console.log(line() + '\n');
324
356
 
@@ -328,9 +360,9 @@ async function startChat() {
328
360
  showSpinner(' Victor is thinking');
329
361
  let firstResponse;
330
362
  try {
331
- firstResponse = await callLLM(providerKey, apiKey, provider.defaultModel, systemPrompt, [
332
- { role: 'user', content: activationMsg },
333
- ]);
363
+ firstResponse = useCLI
364
+ ? await callViaCLI(cliCmd, systemPrompt, [{ role: 'user', content: activationMsg }])
365
+ : await callLLM(providerKey, apiKey, provider.defaultModel, systemPrompt, [{ role: 'user', content: activationMsg }]);
334
366
  } catch (err) {
335
367
  stopSpinner();
336
368
  console.error(`\n ❌ API error: ${err.message}`);
@@ -366,7 +398,9 @@ async function startChat() {
366
398
  showSpinner(' Victor is thinking');
367
399
  let response;
368
400
  try {
369
- response = await callLLM(providerKey, apiKey, provider.defaultModel, systemPrompt, messages);
401
+ response = useCLI
402
+ ? await callViaCLI(cliCmd, systemPrompt, messages)
403
+ : await callLLM(providerKey, apiKey, provider.defaultModel, systemPrompt, messages);
370
404
  } catch (err) {
371
405
  stopSpinner();
372
406
  console.error(`\n ❌ API error: ${err.message}\n`);
@@ -383,9 +417,20 @@ async function startChat() {
383
417
  rl.close();
384
418
  }
385
419
 
386
- // ─── Spinner ───────────────────────────────────────────────────────────────────
420
+ // ─── CLI Detection ─────────────────────────────────────────────────────────────
387
421
 
388
- let _spinner;
422
+ function detectCLI(providerKey) {
423
+ const tool = CLI_TOOLS[providerKey];
424
+ if (!tool) return null;
425
+ try {
426
+ const result = spawnSync('which', [tool.cmd], { encoding: 'utf8', stdio: 'pipe' });
427
+ return result.status === 0 && result.stdout.trim() ? tool : null;
428
+ } catch {
429
+ return null;
430
+ }
431
+ }
432
+
433
+ // ─── Spinner ───────────────────────────────────────────────────────────────────
389
434
  function showSpinner(msg) {
390
435
  const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
391
436
  let i = 0;
@@ -442,6 +487,31 @@ async function callLLM(provider, apiKey, model, system, messages) {
442
487
  throw new Error(`Unknown provider: ${provider}`);
443
488
  }
444
489
 
490
+ async function callViaCLI(cliCmd, system, messages) {
491
+ // Build full context: system + conversation history + latest user message
492
+ let prompt = system + '\n\n';
493
+
494
+ for (const msg of messages.slice(0, -1)) {
495
+ const role = msg.role === 'user' ? 'Human' : 'Assistant';
496
+ prompt += `${role}: ${msg.content}\n\n`;
497
+ }
498
+
499
+ const lastMsg = messages[messages.length - 1];
500
+ prompt += `Human: ${lastMsg.content}`;
501
+
502
+ const result = spawnSync(cliCmd, ['-p', prompt], {
503
+ encoding: 'utf8',
504
+ maxBuffer: 10 * 1024 * 1024,
505
+ timeout: 120000,
506
+ });
507
+
508
+ if (result.error) throw result.error;
509
+ if (result.status !== 0) {
510
+ throw new Error(result.stderr?.trim() || `${cliCmd} CLI exited with code ${result.status}`);
511
+ }
512
+ return result.stdout.trim();
513
+ }
514
+
445
515
  async function callAnthropic(apiKey, model, system, messages) {
446
516
  const res = await fetch('https://api.anthropic.com/v1/messages', {
447
517
  method: 'POST',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ventureos",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "VentureOS — AI-powered venture building framework. From raw idea to investor-ready pitch in 12 structured weeks.",
5
5
  "type": "module",
6
6
  "bin": {