agent-yes 1.246.4 → 1.246.5
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/dist/{SUPPORTED_CLIS-Bxzq06Mp.js → SUPPORTED_CLIS-D3b_1q8z.js} +3 -3
- package/dist/{SUPPORTED_CLIS-DjDZ3MGT.js → SUPPORTED_CLIS-ia9b-P1k.js} +2 -2
- package/dist/{agent-yes.config-DPtMM0S-.js → agent-yes.config-C8e9rNLW.js} +3 -3
- package/dist/{agentShare-DfvmYPdC.js → agentShare-BazKWNQQ.js} +3 -3
- package/dist/{callback-Bd4vejg2.js → callback-Csr8_-FG.js} +3 -3
- package/dist/{callback-CgvcnRIP.js → callback-DyyjF-fr.js} +5 -5
- package/dist/cli.js +5 -5
- package/dist/{configShared-9wVlbPyC.js → configShared-IBbnn9b8.js} +2 -2
- package/dist/{expose-Ct28jckQ.js → expose-BU3f7VfC.js} +3 -3
- package/dist/index.js +2 -2
- package/dist/{notifyDaemon-Cgx9Sauh.js → notifyDaemon-DDPfMGlw.js} +3 -3
- package/dist/{rustBinary-t6UmLbT8.js → rustBinary-DuwxRidk.js} +2 -2
- package/dist/{schedule-Ak3Z7M7d.js → schedule-CWBHxQxk.js} +4 -4
- package/dist/{serve-88nSS8sz.js → serve-DyZpvp4C.js} +17 -17
- package/dist/{setup-Dfc3vx65.js → setup-JqletyDD.js} +2 -2
- package/dist/{subcommands-WOGfqD8M.js → subcommands-BL_SWFDC.js} +14 -14
- package/dist/{subcommands-BLOe70zq.js → subcommands-CdWAGc4C.js} +2 -2
- package/dist/{terminal-DxXJeIF4.js → terminal-BFq0mWdQ.js} +2 -2
- package/dist/{ts-CQ67EOjN.js → ts-B51ZLoJC.js} +89 -10
- package/dist/{versionChecker-D5s9vQ-1.js → versionChecker-D5ir842c.js} +2 -2
- package/dist/{widget-DZxzSlx6.js → widget-BXlREJHQ.js} +3 -3
- package/dist/{ws-BSxJ9sZs.js → ws-C6gfqPHM.js} +3 -3
- package/package.json +1 -1
- package/ts/index.ts +10 -3
- package/ts/resolveBinary.spec.ts +133 -0
- package/ts/resolveBinary.ts +95 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./versionChecker-
|
|
3
|
-
import "./ts-
|
|
2
|
+
import "./versionChecker-D5ir842c.js";
|
|
3
|
+
import "./ts-B51ZLoJC.js";
|
|
4
4
|
import "./todoAutomation-Buo457VO.js";
|
|
5
5
|
import "./JsonlStore-CPGIR0Wy.js";
|
|
6
6
|
import "./globalPidIndex-D9DOSd-c.js";
|
|
7
7
|
import "./pidStore-6EZd5DUv.js";
|
|
8
8
|
import "./messageLog-C-YIzhRj.js";
|
|
9
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
9
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-ia9b-P1k.js";
|
|
10
10
|
|
|
11
11
|
export { SUPPORTED_CLIS };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-B51ZLoJC.js";
|
|
2
2
|
|
|
3
3
|
//#region ts/SUPPORTED_CLIS.ts
|
|
4
4
|
const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
|
|
5
5
|
|
|
6
6
|
//#endregion
|
|
7
7
|
export { SUPPORTED_CLIS as t };
|
|
8
|
-
//# sourceMappingURL=SUPPORTED_CLIS-
|
|
8
|
+
//# sourceMappingURL=SUPPORTED_CLIS-ia9b-P1k.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as logger } from "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import { n as normalizeAgentYesConfig, t as loadSharedCliDefaults } from "./configShared-
|
|
2
|
+
import { n as normalizeAgentYesConfig, t as loadSharedCliDefaults } from "./configShared-IBbnn9b8.js";
|
|
3
|
+
import path from "node:path";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
5
|
-
import path from "node:path";
|
|
6
6
|
import { parse } from "yaml";
|
|
7
7
|
|
|
8
8
|
//#region ts/defineConfig.ts
|
|
@@ -226,4 +226,4 @@ async function getDefaultConfig() {
|
|
|
226
226
|
|
|
227
227
|
//#endregion
|
|
228
228
|
export { agent_yes_config_default as default };
|
|
229
|
-
//# sourceMappingURL=agent-yes.config-
|
|
229
|
+
//# sourceMappingURL=agent-yes.config-C8e9rNLW.js.map
|
|
@@ -2,8 +2,8 @@ import "./logger-CDIsZ-Pp.js";
|
|
|
2
2
|
import "./globalPidIndex-D9DOSd-c.js";
|
|
3
3
|
import "./messageLog-C-YIzhRj.js";
|
|
4
4
|
import "./e2e-CEIdJGZ7.js";
|
|
5
|
-
import "./configShared-
|
|
6
|
-
import { P as resolveOne } from "./subcommands-
|
|
5
|
+
import "./configShared-IBbnn9b8.js";
|
|
6
|
+
import { P as resolveOne } from "./subcommands-BL_SWFDC.js";
|
|
7
7
|
import "./webrtcLink-BMYneHbu.js";
|
|
8
8
|
import "./remotes-BxQnNxQv.js";
|
|
9
9
|
import { a as startShare } from "./share-BGl3wutJ.js";
|
|
@@ -229,4 +229,4 @@ function transformEvent(rawEvent, agentId, forwarded) {
|
|
|
229
229
|
|
|
230
230
|
//#endregion
|
|
231
231
|
export { createScopedShare, listShares, revokeAllShares, revokeShare };
|
|
232
|
-
//# sourceMappingURL=agentShare-
|
|
232
|
+
//# sourceMappingURL=agentShare-BazKWNQQ.js.map
|
|
@@ -2,11 +2,11 @@ import "./logger-CDIsZ-Pp.js";
|
|
|
2
2
|
import "./globalPidIndex-D9DOSd-c.js";
|
|
3
3
|
import "./messageLog-C-YIzhRj.js";
|
|
4
4
|
import "./e2e-CEIdJGZ7.js";
|
|
5
|
-
import "./configShared-
|
|
6
|
-
import "./subcommands-
|
|
5
|
+
import "./configShared-IBbnn9b8.js";
|
|
6
|
+
import "./subcommands-BL_SWFDC.js";
|
|
7
7
|
import "./webrtcLink-BMYneHbu.js";
|
|
8
8
|
import "./remotes-BxQnNxQv.js";
|
|
9
9
|
import "./callbackCore-Dd28_cBM.js";
|
|
10
|
-
import { i as loadOrCreateCallbackSecret, n as isCallbackRevoked, r as loadCallbackSecretReadOnly, t as cmdCallback } from "./callback-
|
|
10
|
+
import { i as loadOrCreateCallbackSecret, n as isCallbackRevoked, r as loadCallbackSecretReadOnly, t as cmdCallback } from "./callback-DyyjF-fr.js";
|
|
11
11
|
|
|
12
12
|
export { cmdCallback };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { t as agentYesHome } from "./agentYesHome-CtmsY6I-.js";
|
|
2
|
-
import { P as resolveOne } from "./subcommands-
|
|
2
|
+
import { P as resolveOne } from "./subcommands-BL_SWFDC.js";
|
|
3
3
|
import { a as mintCapability, o as parseExpires } from "./callbackCore-Dd28_cBM.js";
|
|
4
4
|
import { randomBytes } from "node:crypto";
|
|
5
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
|
-
import path from "node:path";
|
|
7
5
|
import { chmodSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
8
8
|
|
|
9
9
|
//#region ts/callback.ts
|
|
10
10
|
function callbacksPath() {
|
|
@@ -72,7 +72,7 @@ async function resolveBase(flag) {
|
|
|
72
72
|
if (flag) return flag;
|
|
73
73
|
if (process.env.AGENT_YES_CALLBACK_BASE) return process.env.AGENT_YES_CALLBACK_BASE;
|
|
74
74
|
try {
|
|
75
|
-
const { resolveLocalServeUrl } = await import("./serve-
|
|
75
|
+
const { resolveLocalServeUrl } = await import("./serve-DyZpvp4C.js");
|
|
76
76
|
const url = await resolveLocalServeUrl();
|
|
77
77
|
if (url) return url;
|
|
78
78
|
} catch {}
|
|
@@ -187,4 +187,4 @@ async function cmdCallback(rest) {
|
|
|
187
187
|
|
|
188
188
|
//#endregion
|
|
189
189
|
export { loadOrCreateCallbackSecret as i, isCallbackRevoked as n, loadCallbackSecretReadOnly as r, cmdCallback as t };
|
|
190
|
-
//# sourceMappingURL=callback-
|
|
190
|
+
//# sourceMappingURL=callback-DyyjF-fr.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { t as invokedCliName } from "./invokedCli-uqM2YYA7.js";
|
|
3
3
|
import { n as logger } from "./logger-CDIsZ-Pp.js";
|
|
4
|
-
import { i as versionString, n as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-
|
|
5
|
-
import { n as getRustBinary } from "./rustBinary-
|
|
4
|
+
import { i as versionString, n as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-D5ir842c.js";
|
|
5
|
+
import { n as getRustBinary } from "./rustBinary-DuwxRidk.js";
|
|
6
6
|
import { argv } from "process";
|
|
7
7
|
import { spawn } from "child_process";
|
|
8
8
|
import ms from "ms";
|
|
@@ -285,7 +285,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
285
285
|
const rawArg = process.argv[2];
|
|
286
286
|
const managerCommands = !invokedCliName(process.argv);
|
|
287
287
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
288
|
-
const { isSubcommand, runSubcommand, cmdHelp, isUnknownManagerToken } = await import("./subcommands-
|
|
288
|
+
const { isSubcommand, runSubcommand, cmdHelp, isUnknownManagerToken } = await import("./subcommands-CdWAGc4C.js");
|
|
289
289
|
if (isHelpFlag && process.argv.length === 3) {
|
|
290
290
|
await cmdHelp(managerCommands);
|
|
291
291
|
process.exit(0);
|
|
@@ -295,7 +295,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
295
295
|
process.exit(code ?? 0);
|
|
296
296
|
}
|
|
297
297
|
{
|
|
298
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
298
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-D3b_1q8z.js");
|
|
299
299
|
if (isUnknownManagerToken(rawArg, managerCommands, SUPPORTED_CLIS)) {
|
|
300
300
|
process.stderr.write(`ay: unknown subcommand or CLI '${rawArg}'.\n See 'ay help' for subcommands. To run an agent, name a CLI:\n 'ay <cli> …' (e.g. 'ay claude …') or 'ay --cli <cli> …'.\n`);
|
|
301
301
|
process.exit(1);
|
|
@@ -346,7 +346,7 @@ if (config.useRust) {
|
|
|
346
346
|
}
|
|
347
347
|
}
|
|
348
348
|
if (rustBinary) {
|
|
349
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
349
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-D3b_1q8z.js");
|
|
350
350
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
351
351
|
if (config.verbose) {
|
|
352
352
|
console.log(`[rust] Using binary: ${rustBinary}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { access, readFile } from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
2
|
+
import { access, readFile } from "node:fs/promises";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { parse } from "yaml";
|
|
5
5
|
|
|
@@ -69,4 +69,4 @@ async function loadSharedCliDefaults(fromUrl = import.meta.url) {
|
|
|
69
69
|
|
|
70
70
|
//#endregion
|
|
71
71
|
export { normalizeAgentYesConfig as n, loadSharedCliDefaults as t };
|
|
72
|
-
//# sourceMappingURL=configShared-
|
|
72
|
+
//# sourceMappingURL=configShared-IBbnn9b8.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
2
|
import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
5
|
|
|
6
6
|
//#region node_modules/codehost/src/tunnel/protocol.ts
|
|
7
7
|
let Op = /* @__PURE__ */ function(Op) {
|
|
@@ -546,4 +546,4 @@ async function cmdExpose(args) {
|
|
|
546
546
|
|
|
547
547
|
//#endregion
|
|
548
548
|
export { cmdExpose, ensureExposure, listExposures, stopExposure };
|
|
549
|
-
//# sourceMappingURL=expose-
|
|
549
|
+
//# sourceMappingURL=expose-BU3f7VfC.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./versionChecker-
|
|
3
|
-
import { a as hasTodoStore, c as AgentContext, i as answerAsk, n as agentYes, o as listAsks, r as config, s as listAsksForProject, t as CLIS_CONFIG } from "./ts-
|
|
2
|
+
import "./versionChecker-D5ir842c.js";
|
|
3
|
+
import { a as hasTodoStore, c as AgentContext, i as answerAsk, n as agentYes, o as listAsks, r as config, s as listAsksForProject, t as CLIS_CONFIG } from "./ts-B51ZLoJC.js";
|
|
4
4
|
import { _ as isKnownKind, a as renderTree, b as statesOf, c as monitorHint, d as openStore, f as DONE_STATE, g as initialState, h as canTransition, i as renderDigest, l as CycleError, m as ORPHANED_STATE, o as unblockedTasks, p as LIFECYCLES, r as openBlockers, s as describeBlock, t as reconcileTodos, u as TodoStore, v as nextStates, x as removeControlCharacters, y as requiredGate } from "./todoAutomation-Buo457VO.js";
|
|
5
5
|
import "./JsonlStore-CPGIR0Wy.js";
|
|
6
6
|
import "./globalPidIndex-D9DOSd-c.js";
|
|
@@ -2,8 +2,8 @@ import { n as logger } from "./logger-CDIsZ-Pp.js";
|
|
|
2
2
|
import "./globalPidIndex-D9DOSd-c.js";
|
|
3
3
|
import "./messageLog-C-YIzhRj.js";
|
|
4
4
|
import "./e2e-CEIdJGZ7.js";
|
|
5
|
-
import "./configShared-
|
|
6
|
-
import { $ as shouldStealLock, C as listRecords, J as hostId, K as appendEvent, Q as readInbox, X as listInboxParents, Z as liveWatchers, _ as isPidAlive, c as deriveLiveState, et as daemonLockDir, j as renderLogTailLines, nt as notifyDir, q as gcInboxes, tt as daemonLockOwnerPath } from "./subcommands-
|
|
5
|
+
import "./configShared-IBbnn9b8.js";
|
|
6
|
+
import { $ as shouldStealLock, C as listRecords, J as hostId, K as appendEvent, Q as readInbox, X as listInboxParents, Z as liveWatchers, _ as isPidAlive, c as deriveLiveState, et as daemonLockDir, j as renderLogTailLines, nt as notifyDir, q as gcInboxes, tt as daemonLockOwnerPath } from "./subcommands-BL_SWFDC.js";
|
|
7
7
|
import "./webrtcLink-BMYneHbu.js";
|
|
8
8
|
import "./remotes-BxQnNxQv.js";
|
|
9
9
|
import { mkdir, readFile, rename, rm, stat, writeFile } from "fs/promises";
|
|
@@ -589,4 +589,4 @@ async function ensureDaemon() {
|
|
|
589
589
|
|
|
590
590
|
//#endregion
|
|
591
591
|
export { daemonStatus, ensureDaemon, requestDaemonStop, runDaemon };
|
|
592
|
-
//# sourceMappingURL=notifyDaemon-
|
|
592
|
+
//# sourceMappingURL=notifyDaemon-DDPfMGlw.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
1
|
+
import { r as getInstalledPackage } from "./versionChecker-D5ir842c.js";
|
|
2
2
|
import { execFileSync } from "child_process";
|
|
3
3
|
import { existsSync, mkdirSync, unlinkSync } from "fs";
|
|
4
4
|
import { chmod, copyFile } from "fs/promises";
|
|
@@ -225,4 +225,4 @@ async function getRustBinary(options = {}) {
|
|
|
225
225
|
|
|
226
226
|
//#endregion
|
|
227
227
|
export { getRustBinary as n, findSpawnHiddenLauncher as t };
|
|
228
|
-
//# sourceMappingURL=rustBinary-
|
|
228
|
+
//# sourceMappingURL=rustBinary-DuwxRidk.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./versionChecker-
|
|
3
|
-
import "./ts-
|
|
2
|
+
import "./versionChecker-D5ir842c.js";
|
|
3
|
+
import "./ts-B51ZLoJC.js";
|
|
4
4
|
import "./todoAutomation-Buo457VO.js";
|
|
5
5
|
import "./JsonlStore-CPGIR0Wy.js";
|
|
6
6
|
import "./globalPidIndex-D9DOSd-c.js";
|
|
7
7
|
import "./pidStore-6EZd5DUv.js";
|
|
8
8
|
import "./messageLog-C-YIzhRj.js";
|
|
9
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
9
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-ia9b-P1k.js";
|
|
10
10
|
import { d as resolveSpawnCwd } from "./workspaceConfig-DOHygA2x.js";
|
|
11
11
|
import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-BtL6Oo1o.js";
|
|
12
12
|
import { createHash } from "node:crypto";
|
|
@@ -153,4 +153,4 @@ async function cmdSchedule(rest) {
|
|
|
153
153
|
|
|
154
154
|
//#endregion
|
|
155
155
|
export { cmdSchedule };
|
|
156
|
-
//# sourceMappingURL=schedule-
|
|
156
|
+
//# sourceMappingURL=schedule-CWBHxQxk.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
-
import { t as findSpawnHiddenLauncher } from "./rustBinary-
|
|
4
|
-
import { i as answerAsk, l as CLAUDE_SESSION_PIN_ENV, o as listAsks } from "./ts-
|
|
2
|
+
import { r as getInstalledPackage } from "./versionChecker-D5ir842c.js";
|
|
3
|
+
import { t as findSpawnHiddenLauncher } from "./rustBinary-DuwxRidk.js";
|
|
4
|
+
import { i as answerAsk, l as CLAUDE_SESSION_PIN_ENV, o as listAsks } from "./ts-B51ZLoJC.js";
|
|
5
5
|
import { t as agentYesHome$1 } from "./agentYesHome-CtmsY6I-.js";
|
|
6
6
|
import { x as removeControlCharacters } from "./todoAutomation-Buo457VO.js";
|
|
7
7
|
import "./JsonlStore-CPGIR0Wy.js";
|
|
@@ -10,13 +10,13 @@ import "./pidStore-6EZd5DUv.js";
|
|
|
10
10
|
import { r as recordInbox } from "./messageLog-C-YIzhRj.js";
|
|
11
11
|
import { t as pgidForWrapper } from "./reaper-DP49VCKx.js";
|
|
12
12
|
import "./e2e-CEIdJGZ7.js";
|
|
13
|
-
import "./configShared-
|
|
14
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
15
|
-
import { A as recentReadEdges, C as listRecords, D as readNotes, G as writeToIpc, M as renderRawLog, N as renderRawLogLines, O as readPtysize, P as resolveOne, Y as isTransientLockMkdirError, f as extractNeedsInput, j as renderLogTailLines, k as recentMessageEdges, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, rt as TYPING_BADGE, u as extractBadges, x as isUserTyping, z as snapshotStatus } from "./subcommands-
|
|
13
|
+
import "./configShared-IBbnn9b8.js";
|
|
14
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-ia9b-P1k.js";
|
|
15
|
+
import { A as recentReadEdges, C as listRecords, D as readNotes, G as writeToIpc, M as renderRawLog, N as renderRawLogLines, O as readPtysize, P as resolveOne, Y as isTransientLockMkdirError, f as extractNeedsInput, j as renderLogTailLines, k as recentMessageEdges, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, rt as TYPING_BADGE, u as extractBadges, x as isUserTyping, z as snapshotStatus } from "./subcommands-BL_SWFDC.js";
|
|
16
16
|
import "./webrtcLink-BMYneHbu.js";
|
|
17
17
|
import "./remotes-BxQnNxQv.js";
|
|
18
18
|
import { i as frameVisitorMessage, s as verifyCapability, t as MAX_CALLBACK_MSG_BYTES } from "./callbackCore-Dd28_cBM.js";
|
|
19
|
-
import { n as isCallbackRevoked, r as loadCallbackSecretReadOnly } from "./callback-
|
|
19
|
+
import { n as isCallbackRevoked, r as loadCallbackSecretReadOnly } from "./callback-DyyjF-fr.js";
|
|
20
20
|
import { a as getSpawnHook, c as hasProvisionHook, d as resolveSpawnCwd, i as getProvisionRoot, l as hasSpawnHook, r as getProvisionHook, u as isProvisionAllowed } from "./workspaceConfig-DOHygA2x.js";
|
|
21
21
|
import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-BtL6Oo1o.js";
|
|
22
22
|
import { r as spawnRejectionReason } from "./spawnGate-BxgS_GlF.js";
|
|
@@ -2300,7 +2300,7 @@ Options:
|
|
|
2300
2300
|
}
|
|
2301
2301
|
});
|
|
2302
2302
|
if (req.method === "GET" && p === "/api/ws") {
|
|
2303
|
-
const ws = await import("./ws-
|
|
2303
|
+
const ws = await import("./ws-C6gfqPHM.js");
|
|
2304
2304
|
try {
|
|
2305
2305
|
await ws.loadProvision();
|
|
2306
2306
|
} catch (e) {
|
|
@@ -2320,7 +2320,7 @@ Options:
|
|
|
2320
2320
|
if (req.method === "GET" && p === "/api/ws/status") {
|
|
2321
2321
|
const dirRaw = url.searchParams.get("path");
|
|
2322
2322
|
if (!dirRaw) return new Response("missing ?path=<workspace dir>", { status: 400 });
|
|
2323
|
-
const ws = await import("./ws-
|
|
2323
|
+
const ws = await import("./ws-C6gfqPHM.js");
|
|
2324
2324
|
let prov;
|
|
2325
2325
|
try {
|
|
2326
2326
|
prov = await ws.loadProvision();
|
|
@@ -3070,7 +3070,7 @@ Options:
|
|
|
3070
3070
|
const perm = body.perm ?? "r";
|
|
3071
3071
|
if (perm !== "r" && perm !== "rw") return new Response(`invalid perm ${perm} (want r or rw)`, { status: 400 });
|
|
3072
3072
|
try {
|
|
3073
|
-
const { createScopedShare } = await import("./agentShare-
|
|
3073
|
+
const { createScopedShare } = await import("./agentShare-BazKWNQQ.js");
|
|
3074
3074
|
const share = await createScopedShare({
|
|
3075
3075
|
agent: body.agent,
|
|
3076
3076
|
perm,
|
|
@@ -3085,12 +3085,12 @@ Options:
|
|
|
3085
3085
|
}
|
|
3086
3086
|
}
|
|
3087
3087
|
if (req.method === "GET" && p === "/api/shares") {
|
|
3088
|
-
const { listShares } = await import("./agentShare-
|
|
3088
|
+
const { listShares } = await import("./agentShare-BazKWNQQ.js");
|
|
3089
3089
|
return Response.json(listShares());
|
|
3090
3090
|
}
|
|
3091
3091
|
const revokeM = /^\/api\/share\/([^/]+)$/.exec(p);
|
|
3092
3092
|
if (req.method === "DELETE" && revokeM) {
|
|
3093
|
-
const { revokeShare } = await import("./agentShare-
|
|
3093
|
+
const { revokeShare } = await import("./agentShare-BazKWNQQ.js");
|
|
3094
3094
|
const ok = revokeShare(decodeURIComponent(revokeM[1]));
|
|
3095
3095
|
return new Response(ok ? "revoked" : "no such share", { status: ok ? 200 : 404 });
|
|
3096
3096
|
}
|
|
@@ -3104,7 +3104,7 @@ Options:
|
|
|
3104
3104
|
const port = Number(body.port);
|
|
3105
3105
|
if (!Number.isInteger(port) || port < 1 || port > 65535) return new Response("valid port required", { status: 400 });
|
|
3106
3106
|
try {
|
|
3107
|
-
const { ensureExposure } = await import("./expose-
|
|
3107
|
+
const { ensureExposure } = await import("./expose-BU3f7VfC.js");
|
|
3108
3108
|
const h = await ensureExposure(port, body.relay);
|
|
3109
3109
|
return Response.json({
|
|
3110
3110
|
id: h.id,
|
|
@@ -3118,12 +3118,12 @@ Options:
|
|
|
3118
3118
|
}
|
|
3119
3119
|
}
|
|
3120
3120
|
if (req.method === "GET" && p === "/api/exposes") {
|
|
3121
|
-
const { listExposures } = await import("./expose-
|
|
3121
|
+
const { listExposures } = await import("./expose-BU3f7VfC.js");
|
|
3122
3122
|
return Response.json(listExposures());
|
|
3123
3123
|
}
|
|
3124
3124
|
const unexposeM = /^\/api\/expose\/(\d+)$/.exec(p);
|
|
3125
3125
|
if (req.method === "DELETE" && unexposeM) {
|
|
3126
|
-
const { stopExposure } = await import("./expose-
|
|
3126
|
+
const { stopExposure } = await import("./expose-BU3f7VfC.js");
|
|
3127
3127
|
const ok = stopExposure(Number(unexposeM[1]));
|
|
3128
3128
|
return new Response(ok ? "revoked" : "no such exposure", { status: ok ? 200 : 404 });
|
|
3129
3129
|
}
|
|
@@ -3392,7 +3392,7 @@ Options:
|
|
|
3392
3392
|
const shutdown = (resolve) => {
|
|
3393
3393
|
if (heartbeat) clearInterval(heartbeat);
|
|
3394
3394
|
closeShare?.();
|
|
3395
|
-
import("./agentShare-
|
|
3395
|
+
import("./agentShare-BazKWNQQ.js").then((m) => m.revokeAllShares()).catch(() => {});
|
|
3396
3396
|
server?.stop();
|
|
3397
3397
|
Promise.resolve(releaseHostLock?.()).catch(() => {}).then(resolve);
|
|
3398
3398
|
};
|
|
@@ -3405,4 +3405,4 @@ Options:
|
|
|
3405
3405
|
|
|
3406
3406
|
//#endregion
|
|
3407
3407
|
export { cmdServe, loadTokenReadOnly, mintScopedTermToken, resolveDaemonHttpBase, resolveLocalServeUrl };
|
|
3408
|
-
//# sourceMappingURL=serve-
|
|
3408
|
+
//# sourceMappingURL=serve-DyZpvp4C.js.map
|
|
@@ -32,7 +32,7 @@ async function cmdSetup(rest) {
|
|
|
32
32
|
if (!existsSync(abs)) process.stderr.write(` note: that directory doesn't exist yet — create it, or agents spawned there will fail\n`);
|
|
33
33
|
if (noShare) return 0;
|
|
34
34
|
process.stdout.write(`\nsharing this machine to agent-yes.com…\n`);
|
|
35
|
-
const { cmdServe } = await import("./serve-
|
|
35
|
+
const { cmdServe } = await import("./serve-DyZpvp4C.js");
|
|
36
36
|
return cmdServe([
|
|
37
37
|
"install",
|
|
38
38
|
"--share",
|
|
@@ -42,4 +42,4 @@ async function cmdSetup(rest) {
|
|
|
42
42
|
|
|
43
43
|
//#endregion
|
|
44
44
|
export { cmdSetup };
|
|
45
|
-
//# sourceMappingURL=setup-
|
|
45
|
+
//# sourceMappingURL=setup-JqletyDD.js.map
|
|
@@ -3,7 +3,7 @@ import { n as logger } from "./logger-CDIsZ-Pp.js";
|
|
|
3
3
|
import { t as agentYesHome } from "./agentYesHome-CtmsY6I-.js";
|
|
4
4
|
import { a as updateGlobalPidStatus, i as readGlobalPids } from "./globalPidIndex-D9DOSd-c.js";
|
|
5
5
|
import { a as recordOutbox, i as recordMessage, n as readMailbox, t as partyMatches } from "./messageLog-C-YIzhRj.js";
|
|
6
|
-
import { t as loadSharedCliDefaults } from "./configShared-
|
|
6
|
+
import { t as loadSharedCliDefaults } from "./configShared-IBbnn9b8.js";
|
|
7
7
|
import { n as isWebrtcSpec } from "./webrtcLink-BMYneHbu.js";
|
|
8
8
|
import { a as resolveRemoteSpec, i as readRemotes } from "./remotes-BxQnNxQv.js";
|
|
9
9
|
import ms from "ms";
|
|
@@ -1267,31 +1267,31 @@ async function runSubcommand(argv) {
|
|
|
1267
1267
|
return cmdCh(rest);
|
|
1268
1268
|
}
|
|
1269
1269
|
case "term": {
|
|
1270
|
-
const { cmdTerm } = await import("./terminal-
|
|
1270
|
+
const { cmdTerm } = await import("./terminal-BFq0mWdQ.js");
|
|
1271
1271
|
return cmdTerm(rest);
|
|
1272
1272
|
}
|
|
1273
1273
|
case "widget": {
|
|
1274
|
-
const { cmdWidget } = await import("./widget-
|
|
1274
|
+
const { cmdWidget } = await import("./widget-BXlREJHQ.js");
|
|
1275
1275
|
return cmdWidget(rest);
|
|
1276
1276
|
}
|
|
1277
1277
|
case "mint": {
|
|
1278
|
-
const { cmdMint } = await import("./widget-
|
|
1278
|
+
const { cmdMint } = await import("./widget-BXlREJHQ.js");
|
|
1279
1279
|
return cmdMint(rest);
|
|
1280
1280
|
}
|
|
1281
1281
|
case "serve": {
|
|
1282
|
-
const { cmdServe } = await import("./serve-
|
|
1282
|
+
const { cmdServe } = await import("./serve-DyZpvp4C.js");
|
|
1283
1283
|
return cmdServe(rest);
|
|
1284
1284
|
}
|
|
1285
1285
|
case "setup": {
|
|
1286
|
-
const { cmdSetup } = await import("./setup-
|
|
1286
|
+
const { cmdSetup } = await import("./setup-JqletyDD.js");
|
|
1287
1287
|
return cmdSetup(rest);
|
|
1288
1288
|
}
|
|
1289
1289
|
case "ws": {
|
|
1290
|
-
const { cmdWs } = await import("./ws-
|
|
1290
|
+
const { cmdWs } = await import("./ws-C6gfqPHM.js");
|
|
1291
1291
|
return cmdWs(rest);
|
|
1292
1292
|
}
|
|
1293
1293
|
case "schedule": {
|
|
1294
|
-
const { cmdSchedule } = await import("./schedule-
|
|
1294
|
+
const { cmdSchedule } = await import("./schedule-CWBHxQxk.js");
|
|
1295
1295
|
return cmdSchedule(rest);
|
|
1296
1296
|
}
|
|
1297
1297
|
case "remote": {
|
|
@@ -1299,11 +1299,11 @@ async function runSubcommand(argv) {
|
|
|
1299
1299
|
return cmdRemote(rest);
|
|
1300
1300
|
}
|
|
1301
1301
|
case "expose": {
|
|
1302
|
-
const { cmdExpose } = await import("./expose-
|
|
1302
|
+
const { cmdExpose } = await import("./expose-BU3f7VfC.js");
|
|
1303
1303
|
return cmdExpose(rest);
|
|
1304
1304
|
}
|
|
1305
1305
|
case "callback": {
|
|
1306
|
-
const { cmdCallback } = await import("./callback-
|
|
1306
|
+
const { cmdCallback } = await import("./callback-Csr8_-FG.js");
|
|
1307
1307
|
return cmdCallback(rest);
|
|
1308
1308
|
}
|
|
1309
1309
|
case "reap":
|
|
@@ -3706,7 +3706,7 @@ async function cmdAttach(rest) {
|
|
|
3706
3706
|
const winsizeDir = path.join(ayHome, "winsize");
|
|
3707
3707
|
await mkdir(winsizeDir, { recursive: true });
|
|
3708
3708
|
const winsizePath = path.join(winsizeDir, String(record.pid));
|
|
3709
|
-
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-
|
|
3709
|
+
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-DyZpvp4C.js");
|
|
3710
3710
|
const daemonBase = await resolveDaemonHttpBase().catch(() => null);
|
|
3711
3711
|
const daemonToken = daemonBase ? await loadTokenReadOnly().catch(() => null) ?? "" : "";
|
|
3712
3712
|
const capViewer = `attach:${process.pid}`;
|
|
@@ -4403,7 +4403,7 @@ async function cmdNotify(rest) {
|
|
|
4403
4403
|
}
|
|
4404
4404
|
const ensure = async () => {
|
|
4405
4405
|
if (!argv["ensure-daemon"]) return;
|
|
4406
|
-
const { ensureDaemon } = await import("./notifyDaemon-
|
|
4406
|
+
const { ensureDaemon } = await import("./notifyDaemon-DDPfMGlw.js");
|
|
4407
4407
|
await ensureDaemon().catch(() => null);
|
|
4408
4408
|
};
|
|
4409
4409
|
await heartbeatWatcher(parent, selfStartedAt);
|
|
@@ -4477,7 +4477,7 @@ async function cmdNotifyCursor(args) {
|
|
|
4477
4477
|
}
|
|
4478
4478
|
async function cmdNotifyd(rest) {
|
|
4479
4479
|
const sub = rest[0] ?? "status";
|
|
4480
|
-
const daemon = await import("./notifyDaemon-
|
|
4480
|
+
const daemon = await import("./notifyDaemon-DDPfMGlw.js");
|
|
4481
4481
|
switch (sub) {
|
|
4482
4482
|
case "run": return daemon.runDaemon();
|
|
4483
4483
|
case "once": return daemon.runDaemon({ once: true });
|
|
@@ -4504,4 +4504,4 @@ async function cmdNotifyd(rest) {
|
|
|
4504
4504
|
|
|
4505
4505
|
//#endregion
|
|
4506
4506
|
export { shouldStealLock as $, recentReadEdges as A, stdinActivityPath as B, listRecords as C, readNotes as D, readAgentPtysize as E, resolveReadWindow as F, writeToIpc as G, submitAndConfirm as H, resolveResumeArgs as I, hostId as J, appendEvent as K, restartHintLines as L, renderRawLog as M, renderRawLogLines as N, readPtysize as O, resolveOne as P, readInbox as Q, runSubcommand as R, lastStdinAt as S, menuSelectKeys as T, waitForLogQuiet as U, stopTipForCli as V, writeKeysPaced as W, listInboxParents as X, isTransientLockMkdirError as Y, liveWatchers as Z, isPidAlive as _, cmdHelp as a, isUnknownManagerToken as b, deriveLiveState as c, extractMenu as d, daemonLockDir as et, extractNeedsInput as f, isExitRequest as g, isAgentStuck as h, backoffWhileTyping as i, renderLogTailLines as j, recentMessageEdges as k, deriveLiveStatus as l, finalizedLines as m, READ_PAGE_DEFAULT as n, notifyDir as nt, controlCodeFromName as o, extractTaskCounts as p, gcInboxes as q, TYPING_WINDOW_MS as r, TYPING_BADGE as rt, cursorAbs as s, GRACEFUL_EXIT_COMMANDS as t, daemonLockOwnerPath as tt, extractBadges as u, isSlashCommand as v, matchKeyword as w, isUserTyping as x, isSubcommand as y, snapshotStatus as z };
|
|
4507
|
-
//# sourceMappingURL=subcommands-
|
|
4507
|
+
//# sourceMappingURL=subcommands-BL_SWFDC.js.map
|
|
@@ -2,8 +2,8 @@ import "./logger-CDIsZ-Pp.js";
|
|
|
2
2
|
import "./globalPidIndex-D9DOSd-c.js";
|
|
3
3
|
import "./messageLog-C-YIzhRj.js";
|
|
4
4
|
import "./e2e-CEIdJGZ7.js";
|
|
5
|
-
import "./configShared-
|
|
6
|
-
import { A as recentReadEdges, B as stdinActivityPath, C as listRecords, D as readNotes, E as readAgentPtysize, F as resolveReadWindow, G as writeToIpc, H as submitAndConfirm, I as resolveResumeArgs, L as restartHintLines, M as renderRawLog, N as renderRawLogLines, O as readPtysize, P as resolveOne, R as runSubcommand, S as lastStdinAt, T as menuSelectKeys, U as waitForLogQuiet, V as stopTipForCli, W as writeKeysPaced, _ as isPidAlive, a as cmdHelp, b as isUnknownManagerToken, c as deriveLiveState, d as extractMenu, f as extractNeedsInput, g as isExitRequest, h as isAgentStuck, i as backoffWhileTyping, j as renderLogTailLines, k as recentMessageEdges, l as deriveLiveStatus, m as finalizedLines, n as READ_PAGE_DEFAULT, o as controlCodeFromName, p as extractTaskCounts, r as TYPING_WINDOW_MS, s as cursorAbs, t as GRACEFUL_EXIT_COMMANDS, u as extractBadges, v as isSlashCommand, w as matchKeyword, x as isUserTyping, y as isSubcommand, z as snapshotStatus } from "./subcommands-
|
|
5
|
+
import "./configShared-IBbnn9b8.js";
|
|
6
|
+
import { A as recentReadEdges, B as stdinActivityPath, C as listRecords, D as readNotes, E as readAgentPtysize, F as resolveReadWindow, G as writeToIpc, H as submitAndConfirm, I as resolveResumeArgs, L as restartHintLines, M as renderRawLog, N as renderRawLogLines, O as readPtysize, P as resolveOne, R as runSubcommand, S as lastStdinAt, T as menuSelectKeys, U as waitForLogQuiet, V as stopTipForCli, W as writeKeysPaced, _ as isPidAlive, a as cmdHelp, b as isUnknownManagerToken, c as deriveLiveState, d as extractMenu, f as extractNeedsInput, g as isExitRequest, h as isAgentStuck, i as backoffWhileTyping, j as renderLogTailLines, k as recentMessageEdges, l as deriveLiveStatus, m as finalizedLines, n as READ_PAGE_DEFAULT, o as controlCodeFromName, p as extractTaskCounts, r as TYPING_WINDOW_MS, s as cursorAbs, t as GRACEFUL_EXIT_COMMANDS, u as extractBadges, v as isSlashCommand, w as matchKeyword, x as isUserTyping, y as isSubcommand, z as snapshotStatus } from "./subcommands-BL_SWFDC.js";
|
|
7
7
|
import "./webrtcLink-BMYneHbu.js";
|
|
8
8
|
import "./remotes-BxQnNxQv.js";
|
|
9
9
|
|
|
@@ -98,7 +98,7 @@ async function cmdTermMint(args) {
|
|
|
98
98
|
if (flags.ro && flags.interactive) throw new Error("--ro and --interactive are mutually exclusive");
|
|
99
99
|
const ttlSec = parseTtlSec(typeof flags.ttl === "string" ? flags.ttl : "15m");
|
|
100
100
|
const canSend = flags.interactive === true;
|
|
101
|
-
const { mintScopedTermToken } = await import("./serve-
|
|
101
|
+
const { mintScopedTermToken } = await import("./serve-DyZpvp4C.js");
|
|
102
102
|
const r = await mintScopedTermToken(pid, {
|
|
103
103
|
ttlSec,
|
|
104
104
|
canSend
|
|
@@ -135,4 +135,4 @@ async function cmdTerm(args) {
|
|
|
135
135
|
|
|
136
136
|
//#endregion
|
|
137
137
|
export { cmdTerm };
|
|
138
|
-
//# sourceMappingURL=terminal-
|
|
138
|
+
//# sourceMappingURL=terminal-BFq0mWdQ.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __esmMin, r as __exportAll } from "./chunk-cZBX9HZv.js";
|
|
2
2
|
import { n as logger, t as addTransport } from "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-D5ir842c.js";
|
|
4
4
|
import { t as agentYesHome } from "./agentYesHome-CtmsY6I-.js";
|
|
5
5
|
import { d as openStore, p as LIFECYCLES, x as removeControlCharacters } from "./todoAutomation-Buo457VO.js";
|
|
6
6
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-DBoONoM-.js";
|
|
@@ -22,10 +22,10 @@ import sflow from "sflow";
|
|
|
22
22
|
import xterm from "@xterm/headless";
|
|
23
23
|
import { createServer } from "net";
|
|
24
24
|
import { execSync as execSync$1 } from "node:child_process";
|
|
25
|
+
import { accessSync, constants as constants$1, existsSync as existsSync$1, statSync as statSync$1 } from "node:fs";
|
|
26
|
+
import path$1 from "node:path";
|
|
25
27
|
import os$1 from "node:os";
|
|
26
28
|
import { readFile as readFile$1 } from "node:fs/promises";
|
|
27
|
-
import path$1 from "node:path";
|
|
28
|
-
import { existsSync as existsSync$1 } from "node:fs";
|
|
29
29
|
|
|
30
30
|
//#region ts/xterm-proxy.ts
|
|
31
31
|
const { Terminal } = xterm;
|
|
@@ -749,6 +749,84 @@ async function applyAgentNice(pid, env = process.env) {
|
|
|
749
749
|
} catch {}
|
|
750
750
|
}
|
|
751
751
|
|
|
752
|
+
//#endregion
|
|
753
|
+
//#region ts/resolveBinary.ts
|
|
754
|
+
/**
|
|
755
|
+
* Decide whether a PATH candidate is a runnable program.
|
|
756
|
+
*
|
|
757
|
+
* Two checks, both load-bearing:
|
|
758
|
+
* - `isFile()` rejects directories and symlinks-to-directories (statSync FOLLOWS
|
|
759
|
+
* symlinks), which is the case that used to abort the whole process — see
|
|
760
|
+
* {@link resolveProgram}.
|
|
761
|
+
* - `access(X_OK)` rejects non-executables. Preferred over testing the raw mode
|
|
762
|
+
* bits because it accounts for the caller's uid/gid, and because Windows has
|
|
763
|
+
* no exec bit (there it succeeds for any existing file, which is correct —
|
|
764
|
+
* Windows executability is decided by PATHEXT, not by permissions).
|
|
765
|
+
*
|
|
766
|
+
* The Rust runtime's `resolve_program` makes the equivalent pair of checks with
|
|
767
|
+
* `metadata().is_file()` + mode & 0o111 (it only ever runs on unix).
|
|
768
|
+
*/
|
|
769
|
+
function isExecutableFile(candidate) {
|
|
770
|
+
try {
|
|
771
|
+
if (!statSync$1(candidate).isFile()) return false;
|
|
772
|
+
accessSync(candidate, constants$1.X_OK);
|
|
773
|
+
return true;
|
|
774
|
+
} catch {
|
|
775
|
+
return false;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Walk `rawPath` and return the first entry that names a runnable `bin`.
|
|
780
|
+
*
|
|
781
|
+
* Split out from {@link resolveProgram} (and taking an injectable `isExec`) so
|
|
782
|
+
* the resolution logic itself is exercised on every platform, including the
|
|
783
|
+
* Windows CI leg where {@link resolveProgram} short-circuits.
|
|
784
|
+
*
|
|
785
|
+
* @throws Error mentioning ENOENT / "command not found" when unresolvable, so
|
|
786
|
+
* `isCommandNotFoundError` in ts/core/spawner.ts still routes it to the
|
|
787
|
+
* auto-install path
|
|
788
|
+
*/
|
|
789
|
+
function resolveOnPath(bin, rawPath, isExec = isExecutableFile) {
|
|
790
|
+
if (bin.includes("/") || bin.includes(path$1.sep)) return bin;
|
|
791
|
+
for (const dir of rawPath.split(path$1.delimiter)) {
|
|
792
|
+
if (!dir) continue;
|
|
793
|
+
const candidate = path$1.join(dir, bin);
|
|
794
|
+
if (isExec(candidate)) return candidate;
|
|
795
|
+
}
|
|
796
|
+
throw new Error(`spawn ${bin} ENOENT: command not found in PATH (install it, or point \`binary:\` at a full path)`);
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Resolve a bare program name to an absolute path using POSIX PATH semantics.
|
|
800
|
+
*
|
|
801
|
+
* `portable-pty`'s `CommandBuilder` — reached from the TS runtime through
|
|
802
|
+
* `bun-pty`'s `librust_pty` — resolves a RELATIVE program name against the cwd
|
|
803
|
+
* FIRST and accepts the result if it merely `exists()`, with no regular-file or
|
|
804
|
+
* executable check (portable-pty 0.8.1, `cmdbuilder.rs::search_path`). So a cwd
|
|
805
|
+
* that happens to hold an entry named like the agent CLI — a `claude/` directory,
|
|
806
|
+
* a symlink to one, or a non-executable `claude` file — shadows the real binary.
|
|
807
|
+
* exec then fails inside the forked child, and portable-pty's `close_random_fds()`
|
|
808
|
+
* `pre_exec` hook has already closed every fd >= 3, including std's CLOEXEC
|
|
809
|
+
* error-report pipe. The child therefore can't hand the errno back to the parent
|
|
810
|
+
* and dies on std's `rtassert!(output.write(&bytes).is_ok())` with
|
|
811
|
+
* `fatal runtime error: assertion failed: output.write(&bytes).is_ok(), aborting`
|
|
812
|
+
* instead of surfacing a normal "not found / not executable" spawn error.
|
|
813
|
+
* See issue #138.
|
|
814
|
+
*
|
|
815
|
+
* POSIX is unambiguous that a command name containing no slash is looked up in
|
|
816
|
+
* PATH *only*, never in the cwd, so pre-resolving here is both the fix and the
|
|
817
|
+
* correct semantics.
|
|
818
|
+
*
|
|
819
|
+
* Mirrors `resolve_program` in rs/src/pty_spawner.rs — keep the two in sync.
|
|
820
|
+
*
|
|
821
|
+
* @param bin - Program name as configured (`cliConf.binary` or the CLI name)
|
|
822
|
+
* @param pathEnv - PATH the child will see; defaults to this process's PATH
|
|
823
|
+
* @returns Absolute path to the executable
|
|
824
|
+
*/
|
|
825
|
+
function resolveProgram(bin, pathEnv) {
|
|
826
|
+
if (process.platform === "win32") return bin;
|
|
827
|
+
return resolveOnPath(bin, pathEnv ?? process.env.PATH ?? "");
|
|
828
|
+
}
|
|
829
|
+
|
|
752
830
|
//#endregion
|
|
753
831
|
//#region ts/pty-fix.ts
|
|
754
832
|
var pty_fix_exports = /* @__PURE__ */ __exportAll({});
|
|
@@ -915,8 +993,9 @@ function spawnAgent(options) {
|
|
|
915
993
|
const { cli, cliConf, cliArgs, install, ptyOptions } = options;
|
|
916
994
|
const spawn = () => {
|
|
917
995
|
let [bin, ...args] = [...parseCommandString(cliConf?.binary || cli), ...cliArgs];
|
|
918
|
-
|
|
919
|
-
|
|
996
|
+
const program = resolveProgram(bin, ptyOptions.env.PATH);
|
|
997
|
+
logger.debug(`Spawning ${program} with args: ${JSON.stringify(args)}`);
|
|
998
|
+
const spawned = pty_default.spawn(program, args, ptyOptions);
|
|
920
999
|
logger.info(`[${cli}-yes] Spawned ${bin} with PID ${spawned.pid} (agent-yes v${getInstalledPackage().version})`);
|
|
921
1000
|
applyAgentNice(spawned.pid);
|
|
922
1001
|
return spawned;
|
|
@@ -1268,7 +1347,7 @@ async function answerAsk(projectRoot, taskId, answer) {
|
|
|
1268
1347
|
|
|
1269
1348
|
//#endregion
|
|
1270
1349
|
//#region ts/index.ts
|
|
1271
|
-
const config = await import("./agent-yes.config-
|
|
1350
|
+
const config = await import("./agent-yes.config-C8e9rNLW.js").then((mod) => mod.default || mod);
|
|
1272
1351
|
const CLIS_CONFIG = config.clis;
|
|
1273
1352
|
/**
|
|
1274
1353
|
* Main function to run agent-cli with automatic yes/no responses
|
|
@@ -1547,7 +1626,7 @@ async function agentYes({ cli, cliArgs = [], skipPermissions = false, prompt, ro
|
|
|
1547
1626
|
cwd: cwd ?? process.cwd(),
|
|
1548
1627
|
env: ptyEnv
|
|
1549
1628
|
};
|
|
1550
|
-
shell = pty_default.spawn(bin, args, restartPtyOptions);
|
|
1629
|
+
shell = pty_default.spawn(resolveProgram(bin, ptyEnv.PATH), args, restartPtyOptions);
|
|
1551
1630
|
shellWrite = (data) => shell.write(data);
|
|
1552
1631
|
try {
|
|
1553
1632
|
await pidStore.registerProcess({
|
|
@@ -1631,7 +1710,7 @@ async function agentYes({ cli, cliArgs = [], skipPermissions = false, prompt, ro
|
|
|
1631
1710
|
cwd: cwd ?? process.cwd(),
|
|
1632
1711
|
env: ptyEnv
|
|
1633
1712
|
};
|
|
1634
|
-
shell = pty_default.spawn(cli, restoreArgs, restorePtyOptions);
|
|
1713
|
+
shell = pty_default.spawn(resolveProgram(cli, ptyEnv.PATH), restoreArgs, restorePtyOptions);
|
|
1635
1714
|
shellWrite = (data) => shell.write(data);
|
|
1636
1715
|
try {
|
|
1637
1716
|
await pidStore.registerProcess({
|
|
@@ -2017,7 +2096,7 @@ async function agentYes({ cli, cliArgs = [], skipPermissions = false, prompt, ro
|
|
|
2017
2096
|
};
|
|
2018
2097
|
return {
|
|
2019
2098
|
cols: Math.max(20, process.stdout.columns),
|
|
2020
|
-
rows: process.stdout.rows
|
|
2099
|
+
rows: Math.max(4, process.stdout.rows)
|
|
2021
2100
|
};
|
|
2022
2101
|
}
|
|
2023
2102
|
}
|
|
@@ -2027,4 +2106,4 @@ function sleep(ms) {
|
|
|
2027
2106
|
|
|
2028
2107
|
//#endregion
|
|
2029
2108
|
export { hasTodoStore as a, AgentContext as c, answerAsk as i, CLAUDE_SESSION_PIN_ENV as l, agentYes as n, listAsks as o, config as r, listAsksForProject as s, CLIS_CONFIG as t };
|
|
2030
|
-
//# sourceMappingURL=ts-
|
|
2109
|
+
//# sourceMappingURL=ts-B51ZLoJC.js.map
|
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
|
|
8
8
|
//#region package.json
|
|
9
9
|
var name = "agent-yes";
|
|
10
|
-
var version = "1.246.
|
|
10
|
+
var version = "1.246.5";
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region ts/versionChecker.ts
|
|
@@ -215,4 +215,4 @@ async function displayVersion() {
|
|
|
215
215
|
|
|
216
216
|
//#endregion
|
|
217
217
|
export { versionString as i, displayVersion as n, getInstalledPackage as r, checkAndAutoUpdate as t };
|
|
218
|
-
//# sourceMappingURL=versionChecker-
|
|
218
|
+
//# sourceMappingURL=versionChecker-D5ir842c.js.map
|
|
@@ -28,7 +28,7 @@ function parseFlags(args, known) {
|
|
|
28
28
|
}
|
|
29
29
|
/** Resolve the local daemon base URL + token (flags override discovery). */
|
|
30
30
|
async function daemonTarget(flags) {
|
|
31
|
-
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-
|
|
31
|
+
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-DyZpvp4C.js");
|
|
32
32
|
const base = typeof flags.base === "string" ? flags.base : await resolveDaemonHttpBase();
|
|
33
33
|
if (!base) throw new Error("no running ay serve daemon found — start `ay serve` or pass --base <url> (e.g. http://127.0.0.1:PORT)");
|
|
34
34
|
const token = typeof flags.token === "string" ? flags.token : await loadTokenReadOnly() ?? "";
|
|
@@ -186,7 +186,7 @@ async function cmdMint(args) {
|
|
|
186
186
|
const bad = caps.filter((c) => !KNOWN_CAPS.has(c));
|
|
187
187
|
if (bad.length) throw new Error(`unknown cap(s): ${bad.join(", ")} (valid: ${[...KNOWN_CAPS].join(", ")})`);
|
|
188
188
|
const ttlSec = parseTtlSec(typeof flags.ttl === "string" ? flags.ttl : "15m");
|
|
189
|
-
const { mintScopedTermToken } = await import("./serve-
|
|
189
|
+
const { mintScopedTermToken } = await import("./serve-DyZpvp4C.js");
|
|
190
190
|
const r = await mintScopedTermToken(target, {
|
|
191
191
|
ttlSec,
|
|
192
192
|
caps
|
|
@@ -202,4 +202,4 @@ async function cmdMint(args) {
|
|
|
202
202
|
|
|
203
203
|
//#endregion
|
|
204
204
|
export { cmdMint, cmdWidget };
|
|
205
|
-
//# sourceMappingURL=widget-
|
|
205
|
+
//# sourceMappingURL=widget-BXlREJHQ.js.map
|
|
@@ -2,8 +2,8 @@ import "./logger-CDIsZ-Pp.js";
|
|
|
2
2
|
import "./globalPidIndex-D9DOSd-c.js";
|
|
3
3
|
import "./messageLog-C-YIzhRj.js";
|
|
4
4
|
import "./e2e-CEIdJGZ7.js";
|
|
5
|
-
import "./configShared-
|
|
6
|
-
import { C as listRecords } from "./subcommands-
|
|
5
|
+
import "./configShared-IBbnn9b8.js";
|
|
6
|
+
import { C as listRecords } from "./subcommands-BL_SWFDC.js";
|
|
7
7
|
import "./webrtcLink-BMYneHbu.js";
|
|
8
8
|
import "./remotes-BxQnNxQv.js";
|
|
9
9
|
import { i as getProvisionRoot } from "./workspaceConfig-DOHygA2x.js";
|
|
@@ -418,4 +418,4 @@ async function cmdWs(args) {
|
|
|
418
418
|
|
|
419
419
|
//#endregion
|
|
420
420
|
export { WS_JSON_SCHEMA, cmdWs, collectWorkspaces, isPathInside, loadProvision, workspaceStatus };
|
|
421
|
-
//# sourceMappingURL=ws-
|
|
421
|
+
//# sourceMappingURL=ws-C6gfqPHM.js.map
|
package/package.json
CHANGED
package/ts/index.ts
CHANGED
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
saveDeprecatedLogFile,
|
|
38
38
|
} from "./core/logging.ts";
|
|
39
39
|
import { spawnAgent } from "./core/spawner.ts";
|
|
40
|
+
import { resolveProgram } from "./resolveBinary.ts";
|
|
40
41
|
import { AgentContext } from "./core/context.ts";
|
|
41
42
|
import { createTerminatorStream } from "./core/streamHelpers.ts";
|
|
42
43
|
import { globalAgentRegistry } from "./agentRegistry.ts";
|
|
@@ -639,7 +640,8 @@ export default async function agentYes({
|
|
|
639
640
|
cwd: cwd ?? process.cwd(),
|
|
640
641
|
env: ptyEnv,
|
|
641
642
|
};
|
|
642
|
-
|
|
643
|
+
// Resolve via PATH so a cwd entry named like the CLI can't shadow it (#138).
|
|
644
|
+
shell = pty.spawn(resolveProgram(bin!, ptyEnv.PATH), args, restartPtyOptions);
|
|
643
645
|
shellWrite = (data: string) => shell.write(data);
|
|
644
646
|
// Register process in pidStore (non-blocking)
|
|
645
647
|
try {
|
|
@@ -745,7 +747,8 @@ export default async function agentYes({
|
|
|
745
747
|
cwd: cwd ?? process.cwd(),
|
|
746
748
|
env: ptyEnv,
|
|
747
749
|
};
|
|
748
|
-
|
|
750
|
+
// Resolve via PATH so a cwd entry named like the CLI can't shadow it (#138).
|
|
751
|
+
shell = pty.spawn(resolveProgram(cli, ptyEnv.PATH), restoreArgs, restorePtyOptions);
|
|
749
752
|
shellWrite = (data: string) => shell.write(data);
|
|
750
753
|
// Register process in pidStore (non-blocking)
|
|
751
754
|
try {
|
|
@@ -1417,7 +1420,11 @@ export default async function agentYes({
|
|
|
1417
1420
|
return {
|
|
1418
1421
|
// Enforce minimum 20 columns to avoid layout issues
|
|
1419
1422
|
cols: Math.max(20, process.stdout.columns),
|
|
1420
|
-
rows:
|
|
1423
|
+
// Clamp rows too: a tty whose winsize was never set (e.g. a pty created by
|
|
1424
|
+
// `script`/a daemon) reports 0, and bun-pty rejects rows <= 0 outright —
|
|
1425
|
+
// the spawn then fails with a bare "PTY spawn failed" and no clue why.
|
|
1426
|
+
// Mirrors get_terminal_size() in rs/src/pty_spawner.rs.
|
|
1427
|
+
rows: Math.max(4, process.stdout.rows),
|
|
1421
1428
|
};
|
|
1422
1429
|
}
|
|
1423
1430
|
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { chmodSync, mkdirSync, mkdtempSync, symlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { isExecutableFile, resolveOnPath, resolveProgram } from "./resolveBinary.ts";
|
|
6
|
+
|
|
7
|
+
// Issue #138: a cwd entry named like the agent CLI used to shadow the real
|
|
8
|
+
// binary inside portable-pty (reached via bun-pty), killing the forked child
|
|
9
|
+
// with "fatal runtime error: assertion failed: output.write(&bytes).is_ok()".
|
|
10
|
+
// Resolution must consult PATH only, and only accept runnable files.
|
|
11
|
+
|
|
12
|
+
const isWindows = process.platform === "win32";
|
|
13
|
+
const root = mkdtempSync(path.join(os.tmpdir(), "ay-resolve-"));
|
|
14
|
+
|
|
15
|
+
// resolveOnPath takes an injected probe, so these run on every platform —
|
|
16
|
+
// including the Windows CI leg, where resolveProgram itself short-circuits.
|
|
17
|
+
describe("resolveOnPath", () => {
|
|
18
|
+
const binDir = path.join(root, "bin");
|
|
19
|
+
const real = path.join(binDir, "ayfake");
|
|
20
|
+
// Only `real` is runnable; anything else the walk considers must be rejected.
|
|
21
|
+
const isExec = (candidate: string) => candidate === real;
|
|
22
|
+
|
|
23
|
+
it("returns the PATH entry that is actually runnable", () => {
|
|
24
|
+
expect(resolveOnPath("ayfake", binDir, isExec)).toBe(real);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("skips PATH entries that are not runnable and keeps walking", () => {
|
|
28
|
+
const decoys = [path.join(root, "a"), path.join(root, "b")].join(path.delimiter);
|
|
29
|
+
expect(resolveOnPath("ayfake", `${decoys}${path.delimiter}${binDir}`, isExec)).toBe(real);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("does not treat an empty PATH entry as the cwd", () => {
|
|
33
|
+
expect(resolveOnPath("ayfake", `${path.delimiter}${binDir}`, isExec)).toBe(real);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("passes through a name that already contains a separator", () => {
|
|
37
|
+
expect(resolveOnPath(`.${path.sep}ayfake`, binDir, isExec)).toBe(`.${path.sep}ayfake`);
|
|
38
|
+
expect(resolveOnPath("/usr/bin/env", binDir, isExec)).toBe("/usr/bin/env");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("throws a command-not-found error the auto-install path recognises", () => {
|
|
42
|
+
// ts/core/spawner.ts isCommandNotFoundError() keys off these substrings.
|
|
43
|
+
expect(() => resolveOnPath("ay-nope", binDir, isExec)).toThrow(/ENOENT/);
|
|
44
|
+
expect(() => resolveOnPath("ay-nope", binDir, isExec)).toThrow(/command not found/);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe("isExecutableFile", () => {
|
|
49
|
+
const dir = path.join(root, "probe");
|
|
50
|
+
mkdirSync(dir, { recursive: true });
|
|
51
|
+
|
|
52
|
+
it("accepts a runnable file", () => {
|
|
53
|
+
// Windows has no exec bit — access(X_OK) succeeds for any existing file
|
|
54
|
+
// there, which is the intended behaviour (PATHEXT decides executability).
|
|
55
|
+
const exe = path.join(dir, "ayexe");
|
|
56
|
+
writeFileSync(exe, "#!/bin/sh\n");
|
|
57
|
+
chmodSync(exe, 0o755);
|
|
58
|
+
expect(isExecutableFile(exe)).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("rejects a directory named like the CLI", () => {
|
|
62
|
+
const asDir = path.join(dir, "aydir");
|
|
63
|
+
mkdirSync(asDir, { recursive: true });
|
|
64
|
+
expect(isExecutableFile(asDir)).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("rejects a path that does not exist", () => {
|
|
68
|
+
expect(isExecutableFile(path.join(dir, "ay-missing"))).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Symlink creation needs elevation on Windows, and there is no exec bit there.
|
|
72
|
+
it.skipIf(isWindows)("rejects a symlink pointing at a directory", () => {
|
|
73
|
+
const target = path.join(dir, "aydir");
|
|
74
|
+
const link = path.join(dir, "aylink");
|
|
75
|
+
symlinkSync(target, link);
|
|
76
|
+
expect(isExecutableFile(link)).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it.skipIf(isWindows)("rejects a non-executable file", () => {
|
|
80
|
+
const dud = path.join(dir, "aydud");
|
|
81
|
+
writeFileSync(dud, "not executable");
|
|
82
|
+
chmodSync(dud, 0o644);
|
|
83
|
+
expect(isExecutableFile(dud)).toBe(false);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe("resolveProgram", () => {
|
|
88
|
+
// Both platform arms matter on both CI legs, so drive process.platform
|
|
89
|
+
// directly rather than skipping half the behaviour on each OS.
|
|
90
|
+
function withPlatform(value: string, fn: () => void) {
|
|
91
|
+
const original = Object.getOwnPropertyDescriptor(process, "platform")!;
|
|
92
|
+
Object.defineProperty(process, "platform", { ...original, value });
|
|
93
|
+
try {
|
|
94
|
+
fn();
|
|
95
|
+
} finally {
|
|
96
|
+
Object.defineProperty(process, "platform", original);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
it("passes the name through on Windows", () => {
|
|
101
|
+
// cmd.exe / ConPTY do their own PATH+PATHEXT resolution there.
|
|
102
|
+
withPlatform("win32", () => {
|
|
103
|
+
expect(resolveProgram("cmd", `C:${path.sep}nonexistent`)).toBe("cmd");
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("resolves against the real filesystem via PATH elsewhere", () => {
|
|
108
|
+
const binDir = path.join(root, "realbin");
|
|
109
|
+
mkdirSync(binDir, { recursive: true });
|
|
110
|
+
const exe = path.join(binDir, "ayreal");
|
|
111
|
+
writeFileSync(exe, "#!/bin/sh\n");
|
|
112
|
+
chmodSync(exe, 0o755);
|
|
113
|
+
// A same-named directory next to it must NOT win: only PATH is consulted.
|
|
114
|
+
mkdirSync(path.join(root, "ayreal"), { recursive: true });
|
|
115
|
+
withPlatform("linux", () => {
|
|
116
|
+
expect(resolveProgram("ayreal", binDir)).toBe(exe);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("falls back to the process PATH, and to none at all", () => {
|
|
121
|
+
const original = process.env.PATH;
|
|
122
|
+
try {
|
|
123
|
+
withPlatform("linux", () => {
|
|
124
|
+
expect(() => resolveProgram("ay-definitely-missing")).toThrow(/command not found/);
|
|
125
|
+
delete process.env.PATH;
|
|
126
|
+
expect(() => resolveProgram("ay-definitely-missing")).toThrow(/command not found/);
|
|
127
|
+
});
|
|
128
|
+
} finally {
|
|
129
|
+
if (original === undefined) delete process.env.PATH;
|
|
130
|
+
else process.env.PATH = original;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { accessSync, constants, statSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Decide whether a PATH candidate is a runnable program.
|
|
6
|
+
*
|
|
7
|
+
* Two checks, both load-bearing:
|
|
8
|
+
* - `isFile()` rejects directories and symlinks-to-directories (statSync FOLLOWS
|
|
9
|
+
* symlinks), which is the case that used to abort the whole process — see
|
|
10
|
+
* {@link resolveProgram}.
|
|
11
|
+
* - `access(X_OK)` rejects non-executables. Preferred over testing the raw mode
|
|
12
|
+
* bits because it accounts for the caller's uid/gid, and because Windows has
|
|
13
|
+
* no exec bit (there it succeeds for any existing file, which is correct —
|
|
14
|
+
* Windows executability is decided by PATHEXT, not by permissions).
|
|
15
|
+
*
|
|
16
|
+
* The Rust runtime's `resolve_program` makes the equivalent pair of checks with
|
|
17
|
+
* `metadata().is_file()` + mode & 0o111 (it only ever runs on unix).
|
|
18
|
+
*/
|
|
19
|
+
export function isExecutableFile(candidate: string): boolean {
|
|
20
|
+
try {
|
|
21
|
+
if (!statSync(candidate).isFile()) return false;
|
|
22
|
+
accessSync(candidate, constants.X_OK);
|
|
23
|
+
return true;
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Walk `rawPath` and return the first entry that names a runnable `bin`.
|
|
31
|
+
*
|
|
32
|
+
* Split out from {@link resolveProgram} (and taking an injectable `isExec`) so
|
|
33
|
+
* the resolution logic itself is exercised on every platform, including the
|
|
34
|
+
* Windows CI leg where {@link resolveProgram} short-circuits.
|
|
35
|
+
*
|
|
36
|
+
* @throws Error mentioning ENOENT / "command not found" when unresolvable, so
|
|
37
|
+
* `isCommandNotFoundError` in ts/core/spawner.ts still routes it to the
|
|
38
|
+
* auto-install path
|
|
39
|
+
*/
|
|
40
|
+
export function resolveOnPath(
|
|
41
|
+
bin: string,
|
|
42
|
+
rawPath: string,
|
|
43
|
+
isExec: (candidate: string) => boolean = isExecutableFile,
|
|
44
|
+
): string {
|
|
45
|
+
// A name that already carries a separator is a path, not a PATH lookup —
|
|
46
|
+
// `./claude` must keep meaning the one in this directory.
|
|
47
|
+
if (bin.includes("/") || bin.includes(path.sep)) return bin;
|
|
48
|
+
|
|
49
|
+
for (const dir of rawPath.split(path.delimiter)) {
|
|
50
|
+
// Empty PATH entries mean "the cwd" under a legacy POSIX allowance.
|
|
51
|
+
// Honouring that would reintroduce exactly the shadowing described in
|
|
52
|
+
// resolveProgram, so skip them.
|
|
53
|
+
if (!dir) continue;
|
|
54
|
+
const candidate = path.join(dir, bin);
|
|
55
|
+
if (isExec(candidate)) return candidate;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
throw new Error(
|
|
59
|
+
`spawn ${bin} ENOENT: command not found in PATH (install it, or point \`binary:\` at a full path)`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolve a bare program name to an absolute path using POSIX PATH semantics.
|
|
65
|
+
*
|
|
66
|
+
* `portable-pty`'s `CommandBuilder` — reached from the TS runtime through
|
|
67
|
+
* `bun-pty`'s `librust_pty` — resolves a RELATIVE program name against the cwd
|
|
68
|
+
* FIRST and accepts the result if it merely `exists()`, with no regular-file or
|
|
69
|
+
* executable check (portable-pty 0.8.1, `cmdbuilder.rs::search_path`). So a cwd
|
|
70
|
+
* that happens to hold an entry named like the agent CLI — a `claude/` directory,
|
|
71
|
+
* a symlink to one, or a non-executable `claude` file — shadows the real binary.
|
|
72
|
+
* exec then fails inside the forked child, and portable-pty's `close_random_fds()`
|
|
73
|
+
* `pre_exec` hook has already closed every fd >= 3, including std's CLOEXEC
|
|
74
|
+
* error-report pipe. The child therefore can't hand the errno back to the parent
|
|
75
|
+
* and dies on std's `rtassert!(output.write(&bytes).is_ok())` with
|
|
76
|
+
* `fatal runtime error: assertion failed: output.write(&bytes).is_ok(), aborting`
|
|
77
|
+
* instead of surfacing a normal "not found / not executable" spawn error.
|
|
78
|
+
* See issue #138.
|
|
79
|
+
*
|
|
80
|
+
* POSIX is unambiguous that a command name containing no slash is looked up in
|
|
81
|
+
* PATH *only*, never in the cwd, so pre-resolving here is both the fix and the
|
|
82
|
+
* correct semantics.
|
|
83
|
+
*
|
|
84
|
+
* Mirrors `resolve_program` in rs/src/pty_spawner.rs — keep the two in sync.
|
|
85
|
+
*
|
|
86
|
+
* @param bin - Program name as configured (`cliConf.binary` or the CLI name)
|
|
87
|
+
* @param pathEnv - PATH the child will see; defaults to this process's PATH
|
|
88
|
+
* @returns Absolute path to the executable
|
|
89
|
+
*/
|
|
90
|
+
export function resolveProgram(bin: string, pathEnv?: string): string {
|
|
91
|
+
// Windows spawns through cmd.exe / ConPTY, which apply their own PATH+PATHEXT
|
|
92
|
+
// resolution — the cwd-shadowing bug is unix-specific, so pass through.
|
|
93
|
+
if (process.platform === "win32") return bin;
|
|
94
|
+
return resolveOnPath(bin, pathEnv ?? process.env.PATH ?? "");
|
|
95
|
+
}
|