claude-yes 1.170.1 → 1.171.0
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-Bz-oXKG8.js → SUPPORTED_CLIS-CLwNa69l.js} +2 -2
- package/dist/SUPPORTED_CLIS-vi4ofK0T.js +8 -0
- package/dist/cli.js +4 -4
- package/dist/index.js +2 -2
- package/dist/{notifyDaemon-BB08sE7n.js → notifyDaemon-DKoSrGSO.js} +2 -2
- package/dist/{rustBinary-CYS7148m.js → rustBinary-4qI6-ALa.js} +2 -2
- package/dist/{schedule-D4KvBh5w.js → schedule-DclnMR6W.js} +4 -4
- package/dist/{serve-BN0mUK9m.js → serve-B6suh4Mj.js} +8 -6
- package/dist/{setup-CUrjwXNE.js → setup-Bt9v70jO.js} +2 -2
- package/dist/{subcommands-DOnqoHyP.js → subcommands-BG8zmd95.js} +1 -1
- package/dist/{subcommands-CbcBfInM.js → subcommands-CGFVw3RU.js} +6 -6
- package/dist/{ts-kJRKPdFi.js → ts-CJuOKFYC.js} +2 -2
- package/dist/{versionChecker-eVbxzEL3.js → versionChecker-OhTh_a0W.js} +2 -2
- package/lab/ui/console-logic.js +46 -0
- package/lab/ui/index.html +166 -3
- package/package.json +1 -1
- package/ts/serve.ts +14 -0
- package/dist/SUPPORTED_CLIS-Dby-8X2S.js +0 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-CJuOKFYC.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-CLwNa69l.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-CJuOKFYC.js";
|
|
2
|
+
import "./logger-CDIsZ-Pp.js";
|
|
3
|
+
import "./versionChecker-OhTh_a0W.js";
|
|
4
|
+
import "./pidStore-BIvsBQ8X.js";
|
|
5
|
+
import "./globalPidIndex-CoNr7tS8.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CLwNa69l.js";
|
|
7
|
+
|
|
8
|
+
export { SUPPORTED_CLIS };
|
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-OhTh_a0W.js";
|
|
5
|
+
import { n as getRustBinary } from "./rustBinary-4qI6-ALa.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 } = await import("./subcommands-
|
|
288
|
+
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-BG8zmd95.js");
|
|
289
289
|
if (isHelpFlag && process.argv.length === 3) {
|
|
290
290
|
await cmdHelp(managerCommands);
|
|
291
291
|
process.exit(0);
|
|
@@ -327,7 +327,7 @@ if (config.useRust) {
|
|
|
327
327
|
}
|
|
328
328
|
}
|
|
329
329
|
if (rustBinary) {
|
|
330
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
330
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-vi4ofK0T.js");
|
|
331
331
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
332
332
|
if (config.verbose) {
|
|
333
333
|
console.log(`[rust] Using binary: ${rustBinary}`);
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-CJuOKFYC.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-OhTh_a0W.js";
|
|
4
4
|
import "./pidStore-BIvsBQ8X.js";
|
|
5
5
|
import "./globalPidIndex-CoNr7tS8.js";
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as logger } from "./logger-CDIsZ-Pp.js";
|
|
2
2
|
import "./globalPidIndex-CoNr7tS8.js";
|
|
3
3
|
import "./configShared-0MnIQ652.js";
|
|
4
|
-
import { D as renderLogTailLines, G as hostId, J as readInbox, K as listInboxParents, Q as notifyDir, S as listRecords, U as appendEvent, W as gcInboxes, X as daemonLockDir, Y as shouldStealLock, Z as daemonLockOwnerPath, _ as isPidAlive, c as deriveLiveState, q as liveWatchers } from "./subcommands-
|
|
4
|
+
import { D as renderLogTailLines, G as hostId, J as readInbox, K as listInboxParents, Q as notifyDir, S as listRecords, U as appendEvent, W as gcInboxes, X as daemonLockDir, Y as shouldStealLock, Z as daemonLockOwnerPath, _ as isPidAlive, c as deriveLiveState, q as liveWatchers } from "./subcommands-CGFVw3RU.js";
|
|
5
5
|
import "./e2e-jb0Hp43q.js";
|
|
6
6
|
import "./webrtcLink-B7REGtK2.js";
|
|
7
7
|
import "./remotes-CC-4GuJb.js";
|
|
@@ -588,4 +588,4 @@ async function ensureDaemon() {
|
|
|
588
588
|
|
|
589
589
|
//#endregion
|
|
590
590
|
export { daemonStatus, ensureDaemon, requestDaemonStop, runDaemon };
|
|
591
|
-
//# sourceMappingURL=notifyDaemon-
|
|
591
|
+
//# sourceMappingURL=notifyDaemon-DKoSrGSO.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
1
|
+
import { r as getInstalledPackage } from "./versionChecker-OhTh_a0W.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-4qI6-ALa.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-CJuOKFYC.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-OhTh_a0W.js";
|
|
4
4
|
import "./pidStore-BIvsBQ8X.js";
|
|
5
5
|
import "./globalPidIndex-CoNr7tS8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CLwNa69l.js";
|
|
7
7
|
import { d as resolveSpawnCwd } from "./workspaceConfig-BgqK-31W.js";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
|
|
@@ -141,4 +141,4 @@ async function cmdSchedule(rest) {
|
|
|
141
141
|
|
|
142
142
|
//#endregion
|
|
143
143
|
export { cmdSchedule };
|
|
144
|
-
//# sourceMappingURL=schedule-
|
|
144
|
+
//# sourceMappingURL=schedule-DclnMR6W.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-CJuOKFYC.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
4
|
-
import { t as findSpawnHiddenLauncher } from "./rustBinary-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-OhTh_a0W.js";
|
|
4
|
+
import { t as findSpawnHiddenLauncher } from "./rustBinary-4qI6-ALa.js";
|
|
5
5
|
import "./pidStore-BIvsBQ8X.js";
|
|
6
6
|
import { a as updateGlobalPidStatus } from "./globalPidIndex-CoNr7tS8.js";
|
|
7
7
|
import { t as pgidForWrapper } from "./reaper-CWF2_ATd.js";
|
|
8
8
|
import "./configShared-0MnIQ652.js";
|
|
9
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
10
|
-
import { A as resolveOne, E as readPtysize, F as snapshotStatus, H as TYPING_BADGE, O as renderRawLog, S as listRecords, T as readNotes, V as writeToIpc, b as isUserTyping, f as extractNeedsInput, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, u as extractBadges } from "./subcommands-
|
|
9
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CLwNa69l.js";
|
|
10
|
+
import { A as resolveOne, E as readPtysize, F as snapshotStatus, H as TYPING_BADGE, O as renderRawLog, S as listRecords, T as readNotes, V as writeToIpc, b as isUserTyping, f as extractNeedsInput, l as deriveLiveStatus, o as controlCodeFromName, p as extractTaskCounts, u as extractBadges } from "./subcommands-CGFVw3RU.js";
|
|
11
11
|
import "./e2e-jb0Hp43q.js";
|
|
12
12
|
import "./webrtcLink-B7REGtK2.js";
|
|
13
13
|
import "./remotes-CC-4GuJb.js";
|
|
@@ -849,9 +849,11 @@ Options:
|
|
|
849
849
|
const status = await deriveLiveStatus(r);
|
|
850
850
|
const question = status !== "exited" && !r.unresponsive ? await logNeedsInput(r.log_file, r.cli) : null;
|
|
851
851
|
const lastActiveAt = r.log_file ? await stat(r.log_file).then((s) => s.mtimeMs).catch(() => r.started_at) : r.started_at;
|
|
852
|
+
const lastStdinAt = status !== "exited" && r.fifo_file ? await stat(r.fifo_file).then((s) => s.mtimeMs).catch(() => null) : null;
|
|
852
853
|
return {
|
|
853
854
|
...r,
|
|
854
855
|
last_active_at: lastActiveAt,
|
|
856
|
+
last_stdin_at: lastStdinAt,
|
|
855
857
|
status: status === "exited" ? status : r.unresponsive ? "stuck" : question ? "needs_input" : status,
|
|
856
858
|
question,
|
|
857
859
|
title: await logTitle(r.log_file),
|
|
@@ -1558,4 +1560,4 @@ Options:
|
|
|
1558
1560
|
|
|
1559
1561
|
//#endregion
|
|
1560
1562
|
export { cmdServe };
|
|
1561
|
-
//# sourceMappingURL=serve-
|
|
1563
|
+
//# sourceMappingURL=serve-B6suh4Mj.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-B6suh4Mj.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-Bt9v70jO.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
2
|
import "./globalPidIndex-CoNr7tS8.js";
|
|
3
3
|
import "./configShared-0MnIQ652.js";
|
|
4
|
-
import { A as resolveOne, B as writeKeysPaced, C as matchKeyword, D as renderLogTailLines, E as readPtysize, F as snapshotStatus, I as stdinActivityPath, L as stopTipForCli, M as resolveResumeArgs, N as restartHintLines, O as renderRawLog, P as runSubcommand, R as submitAndConfirm, S as listRecords, T as readNotes, V as writeToIpc, _ as isPidAlive, a as cmdHelp, b as isUserTyping, c as deriveLiveState, d as extractMenu, f as extractNeedsInput, g as isExitRequest, h as isAgentStuck, i as backoffWhileTyping, j as resolveReadWindow, k as renderRawLogLines, 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 menuSelectKeys, x as lastStdinAt, y as isSubcommand, z as waitForLogQuiet } from "./subcommands-
|
|
4
|
+
import { A as resolveOne, B as writeKeysPaced, C as matchKeyword, D as renderLogTailLines, E as readPtysize, F as snapshotStatus, I as stdinActivityPath, L as stopTipForCli, M as resolveResumeArgs, N as restartHintLines, O as renderRawLog, P as runSubcommand, R as submitAndConfirm, S as listRecords, T as readNotes, V as writeToIpc, _ as isPidAlive, a as cmdHelp, b as isUserTyping, c as deriveLiveState, d as extractMenu, f as extractNeedsInput, g as isExitRequest, h as isAgentStuck, i as backoffWhileTyping, j as resolveReadWindow, k as renderRawLogLines, 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 menuSelectKeys, x as lastStdinAt, y as isSubcommand, z as waitForLogQuiet } from "./subcommands-CGFVw3RU.js";
|
|
5
5
|
import "./e2e-jb0Hp43q.js";
|
|
6
6
|
import "./webrtcLink-B7REGtK2.js";
|
|
7
7
|
import "./remotes-CC-4GuJb.js";
|
|
@@ -1126,15 +1126,15 @@ async function runSubcommand(argv) {
|
|
|
1126
1126
|
case "restart": return await cmdRestart(rest);
|
|
1127
1127
|
case "note": return await cmdNote(rest);
|
|
1128
1128
|
case "serve": {
|
|
1129
|
-
const { cmdServe } = await import("./serve-
|
|
1129
|
+
const { cmdServe } = await import("./serve-B6suh4Mj.js");
|
|
1130
1130
|
return cmdServe(rest);
|
|
1131
1131
|
}
|
|
1132
1132
|
case "setup": {
|
|
1133
|
-
const { cmdSetup } = await import("./setup-
|
|
1133
|
+
const { cmdSetup } = await import("./setup-Bt9v70jO.js");
|
|
1134
1134
|
return cmdSetup(rest);
|
|
1135
1135
|
}
|
|
1136
1136
|
case "schedule": {
|
|
1137
|
-
const { cmdSchedule } = await import("./schedule-
|
|
1137
|
+
const { cmdSchedule } = await import("./schedule-DclnMR6W.js");
|
|
1138
1138
|
return cmdSchedule(rest);
|
|
1139
1139
|
}
|
|
1140
1140
|
case "remote": {
|
|
@@ -3963,7 +3963,7 @@ async function cmdNotify(rest) {
|
|
|
3963
3963
|
}
|
|
3964
3964
|
const ensure = async () => {
|
|
3965
3965
|
if (!argv["ensure-daemon"]) return;
|
|
3966
|
-
const { ensureDaemon } = await import("./notifyDaemon-
|
|
3966
|
+
const { ensureDaemon } = await import("./notifyDaemon-DKoSrGSO.js");
|
|
3967
3967
|
await ensureDaemon().catch(() => null);
|
|
3968
3968
|
};
|
|
3969
3969
|
await heartbeatWatcher(parent, selfStartedAt);
|
|
@@ -4037,7 +4037,7 @@ async function cmdNotifyCursor(args) {
|
|
|
4037
4037
|
}
|
|
4038
4038
|
async function cmdNotifyd(rest) {
|
|
4039
4039
|
const sub = rest[0] ?? "status";
|
|
4040
|
-
const daemon = await import("./notifyDaemon-
|
|
4040
|
+
const daemon = await import("./notifyDaemon-DKoSrGSO.js");
|
|
4041
4041
|
switch (sub) {
|
|
4042
4042
|
case "run": return daemon.runDaemon();
|
|
4043
4043
|
case "once": return daemon.runDaemon({ once: true });
|
|
@@ -4064,4 +4064,4 @@ async function cmdNotifyd(rest) {
|
|
|
4064
4064
|
|
|
4065
4065
|
//#endregion
|
|
4066
4066
|
export { resolveOne as A, writeKeysPaced as B, matchKeyword as C, renderLogTailLines as D, readPtysize as E, snapshotStatus as F, hostId as G, TYPING_BADGE as H, stdinActivityPath as I, readInbox as J, listInboxParents as K, stopTipForCli as L, resolveResumeArgs as M, restartHintLines as N, renderRawLog as O, runSubcommand as P, notifyDir as Q, submitAndConfirm as R, listRecords as S, readNotes as T, appendEvent as U, writeToIpc as V, gcInboxes as W, daemonLockDir as X, shouldStealLock as Y, daemonLockOwnerPath as Z, isPidAlive as _, cmdHelp as a, isUserTyping as b, deriveLiveState as c, extractMenu as d, extractNeedsInput as f, isExitRequest as g, isAgentStuck as h, backoffWhileTyping as i, resolveReadWindow as j, renderRawLogLines as k, deriveLiveStatus as l, finalizedLines as m, READ_PAGE_DEFAULT as n, controlCodeFromName as o, extractTaskCounts as p, liveWatchers as q, TYPING_WINDOW_MS as r, cursorAbs as s, GRACEFUL_EXIT_COMMANDS as t, extractBadges as u, isSlashCommand as v, menuSelectKeys as w, lastStdinAt as x, isSubcommand as y, waitForLogQuiet as z };
|
|
4067
|
-
//# sourceMappingURL=subcommands-
|
|
4067
|
+
//# sourceMappingURL=subcommands-CGFVw3RU.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as logger, t as addTransport } from "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
2
|
+
import { r as getInstalledPackage } from "./versionChecker-OhTh_a0W.js";
|
|
3
3
|
import { t as agentYesHome } from "./agentYesHome-CtHb5b71.js";
|
|
4
4
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-CNMl13dC.js";
|
|
5
5
|
import { t as PidStore } from "./pidStore-BIvsBQ8X.js";
|
|
@@ -1824,4 +1824,4 @@ function sleep(ms) {
|
|
|
1824
1824
|
|
|
1825
1825
|
//#endregion
|
|
1826
1826
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1827
|
-
//# sourceMappingURL=ts-
|
|
1827
|
+
//# sourceMappingURL=ts-CJuOKFYC.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.
|
|
10
|
+
var version = "1.171.0";
|
|
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-OhTh_a0W.js.map
|
package/lab/ui/console-logic.js
CHANGED
|
@@ -549,6 +549,52 @@ export function nextIndex(len, i, dir) {
|
|
|
549
549
|
// coordinate math lives here so it's unit-testable without a browser.
|
|
550
550
|
// ---------------------------------------------------------------------------
|
|
551
551
|
|
|
552
|
+
// ---- collaborative presence: peer focus + stdin flash ----------------------
|
|
553
|
+
// The left panel colour-codes who's on which agent: your own selection is blue
|
|
554
|
+
// (the .sel bar), every OTHER human peer's focus is yellow (.peerfocus), and a
|
|
555
|
+
// row pulses when its stdin was just written — independent of focus, since an
|
|
556
|
+
// `ay send` feeds an agent no one is looking at. These pure helpers own the
|
|
557
|
+
// bookkeeping so index.html only measures the DOM.
|
|
558
|
+
|
|
559
|
+
// Detect agents whose stdin just advanced. `seen` maps _key -> the last
|
|
560
|
+
// last_stdin_at we observed; given the current entries, return the _keys whose
|
|
561
|
+
// last_stdin_at is NEWER than what we'd seen (someone typed / `ay send` pushed),
|
|
562
|
+
// and fold the new values into `seen`. A key seen for the FIRST time never
|
|
563
|
+
// flashes (else every agent would pulse on initial load) — only a later bump
|
|
564
|
+
// does. Keys no longer present are pruned so `seen` can't grow without bound.
|
|
565
|
+
export function advanceStdinFlashes(entries, seen) {
|
|
566
|
+
const fresh = [];
|
|
567
|
+
const alive = new Set();
|
|
568
|
+
for (const e of entries) {
|
|
569
|
+
const key = e._key;
|
|
570
|
+
if (!key) continue;
|
|
571
|
+
alive.add(key);
|
|
572
|
+
const at = e.last_stdin_at;
|
|
573
|
+
if (typeof at !== "number") continue;
|
|
574
|
+
const prev = seen.get(key);
|
|
575
|
+
if (prev !== undefined && at > prev) fresh.push(key);
|
|
576
|
+
if (prev === undefined || at > prev) seen.set(key, at);
|
|
577
|
+
}
|
|
578
|
+
for (const key of [...seen.keys()]) if (!alive.has(key)) seen.delete(key);
|
|
579
|
+
return fresh;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Summarize fleet presence for the peers badge + per-row chips. `records` is one
|
|
583
|
+
// entry per OTHER viewer currently watching an agent: { key, viewer } (key = the
|
|
584
|
+
// composite _key of the agent they're on). Returns { total, byKey }: `total`
|
|
585
|
+
// distinct viewers (the "N peers" badge), `byKey` a Map of _key -> how many
|
|
586
|
+
// peers watch that agent (the yellow per-row chip + .peerfocus trigger).
|
|
587
|
+
export function focusSummary(records) {
|
|
588
|
+
const viewers = new Set();
|
|
589
|
+
const byKey = new Map();
|
|
590
|
+
for (const r of records) {
|
|
591
|
+
if (!r || !r.key || !r.viewer) continue;
|
|
592
|
+
viewers.add(r.viewer);
|
|
593
|
+
byKey.set(r.key, (byKey.get(r.key) || 0) + 1);
|
|
594
|
+
}
|
|
595
|
+
return { total: viewers.size, byKey };
|
|
596
|
+
}
|
|
597
|
+
|
|
552
598
|
// Stable per-viewer hue (0..359) for colour-coding peers' selections.
|
|
553
599
|
export function hashHue(s) {
|
|
554
600
|
let h = 0;
|
package/lab/ui/index.html
CHANGED
|
@@ -37,6 +37,9 @@
|
|
|
37
37
|
--purple: #bc8cff;
|
|
38
38
|
--pink: #f778ba;
|
|
39
39
|
--red: #f85149;
|
|
40
|
+
/* Peer-focus yellow: a human collaborator (not you) is on this agent.
|
|
41
|
+
Distinct from your own blue (--accent) and the idle-dot amber. */
|
|
42
|
+
--peer: #e3b341;
|
|
40
43
|
--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
41
44
|
/* Safe-area insets — non-zero only in a standalone PWA on a notched /
|
|
42
45
|
gesture-bar device (else 0, so these are harmless on desktop). Consumed
|
|
@@ -70,6 +73,7 @@
|
|
|
70
73
|
--purple: #8250df;
|
|
71
74
|
--pink: #bf3989;
|
|
72
75
|
--red: #cf222e;
|
|
76
|
+
--peer: #bf8700;
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
* {
|
|
@@ -420,6 +424,21 @@
|
|
|
420
424
|
font-size: 11.5px;
|
|
421
425
|
margin-top: 8px;
|
|
422
426
|
}
|
|
427
|
+
.metaleft {
|
|
428
|
+
display: inline-flex;
|
|
429
|
+
align-items: center;
|
|
430
|
+
gap: 8px;
|
|
431
|
+
}
|
|
432
|
+
/* Peers badge beside the agent counter — how many other humans are in the
|
|
433
|
+
fleet right now. Yellow ("here") when a peer shares the agent you have
|
|
434
|
+
open, muted otherwise. Hidden entirely when you're alone. */
|
|
435
|
+
.peers {
|
|
436
|
+
color: var(--muted);
|
|
437
|
+
cursor: default;
|
|
438
|
+
}
|
|
439
|
+
.peers.here {
|
|
440
|
+
color: var(--peer);
|
|
441
|
+
}
|
|
423
442
|
.connbadge {
|
|
424
443
|
cursor: pointer;
|
|
425
444
|
user-select: none;
|
|
@@ -818,6 +837,39 @@
|
|
|
818
837
|
background: var(--panel);
|
|
819
838
|
box-shadow: inset 3px 0 0 var(--accent);
|
|
820
839
|
}
|
|
840
|
+
/* A human peer (not you) is watching this agent: yellow, mirrored on the
|
|
841
|
+
RIGHT edge so it can coexist with your own blue selection bar on the
|
|
842
|
+
left — a row you BOTH have open shows blue-left + yellow-right. */
|
|
843
|
+
.row.peerfocus {
|
|
844
|
+
box-shadow: inset -3px 0 0 var(--peer);
|
|
845
|
+
background: color-mix(in srgb, var(--peer) 7%, transparent);
|
|
846
|
+
}
|
|
847
|
+
.row.sel.peerfocus {
|
|
848
|
+
background: var(--panel);
|
|
849
|
+
box-shadow: inset 3px 0 0 var(--accent), inset -3px 0 0 var(--peer);
|
|
850
|
+
}
|
|
851
|
+
/* stdin just landed here (someone typed, or `ay send` pushed a command) —
|
|
852
|
+
pulse the row regardless of who (if anyone) is focused on it. Runs while
|
|
853
|
+
the .stdinflash class is present; index.html removes it after the window. */
|
|
854
|
+
.row.stdinflash {
|
|
855
|
+
animation: stdinpulse 0.6s ease-in-out infinite;
|
|
856
|
+
}
|
|
857
|
+
@keyframes stdinpulse {
|
|
858
|
+
0%,
|
|
859
|
+
100% {
|
|
860
|
+
background-color: transparent;
|
|
861
|
+
}
|
|
862
|
+
50% {
|
|
863
|
+
background-color: color-mix(in srgb, var(--peer) 24%, transparent);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
/* Per-row chip: how many peers are watching THIS agent (yellow, mono). */
|
|
867
|
+
.peerchip {
|
|
868
|
+
font-family: var(--mono);
|
|
869
|
+
font-size: 11px;
|
|
870
|
+
color: var(--peer);
|
|
871
|
+
flex: none;
|
|
872
|
+
}
|
|
821
873
|
.r1 {
|
|
822
874
|
display: flex;
|
|
823
875
|
align-items: center;
|
|
@@ -1392,7 +1444,10 @@
|
|
|
1392
1444
|
/>
|
|
1393
1445
|
</div>
|
|
1394
1446
|
<div class="meta">
|
|
1395
|
-
<span
|
|
1447
|
+
<span class="metaleft">
|
|
1448
|
+
<span id="count"></span>
|
|
1449
|
+
<span id="peers" class="peers" hidden></span>
|
|
1450
|
+
</span>
|
|
1396
1451
|
<span class="metaright">
|
|
1397
1452
|
<button id="foldbtn" class="viewbtn" title="fold subagent trees">⊞ subs</button>
|
|
1398
1453
|
<button id="sortbtn" class="viewbtn" title="cycle sort order">⇅ state</button>
|
|
@@ -1584,6 +1639,8 @@
|
|
|
1584
1639
|
SORT_MODES,
|
|
1585
1640
|
taskLabel,
|
|
1586
1641
|
badgesFor,
|
|
1642
|
+
advanceStdinFlashes,
|
|
1643
|
+
focusSummary,
|
|
1587
1644
|
hashHue,
|
|
1588
1645
|
selFromBottom,
|
|
1589
1646
|
parseSel,
|
|
@@ -1610,6 +1667,17 @@
|
|
|
1610
1667
|
|
|
1611
1668
|
let entries = [];
|
|
1612
1669
|
let sel = null; // selected agent's composite key (room#pid)
|
|
1670
|
+
// Collaborative presence, fleet-wide: focusByKey maps an agent's _key ->
|
|
1671
|
+
// how many OTHER human peers are watching it (yellow bars + per-row chip);
|
|
1672
|
+
// peerTotal is the distinct-peer count for the header badge. stdinSeen +
|
|
1673
|
+
// flashUntil drive the stdin pulse: stdinSeen remembers each agent's last
|
|
1674
|
+
// last_stdin_at so we can spot a bump, flashUntil holds the deadline the
|
|
1675
|
+
// row keeps pulsing to. See advanceStdinFlashes/focusSummary (console-logic).
|
|
1676
|
+
let focusByKey = new Map();
|
|
1677
|
+
let peerTotal = 0;
|
|
1678
|
+
const stdinSeen = new Map();
|
|
1679
|
+
const flashUntil = new Map();
|
|
1680
|
+
const STDIN_FLASH_MS = 1200;
|
|
1613
1681
|
let es = null; // live-tail subscription closer
|
|
1614
1682
|
let term = null; // xterm.js Terminal rendering the raw PTY stream
|
|
1615
1683
|
let fit = null;
|
|
@@ -2713,10 +2781,65 @@
|
|
|
2713
2781
|
}
|
|
2714
2782
|
renderPeerSelections();
|
|
2715
2783
|
}
|
|
2784
|
+
// Fleet-wide presence: unlike pollPresence (only the SELECTED agent's host,
|
|
2785
|
+
// for the terminal overlay), this reads EVERY live source's blackboard so
|
|
2786
|
+
// the left panel can colour any agent a peer is watching. Each viewer
|
|
2787
|
+
// self-reports the pid it's on; we map that back to the source's composite
|
|
2788
|
+
// _key. Best-effort — a source that 404s (older host) contributes nothing.
|
|
2789
|
+
async function pollFleetPresence() {
|
|
2790
|
+
const recs = [];
|
|
2791
|
+
await Promise.all(
|
|
2792
|
+
[...sources.values()].map(async (s) => {
|
|
2793
|
+
if (!s.tx || !s.live) return;
|
|
2794
|
+
let all;
|
|
2795
|
+
try {
|
|
2796
|
+
all = await s.tx.fetchJSON("/api/presence");
|
|
2797
|
+
} catch {
|
|
2798
|
+
return;
|
|
2799
|
+
}
|
|
2800
|
+
if (!Array.isArray(all)) return;
|
|
2801
|
+
const keyOfPid = new Map((s.agents || []).map((e) => [String(e.pid), e._key]));
|
|
2802
|
+
for (const v of all) {
|
|
2803
|
+
if (!v || v.viewer === myViewerId) continue;
|
|
2804
|
+
const key = keyOfPid.get(String(v.agent));
|
|
2805
|
+
// Prefix the viewer id with its source so the same id on two hosts
|
|
2806
|
+
// still counts as two distinct people in the fleet total.
|
|
2807
|
+
if (key) recs.push({ key, viewer: s.id + ":" + v.viewer });
|
|
2808
|
+
}
|
|
2809
|
+
}),
|
|
2810
|
+
);
|
|
2811
|
+
const sum = focusSummary(recs);
|
|
2812
|
+
focusByKey = sum.byKey;
|
|
2813
|
+
peerTotal = sum.total;
|
|
2814
|
+
paintPeersBadge();
|
|
2815
|
+
renderList();
|
|
2816
|
+
}
|
|
2817
|
+
// "N peers" badge beside the agent counter. Yellow when a peer shares the
|
|
2818
|
+
// agent you have open ("same agent"); its tooltip breaks the count down by
|
|
2819
|
+
// agent so you can see who's where. Hidden when you're the only one here.
|
|
2820
|
+
function paintPeersBadge() {
|
|
2821
|
+
const el = $("peers");
|
|
2822
|
+
if (!el) return;
|
|
2823
|
+
if (!peerTotal) {
|
|
2824
|
+
el.hidden = true;
|
|
2825
|
+
el.removeAttribute("title");
|
|
2826
|
+
return;
|
|
2827
|
+
}
|
|
2828
|
+
el.hidden = false;
|
|
2829
|
+
el.textContent = `👤 ${peerTotal} peer${peerTotal === 1 ? "" : "s"}`;
|
|
2830
|
+
el.classList.toggle("here", !!(sel && focusByKey.get(sel)));
|
|
2831
|
+
const lines = [...focusByKey.entries()].map(([k, n]) => {
|
|
2832
|
+
const e = entries.find((x) => x._key === k);
|
|
2833
|
+
const name = e ? e.title || cliLabel(e) || ident(e) || `pid ${e.pid}` : k;
|
|
2834
|
+
return ` ${n} on ${name}`;
|
|
2835
|
+
});
|
|
2836
|
+
el.title = "peers watching agents in this fleet:\n" + lines.join("\n");
|
|
2837
|
+
}
|
|
2716
2838
|
// 3s heartbeat (< the host's 12s TTL): refresh our presence + read others',
|
|
2717
2839
|
// and follow the canonical grid size (resize+scale, never reflow) so all
|
|
2718
2840
|
// viewers stay on one shared canvas and selections line up.
|
|
2719
2841
|
setInterval(() => {
|
|
2842
|
+
pollFleetPresence(); // fleet-wide peer focus (independent of what's selected)
|
|
2720
2843
|
if (!sel) return;
|
|
2721
2844
|
sendPresence();
|
|
2722
2845
|
pollPresence();
|
|
@@ -2727,6 +2850,20 @@
|
|
|
2727
2850
|
.then(followAgentSize)
|
|
2728
2851
|
.catch(() => {});
|
|
2729
2852
|
}, 3000);
|
|
2853
|
+
// Fast pulse loop: drive the stdin flash on the STABLE list DOM (toggle a
|
|
2854
|
+
// class, no re-render) so a pulse begins/ends promptly regardless of the
|
|
2855
|
+
// list's own render cadence. Cheap — a no-op until something is flashing.
|
|
2856
|
+
setInterval(() => {
|
|
2857
|
+
if (!flashUntil.size) return;
|
|
2858
|
+
const now = Date.now();
|
|
2859
|
+
for (const [k, until] of [...flashUntil.entries()]) if (until <= now) flashUntil.delete(k);
|
|
2860
|
+
const listEl = $("list");
|
|
2861
|
+
if (!listEl) return;
|
|
2862
|
+
for (const el of listEl.querySelectorAll(".row[data-key]")) {
|
|
2863
|
+
const on = (flashUntil.get(el.getAttribute("data-key")) || 0) > now;
|
|
2864
|
+
el.classList.toggle("stdinflash", on);
|
|
2865
|
+
}
|
|
2866
|
+
}, 200);
|
|
2730
2867
|
|
|
2731
2868
|
// Peer-selection overlay. The coordinate math (parseSel / selSegments /
|
|
2732
2869
|
// hashHue) lives in console-logic.js (unit-tested); here we just measure the
|
|
@@ -3311,6 +3448,22 @@
|
|
|
3311
3448
|
return `<div class="ghead g-${r.kind}">${r.branch ? `<span class="tbranch">${esc(r.branch)}</span>` : ""}<span class="gicon">${icon}</span><span class="glabel">${esc(r.label || "")}</span>${ctag}<span class="gkind">${r.kind}</span></div>`;
|
|
3312
3449
|
}
|
|
3313
3450
|
|
|
3451
|
+
// Extra row classes for collaborative presence: a yellow bar when a human
|
|
3452
|
+
// peer is watching this agent, plus the stdin pulse while its input just
|
|
3453
|
+
// advanced. Empty in the solo case, so a single-user list is unchanged.
|
|
3454
|
+
function rowFlags(e) {
|
|
3455
|
+
const peers = focusByKey.get(e._key) || 0;
|
|
3456
|
+
const flash = (flashUntil.get(e._key) || 0) > Date.now();
|
|
3457
|
+
return (peers ? " peerfocus" : "") + (flash ? " stdinflash" : "");
|
|
3458
|
+
}
|
|
3459
|
+
// A yellow chip showing how many peers are watching this agent ("" if none).
|
|
3460
|
+
function peerChipHtml(e) {
|
|
3461
|
+
const n = focusByKey.get(e._key) || 0;
|
|
3462
|
+
return n
|
|
3463
|
+
? `<span class="peerchip" title="${n} peer${n === 1 ? "" : "s"} watching this agent">👤${n}</span>`
|
|
3464
|
+
: "";
|
|
3465
|
+
}
|
|
3466
|
+
|
|
3314
3467
|
function renderList() {
|
|
3315
3468
|
const toks = $("q").value.trim().split(/\s+/).filter(Boolean);
|
|
3316
3469
|
// Build the full signalling-server > rooms > peers > agents > subagents
|
|
@@ -3325,6 +3478,7 @@
|
|
|
3325
3478
|
? fullRows.filter((r) => !(r.kind === "agent" && r.parentEntry))
|
|
3326
3479
|
: fullRows;
|
|
3327
3480
|
$("count").textContent = `${agentRows.length} / ${entries.length} agents`;
|
|
3481
|
+
paintPeersBadge(); // keep the peers badge in step with sel / the entry list
|
|
3328
3482
|
$("foldbtn").textContent = foldSubs ? "⊞ subs" : "⊟ subs";
|
|
3329
3483
|
$("foldbtn").classList.toggle("on", !foldSubs);
|
|
3330
3484
|
$("viewbtn").classList.toggle("on", compactList);
|
|
@@ -3347,7 +3501,7 @@
|
|
|
3347
3501
|
const t = e.title || e.prompt || "";
|
|
3348
3502
|
const id = compactIdent(e, ctx, 3, r.parentEntry);
|
|
3349
3503
|
const cli = cliLabel(e);
|
|
3350
|
-
return `<div class="row crow ${e._key === sel ? "sel" : ""}" data-key="${esc(e._key)}">
|
|
3504
|
+
return `<div class="row crow ${e._key === sel ? "sel" : ""}${rowFlags(e)}" data-key="${esc(e._key)}">
|
|
3351
3505
|
${r.branch ? `<span class="tbranch">${esc(r.branch)}</span>` : ""}
|
|
3352
3506
|
<span class="dot ${esc(e.status)}"></span>
|
|
3353
3507
|
${hasIdent(id) ? `<span class="cident" title="${esc(fullIdent(e))}">${esc(id)}</span>` : ""}
|
|
@@ -3357,6 +3511,7 @@
|
|
|
3357
3511
|
${taskChipHtml(e)}
|
|
3358
3512
|
${badgeChipsHtml(e)}
|
|
3359
3513
|
${gitChipHtml(e)}
|
|
3514
|
+
${peerChipHtml(e)}
|
|
3360
3515
|
<span class="age">${age(e)}</span></div>`;
|
|
3361
3516
|
})
|
|
3362
3517
|
.join("") || `<div class="empty">no match</div>`;
|
|
@@ -3376,7 +3531,7 @@
|
|
|
3376
3531
|
`<span class="rtag" data-k="${k}"><span style="opacity:.55">${k}:</span>${esc(v)}</span>`,
|
|
3377
3532
|
)
|
|
3378
3533
|
.join("");
|
|
3379
|
-
return `<div class="row ${e._key === sel ? "sel" : ""}" data-key="${esc(e._key)}">
|
|
3534
|
+
return `<div class="row ${e._key === sel ? "sel" : ""}${rowFlags(e)}" data-key="${esc(e._key)}">
|
|
3380
3535
|
<div class="r1">${r.branch ? `<span class="tbranch">${esc(r.branch)}</span>` : ""}<span class="dot ${esc(e.status)}"></span>
|
|
3381
3536
|
<span class="name">${esc(cliLabel(e) || ident(e) || "agent")}</span>
|
|
3382
3537
|
<span class="badge">pid ${e.pid}</span>
|
|
@@ -3384,6 +3539,7 @@
|
|
|
3384
3539
|
${taskChipHtml(e)}
|
|
3385
3540
|
${badgeChipsHtml(e)}
|
|
3386
3541
|
${gitChipHtml(e)}
|
|
3542
|
+
${peerChipHtml(e)}
|
|
3387
3543
|
<span class="age">${age(e)}</span></div>
|
|
3388
3544
|
${e.title ? `<div class="rowtitle" title="${esc(e.title)}">${esc(e.title)}</div>` : ""}
|
|
3389
3545
|
${
|
|
@@ -3445,6 +3601,13 @@
|
|
|
3445
3601
|
function mergeRender() {
|
|
3446
3602
|
const srcs = [...sources.values()];
|
|
3447
3603
|
entries = srcs.flatMap((s) => s.agents || []);
|
|
3604
|
+
// Spot agents whose stdin just advanced (last_stdin_at bumped since we
|
|
3605
|
+
// last saw them — someone typed, or `ay send` pushed input) and arm the
|
|
3606
|
+
// pulse. Runs before renderList so the flashing rows render pulsing; the
|
|
3607
|
+
// fast loop above stops them when the window lapses. Streamed deltas carry
|
|
3608
|
+
// the new mtime, so a silent `ay send` still trips the flash within ~1s.
|
|
3609
|
+
const until = Date.now() + STDIN_FLASH_MS;
|
|
3610
|
+
for (const k of advanceStdinFlashes(entries, stdinSeen)) flashUntil.set(k, until);
|
|
3448
3611
|
// Badge: total agents + how many rooms are live. Red only when nothing
|
|
3449
3612
|
// at all is reachable (no source answered).
|
|
3450
3613
|
const roomSrcs = srcs.filter((s) => s.id !== LOCAL);
|
package/package.json
CHANGED
package/ts/serve.ts
CHANGED
|
@@ -1255,9 +1255,23 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
1255
1255
|
.then((s) => s.mtimeMs)
|
|
1256
1256
|
.catch(() => r.started_at)
|
|
1257
1257
|
: r.started_at;
|
|
1258
|
+
// Last-stdin time: the mtime of the agent's stdin FIFO, which the kernel
|
|
1259
|
+
// bumps on EVERY write to it — the console composer, a remote `ay send`, or
|
|
1260
|
+
// a peer's `ay send` all funnel through writeToIpc(fifo_file, …). So this is
|
|
1261
|
+
// a source-agnostic "someone just fed this agent input" signal, distinct from
|
|
1262
|
+
// last_active_at (stdout). The console flashes a row when it advances, so a
|
|
1263
|
+
// collaborator sees keystrokes land even when they weren't the one typing.
|
|
1264
|
+
// Null when there's no live input pipe (exited, or no fifo yet).
|
|
1265
|
+
const lastStdinAt =
|
|
1266
|
+
status !== "exited" && r.fifo_file
|
|
1267
|
+
? await stat(r.fifo_file)
|
|
1268
|
+
.then((s) => s.mtimeMs)
|
|
1269
|
+
.catch(() => null)
|
|
1270
|
+
: null;
|
|
1258
1271
|
return {
|
|
1259
1272
|
...r,
|
|
1260
1273
|
last_active_at: lastActiveAt,
|
|
1274
|
+
last_stdin_at: lastStdinAt,
|
|
1261
1275
|
// Precedence: exited stays exited; the Rust supervisor's unresponsive flag is
|
|
1262
1276
|
// an authoritative wedge signal (`stuck`); then a blocked menu (`needs_input`);
|
|
1263
1277
|
// else the base live status — so the console's dot matches `ay ls`. (A dead
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-kJRKPdFi.js";
|
|
2
|
-
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-eVbxzEL3.js";
|
|
4
|
-
import "./pidStore-BIvsBQ8X.js";
|
|
5
|
-
import "./globalPidIndex-CoNr7tS8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-Bz-oXKG8.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|