claude-yes 1.133.1 → 1.135.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-B7wli1t3.js +8 -0
- package/dist/{SUPPORTED_CLIS-CffqZtcC.js → SUPPORTED_CLIS-CF3oohXF.js} +2 -2
- package/dist/cli.js +3 -3
- package/dist/index.js +2 -2
- package/dist/{schedule-CJB2SS_5.js → schedule-CbeQYbBT.js} +4 -4
- package/dist/{serve-DNqpW389.js → serve-B2KHUFVC.js} +34 -5
- package/dist/{setup-DKeEBsgH.js → setup-Cg2GKFP7.js} +2 -2
- package/dist/{subcommands-BvL7qpUL.js → subcommands-C4DD5Ihs.js} +4 -4
- package/dist/{subcommands-BOpq1lzK.js → subcommands-D01v41kV.js} +1 -1
- package/dist/{ts-D_4N8xNF.js → ts-nfb-SXN0.js} +2 -2
- package/dist/{versionChecker-DHg-gsSi.js → versionChecker-CDzZhfJg.js} +2 -2
- package/lab/ui/index.html +175 -1
- package/package.json +1 -1
- package/ts/serve.ts +49 -0
- package/dist/SUPPORTED_CLIS-DI4O_0OU.js +0 -8
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-nfb-SXN0.js";
|
|
2
|
+
import "./logger-CDIsZ-Pp.js";
|
|
3
|
+
import "./versionChecker-CDzZhfJg.js";
|
|
4
|
+
import "./pidStore-fqXqTKkh.js";
|
|
5
|
+
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CF3oohXF.js";
|
|
7
|
+
|
|
8
|
+
export { SUPPORTED_CLIS };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-nfb-SXN0.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-CF3oohXF.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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 { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-
|
|
4
|
+
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-CDzZhfJg.js";
|
|
5
5
|
import { argv } from "process";
|
|
6
6
|
import { execFileSync, spawn } from "child_process";
|
|
7
7
|
import ms from "ms";
|
|
@@ -480,7 +480,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
480
480
|
const rawArg = process.argv[2];
|
|
481
481
|
const managerCommands = !invokedCliName(process.argv);
|
|
482
482
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
483
|
-
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-
|
|
483
|
+
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-D01v41kV.js");
|
|
484
484
|
if (isHelpFlag && process.argv.length === 3) {
|
|
485
485
|
cmdHelp(managerCommands);
|
|
486
486
|
process.exit(0);
|
|
@@ -513,7 +513,7 @@ if (config.useRust) {
|
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
515
|
if (rustBinary) {
|
|
516
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
516
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-B7wli1t3.js");
|
|
517
517
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
518
518
|
if (config.verbose) {
|
|
519
519
|
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-nfb-SXN0.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-CDzZhfJg.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-nfb-SXN0.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-CDzZhfJg.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CF3oohXF.js";
|
|
7
7
|
import { n as resolveSpawnCwd } from "./workspaceConfig-BCOqRBEW.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-CbeQYbBT.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-nfb-SXN0.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-CDzZhfJg.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import { a as updateGlobalPidStatus } from "./globalPidIndex-DlmmJlO8.js";
|
|
6
6
|
import { t as pgidForWrapper } from "./reaper-C-eWAxIj.js";
|
|
7
7
|
import "./configShared-C1C04bbq.js";
|
|
8
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
8
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CF3oohXF.js";
|
|
9
9
|
import "./remotes-PKKjfTI1.js";
|
|
10
|
-
import { d as listRecords, g as resolveOne, i as controlCodeFromName, m as renderRawLog, p as readNotes, s as extractTaskCounts, x as writeToIpc, y as snapshotStatus } from "./subcommands-
|
|
10
|
+
import { d as listRecords, g as resolveOne, i as controlCodeFromName, m as renderRawLog, p as readNotes, s as extractTaskCounts, x as writeToIpc, y as snapshotStatus } from "./subcommands-C4DD5Ihs.js";
|
|
11
11
|
import yargs from "yargs";
|
|
12
12
|
import { mkdir, open, readFile, stat, writeFile } from "fs/promises";
|
|
13
13
|
import { homedir, hostname, userInfo } from "os";
|
|
@@ -657,6 +657,8 @@ Options:
|
|
|
657
657
|
git: r.status === "exited" ? null : await gitStatus(r.cwd),
|
|
658
658
|
tasks: r.status === "exited" ? null : await logTasks(r.log_file)
|
|
659
659
|
});
|
|
660
|
+
const presence = /* @__PURE__ */ new Map();
|
|
661
|
+
const PRESENCE_TTL_MS = 12e3;
|
|
660
662
|
const apiFetch = async (req) => {
|
|
661
663
|
if (!checkAuth(req, token)) return new Response("Unauthorized", { status: 401 });
|
|
662
664
|
const url = new URL(req.url);
|
|
@@ -985,6 +987,33 @@ Options:
|
|
|
985
987
|
return new Response(e.message, { status: 404 });
|
|
986
988
|
}
|
|
987
989
|
}
|
|
990
|
+
if (req.method === "POST" && p === "/api/presence") {
|
|
991
|
+
let b;
|
|
992
|
+
try {
|
|
993
|
+
b = await req.json();
|
|
994
|
+
} catch {
|
|
995
|
+
return new Response("invalid JSON body", { status: 400 });
|
|
996
|
+
}
|
|
997
|
+
const viewer = String(b.viewer ?? "").slice(0, 64);
|
|
998
|
+
if (!viewer) return new Response("missing viewer", { status: 400 });
|
|
999
|
+
if (b.agent == null) presence.delete(viewer);
|
|
1000
|
+
else presence.set(viewer, {
|
|
1001
|
+
viewer,
|
|
1002
|
+
agent: String(b.agent),
|
|
1003
|
+
cols: Math.max(0, Math.floor(Number(b.cols) || 0)),
|
|
1004
|
+
rows: Math.max(0, Math.floor(Number(b.rows) || 0)),
|
|
1005
|
+
sel: typeof b.sel === "string" ? b.sel.slice(0, 200) : null,
|
|
1006
|
+
ts: Date.now()
|
|
1007
|
+
});
|
|
1008
|
+
return new Response(null, { status: 204 });
|
|
1009
|
+
}
|
|
1010
|
+
if (req.method === "GET" && p === "/api/presence") {
|
|
1011
|
+
const now = Date.now();
|
|
1012
|
+
const live = [];
|
|
1013
|
+
for (const [k, v] of presence) if (now - v.ts > PRESENCE_TTL_MS) presence.delete(k);
|
|
1014
|
+
else live.push(v);
|
|
1015
|
+
return Response.json(live);
|
|
1016
|
+
}
|
|
988
1017
|
if (req.method === "POST" && p === "/api/spawn") {
|
|
989
1018
|
let body;
|
|
990
1019
|
try {
|
|
@@ -1142,4 +1171,4 @@ Options:
|
|
|
1142
1171
|
|
|
1143
1172
|
//#endregion
|
|
1144
1173
|
export { cmdServe };
|
|
1145
|
-
//# sourceMappingURL=serve-
|
|
1174
|
+
//# sourceMappingURL=serve-B2KHUFVC.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-B2KHUFVC.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-Cg2GKFP7.js.map
|
|
@@ -533,15 +533,15 @@ async function runSubcommand(argv) {
|
|
|
533
533
|
case "restart": return await cmdRestart(rest);
|
|
534
534
|
case "note": return await cmdNote(rest);
|
|
535
535
|
case "serve": {
|
|
536
|
-
const { cmdServe } = await import("./serve-
|
|
536
|
+
const { cmdServe } = await import("./serve-B2KHUFVC.js");
|
|
537
537
|
return cmdServe(rest);
|
|
538
538
|
}
|
|
539
539
|
case "setup": {
|
|
540
|
-
const { cmdSetup } = await import("./setup-
|
|
540
|
+
const { cmdSetup } = await import("./setup-Cg2GKFP7.js");
|
|
541
541
|
return cmdSetup(rest);
|
|
542
542
|
}
|
|
543
543
|
case "schedule": {
|
|
544
|
-
const { cmdSchedule } = await import("./schedule-
|
|
544
|
+
const { cmdSchedule } = await import("./schedule-CbeQYbBT.js");
|
|
545
545
|
return cmdSchedule(rest);
|
|
546
546
|
}
|
|
547
547
|
case "remote": {
|
|
@@ -2428,4 +2428,4 @@ async function cmdResultSet(rest) {
|
|
|
2428
2428
|
|
|
2429
2429
|
//#endregion
|
|
2430
2430
|
export { resolveReadWindow as _, cursorAbs as a, stopTipForCli as b, finalizedLines as c, listRecords as d, matchKeyword as f, resolveOne as g, renderRawLogLines as h, controlCodeFromName as i, isPidAlive as l, renderRawLog as m, READ_PAGE_DEFAULT as n, extractNeedsInput as o, readNotes as p, cmdHelp as r, extractTaskCounts as s, GRACEFUL_EXIT_COMMANDS as t, isSubcommand as u, runSubcommand as v, writeToIpc as x, snapshotStatus as y };
|
|
2431
|
-
//# sourceMappingURL=subcommands-
|
|
2431
|
+
//# sourceMappingURL=subcommands-C4DD5Ihs.js.map
|
|
@@ -2,6 +2,6 @@ import "./logger-CDIsZ-Pp.js";
|
|
|
2
2
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
3
3
|
import "./configShared-C1C04bbq.js";
|
|
4
4
|
import "./remotes-PKKjfTI1.js";
|
|
5
|
-
import { _ as resolveReadWindow, a as cursorAbs, b as stopTipForCli, c as finalizedLines, d as listRecords, f as matchKeyword, g as resolveOne, h as renderRawLogLines, i as controlCodeFromName, l as isPidAlive, m as renderRawLog, n as READ_PAGE_DEFAULT, o as extractNeedsInput, p as readNotes, r as cmdHelp, s as extractTaskCounts, t as GRACEFUL_EXIT_COMMANDS, u as isSubcommand, v as runSubcommand, x as writeToIpc, y as snapshotStatus } from "./subcommands-
|
|
5
|
+
import { _ as resolveReadWindow, a as cursorAbs, b as stopTipForCli, c as finalizedLines, d as listRecords, f as matchKeyword, g as resolveOne, h as renderRawLogLines, i as controlCodeFromName, l as isPidAlive, m as renderRawLog, n as READ_PAGE_DEFAULT, o as extractNeedsInput, p as readNotes, r as cmdHelp, s as extractTaskCounts, t as GRACEFUL_EXIT_COMMANDS, u as isSubcommand, v as runSubcommand, x as writeToIpc, y as snapshotStatus } from "./subcommands-C4DD5Ihs.js";
|
|
6
6
|
|
|
7
7
|
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -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-CDzZhfJg.js";
|
|
3
3
|
import { t as agentYesHome } from "./agentYesHome-_eJa3DaX.js";
|
|
4
4
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-V4qvXgAw.js";
|
|
5
5
|
import { t as PidStore } from "./pidStore-fqXqTKkh.js";
|
|
@@ -1788,4 +1788,4 @@ function sleep(ms) {
|
|
|
1788
1788
|
|
|
1789
1789
|
//#endregion
|
|
1790
1790
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1791
|
-
//# sourceMappingURL=ts-
|
|
1791
|
+
//# sourceMappingURL=ts-nfb-SXN0.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.135.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-CDzZhfJg.js.map
|
package/lab/ui/index.html
CHANGED
|
@@ -966,10 +966,39 @@
|
|
|
966
966
|
overflow: hidden;
|
|
967
967
|
padding: 8px max(10px, var(--sar)) 8px max(10px, var(--sal));
|
|
968
968
|
background: var(--bg);
|
|
969
|
+
position: relative; /* anchor for the peer-selection overlay */
|
|
969
970
|
}
|
|
970
971
|
.log .xterm {
|
|
971
972
|
height: 100%;
|
|
972
973
|
}
|
|
974
|
+
/* Other viewers' selection ranges, drawn over our grid (slice 2 of
|
|
975
|
+
multi-peer presence). Approximate — peer coords are mapped proportionally
|
|
976
|
+
across viewport sizes and don't track scrollback — a "roughly here" hint. */
|
|
977
|
+
.peer-overlay {
|
|
978
|
+
position: absolute;
|
|
979
|
+
inset: 0;
|
|
980
|
+
pointer-events: none;
|
|
981
|
+
z-index: 6;
|
|
982
|
+
}
|
|
983
|
+
.peer-sel {
|
|
984
|
+
position: absolute;
|
|
985
|
+
background: hsla(var(--ph, 200), 80%, 55%, 0.16);
|
|
986
|
+
border: 1px solid hsla(var(--ph, 200), 80%, 62%, 0.7);
|
|
987
|
+
border-radius: 2px;
|
|
988
|
+
box-sizing: border-box;
|
|
989
|
+
}
|
|
990
|
+
.peer-tag {
|
|
991
|
+
position: absolute;
|
|
992
|
+
top: -13px;
|
|
993
|
+
left: -1px;
|
|
994
|
+
font: 9px var(--mono);
|
|
995
|
+
line-height: 12px;
|
|
996
|
+
padding: 0 3px;
|
|
997
|
+
white-space: nowrap;
|
|
998
|
+
color: hsl(var(--ph, 200), 85%, 75%);
|
|
999
|
+
background: var(--bg);
|
|
1000
|
+
border-radius: 3px 3px 0 0;
|
|
1001
|
+
}
|
|
973
1002
|
.log .xterm-viewport {
|
|
974
1003
|
background: transparent !important;
|
|
975
1004
|
}
|
|
@@ -2386,12 +2415,27 @@
|
|
|
2386
2415
|
const traffic =
|
|
2387
2416
|
`<div class="ctip-traf"><span class="ctip-k">i/o</span>${sparkSvg(traf.hist, 96, 22) || "—"}</div>` +
|
|
2388
2417
|
`<div><span class="ctip-k"></span>↓ ${fmtBytes(last.o)}/s ↑ ${fmtBytes(last.i)}/s</div>`;
|
|
2418
|
+
const viewers = presenceHtml();
|
|
2389
2419
|
return (
|
|
2390
2420
|
`<div class="ctip-sec">${vp}</div>` +
|
|
2391
2421
|
`<div class="ctip-sec">${capHtml}</div>` +
|
|
2392
|
-
`<div class="ctip-sec">${traffic}</div>`
|
|
2422
|
+
`<div class="ctip-sec">${traffic}</div>` +
|
|
2423
|
+
(viewers ? `<div class="ctip-sec">${viewers}</div>` : "")
|
|
2393
2424
|
);
|
|
2394
2425
|
}
|
|
2426
|
+
// Other viewers watching THIS agent (we exclude ourselves) + their viewports.
|
|
2427
|
+
function presenceHtml() {
|
|
2428
|
+
const others = presencePeers;
|
|
2429
|
+
if (!others.length) return "";
|
|
2430
|
+
const head = `<div><span class="ctip-k">viewers</span>👁 ${others.length + 1} <span style="color:var(--muted)">(you + ${others.length})</span></div>`;
|
|
2431
|
+
const list = others
|
|
2432
|
+
.map(
|
|
2433
|
+
(v) =>
|
|
2434
|
+
`<div><span class="ctip-k"></span>${esc((v.cols || "?") + "×" + (v.rows || "?"))}${v.sel ? " · sel" : ""}</div>`,
|
|
2435
|
+
)
|
|
2436
|
+
.join("");
|
|
2437
|
+
return head + list;
|
|
2438
|
+
}
|
|
2395
2439
|
// Always-on: sample the I/O ring every second and, while an agent is open,
|
|
2396
2440
|
// repaint the badge so its hover tooltip (sparkline + caps + sizes) stays live.
|
|
2397
2441
|
setInterval(() => {
|
|
@@ -2401,6 +2445,132 @@
|
|
|
2401
2445
|
if (sel) paintHeaderBadge();
|
|
2402
2446
|
}, 1000);
|
|
2403
2447
|
|
|
2448
|
+
// ---- multi-peer presence: report which agent we're watching + our viewport
|
|
2449
|
+
// to the host, and read back the OTHER viewers, so the badge can show how many
|
|
2450
|
+
// peers look at the same agent and at what size. Cosmetic; the host's
|
|
2451
|
+
// /api/presence blackboard TTLs entries (hosts on an older `ay serve` just 404
|
|
2452
|
+
// → we degrade to no viewers). Keyed by a per-tab viewer id so switching agents
|
|
2453
|
+
// moves our single entry rather than stacking up.
|
|
2454
|
+
const myViewerId = (() => {
|
|
2455
|
+
try {
|
|
2456
|
+
let v = sessionStorage.getItem("ay.viewer");
|
|
2457
|
+
if (!v) {
|
|
2458
|
+
v = Math.random().toString(36).slice(2, 10);
|
|
2459
|
+
sessionStorage.setItem("ay.viewer", v);
|
|
2460
|
+
}
|
|
2461
|
+
return v;
|
|
2462
|
+
} catch {
|
|
2463
|
+
return Math.random().toString(36).slice(2, 10);
|
|
2464
|
+
}
|
|
2465
|
+
})();
|
|
2466
|
+
let presencePeers = []; // others watching the SELECTED agent: [{cols,rows,sel}]
|
|
2467
|
+
function presenceTarget() {
|
|
2468
|
+
const e = sel ? entries.find((x) => x._key === sel) : null;
|
|
2469
|
+
const src = e ? srcFor(e) : null;
|
|
2470
|
+
return e && src && src.tx ? { e, tx: src.tx } : null;
|
|
2471
|
+
}
|
|
2472
|
+
function sendPresence() {
|
|
2473
|
+
const cur = presenceTarget();
|
|
2474
|
+
if (!cur || !term) return;
|
|
2475
|
+
let selR = null;
|
|
2476
|
+
try {
|
|
2477
|
+
const s = term.getSelectionPosition && term.getSelectionPosition();
|
|
2478
|
+
if (s) selR = `${s.startRow},${s.startColumn}-${s.endRow},${s.endColumn}`;
|
|
2479
|
+
} catch {}
|
|
2480
|
+
cur.tx
|
|
2481
|
+
.post("/api/presence", {
|
|
2482
|
+
viewer: myViewerId,
|
|
2483
|
+
agent: cur.e.pid,
|
|
2484
|
+
cols: term.cols,
|
|
2485
|
+
rows: term.rows,
|
|
2486
|
+
sel: selR,
|
|
2487
|
+
})
|
|
2488
|
+
.catch(() => {});
|
|
2489
|
+
}
|
|
2490
|
+
async function pollPresence() {
|
|
2491
|
+
const cur = presenceTarget();
|
|
2492
|
+
if (cur) {
|
|
2493
|
+
try {
|
|
2494
|
+
const all = await cur.tx.fetchJSON("/api/presence");
|
|
2495
|
+
presencePeers = (Array.isArray(all) ? all : []).filter(
|
|
2496
|
+
(v) => String(v.agent) === String(cur.e.pid) && v.viewer !== myViewerId,
|
|
2497
|
+
);
|
|
2498
|
+
} catch {
|
|
2499
|
+
presencePeers = [];
|
|
2500
|
+
}
|
|
2501
|
+
} else {
|
|
2502
|
+
presencePeers = [];
|
|
2503
|
+
}
|
|
2504
|
+
renderPeerSelections();
|
|
2505
|
+
}
|
|
2506
|
+
// 3s heartbeat (< the host's 12s TTL): refresh our presence + read others'.
|
|
2507
|
+
setInterval(() => {
|
|
2508
|
+
if (sel) {
|
|
2509
|
+
sendPresence();
|
|
2510
|
+
pollPresence();
|
|
2511
|
+
}
|
|
2512
|
+
}, 3000);
|
|
2513
|
+
|
|
2514
|
+
// ---- slice 2: draw each peer's selection range as an overlay in OUR grid.
|
|
2515
|
+
// Peer coords arrive in the peer's own cols×rows; we map them proportionally
|
|
2516
|
+
// to ours and to pixels via the measured cell size. Approximate by design
|
|
2517
|
+
// (doesn't track scrollback / exact reflow) — a "roughly here" presence hint.
|
|
2518
|
+
function hashHue(s) {
|
|
2519
|
+
let h = 0;
|
|
2520
|
+
for (const ch of String(s)) h = (h * 31 + ch.charCodeAt(0)) >>> 0;
|
|
2521
|
+
return h % 360;
|
|
2522
|
+
}
|
|
2523
|
+
function mapPeerSel(selStr, pc, pr, mc, mr) {
|
|
2524
|
+
const m = /^(\d+),(\d+)-(\d+),(\d+)$/.exec(selStr || "");
|
|
2525
|
+
if (!m) return null;
|
|
2526
|
+
const mapR = (r) => (pr > 0 ? Math.round((r / pr) * mr) : r);
|
|
2527
|
+
const mapC = (c) => (pc > 0 ? Math.round((c / pc) * mc) : c);
|
|
2528
|
+
const r0 = mapR(+m[1]),
|
|
2529
|
+
c0 = mapC(+m[2]),
|
|
2530
|
+
r1 = mapR(+m[3]),
|
|
2531
|
+
c1 = mapC(+m[4]);
|
|
2532
|
+
return { r0: Math.min(r0, r1), c0: Math.min(c0, c1), r1: Math.max(r0, r1), c1: Math.max(c0, c1) };
|
|
2533
|
+
}
|
|
2534
|
+
function renderPeerSelections() {
|
|
2535
|
+
const logEl = $("log");
|
|
2536
|
+
if (!logEl) return;
|
|
2537
|
+
let ov = logEl.querySelector(".peer-overlay");
|
|
2538
|
+
const peers = term ? presencePeers.filter((p) => p && p.sel) : [];
|
|
2539
|
+
const screen = term && term.element && term.element.querySelector(".xterm-screen");
|
|
2540
|
+
if (!peers.length || !screen) {
|
|
2541
|
+
if (ov) ov.innerHTML = "";
|
|
2542
|
+
return;
|
|
2543
|
+
}
|
|
2544
|
+
if (!ov) {
|
|
2545
|
+
ov = document.createElement("div");
|
|
2546
|
+
ov.className = "peer-overlay";
|
|
2547
|
+
logEl.appendChild(ov);
|
|
2548
|
+
}
|
|
2549
|
+
const sr = screen.getBoundingClientRect();
|
|
2550
|
+
const lr = logEl.getBoundingClientRect();
|
|
2551
|
+
if (!sr.width || !term.cols || !term.rows) {
|
|
2552
|
+
ov.innerHTML = "";
|
|
2553
|
+
return;
|
|
2554
|
+
}
|
|
2555
|
+
const ox = sr.left - lr.left,
|
|
2556
|
+
oy = sr.top - lr.top;
|
|
2557
|
+
const cw = sr.width / term.cols,
|
|
2558
|
+
ch = sr.height / term.rows;
|
|
2559
|
+
ov.innerHTML = peers
|
|
2560
|
+
.map((p) => {
|
|
2561
|
+
const r = mapPeerSel(p.sel, p.cols || term.cols, p.rows || term.rows, term.cols, term.rows);
|
|
2562
|
+
if (!r) return "";
|
|
2563
|
+
const top = oy + r.r0 * ch,
|
|
2564
|
+
left = ox + r.c0 * cw;
|
|
2565
|
+
const w = Math.max(cw, (r.c1 - r.c0) * cw),
|
|
2566
|
+
h = (r.r1 - r.r0 + 1) * ch;
|
|
2567
|
+
const hue = hashHue(p.viewer);
|
|
2568
|
+
const tag = esc(String(p.viewer).slice(0, 4)) + " " + (p.cols || "?") + "×" + (p.rows || "?");
|
|
2569
|
+
return `<div class="peer-sel" style="--ph:${hue};top:${top.toFixed(1)}px;left:${left.toFixed(1)}px;width:${w.toFixed(1)}px;height:${h.toFixed(1)}px"><span class="peer-tag">${tag}</span></div>`;
|
|
2570
|
+
})
|
|
2571
|
+
.join("");
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2404
2574
|
// Wire the ⋯ overflow menu and restore the saved HUD preference.
|
|
2405
2575
|
// Recovery actions for the SELECTED agent, both confirmed first (destructive):
|
|
2406
2576
|
// Stop — graceful: send the CLI's exit command (claude/codex /exit, gemini
|
|
@@ -2955,6 +3125,9 @@
|
|
|
2955
3125
|
// and the remembered agent winsize so the badge tooltip doesn't show stale data.
|
|
2956
3126
|
trafReset();
|
|
2957
3127
|
agentSize = null;
|
|
3128
|
+
presencePeers = []; // clear other-viewer list until the next poll for this agent
|
|
3129
|
+
renderPeerSelections(); // drop any prior agent's peer-selection overlay now
|
|
3130
|
+
sendPresence(); // announce we're now watching this agent (host TTLs the prior one)
|
|
2958
3131
|
paintHeaderBadge();
|
|
2959
3132
|
// Remember the selection so a refresh re-opens this agent (see boot/autoPid).
|
|
2960
3133
|
try {
|
|
@@ -3205,6 +3378,7 @@
|
|
|
3205
3378
|
try {
|
|
3206
3379
|
fit.fit();
|
|
3207
3380
|
} catch {}
|
|
3381
|
+
renderPeerSelections(); // cell size changed → reposition peer-selection overlays
|
|
3208
3382
|
});
|
|
3209
3383
|
// iOS overlays the soft keyboard ON TOP of the layout viewport rather than
|
|
3210
3384
|
// shrinking it, so a bottom-anchored composer would hide behind it. Track
|
package/package.json
CHANGED
package/ts/serve.ts
CHANGED
|
@@ -942,6 +942,15 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
942
942
|
tasks: r.status === "exited" ? null : await logTasks(r.log_file),
|
|
943
943
|
});
|
|
944
944
|
|
|
945
|
+
// Multi-peer presence blackboard: viewerId -> what that viewer is watching +
|
|
946
|
+
// its viewport/selection. Purely cosmetic ("who else is looking at this agent"),
|
|
947
|
+
// never a security surface — viewers self-report. Pruned by TTL on read.
|
|
948
|
+
const presence = new Map<
|
|
949
|
+
string,
|
|
950
|
+
{ viewer: string; agent: string; cols: number; rows: number; sel: string | null; ts: number }
|
|
951
|
+
>();
|
|
952
|
+
const PRESENCE_TTL_MS = 12_000;
|
|
953
|
+
|
|
945
954
|
// The whole API as a plain handler: served over HTTP by Bun.serve (--http)
|
|
946
955
|
// and called in-process by the WebRTC bridge (--webrtc) — the latter needs
|
|
947
956
|
// no TCP port at all.
|
|
@@ -1375,6 +1384,46 @@ export async function cmdServe(rest: string[]): Promise<number> {
|
|
|
1375
1384
|
}
|
|
1376
1385
|
}
|
|
1377
1386
|
|
|
1387
|
+
// POST /api/presence body {viewer, agent, cols, rows, sel?} — a viewer
|
|
1388
|
+
// self-reports which agent it's watching + its viewport (agent=null clears).
|
|
1389
|
+
if (req.method === "POST" && p === "/api/presence") {
|
|
1390
|
+
let b: {
|
|
1391
|
+
viewer?: string;
|
|
1392
|
+
agent?: string | number | null;
|
|
1393
|
+
cols?: number;
|
|
1394
|
+
rows?: number;
|
|
1395
|
+
sel?: string;
|
|
1396
|
+
};
|
|
1397
|
+
try {
|
|
1398
|
+
b = (await req.json()) as typeof b;
|
|
1399
|
+
} catch {
|
|
1400
|
+
return new Response("invalid JSON body", { status: 400 });
|
|
1401
|
+
}
|
|
1402
|
+
const viewer = String(b.viewer ?? "").slice(0, 64);
|
|
1403
|
+
if (!viewer) return new Response("missing viewer", { status: 400 });
|
|
1404
|
+
if (b.agent == null) presence.delete(viewer);
|
|
1405
|
+
else
|
|
1406
|
+
presence.set(viewer, {
|
|
1407
|
+
viewer,
|
|
1408
|
+
agent: String(b.agent),
|
|
1409
|
+
cols: Math.max(0, Math.floor(Number(b.cols) || 0)),
|
|
1410
|
+
rows: Math.max(0, Math.floor(Number(b.rows) || 0)),
|
|
1411
|
+
sel: typeof b.sel === "string" ? b.sel.slice(0, 200) : null,
|
|
1412
|
+
ts: Date.now(),
|
|
1413
|
+
});
|
|
1414
|
+
return new Response(null, { status: 204 });
|
|
1415
|
+
}
|
|
1416
|
+
// GET /api/presence — all live viewers (TTL-pruned), for "who's watching".
|
|
1417
|
+
if (req.method === "GET" && p === "/api/presence") {
|
|
1418
|
+
const now = Date.now();
|
|
1419
|
+
const live: unknown[] = [];
|
|
1420
|
+
for (const [k, v] of presence) {
|
|
1421
|
+
if (now - v.ts > PRESENCE_TTL_MS) presence.delete(k);
|
|
1422
|
+
else live.push(v);
|
|
1423
|
+
}
|
|
1424
|
+
return Response.json(live);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1378
1427
|
// POST /api/spawn body {cli, cwd, prompt} — launch a new agent
|
|
1379
1428
|
if (req.method === "POST" && p === "/api/spawn") {
|
|
1380
1429
|
let body: { cli?: string; cwd?: string; prompt?: string };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-D_4N8xNF.js";
|
|
2
|
-
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-DHg-gsSi.js";
|
|
4
|
-
import "./pidStore-fqXqTKkh.js";
|
|
5
|
-
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CffqZtcC.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|