@songsid/agend 2.1.1-beta.8 → 2.1.1
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/README.md +1 -0
- package/README.zh-TW.md +1 -0
- package/dist/backend/antigravity.js +4 -9
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.js +4 -7
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.js +22 -8
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/gemini-cli.js +4 -7
- package/dist/backend/gemini-cli.js.map +1 -1
- package/dist/backend/grok.js +4 -7
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.js +4 -7
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/opencode.js +4 -7
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/types.d.ts +5 -0
- package/dist/backend/types.js +2 -2
- package/dist/backend/types.js.map +1 -1
- package/dist/config-validator.js +18 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +9 -0
- package/dist/daemon.js +29 -5
- package/dist/daemon.js.map +1 -1
- package/dist/tmux-control.js +7 -1
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-manager.d.ts +16 -1
- package/dist/tmux-manager.js +69 -3
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types.d.ts +13 -0
- package/dist/ui/view.html +161 -43
- package/dist/view-api.d.ts +7 -0
- package/dist/view-api.js +56 -12
- package/dist/view-api.js.map +1 -1
- package/package.json +1 -1
package/dist/tmux-manager.js
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
import { promisify } from "node:util";
|
|
3
3
|
const exec = promisify(execFile);
|
|
4
|
+
export const DEFAULT_TMUX_LOGICAL_SIZE = Object.freeze({
|
|
5
|
+
columns: 120,
|
|
6
|
+
rows: 36,
|
|
7
|
+
});
|
|
8
|
+
export const LEGACY_TMUX_LOGICAL_SIZE = Object.freeze({
|
|
9
|
+
columns: 80,
|
|
10
|
+
rows: 24,
|
|
11
|
+
});
|
|
12
|
+
/** Resolve an effective config into the geometry that must be pinned in tmux. */
|
|
13
|
+
export function resolveTmuxLogicalSize(config) {
|
|
14
|
+
if (config?.enabled === false)
|
|
15
|
+
return { ...LEGACY_TMUX_LOGICAL_SIZE };
|
|
16
|
+
return {
|
|
17
|
+
columns: config?.columns ?? DEFAULT_TMUX_LOGICAL_SIZE.columns,
|
|
18
|
+
rows: config?.rows ?? DEFAULT_TMUX_LOGICAL_SIZE.rows,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
4
21
|
export class TmuxManager {
|
|
5
22
|
sessionName;
|
|
23
|
+
logicalSize;
|
|
6
24
|
windowId;
|
|
7
25
|
// Socket isolation: null = use tmux default socket (backward compatible).
|
|
8
26
|
// Set to a name to use `-L <name>` for custom AGEND_HOME isolation.
|
|
@@ -16,8 +34,9 @@ export class TmuxManager {
|
|
|
16
34
|
return args;
|
|
17
35
|
return ["-L", TmuxManager.socketName, ...args];
|
|
18
36
|
}
|
|
19
|
-
constructor(sessionName, windowId) {
|
|
37
|
+
constructor(sessionName, windowId, logicalSize = { ...DEFAULT_TMUX_LOGICAL_SIZE }) {
|
|
20
38
|
this.sessionName = sessionName;
|
|
39
|
+
this.logicalSize = logicalSize;
|
|
21
40
|
this.windowId = windowId;
|
|
22
41
|
}
|
|
23
42
|
// === Static session-level methods ===
|
|
@@ -84,8 +103,19 @@ export class TmuxManager {
|
|
|
84
103
|
args.push("-P", "-F", "#{window_id}", command);
|
|
85
104
|
const { stdout } = await exec("tmux", TmuxManager.tmuxArgs(args));
|
|
86
105
|
this.windowId = stdout.trim();
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
try {
|
|
107
|
+
// `window-size=manual` is essential: the shared control-mode client has
|
|
108
|
+
// no PTY and otherwise makes `window-size=latest` collapse windows back
|
|
109
|
+
// to its synthetic 80-column geometry.
|
|
110
|
+
await this.applyLogicalSize();
|
|
111
|
+
if (windowName) {
|
|
112
|
+
await exec("tmux", TmuxManager.tmuxArgs(["set-window-option", "-t", `${this.sessionName}:${this.windowId}`, "allow-rename", "off"])).catch(() => { });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
// Do not leave a live instance in an unpinned geometry if setup fails.
|
|
117
|
+
await this.killWindow();
|
|
118
|
+
throw err;
|
|
89
119
|
}
|
|
90
120
|
return this.windowId;
|
|
91
121
|
}
|
|
@@ -93,11 +123,27 @@ export class TmuxManager {
|
|
|
93
123
|
async respawnWindow(command, cwd) {
|
|
94
124
|
if (!this.windowId)
|
|
95
125
|
throw new Error("Cannot respawn tmux window without a window id");
|
|
126
|
+
// Apply before respawn so the new CLI sees the intended COLUMNS/LINES from
|
|
127
|
+
// its first frame. Reapplying is idempotent and repairs external drift.
|
|
128
|
+
await this.applyLogicalSize();
|
|
96
129
|
await exec("tmux", TmuxManager.tmuxArgs([
|
|
97
130
|
"respawn-window", "-k", "-t", `${this.sessionName}:${this.windowId}`,
|
|
98
131
|
"-c", cwd, command,
|
|
99
132
|
]));
|
|
100
133
|
}
|
|
134
|
+
async applyLogicalSize() {
|
|
135
|
+
if (!this.windowId)
|
|
136
|
+
throw new Error("Cannot size tmux window without a window id");
|
|
137
|
+
const target = `${this.sessionName}:${this.windowId}`;
|
|
138
|
+
await exec("tmux", TmuxManager.tmuxArgs([
|
|
139
|
+
"set-window-option", "-t", target, "window-size", "manual",
|
|
140
|
+
]));
|
|
141
|
+
await exec("tmux", TmuxManager.tmuxArgs([
|
|
142
|
+
"resize-window", "-t", target,
|
|
143
|
+
"-x", String(this.logicalSize.columns),
|
|
144
|
+
"-y", String(this.logicalSize.rows),
|
|
145
|
+
]));
|
|
146
|
+
}
|
|
101
147
|
async killWindow() {
|
|
102
148
|
if (!this.windowId)
|
|
103
149
|
return;
|
|
@@ -159,6 +205,26 @@ export class TmuxManager {
|
|
|
159
205
|
return null;
|
|
160
206
|
}
|
|
161
207
|
}
|
|
208
|
+
/** Return tmux's effective window geometry and sizing policy (diagnostics/tests). */
|
|
209
|
+
async getWindowGeometry() {
|
|
210
|
+
if (!this.windowId)
|
|
211
|
+
throw new Error("Cannot inspect tmux window without a window id");
|
|
212
|
+
const target = `${this.sessionName}:${this.windowId}`;
|
|
213
|
+
const { stdout } = await exec("tmux", TmuxManager.tmuxArgs([
|
|
214
|
+
"display-message", "-p", "-t", target,
|
|
215
|
+
"#{window_width} #{window_height}",
|
|
216
|
+
]));
|
|
217
|
+
const { stdout: modeOutput } = await exec("tmux", TmuxManager.tmuxArgs([
|
|
218
|
+
"show-window-options", "-v", "-t", target, "window-size",
|
|
219
|
+
]));
|
|
220
|
+
const [columnsRaw, rowsRaw] = stdout.trim().split(/\s+/);
|
|
221
|
+
const columns = Number.parseInt(columnsRaw, 10);
|
|
222
|
+
const rows = Number.parseInt(rowsRaw, 10);
|
|
223
|
+
if (!Number.isFinite(columns) || !Number.isFinite(rows)) {
|
|
224
|
+
throw new Error(`Invalid tmux window geometry: ${stdout.trim()}`);
|
|
225
|
+
}
|
|
226
|
+
return { columns, rows, mode: modeOutput.trim() };
|
|
227
|
+
}
|
|
162
228
|
async sendKeys(text) {
|
|
163
229
|
try {
|
|
164
230
|
await exec("tmux", TmuxManager.tmuxArgs(["send-keys", "-l", "-t", `${this.sessionName}:${this.windowId}`, text]));
|
package/dist/tmux-manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tmux-manager.js","sourceRoot":"","sources":["../src/tmux-manager.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tmux-manager.js","sourceRoot":"","sources":["../src/tmux-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAOjC,MAAM,CAAC,MAAM,yBAAyB,GAA8B,MAAM,CAAC,MAAM,CAAC;IAChF,OAAO,EAAE,GAAG;IACZ,IAAI,EAAE,EAAE;CACT,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAA8B,MAAM,CAAC,MAAM,CAAC;IAC/E,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;CACT,CAAC,CAAC;AAEH,iFAAiF;AACjF,MAAM,UAAU,sBAAsB,CAAC,MAAuB;IAC5D,IAAI,MAAM,EAAE,OAAO,KAAK,KAAK;QAAE,OAAO,EAAE,GAAG,wBAAwB,EAAE,CAAC;IACtE,OAAO;QACL,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,yBAAyB,CAAC,OAAO;QAC7D,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,yBAAyB,CAAC,IAAI;KACrD,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,WAAW;IAkBZ;IAEA;IAnBF,QAAQ,CAAS;IAEzB,0EAA0E;IAC1E,oEAAoE;IAC5D,MAAM,CAAC,UAAU,GAAkB,IAAI,CAAC;IAEhD,MAAM,CAAC,aAAa,CAAC,IAAmB;QACtC,WAAW,CAAC,UAAU,GAAG,IAAI,CAAC;IAChC,CAAC;IAED,gEAAgE;IACxD,MAAM,CAAC,QAAQ,CAAC,IAAc;QACpC,IAAI,CAAC,WAAW,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QACzC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,YACU,WAAmB,EAC3B,QAAgB,EACR,cAA+B,EAAE,GAAG,yBAAyB,EAAE;QAF/D,gBAAW,GAAX,WAAW,CAAQ;QAEnB,gBAAW,GAAX,WAAW,CAAoD;QAEvE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,uCAAuC;IAEvC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAY;QACrC,IAAI,MAAM,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC;YAAE,OAAO;QAClD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC;gBAAE,OAAO;YACtD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAY;QACrC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YACtE,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAY;QACnC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACzE,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;QACtC,CAAC;IACH,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,WAAmB;QAC1C,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;gBACzD,cAAc,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,+BAA+B;aACzE,CAAC,CAAC,CAAC;YACJ,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBAC1D,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACrC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,EAAE,CAAC;QAAC,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,WAAmB,EAAE,QAAgB;QAC3D,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;gBACzD,YAAY,EAAE,IAAI,EAAE,GAAG,WAAW,IAAI,QAAQ,EAAE,EAAE,IAAI,EAAE,aAAa;aACtE,CAAC,CAAC,CAAC;YACJ,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YACxC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;IAC1B,CAAC;IAED,kCAAkC;IAElC,KAAK,CAAC,YAAY,CAAC,OAAe,EAAE,GAAW,EAAE,UAAmB;QAClE,MAAM,IAAI,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QACrE,IAAI,UAAU;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,wEAAwE;YACxE,wEAAwE;YACxE,uCAAuC;YACvC,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC9B,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,mBAAmB,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACvJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uEAAuE;YACvE,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACxB,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,aAAa,CAAC,OAAe,EAAE,GAAW;QAC9C,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACtF,2EAA2E;QAC3E,wEAAwE;QACxE,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC9B,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACtC,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE;YACpE,IAAI,EAAE,GAAG,EAAE,OAAO;SACnB,CAAC,CAAC,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC5B,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACnF,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtD,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACtC,mBAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ;SAC3D,CAAC,CAAC,CAAC;QACJ,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACtC,eAAe,EAAE,IAAI,EAAE,MAAM;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;YACtC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;SACpC,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1G,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;QACtC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAChE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC3B,CAAC;IAED,+EAA+E;IAC/E,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACtC,YAAY,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE;YAC1D,gBAAgB,EAAE,IAAI;SACvB,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;gBACzD,YAAY,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE;gBAC1D,IAAI,EAAE,kCAAkC;aACzC,CAAC,CAAC,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACpC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3E,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,qFAAqF;IACrF,KAAK,CAAC,iBAAiB;QACrB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACtF,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACzD,iBAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM;YACrC,kCAAkC;SACnC,CAAC,CAAC,CAAC;QACJ,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACrE,qBAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa;SACzD,CAAC,CAAC,CAAC;QACJ,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,iCAAiC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YAClH,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAA0E;QAC7F,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3G,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtD,MAAM,OAAO,GAAG,SAAS,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACvD,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YACpF,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YACpG,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC3C,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;YAC/E,6EAA6E;YAC7E,sEAAsE;YACtE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAC5C,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;YAC/E,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW,CAAC,IAAY;QAC5B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtD,MAAM,OAAO,GAAG,SAAS,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACvD,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YACpF,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;YACpG,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe;QAC9B,2EAA2E;QAC3E,0EAA0E;QAC1E,uEAAuE;QACvE,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,mDAAmD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACtC,WAAW,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE;YACzD,WAAW,OAAO,GAAG;SACtB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACzD,cAAc,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI;SACnE,CAAC,CAAC,CAAC;QACJ,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,wEAAwE;IACxE,KAAK,CAAC,sBAAsB,CAAC,QAAgB,EAAE;QAC7C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;YACzD,cAAc,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE;YAC5D,IAAI,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE;SACxB,CAAC,CAAC,CAAC;QACJ,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,WAAW,KAAa,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -47,6 +47,17 @@ export interface HangDetectorConfig {
|
|
|
47
47
|
enabled: boolean;
|
|
48
48
|
timeout_minutes: number;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Stable logical terminal geometry for an instance's tmux window.
|
|
52
|
+
*
|
|
53
|
+
* `enabled: false` is the compatibility escape hatch: the window is pinned to
|
|
54
|
+
* tmux's historical 80x24 geometry rather than inheriting the larger defaults.
|
|
55
|
+
*/
|
|
56
|
+
export interface TerminalConfig {
|
|
57
|
+
enabled?: boolean;
|
|
58
|
+
columns?: number;
|
|
59
|
+
rows?: number;
|
|
60
|
+
}
|
|
50
61
|
export interface DailySummaryConfig {
|
|
51
62
|
enabled: boolean;
|
|
52
63
|
hour: number;
|
|
@@ -130,6 +141,8 @@ export interface InstanceConfig {
|
|
|
130
141
|
agent_mode?: "mcp" | "cli";
|
|
131
142
|
/** Hang detector override for this instance. */
|
|
132
143
|
hang_detector?: HangDetectorConfig;
|
|
144
|
+
/** Logical terminal size. Defaults to 120x36; set enabled=false for 80x24 compatibility. */
|
|
145
|
+
terminal?: TerminalConfig;
|
|
133
146
|
/** Command to paste raw before each user message (e.g. "/chat load base.json") */
|
|
134
147
|
pre_task_command?: string;
|
|
135
148
|
}
|
package/dist/ui/view.html
CHANGED
|
@@ -31,21 +31,35 @@
|
|
|
31
31
|
|
|
32
32
|
/* Main */
|
|
33
33
|
#main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
|
|
34
|
-
|
|
34
|
+
/* Padding kept at 5/6px: enough that glyphs don't touch the edge, small
|
|
35
|
+
enough that the terminal keeps essentially the whole main area. */
|
|
36
|
+
#term { flex: 1; background: #000; overflow: auto; scrollbar-gutter: stable; padding: 5px 6px; }
|
|
35
37
|
#term pre { min-width: 100%; min-height: 100%; font-family: "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace; line-height: 1.2; white-space: pre; color: #d0d0d0; }
|
|
36
38
|
|
|
37
|
-
/* Card
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
.avatar-
|
|
42
|
-
|
|
43
|
-
#cardBody
|
|
44
|
-
#cardBody .
|
|
45
|
-
#cardBody .
|
|
46
|
-
#cardBody .
|
|
47
|
-
#cardBody .
|
|
48
|
-
#
|
|
39
|
+
/* Card — a single compact bar by default so the terminal keeps the height.
|
|
40
|
+
`.expanded` restores the tall layout with avatar + description. */
|
|
41
|
+
#card { background: var(--panel); border-top: 1px solid var(--border); padding: 5px 10px; display: flex; gap: 10px; align-items: center; }
|
|
42
|
+
#avatarBox { width: 24px; height: 24px; flex: 0 0 24px; }
|
|
43
|
+
.avatar-img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
|
|
44
|
+
.avatar-ph { width: 100%; height: 100%; border-radius: 50%; background: #30363d; color: var(--dim); display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; text-transform: uppercase; user-select: none; }
|
|
45
|
+
#cardBody { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 10px; overflow: hidden; }
|
|
46
|
+
#cardBody .row1 { display: flex; align-items: baseline; gap: 10px; flex: 0 0 auto; }
|
|
47
|
+
#cardBody .dname { font-size: 13px; font-weight: 600; white-space: nowrap; }
|
|
48
|
+
#cardBody .role { color: var(--accent); font-size: 12px; white-space: nowrap; }
|
|
49
|
+
#cardBody .meta { color: var(--dim); font-size: 11px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
50
|
+
#cardBody .desc { display: none; }
|
|
51
|
+
#cardToggle { background: none; border: none; color: var(--dim); cursor: pointer; font-size: 12px; padding: 2px 4px; flex: 0 0 auto; }
|
|
52
|
+
#cardToggle:hover { color: var(--fg); }
|
|
53
|
+
|
|
54
|
+
#card.expanded { align-items: flex-start; padding: 12px 14px; }
|
|
55
|
+
#card.expanded #avatarBox { width: 48px; height: 48px; flex: 0 0 48px; }
|
|
56
|
+
#card.expanded .avatar-ph { font-size: 20px; }
|
|
57
|
+
#card.expanded #cardBody { display: block; }
|
|
58
|
+
#card.expanded #cardBody .dname { font-size: 16px; }
|
|
59
|
+
#card.expanded #cardBody .role { font-size: 13px; }
|
|
60
|
+
#card.expanded #cardBody .meta { font-size: 12px; margin-top: 3px; white-space: normal; overflow: visible; }
|
|
61
|
+
#card.expanded #cardBody .desc { display: block; font-size: 13px; margin-top: 6px; color: #adbac7; white-space: pre-wrap; }
|
|
62
|
+
#editBtn { background: #21262d; color: var(--fg); border: 1px solid var(--border); border-radius: 6px; padding: 3px 10px; cursor: pointer; font-size: 12px; flex: 0 0 auto; }
|
|
49
63
|
#editBtn:hover { border-color: var(--accent); }
|
|
50
64
|
|
|
51
65
|
/* Edit form */
|
|
@@ -68,14 +82,18 @@
|
|
|
68
82
|
.help-panel ul { margin: 8px 0 0 18px; }
|
|
69
83
|
.help-panel li { font-size: 13px; margin: 6px 0; color: var(--fg); }
|
|
70
84
|
.help-panel .close { position: absolute; top: 14px; right: 16px; cursor: pointer; color: var(--dim); font-size: 22px; line-height: 1; background: none; border: none; }
|
|
85
|
+
|
|
86
|
+
#densityBtn { font-size: 14px; font-weight: 600; letter-spacing: -.5px; }
|
|
71
87
|
@media (max-width: 700px) {
|
|
72
88
|
#sidebar { width: 180px; flex-basis: 180px; }
|
|
73
|
-
|
|
89
|
+
/* The compact bar must stay one line; only the expanded form wraps. */
|
|
90
|
+
#card.expanded { flex-wrap: wrap; padding: 10px 12px; }
|
|
74
91
|
#edit { flex-basis: 100%; }
|
|
75
92
|
}
|
|
76
93
|
</style>
|
|
77
94
|
</head>
|
|
78
95
|
<body>
|
|
96
|
+
<button class="help-btn" id="densityBtn" title="Font density" style="right:98px">⤢</button>
|
|
79
97
|
<button class="help-btn" id="langBtn" title="Language" style="right:56px">🌐</button>
|
|
80
98
|
<button class="help-btn" id="helpBtn" title="Help">ℹ️</button>
|
|
81
99
|
<div class="help-backdrop" id="helpBackdrop"></div>
|
|
@@ -93,6 +111,7 @@
|
|
|
93
111
|
<div class="meta" id="meta"></div>
|
|
94
112
|
<div class="desc" id="desc"></div>
|
|
95
113
|
</div>
|
|
114
|
+
<button id="cardToggle" title="Expand profile" aria-expanded="false">▲</button>
|
|
96
115
|
<button id="editBtn" data-i18n="editProfile">✏️ Edit</button>
|
|
97
116
|
<div id="edit">
|
|
98
117
|
<input id="fDisplay" data-i18n-ph="displayName" placeholder="Display name">
|
|
@@ -126,13 +145,17 @@
|
|
|
126
145
|
saveHint: "Viewing is open (read-only). Saving requires the web.token (~/.agend/web.token).", helpTitle: "📖 Help",
|
|
127
146
|
help1: "Pick an instance on the left → its live terminal shows on the right",
|
|
128
147
|
help2: "Click a group header ▼/▶ to collapse/expand", help3: "✏️ Edit changes display name, role, description",
|
|
129
|
-
help4: "Drag to reorder (needs web.token permission)"
|
|
148
|
+
help4: "Drag to reorder (needs web.token permission)",
|
|
149
|
+
help5: "Click ⤢ to cycle font density: Fit → Comfortable → Compact",
|
|
150
|
+
densityFit: "Fit", densityComfortable: "Comfortable", densityCompact: "Compact", densityLabel: "Font density" },
|
|
130
151
|
"zh-TW": { viewTitle: "AgEnD · 檢視", editProfile: "✏️ 編輯", save: "儲存", cancel: "取消",
|
|
131
152
|
displayName: "顯示名稱", role: "角色", description: "描述", tokenPh: "web.token(儲存時需要)",
|
|
132
153
|
saveHint: "檢視為公開(唯讀)。儲存需要 web.token(~/.agend/web.token)。", helpTitle: "📖 使用說明",
|
|
133
154
|
help1: "左側選 instance → 右側顯示即時 terminal 畫面",
|
|
134
155
|
help2: "點 group header ▼/▶ 收合/展開", help3: "✏️ Edit 可修改顯示名稱、角色、描述",
|
|
135
|
-
help4: "拖曳可調整順序(需 web.token 權限)"
|
|
156
|
+
help4: "拖曳可調整順序(需 web.token 權限)",
|
|
157
|
+
help5: "點 ⤢ 循環切換字級密度:剛好填滿 → 舒適 → 精簡",
|
|
158
|
+
densityFit: "剛好填滿", densityComfortable: "舒適", densityCompact: "精簡", densityLabel: "字級密度" },
|
|
136
159
|
};
|
|
137
160
|
let lang = localStorage.getItem("agend_lang") || (navigator.language && navigator.language.toLowerCase().startsWith("zh") ? "zh-TW" : "en");
|
|
138
161
|
if (!I18N[lang]) lang = "en";
|
|
@@ -142,16 +165,28 @@
|
|
|
142
165
|
document.querySelectorAll("[data-i18n-ph]").forEach(e => { e.setAttribute("placeholder", T(e.getAttribute("data-i18n-ph"))); });
|
|
143
166
|
const hc = q("helpContent");
|
|
144
167
|
if (hc) { hc.innerHTML = ""; const h3 = document.createElement("h3"); h3.textContent = T("helpTitle"); hc.append(h3);
|
|
145
|
-
const ul = document.createElement("ul"); for (const k of ["help1","help2","help3","help4"]) { const li = document.createElement("li"); li.textContent = T(k); ul.append(li); } hc.append(ul); }
|
|
168
|
+
const ul = document.createElement("ul"); for (const k of ["help1","help2","help3","help4","help5"]) { const li = document.createElement("li"); li.textContent = T(k); ul.append(li); } hc.append(ul); }
|
|
169
|
+
renderDensityBtn();
|
|
146
170
|
}
|
|
147
171
|
|
|
148
172
|
let roster = [];
|
|
149
173
|
let rosterByName = new Map();
|
|
150
174
|
let current = null;
|
|
151
175
|
let poll = null;
|
|
152
|
-
|
|
153
|
-
|
|
176
|
+
// Pane grid in cells, reported by /api/pane's X-Pane-Cols / X-Pane-Rows.
|
|
177
|
+
// This — not the captured text — is the font-size input.
|
|
178
|
+
let paneCols = 0, paneRows = 0;
|
|
179
|
+
let lastFitKey = ""; // skip redundant recalcs
|
|
180
|
+
let appliedSize = 0; // last font-size actually written to #pre
|
|
154
181
|
let resizeTimer = null;
|
|
182
|
+
// Font density — the manual escape hatch. Once the tmux grid is large
|
|
183
|
+
// (120x32), the auto-fit size is necessarily small, so the user needs a way
|
|
184
|
+
// to trade "everything visible" against "readable glyphs".
|
|
185
|
+
const DENSITY = { fit: 1, comfortable: 1.25, compact: 0.8 };
|
|
186
|
+
const DENSITY_GLYPH = { fit: "⤢", comfortable: "A+", compact: "A−" };
|
|
187
|
+
const DENSITY_ORDER = ["fit", "comfortable", "compact"];
|
|
188
|
+
let density = localStorage.getItem("agend_view_density");
|
|
189
|
+
if (!DENSITY[density]) density = "fit";
|
|
155
190
|
const collapsed = new Set(); // group names the user has collapsed
|
|
156
191
|
// Drag-sort state
|
|
157
192
|
let sortGroups = new Map(); // groupName -> sort_index (persisted override)
|
|
@@ -463,38 +498,114 @@
|
|
|
463
498
|
}
|
|
464
499
|
const text = await r.text();
|
|
465
500
|
if (target !== current) return;
|
|
466
|
-
|
|
501
|
+
// Pane grid comes from tmux, so a sparse frame can't distort the fit.
|
|
502
|
+
const c = Number(r.headers.get("X-Pane-Cols")), rw = Number(r.headers.get("X-Pane-Rows"));
|
|
503
|
+
if (c >= 1 && rw >= 1 && (c !== paneCols || rw !== paneRows)) { paneCols = c; paneRows = rw; lastFitKey = ""; }
|
|
467
504
|
q("pre").innerHTML = ansiToHtml(text);
|
|
468
|
-
|
|
505
|
+
fitFont();
|
|
469
506
|
} catch { /* transient network error — keep last frame */ }
|
|
470
507
|
}
|
|
471
508
|
|
|
472
|
-
//
|
|
473
|
-
//
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
509
|
+
// ── Font sizing ───────────────────────────────────────
|
|
510
|
+
// Measured advance width of one monospace cell as a fraction of font-size.
|
|
511
|
+
// The old hardcoded .6em was only an estimate and drifts per resolved font.
|
|
512
|
+
// The ratio is font-size independent, so measuring once is enough.
|
|
513
|
+
let cellRatio = 0;
|
|
514
|
+
function glyphRatio() {
|
|
515
|
+
if (cellRatio) return cellRatio;
|
|
516
|
+
const probe = document.createElement("span");
|
|
517
|
+
probe.style.cssText = "position:absolute;visibility:hidden;white-space:pre;left:-9999px;top:0;font-size:100px";
|
|
518
|
+
probe.style.fontFamily = getComputedStyle(q("pre")).fontFamily;
|
|
519
|
+
probe.textContent = "0".repeat(100);
|
|
520
|
+
document.body.appendChild(probe);
|
|
521
|
+
const w = probe.getBoundingClientRect().width;
|
|
522
|
+
probe.remove();
|
|
523
|
+
if (w > 0) cellRatio = w / 100 / 100; // ÷100 chars, ÷100px font-size
|
|
524
|
+
return cellRatio || 0.6; // headless / odd env → old estimate
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// The removed 48px ceiling was what made an 80x24 pane render at ~33px on a
|
|
528
|
+
// 1080p screen — the "font is huge" complaint. A single desktop range is
|
|
529
|
+
// enough; /view is not targeting phones.
|
|
530
|
+
const MIN_PX = 12, MAX_PX = 22;
|
|
531
|
+
|
|
532
|
+
// Order: fit → clamp → user density → absolute readability bounds. When the
|
|
533
|
+
// clamped size can't show all `cols`, #term scrolls rather than shrinking
|
|
534
|
+
// below the floor.
|
|
535
|
+
function fitFont() {
|
|
536
|
+
if (paneCols < 1 || paneRows < 1) return; // no trustworthy size yet
|
|
537
|
+
const term = q("term"), pre = q("pre");
|
|
538
|
+
const cs = getComputedStyle(term);
|
|
539
|
+
const padX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
|
|
540
|
+
const padY = parseFloat(cs.paddingTop) + parseFloat(cs.paddingBottom);
|
|
541
|
+
const innerW = Math.max(1, term.clientWidth - (padX || 0));
|
|
542
|
+
const innerH = Math.max(1, term.clientHeight - (padY || 0));
|
|
543
|
+
const key = `${paneCols}x${paneRows}@${Math.round(innerW)}x${Math.round(innerH)}/${density}`;
|
|
544
|
+
if (key === lastFitKey) return;
|
|
545
|
+
const pcs = getComputedStyle(pre);
|
|
546
|
+
const lhRatio = parseFloat(pcs.lineHeight) / parseFloat(pcs.fontSize);
|
|
547
|
+
const lineH = Number.isFinite(lhRatio) && lhRatio > 0 ? lhRatio : 1.2;
|
|
548
|
+
const widthFit = innerW / (paneCols * glyphRatio());
|
|
549
|
+
const heightFit = innerH / (paneRows * lineH);
|
|
550
|
+
// 0.5% slack keeps an exact fit from rounding into a scrollbar (paired with
|
|
551
|
+
// scrollbar-gutter:stable, that's what stops resize→scrollbar→resize loops).
|
|
552
|
+
let size = Math.min(widthFit, heightFit) * 0.995;
|
|
553
|
+
size = Math.max(MIN_PX, Math.min(size, MAX_PX));
|
|
554
|
+
size *= DENSITY[density] || 1;
|
|
555
|
+
size = Math.max(8, Math.min(size, 32));
|
|
556
|
+
lastFitKey = key;
|
|
557
|
+
// Sub-pixel churn (a scrollbar appearing shrinks the box, which would shrink
|
|
558
|
+
// the font, which would hide the scrollbar again) resolves to a no-op here.
|
|
559
|
+
if (Math.abs(size - appliedSize) < 0.75) return;
|
|
560
|
+
appliedSize = size;
|
|
561
|
+
pre.style.fontSize = size.toFixed(2) + "px";
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
function scheduleFit() {
|
|
565
|
+
clearTimeout(resizeTimer);
|
|
566
|
+
resizeTimer = setTimeout(() => { lastFitKey = ""; fitFont(); }, 80);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function renderDensityBtn() {
|
|
570
|
+
const b = q("densityBtn");
|
|
571
|
+
if (!b) return;
|
|
572
|
+
b.textContent = DENSITY_GLYPH[density];
|
|
573
|
+
b.title = `${T("densityLabel")}: ${T("density" + density.charAt(0).toUpperCase() + density.slice(1))}`;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function cycleDensity() {
|
|
577
|
+
density = DENSITY_ORDER[(DENSITY_ORDER.indexOf(density) + 1) % DENSITY_ORDER.length];
|
|
578
|
+
localStorage.setItem("agend_view_density", density);
|
|
579
|
+
renderDensityBtn();
|
|
580
|
+
lastFitKey = "";
|
|
581
|
+
fitFont();
|
|
487
582
|
}
|
|
488
583
|
|
|
489
584
|
function select(name) {
|
|
490
585
|
if (name === current) return;
|
|
491
|
-
current = name;
|
|
586
|
+
current = name;
|
|
587
|
+
lastFitKey = ""; // force a refit once the new pane's size lands
|
|
492
588
|
exitEdit();
|
|
493
589
|
q("pre").textContent = ""; // blank the old instance's output immediately
|
|
494
590
|
renderList(); renderCard(); refreshPane();
|
|
495
591
|
}
|
|
496
592
|
|
|
497
593
|
// ── Edit ──────────────────────────────────────────────
|
|
594
|
+
// The card is a one-line bar by default; expanding it (or editing) is what
|
|
595
|
+
// borrows height back from the terminal.
|
|
596
|
+
let cardExpanded = localStorage.getItem("agend_view_card_expanded") === "1";
|
|
597
|
+
function applyCardExpanded(on) {
|
|
598
|
+
q("card").classList.toggle("expanded", on);
|
|
599
|
+
const t = q("cardToggle");
|
|
600
|
+
t.textContent = on ? "▼" : "▲";
|
|
601
|
+
t.setAttribute("aria-expanded", on ? "true" : "false");
|
|
602
|
+
scheduleFit(); // the terminal just gained or lost height
|
|
603
|
+
}
|
|
604
|
+
function setCardExpanded(on, persist) {
|
|
605
|
+
if (persist) { cardExpanded = on; localStorage.setItem("agend_view_card_expanded", on ? "1" : "0"); }
|
|
606
|
+
applyCardExpanded(on);
|
|
607
|
+
}
|
|
608
|
+
|
|
498
609
|
function enterEdit() {
|
|
499
610
|
const it = roster.find(r => r.instance_name === current);
|
|
500
611
|
if (!it) return;
|
|
@@ -503,14 +614,18 @@
|
|
|
503
614
|
q("fDesc").value = it.description || "";
|
|
504
615
|
q("fToken").value = localStorage.getItem("agend_web_token") || "";
|
|
505
616
|
q("msg").textContent = "";
|
|
617
|
+
applyCardExpanded(true); // form needs the room; don't persist it
|
|
506
618
|
q("cardBody").style.display = "none";
|
|
619
|
+
q("cardToggle").style.display = "none";
|
|
507
620
|
q("editBtn").style.display = "none";
|
|
508
621
|
q("edit").style.display = "flex";
|
|
509
622
|
}
|
|
510
623
|
function exitEdit() {
|
|
511
624
|
q("edit").style.display = "none";
|
|
512
625
|
q("cardBody").style.display = "";
|
|
626
|
+
q("cardToggle").style.display = "";
|
|
513
627
|
q("editBtn").style.display = "";
|
|
628
|
+
applyCardExpanded(cardExpanded); // back to the user's own preference
|
|
514
629
|
}
|
|
515
630
|
|
|
516
631
|
async function save() {
|
|
@@ -542,19 +657,22 @@
|
|
|
542
657
|
q("editBtn").onclick = enterEdit;
|
|
543
658
|
q("cancelBtn").onclick = exitEdit;
|
|
544
659
|
q("saveBtn").onclick = save;
|
|
660
|
+
q("cardToggle").onclick = () => setCardExpanded(!q("card").classList.contains("expanded"), true);
|
|
545
661
|
|
|
546
662
|
const setHelp = (open) => { q("helpPanel").classList.toggle("open", open); q("helpBackdrop").classList.toggle("open", open); };
|
|
547
663
|
q("helpBtn").onclick = () => setHelp(!q("helpPanel").classList.contains("open"));
|
|
548
664
|
q("helpClose").onclick = () => setHelp(false);
|
|
549
665
|
q("helpBackdrop").onclick = () => setHelp(false);
|
|
550
666
|
q("langBtn").onclick = () => { lang = lang === "en" ? "zh-TW" : "en"; localStorage.setItem("agend_lang", lang); applyI18n(); };
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
667
|
+
q("densityBtn").onclick = cycleDensity;
|
|
668
|
+
window.addEventListener("keydown", (e) => { if (e.key === "Escape") setHelp(false); });
|
|
669
|
+
|
|
670
|
+
window.addEventListener("resize", scheduleFit);
|
|
671
|
+
// Catches container changes the window resize event doesn't see — chiefly the
|
|
672
|
+
// profile card expanding or collapsing.
|
|
673
|
+
if (window.ResizeObserver) new ResizeObserver(scheduleFit).observe(q("term"));
|
|
557
674
|
applyI18n();
|
|
675
|
+
applyCardExpanded(cardExpanded);
|
|
558
676
|
|
|
559
677
|
// ── Boot ──────────────────────────────────────────────
|
|
560
678
|
loadRoster().then(() => { refreshPane(); });
|
package/dist/view-api.d.ts
CHANGED
|
@@ -19,6 +19,13 @@ export interface ViewApiContext {
|
|
|
19
19
|
getInstanceStatus(name: string): "running" | "paused" | "stopped" | "crashed";
|
|
20
20
|
getUiStatus(): unknown;
|
|
21
21
|
}
|
|
22
|
+
/** A pane's logical grid size in cells, as tmux sees it. */
|
|
23
|
+
export interface PaneSize {
|
|
24
|
+
cols: number;
|
|
25
|
+
rows: number;
|
|
26
|
+
}
|
|
27
|
+
/** Parse `display-message`'s `<cols>x<rows>` output. Returns null if unusable. */
|
|
28
|
+
export declare function parsePaneSize(out: string): PaneSize | null;
|
|
22
29
|
/** True if the path belongs to the view feature (so the caller can skip the
|
|
23
30
|
* global web-token gate and let this module do its own token checks). */
|
|
24
31
|
export declare function isViewPath(path: string): boolean;
|
package/dist/view-api.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* instance profiles. Separate from the operator Web UI (`/ui`):
|
|
4
4
|
*
|
|
5
5
|
* GET /view → static page (no token)
|
|
6
|
-
* GET /api/pane/:instance → `tmux capture-pane -ep` output (ANSI text)
|
|
6
|
+
* GET /api/pane/:instance → `tmux capture-pane -ep` output (ANSI text),
|
|
7
|
+
* plus X-Pane-Cols / X-Pane-Rows response headers
|
|
7
8
|
* GET /api/profiles → merged roster (live status + config + profile)
|
|
8
9
|
* GET /api/profile/:instance → one profile row
|
|
9
10
|
* POST /api/profile/:instance → upsert profile (web.token only)
|
|
@@ -107,21 +108,53 @@ function readBody(req, maxBytes) {
|
|
|
107
108
|
req.on("error", reject);
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
|
-
/**
|
|
111
|
-
|
|
111
|
+
/** tmux target for an instance's window, or null if it has no window yet. */
|
|
112
|
+
function paneTarget(ctx, name) {
|
|
112
113
|
const widFile = join(ctx.dataDir, "instances", name, "window-id");
|
|
113
114
|
if (!existsSync(widFile))
|
|
114
|
-
return
|
|
115
|
+
return null;
|
|
115
116
|
const wid = readFileSync(widFile, "utf-8").trim();
|
|
116
117
|
if (!wid)
|
|
117
|
-
return
|
|
118
|
+
return null;
|
|
119
|
+
return `${getTmuxSession()}:${wid}`;
|
|
120
|
+
}
|
|
121
|
+
function tmuxArgs(rest) {
|
|
118
122
|
const socket = getTmuxSocketName();
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
return socket ? ["-L", socket, ...rest] : rest;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Capture a pane's contents (with ANSI escapes) **and** its logical grid size.
|
|
127
|
+
*
|
|
128
|
+
* The size matters as much as the text: the web view sizes its font from
|
|
129
|
+
* `cols`/`rows` rather than from the captured text's longest line, because a
|
|
130
|
+
* sparse frame (a freshly-started CLI printing three short lines) would
|
|
131
|
+
* otherwise fit to ~3 columns and blow the font up to the 48px ceiling.
|
|
132
|
+
*/
|
|
133
|
+
async function capturePane(ctx, name) {
|
|
134
|
+
const target = paneTarget(ctx, name);
|
|
135
|
+
if (!target)
|
|
136
|
+
return { text: "", size: null };
|
|
137
|
+
const [text, size] = await Promise.all([
|
|
138
|
+
execFileP("tmux", tmuxArgs(["capture-pane", "-p", "-e", "-t", target]), { maxBuffer: 8 * 1024 * 1024 })
|
|
139
|
+
.then(r => r.stdout),
|
|
140
|
+
// display-message resolves the window's *active* pane, matching capture-pane.
|
|
141
|
+
execFileP("tmux", tmuxArgs(["display-message", "-p", "-t", target, "#{pane_width}x#{pane_height}"]))
|
|
142
|
+
.then(r => parsePaneSize(r.stdout))
|
|
143
|
+
// A missing size must not fail the whole capture — the client falls back
|
|
144
|
+
// to its last known size (or skips refitting) when the headers are absent.
|
|
145
|
+
.catch(() => null),
|
|
146
|
+
]);
|
|
147
|
+
return { text, size };
|
|
148
|
+
}
|
|
149
|
+
/** Parse `display-message`'s `<cols>x<rows>` output. Returns null if unusable. */
|
|
150
|
+
export function parsePaneSize(out) {
|
|
151
|
+
const m = /^(\d+)x(\d+)$/.exec(out.trim());
|
|
152
|
+
if (!m)
|
|
153
|
+
return null;
|
|
154
|
+
const cols = Number(m[1]), rows = Number(m[2]);
|
|
155
|
+
if (!Number.isFinite(cols) || !Number.isFinite(rows) || cols < 1 || rows < 1)
|
|
156
|
+
return null;
|
|
157
|
+
return { cols, rows };
|
|
125
158
|
}
|
|
126
159
|
/** True if the path belongs to the view feature (so the caller can skip the
|
|
127
160
|
* global web-token gate and let this module do its own token checks). */
|
|
@@ -158,6 +191,9 @@ export function handleViewRequest(req, res, url, ctx) {
|
|
|
158
191
|
return true;
|
|
159
192
|
}
|
|
160
193
|
// ── GET /api/pane/:instance ──
|
|
194
|
+
// Body is the raw ANSI capture; the pane's cell grid rides along in
|
|
195
|
+
// X-Pane-Cols / X-Pane-Rows so the client can size its font from the pane's
|
|
196
|
+
// real dimensions instead of guessing from the captured text.
|
|
161
197
|
if (method === "GET" && path.startsWith("/api/pane/")) {
|
|
162
198
|
const name = decodeURIComponent(path.slice("/api/pane/".length));
|
|
163
199
|
if (!knownInstance(ctx, name)) {
|
|
@@ -165,7 +201,15 @@ export function handleViewRequest(req, res, url, ctx) {
|
|
|
165
201
|
return true;
|
|
166
202
|
}
|
|
167
203
|
capturePane(ctx, name)
|
|
168
|
-
.then(
|
|
204
|
+
.then(({ text, size }) => {
|
|
205
|
+
const headers = { "Content-Type": "text/plain; charset=utf-8" };
|
|
206
|
+
if (size) {
|
|
207
|
+
headers["X-Pane-Cols"] = String(size.cols);
|
|
208
|
+
headers["X-Pane-Rows"] = String(size.rows);
|
|
209
|
+
}
|
|
210
|
+
res.writeHead(200, headers);
|
|
211
|
+
res.end(text);
|
|
212
|
+
})
|
|
169
213
|
.catch(err => { ctx.logger.debug({ err, name }, "capture-pane failed"); res.writeHead(200, { "Content-Type": "text/plain" }); res.end(""); });
|
|
170
214
|
return true;
|
|
171
215
|
}
|