claude-yes 1.136.1 → 1.138.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-BlYVTStU.js +8 -0
- package/dist/{SUPPORTED_CLIS-D9x14LOU.js → SUPPORTED_CLIS-D3iEYFql.js} +2 -2
- package/dist/cli.js +3 -3
- package/dist/index.js +2 -2
- package/dist/{schedule-BHQxJryR.js → schedule-Cz9peq9i.js} +4 -4
- package/dist/{serve-BIB4RhmY.js → serve-DJrBiSD9.js} +5 -5
- package/dist/{setup-k1tlrF_v.js → setup-B138hyq0.js} +2 -2
- package/dist/{subcommands-Dkoh93LI.js → subcommands-DbNS4vIg.js} +1 -1
- package/dist/{subcommands-MsZtpbY6.js → subcommands-viZJtGlf.js} +4 -4
- package/dist/{ts-BwsLxt1F.js → ts-CSn43pN8.js} +2 -2
- package/dist/{versionChecker-wZekjh0q.js → versionChecker-C6bI89jZ.js} +2 -2
- package/lab/ui/console-logic.js +73 -0
- package/lab/ui/index.html +100 -57
- package/package.json +1 -1
- package/dist/SUPPORTED_CLIS-BAqEnz6_.js +0 -8
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-CSn43pN8.js";
|
|
2
|
+
import "./logger-CDIsZ-Pp.js";
|
|
3
|
+
import "./versionChecker-C6bI89jZ.js";
|
|
4
|
+
import "./pidStore-fqXqTKkh.js";
|
|
5
|
+
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-D3iEYFql.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-CSn43pN8.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-D3iEYFql.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-C6bI89jZ.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-DbNS4vIg.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-BlYVTStU.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-CSn43pN8.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-C6bI89jZ.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-CSn43pN8.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-C6bI89jZ.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-D3iEYFql.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-Cz9peq9i.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-CSn43pN8.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-C6bI89jZ.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-D3iEYFql.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-viZJtGlf.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";
|
|
@@ -1171,4 +1171,4 @@ Options:
|
|
|
1171
1171
|
|
|
1172
1172
|
//#endregion
|
|
1173
1173
|
export { cmdServe };
|
|
1174
|
-
//# sourceMappingURL=serve-
|
|
1174
|
+
//# sourceMappingURL=serve-DJrBiSD9.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-DJrBiSD9.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-B138hyq0.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-viZJtGlf.js";
|
|
6
6
|
|
|
7
7
|
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -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-DJrBiSD9.js");
|
|
537
537
|
return cmdServe(rest);
|
|
538
538
|
}
|
|
539
539
|
case "setup": {
|
|
540
|
-
const { cmdSetup } = await import("./setup-
|
|
540
|
+
const { cmdSetup } = await import("./setup-B138hyq0.js");
|
|
541
541
|
return cmdSetup(rest);
|
|
542
542
|
}
|
|
543
543
|
case "schedule": {
|
|
544
|
-
const { cmdSchedule } = await import("./schedule-
|
|
544
|
+
const { cmdSchedule } = await import("./schedule-Cz9peq9i.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-viZJtGlf.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-C6bI89jZ.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-CSn43pN8.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.138.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-C6bI89jZ.js.map
|
package/lab/ui/console-logic.js
CHANGED
|
@@ -395,3 +395,76 @@ export function nextIndex(len, i, dir) {
|
|
|
395
395
|
if (i < 0) return dir > 0 ? 0 : len - 1;
|
|
396
396
|
return Math.max(0, Math.min(len - 1, i + dir));
|
|
397
397
|
}
|
|
398
|
+
|
|
399
|
+
// ---------------------------------------------------------------------------
|
|
400
|
+
// multi-viewer presence + shared-canvas geometry
|
|
401
|
+
// index.html keeps the DOM glue (measuring elements, applying transforms); the
|
|
402
|
+
// coordinate math lives here so it's unit-testable without a browser.
|
|
403
|
+
// ---------------------------------------------------------------------------
|
|
404
|
+
|
|
405
|
+
// Stable per-viewer hue (0..359) for colour-coding peers' selections.
|
|
406
|
+
export function hashHue(s) {
|
|
407
|
+
let h = 0;
|
|
408
|
+
for (const ch of String(s)) h = (h * 31 + ch.charCodeAt(0)) >>> 0;
|
|
409
|
+
return h % 360;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Encode an xterm selection (getSelectionPosition() → {start:{x,y}, end:{x,y}},
|
|
413
|
+
// y = ABSOLUTE buffer line) as "fromBottomRow,col-fromBottomRow,col". Viewers
|
|
414
|
+
// connect at different times so absolute rows don't align, but the live-tail
|
|
415
|
+
// content does — distance from the bottom is a shared coordinate. `bufferLen` is
|
|
416
|
+
// the buffer's line count. Returns null when there's no selection.
|
|
417
|
+
export function selFromBottom(s, bufferLen) {
|
|
418
|
+
if (!s || !s.start || !s.end) return null;
|
|
419
|
+
const last = (bufferLen || 1) - 1;
|
|
420
|
+
return `${last - s.start.y},${s.start.x}-${last - s.end.y},${s.end.x}`;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Parse "fbRow,col-fbRow,col" (rows = lines-from-bottom). null if malformed.
|
|
424
|
+
export function parseSel(selStr) {
|
|
425
|
+
const m = /^(\d+),(\d+)-(\d+),(\d+)$/.exec(selStr || "");
|
|
426
|
+
if (!m) return null;
|
|
427
|
+
return { fa: +m[1], ca: +m[2], fb: +m[3], cb: +m[4] };
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Per-row spans for a peer selection, in OUR buffer rows, clipped to the visible
|
|
431
|
+
// viewport [vy, vy+myRows). fromBottom is mapped against OUR buffer bottom
|
|
432
|
+
// (myLast) so the same tail line matches across viewers of different scrollback
|
|
433
|
+
// depth. A selection is per-row: top row cA→edge, full-width middle, bottom row
|
|
434
|
+
// 0→cB. Columns are EXACT when widths match, proportional only as a fallback.
|
|
435
|
+
export function selSegments(sel, myLast, vy, myRows, peerCols, myCols) {
|
|
436
|
+
if (!sel) return [];
|
|
437
|
+
const sameW = (peerCols || myCols) === myCols;
|
|
438
|
+
const mapC = (c) => (sameW ? c : Math.round((c / (peerCols || myCols)) * myCols));
|
|
439
|
+
let rA = myLast - sel.fa,
|
|
440
|
+
rB = myLast - sel.fb,
|
|
441
|
+
cA = sel.ca,
|
|
442
|
+
cB = sel.cb;
|
|
443
|
+
if (rA > rB) ([rA, rB] = [rB, rA]), ([cA, cB] = [cB, cA]); // rA = top row
|
|
444
|
+
const segs = [];
|
|
445
|
+
const from = Math.max(rA, vy),
|
|
446
|
+
to = Math.min(rB, vy + myRows - 1);
|
|
447
|
+
for (let r = from; r <= to; r++) {
|
|
448
|
+
const a = r === rA ? cA : 0;
|
|
449
|
+
const b = r === rB ? cB : myCols;
|
|
450
|
+
segs.push({ row: r, a: Math.min(mapC(a), mapC(b)), b: Math.max(mapC(a), mapC(b)) });
|
|
451
|
+
}
|
|
452
|
+
return segs;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Shared-canvas fit: the CSS transform that fits a grid (gridW×gridH px) into a
|
|
456
|
+
// pane (paneW×paneH px). Near-1 → "none" so the driver / single viewer (whose
|
|
457
|
+
// grid already fits) stays crisp and unchanged; otherwise "scale(s)". The
|
|
458
|
+
// 0.985–1.04 band absorbs FitAddon's whole-cell rounding slack.
|
|
459
|
+
export function fitTransform(gridW, gridH, paneW, paneH) {
|
|
460
|
+
if (!gridW || !gridH || paneW <= 0 || paneH <= 0) return "none";
|
|
461
|
+
const s = Math.min(paneW / gridW, paneH / gridH);
|
|
462
|
+
return s > 0.985 && s < 1.04 ? "none" : "scale(" + s.toFixed(4) + ")";
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Browser-tab title: "<selected agent title> - agent-yes", or the bare console
|
|
466
|
+
// title when nothing is selected (blank/whitespace name).
|
|
467
|
+
export function docTitle(name) {
|
|
468
|
+
const n = name && String(name).trim();
|
|
469
|
+
return n ? n + " - agent-yes" : "agent-yes · console";
|
|
470
|
+
}
|
package/lab/ui/index.html
CHANGED
|
@@ -970,6 +970,13 @@
|
|
|
970
970
|
}
|
|
971
971
|
.log .xterm {
|
|
972
972
|
height: 100%;
|
|
973
|
+
/* Shared-canvas: when we're a WATCHER rendering at another viewer's
|
|
974
|
+
(the driver's) grid size, scale the whole grid to fit our pane instead
|
|
975
|
+
of reflowing. transform-origin keeps the scaled grid pinned top-left so
|
|
976
|
+
the peer-selection overlay (which uses grid coords) still lines up.
|
|
977
|
+
For the driver / single viewer the grid already fits, so no transform
|
|
978
|
+
is applied (see applyCanvasScale). */
|
|
979
|
+
transform-origin: top left;
|
|
973
980
|
}
|
|
974
981
|
/* Other viewers' selection ranges, drawn over our grid (slice 2 of
|
|
975
982
|
multi-peer presence). Approximate — peer coords are mapped proportionally
|
|
@@ -1394,6 +1401,12 @@
|
|
|
1394
1401
|
deviceCount,
|
|
1395
1402
|
layeredRows,
|
|
1396
1403
|
taskLabel,
|
|
1404
|
+
hashHue,
|
|
1405
|
+
selFromBottom,
|
|
1406
|
+
parseSel,
|
|
1407
|
+
selSegments,
|
|
1408
|
+
fitTransform,
|
|
1409
|
+
docTitle,
|
|
1397
1410
|
} from "./console-logic.js";
|
|
1398
1411
|
import {
|
|
1399
1412
|
MARKER as E2E_MARKER,
|
|
@@ -2335,6 +2348,10 @@
|
|
|
2335
2348
|
// The last winsize the agent's PTY reported (from /api/size), so the tooltip
|
|
2336
2349
|
// can show OUR viewport vs the agent's render size. Reset on agent switch.
|
|
2337
2350
|
let agentSize = null;
|
|
2351
|
+
// When WE last drove the grid size (pushed our size to the agent). For a
|
|
2352
|
+
// short lease after that, the heartbeat won't follow/override — so our own
|
|
2353
|
+
// push isn't fought while the agent's /api/size is still catching up.
|
|
2354
|
+
let lastDroveAt = 0;
|
|
2338
2355
|
|
|
2339
2356
|
function isDarkColor(c) {
|
|
2340
2357
|
try {
|
|
@@ -2474,17 +2491,11 @@
|
|
|
2474
2491
|
if (!cur || !term) return;
|
|
2475
2492
|
let selR = null;
|
|
2476
2493
|
try {
|
|
2477
|
-
//
|
|
2478
|
-
//
|
|
2479
|
-
//
|
|
2480
|
-
// is identical, so "lines from the BOTTOM" (length-1 - y) IS a shared
|
|
2481
|
-
// coordinate. We emit fromBottom for rows; the receiver maps it back into
|
|
2482
|
-
// its own buffer + viewport. cols stay as-is.
|
|
2494
|
+
// selFromBottom (console-logic.js) encodes the selection as
|
|
2495
|
+
// lines-from-bottom — a coordinate shared across differently-sized
|
|
2496
|
+
// viewers (see its doc); the receiver maps it back into its own buffer.
|
|
2483
2497
|
const s = term.getSelectionPosition && term.getSelectionPosition();
|
|
2484
|
-
|
|
2485
|
-
const last = (term.buffer.active.length || 1) - 1;
|
|
2486
|
-
selR = `${last - s.start.y},${s.start.x}-${last - s.end.y},${s.end.x}`;
|
|
2487
|
-
}
|
|
2498
|
+
selR = selFromBottom(s, term.buffer.active.length);
|
|
2488
2499
|
} catch {}
|
|
2489
2500
|
cur.tx
|
|
2490
2501
|
.post("/api/presence", {
|
|
@@ -2512,54 +2523,24 @@
|
|
|
2512
2523
|
}
|
|
2513
2524
|
renderPeerSelections();
|
|
2514
2525
|
}
|
|
2515
|
-
// 3s heartbeat (< the host's 12s TTL): refresh our presence + read others'
|
|
2526
|
+
// 3s heartbeat (< the host's 12s TTL): refresh our presence + read others',
|
|
2527
|
+
// and follow the canonical grid size (resize+scale, never reflow) so all
|
|
2528
|
+
// viewers stay on one shared canvas and selections line up.
|
|
2516
2529
|
setInterval(() => {
|
|
2517
|
-
if (sel)
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2530
|
+
if (!sel) return;
|
|
2531
|
+
sendPresence();
|
|
2532
|
+
pollPresence();
|
|
2533
|
+
const cur = presenceTarget();
|
|
2534
|
+
if (cur)
|
|
2535
|
+
cur.tx
|
|
2536
|
+
.fetchJSON("/api/size/" + encodeURIComponent(cur.e.pid))
|
|
2537
|
+
.then(followAgentSize)
|
|
2538
|
+
.catch(() => {});
|
|
2521
2539
|
}, 3000);
|
|
2522
2540
|
|
|
2523
|
-
//
|
|
2524
|
-
//
|
|
2525
|
-
//
|
|
2526
|
-
// (doesn't track scrollback / exact reflow) — a "roughly here" presence hint.
|
|
2527
|
-
function hashHue(s) {
|
|
2528
|
-
let h = 0;
|
|
2529
|
-
for (const ch of String(s)) h = (h * 31 + ch.charCodeAt(0)) >>> 0;
|
|
2530
|
-
return h % 360;
|
|
2531
|
-
}
|
|
2532
|
-
// Parse "fbRow,col-fbRow,col" where the rows are LINES-FROM-THE-BOTTOM of the
|
|
2533
|
-
// peer's buffer (a coordinate shared across viewers — see sendPresence).
|
|
2534
|
-
function parseSel(selStr) {
|
|
2535
|
-
const m = /^(\d+),(\d+)-(\d+),(\d+)$/.exec(selStr || "");
|
|
2536
|
-
if (!m) return null;
|
|
2537
|
-
return { fa: +m[1], ca: +m[2], fb: +m[3], cb: +m[4] };
|
|
2538
|
-
}
|
|
2539
|
-
// Per-row spans for a peer selection, in OUR buffer rows. fromBottom is mapped
|
|
2540
|
-
// against OUR buffer bottom (myLast) so the same live-tail line matches even
|
|
2541
|
-
// though absolute indices differ between viewers; only the rows visible in our
|
|
2542
|
-
// viewport [vy, vy+myRows) are emitted (so a giant selection stays cheap). A
|
|
2543
|
-
// selection is per-row: top row cA→edge, full-width middle, bottom row 0→cB.
|
|
2544
|
-
// Columns are EXACT when widths match, proportional only as a fallback.
|
|
2545
|
-
function selSegments(sel, myLast, vy, myRows, peerCols, myCols) {
|
|
2546
|
-
const sameW = (peerCols || myCols) === myCols;
|
|
2547
|
-
const mapC = (c) => (sameW ? c : Math.round((c / (peerCols || myCols)) * myCols));
|
|
2548
|
-
let rA = myLast - sel.fa,
|
|
2549
|
-
rB = myLast - sel.fb,
|
|
2550
|
-
cA = sel.ca,
|
|
2551
|
-
cB = sel.cb;
|
|
2552
|
-
if (rA > rB) ([rA, rB] = [rB, rA]), ([cA, cB] = [cB, cA]); // rA = top row
|
|
2553
|
-
const segs = [];
|
|
2554
|
-
const from = Math.max(rA, vy),
|
|
2555
|
-
to = Math.min(rB, vy + myRows - 1);
|
|
2556
|
-
for (let r = from; r <= to; r++) {
|
|
2557
|
-
const a = r === rA ? cA : 0;
|
|
2558
|
-
const b = r === rB ? cB : myCols;
|
|
2559
|
-
segs.push({ row: r, a: Math.min(mapC(a), mapC(b)), b: Math.max(mapC(a), mapC(b)) });
|
|
2560
|
-
}
|
|
2561
|
-
return segs;
|
|
2562
|
-
}
|
|
2541
|
+
// Peer-selection overlay. The coordinate math (parseSel / selSegments /
|
|
2542
|
+
// hashHue) lives in console-logic.js (unit-tested); here we just measure the
|
|
2543
|
+
// DOM and place the boxes. Drawn in OUR buffer rows, clipped to the viewport.
|
|
2563
2544
|
function renderPeerSelections() {
|
|
2564
2545
|
const logEl = $("log");
|
|
2565
2546
|
if (!logEl) return;
|
|
@@ -2614,6 +2595,49 @@
|
|
|
2614
2595
|
ov.innerHTML = html.join("");
|
|
2615
2596
|
}
|
|
2616
2597
|
|
|
2598
|
+
// ---- shared canvas: scale (don't reflow) the grid to fit our pane --------
|
|
2599
|
+
// When we render at the canonical (driver/agent) grid size and it doesn't
|
|
2600
|
+
// match our pane, CSS-scale the whole .xterm to fit — so every viewer shows
|
|
2601
|
+
// identical content and selections/overlays line up. For the driver / single
|
|
2602
|
+
// viewer the grid already fits the pane (scale ≈ 1) → no transform, so the
|
|
2603
|
+
// common path is byte-for-byte unchanged. Best-effort + guarded.
|
|
2604
|
+
function applyCanvasScale() {
|
|
2605
|
+
try {
|
|
2606
|
+
const logEl = $("log");
|
|
2607
|
+
const xt = logEl && logEl.querySelector(".xterm");
|
|
2608
|
+
if (!xt) return;
|
|
2609
|
+
xt.style.transform = "none"; // measure the natural (unscaled) grid
|
|
2610
|
+
const screen = xt.querySelector(".xterm-screen");
|
|
2611
|
+
if (!screen) return;
|
|
2612
|
+
const gw = screen.offsetWidth,
|
|
2613
|
+
gh = screen.offsetHeight;
|
|
2614
|
+
if (!gw || !gh) return;
|
|
2615
|
+
const cs = getComputedStyle(logEl);
|
|
2616
|
+
const pw = logEl.clientWidth - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight);
|
|
2617
|
+
const ph = logEl.clientHeight - parseFloat(cs.paddingTop) - parseFloat(cs.paddingBottom);
|
|
2618
|
+
// fitTransform (console-logic.js) decides none-vs-scale (unit-tested).
|
|
2619
|
+
xt.style.transform = fitTransform(gw, gh, pw, ph);
|
|
2620
|
+
} catch {}
|
|
2621
|
+
}
|
|
2622
|
+
// Follow the canonical grid: resize our xterm to the agent's size (set by the
|
|
2623
|
+
// active driver / local owner) WITHOUT reflowing to our pane, then scale to
|
|
2624
|
+
// fit. No-op when we already match (we're the driver, or sizes agree).
|
|
2625
|
+
function followAgentSize(sz) {
|
|
2626
|
+
if (!term || !sz || !sz.cols || !sz.rows) return;
|
|
2627
|
+
// While our own recent push is still settling, don't fight it.
|
|
2628
|
+
if (Date.now() - lastDroveAt < 6000) {
|
|
2629
|
+
applyCanvasScale();
|
|
2630
|
+
return;
|
|
2631
|
+
}
|
|
2632
|
+
if (sz.cols !== term.cols || sz.rows !== term.rows) {
|
|
2633
|
+
agentSize = sz;
|
|
2634
|
+
try {
|
|
2635
|
+
term.resize(sz.cols, sz.rows);
|
|
2636
|
+
} catch {}
|
|
2637
|
+
}
|
|
2638
|
+
applyCanvasScale();
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2617
2641
|
// Wire the ⋯ overflow menu and restore the saved HUD preference.
|
|
2618
2642
|
// Recovery actions for the SELECTED agent, both confirmed first (destructive):
|
|
2619
2643
|
// Stop — graceful: send the CLI's exit command (claude/codex /exit, gemini
|
|
@@ -3155,6 +3179,14 @@
|
|
|
3155
3179
|
}
|
|
3156
3180
|
}
|
|
3157
3181
|
|
|
3182
|
+
// Reflect the selected agent's title in the browser tab, live. Mirrors
|
|
3183
|
+
// $("rname") — set on select() and again on the agent's OSC title sequence —
|
|
3184
|
+
// so the tab tracks renames in realtime. Reverts to the default when nothing
|
|
3185
|
+
// is selected.
|
|
3186
|
+
function setDocTitle(name) {
|
|
3187
|
+
document.title = docTitle(name); // pure formatter in console-logic.js (tested)
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3158
3190
|
function select(keyOrPid) {
|
|
3159
3191
|
const e =
|
|
3160
3192
|
entries.find((x) => x._key === keyOrPid) ||
|
|
@@ -3195,7 +3227,9 @@
|
|
|
3195
3227
|
document.querySelector(".app").classList.add("show-detail");
|
|
3196
3228
|
$("rhead").style.display = "flex";
|
|
3197
3229
|
$("rdot").className = "dot " + e.status;
|
|
3198
|
-
|
|
3230
|
+
const rname = e.title || cliLabel(e) || ident(e) || "agent";
|
|
3231
|
+
$("rname").textContent = rname;
|
|
3232
|
+
setDocTitle(rname); // tab title follows the selected agent
|
|
3199
3233
|
$("rpid").textContent = "pid " + e.pid;
|
|
3200
3234
|
|
|
3201
3235
|
// Render the agent's native TUI with xterm.js by feeding it the raw PTY
|
|
@@ -3244,6 +3278,7 @@
|
|
|
3244
3278
|
const title = t && t.trim();
|
|
3245
3279
|
if (sel !== e._key || !title) return;
|
|
3246
3280
|
$("rname").textContent = title;
|
|
3281
|
+
setDocTitle(title); // realtime rename → update the browser tab too
|
|
3247
3282
|
// Keep the left panel in lockstep with the terminal header. The row
|
|
3248
3283
|
// title otherwise only refreshes on the 3s /api/ls poll, so it visibly
|
|
3249
3284
|
// lagged the live terminal. Patch the current entry (entries is
|
|
@@ -3262,11 +3297,13 @@
|
|
|
3262
3297
|
// one-shot "push only if the agent is out of sync" check.
|
|
3263
3298
|
let suppressPush = true;
|
|
3264
3299
|
const pushSize = () => {
|
|
3265
|
-
if (term && sel === e._key && !suppressPush)
|
|
3300
|
+
if (term && sel === e._key && !suppressPush) {
|
|
3301
|
+
lastDroveAt = Date.now(); // we're driving the size now (lease the grid)
|
|
3266
3302
|
tx.post("/api/resize/" + encodeURIComponent(pid), {
|
|
3267
3303
|
cols: term.cols,
|
|
3268
3304
|
rows: term.rows,
|
|
3269
3305
|
}).catch(() => {});
|
|
3306
|
+
}
|
|
3270
3307
|
};
|
|
3271
3308
|
term.onResize(pushSize);
|
|
3272
3309
|
// Scrolling through OUR scrollback moves the viewport over the buffer, so
|
|
@@ -3306,12 +3343,14 @@
|
|
|
3306
3343
|
fit.fit();
|
|
3307
3344
|
} catch {}
|
|
3308
3345
|
if (!sz || sz.cols !== term.cols || sz.rows !== term.rows) {
|
|
3346
|
+
lastDroveAt = Date.now(); // adopting our size on open = we drive (lease)
|
|
3309
3347
|
tx.post("/api/resize/" + encodeURIComponent(pid), {
|
|
3310
3348
|
cols: term.cols,
|
|
3311
3349
|
rows: term.rows,
|
|
3312
3350
|
}).catch(() => {});
|
|
3313
3351
|
}
|
|
3314
3352
|
suppressPush = false;
|
|
3353
|
+
applyCanvasScale(); // driver: grid == pane → no-op; otherwise letterbox
|
|
3315
3354
|
};
|
|
3316
3355
|
// Fit + sync now, and on every later tab re-activation: re-measure our pane
|
|
3317
3356
|
// and re-assert our size to the agent so the stream always reflows to OUR
|
|
@@ -3420,10 +3459,14 @@
|
|
|
3420
3459
|
renderList();
|
|
3421
3460
|
});
|
|
3422
3461
|
window.addEventListener("resize", () => {
|
|
3462
|
+
// Resizing our window is strong intent → re-fit to our pane (we become the
|
|
3463
|
+
// size driver; the push rides term.onResize). applyCanvasScale then clears
|
|
3464
|
+
// the transform since our grid now matches our pane.
|
|
3423
3465
|
if (fit)
|
|
3424
3466
|
try {
|
|
3425
3467
|
fit.fit();
|
|
3426
3468
|
} catch {}
|
|
3469
|
+
applyCanvasScale();
|
|
3427
3470
|
renderPeerSelections(); // cell size changed → reposition peer-selection overlays
|
|
3428
3471
|
});
|
|
3429
3472
|
// iOS overlays the soft keyboard ON TOP of the layout viewport rather than
|
package/package.json
CHANGED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-BwsLxt1F.js";
|
|
2
|
-
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-wZekjh0q.js";
|
|
4
|
-
import "./pidStore-fqXqTKkh.js";
|
|
5
|
-
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-D9x14LOU.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|