agent-yes 1.123.0 → 1.125.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-DNtSBnm9.js +8 -0
- package/dist/{SUPPORTED_CLIS-B4O2cFlt.js → SUPPORTED_CLIS-gldLvxxn.js} +2 -2
- package/dist/cli.js +3 -3
- package/dist/index.js +2 -2
- package/dist/{schedule-DULdIkU9.js → schedule-BB-l_J5d.js} +4 -4
- package/dist/{serve-r_2v9EKc.js → serve-Ch_WYsPB.js} +5 -5
- package/dist/{setup-DHa6fX8M.js → setup-BMo2EhUJ.js} +2 -2
- package/dist/{subcommands-Tv6AwUkD.js → subcommands-C13_tHG5.js} +1 -1
- package/dist/{subcommands-B13Kto-u.js → subcommands-C1vGCBlc.js} +4 -4
- package/dist/{ts-DgukRoEI.js → ts-Dlf0U2sb.js} +2 -2
- package/dist/{versionChecker-BqOr1YqC.js → versionChecker-DY4oPzQl.js} +2 -2
- package/lab/ui/index.html +469 -17
- package/package.json +1 -1
- package/dist/SUPPORTED_CLIS-DHkqGoNv.js +0 -8
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-Dlf0U2sb.js";
|
|
2
|
+
import "./logger-B9h0djqx.js";
|
|
3
|
+
import "./versionChecker-DY4oPzQl.js";
|
|
4
|
+
import "./pidStore-CGKIhaJO.js";
|
|
5
|
+
import "./globalPidIndex-C7r2m6s7.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-gldLvxxn.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-Dlf0U2sb.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-gldLvxxn.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { n as logger } from "./logger-B9h0djqx.js";
|
|
3
|
-
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-
|
|
3
|
+
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-DY4oPzQl.js";
|
|
4
4
|
import { argv } from "process";
|
|
5
5
|
import { execFileSync, spawn } from "child_process";
|
|
6
6
|
import ms from "ms";
|
|
@@ -482,7 +482,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
482
482
|
{
|
|
483
483
|
const rawArg = process.argv[2];
|
|
484
484
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
485
|
-
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-
|
|
485
|
+
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-C13_tHG5.js");
|
|
486
486
|
if (isHelpFlag && process.argv.length === 3) {
|
|
487
487
|
cmdHelp();
|
|
488
488
|
process.exit(0);
|
|
@@ -515,7 +515,7 @@ if (config.useRust) {
|
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
517
|
if (rustBinary) {
|
|
518
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
518
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-DNtSBnm9.js");
|
|
519
519
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
520
520
|
if (config.verbose) {
|
|
521
521
|
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-Dlf0U2sb.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-DY4oPzQl.js";
|
|
4
4
|
import "./pidStore-CGKIhaJO.js";
|
|
5
5
|
import "./globalPidIndex-C7r2m6s7.js";
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-Dlf0U2sb.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-DY4oPzQl.js";
|
|
4
4
|
import "./pidStore-CGKIhaJO.js";
|
|
5
5
|
import "./globalPidIndex-C7r2m6s7.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-gldLvxxn.js";
|
|
7
7
|
import { n as resolveSpawnCwd } from "./workspaceConfig-BJO4fzEn.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-BB-l_J5d.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-Dlf0U2sb.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-DY4oPzQl.js";
|
|
4
4
|
import "./pidStore-CGKIhaJO.js";
|
|
5
5
|
import { a as updateGlobalPidStatus } from "./globalPidIndex-C7r2m6s7.js";
|
|
6
6
|
import { t as pgidForWrapper } from "./reaper-BkjPN7mw.js";
|
|
7
7
|
import "./configShared-C5QaNPnz.js";
|
|
8
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
8
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-gldLvxxn.js";
|
|
9
9
|
import "./remotes-D8GvSbhf.js";
|
|
10
|
-
import { f as readNotes, g as snapshotStatus, m as resolveOne, o as extractTaskCounts, p as renderRawLog, r as controlCodeFromName, u as listRecords, v as writeToIpc } from "./subcommands-
|
|
10
|
+
import { f as readNotes, g as snapshotStatus, m as resolveOne, o as extractTaskCounts, p as renderRawLog, r as controlCodeFromName, u as listRecords, v as writeToIpc } from "./subcommands-C1vGCBlc.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";
|
|
@@ -1107,4 +1107,4 @@ Options:
|
|
|
1107
1107
|
|
|
1108
1108
|
//#endregion
|
|
1109
1109
|
export { cmdServe };
|
|
1110
|
-
//# sourceMappingURL=serve-
|
|
1110
|
+
//# sourceMappingURL=serve-Ch_WYsPB.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-Ch_WYsPB.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-BMo2EhUJ.js.map
|
|
@@ -2,6 +2,6 @@ import "./logger-B9h0djqx.js";
|
|
|
2
2
|
import "./globalPidIndex-C7r2m6s7.js";
|
|
3
3
|
import "./configShared-C5QaNPnz.js";
|
|
4
4
|
import "./remotes-D8GvSbhf.js";
|
|
5
|
-
import { _ as stopTipForCli, a as extractNeedsInput, c as isPidAlive, d as matchKeyword, f as readNotes, g as snapshotStatus, h as runSubcommand, i as cursorAbs, l as isSubcommand, m as resolveOne, n as cmdHelp, o as extractTaskCounts, p as renderRawLog, r as controlCodeFromName, s as finalizedLines, t as GRACEFUL_EXIT_COMMANDS, u as listRecords, v as writeToIpc } from "./subcommands-
|
|
5
|
+
import { _ as stopTipForCli, a as extractNeedsInput, c as isPidAlive, d as matchKeyword, f as readNotes, g as snapshotStatus, h as runSubcommand, i as cursorAbs, l as isSubcommand, m as resolveOne, n as cmdHelp, o as extractTaskCounts, p as renderRawLog, r as controlCodeFromName, s as finalizedLines, t as GRACEFUL_EXIT_COMMANDS, u as listRecords, v as writeToIpc } from "./subcommands-C1vGCBlc.js";
|
|
6
6
|
|
|
7
7
|
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -524,15 +524,15 @@ async function runSubcommand(argv) {
|
|
|
524
524
|
case "restart": return await cmdRestart(rest);
|
|
525
525
|
case "note": return await cmdNote(rest);
|
|
526
526
|
case "serve": {
|
|
527
|
-
const { cmdServe } = await import("./serve-
|
|
527
|
+
const { cmdServe } = await import("./serve-Ch_WYsPB.js");
|
|
528
528
|
return cmdServe(rest);
|
|
529
529
|
}
|
|
530
530
|
case "setup": {
|
|
531
|
-
const { cmdSetup } = await import("./setup-
|
|
531
|
+
const { cmdSetup } = await import("./setup-BMo2EhUJ.js");
|
|
532
532
|
return cmdSetup(rest);
|
|
533
533
|
}
|
|
534
534
|
case "schedule": {
|
|
535
|
-
const { cmdSchedule } = await import("./schedule-
|
|
535
|
+
const { cmdSchedule } = await import("./schedule-BB-l_J5d.js");
|
|
536
536
|
return cmdSchedule(rest);
|
|
537
537
|
}
|
|
538
538
|
case "remote": {
|
|
@@ -2304,4 +2304,4 @@ async function cmdResultSet(rest) {
|
|
|
2304
2304
|
|
|
2305
2305
|
//#endregion
|
|
2306
2306
|
export { stopTipForCli as _, extractNeedsInput as a, isPidAlive as c, matchKeyword as d, readNotes as f, snapshotStatus as g, runSubcommand as h, cursorAbs as i, isSubcommand as l, resolveOne as m, cmdHelp as n, extractTaskCounts as o, renderRawLog as p, controlCodeFromName as r, finalizedLines as s, GRACEFUL_EXIT_COMMANDS as t, listRecords as u, writeToIpc as v };
|
|
2307
|
-
//# sourceMappingURL=subcommands-
|
|
2307
|
+
//# sourceMappingURL=subcommands-C1vGCBlc.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as logger, t as addTransport } from "./logger-B9h0djqx.js";
|
|
2
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
2
|
+
import { r as getInstalledPackage } from "./versionChecker-DY4oPzQl.js";
|
|
3
3
|
import { t as agentYesHome } from "./agentYesHome-BvaUOzCV.js";
|
|
4
4
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-CJxsoGdb.js";
|
|
5
5
|
import { t as PidStore } from "./pidStore-CGKIhaJO.js";
|
|
@@ -1787,4 +1787,4 @@ function sleep(ms) {
|
|
|
1787
1787
|
|
|
1788
1788
|
//#endregion
|
|
1789
1789
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1790
|
-
//# sourceMappingURL=ts-
|
|
1790
|
+
//# sourceMappingURL=ts-Dlf0U2sb.js.map
|
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
|
|
8
8
|
//#region package.json
|
|
9
9
|
var name = "agent-yes";
|
|
10
|
-
var version = "1.
|
|
10
|
+
var version = "1.125.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-DY4oPzQl.js.map
|
package/lab/ui/index.html
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
|
-
<meta
|
|
5
|
+
<meta
|
|
6
|
+
name="viewport"
|
|
7
|
+
content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content"
|
|
8
|
+
/>
|
|
6
9
|
<title>agent-yes · console</title>
|
|
7
10
|
<!-- PWA: installable console under /w/ (manifest scope is /w/). The service
|
|
8
11
|
worker is network-first so it never serves a stale wire protocol — the
|
|
@@ -35,6 +38,17 @@
|
|
|
35
38
|
--pink: #f778ba;
|
|
36
39
|
--red: #f85149;
|
|
37
40
|
--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
41
|
+
/* Safe-area insets — non-zero only in a standalone PWA on a notched /
|
|
42
|
+
gesture-bar device (else 0, so these are harmless on desktop). Consumed
|
|
43
|
+
via max() so the surface keeps its normal padding when the inset is 0.
|
|
44
|
+
Needs <meta viewport ... viewport-fit=cover> to be reported at all. */
|
|
45
|
+
--sat: env(safe-area-inset-top);
|
|
46
|
+
--sar: env(safe-area-inset-right);
|
|
47
|
+
--sab: env(safe-area-inset-bottom);
|
|
48
|
+
--sal: env(safe-area-inset-left);
|
|
49
|
+
/* height the iOS soft keyboard overlays the viewport with (set from JS
|
|
50
|
+
via visualViewport; 0 on desktop / Android, which resizes instead). */
|
|
51
|
+
--kb: 0px;
|
|
38
52
|
}
|
|
39
53
|
/* Light theme — GitHub-light, the daylight counterpart of the dark palette
|
|
40
54
|
above. prefers-color-scheme is re-evaluated by the browser the moment the
|
|
@@ -93,7 +107,8 @@
|
|
|
93
107
|
grid-template-columns: var(--leftw, 42%) 1px 1fr;
|
|
94
108
|
grid-template-rows: minmax(0, 1fr);
|
|
95
109
|
height: 100vh;
|
|
96
|
-
|
|
110
|
+
/* subtract the iOS keyboard overlay so the composer stays above it */
|
|
111
|
+
height: calc(100dvh - var(--kb, 0px));
|
|
97
112
|
}
|
|
98
113
|
|
|
99
114
|
/* VSCode-style splitter: the visible divider stays 1px, but a ::before
|
|
@@ -125,7 +140,7 @@
|
|
|
125
140
|
min-height: 0;
|
|
126
141
|
}
|
|
127
142
|
.head {
|
|
128
|
-
padding: 16px 18px 10px;
|
|
143
|
+
padding: max(16px, var(--sat)) max(18px, var(--sar)) 10px max(18px, var(--sal));
|
|
129
144
|
border-bottom: 1px solid var(--line);
|
|
130
145
|
}
|
|
131
146
|
h1 {
|
|
@@ -260,6 +275,40 @@
|
|
|
260
275
|
background: var(--line);
|
|
261
276
|
margin: 4px 2px;
|
|
262
277
|
}
|
|
278
|
+
/* Terminal font-size stepper (a static row, not a hover/click target). */
|
|
279
|
+
.rmenufont {
|
|
280
|
+
justify-content: space-between;
|
|
281
|
+
cursor: default;
|
|
282
|
+
}
|
|
283
|
+
.rmenufont:hover {
|
|
284
|
+
background: none;
|
|
285
|
+
}
|
|
286
|
+
.fontstep {
|
|
287
|
+
display: inline-flex;
|
|
288
|
+
align-items: center;
|
|
289
|
+
gap: 8px;
|
|
290
|
+
}
|
|
291
|
+
.fontstep button {
|
|
292
|
+
width: 26px;
|
|
293
|
+
height: 26px;
|
|
294
|
+
background: var(--panel2);
|
|
295
|
+
border: 1px solid var(--line);
|
|
296
|
+
border-radius: 6px;
|
|
297
|
+
color: var(--fg);
|
|
298
|
+
font-size: 13px;
|
|
299
|
+
line-height: 1;
|
|
300
|
+
cursor: pointer;
|
|
301
|
+
}
|
|
302
|
+
.fontstep button:hover {
|
|
303
|
+
border-color: var(--accent);
|
|
304
|
+
color: var(--accent);
|
|
305
|
+
}
|
|
306
|
+
.fontstep #fontVal {
|
|
307
|
+
min-width: 18px;
|
|
308
|
+
text-align: center;
|
|
309
|
+
font-variant-numeric: tabular-nums;
|
|
310
|
+
color: var(--muted);
|
|
311
|
+
}
|
|
263
312
|
/* Live performance HUD — opt-in via the ⋯ menu, hidden by default. */
|
|
264
313
|
.perfhud {
|
|
265
314
|
position: absolute;
|
|
@@ -627,6 +676,8 @@
|
|
|
627
676
|
overflow-y: auto;
|
|
628
677
|
flex: 1;
|
|
629
678
|
min-height: 0;
|
|
679
|
+
/* clear the home-indicator / gesture bar so the last row stays tappable */
|
|
680
|
+
padding-bottom: var(--sab);
|
|
630
681
|
}
|
|
631
682
|
.row {
|
|
632
683
|
padding: 11px 18px;
|
|
@@ -834,7 +885,7 @@
|
|
|
834
885
|
position: relative; /* anchor for the absolutely-positioned perf HUD */
|
|
835
886
|
}
|
|
836
887
|
.rhead {
|
|
837
|
-
padding: 14px 20px;
|
|
888
|
+
padding: max(14px, var(--sat)) max(20px, var(--sar)) 14px max(20px, var(--sal));
|
|
838
889
|
border-bottom: 1px solid var(--line);
|
|
839
890
|
display: flex;
|
|
840
891
|
align-items: center;
|
|
@@ -842,6 +893,13 @@
|
|
|
842
893
|
}
|
|
843
894
|
.rhead .name {
|
|
844
895
|
font-size: 15px;
|
|
896
|
+
/* shrink + ellipsis so a long agent title can't shove the live/⋯
|
|
897
|
+
controls off the edge on a narrow phone header */
|
|
898
|
+
flex: 0 1 auto;
|
|
899
|
+
min-width: 0;
|
|
900
|
+
overflow: hidden;
|
|
901
|
+
text-overflow: ellipsis;
|
|
902
|
+
white-space: nowrap;
|
|
845
903
|
}
|
|
846
904
|
/* back-to-list affordance — only surfaces in the single-column mobile view */
|
|
847
905
|
.rback {
|
|
@@ -882,7 +940,7 @@
|
|
|
882
940
|
flex: 1;
|
|
883
941
|
min-height: 0;
|
|
884
942
|
overflow: hidden;
|
|
885
|
-
padding: 8px 10px;
|
|
943
|
+
padding: 8px max(10px, var(--sar)) 8px max(10px, var(--sal));
|
|
886
944
|
background: var(--bg);
|
|
887
945
|
}
|
|
888
946
|
.log .xterm {
|
|
@@ -899,6 +957,96 @@
|
|
|
899
957
|
color: var(--muted);
|
|
900
958
|
font-size: 14px;
|
|
901
959
|
}
|
|
960
|
+
/* On-screen key bar — hidden on desktop, flex on mobile (720px block).
|
|
961
|
+
Scrolls horizontally so it never wraps or steals height from the log. */
|
|
962
|
+
.keybar {
|
|
963
|
+
display: none;
|
|
964
|
+
flex: none;
|
|
965
|
+
gap: 6px;
|
|
966
|
+
align-items: center;
|
|
967
|
+
padding: 6px max(8px, var(--sar)) 6px max(8px, var(--sal));
|
|
968
|
+
border-top: 1px solid var(--line);
|
|
969
|
+
background: var(--panel);
|
|
970
|
+
overflow-x: auto;
|
|
971
|
+
-webkit-overflow-scrolling: touch;
|
|
972
|
+
scrollbar-width: none;
|
|
973
|
+
}
|
|
974
|
+
.keybar::-webkit-scrollbar {
|
|
975
|
+
display: none;
|
|
976
|
+
}
|
|
977
|
+
.keybar .kb {
|
|
978
|
+
flex: none;
|
|
979
|
+
min-width: 36px;
|
|
980
|
+
height: 36px;
|
|
981
|
+
padding: 0 11px;
|
|
982
|
+
background: var(--panel2);
|
|
983
|
+
border: 1px solid var(--line);
|
|
984
|
+
border-radius: 8px;
|
|
985
|
+
color: var(--fg);
|
|
986
|
+
font: 13px/1 var(--mono);
|
|
987
|
+
cursor: pointer;
|
|
988
|
+
-webkit-tap-highlight-color: transparent;
|
|
989
|
+
user-select: none;
|
|
990
|
+
}
|
|
991
|
+
.keybar .kb:active {
|
|
992
|
+
background: var(--line);
|
|
993
|
+
}
|
|
994
|
+
/* a sticky Ctrl/Alt that's armed for the next keystroke */
|
|
995
|
+
.keybar .kb.on {
|
|
996
|
+
background: var(--accent);
|
|
997
|
+
border-color: var(--accent);
|
|
998
|
+
color: #fff;
|
|
999
|
+
}
|
|
1000
|
+
/* Line composer — mobile-only. Carries the bottom safe-area inset so it
|
|
1001
|
+
clears the home indicator (completes the terminal pane's inset cover). */
|
|
1002
|
+
.composer {
|
|
1003
|
+
display: none;
|
|
1004
|
+
flex: none;
|
|
1005
|
+
gap: 8px;
|
|
1006
|
+
align-items: flex-end;
|
|
1007
|
+
padding: 8px max(10px, var(--sar)) max(8px, var(--sab)) max(10px, var(--sal));
|
|
1008
|
+
border-top: 1px solid var(--line);
|
|
1009
|
+
background: var(--panel);
|
|
1010
|
+
}
|
|
1011
|
+
.composer textarea {
|
|
1012
|
+
flex: 1;
|
|
1013
|
+
min-width: 0;
|
|
1014
|
+
resize: none;
|
|
1015
|
+
max-height: 120px;
|
|
1016
|
+
padding: 9px 11px;
|
|
1017
|
+
background: var(--bg);
|
|
1018
|
+
border: 1px solid var(--line);
|
|
1019
|
+
border-radius: 10px;
|
|
1020
|
+
color: var(--fg);
|
|
1021
|
+
/* ≥16px so iOS Safari doesn't auto-zoom the page when it gains focus */
|
|
1022
|
+
font:
|
|
1023
|
+
16px/1.4 -apple-system,
|
|
1024
|
+
BlinkMacSystemFont,
|
|
1025
|
+
system-ui,
|
|
1026
|
+
sans-serif;
|
|
1027
|
+
}
|
|
1028
|
+
.composer textarea:focus {
|
|
1029
|
+
outline: none;
|
|
1030
|
+
border-color: var(--accent);
|
|
1031
|
+
}
|
|
1032
|
+
.composer .cmpsend {
|
|
1033
|
+
flex: none;
|
|
1034
|
+
height: 38px;
|
|
1035
|
+
padding: 0 14px;
|
|
1036
|
+
background: var(--accent);
|
|
1037
|
+
border: 1px solid var(--accent);
|
|
1038
|
+
border-radius: 10px;
|
|
1039
|
+
color: #fff;
|
|
1040
|
+
font:
|
|
1041
|
+
600 13px/1 -apple-system,
|
|
1042
|
+
system-ui,
|
|
1043
|
+
sans-serif;
|
|
1044
|
+
cursor: pointer;
|
|
1045
|
+
-webkit-tap-highlight-color: transparent;
|
|
1046
|
+
}
|
|
1047
|
+
.composer .cmpsend:active {
|
|
1048
|
+
opacity: 0.85;
|
|
1049
|
+
}
|
|
902
1050
|
|
|
903
1051
|
/* ---- mobile: collapse the two-pane desktop layout into a single column ----
|
|
904
1052
|
The list and the terminal stack into the same cell; only one is visible at
|
|
@@ -937,7 +1085,7 @@
|
|
|
937
1085
|
}
|
|
938
1086
|
|
|
939
1087
|
.head {
|
|
940
|
-
padding: 12px 14px 8px;
|
|
1088
|
+
padding: max(12px, var(--sat)) max(14px, var(--sar)) 8px max(14px, var(--sal));
|
|
941
1089
|
}
|
|
942
1090
|
h1 {
|
|
943
1091
|
font-size: 17px;
|
|
@@ -961,7 +1109,8 @@
|
|
|
961
1109
|
padding: 10px 14px;
|
|
962
1110
|
}
|
|
963
1111
|
.rhead {
|
|
964
|
-
padding: 12px 14px;
|
|
1112
|
+
padding: max(12px, var(--sat)) max(14px, var(--sar)) 12px max(14px, var(--sal));
|
|
1113
|
+
gap: 8px;
|
|
965
1114
|
}
|
|
966
1115
|
.list .row,
|
|
967
1116
|
.rooms .ritem,
|
|
@@ -972,6 +1121,15 @@
|
|
|
972
1121
|
-webkit-tap-highlight-color: transparent;
|
|
973
1122
|
}
|
|
974
1123
|
}
|
|
1124
|
+
/* Touch input aids (key bar + composer) show on ANY touch device, not just
|
|
1125
|
+
narrow ones — so a tablet in the two-pane layout (typically no hardware
|
|
1126
|
+
keyboard) still gets Esc/Ctrl/arrows and a reliable line composer. */
|
|
1127
|
+
@media (pointer: coarse) {
|
|
1128
|
+
.keybar,
|
|
1129
|
+
.composer {
|
|
1130
|
+
display: flex;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
975
1133
|
</style>
|
|
976
1134
|
<link
|
|
977
1135
|
rel="stylesheet"
|
|
@@ -1051,6 +1209,15 @@
|
|
|
1051
1209
|
<span class="rmenu">
|
|
1052
1210
|
<button class="rmenubtn" id="rmenubtn" title="more" aria-label="more">⋯</button>
|
|
1053
1211
|
<div class="rmenupanel" id="rmenupanel" hidden>
|
|
1212
|
+
<div class="rmenuitem rmenufont">
|
|
1213
|
+
<span>Font size</span>
|
|
1214
|
+
<span class="fontstep">
|
|
1215
|
+
<button type="button" id="fontDown" aria-label="smaller font">A−</button>
|
|
1216
|
+
<span id="fontVal">12</span>
|
|
1217
|
+
<button type="button" id="fontUp" aria-label="larger font">A+</button>
|
|
1218
|
+
</span>
|
|
1219
|
+
</div>
|
|
1220
|
+
<div class="rmenusep"></div>
|
|
1054
1221
|
<label class="rmenuitem"
|
|
1055
1222
|
><input type="checkbox" id="perfToggle" /> <span>Perf HUD</span></label
|
|
1056
1223
|
>
|
|
@@ -1067,6 +1234,41 @@
|
|
|
1067
1234
|
← pick an agent to tail its log; type directly into the terminal
|
|
1068
1235
|
</div>
|
|
1069
1236
|
</div>
|
|
1237
|
+
<!-- On-screen key bar — phones have no Esc/Tab/Ctrl/arrows, so agent TUIs
|
|
1238
|
+
are otherwise undriveable. Mobile-only (shown in the 720px block);
|
|
1239
|
+
posts raw sequences to the agent over the same /api/send wire. -->
|
|
1240
|
+
<div class="keybar" id="keybar" role="group" aria-label="terminal keys">
|
|
1241
|
+
<button class="kb" data-key="esc" title="Escape">Esc</button>
|
|
1242
|
+
<button class="kb kbmod" data-mod="ctrl" title="Ctrl — applies to the next key">
|
|
1243
|
+
Ctrl
|
|
1244
|
+
</button>
|
|
1245
|
+
<button class="kb kbmod" data-mod="alt" title="Alt — applies to the next key">Alt</button>
|
|
1246
|
+
<button class="kb" data-key="tab" title="Tab">Tab</button>
|
|
1247
|
+
<button class="kb" data-key="stab" title="Shift-Tab (e.g. cycle modes)">⇧Tab</button>
|
|
1248
|
+
<button class="kb" data-key="cc" title="Ctrl-C — interrupt">^C</button>
|
|
1249
|
+
<button class="kb" data-arrow="up" title="Up" aria-label="Up">↑</button>
|
|
1250
|
+
<button class="kb" data-arrow="down" title="Down" aria-label="Down">↓</button>
|
|
1251
|
+
<button class="kb" data-arrow="left" title="Left" aria-label="Left">←</button>
|
|
1252
|
+
<button class="kb" data-arrow="right" title="Right" aria-label="Right">→</button>
|
|
1253
|
+
<button class="kb" data-key="enter" title="Enter">⏎</button>
|
|
1254
|
+
</div>
|
|
1255
|
+
<!-- Line composer — the reliable path for typing a prompt on a phone:
|
|
1256
|
+
a normal textarea (no IME/autocorrect surprises that plague xterm's
|
|
1257
|
+
hidden input). Enter sends, Shift+Enter inserts a newline. -->
|
|
1258
|
+
<form class="composer" id="composer">
|
|
1259
|
+
<textarea
|
|
1260
|
+
id="cmpin"
|
|
1261
|
+
rows="1"
|
|
1262
|
+
placeholder="Message agent… ↵ to send"
|
|
1263
|
+
enterkeyhint="send"
|
|
1264
|
+
inputmode="text"
|
|
1265
|
+
autocapitalize="off"
|
|
1266
|
+
autocorrect="off"
|
|
1267
|
+
autocomplete="off"
|
|
1268
|
+
spellcheck="false"
|
|
1269
|
+
></textarea>
|
|
1270
|
+
<button type="submit" class="cmpsend" title="Send to agent">Send</button>
|
|
1271
|
+
</form>
|
|
1070
1272
|
<div class="perfhud" id="perfhud" hidden></div>
|
|
1071
1273
|
</div>
|
|
1072
1274
|
</div>
|
|
@@ -1117,6 +1319,28 @@
|
|
|
1117
1319
|
let es = null; // live-tail subscription closer
|
|
1118
1320
|
let term = null; // xterm.js Terminal rendering the raw PTY stream
|
|
1119
1321
|
let fit = null;
|
|
1322
|
+
// Terminal font size (px) — adjustable from the ⋯ menu, persisted across
|
|
1323
|
+
// reloads, applied live to the open terminal and used by every new one.
|
|
1324
|
+
let termFontSize = 12;
|
|
1325
|
+
try {
|
|
1326
|
+
const n = parseInt(localStorage.getItem("ay.fontSize") || "", 10);
|
|
1327
|
+
if (n >= 8 && n <= 32) termFontSize = n;
|
|
1328
|
+
} catch {}
|
|
1329
|
+
function setTermFontSize(px) {
|
|
1330
|
+
termFontSize = Math.max(8, Math.min(32, px | 0));
|
|
1331
|
+
const v = $("fontVal");
|
|
1332
|
+
if (v) v.textContent = String(termFontSize);
|
|
1333
|
+
try {
|
|
1334
|
+
localStorage.setItem("ay.fontSize", String(termFontSize));
|
|
1335
|
+
} catch {}
|
|
1336
|
+
if (term) {
|
|
1337
|
+
term.options.fontSize = termFontSize;
|
|
1338
|
+
if (fit)
|
|
1339
|
+
try {
|
|
1340
|
+
fit.fit();
|
|
1341
|
+
} catch {}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1120
1344
|
|
|
1121
1345
|
// xterm paints to a <canvas>, so unlike the CSS var() consumers it can't
|
|
1122
1346
|
// ride prefers-color-scheme on its own — its theme is a JS object. Mirror
|
|
@@ -2020,6 +2244,161 @@
|
|
|
2020
2244
|
await new Promise((r) => setTimeout(r, 200));
|
|
2021
2245
|
await send("\r");
|
|
2022
2246
|
}
|
|
2247
|
+
|
|
2248
|
+
// ---- On-screen key bar (mobile) -------------------------------------
|
|
2249
|
+
// A phone keyboard has no Esc/Tab/Ctrl/arrows, so agent TUIs (claude,
|
|
2250
|
+
// codex, vim…) are otherwise undriveable. The bar posts raw byte
|
|
2251
|
+
// sequences straight to the selected agent's stdin, and a sticky Ctrl/Alt
|
|
2252
|
+
// rewrites the NEXT character typed on the soft keyboard.
|
|
2253
|
+
let modCtrl = false,
|
|
2254
|
+
modAlt = false;
|
|
2255
|
+
// Send raw bytes to the currently-selected agent. Uses the live `sel`, so
|
|
2256
|
+
// it always hits the open agent even while an old terminal tears down mid
|
|
2257
|
+
// switch — the same /api/send wire the terminal's own input uses.
|
|
2258
|
+
function sendToSelected(data) {
|
|
2259
|
+
const e = sel ? entries.find((x) => x._key === sel) : null;
|
|
2260
|
+
if (!e || data == null) return;
|
|
2261
|
+
perfNote("in", typeof data === "string" ? data.length : (data?.byteLength ?? 0));
|
|
2262
|
+
txFor(e)
|
|
2263
|
+
.post("/api/send", { keyword: String(e.pid), msg: data, code: "none" })
|
|
2264
|
+
.catch(() => {});
|
|
2265
|
+
}
|
|
2266
|
+
// Apply a pending sticky Ctrl/Alt to ONE typed character (soft-keyboard
|
|
2267
|
+
// path only). Multi-char input — paste, an IME commit, an escape sequence —
|
|
2268
|
+
// passes through untouched. Ctrl folds @A–Z[\]^_ (case-insensitive) to
|
|
2269
|
+
// 0x00–0x1f; Alt/Meta is an ESC prefix. One-shot: clears after one char.
|
|
2270
|
+
function applyStickyMods(d) {
|
|
2271
|
+
if ((!modCtrl && !modAlt) || typeof d !== "string" || d.length !== 1) return d;
|
|
2272
|
+
let c = d;
|
|
2273
|
+
if (modCtrl) {
|
|
2274
|
+
const u = d.toUpperCase().charCodeAt(0);
|
|
2275
|
+
if (u >= 64 && u <= 95) c = String.fromCharCode(u - 64);
|
|
2276
|
+
else if (u === 32) c = "\x00"; // Ctrl-Space → NUL
|
|
2277
|
+
}
|
|
2278
|
+
if (modAlt) c = "\x1b" + c;
|
|
2279
|
+
modCtrl = modAlt = false;
|
|
2280
|
+
syncModButtons();
|
|
2281
|
+
return c;
|
|
2282
|
+
}
|
|
2283
|
+
function syncModButtons() {
|
|
2284
|
+
const kb = $("keybar");
|
|
2285
|
+
if (!kb) return;
|
|
2286
|
+
kb.querySelector('[data-mod="ctrl"]')?.classList.toggle("on", modCtrl);
|
|
2287
|
+
kb.querySelector('[data-mod="alt"]')?.classList.toggle("on", modAlt);
|
|
2288
|
+
}
|
|
2289
|
+
(function keybarBoot() {
|
|
2290
|
+
const kb = $("keybar");
|
|
2291
|
+
if (!kb) return;
|
|
2292
|
+
// stab = Shift-Tab → CBT (ESC [ Z); back-tab / reverse field nav, and
|
|
2293
|
+
// what Claude Code's TUI reads to cycle permission modes.
|
|
2294
|
+
const SEQ = { esc: "\x1b", tab: "\t", stab: "\x1b[Z", enter: "\r", cc: "\x03" };
|
|
2295
|
+
const ARROW = { up: "A", down: "B", right: "C", left: "D" };
|
|
2296
|
+
// Don't let a button steal focus — that would drop the soft keyboard and
|
|
2297
|
+
// blur whatever the user is typing into (terminal or composer).
|
|
2298
|
+
kb.addEventListener("pointerdown", (ev) => {
|
|
2299
|
+
if (ev.target.closest("button")) ev.preventDefault();
|
|
2300
|
+
});
|
|
2301
|
+
kb.addEventListener("click", (ev) => {
|
|
2302
|
+
const b = ev.target.closest("button.kb");
|
|
2303
|
+
if (!b) return;
|
|
2304
|
+
if (b.dataset.mod) {
|
|
2305
|
+
// sticky toggle — armed for the next soft-keyboard character
|
|
2306
|
+
if (b.dataset.mod === "ctrl") modCtrl = !modCtrl;
|
|
2307
|
+
else modAlt = !modAlt;
|
|
2308
|
+
syncModButtons();
|
|
2309
|
+
return;
|
|
2310
|
+
}
|
|
2311
|
+
let seq = null;
|
|
2312
|
+
if (b.dataset.arrow) {
|
|
2313
|
+
const L = ARROW[b.dataset.arrow];
|
|
2314
|
+
if (modCtrl || modAlt) {
|
|
2315
|
+
// Ctrl/Alt + arrow → CSI modifier form ESC [ 1 ; <m> <L>, where
|
|
2316
|
+
// m = 1 + Alt(2) + Ctrl(4) (e.g. Ctrl-Left = ESC [ 1 ; 5 D for
|
|
2317
|
+
// word-wise motion). Modified cursor keys are always CSI, never
|
|
2318
|
+
// SS3, so DECCKM doesn't apply when a modifier is held.
|
|
2319
|
+
seq = "\x1b[1;" + (1 + (modAlt ? 2 : 0) + (modCtrl ? 4 : 0)) + L;
|
|
2320
|
+
} else {
|
|
2321
|
+
// Honour application-cursor-key mode (DECCKM): TUIs that enable it
|
|
2322
|
+
// expect SS3 (ESC O x) arrows, not CSI (ESC [ x). xterm tracks it.
|
|
2323
|
+
const app = term && term.modes && term.modes.applicationCursorKeysMode;
|
|
2324
|
+
seq = (app ? "\x1bO" : "\x1b[") + L;
|
|
2325
|
+
}
|
|
2326
|
+
} else if (b.dataset.key) {
|
|
2327
|
+
seq = SEQ[b.dataset.key];
|
|
2328
|
+
// Alt/Meta on a fixed key = ESC prefix (e.g. Alt+Enter). Ctrl on
|
|
2329
|
+
// Esc/Tab/Enter has no standard sequence, so it's left as the bare key.
|
|
2330
|
+
if (seq != null && modAlt) seq = "\x1b" + seq;
|
|
2331
|
+
}
|
|
2332
|
+
if (seq == null) return;
|
|
2333
|
+
// the armed modifier (if any) has now been folded into this key — clear it
|
|
2334
|
+
modCtrl = modAlt = false;
|
|
2335
|
+
syncModButtons();
|
|
2336
|
+
sendToSelected(seq);
|
|
2337
|
+
});
|
|
2338
|
+
})();
|
|
2339
|
+
// ---- Line composer (mobile) ----------------------------------------
|
|
2340
|
+
// The dependable way to type a prompt on a phone: a real textarea, immune
|
|
2341
|
+
// to the IME/autocorrect glitches that dog xterm's hidden input. Enter
|
|
2342
|
+
// sends text + a carriage return in one write (identical to typing then ↵);
|
|
2343
|
+
// Shift+Enter inserts a literal newline.
|
|
2344
|
+
(function composerBoot() {
|
|
2345
|
+
const form = $("composer"),
|
|
2346
|
+
ta = $("cmpin");
|
|
2347
|
+
if (!form || !ta) return;
|
|
2348
|
+
const grow = () => {
|
|
2349
|
+
ta.style.height = "auto";
|
|
2350
|
+
ta.style.height = Math.min(ta.scrollHeight, 120) + "px";
|
|
2351
|
+
};
|
|
2352
|
+
const sendLine = () => {
|
|
2353
|
+
let v = ta.value;
|
|
2354
|
+
if (!v) return;
|
|
2355
|
+
// An armed sticky Ctrl/Alt decorates a single-char line (e.g. Ctrl-D);
|
|
2356
|
+
// longer text can't carry it, but the modifier must still be cleared so
|
|
2357
|
+
// it doesn't silently leak into the next terminal keystroke.
|
|
2358
|
+
v = applyStickyMods(v);
|
|
2359
|
+
if (modCtrl || modAlt) {
|
|
2360
|
+
modCtrl = modAlt = false;
|
|
2361
|
+
syncModButtons();
|
|
2362
|
+
}
|
|
2363
|
+
sendToSelected(v + "\r");
|
|
2364
|
+
ta.value = "";
|
|
2365
|
+
grow();
|
|
2366
|
+
ta.focus(); // keep the soft keyboard up for the next line
|
|
2367
|
+
};
|
|
2368
|
+
ta.addEventListener("input", grow);
|
|
2369
|
+
form.addEventListener("submit", (ev) => {
|
|
2370
|
+
ev.preventDefault();
|
|
2371
|
+
sendLine();
|
|
2372
|
+
});
|
|
2373
|
+
// Enter sends; Shift+Enter inserts a newline; never fire mid-IME-commit
|
|
2374
|
+
// (the confirming Enter reports keyCode 229 / isComposing). `enterSeen`
|
|
2375
|
+
// lets the beforeinput fallback below know keydown already decided this
|
|
2376
|
+
// Enter (so it doesn't double-send, and Shift+Enter still makes a newline).
|
|
2377
|
+
let enterSeen = false;
|
|
2378
|
+
ta.addEventListener("keydown", (ev) => {
|
|
2379
|
+
enterSeen = false;
|
|
2380
|
+
if (ev.key === "Enter" && !ev.isComposing && ev.keyCode !== 229) {
|
|
2381
|
+
enterSeen = true;
|
|
2382
|
+
if (!ev.shiftKey) {
|
|
2383
|
+
ev.preventDefault();
|
|
2384
|
+
sendLine();
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
});
|
|
2388
|
+
// Android (Gboard) commonly delivers Enter as keyCode 229 / key
|
|
2389
|
+
// "Unidentified", so the keydown above never matches it. beforeinput's
|
|
2390
|
+
// insertLineBreak fires reliably there; skip it when keydown already
|
|
2391
|
+
// saw the Enter (desktop/iOS, including the Shift+Enter newline case).
|
|
2392
|
+
ta.addEventListener("beforeinput", (ev) => {
|
|
2393
|
+
if (ev.inputType !== "insertLineBreak") return;
|
|
2394
|
+
if (enterSeen) {
|
|
2395
|
+
enterSeen = false;
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2398
|
+
ev.preventDefault();
|
|
2399
|
+
sendLine();
|
|
2400
|
+
});
|
|
2401
|
+
})();
|
|
2023
2402
|
(function perfMenuBoot() {
|
|
2024
2403
|
const btn = $("rmenubtn"),
|
|
2025
2404
|
panel = $("rmenupanel"),
|
|
@@ -2037,6 +2416,10 @@
|
|
|
2037
2416
|
if (cb) cb.addEventListener("change", () => setPerfHud(cb.checked));
|
|
2038
2417
|
$("stopAgent")?.addEventListener("click", () => (closePanel(), stopAgent(false)));
|
|
2039
2418
|
$("killAgent")?.addEventListener("click", () => (closePanel(), stopAgent(true)));
|
|
2419
|
+
// Font stepper — stays open so you can tap repeatedly; persists + refits.
|
|
2420
|
+
$("fontDown")?.addEventListener("click", () => setTermFontSize(termFontSize - 1));
|
|
2421
|
+
$("fontUp")?.addEventListener("click", () => setTermFontSize(termFontSize + 1));
|
|
2422
|
+
setTermFontSize(termFontSize); // sync the label with the restored value
|
|
2040
2423
|
let saved = false;
|
|
2041
2424
|
try {
|
|
2042
2425
|
saved = localStorage.getItem("ay.perfHud") === "1";
|
|
@@ -2397,7 +2780,7 @@
|
|
|
2397
2780
|
disableStdin: false,
|
|
2398
2781
|
cursorBlink: true,
|
|
2399
2782
|
scrollback: 5000,
|
|
2400
|
-
fontSize:
|
|
2783
|
+
fontSize: termFontSize,
|
|
2401
2784
|
fontFamily: 'ui-monospace, "SF Mono", Menlo, monospace',
|
|
2402
2785
|
theme: termTheme(),
|
|
2403
2786
|
});
|
|
@@ -2463,10 +2846,11 @@
|
|
|
2463
2846
|
// keyword with 400 (pid arrives as a number from /api/ls JSON).
|
|
2464
2847
|
const kw = String(pid);
|
|
2465
2848
|
const fwd = (d) => {
|
|
2466
|
-
if (sel
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2849
|
+
if (sel !== e._key) return; // ignore a stale terminal mid-switch
|
|
2850
|
+
// a soft-keyboard character may be decorated by an armed sticky Ctrl/Alt
|
|
2851
|
+
if (typeof d === "string") d = applyStickyMods(d);
|
|
2852
|
+
perfNote("in", typeof d === "string" ? d.length : (d?.byteLength ?? 0));
|
|
2853
|
+
tx.post("/api/send", { keyword: kw, msg: d, code: "none" }).catch(() => {});
|
|
2470
2854
|
};
|
|
2471
2855
|
term.onData(fwd);
|
|
2472
2856
|
term.onBinary(fwd);
|
|
@@ -2527,11 +2911,51 @@
|
|
|
2527
2911
|
const row = ev.target.closest(".row");
|
|
2528
2912
|
if (row) select(row.dataset.key);
|
|
2529
2913
|
});
|
|
2530
|
-
// Mobile back
|
|
2914
|
+
// Mobile back: return to the list pane. The tail keeps streaming in the
|
|
2531
2915
|
// background (selection unchanged), so reopening the agent is instant.
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2916
|
+
const goBack = () => document.querySelector(".app").classList.remove("show-detail");
|
|
2917
|
+
$("rback").addEventListener("click", goBack);
|
|
2918
|
+
// Swipe-right-from-the-left-edge → back, an alternative to the ‹ button.
|
|
2919
|
+
// Passive/read-only so it never fights xterm's own scroll or text
|
|
2920
|
+
// selection; armed only from the left edge, in the single-column view, and
|
|
2921
|
+
// never when a TUI has mouse tracking on (that touch belongs to the agent).
|
|
2922
|
+
(function swipeBackBoot() {
|
|
2923
|
+
const pane = document.querySelector(".right");
|
|
2924
|
+
if (!pane) return;
|
|
2925
|
+
let sx = 0,
|
|
2926
|
+
sy = 0,
|
|
2927
|
+
st = 0,
|
|
2928
|
+
armed = false;
|
|
2929
|
+
pane.addEventListener(
|
|
2930
|
+
"touchstart",
|
|
2931
|
+
(ev) => {
|
|
2932
|
+
armed = false;
|
|
2933
|
+
if (window.innerWidth > 720 || ev.touches.length !== 1) return;
|
|
2934
|
+
const t = ev.touches[0];
|
|
2935
|
+
armed = t.clientX <= 28; // left-edge start only
|
|
2936
|
+
sx = t.clientX;
|
|
2937
|
+
sy = t.clientY;
|
|
2938
|
+
st = ev.timeStamp;
|
|
2939
|
+
},
|
|
2940
|
+
{ passive: true },
|
|
2941
|
+
);
|
|
2942
|
+
pane.addEventListener(
|
|
2943
|
+
"touchend",
|
|
2944
|
+
(ev) => {
|
|
2945
|
+
if (!armed) return;
|
|
2946
|
+
armed = false;
|
|
2947
|
+
const mt = term && term.modes && term.modes.mouseTrackingMode;
|
|
2948
|
+
if (mt && mt !== "none") return; // the TUI wants this touch
|
|
2949
|
+
const t = ev.changedTouches[0];
|
|
2950
|
+
if (!t) return;
|
|
2951
|
+
const dx = t.clientX - sx,
|
|
2952
|
+
dy = t.clientY - sy;
|
|
2953
|
+
// a quick, clearly-horizontal rightward flick (not a scroll/tap)
|
|
2954
|
+
if (dx > 45 && Math.abs(dx) > 2 * Math.abs(dy) && ev.timeStamp - st < 500) goBack();
|
|
2955
|
+
},
|
|
2956
|
+
{ passive: true },
|
|
2957
|
+
);
|
|
2958
|
+
})();
|
|
2535
2959
|
$("q").addEventListener("input", () => {
|
|
2536
2960
|
try {
|
|
2537
2961
|
localStorage.setItem("ay.filter", $("q").value);
|
|
@@ -2549,6 +2973,26 @@
|
|
|
2549
2973
|
fit.fit();
|
|
2550
2974
|
} catch {}
|
|
2551
2975
|
});
|
|
2976
|
+
// iOS overlays the soft keyboard ON TOP of the layout viewport rather than
|
|
2977
|
+
// shrinking it, so a bottom-anchored composer would hide behind it. Track
|
|
2978
|
+
// the visual viewport and reserve the covered height as --kb (which .app
|
|
2979
|
+
// subtracts from its height), then refit the terminal. Android Chrome
|
|
2980
|
+
// resizes the layout viewport itself (interactive-widget=resizes-content),
|
|
2981
|
+
// so --kb stays ~0 there — this is harmless and idempotent on desktop too.
|
|
2982
|
+
if (window.visualViewport) {
|
|
2983
|
+
const vv = window.visualViewport;
|
|
2984
|
+
const onVV = () => {
|
|
2985
|
+
const kb = Math.max(0, Math.round(window.innerHeight - vv.height - vv.offsetTop));
|
|
2986
|
+
document.documentElement.style.setProperty("--kb", kb + "px");
|
|
2987
|
+
if (fit)
|
|
2988
|
+
try {
|
|
2989
|
+
fit.fit();
|
|
2990
|
+
} catch {}
|
|
2991
|
+
};
|
|
2992
|
+
vv.addEventListener("resize", onVV);
|
|
2993
|
+
vv.addEventListener("scroll", onVV);
|
|
2994
|
+
onVV();
|
|
2995
|
+
}
|
|
2552
2996
|
|
|
2553
2997
|
// Step the selection up/down the (filtered) list — same order the left panel
|
|
2554
2998
|
// renders. Clamps at the ends, scrolls the row into view.
|
|
@@ -3158,7 +3602,15 @@
|
|
|
3158
3602
|
// composite key so it picks the right host when pids collide across rooms.
|
|
3159
3603
|
const [, room, aid] = full;
|
|
3160
3604
|
autoPid = room + "#" + aid;
|
|
3161
|
-
|
|
3605
|
+
// A #room:agentId hash is BOTH our own persisted selection (select()
|
|
3606
|
+
// writes it so a refresh reopens) AND a shareable deep link — same
|
|
3607
|
+
// format, two intents. Disambiguate by navigation type: a reload is a
|
|
3608
|
+
// restore (on a phone, just re-highlight the row and stay on the list,
|
|
3609
|
+
// per mergeRender), while a fresh navigation is a deliberate "take me
|
|
3610
|
+
// to this agent" that opens even on mobile. (No nav entry → treat as
|
|
3611
|
+
// explicit, preserving the old always-open behaviour.)
|
|
3612
|
+
const nav = performance.getEntriesByType("navigation")[0];
|
|
3613
|
+
autoPidExplicit = nav ? nav.type !== "reload" : true;
|
|
3162
3614
|
const r = loadRooms()[room];
|
|
3163
3615
|
if (r) pending = { room, token: r.token, host: r.host };
|
|
3164
3616
|
} else if (bare && loadRooms()[bare[1]]) {
|
package/package.json
CHANGED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-DgukRoEI.js";
|
|
2
|
-
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-BqOr1YqC.js";
|
|
4
|
-
import "./pidStore-CGKIhaJO.js";
|
|
5
|
-
import "./globalPidIndex-C7r2m6s7.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-B4O2cFlt.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|