cli-jaw 2.2.13 → 2.2.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cli-jaw",
3
- "version": "2.2.13",
3
+ "version": "2.2.14",
4
4
  "description": "Personal AI assistant powered by Pi, Antigravity, AI-E, Claude, Claude E, Codex, Codex App, Cursor, Grok, Kiro, OpenCode, and Copilot — Web, Terminal, Telegram, and Discord interfaces with 107 built-in skills",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Run electron-builder with a node-gyp-capable python resolved first.
4
+ *
5
+ * The scripts used to inline the lookup as
6
+ * `PYTHON="$(bash ../scripts/pick-gyp-python.sh)" electron-builder --win`.
7
+ * npm hands package scripts to cmd.exe on Windows, which does not expand
8
+ * `$(...)`, so the literal text arrived as a filename and the Windows job of
9
+ * every desktop release from v2.2.11 onward died before electron-builder even
10
+ * started:
11
+ *
12
+ * PYTHON: can't open file 'D:\a\cli-jaw\cli-jaw\electron\=$(bash ..\scripts\pick-gyp-python.sh)'
13
+ *
14
+ * macOS and Linux kept building, so the release looked successful while its
15
+ * Windows artifacts silently went missing.
16
+ *
17
+ * Node is the one interpreter guaranteed to exist wherever npm runs a script,
18
+ * so the resolution happens here instead of in shell syntax. The picker itself
19
+ * stays in bash and stays authoritative; it is simply invoked rather than
20
+ * interpolated. When bash is unavailable (a plain Windows box without Git
21
+ * Bash), the build proceeds with the ambient python3: node-gyp then fails with
22
+ * its own diagnostic instead of a confusing missing-file error.
23
+ */
24
+ import { spawnSync } from 'node:child_process';
25
+ import { dirname, join } from 'node:path';
26
+ import { fileURLToPath } from 'node:url';
27
+
28
+ const scriptsDir = dirname(fileURLToPath(import.meta.url));
29
+ const picker = join(scriptsDir, 'pick-gyp-python.sh');
30
+
31
+ /** Ask the bash picker for an interpreter that still has distutils. */
32
+ function resolvePython() {
33
+ if (process.env['PYTHON']) return process.env['PYTHON'];
34
+ const probe = spawnSync('bash', [picker], { encoding: 'utf8' });
35
+ if (probe.status !== 0) {
36
+ const reason = probe.error ? probe.error.message : (probe.stderr || '').trim();
37
+ console.warn(`[gyp-python] picker unavailable (${reason || 'unknown'}); leaving python resolution to node-gyp`);
38
+ return null;
39
+ }
40
+ return probe.stdout.trim() || null;
41
+ }
42
+
43
+ const python = resolvePython();
44
+ const env = { ...process.env };
45
+ if (python) {
46
+ env['PYTHON'] = python;
47
+ // node-gyp does not read PYTHON on its own; npm_config_python is the knob
48
+ // it actually consults.
49
+ env['npm_config_python'] = python;
50
+ }
51
+
52
+ const args = process.argv.slice(2);
53
+ const builder = process.platform === 'win32' ? 'electron-builder.cmd' : 'electron-builder';
54
+ const result = spawnSync(builder, args, { stdio: 'inherit', env, shell: process.platform === 'win32' });
55
+
56
+ if (result.error) {
57
+ console.error(`[electron-builder] failed to start: ${result.error.message}`);
58
+ process.exit(1);
59
+ }
60
+ process.exit(result.status ?? 1);