colana 1.0.0-beta.67 → 1.0.0-beta.69

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": "colana",
3
- "version": "1.0.0-beta.67",
3
+ "version": "1.0.0-beta.69",
4
4
  "description": "Agent-First. Multiplied. Multi-agent command center for AI coding agents.",
5
5
  "type": "module",
6
6
  "main": "server/index.js",
@@ -873,6 +873,9 @@ export async function startPtyAgent(projectId, projectPath, task, options = {})
873
873
  }
874
874
  }
875
875
 
876
+ // Save bare binary name before full-path resolution (needed for spawn retry)
877
+ const bareBinary = binary;
878
+
876
879
  // On macOS/Linux, resolve the binary to a full path. node-pty's posix_spawnp
877
880
  // uses the spawned env's PATH, which may be stale if the CLI was installed
878
881
  // after the server started (e.g. via wizard). getCommandPath() calls `which`
@@ -1161,13 +1164,42 @@ export async function startPtyAgent(projectId, projectPath, task, options = {})
1161
1164
  binary = process.env.COMSPEC || 'cmd.exe';
1162
1165
  }
1163
1166
 
1164
- const shell = ptySpawnFn(binary, args, {
1167
+ const spawnOpts = {
1165
1168
  name: 'xterm-256color',
1166
1169
  cols: options.cols || config.ptyDefaultCols,
1167
1170
  rows: options.rows || config.ptyDefaultRows,
1168
1171
  cwd: effectiveCwd,
1169
- env: spawnEnv
1170
- });
1172
+ env: spawnEnv,
1173
+ };
1174
+
1175
+ let shell;
1176
+ try {
1177
+ shell = ptySpawnFn(binary, args, spawnOpts);
1178
+ } catch (spawnErr) {
1179
+ // Windows uses cmd.exe wrapper (set above) — no retry needed
1180
+ if (process.platform === 'win32') throw spawnErr;
1181
+
1182
+ // macOS/Linux: posix_spawnp can fail with full paths to npm-installed CLIs
1183
+ // (symlinks to Node.js scripts with shebangs). Retry with progressively
1184
+ // simpler strategies: bare binary name (uses spawnEnv PATH), then /bin/sh -c
1185
+ // wrapper (shell handles shebang/symlink resolution natively).
1186
+ const retries = [];
1187
+ if (binary !== bareBinary) {
1188
+ retries.push({ bin: bareBinary, a: args, label: `bare name '${bareBinary}'` });
1189
+ }
1190
+ const escaped = [bareBinary, ...args].map(s => `'${s.replace(/'/g, "'\\''")}'`).join(' ');
1191
+ retries.push({ bin: '/bin/sh', a: ['-c', escaped], label: '/bin/sh -c wrapper' });
1192
+
1193
+ for (const r of retries) {
1194
+ try {
1195
+ console.warn(`[pty-manager] posix_spawnp failed with '${binary}', retrying with ${r.label}`);
1196
+ shell = ptySpawnFn(r.bin, r.a, spawnOpts);
1197
+ break;
1198
+ } catch { /* try next strategy */ }
1199
+ }
1200
+
1201
+ if (!shell) throw spawnErr; // All retries failed — throw original error
1202
+ }
1171
1203
 
1172
1204
  // 4. Create PtySession, wire events
1173
1205
  const ptySession = new PtySession(session.id, shell, {