claude-yes 1.300.2 → 1.300.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/dist/{SUPPORTED_CLIS-Dxw9H99T.js → SUPPORTED_CLIS-DMQwDMfP.js} +2 -2
- package/dist/{SUPPORTED_CLIS-BX5_erb1.js → SUPPORTED_CLIS-jZFHwXHE.js} +3 -3
- package/dist/{agentShare-C178Fz-8.js → agentShare-BASAaPka.js} +2 -2
- package/dist/{callback-DDFaB2fy.js → callback-BnkktH-1.js} +2 -2
- package/dist/{callback-DEhpIaK7.js → callback-ZCnvZXqD.js} +3 -3
- package/dist/cli.js +5 -5
- package/dist/{cmdPs-C87Caduf.js → cmdPs-BM2Srp1S.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/{notifyDaemon-NxyVEhVq.js → notifyDaemon-BtbS2lBT.js} +2 -2
- package/dist/{parentPingLoop-zAmYgESx.js → parentPingLoop-rLQBc0G5.js} +2 -2
- package/dist/{rustBinary-FjEdM28b.js → rustBinary-DHWoCbGC.js} +2 -2
- package/dist/{rustBinary-CicmJTei.js → rustBinary-Lzt3pVh_.js} +2 -2
- package/dist/{schedule-DPiovnJr.js → schedule-D45Ja0h0.js} +4 -4
- package/dist/{serve-C_9bMH27.js → serve-BPl5u9Mw.js} +18 -18
- package/dist/{setup-DVMeGj5u.js → setup-IbpYJdQm.js} +2 -2
- package/dist/{shareCmd-cNNr7i3a.js → shareCmd-8EPCR-WP.js} +3 -3
- package/dist/{subcommands-CzSrhEYG.js → subcommands-BusIzjLq.js} +143 -35
- package/dist/subcommands-CQINL3Uv.js +13 -0
- package/dist/{terminal-MTNQuGD5.js → terminal-Del-sL1m.js} +2 -2
- package/dist/trayApp-2yKAAVa7.js +5 -0
- package/dist/{trayApp-DO3YALy1.js → trayApp-Tp8PsCsA.js} +2 -2
- package/dist/{ts-C8dvu_cD.js → ts-BFVAQ0Zs.js} +3 -3
- package/dist/{versionChecker-Bmtx6fPv.js → versionChecker-DUIQTHWC.js} +2 -2
- package/dist/{widget-BCrKF9Vw.js → widget-E8nWj1fn.js} +3 -3
- package/dist/{ws-BTXQauqi.js → ws-CMkJamuh.js} +2 -2
- package/dist/{ws-D1ggWZ_I.js → ws-D9EBcPei.js} +2 -2
- package/package.json +1 -1
- package/ts/composerGuard.spec.ts +34 -0
- package/ts/composerGuard.ts +38 -1
- package/ts/subcommands.spec.ts +95 -1
- package/ts/subcommands.ts +105 -16
- package/dist/subcommands-2tF2Psrc.js +0 -13
- package/dist/trayApp-Cx9ktCQ-.js +0 -5
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-BFVAQ0Zs.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-DMQwDMfP.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./versionChecker-
|
|
3
|
-
import "./ts-
|
|
2
|
+
import "./versionChecker-DUIQTHWC.js";
|
|
3
|
+
import "./ts-BFVAQ0Zs.js";
|
|
4
4
|
import "./todoAutomation-CbVVS4re.js";
|
|
5
5
|
import "./JsonlStore-BqF7AQ6E.js";
|
|
6
6
|
import "./globalPidIndex-CRH9L9tn.js";
|
|
7
7
|
import "./pidStore-DXWqzTSz.js";
|
|
8
8
|
import "./messageLog-Brx3w6zT.js";
|
|
9
9
|
import "./todoStore-DF6vxHgV.js";
|
|
10
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
10
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DMQwDMfP.js";
|
|
11
11
|
|
|
12
12
|
export { SUPPORTED_CLIS };
|
|
@@ -5,7 +5,7 @@ import "./pidStore-DXWqzTSz.js";
|
|
|
5
5
|
import "./messageLog-Brx3w6zT.js";
|
|
6
6
|
import "./e2e-z1xpwSAg.js";
|
|
7
7
|
import "./configShared-DKTgiz7K.js";
|
|
8
|
-
import {
|
|
8
|
+
import { nt as resolveOne } from "./subcommands-BusIzjLq.js";
|
|
9
9
|
import "./notifyStore-2SWKGwZI.js";
|
|
10
10
|
import "./webrtcLink-DFRyWNMs.js";
|
|
11
11
|
import "./remotes-B4v0Nowo.js";
|
|
@@ -232,4 +232,4 @@ function transformEvent(rawEvent, agentId, forwarded) {
|
|
|
232
232
|
|
|
233
233
|
//#endregion
|
|
234
234
|
export { createScopedShare, listShares, revokeAllShares, revokeShare };
|
|
235
|
-
//# sourceMappingURL=agentShare-
|
|
235
|
+
//# sourceMappingURL=agentShare-BASAaPka.js.map
|
|
@@ -5,11 +5,11 @@ import "./pidStore-DXWqzTSz.js";
|
|
|
5
5
|
import "./messageLog-Brx3w6zT.js";
|
|
6
6
|
import "./e2e-z1xpwSAg.js";
|
|
7
7
|
import "./configShared-DKTgiz7K.js";
|
|
8
|
-
import "./subcommands-
|
|
8
|
+
import "./subcommands-BusIzjLq.js";
|
|
9
9
|
import "./notifyStore-2SWKGwZI.js";
|
|
10
10
|
import "./webrtcLink-DFRyWNMs.js";
|
|
11
11
|
import "./remotes-B4v0Nowo.js";
|
|
12
12
|
import "./callbackCore-Bl2gGcxg.js";
|
|
13
|
-
import { i as loadOrCreateCallbackSecret, n as isCallbackRevoked, r as loadCallbackSecretReadOnly, t as cmdCallback } from "./callback-
|
|
13
|
+
import { i as loadOrCreateCallbackSecret, n as isCallbackRevoked, r as loadCallbackSecretReadOnly, t as cmdCallback } from "./callback-ZCnvZXqD.js";
|
|
14
14
|
|
|
15
15
|
export { cmdCallback };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as agentYesHome } from "./agentYesHome-BNtn19J4.js";
|
|
2
|
-
import {
|
|
2
|
+
import { nt as resolveOne } from "./subcommands-BusIzjLq.js";
|
|
3
3
|
import { a as mintCapability, o as parseExpires } from "./callbackCore-Bl2gGcxg.js";
|
|
4
4
|
import { randomBytes } from "node:crypto";
|
|
5
5
|
import { chmodSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
@@ -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-BPl5u9Mw.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-ZCnvZXqD.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-zdFbz1ST.js";
|
|
3
3
|
import { n as logger } from "./logger-CDIsZ-Pp.js";
|
|
4
|
-
import { a as versionString, r as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-
|
|
5
|
-
import { d as getRustBinary } from "./rustBinary-
|
|
4
|
+
import { a as versionString, r as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-DUIQTHWC.js";
|
|
5
|
+
import { d as getRustBinary } from "./rustBinary-DHWoCbGC.js";
|
|
6
6
|
import { argv } from "process";
|
|
7
7
|
import { spawn } from "child_process";
|
|
8
8
|
import ms from "ms";
|
|
@@ -295,7 +295,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
295
295
|
const rawArg = process.argv[2];
|
|
296
296
|
const managerCommands = !invokedCliName(process.argv);
|
|
297
297
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
298
|
-
const { isSubcommand, runSubcommand, cmdHelp, isUnknownManagerToken, isBareManagerInvocation } = await import("./subcommands-
|
|
298
|
+
const { isSubcommand, runSubcommand, cmdHelp, isUnknownManagerToken, isBareManagerInvocation } = await import("./subcommands-CQINL3Uv.js");
|
|
299
299
|
if (isHelpFlag && process.argv.length === 3) {
|
|
300
300
|
await cmdHelp(managerCommands);
|
|
301
301
|
process.exit(0);
|
|
@@ -309,7 +309,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
309
309
|
process.exit(code ?? 0);
|
|
310
310
|
}
|
|
311
311
|
{
|
|
312
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
312
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-jZFHwXHE.js");
|
|
313
313
|
if (isUnknownManagerToken(rawArg, managerCommands, SUPPORTED_CLIS)) {
|
|
314
314
|
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`);
|
|
315
315
|
process.exit(1);
|
|
@@ -360,7 +360,7 @@ if (config.useRust) {
|
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
362
|
if (rustBinary) {
|
|
363
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
363
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-jZFHwXHE.js");
|
|
364
364
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
365
365
|
if (config.verbose) {
|
|
366
366
|
console.log(`[rust] Using binary: ${rustBinary}`);
|
|
@@ -5,7 +5,7 @@ import "./pidStore-DXWqzTSz.js";
|
|
|
5
5
|
import "./messageLog-Brx3w6zT.js";
|
|
6
6
|
import "./e2e-z1xpwSAg.js";
|
|
7
7
|
import "./configShared-DKTgiz7K.js";
|
|
8
|
-
import {
|
|
8
|
+
import { V as listRecords, bt as flattenForest, v as deriveLiveState, yt as buildAgentForest } from "./subcommands-BusIzjLq.js";
|
|
9
9
|
import "./notifyStore-2SWKGwZI.js";
|
|
10
10
|
import "./webrtcLink-DFRyWNMs.js";
|
|
11
11
|
import "./remotes-B4v0Nowo.js";
|
|
@@ -330,4 +330,4 @@ function readPpidSync(pid) {
|
|
|
330
330
|
|
|
331
331
|
//#endregion
|
|
332
332
|
export { cmdPs };
|
|
333
|
-
//# sourceMappingURL=cmdPs-
|
|
333
|
+
//# sourceMappingURL=cmdPs-BM2Srp1S.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, i as answerAsk, l as AgentContext, n as agentYes, o as listAsks, r as config, s as listAsksForProject, t as CLIS_CONFIG } from "./ts-
|
|
2
|
+
import "./versionChecker-DUIQTHWC.js";
|
|
3
|
+
import { a as hasTodoStore, i as answerAsk, l as AgentContext, n as agentYes, o as listAsks, r as config, s as listAsksForProject, t as CLIS_CONFIG } from "./ts-BFVAQ0Zs.js";
|
|
4
4
|
import { a as renderTree, c as describeBlock, i as renderDigest, l as monitorHint, o as unblockedTasks, r as openBlockers, t as reconcileTodos, u as removeControlCharacters } from "./todoAutomation-CbVVS4re.js";
|
|
5
5
|
import "./JsonlStore-BqF7AQ6E.js";
|
|
6
6
|
import "./globalPidIndex-CRH9L9tn.js";
|
|
@@ -5,7 +5,7 @@ import "./pidStore-DXWqzTSz.js";
|
|
|
5
5
|
import "./messageLog-Brx3w6zT.js";
|
|
6
6
|
import "./e2e-z1xpwSAg.js";
|
|
7
7
|
import "./configShared-DKTgiz7K.js";
|
|
8
|
-
import {
|
|
8
|
+
import { $ as renderLogTailLines, N as isPidAlive, V as listRecords, v as deriveLiveState } from "./subcommands-BusIzjLq.js";
|
|
9
9
|
import { f as readInbox, g as daemonLockOwnerPath, h as daemonLockDir, i as gcInboxes, l as listInboxParents, m as shouldStealLock, n as appendEvent, s as hostId, u as liveWatchers, x as notifyDir } from "./notifyStore-2SWKGwZI.js";
|
|
10
10
|
import "./webrtcLink-DFRyWNMs.js";
|
|
11
11
|
import "./remotes-B4v0Nowo.js";
|
|
@@ -879,4 +879,4 @@ async function ensureDaemon() {
|
|
|
879
879
|
|
|
880
880
|
//#endregion
|
|
881
881
|
export { daemonStatus, ensureDaemon, requestDaemonStop, runDaemon };
|
|
882
|
-
//# sourceMappingURL=notifyDaemon-
|
|
882
|
+
//# sourceMappingURL=notifyDaemon-BtbS2lBT.js.map
|
|
@@ -338,7 +338,7 @@ async function isParentWatching(parentWrapperPid, parentAgentPid, selfAgentPid,
|
|
|
338
338
|
logger.debug("[parent-ping] watcher lookup failed:", error);
|
|
339
339
|
}
|
|
340
340
|
try {
|
|
341
|
-
const { lastReadAt, READ_WINDOW_MS } = await import("./subcommands-
|
|
341
|
+
const { lastReadAt, READ_WINDOW_MS } = await import("./subcommands-CQINL3Uv.js");
|
|
342
342
|
const last = await lastReadAt(`agent:${parentAgentPid}`, selfAgentPid);
|
|
343
343
|
if (last !== null && now - last <= READ_WINDOW_MS) return true;
|
|
344
344
|
} catch (error) {
|
|
@@ -466,4 +466,4 @@ function startParentPingLoop(opts) {
|
|
|
466
466
|
|
|
467
467
|
//#endregion
|
|
468
468
|
export { startParentPingLoop };
|
|
469
|
-
//# sourceMappingURL=parentPingLoop-
|
|
469
|
+
//# sourceMappingURL=parentPingLoop-rLQBc0G5.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as getInstalledPackage, n as compareVersions } from "./versionChecker-
|
|
1
|
+
import { i as getInstalledPackage, n as compareVersions } from "./versionChecker-DUIQTHWC.js";
|
|
2
2
|
import { execFileSync } from "child_process";
|
|
3
3
|
import { existsSync, mkdirSync, readdirSync, rmSync, statSync, unlinkSync } from "fs";
|
|
4
4
|
import { chmod, copyFile } from "fs/promises";
|
|
@@ -371,4 +371,4 @@ async function getRustBinary(options = {}) {
|
|
|
371
371
|
|
|
372
372
|
//#endregion
|
|
373
373
|
export { findSpawnHiddenLauncher as a, getBinDir as c, getRustBinary as d, hasValidMacSignature as f, findRustBinary as i, getBinaryName as l, downloadBinary as n, findTrayLauncher as o, findAyrsBinary as r, gcOldBinaryDirs as s, devBuildInfo as t, getDownloadUrl as u };
|
|
374
|
-
//# sourceMappingURL=rustBinary-
|
|
374
|
+
//# sourceMappingURL=rustBinary-DHWoCbGC.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./versionChecker-
|
|
2
|
-
import { a as findSpawnHiddenLauncher, c as getBinDir, d as getRustBinary, f as hasValidMacSignature, i as findRustBinary, l as getBinaryName, n as downloadBinary, o as findTrayLauncher, r as findAyrsBinary, s as gcOldBinaryDirs, t as devBuildInfo, u as getDownloadUrl } from "./rustBinary-
|
|
1
|
+
import "./versionChecker-DUIQTHWC.js";
|
|
2
|
+
import { a as findSpawnHiddenLauncher, c as getBinDir, d as getRustBinary, f as hasValidMacSignature, i as findRustBinary, l as getBinaryName, n as downloadBinary, o as findTrayLauncher, r as findAyrsBinary, s as gcOldBinaryDirs, t as devBuildInfo, u as getDownloadUrl } from "./rustBinary-DHWoCbGC.js";
|
|
3
3
|
|
|
4
4
|
export { findAyrsBinary, gcOldBinaryDirs };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./versionChecker-
|
|
3
|
-
import "./ts-
|
|
2
|
+
import "./versionChecker-DUIQTHWC.js";
|
|
3
|
+
import "./ts-BFVAQ0Zs.js";
|
|
4
4
|
import "./todoAutomation-CbVVS4re.js";
|
|
5
5
|
import "./JsonlStore-BqF7AQ6E.js";
|
|
6
6
|
import "./globalPidIndex-CRH9L9tn.js";
|
|
7
7
|
import "./pidStore-DXWqzTSz.js";
|
|
8
8
|
import "./messageLog-Brx3w6zT.js";
|
|
9
9
|
import "./todoStore-DF6vxHgV.js";
|
|
10
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
10
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DMQwDMfP.js";
|
|
11
11
|
import { f as resolveSpawnCwd } from "./workspaceConfig-DTvPtr5j.js";
|
|
12
12
|
import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-CipjIwfO.js";
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
@@ -154,4 +154,4 @@ async function cmdSchedule(rest) {
|
|
|
154
154
|
|
|
155
155
|
//#endregion
|
|
156
156
|
export { cmdSchedule };
|
|
157
|
-
//# sourceMappingURL=schedule-
|
|
157
|
+
//# sourceMappingURL=schedule-D45Ja0h0.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import { i as getInstalledPackage } from "./versionChecker-
|
|
3
|
-
import { a as findSpawnHiddenLauncher } from "./rustBinary-
|
|
4
|
-
import { c as permissionBadge, i as answerAsk, o as listAsks, u as CLAUDE_SESSION_PIN_ENV } from "./ts-
|
|
2
|
+
import { i as getInstalledPackage } from "./versionChecker-DUIQTHWC.js";
|
|
3
|
+
import { a as findSpawnHiddenLauncher } from "./rustBinary-DHWoCbGC.js";
|
|
4
|
+
import { c as permissionBadge, i as answerAsk, o as listAsks, u as CLAUDE_SESSION_PIN_ENV } from "./ts-BFVAQ0Zs.js";
|
|
5
5
|
import { t as agentYesHome$1 } from "./agentYesHome-BNtn19J4.js";
|
|
6
6
|
import { u as removeControlCharacters } from "./todoAutomation-CbVVS4re.js";
|
|
7
7
|
import "./JsonlStore-BqF7AQ6E.js";
|
|
@@ -12,19 +12,19 @@ import { t as pgidForWrapper } from "./reaper-UimuuTfO.js";
|
|
|
12
12
|
import "./todoStore-DF6vxHgV.js";
|
|
13
13
|
import "./e2e-z1xpwSAg.js";
|
|
14
14
|
import "./configShared-DKTgiz7K.js";
|
|
15
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
16
|
-
import { $ as
|
|
15
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DMQwDMfP.js";
|
|
16
|
+
import { $ as renderLogTailLines, C as extractBadges, E as extractTaskCounts, J as readLogForRender, P as isSlashCommand, Q as recentReadEdges, R as isUserTyping, T as extractNeedsInput, V as listRecords, X as readPtysize, Y as readNotes, Z as recentMessageEdges, _t as shouldFramePaste, ct as snapshotStatus, et as renderRawLog, f as cliDefaults, gt as framePaste, h as controlCodeFromName, ht as withIpcLock, mt as writeToIpc, nt as resolveOne, tt as renderRawLogLines, vt as TYPING_BADGE, y as deriveLiveStatus } from "./subcommands-BusIzjLq.js";
|
|
17
17
|
import { c as isTransientLockMkdirError } from "./notifyStore-2SWKGwZI.js";
|
|
18
18
|
import { i as toWebrtcUrl, n as isWebrtcSpec } from "./webrtcLink-DFRyWNMs.js";
|
|
19
19
|
import "./remotes-B4v0Nowo.js";
|
|
20
20
|
import { i as frameVisitorMessage, s as verifyCapability, t as MAX_CALLBACK_MSG_BYTES } from "./callbackCore-Bl2gGcxg.js";
|
|
21
|
-
import { n as isCallbackRevoked, r as loadCallbackSecretReadOnly } from "./callback-
|
|
21
|
+
import { n as isCallbackRevoked, r as loadCallbackSecretReadOnly } from "./callback-ZCnvZXqD.js";
|
|
22
22
|
import { n as sampleTrees } from "./procStats-CyD8h5nx.js";
|
|
23
23
|
import { a as getProvisionRoot, d as isProvisionAllowed, f as resolveSpawnCwd, i as getProvisionHook, l as hasProvisionHook, o as getSpawnHook, t as allowsSkipPermissions, u as hasSpawnHook } from "./workspaceConfig-DTvPtr5j.js";
|
|
24
24
|
import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-CipjIwfO.js";
|
|
25
|
-
import { i as importProvisionModule } from "./ws-
|
|
25
|
+
import { i as importProvisionModule } from "./ws-D9EBcPei.js";
|
|
26
26
|
import { r as spawnRejectionReason } from "./spawnGate-YpHopveO.js";
|
|
27
|
-
import { i as launchTray } from "./trayApp-
|
|
27
|
+
import { i as launchTray } from "./trayApp-Tp8PsCsA.js";
|
|
28
28
|
import yargs from "yargs";
|
|
29
29
|
import { appendFile, mkdir, open, readFile, readdir, rename, rm, stat, unlink, writeFile } from "fs/promises";
|
|
30
30
|
import { arch, cpus, freemem, homedir, hostname, loadavg, platform, totalmem, uptime, userInfo } from "os";
|
|
@@ -1704,7 +1704,7 @@ Options:
|
|
|
1704
1704
|
const { planRustServe } = await import("./serveRust-DDQiZmMf.js");
|
|
1705
1705
|
const plan = planRustServe(rest);
|
|
1706
1706
|
if (plan.kind === "rust") {
|
|
1707
|
-
const { findAyrsBinary } = await import("./rustBinary-
|
|
1707
|
+
const { findAyrsBinary } = await import("./rustBinary-Lzt3pVh_.js");
|
|
1708
1708
|
const ayrs = findAyrsBinary();
|
|
1709
1709
|
if (ayrs) return runAyrsServe(ayrs, plan.argv);
|
|
1710
1710
|
process.stderr.write("ay serve: ayrs binary not found — running the TypeScript server (bun run build:rs, or reinstall, to get the Rust daemon)\n");
|
|
@@ -2679,7 +2679,7 @@ Options:
|
|
|
2679
2679
|
}
|
|
2680
2680
|
});
|
|
2681
2681
|
if (req.method === "GET" && p === "/api/ws") {
|
|
2682
|
-
const ws = await import("./ws-
|
|
2682
|
+
const ws = await import("./ws-CMkJamuh.js");
|
|
2683
2683
|
try {
|
|
2684
2684
|
await ws.loadProvision();
|
|
2685
2685
|
} catch (e) {
|
|
@@ -2699,7 +2699,7 @@ Options:
|
|
|
2699
2699
|
if (req.method === "GET" && p === "/api/ws/status") {
|
|
2700
2700
|
const dirRaw = url.searchParams.get("path");
|
|
2701
2701
|
if (!dirRaw) return new Response("missing ?path=<workspace dir>", { status: 400 });
|
|
2702
|
-
const ws = await import("./ws-
|
|
2702
|
+
const ws = await import("./ws-CMkJamuh.js");
|
|
2703
2703
|
let prov;
|
|
2704
2704
|
try {
|
|
2705
2705
|
prov = await ws.loadProvision();
|
|
@@ -2721,7 +2721,7 @@ Options:
|
|
|
2721
2721
|
}
|
|
2722
2722
|
}
|
|
2723
2723
|
if (req.method === "GET" && p === "/api/ws/repos") {
|
|
2724
|
-
const ws = await import("./ws-
|
|
2724
|
+
const ws = await import("./ws-CMkJamuh.js");
|
|
2725
2725
|
try {
|
|
2726
2726
|
await ws.loadProvision();
|
|
2727
2727
|
} catch (e) {
|
|
@@ -2802,7 +2802,7 @@ Options:
|
|
|
2802
2802
|
const m = /^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/.exec(repoParam);
|
|
2803
2803
|
if (!m || m[1] === "." || m[1] === ".." || m[2] === "." || m[2] === "..") return new Response("missing/invalid ?repo=<owner>/<repo>", { status: 400 });
|
|
2804
2804
|
const [, owner, repo] = m;
|
|
2805
|
-
const ws = await import("./ws-
|
|
2805
|
+
const ws = await import("./ws-CMkJamuh.js");
|
|
2806
2806
|
let prov;
|
|
2807
2807
|
try {
|
|
2808
2808
|
prov = await ws.loadProvision();
|
|
@@ -3720,7 +3720,7 @@ Options:
|
|
|
3720
3720
|
const perm = body.perm ?? "r";
|
|
3721
3721
|
if (perm !== "r" && perm !== "rw") return new Response(`invalid perm ${perm} (want r or rw)`, { status: 400 });
|
|
3722
3722
|
try {
|
|
3723
|
-
const { createScopedShare } = await import("./agentShare-
|
|
3723
|
+
const { createScopedShare } = await import("./agentShare-BASAaPka.js");
|
|
3724
3724
|
const share = await createScopedShare({
|
|
3725
3725
|
agent: body.agent,
|
|
3726
3726
|
perm,
|
|
@@ -3735,12 +3735,12 @@ Options:
|
|
|
3735
3735
|
}
|
|
3736
3736
|
}
|
|
3737
3737
|
if (req.method === "GET" && p === "/api/shares") {
|
|
3738
|
-
const { listShares } = await import("./agentShare-
|
|
3738
|
+
const { listShares } = await import("./agentShare-BASAaPka.js");
|
|
3739
3739
|
return Response.json(listShares());
|
|
3740
3740
|
}
|
|
3741
3741
|
const revokeM = /^\/api\/share\/([^/]+)$/.exec(p);
|
|
3742
3742
|
if (req.method === "DELETE" && revokeM) {
|
|
3743
|
-
const { revokeShare } = await import("./agentShare-
|
|
3743
|
+
const { revokeShare } = await import("./agentShare-BASAaPka.js");
|
|
3744
3744
|
const ok = revokeShare(decodeURIComponent(revokeM[1]));
|
|
3745
3745
|
return new Response(ok ? "revoked" : "no such share", { status: ok ? 200 : 404 });
|
|
3746
3746
|
}
|
|
@@ -4052,7 +4052,7 @@ Options:
|
|
|
4052
4052
|
const shutdown = (resolve) => {
|
|
4053
4053
|
if (heartbeat) clearInterval(heartbeat);
|
|
4054
4054
|
closeShare?.();
|
|
4055
|
-
import("./agentShare-
|
|
4055
|
+
import("./agentShare-BASAaPka.js").then((m) => m.revokeAllShares()).catch(() => {});
|
|
4056
4056
|
server?.stop();
|
|
4057
4057
|
Promise.resolve(releaseHostLock?.()).catch(() => {}).then(resolve);
|
|
4058
4058
|
};
|
|
@@ -4065,4 +4065,4 @@ Options:
|
|
|
4065
4065
|
|
|
4066
4066
|
//#endregion
|
|
4067
4067
|
export { cmdServe, inspectServeDaemon, loadTokenReadOnly, mintScopedTermToken, resolveDaemonHttpBase, resolveLocalServeUrl };
|
|
4068
|
-
//# sourceMappingURL=serve-
|
|
4068
|
+
//# sourceMappingURL=serve-BPl5u9Mw.js.map
|
|
@@ -97,7 +97,7 @@ async function cmdSetup(rest) {
|
|
|
97
97
|
} catch {}
|
|
98
98
|
if (noShare) return 0;
|
|
99
99
|
process.stdout.write(`\nsharing this machine to agent-yes.com…\n`);
|
|
100
|
-
const { cmdServe } = await import("./serve-
|
|
100
|
+
const { cmdServe } = await import("./serve-BPl5u9Mw.js");
|
|
101
101
|
return cmdServe([
|
|
102
102
|
"install",
|
|
103
103
|
"--share",
|
|
@@ -107,4 +107,4 @@ async function cmdSetup(rest) {
|
|
|
107
107
|
|
|
108
108
|
//#endregion
|
|
109
109
|
export { cmdSetup };
|
|
110
|
-
//# sourceMappingURL=setup-
|
|
110
|
+
//# sourceMappingURL=setup-IbpYJdQm.js.map
|
|
@@ -243,7 +243,7 @@ shown first and needs a y at a [y/N] prompt.
|
|
|
243
243
|
Options:
|
|
244
244
|
--port N HTTP port (default: ${DEFAULT_SHARE_PORT}, or the daemon's)\n --path /ay tailscale mount path (default: ${DEFAULT_TS_PATH})\n -y, --yes approve the shown commands without prompting\n --json print {mode, url} as JSON\n\nThe URL carries this host's serve token: whoever holds it can read and steer\nevery agent here. Rotate: rm ~/.agent-yes/.serve-token && ay serve install\n`;
|
|
245
245
|
async function cmdShareStatus(mount) {
|
|
246
|
-
const { inspectServeDaemon } = await import("./serve-
|
|
246
|
+
const { inspectServeDaemon } = await import("./serve-BPl5u9Mw.js");
|
|
247
247
|
const [d, ts] = await Promise.all([inspectServeDaemon(), detectTailscale()]);
|
|
248
248
|
const line = (k, v) => process.stdout.write(`${k.padEnd(11)}${v}\n`);
|
|
249
249
|
if (d.args === null) {
|
|
@@ -287,7 +287,7 @@ async function cmdShare(rest) {
|
|
|
287
287
|
process.stderr.write(`ay share: unknown mode '${mode}' — one of ${SHARE_MODES.join(", ")}\n`);
|
|
288
288
|
return 1;
|
|
289
289
|
}
|
|
290
|
-
const { inspectServeDaemon, cmdServe } = await import("./serve-
|
|
290
|
+
const { inspectServeDaemon, cmdServe } = await import("./serve-BPl5u9Mw.js");
|
|
291
291
|
const [daemon, ts] = await Promise.all([inspectServeDaemon(), detectTailscale()]);
|
|
292
292
|
const lanIp = pickLanIp(networkInterfaces());
|
|
293
293
|
if (!mode) {
|
|
@@ -412,4 +412,4 @@ async function cmdShare(rest) {
|
|
|
412
412
|
|
|
413
413
|
//#endregion
|
|
414
414
|
export { cmdShare };
|
|
415
|
-
//# sourceMappingURL=shareCmd-
|
|
415
|
+
//# sourceMappingURL=shareCmd-8EPCR-WP.js.map
|
|
@@ -1083,6 +1083,31 @@ function composerPromptRow(texts) {
|
|
|
1083
1083
|
return texts.findLastIndex((t) => PROMPT_RE.test(t));
|
|
1084
1084
|
}
|
|
1085
1085
|
/**
|
|
1086
|
+
* Is Claude Code's composer box the bottom of the screen: a rule directly above a
|
|
1087
|
+
* prompt row, at most a few draft rows (none of them another prompt) up to the
|
|
1088
|
+
* rule or footer that closes the box, and below that nothing but a few footer
|
|
1089
|
+
* rows? A box a partial redraw left open does not count: what is under its
|
|
1090
|
+
* prompt cannot be told from history, so the caller looks further back. When it is not, composerPromptRow either fell back to the last
|
|
1091
|
+
* prompt-looking row (on a Claude screen, possibly an old turn in the transcript)
|
|
1092
|
+
* or found a box that history has since been drawn under, so it is a stale one.
|
|
1093
|
+
* A real draft longer than MAX_DRAFT_ROWS fails too and reads "hidden", which
|
|
1094
|
+
* parks the send just as a draft does.
|
|
1095
|
+
*/
|
|
1096
|
+
function composerBoxed(texts) {
|
|
1097
|
+
const prompt = composerPromptRow(texts);
|
|
1098
|
+
if (prompt < 1 || !SEPARATOR_RE.test(texts[prompt - 1])) return false;
|
|
1099
|
+
const nonBlank = (rows) => rows.filter((t) => t.trim());
|
|
1100
|
+
const close = texts.findIndex((t, i) => i > prompt && isComposerChrome(t));
|
|
1101
|
+
if (close < 0) return false;
|
|
1102
|
+
const inside = nonBlank(texts.slice(prompt + 1, close));
|
|
1103
|
+
const below = nonBlank(texts.slice(close + 1));
|
|
1104
|
+
return inside.length <= MAX_DRAFT_ROWS && below.length <= MAX_ROWS_BELOW_BOX && ![...inside, ...below].some((t) => PROMPT_RE.test(t));
|
|
1105
|
+
}
|
|
1106
|
+
/** Draft rows under the prompt row, before the box is read as stale (see above). */
|
|
1107
|
+
const MAX_DRAFT_ROWS = 8;
|
|
1108
|
+
/** Footer rows Claude Code draws under its composer box (mode, hints, agents, notices). */
|
|
1109
|
+
const MAX_ROWS_BELOW_BOX = 4;
|
|
1110
|
+
/**
|
|
1086
1111
|
* Is this row composer chrome (a rule or a Claude/Codex footer) — the end of the
|
|
1087
1112
|
* input? Pass the row's `cells` when known: the loose footer match then also
|
|
1088
1113
|
* requires every visible cell to be coloured, so a typed line is never cut off.
|
|
@@ -1986,7 +2011,7 @@ async function runSubcommand(argv) {
|
|
|
1986
2011
|
switch (sub) {
|
|
1987
2012
|
case "ls":
|
|
1988
2013
|
case "list": return await cmdLs(rest);
|
|
1989
|
-
case "ps": return await (await import("./cmdPs-
|
|
2014
|
+
case "ps": return await (await import("./cmdPs-BM2Srp1S.js")).cmdPs(rest);
|
|
1990
2015
|
case "status": return await cmdStatus(rest);
|
|
1991
2016
|
case "whoami": return await cmdWhoami(rest);
|
|
1992
2017
|
case "result": return await cmdResult(rest);
|
|
@@ -2034,35 +2059,35 @@ async function runSubcommand(argv) {
|
|
|
2034
2059
|
return cmdCh(rest);
|
|
2035
2060
|
}
|
|
2036
2061
|
case "term": {
|
|
2037
|
-
const { cmdTerm } = await import("./terminal-
|
|
2062
|
+
const { cmdTerm } = await import("./terminal-Del-sL1m.js");
|
|
2038
2063
|
return cmdTerm(rest);
|
|
2039
2064
|
}
|
|
2040
2065
|
case "widget": {
|
|
2041
|
-
const { cmdWidget } = await import("./widget-
|
|
2066
|
+
const { cmdWidget } = await import("./widget-E8nWj1fn.js");
|
|
2042
2067
|
return cmdWidget(rest);
|
|
2043
2068
|
}
|
|
2044
2069
|
case "mint": {
|
|
2045
|
-
const { cmdMint } = await import("./widget-
|
|
2070
|
+
const { cmdMint } = await import("./widget-E8nWj1fn.js");
|
|
2046
2071
|
return cmdMint(rest);
|
|
2047
2072
|
}
|
|
2048
2073
|
case "serve": {
|
|
2049
|
-
const { cmdServe } = await import("./serve-
|
|
2074
|
+
const { cmdServe } = await import("./serve-BPl5u9Mw.js");
|
|
2050
2075
|
return cmdServe(rest);
|
|
2051
2076
|
}
|
|
2052
2077
|
case "tray": {
|
|
2053
|
-
const { cmdTray } = await import("./trayApp-
|
|
2078
|
+
const { cmdTray } = await import("./trayApp-2yKAAVa7.js");
|
|
2054
2079
|
return cmdTray(rest);
|
|
2055
2080
|
}
|
|
2056
2081
|
case "setup": {
|
|
2057
|
-
const { cmdSetup } = await import("./setup-
|
|
2082
|
+
const { cmdSetup } = await import("./setup-IbpYJdQm.js");
|
|
2058
2083
|
return cmdSetup(rest);
|
|
2059
2084
|
}
|
|
2060
2085
|
case "ws": {
|
|
2061
|
-
const { cmdWs } = await import("./ws-
|
|
2086
|
+
const { cmdWs } = await import("./ws-CMkJamuh.js");
|
|
2062
2087
|
return cmdWs(rest);
|
|
2063
2088
|
}
|
|
2064
2089
|
case "schedule": {
|
|
2065
|
-
const { cmdSchedule } = await import("./schedule-
|
|
2090
|
+
const { cmdSchedule } = await import("./schedule-D45Ja0h0.js");
|
|
2066
2091
|
return cmdSchedule(rest);
|
|
2067
2092
|
}
|
|
2068
2093
|
case "remote": {
|
|
@@ -2070,7 +2095,7 @@ async function runSubcommand(argv) {
|
|
|
2070
2095
|
return cmdRemote(rest);
|
|
2071
2096
|
}
|
|
2072
2097
|
case "share": {
|
|
2073
|
-
const { cmdShare } = await import("./shareCmd-
|
|
2098
|
+
const { cmdShare } = await import("./shareCmd-8EPCR-WP.js");
|
|
2074
2099
|
return cmdShare(rest);
|
|
2075
2100
|
}
|
|
2076
2101
|
case "connect": {
|
|
@@ -2082,7 +2107,7 @@ async function runSubcommand(argv) {
|
|
|
2082
2107
|
return cmdExpose(rest);
|
|
2083
2108
|
}
|
|
2084
2109
|
case "callback": {
|
|
2085
|
-
const { cmdCallback } = await import("./callback-
|
|
2110
|
+
const { cmdCallback } = await import("./callback-BnkktH-1.js");
|
|
2086
2111
|
return cmdCallback(rest);
|
|
2087
2112
|
}
|
|
2088
2113
|
case "reap":
|
|
@@ -2093,7 +2118,7 @@ async function runSubcommand(argv) {
|
|
|
2093
2118
|
return await cmdDsh(rest);
|
|
2094
2119
|
}
|
|
2095
2120
|
case "gc": {
|
|
2096
|
-
const { gcOldBinaryDirs } = await import("./rustBinary-
|
|
2121
|
+
const { gcOldBinaryDirs } = await import("./rustBinary-Lzt3pVh_.js");
|
|
2097
2122
|
const { gcLogs } = await import("./globalPidIndex-DC93JhHQ.js");
|
|
2098
2123
|
const bins = gcOldBinaryDirs();
|
|
2099
2124
|
const logs = await gcLogs();
|
|
@@ -4229,37 +4254,119 @@ async function renderLogTailLines(logPath, n = 40, geom) {
|
|
|
4229
4254
|
}
|
|
4230
4255
|
}
|
|
4231
4256
|
/**
|
|
4257
|
+
* Tail windows the composer check renders, smallest first. Rendering a tail
|
|
4258
|
+
* starts mid-stream, and Claude Code's renderer redraws only the rows that
|
|
4259
|
+
* changed: on a lane that has sat idle for hours the last 32 KB can hold
|
|
4260
|
+
* redraws of transcript rows (an old `❯` turn among them) but not the unchanged
|
|
4261
|
+
* rule and empty prompt row of the composer box, so the old turn was read as
|
|
4262
|
+
* the prompt and the transcript under it as a draft. A Claude screen without
|
|
4263
|
+
* its box is therefore re-rendered from further back, last of all from as far
|
|
4264
|
+
* back as `ay read` renders. When even that shows no box, a draft read under
|
|
4265
|
+
* some other prompt row is reported as "hidden" rather than as a draft: the
|
|
4266
|
+
* send still parks, and the drainer waits for the box.
|
|
4267
|
+
*
|
|
4268
|
+
* Logs run to 100+ MB and the drainer re-checks every few seconds, so the
|
|
4269
|
+
* rendered terminal is kept per log and later checks feed it only the bytes
|
|
4270
|
+
* appended since: each window is rendered at most once per process, and a
|
|
4271
|
+
* screen that stays without a box costs only its new output on every poll.
|
|
4272
|
+
*/
|
|
4273
|
+
const COMPOSER_WINDOWS = [
|
|
4274
|
+
32 * 1024,
|
|
4275
|
+
1024 * 1024,
|
|
4276
|
+
8 * 1024 * 1024,
|
|
4277
|
+
MAX_RENDER_BYTES
|
|
4278
|
+
];
|
|
4279
|
+
const composerTerms = /* @__PURE__ */ new Map();
|
|
4280
|
+
const COMPOSER_TERMS_MAX = 64;
|
|
4281
|
+
function dropComposerTerm(logPath) {
|
|
4282
|
+
composerTerms.get(logPath)?.term.dispose();
|
|
4283
|
+
composerTerms.delete(logPath);
|
|
4284
|
+
}
|
|
4285
|
+
/**
|
|
4232
4286
|
* What the target's composer holds right now, read from the same 32 KB tail
|
|
4233
|
-
* `renderLogTailLines` renders
|
|
4234
|
-
*
|
|
4287
|
+
* `renderLogTailLines` renders (further back when a Claude screen shows no
|
|
4288
|
+
* composer box), keeping per-cell attributes (dim/inverse) so ghost text can be
|
|
4289
|
+
* told from a real draft. See ts/composerGuard.ts.
|
|
4235
4290
|
*/
|
|
4236
|
-
async function readComposerState(record) {
|
|
4237
|
-
|
|
4291
|
+
async function readComposerState(record, windows = COMPOSER_WINDOWS) {
|
|
4292
|
+
const logPath = record.log_file;
|
|
4293
|
+
if (!logPath) return {
|
|
4238
4294
|
kind: "unknown",
|
|
4239
4295
|
reason: "no log file recorded"
|
|
4240
4296
|
};
|
|
4241
|
-
const buf = await readLogTailBytes(record.log_file);
|
|
4242
|
-
if (!buf) return {
|
|
4243
|
-
kind: "unknown",
|
|
4244
|
-
reason: "log unreadable or empty"
|
|
4245
|
-
};
|
|
4246
4297
|
const geom = await readAgentPtysize(record) ?? void 0;
|
|
4298
|
+
const key = `${geom?.cols}x${geom?.rows}:${record.cli}:${windows.join()}`;
|
|
4299
|
+
const claude = record.cli === "claude";
|
|
4247
4300
|
try {
|
|
4248
|
-
const
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4301
|
+
const { size } = await stat(logPath);
|
|
4302
|
+
if (size === 0) return {
|
|
4303
|
+
kind: "unknown",
|
|
4304
|
+
reason: "log unreadable or empty"
|
|
4305
|
+
};
|
|
4306
|
+
let ct = composerTerms.get(logPath);
|
|
4307
|
+
if (ct && (ct.key !== key || size < ct.offset)) {
|
|
4308
|
+
dropComposerTerm(logPath);
|
|
4309
|
+
ct = void 0;
|
|
4310
|
+
}
|
|
4311
|
+
let rows;
|
|
4312
|
+
let next = 0;
|
|
4313
|
+
if (ct) {
|
|
4314
|
+
if (size > ct.offset) {
|
|
4315
|
+
const delta = await readLogRange(logPath, ct.offset, size);
|
|
4316
|
+
await new Promise((resolve) => ct.term.write(delta, resolve));
|
|
4317
|
+
ct.offset += delta.length;
|
|
4318
|
+
}
|
|
4319
|
+
rows = rowsFromXterm(ct.term, 40);
|
|
4320
|
+
next = ct.whole ? windows.length : ct.window + 1;
|
|
4321
|
+
if (!claude || composerBoxed(rows.map((r) => r.text))) next = windows.length;
|
|
4322
|
+
}
|
|
4323
|
+
for (let w = next; w < windows.length; w++) {
|
|
4324
|
+
const from = Math.max(0, size - windows[w]);
|
|
4325
|
+
const buf = await readLogRange(logPath, from, size);
|
|
4326
|
+
const term = new (await (loadXtermTerminal()))({
|
|
4327
|
+
cols: geom?.cols && geom.cols > 0 ? geom.cols : 200,
|
|
4328
|
+
rows: geom?.rows && geom.rows > 0 ? geom.rows : 50,
|
|
4329
|
+
scrollback: 1e3,
|
|
4330
|
+
allowProposedApi: true
|
|
4331
|
+
});
|
|
4332
|
+
await new Promise((resolve) => term.write(buf, resolve));
|
|
4333
|
+
dropComposerTerm(logPath);
|
|
4334
|
+
composerTerms.set(logPath, {
|
|
4335
|
+
term,
|
|
4336
|
+
key,
|
|
4337
|
+
window: w,
|
|
4338
|
+
offset: from + buf.length,
|
|
4339
|
+
whole: from === 0
|
|
4340
|
+
});
|
|
4341
|
+
if (composerTerms.size > COMPOSER_TERMS_MAX) dropComposerTerm(composerTerms.keys().next().value);
|
|
4342
|
+
rows = rowsFromXterm(term, 40);
|
|
4343
|
+
if (!claude || from === 0 || composerBoxed(rows.map((r) => r.text))) break;
|
|
4344
|
+
}
|
|
4345
|
+
const state = classifyComposer(rows ?? []);
|
|
4346
|
+
if (claude && state.kind === "draft" && !composerBoxed((rows ?? []).map((r) => r.text))) return {
|
|
4347
|
+
kind: "hidden",
|
|
4348
|
+
reason: "its input box is not on screen"
|
|
4349
|
+
};
|
|
4350
|
+
return state;
|
|
4256
4351
|
} catch (e) {
|
|
4352
|
+
dropComposerTerm(logPath);
|
|
4257
4353
|
return {
|
|
4258
4354
|
kind: "unknown",
|
|
4259
|
-
reason: `render failed: ${e?.message ?? e}`
|
|
4355
|
+
reason: `log unreadable or render failed: ${e?.message ?? e}`
|
|
4260
4356
|
};
|
|
4261
4357
|
}
|
|
4262
4358
|
}
|
|
4359
|
+
/** Bytes `[from, to)` of a log file. */
|
|
4360
|
+
async function readLogRange(logPath, from, to) {
|
|
4361
|
+
const fh = await open(logPath, "r");
|
|
4362
|
+
try {
|
|
4363
|
+
const buf = Buffer.alloc(Math.max(0, to - from));
|
|
4364
|
+
const { bytesRead } = await fh.read(buf, 0, buf.length, from);
|
|
4365
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, bytesRead);
|
|
4366
|
+
} finally {
|
|
4367
|
+
await fh.close();
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4263
4370
|
async function readLogTailBytes(logPath) {
|
|
4264
4371
|
const TAIL_BYTES = 32 * 1024;
|
|
4265
4372
|
let buf;
|
|
@@ -4956,6 +5063,7 @@ async function cmdSend(rest) {
|
|
|
4956
5063
|
if (!parkReason) {
|
|
4957
5064
|
const composer = await readComposerState(record);
|
|
4958
5065
|
if (composer.kind === "draft") parkReason = `its input box holds a draft (${composer.chars} chars)`;
|
|
5066
|
+
else if (composer.kind === "hidden") parkReason = composer.reason;
|
|
4959
5067
|
else if (composer.kind === "unknown") process.stderr.write(`warning: ay send could not see pid ${record.pid}'s input box (${composer.reason}) — sending without the draft check.\n`);
|
|
4960
5068
|
}
|
|
4961
5069
|
if (dedupeKey) await noteRecentSend(record.pid, dedupeKey, body, parkReason ? "queued" : "sent");
|
|
@@ -5590,7 +5698,7 @@ async function cmdAttach(rest) {
|
|
|
5590
5698
|
const winsizeDir = path.join(ayHome, "winsize");
|
|
5591
5699
|
await mkdir(winsizeDir, { recursive: true });
|
|
5592
5700
|
const winsizePath = path.join(winsizeDir, String(record.pid));
|
|
5593
|
-
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-
|
|
5701
|
+
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-BPl5u9Mw.js");
|
|
5594
5702
|
const daemonBase = await resolveDaemonHttpBase().catch(() => null);
|
|
5595
5703
|
const daemonToken = daemonBase ? await loadTokenReadOnly().catch(() => null) ?? "" : "";
|
|
5596
5704
|
const capViewer = `attach:${process.pid}`;
|
|
@@ -6319,7 +6427,7 @@ async function cmdNotify(rest) {
|
|
|
6319
6427
|
}
|
|
6320
6428
|
const ensure = async () => {
|
|
6321
6429
|
if (!argv["ensure-daemon"]) return;
|
|
6322
|
-
const { ensureDaemon } = await import("./notifyDaemon-
|
|
6430
|
+
const { ensureDaemon } = await import("./notifyDaemon-BtbS2lBT.js");
|
|
6323
6431
|
await ensureDaemon().catch(() => null);
|
|
6324
6432
|
};
|
|
6325
6433
|
await heartbeatWatcher(parent, selfStartedAt);
|
|
@@ -6393,7 +6501,7 @@ async function cmdNotifyCursor(args) {
|
|
|
6393
6501
|
}
|
|
6394
6502
|
async function cmdNotifyd(rest) {
|
|
6395
6503
|
const sub = rest[0] ?? "status";
|
|
6396
|
-
const daemon = await import("./notifyDaemon-
|
|
6504
|
+
const daemon = await import("./notifyDaemon-BtbS2lBT.js");
|
|
6397
6505
|
switch (sub) {
|
|
6398
6506
|
case "run": return daemon.runDaemon();
|
|
6399
6507
|
case "once": return daemon.runDaemon({ once: true });
|
|
@@ -6419,5 +6527,5 @@ async function cmdNotifyd(rest) {
|
|
|
6419
6527
|
}
|
|
6420
6528
|
|
|
6421
6529
|
//#endregion
|
|
6422
|
-
export {
|
|
6423
|
-
//# sourceMappingURL=subcommands-
|
|
6530
|
+
export { renderLogTailLines as $, isAgentStuck as A, lastStdinAt as B, extractBadges as C, finalizedLines as D, extractTaskCounts as E, isSubcommand as F, probeStdinReachable as G, matchKeyword as H, isUnknownManagerToken as I, readLogForRender as J, readAgentPtysize as K, isUnreachableWriteErrno as L, isExitRequest as M, isPidAlive as N, inspectSubmission as O, isSlashCommand as P, recentReadEdges as Q, isUserTyping as R, envelopeCostFor as S, extractNeedsInput as T, menuSelectKeys as U, listRecords as V, ownedCollapsedPaste as W, readPtysize as X, readNotes as Y, recentMessageEdges as Z, cwdLabel as _, shouldFramePaste as _t, READ_WINDOW_MS as a, restartHintLines as at, drainerLauncher as b, flattenForest as bt, SEND_EXIT_UNREACHABLE as c, snapshotStatus as ct, buildEnvelope as d, submitAndConfirm as dt, renderRawLog as et, cliDefaults as f, waitForLogQuiet as ft, cursorAbs as g, framePaste as gt, controlCodeFromName as h, withIpcLock as ht, READ_PAGE_DEFAULT as i, resolveResumeArgs as it, isBareManagerInvocation as j, isAgentIdShaped as k, TYPING_WINDOW_MS as l, stdinActivityPath as lt, confirmStdinUnreachable as m, writeToIpc as mt, GRACEFUL_EXIT_COMMANDS as n, resolveOne as nt, SEND_BODY_MAX_CHARS as o, runSubcommand as ot, cmdHelp as p, writeKeysPaced as pt, readComposerState as q, MAX_RENDER_BYTES as r, resolveReadWindow as rt, SEND_EXIT_QUEUED as s, sendPayloadCapError as st, COMPOSER_WINDOWS as t, renderRawLogLines as tt, backoffWhileTyping as u, stopTipForCli as ut, deriveLiveState as v, TYPING_BADGE as vt, extractMenu as w, envelopeAttribution as x, deriveLiveStatus as y, buildAgentForest as yt, lastReadAt as z };
|
|
6531
|
+
//# sourceMappingURL=subcommands-BusIzjLq.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import "./logger-CDIsZ-Pp.js";
|
|
2
|
+
import "./JsonlStore-BqF7AQ6E.js";
|
|
3
|
+
import "./globalPidIndex-CRH9L9tn.js";
|
|
4
|
+
import "./pidStore-DXWqzTSz.js";
|
|
5
|
+
import "./messageLog-Brx3w6zT.js";
|
|
6
|
+
import "./e2e-z1xpwSAg.js";
|
|
7
|
+
import "./configShared-DKTgiz7K.js";
|
|
8
|
+
import { $ as renderLogTailLines, A as isAgentStuck, B as lastStdinAt, C as extractBadges, D as finalizedLines, E as extractTaskCounts, F as isSubcommand, G as probeStdinReachable, H as matchKeyword, I as isUnknownManagerToken, J as readLogForRender, K as readAgentPtysize, L as isUnreachableWriteErrno, M as isExitRequest, N as isPidAlive, O as inspectSubmission, P as isSlashCommand, Q as recentReadEdges, R as isUserTyping, S as envelopeCostFor, T as extractNeedsInput, U as menuSelectKeys, V as listRecords, W as ownedCollapsedPaste, X as readPtysize, Y as readNotes, Z as recentMessageEdges, _ as cwdLabel, a as READ_WINDOW_MS, at as restartHintLines, b as drainerLauncher, c as SEND_EXIT_UNREACHABLE, ct as snapshotStatus, d as buildEnvelope, dt as submitAndConfirm, et as renderRawLog, f as cliDefaults, ft as waitForLogQuiet, g as cursorAbs, h as controlCodeFromName, i as READ_PAGE_DEFAULT, it as resolveResumeArgs, j as isBareManagerInvocation, k as isAgentIdShaped, l as TYPING_WINDOW_MS, lt as stdinActivityPath, m as confirmStdinUnreachable, mt as writeToIpc, n as GRACEFUL_EXIT_COMMANDS, nt as resolveOne, o as SEND_BODY_MAX_CHARS, ot as runSubcommand, p as cmdHelp, pt as writeKeysPaced, q as readComposerState, r as MAX_RENDER_BYTES, rt as resolveReadWindow, s as SEND_EXIT_QUEUED, st as sendPayloadCapError, t as COMPOSER_WINDOWS, tt as renderRawLogLines, u as backoffWhileTyping, ut as stopTipForCli, v as deriveLiveState, w as extractMenu, x as envelopeAttribution, y as deriveLiveStatus, z as lastReadAt } from "./subcommands-BusIzjLq.js";
|
|
9
|
+
import "./notifyStore-2SWKGwZI.js";
|
|
10
|
+
import "./webrtcLink-DFRyWNMs.js";
|
|
11
|
+
import "./remotes-B4v0Nowo.js";
|
|
12
|
+
|
|
13
|
+
export { READ_WINDOW_MS, cmdHelp, isBareManagerInvocation, isSubcommand, isUnknownManagerToken, lastReadAt, runSubcommand };
|
|
@@ -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-BPl5u9Mw.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-Del-sL1m.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { o as findTrayLauncher } from "./rustBinary-
|
|
1
|
+
import { o as findTrayLauncher } from "./rustBinary-DHWoCbGC.js";
|
|
2
2
|
import { t as agentYesHome } from "./agentYesHome-BNtn19J4.js";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -97,4 +97,4 @@ async function cmdTray(args) {
|
|
|
97
97
|
|
|
98
98
|
//#endregion
|
|
99
99
|
export { trayHiddenMarker as a, launchTray as i, hasDesktop as n, isTrayHidden as r, cmdTray as t };
|
|
100
|
-
//# sourceMappingURL=trayApp-
|
|
100
|
+
//# sourceMappingURL=trayApp-Tp8PsCsA.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 { i as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { i as getInstalledPackage } from "./versionChecker-DUIQTHWC.js";
|
|
4
4
|
import { t as agentYesHome } from "./agentYesHome-BNtn19J4.js";
|
|
5
5
|
import { u as removeControlCharacters } from "./todoAutomation-CbVVS4re.js";
|
|
6
6
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-BOIPD_Vs.js";
|
|
@@ -2086,7 +2086,7 @@ async function agentYes({ cli, cliArgs = [], skipPermissions = false, prompt, ro
|
|
|
2086
2086
|
}, 100);
|
|
2087
2087
|
const cleanupHeartbeat = () => clearInterval(heartbeatInterval);
|
|
2088
2088
|
shell.onExit(cleanupHeartbeat);
|
|
2089
|
-
const { startParentPingLoop } = await import("./parentPingLoop-
|
|
2089
|
+
const { startParentPingLoop } = await import("./parentPingLoop-rLQBc0G5.js");
|
|
2090
2090
|
const parentPingLoop = startParentPingLoop({
|
|
2091
2091
|
parentPid,
|
|
2092
2092
|
selfWrapperPid: process.pid,
|
|
@@ -2349,4 +2349,4 @@ function sleep(ms) {
|
|
|
2349
2349
|
|
|
2350
2350
|
//#endregion
|
|
2351
2351
|
export { hasTodoStore as a, permissionBadge as c, answerAsk as i, AgentContext as l, agentYes as n, listAsks as o, config as r, listAsksForProject as s, CLIS_CONFIG as t, CLAUDE_SESSION_PIN_ENV as u };
|
|
2352
|
-
//# sourceMappingURL=ts-
|
|
2352
|
+
//# sourceMappingURL=ts-BFVAQ0Zs.js.map
|
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
|
|
8
8
|
//#region package.json
|
|
9
9
|
var name = "claude-yes";
|
|
10
|
-
var version = "1.300.
|
|
10
|
+
var version = "1.300.3";
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region ts/versionChecker.ts
|
|
@@ -285,4 +285,4 @@ async function displayVersion() {
|
|
|
285
285
|
|
|
286
286
|
//#endregion
|
|
287
287
|
export { versionString as a, getInstalledPackage as i, compareVersions as n, displayVersion as r, checkAndAutoUpdate as t };
|
|
288
|
-
//# sourceMappingURL=versionChecker-
|
|
288
|
+
//# sourceMappingURL=versionChecker-DUIQTHWC.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-BPl5u9Mw.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-BPl5u9Mw.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-E8nWj1fn.js.map
|
|
@@ -5,10 +5,10 @@ import "./pidStore-DXWqzTSz.js";
|
|
|
5
5
|
import "./messageLog-Brx3w6zT.js";
|
|
6
6
|
import "./e2e-z1xpwSAg.js";
|
|
7
7
|
import "./configShared-DKTgiz7K.js";
|
|
8
|
-
import "./subcommands-
|
|
8
|
+
import "./subcommands-BusIzjLq.js";
|
|
9
9
|
import "./notifyStore-2SWKGwZI.js";
|
|
10
10
|
import "./webrtcLink-DFRyWNMs.js";
|
|
11
11
|
import "./remotes-B4v0Nowo.js";
|
|
12
|
-
import { a as isPathInside, c as walkWorkspaces, i as importProvisionModule, l as workspaceStatus, n as cmdWs, o as loadProvision, r as collectWorkspaces, s as resolveOperand, t as WS_JSON_SCHEMA } from "./ws-
|
|
12
|
+
import { a as isPathInside, c as walkWorkspaces, i as importProvisionModule, l as workspaceStatus, n as cmdWs, o as loadProvision, r as collectWorkspaces, s as resolveOperand, t as WS_JSON_SCHEMA } from "./ws-D9EBcPei.js";
|
|
13
13
|
|
|
14
14
|
export { WS_JSON_SCHEMA, cmdWs, collectWorkspaces, isPathInside, loadProvision, walkWorkspaces, workspaceStatus };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { V as listRecords } from "./subcommands-BusIzjLq.js";
|
|
2
2
|
import { a as getProvisionRoot } from "./workspaceConfig-DTvPtr5j.js";
|
|
3
3
|
import { existsSync } from "fs";
|
|
4
4
|
import { lstat, opendir } from "fs/promises";
|
|
@@ -424,4 +424,4 @@ async function cmdWs(args) {
|
|
|
424
424
|
|
|
425
425
|
//#endregion
|
|
426
426
|
export { isPathInside as a, walkWorkspaces as c, importProvisionModule as i, workspaceStatus as l, cmdWs as n, loadProvision as o, collectWorkspaces as r, resolveOperand as s, WS_JSON_SCHEMA as t };
|
|
427
|
-
//# sourceMappingURL=ws-
|
|
427
|
+
//# sourceMappingURL=ws-D9EBcPei.js.map
|
package/package.json
CHANGED
package/ts/composerGuard.spec.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Terminal } from "@xterm/headless";
|
|
|
6
6
|
import {
|
|
7
7
|
claimPending,
|
|
8
8
|
classifyComposer,
|
|
9
|
+
composerBoxed,
|
|
9
10
|
DUPLICATE_WINDOW_MS,
|
|
10
11
|
enqueuePending,
|
|
11
12
|
findRecentDuplicate,
|
|
@@ -277,3 +278,36 @@ describe("duplicate suppression at the sink", () => {
|
|
|
277
278
|
);
|
|
278
279
|
});
|
|
279
280
|
});
|
|
281
|
+
|
|
282
|
+
describe("composerBoxed", () => {
|
|
283
|
+
const RULE = "─".repeat(40);
|
|
284
|
+
const FOOTER = " ? for shortcuts";
|
|
285
|
+
it("accepts the box at the bottom, closed by its rule or the footer", () => {
|
|
286
|
+
expect(composerBoxed(["● done", RULE, "❯ ", RULE, FOOTER])).toBe(true);
|
|
287
|
+
expect(composerBoxed(["● done", RULE, "❯ btw how", FOOTER])).toBe(true);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("rejects a box a partial redraw left open, however short", () => {
|
|
291
|
+
expect(composerBoxed(["● done", RULE, "❯ btw how"])).toBe(false);
|
|
292
|
+
expect(composerBoxed([RULE, "❯ ", " answer line"])).toBe(false);
|
|
293
|
+
});
|
|
294
|
+
it("rejects a screen whose prompt row has no rule above it", () => {
|
|
295
|
+
expect(composerBoxed(["● done", "❯ please summarise", " answer"])).toBe(false);
|
|
296
|
+
});
|
|
297
|
+
it("rejects a stale box that history has been drawn under", () => {
|
|
298
|
+
expect(composerBoxed([RULE, "❯ old draft", RULE, "● done", "❯ please summarise", " answer"])).toBe(false);
|
|
299
|
+
expect(composerBoxed([RULE, "❯ ", RULE, " a", " b", " c", " d", " e"])).toBe(false);
|
|
300
|
+
// Left open by a partial redraw, with history drawn under it.
|
|
301
|
+
expect(composerBoxed([RULE, "❯ ", "● done", "❯ please summarise", " answer"])).toBe(false);
|
|
302
|
+
expect(composerBoxed([RULE, "❯ ", " a", " b", " c", " d", " e", " f", " g", " h", " i"])).toBe(false);
|
|
303
|
+
// Transcript drawn under a stale prompt, with chrome further down.
|
|
304
|
+
expect(composerBoxed([RULE, "❯ ", "● done", "❯ please summarise", " answer", RULE])).toBe(false);
|
|
305
|
+
expect(
|
|
306
|
+
composerBoxed([RULE, "❯ ", ...Array.from({ length: 9 }, (_, i) => ` row ${i}`), FOOTER]),
|
|
307
|
+
).toBe(false);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it("accepts a short multi-line draft inside the box", () => {
|
|
311
|
+
expect(composerBoxed([RULE, "❯ first line", " second line", " third", RULE, FOOTER])).toBe(true);
|
|
312
|
+
});
|
|
313
|
+
});
|
package/ts/composerGuard.ts
CHANGED
|
@@ -49,7 +49,13 @@ export type ComposerState =
|
|
|
49
49
|
/** Real input is sitting in the composer. `chars` counts the real cells. */
|
|
50
50
|
| { kind: "draft"; chars: number }
|
|
51
51
|
/** No composer is visible (menu, trust dialog, unknown CLI screen). */
|
|
52
|
-
| { kind: "unknown"; reason: string }
|
|
52
|
+
| { kind: "unknown"; reason: string }
|
|
53
|
+
/**
|
|
54
|
+
* Text was read under a prompt row, but Claude Code's composer box is not on
|
|
55
|
+
* screen (a dialog, or no box in any window rendered), so it may be an old
|
|
56
|
+
* turn rather than a draft. Parks like a draft; unlike "unknown", which sends.
|
|
57
|
+
*/
|
|
58
|
+
| { kind: "hidden"; reason: string };
|
|
53
59
|
|
|
54
60
|
const PROMPT_RE = /^\s*[❯›]($|\s)/u;
|
|
55
61
|
// Same chrome inspectSubmission stops at: the separator rule under the box and
|
|
@@ -84,6 +90,37 @@ export function composerPromptRow(texts: string[]): number {
|
|
|
84
90
|
return texts.findLastIndex((t) => PROMPT_RE.test(t));
|
|
85
91
|
}
|
|
86
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Is Claude Code's composer box the bottom of the screen: a rule directly above a
|
|
95
|
+
* prompt row, at most a few draft rows (none of them another prompt) up to the
|
|
96
|
+
* rule or footer that closes the box, and below that nothing but a few footer
|
|
97
|
+
* rows? A box a partial redraw left open does not count: what is under its
|
|
98
|
+
* prompt cannot be told from history, so the caller looks further back. When it is not, composerPromptRow either fell back to the last
|
|
99
|
+
* prompt-looking row (on a Claude screen, possibly an old turn in the transcript)
|
|
100
|
+
* or found a box that history has since been drawn under, so it is a stale one.
|
|
101
|
+
* A real draft longer than MAX_DRAFT_ROWS fails too and reads "hidden", which
|
|
102
|
+
* parks the send just as a draft does.
|
|
103
|
+
*/
|
|
104
|
+
export function composerBoxed(texts: string[]): boolean {
|
|
105
|
+
const prompt = composerPromptRow(texts);
|
|
106
|
+
if (prompt < 1 || !SEPARATOR_RE.test(texts[prompt - 1]!)) return false;
|
|
107
|
+
const nonBlank = (rows: string[]) => rows.filter((t) => t.trim());
|
|
108
|
+
const close = texts.findIndex((t, i) => i > prompt && isComposerChrome(t));
|
|
109
|
+
if (close < 0) return false;
|
|
110
|
+
const inside = nonBlank(texts.slice(prompt + 1, close));
|
|
111
|
+
const below = nonBlank(texts.slice(close + 1));
|
|
112
|
+
return (
|
|
113
|
+
inside.length <= MAX_DRAFT_ROWS &&
|
|
114
|
+
below.length <= MAX_ROWS_BELOW_BOX &&
|
|
115
|
+
![...inside, ...below].some((t) => PROMPT_RE.test(t))
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Draft rows under the prompt row, before the box is read as stale (see above). */
|
|
120
|
+
const MAX_DRAFT_ROWS = 8;
|
|
121
|
+
/** Footer rows Claude Code draws under its composer box (mode, hints, agents, notices). */
|
|
122
|
+
const MAX_ROWS_BELOW_BOX = 4;
|
|
123
|
+
|
|
87
124
|
/**
|
|
88
125
|
* Is this row composer chrome (a rule or a Claude/Codex footer) — the end of the
|
|
89
126
|
* input? Pass the row's `cells` when known: the loose footer match then also
|
package/ts/subcommands.spec.ts
CHANGED
|
@@ -2070,7 +2070,8 @@ describe("subcommands.cmdSend end-to-end submit-confirm wiring", () => {
|
|
|
2070
2070
|
const errs: string[] = [];
|
|
2071
2071
|
const origErr = process.stderr.write.bind(process.stderr);
|
|
2072
2072
|
process.stderr.write = ((c: string | Uint8Array) => (
|
|
2073
|
-
errs.push(String(c)),
|
|
2073
|
+
errs.push(String(c)),
|
|
2074
|
+
true
|
|
2074
2075
|
)) as typeof process.stderr.write;
|
|
2075
2076
|
let res: { code: number | null; stdout: string };
|
|
2076
2077
|
try {
|
|
@@ -4704,3 +4705,96 @@ describe("drainerLauncher", () => {
|
|
|
4704
4705
|
expect(drainerLauncher("C:\\tools\\ay.exe", undefined, null)).toEqual(["C:\\tools\\ay.exe"]);
|
|
4705
4706
|
});
|
|
4706
4707
|
});
|
|
4708
|
+
|
|
4709
|
+
describe("readComposerState on a lane idle for hours", { timeout: 60_000 }, () => {
|
|
4710
|
+
// A renderer that addresses rows absolutely and re-emits only the rows that
|
|
4711
|
+
// changed: the full frame (both rules, the empty prompt) is drawn once, then
|
|
4712
|
+
// >32 KB of redraws touch only transcript rows, an old "❯" turn among them.
|
|
4713
|
+
const COLS = 200;
|
|
4714
|
+
const GRAY = "\x1b[38;2;153;153;153m";
|
|
4715
|
+
const at = (row: number, text: string) => `\x1b[${row};1H\x1b[2K${text}`;
|
|
4716
|
+
function idleLog(composer: string, staleBox?: string, bytes = 200 * 1024): string {
|
|
4717
|
+
const screen: string[] = [];
|
|
4718
|
+
for (let i = 0; i < 38; i++) screen.push(`● step ${i}: lorem ipsum dolor sit amet`);
|
|
4719
|
+
screen.push("❯ please summarise the plan");
|
|
4720
|
+
for (let i = 0; i < 7; i++) screen.push(` answer line ${i}: sed do eiusmod tempor`);
|
|
4721
|
+
screen.push(
|
|
4722
|
+
`${GRAY}${"─".repeat(COLS)}\x1b[0m`,
|
|
4723
|
+
`❯ ${composer}`,
|
|
4724
|
+
`${GRAY}${"─".repeat(COLS)}\x1b[0m`,
|
|
4725
|
+
);
|
|
4726
|
+
screen.push(`${GRAY} ? for shortcuts\x1b[0m`);
|
|
4727
|
+
let log = "\x1b[2J" + screen.map((t, i) => at(i + 1, t)).join("") + "\x1b[48;3H";
|
|
4728
|
+
for (let k = 0; log.length < bytes; k++) {
|
|
4729
|
+
for (let r = 39; r <= 46; r++) log += at(r, screen[r - 1]! + (r === 46 ? ` ${k % 10}` : ""));
|
|
4730
|
+
// A fragment of an older frame's box, still holding what was typed then.
|
|
4731
|
+
if (staleBox !== undefined)
|
|
4732
|
+
log += at(30, `${GRAY}${"─".repeat(COLS)}\x1b[0m`) + at(31, `❯ ${staleBox}`) + at(32, `${GRAY}${"─".repeat(COLS)}\x1b[0m`);
|
|
4733
|
+
log += "\x1b[48;3H";
|
|
4734
|
+
}
|
|
4735
|
+
return log;
|
|
4736
|
+
}
|
|
4737
|
+
let logs = 0;
|
|
4738
|
+
async function stateOf(log: string, cli = "claude", windows?: number[]) {
|
|
4739
|
+
const { readComposerState } = await loadModule();
|
|
4740
|
+
const file = path.join(testHome, `${1111 + logs++}.raw.log`);
|
|
4741
|
+
await writeFile(file, log);
|
|
4742
|
+
return readComposerState({ pid: 1111, cli, log_file: file } as never, windows);
|
|
4743
|
+
}
|
|
4744
|
+
|
|
4745
|
+
it("reads the empty composer drawn before the last 32 KB, not the transcript", async () => {
|
|
4746
|
+
// The 32 KB tail alone renders the old turn as the prompt and its answer as a draft.
|
|
4747
|
+
expect(await stateOf(idleLog(""))).toEqual({ kind: "empty", ghost: false });
|
|
4748
|
+
});
|
|
4749
|
+
|
|
4750
|
+
it("searches as far back as `ay read` renders before giving up on the box", async () => {
|
|
4751
|
+
const { COMPOSER_WINDOWS, MAX_RENDER_BYTES } = await loadModule();
|
|
4752
|
+
expect(COMPOSER_WINDOWS.at(-1)).toBe(MAX_RENDER_BYTES);
|
|
4753
|
+
// Scaled down: windows that stop short of the box report it hidden, one more
|
|
4754
|
+
// that reaches it reads the empty composer.
|
|
4755
|
+
const log = idleLog("", undefined, 300 * 1024);
|
|
4756
|
+
expect((await stateOf(log, "claude", [32 * 1024, 64 * 1024])).kind).toBe("hidden");
|
|
4757
|
+
expect(await stateOf(log, "claude", [32 * 1024, 64 * 1024, 512 * 1024])).toEqual({
|
|
4758
|
+
kind: "empty",
|
|
4759
|
+
ghost: false,
|
|
4760
|
+
});
|
|
4761
|
+
});
|
|
4762
|
+
|
|
4763
|
+
it("does not stop at an older box that history was drawn under", async () => {
|
|
4764
|
+
expect(await stateOf(idleLog("", "old draft"))).toEqual({ kind: "empty", ghost: false });
|
|
4765
|
+
});
|
|
4766
|
+
|
|
4767
|
+
it("still reads a typed draft in that composer", async () => {
|
|
4768
|
+
expect(await stateOf(idleLog("btw how"))).toEqual({ kind: "draft", chars: 6 });
|
|
4769
|
+
});
|
|
4770
|
+
|
|
4771
|
+
it("reads a Claude screen that never shows its box as hidden, not as a draft", async () => {
|
|
4772
|
+
const turn = "❯ please summarise the plan\r\n answer: sed do eiusmod tempor\r\n";
|
|
4773
|
+
expect(await stateOf(turn.repeat(3000))).toEqual({
|
|
4774
|
+
kind: "hidden",
|
|
4775
|
+
reason: "its input box is not on screen",
|
|
4776
|
+
});
|
|
4777
|
+
// CLIs without a box keep reading the last prompt row in the 32 KB tail.
|
|
4778
|
+
expect((await stateOf(turn.repeat(3000), "codex")).kind).toBe("draft");
|
|
4779
|
+
});
|
|
4780
|
+
|
|
4781
|
+
it("follows what is appended after the first reading, and a truncated log", async () => {
|
|
4782
|
+
const { readComposerState } = await loadModule();
|
|
4783
|
+
const file = path.join(testHome, "2222.raw.log");
|
|
4784
|
+
const record = { pid: 2222, cli: "claude", log_file: file } as never;
|
|
4785
|
+
await writeFile(file, idleLog(""));
|
|
4786
|
+
expect(await readComposerState(record)).toEqual({ kind: "empty", ghost: false });
|
|
4787
|
+
appendFileSync(file, at(48, "❯ btw how"));
|
|
4788
|
+
expect(await readComposerState(record)).toEqual({ kind: "draft", chars: 6 });
|
|
4789
|
+
appendFileSync(file, at(48, "❯ "));
|
|
4790
|
+
expect(await readComposerState(record)).toEqual({ kind: "empty", ghost: false });
|
|
4791
|
+
const box = `${GRAY}${"─".repeat(COLS)}\x1b[0m\r\n❯ hi\r\n${GRAY}${"─".repeat(COLS)}\x1b[0m\r\n`;
|
|
4792
|
+
await writeFile(file, "x\r\n".repeat(100) + box);
|
|
4793
|
+
expect(await readComposerState(record)).toEqual({ kind: "draft", chars: 2 });
|
|
4794
|
+
});
|
|
4795
|
+
|
|
4796
|
+
it("keeps a typed draft on screen in the 32 KB tail", async () => {
|
|
4797
|
+
const box = `${GRAY}${"─".repeat(COLS)}\x1b[0m\r\n❯ btw how\r\n${GRAY}${"─".repeat(COLS)}\x1b[0m\r\n`;
|
|
4798
|
+
expect(await stateOf("x\r\n".repeat(20000) + box)).toEqual({ kind: "draft", chars: 6 });
|
|
4799
|
+
});
|
|
4800
|
+
});
|
package/ts/subcommands.ts
CHANGED
|
@@ -103,6 +103,7 @@ import { isWithin, resolveWorkDir } from "./workDir.ts";
|
|
|
103
103
|
import {
|
|
104
104
|
bodyHash,
|
|
105
105
|
classifyComposer,
|
|
106
|
+
composerBoxed,
|
|
106
107
|
composerPromptRow,
|
|
107
108
|
DUPLICATE_WINDOW_MS,
|
|
108
109
|
findRecentDuplicate,
|
|
@@ -4302,28 +4303,115 @@ export async function renderLogTailLines(
|
|
|
4302
4303
|
}
|
|
4303
4304
|
}
|
|
4304
4305
|
|
|
4306
|
+
/**
|
|
4307
|
+
* Tail windows the composer check renders, smallest first. Rendering a tail
|
|
4308
|
+
* starts mid-stream, and Claude Code's renderer redraws only the rows that
|
|
4309
|
+
* changed: on a lane that has sat idle for hours the last 32 KB can hold
|
|
4310
|
+
* redraws of transcript rows (an old `❯` turn among them) but not the unchanged
|
|
4311
|
+
* rule and empty prompt row of the composer box, so the old turn was read as
|
|
4312
|
+
* the prompt and the transcript under it as a draft. A Claude screen without
|
|
4313
|
+
* its box is therefore re-rendered from further back, last of all from as far
|
|
4314
|
+
* back as `ay read` renders. When even that shows no box, a draft read under
|
|
4315
|
+
* some other prompt row is reported as "hidden" rather than as a draft: the
|
|
4316
|
+
* send still parks, and the drainer waits for the box.
|
|
4317
|
+
*
|
|
4318
|
+
* Logs run to 100+ MB and the drainer re-checks every few seconds, so the
|
|
4319
|
+
* rendered terminal is kept per log and later checks feed it only the bytes
|
|
4320
|
+
* appended since: each window is rendered at most once per process, and a
|
|
4321
|
+
* screen that stays without a box costs only its new output on every poll.
|
|
4322
|
+
*/
|
|
4323
|
+
export const COMPOSER_WINDOWS = [32 * 1024, 1024 * 1024, 8 * 1024 * 1024, MAX_RENDER_BYTES];
|
|
4324
|
+
|
|
4325
|
+
/** A log's rendered terminal: fed up to `offset`, started from `windows[window]`. */
|
|
4326
|
+
type ComposerTerm = {
|
|
4327
|
+
term: InstanceType<typeof import("@xterm/headless").Terminal>;
|
|
4328
|
+
key: string;
|
|
4329
|
+
window: number;
|
|
4330
|
+
offset: number;
|
|
4331
|
+
whole: boolean;
|
|
4332
|
+
};
|
|
4333
|
+
const composerTerms = new Map<string, ComposerTerm>();
|
|
4334
|
+
const COMPOSER_TERMS_MAX = 64;
|
|
4335
|
+
|
|
4336
|
+
function dropComposerTerm(logPath: string) {
|
|
4337
|
+
composerTerms.get(logPath)?.term.dispose();
|
|
4338
|
+
composerTerms.delete(logPath);
|
|
4339
|
+
}
|
|
4340
|
+
|
|
4305
4341
|
/**
|
|
4306
4342
|
* What the target's composer holds right now, read from the same 32 KB tail
|
|
4307
|
-
* `renderLogTailLines` renders
|
|
4308
|
-
*
|
|
4343
|
+
* `renderLogTailLines` renders (further back when a Claude screen shows no
|
|
4344
|
+
* composer box), keeping per-cell attributes (dim/inverse) so ghost text can be
|
|
4345
|
+
* told from a real draft. See ts/composerGuard.ts.
|
|
4309
4346
|
*/
|
|
4310
|
-
export async function readComposerState(
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4347
|
+
export async function readComposerState(
|
|
4348
|
+
record: GlobalPidRecord,
|
|
4349
|
+
windows = COMPOSER_WINDOWS,
|
|
4350
|
+
): Promise<ComposerState> {
|
|
4351
|
+
const logPath = record.log_file;
|
|
4352
|
+
if (!logPath) return { kind: "unknown", reason: "no log file recorded" };
|
|
4314
4353
|
const geom = (await readAgentPtysize(record)) ?? undefined;
|
|
4354
|
+
const key = `${geom?.cols}x${geom?.rows}:${record.cli}:${windows.join()}`;
|
|
4355
|
+
const claude = record.cli === "claude";
|
|
4315
4356
|
try {
|
|
4316
|
-
const
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
}
|
|
4323
|
-
|
|
4324
|
-
|
|
4357
|
+
const { size } = await stat(logPath);
|
|
4358
|
+
if (size === 0) return { kind: "unknown", reason: "log unreadable or empty" };
|
|
4359
|
+
let ct = composerTerms.get(logPath);
|
|
4360
|
+
if (ct && (ct.key !== key || size < ct.offset)) {
|
|
4361
|
+
dropComposerTerm(logPath); // resized, or the log was truncated
|
|
4362
|
+
ct = undefined;
|
|
4363
|
+
}
|
|
4364
|
+
let rows: ReturnType<typeof rowsFromXterm> | undefined;
|
|
4365
|
+
let next = 0;
|
|
4366
|
+
if (ct) {
|
|
4367
|
+
if (size > ct.offset) {
|
|
4368
|
+
const delta = await readLogRange(logPath, ct.offset, size);
|
|
4369
|
+
await new Promise<void>((resolve) => ct!.term.write(delta, resolve));
|
|
4370
|
+
ct.offset += delta.length;
|
|
4371
|
+
}
|
|
4372
|
+
rows = rowsFromXterm(ct.term as never, 40);
|
|
4373
|
+
next = ct.whole ? windows.length : ct.window + 1;
|
|
4374
|
+
if (!claude || composerBoxed(rows.map((r) => r.text))) next = windows.length;
|
|
4375
|
+
}
|
|
4376
|
+
for (let w = next; w < windows.length; w++) {
|
|
4377
|
+
const from = Math.max(0, size - windows[w]!);
|
|
4378
|
+
const buf = await readLogRange(logPath, from, size);
|
|
4379
|
+
const Terminal = await loadXtermTerminal();
|
|
4380
|
+
const term = new Terminal({
|
|
4381
|
+
cols: geom?.cols && geom.cols > 0 ? geom.cols : 200,
|
|
4382
|
+
rows: geom?.rows && geom.rows > 0 ? geom.rows : 50,
|
|
4383
|
+
scrollback: 1000,
|
|
4384
|
+
allowProposedApi: true,
|
|
4385
|
+
});
|
|
4386
|
+
await new Promise<void>((resolve) => term.write(buf, resolve));
|
|
4387
|
+
dropComposerTerm(logPath);
|
|
4388
|
+
composerTerms.set(logPath, { term, key, window: w, offset: from + buf.length, whole: from === 0 });
|
|
4389
|
+
if (composerTerms.size > COMPOSER_TERMS_MAX)
|
|
4390
|
+
dropComposerTerm(composerTerms.keys().next().value!); // oldest first
|
|
4391
|
+
rows = rowsFromXterm(term as never, 40);
|
|
4392
|
+
if (!claude || from === 0 || composerBoxed(rows.map((r) => r.text))) break;
|
|
4393
|
+
}
|
|
4394
|
+
const state = classifyComposer(rows ?? []);
|
|
4395
|
+
// No window showed the box, so a "draft" was read under some other prompt
|
|
4396
|
+
// row, possibly an old turn: say so instead of reporting it as a draft.
|
|
4397
|
+
if (claude && state.kind === "draft" && !composerBoxed((rows ?? []).map((r) => r.text)))
|
|
4398
|
+
return { kind: "hidden", reason: "its input box is not on screen" };
|
|
4399
|
+
return state;
|
|
4325
4400
|
} catch (e) {
|
|
4326
|
-
|
|
4401
|
+
dropComposerTerm(logPath);
|
|
4402
|
+
return { kind: "unknown", reason: `log unreadable or render failed: ${(e as Error)?.message ?? e}` };
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
|
|
4406
|
+
/** Bytes `[from, to)` of a log file. */
|
|
4407
|
+
async function readLogRange(logPath: string, from: number, to: number): Promise<Uint8Array> {
|
|
4408
|
+
const fh = await open(logPath, "r");
|
|
4409
|
+
try {
|
|
4410
|
+
const buf = Buffer.alloc(Math.max(0, to - from));
|
|
4411
|
+
const { bytesRead } = await fh.read(buf, 0, buf.length, from);
|
|
4412
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, bytesRead);
|
|
4413
|
+
} finally {
|
|
4414
|
+
await fh.close();
|
|
4327
4415
|
}
|
|
4328
4416
|
}
|
|
4329
4417
|
|
|
@@ -5485,6 +5573,7 @@ async function cmdSend(rest: string[]): Promise<number> {
|
|
|
5485
5573
|
const composer = await readComposerState(record);
|
|
5486
5574
|
if (composer.kind === "draft")
|
|
5487
5575
|
parkReason = `its input box holds a draft (${composer.chars} chars)`;
|
|
5576
|
+
else if (composer.kind === "hidden") parkReason = composer.reason;
|
|
5488
5577
|
else if (composer.kind === "unknown")
|
|
5489
5578
|
process.stderr.write(
|
|
5490
5579
|
`warning: ay send could not see pid ${record.pid}'s input box (${composer.reason}) — sending without the draft check.\n`,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./JsonlStore-BqF7AQ6E.js";
|
|
3
|
-
import "./globalPidIndex-CRH9L9tn.js";
|
|
4
|
-
import "./pidStore-DXWqzTSz.js";
|
|
5
|
-
import "./messageLog-Brx3w6zT.js";
|
|
6
|
-
import "./e2e-z1xpwSAg.js";
|
|
7
|
-
import "./configShared-DKTgiz7K.js";
|
|
8
|
-
import { $ as renderRawLog, A as isBareManagerInvocation, B as listRecords, C as extractMenu, D as inspectSubmission, E as finalizedLines, F as isUnknownManagerToken, G as readAgentPtysize, H as menuSelectKeys, I as isUnreachableWriteErrno, J as readNotes, K as readComposerState, L as isUserTyping, M as isPidAlive, N as isSlashCommand, O as isAgentIdShaped, P as isSubcommand, Q as renderLogTailLines, R as lastReadAt, S as extractBadges, T as extractTaskCounts, U as ownedCollapsedPaste, V as matchKeyword, W as probeStdinReachable, X as recentMessageEdges, Y as readPtysize, Z as recentReadEdges, _ as deriveLiveState, a as SEND_BODY_MAX_CHARS, at as runSubcommand, b as envelopeAttribution, c as TYPING_WINDOW_MS, ct as stdinActivityPath, d as cliDefaults, dt as waitForLogQuiet, et as renderRawLogLines, f as cmdHelp, ft as writeKeysPaced, g as cwdLabel, h as cursorAbs, i as READ_WINDOW_MS, it as restartHintLines, j as isExitRequest, k as isAgentStuck, l as backoffWhileTyping, lt as stopTipForCli, m as controlCodeFromName, n as MAX_RENDER_BYTES, nt as resolveReadWindow, o as SEND_EXIT_QUEUED, ot as sendPayloadCapError, p as confirmStdinUnreachable, pt as writeToIpc, q as readLogForRender, r as READ_PAGE_DEFAULT, rt as resolveResumeArgs, s as SEND_EXIT_UNREACHABLE, st as snapshotStatus, t as GRACEFUL_EXIT_COMMANDS, tt as resolveOne, u as buildEnvelope, ut as submitAndConfirm, v as deriveLiveStatus, w as extractNeedsInput, x as envelopeCostFor, y as drainerLauncher, z as lastStdinAt } from "./subcommands-CzSrhEYG.js";
|
|
9
|
-
import "./notifyStore-2SWKGwZI.js";
|
|
10
|
-
import "./webrtcLink-DFRyWNMs.js";
|
|
11
|
-
import "./remotes-B4v0Nowo.js";
|
|
12
|
-
|
|
13
|
-
export { READ_WINDOW_MS, cmdHelp, isBareManagerInvocation, isSubcommand, isUnknownManagerToken, lastReadAt, runSubcommand };
|
package/dist/trayApp-Cx9ktCQ-.js
DELETED