@claudecollab/cli 0.1.2 → 0.1.3
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 +1 -1
- package/packages/cli/src/pty.js +38 -0
package/package.json
CHANGED
package/packages/cli/src/pty.js
CHANGED
|
@@ -10,8 +10,45 @@
|
|
|
10
10
|
// node-pty is a native module and is imported lazily inside startPty, so this
|
|
11
11
|
// file (and FrameSplitter's tests) load fine even where node-pty isn't built.
|
|
12
12
|
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import { createRequire } from 'node:module';
|
|
16
|
+
|
|
13
17
|
/** Synchronized-update END marker. Claude ends every repaint frame with this. */
|
|
14
18
|
export const SU_END = '\x1b[?2026l';
|
|
19
|
+
|
|
20
|
+
// node-pty forks a small `spawn-helper` binary to launch the child, and that file
|
|
21
|
+
// must be executable. Installers that skip package build scripts (npm's
|
|
22
|
+
// allow-scripts / ignore-scripts policies, pnpm by default) ship it WITHOUT the
|
|
23
|
+
// execute bit, so the very first spawn dies with "posix_spawnp failed". A
|
|
24
|
+
// postinstall script can't fix this — those same policies block it — so we restore
|
|
25
|
+
// the bit at RUNTIME, right before spawning. Best-effort and idempotent: if the
|
|
26
|
+
// bit is already set (or we can't touch the file) we do nothing and let spawn
|
|
27
|
+
// surface the real error. macOS/Linux only; Windows has no such helper.
|
|
28
|
+
export function ensureSpawnHelperExecutable(requireFn) {
|
|
29
|
+
if (process.platform === 'win32') return;
|
|
30
|
+
try {
|
|
31
|
+
const req = requireFn ?? createRequire(import.meta.url);
|
|
32
|
+
const ptyDir = path.dirname(req.resolve('node-pty/package.json'));
|
|
33
|
+
const candidates = [path.join(ptyDir, 'build', 'Release', 'spawn-helper')];
|
|
34
|
+
const prebuilds = path.join(ptyDir, 'prebuilds');
|
|
35
|
+
try {
|
|
36
|
+
for (const d of fs.readdirSync(prebuilds)) candidates.push(path.join(prebuilds, d, 'spawn-helper'));
|
|
37
|
+
} catch {
|
|
38
|
+
/* no prebuilds dir on this layout */
|
|
39
|
+
}
|
|
40
|
+
for (const f of candidates) {
|
|
41
|
+
try {
|
|
42
|
+
const { mode } = fs.statSync(f);
|
|
43
|
+
if (!(mode & 0o111)) fs.chmodSync(f, mode | 0o111); // add u+g+o execute
|
|
44
|
+
} catch {
|
|
45
|
+
/* not present here, or not ours to chmod — skip */
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
/* couldn't even resolve node-pty — the import below throws the real error */
|
|
50
|
+
}
|
|
51
|
+
}
|
|
15
52
|
/** Synchronized-update BEGIN marker (exported for reference / future use). */
|
|
16
53
|
export const SU_BEGIN = '\x1b[?2026h';
|
|
17
54
|
|
|
@@ -78,6 +115,7 @@ export async function startPty({
|
|
|
78
115
|
cwd,
|
|
79
116
|
flushMs = 8,
|
|
80
117
|
} = {}) {
|
|
118
|
+
ensureSpawnHelperExecutable(); // fix node-pty's spawn-helper exec bit before spawning
|
|
81
119
|
const mod = await import('node-pty');
|
|
82
120
|
const spawn = mod.spawn ?? mod.default?.spawn;
|
|
83
121
|
if (typeof spawn !== 'function') {
|