@co0ontty/wand 4.72.0 → 4.72.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/dist/build-info.json +3 -3
- package/dist/process-manager.d.ts +0 -2
- package/dist/process-manager.js +0 -10
- package/dist/pty-terminal-state.d.ts +7 -0
- package/dist/pty-terminal-state.js +139 -22
- package/dist/server.js +0 -2
- package/dist/structured-session-manager.d.ts +10 -0
- package/dist/structured-session-manager.js +164 -15
- package/dist/terminal-daemon-client.js +0 -36
- package/dist/terminal-daemon-server.d.ts +12 -0
- package/dist/terminal-daemon-server.js +53 -7
- package/dist/terminal-host.d.ts +0 -2
- package/dist/terminal-host.js +0 -6
- package/dist/web-ui/content/scripts.js +70 -70
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/embedded-assets.js +2 -2
- package/dist/web-ui/sidebar-layout.d.ts +0 -4
- package/dist/web-ui/sidebar-layout.js +2 -2
- package/dist/ws-broadcast.d.ts +14 -6
- package/dist/ws-broadcast.js +54 -40
- package/package.json +1 -1
|
@@ -1,2 +1,14 @@
|
|
|
1
|
+
/** Retention view of one structured run, in map insertion order (oldest first). */
|
|
2
|
+
export interface StructuredRunRetentionEntry {
|
|
3
|
+
runId: string;
|
|
4
|
+
status: "running" | "exited";
|
|
5
|
+
exitedAt: number | null;
|
|
6
|
+
logChars: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Oldest-first ids of exited runs that fall outside the count, retained-log, or
|
|
10
|
+
* age budget. Running runs are never evicted: their child is still live.
|
|
11
|
+
*/
|
|
12
|
+
export declare function structuredRunEvictionOrder(entries: readonly StructuredRunRetentionEntry[], now?: number): string[];
|
|
1
13
|
export declare function runTerminalDaemon(configPath: string): Promise<void>;
|
|
2
14
|
export declare function readTerminalDaemonPid(configPath: string): number | null;
|
|
@@ -14,6 +14,46 @@ import { PtyTerminalState } from "./pty-terminal-state.js";
|
|
|
14
14
|
import { PtyCliExitMarker } from "./pty-shell-launch.js";
|
|
15
15
|
import { appendWindow, PTY_OUTPUT_MAX_SIZE } from "./pty-text-utils.js";
|
|
16
16
|
const MAX_STRUCTURED_RUNS = 256;
|
|
17
|
+
/**
|
|
18
|
+
* Exited records exist so a web restart can adopt a finished turn. Each one
|
|
19
|
+
* carries a replay log capped at STRUCTURED_RUN_LOG_MAX_CHARS, so a count-only
|
|
20
|
+
* bound would still let the daemon retain 256 x 8M chars of logs; the exited
|
|
21
|
+
* set is bounded by aggregate log size as well, and old records expire.
|
|
22
|
+
*/
|
|
23
|
+
const MAX_EXITED_STRUCTURED_RUNS = 128;
|
|
24
|
+
const EXITED_STRUCTURED_RUN_LOG_MAX_CHARS = 32 * 1024 * 1024;
|
|
25
|
+
const EXITED_STRUCTURED_RUN_RETENTION_MS = 2 * 60 * 60 * 1000;
|
|
26
|
+
/**
|
|
27
|
+
* Oldest-first ids of exited runs that fall outside the count, retained-log, or
|
|
28
|
+
* age budget. Running runs are never evicted: their child is still live.
|
|
29
|
+
*/
|
|
30
|
+
export function structuredRunEvictionOrder(entries, now = Date.now()) {
|
|
31
|
+
let total = entries.length;
|
|
32
|
+
let exitedCount = 0;
|
|
33
|
+
let exitedLogChars = 0;
|
|
34
|
+
for (const entry of entries) {
|
|
35
|
+
if (entry.status !== "exited")
|
|
36
|
+
continue;
|
|
37
|
+
exitedCount++;
|
|
38
|
+
exitedLogChars += entry.logChars;
|
|
39
|
+
}
|
|
40
|
+
const evicted = [];
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
if (entry.status !== "exited")
|
|
43
|
+
continue;
|
|
44
|
+
const expired = entry.exitedAt !== null && now - entry.exitedAt >= EXITED_STRUCTURED_RUN_RETENTION_MS;
|
|
45
|
+
const overBudget = total > MAX_STRUCTURED_RUNS
|
|
46
|
+
|| exitedCount > MAX_EXITED_STRUCTURED_RUNS
|
|
47
|
+
|| exitedLogChars > EXITED_STRUCTURED_RUN_LOG_MAX_CHARS;
|
|
48
|
+
if (!expired && !overBudget)
|
|
49
|
+
continue;
|
|
50
|
+
evicted.push(entry.runId);
|
|
51
|
+
total--;
|
|
52
|
+
exitedCount--;
|
|
53
|
+
exitedLogChars -= entry.logChars;
|
|
54
|
+
}
|
|
55
|
+
return evicted;
|
|
56
|
+
}
|
|
17
57
|
const MAX_REQUEST_BUFFER = 4 * 1024 * 1024;
|
|
18
58
|
export async function runTerminalDaemon(configPath) {
|
|
19
59
|
const paths = terminalDaemonPaths(configPath);
|
|
@@ -178,16 +218,19 @@ export async function runTerminalDaemon(configPath) {
|
|
|
178
218
|
stdoutTruncated: run.stdoutTruncated,
|
|
179
219
|
stderrTruncated: run.stderrTruncated,
|
|
180
220
|
});
|
|
181
|
-
/** Evict oldest exited records
|
|
221
|
+
/** Evict oldest exited records until counts, retained logs, and age are back in budget. */
|
|
182
222
|
const evictStaleStructuredRuns = () => {
|
|
183
|
-
|
|
184
|
-
return;
|
|
223
|
+
const entries = [];
|
|
185
224
|
for (const [runId, run] of structuredRuns) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
225
|
+
entries.push({
|
|
226
|
+
runId,
|
|
227
|
+
status: run.status,
|
|
228
|
+
exitedAt: run.exitedAt,
|
|
229
|
+
logChars: run.stdoutLog.length + run.stderrLog.length,
|
|
230
|
+
});
|
|
190
231
|
}
|
|
232
|
+
for (const runId of structuredRunEvictionOrder(entries))
|
|
233
|
+
structuredRuns.delete(runId);
|
|
191
234
|
};
|
|
192
235
|
const structuredSpawn = (request) => {
|
|
193
236
|
const existing = structuredRuns.get(request.runId);
|
|
@@ -209,6 +252,7 @@ export async function runTerminalDaemon(configPath) {
|
|
|
209
252
|
status: "running",
|
|
210
253
|
exitCode: null,
|
|
211
254
|
signal: null,
|
|
255
|
+
exitedAt: null,
|
|
212
256
|
stdoutSeq: 0,
|
|
213
257
|
stderrSeq: 0,
|
|
214
258
|
stdoutLog: "",
|
|
@@ -252,6 +296,7 @@ export async function runTerminalDaemon(configPath) {
|
|
|
252
296
|
run.child = null;
|
|
253
297
|
run.status = "exited";
|
|
254
298
|
run.exitCode = code;
|
|
299
|
+
run.exitedAt = Date.now();
|
|
255
300
|
run.signal = signalName === null || signalName === undefined ? null : Number(signalName) || signalNumberFromName(signalName);
|
|
256
301
|
broadcast({
|
|
257
302
|
kind: "event",
|
|
@@ -261,6 +306,7 @@ export async function runTerminalDaemon(configPath) {
|
|
|
261
306
|
exitCode: run.exitCode ?? undefined,
|
|
262
307
|
signal: run.signal ?? undefined,
|
|
263
308
|
});
|
|
309
|
+
evictStaleStructuredRuns();
|
|
264
310
|
});
|
|
265
311
|
return serializeStructuredRun(run);
|
|
266
312
|
};
|
package/dist/terminal-host.d.ts
CHANGED
|
@@ -15,8 +15,6 @@ export interface TerminalProcess {
|
|
|
15
15
|
write(data: string): void;
|
|
16
16
|
resize(cols: number, rows: number): void;
|
|
17
17
|
kill(signal?: string): void;
|
|
18
|
-
pause(): void;
|
|
19
|
-
resume(): void;
|
|
20
18
|
onData(listener: (event: TerminalDataEvent) => void): {
|
|
21
19
|
dispose(): void;
|
|
22
20
|
};
|
package/dist/terminal-host.js
CHANGED
|
@@ -23,12 +23,6 @@ class InProcessTerminalProcess {
|
|
|
23
23
|
kill(signal) {
|
|
24
24
|
this.child.kill(signal);
|
|
25
25
|
}
|
|
26
|
-
pause() {
|
|
27
|
-
this.child.pause();
|
|
28
|
-
}
|
|
29
|
-
resume() {
|
|
30
|
-
this.child.resume();
|
|
31
|
-
}
|
|
32
26
|
onData(listener) {
|
|
33
27
|
return this.child.onData((data) => listener({ data, seq: ++this.seq }));
|
|
34
28
|
}
|