0x2ai-zoe 0.2.1 → 0.2.2

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/bin/start.cjs +41 -15
  2. package/package.json +1 -1
package/bin/start.cjs CHANGED
@@ -1,19 +1,34 @@
1
1
  #!/usr/bin/env node
2
+ 'use strict';
2
3
  const fs = require('node:fs'), path = require('node:path');
3
4
  const { spawn } = require('node:child_process');
4
- const cwd = process.cwd();
5
+
6
+ // --- Node version guard (LOUD — old Node is the #1 silent-fail cause) -----
7
+ const major = parseInt(process.versions.node.split('.')[0], 10);
8
+ if (!Number.isFinite(major) || major < 18) {
9
+ console.error('');
10
+ console.error('[0x2ai] Your Node.js is too old: v' + process.versions.node + ' — this needs Node 18 or newer.');
11
+ console.error('[0x2ai] Install current Node LTS from https://nodejs.org (or: winget install OpenJS.NodeJS.LTS),');
12
+ console.error('[0x2ai] close this terminal, open a NEW one, and run the npx command again.');
13
+ console.error('');
14
+ process.exit(1);
15
+ }
16
+
17
+ // Stage into the directory the user actually invoked npx from. INIT_CWD is the
18
+ // npm-canonical invocation dir (what the old working packs used); process.cwd()
19
+ // is the fallback. This avoids staging into the npx cache dir on some setups.
20
+ const cwd = process.env.INIT_CWD || process.cwd();
5
21
  const payload = path.join(__dirname, '..', 'payload');
6
22
  const PKG = require('../package.json').name;
7
23
 
8
- // Tokenless pack: the access token is NEVER baked into this package.
9
- // Resolution order (all npx-safe, no interactive stdin needed):
10
- // 1. command arg -> npx 0x2ai-zoe <TOKEN>
24
+ // Token resolution (all npx-safe NO interactive stdin, which dies under npx):
25
+ // 1. command arg -> npx 0x2ai-zoe <TOKEN>
11
26
  // 2. BRIDGE_TOKEN env
12
- // 3. token.txt in this folder
13
- // 4. an already-installed .mcp.json (re-run with token already in place)
27
+ // 3. token.txt in the folder
28
+ // 4. an already-installed .mcp.json (re-run)
14
29
  function resolveToken() {
15
30
  const arg = (process.argv[2] || '').trim();
16
- if (arg && arg.length >= 24) return arg;
31
+ if (arg.length >= 24) return arg;
17
32
  if (process.env.BRIDGE_TOKEN && process.env.BRIDGE_TOKEN.trim().length >= 24) return process.env.BRIDGE_TOKEN.trim();
18
33
  const tf = path.join(cwd, 'token.txt');
19
34
  if (fs.existsSync(tf)) { const t = fs.readFileSync(tf, 'utf8').trim(); if (t.length >= 24) return t; }
@@ -28,32 +43,43 @@ function resolveToken() {
28
43
  return null;
29
44
  }
30
45
 
31
- // Always stage the connector files first so the folder is never half-empty.
32
- try { fs.cpSync(payload, cwd, { recursive: true, force: false, errorOnExist: false }); } catch (e) {}
46
+ // Stage connector files FIRST so the folder is never empty. Errors are LOUD.
47
+ try {
48
+ fs.cpSync(payload, cwd, { recursive: true, force: false, errorOnExist: false });
49
+ } catch (e) {
50
+ console.error('[0x2ai] could not stage connector files into: ' + cwd);
51
+ console.error('[0x2ai] reason: ' + e.message);
52
+ process.exit(1);
53
+ }
54
+ // Verify staging actually landed (catches silent cwd / permission misses).
55
+ if (!fs.existsSync(path.join(cwd, '.mcp.json'))) {
56
+ console.error('[0x2ai] staging produced no files in: ' + cwd);
57
+ console.error('[0x2ai] (INIT_CWD=' + (process.env.INIT_CWD || '<unset>') + ', cwd=' + process.cwd() + ')');
58
+ console.error('[0x2ai] please report this line to the operator.');
59
+ process.exit(1);
60
+ }
33
61
 
34
62
  const token = resolveToken();
35
63
  if (!token) {
36
64
  console.error('');
37
- console.error('[0x2ai] No access token provided Olivia cannot connect without it.');
38
- console.error('[0x2ai] Re-run with the token on the command, e.g.:');
65
+ console.error('[0x2ai] Connector files are ready, but no access token was provided.');
66
+ console.error('[0x2ai] Re-run with the token on the command:');
39
67
  console.error('');
40
68
  console.error(' npx ' + PKG + ' <YOUR_TOKEN>');
41
69
  console.error('');
42
- console.error('[0x2ai] (NOT launching Claude — it would just fail to reach the bridge.)');
70
+ console.error('[0x2ai] (Not launching Claude — it would just fail to reach the bridge.)');
43
71
  process.exit(1);
44
72
  }
45
73
 
46
- // Inject the token into the staged .mcp.json (idempotent — re-runs re-write it).
47
74
  const mj = path.join(cwd, '.mcp.json');
48
75
  try {
49
76
  const conf = JSON.parse(fs.readFileSync(mj, 'utf8'));
50
77
  conf.mcpServers.chatroom.env.BRIDGE_AUTH_TOKEN = token;
51
78
  fs.writeFileSync(mj, JSON.stringify(conf, null, 2));
52
79
  } catch (e) { console.error('[0x2ai] token install failed: ' + e.message); process.exit(1); }
53
- // Don't leave the hand-carried token lying around in plaintext beside the folder.
54
80
  try { const tf = path.join(cwd, 'token.txt'); if (fs.existsSync(tf)) fs.rmSync(tf); } catch (e) {}
55
81
 
56
- console.log('[0x2ai] Olivia connector ready (token installed). Launching Claude — then run /0x2ai-boot');
82
+ console.log('[0x2ai] Olivia connector ready in ' + cwd + ' (token installed). Launching Claude — then run /0x2ai-boot');
57
83
  const child = spawn('claude', ['--dangerously-skip-permissions'], { stdio: 'inherit', cwd, shell: true });
58
84
  child.on('exit', (c) => process.exit(c == null ? 0 : c));
59
85
  child.on('error', (e) => { console.error('[0x2ai] launch claude failed: ' + e.message + ' — install: npm i -g @anthropic-ai/claude-code'); process.exit(1); });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0x2ai-zoe",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "0x2AI Olivia connector (zoe) — npx 0x2ai-zoe then /0x2ai-boot. Self-contained.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,