aicodeman 1.12.0 → 1.12.2
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/proc-tree.d.ts +50 -0
- package/dist/proc-tree.d.ts.map +1 -0
- package/dist/proc-tree.js +68 -0
- package/dist/proc-tree.js.map +1 -0
- package/dist/session.d.ts +18 -3
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +25 -5
- package/dist/session.js.map +1 -1
- package/dist/tmux-manager.d.ts +37 -1
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +113 -32
- package/dist/tmux-manager.js.map +1 -1
- package/dist/utils/claude-cli-resolver.d.ts +40 -1
- package/dist/utils/claude-cli-resolver.d.ts.map +1 -1
- package/dist/utils/claude-cli-resolver.js +74 -27
- package/dist/utils/claude-cli-resolver.js.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/{app.8998c1b3.js → app.2e9ffd31.js} +4 -4
- package/dist/web/public/app.2e9ffd31.js.br +0 -0
- package/dist/web/public/app.2e9ffd31.js.gz +0 -0
- package/dist/web/public/constants.e7175b95.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/i18n.0fbea500.js.gz +0 -0
- package/dist/web/public/image-input.ee16ad88.js.gz +0 -0
- package/dist/web/public/index.html +5 -5
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.63794d0b.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.9936227d.js.gz +0 -0
- package/dist/web/public/{mobile-handlers.bc2b8c1d.js → mobile-handlers.32fdd57f.js} +62 -37
- package/dist/web/public/mobile-handlers.32fdd57f.js.br +0 -0
- package/dist/web/public/mobile-handlers.32fdd57f.js.gz +0 -0
- package/dist/web/public/mobile-overview.js.gz +0 -0
- package/dist/web/public/mobile.32cacde5.css.gz +0 -0
- package/dist/web/public/notification-manager.5d229063.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/panels-ui.1d4203e0.js.gz +0 -0
- package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
- package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
- package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
- package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
- package/dist/web/public/session-ui.1356a4f4.js.gz +0 -0
- package/dist/web/public/settings-ui.01a1ae7d.js.gz +0 -0
- package/dist/web/public/styles.50cd52bd.css.gz +0 -0
- package/dist/web/public/subagent-windows.4cc8b005.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/terminal-ui.78c71f3a.js +4 -0
- package/dist/web/public/terminal-ui.78c71f3a.js.br +0 -0
- package/dist/web/public/terminal-ui.78c71f3a.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +20 -0
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +26 -9
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/ws-routes.d.ts.map +1 -1
- package/dist/web/routes/ws-routes.js +9 -2
- package/dist/web/routes/ws-routes.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +18 -0
- package/dist/web/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/web/public/app.8998c1b3.js.br +0 -0
- package/dist/web/public/app.8998c1b3.js.gz +0 -0
- package/dist/web/public/mobile-handlers.bc2b8c1d.js.br +0 -0
- package/dist/web/public/mobile-handlers.bc2b8c1d.js.gz +0 -0
- package/dist/web/public/terminal-ui.a7da43e6.js +0 -3
- package/dist/web/public/terminal-ui.a7da43e6.js.br +0 -0
- package/dist/web/public/terminal-ui.a7da43e6.js.gz +0 -0
package/dist/tmux-manager.d.ts
CHANGED
|
@@ -348,7 +348,43 @@ export declare class TmuxManager extends EventEmitter implements TerminalMultipl
|
|
|
348
348
|
*/
|
|
349
349
|
respawnPane(options: RespawnPaneOptions): Promise<number | null>;
|
|
350
350
|
private sessionExists;
|
|
351
|
-
|
|
351
|
+
/** One `ps` snapshot of the whole process table, cached briefly. */
|
|
352
|
+
private static procSnapshot;
|
|
353
|
+
/** Single-flight guard so a hung `ps` cannot pile up parallel refreshes. */
|
|
354
|
+
private static procRefresh;
|
|
355
|
+
/**
|
|
356
|
+
* Fork ONE `ps` asynchronously and cache the parent -> children map.
|
|
357
|
+
*
|
|
358
|
+
* Async on purpose: a synchronous fork here would block the event loop on every
|
|
359
|
+
* stats tick, and under the procfs pathology this module exists to survive,
|
|
360
|
+
* `execSync`'s timeout cannot return at all (spawnSync waits for the unkillable
|
|
361
|
+
* child) — freezing the whole server where a hung async poll only costs staleness.
|
|
362
|
+
*/
|
|
363
|
+
private static refreshProcSnapshot;
|
|
364
|
+
/**
|
|
365
|
+
* Best snapshot WITHOUT forking: returns the cache, kicking off a background
|
|
366
|
+
* refresh when it has gone stale, and never blocks. Stats and window-title
|
|
367
|
+
* consumers tolerate data one interval old; nothing that KILLS may use this.
|
|
368
|
+
*/
|
|
369
|
+
private childrenByParent;
|
|
370
|
+
/**
|
|
371
|
+
* Descendants from a snapshot that is not the cached one — the kill path's variant.
|
|
372
|
+
*
|
|
373
|
+
* killSession re-scans for survivors between SIGTERM and SIGKILL, and the wait in
|
|
374
|
+
* between (200ms) sits far inside the cache TTL (2000ms): reading the cache there
|
|
375
|
+
* returns the pre-SIGTERM state verbatim, so children spawned since are invisible
|
|
376
|
+
* and SIGKILL aims at stale PIDs, guarded only by kill(pid, 0) — which cannot
|
|
377
|
+
* detect PID reuse.
|
|
378
|
+
*
|
|
379
|
+
* It forces a refresh rather than guaranteeing recency: an already-running refresh
|
|
380
|
+
* is reused, so the snapshot can predate this call by up to one `ps` runtime. A
|
|
381
|
+
* strict postdate guarantee would mean chaining a second `ps` behind every
|
|
382
|
+
* in-flight one, which is the fork storm this code exists to avoid.
|
|
383
|
+
*
|
|
384
|
+
* Bounded by design: waiting forever would freeze killSession before it reaches
|
|
385
|
+
* its process-group and tmux fallbacks.
|
|
386
|
+
*/
|
|
387
|
+
private getChildPidsFresh;
|
|
352
388
|
private isProcessAlive;
|
|
353
389
|
private verifyProcessesDead;
|
|
354
390
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tmux-manager.d.ts","sourceRoot":"","sources":["../src/tmux-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tmux-manager.d.ts","sourceRoot":"","sources":["../src/tmux-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/tmux-manager.js
CHANGED
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
* @module tmux-manager
|
|
22
22
|
*/
|
|
23
23
|
import { EventEmitter } from 'node:events';
|
|
24
|
-
import {
|
|
24
|
+
import { collectDescendants } from './proc-tree.js';
|
|
25
|
+
import { execSync, exec, execFile } from 'node:child_process';
|
|
25
26
|
import { promisify } from 'node:util';
|
|
26
27
|
const execAsync = promisify(exec);
|
|
27
28
|
import { existsSync, readFileSync, mkdirSync } from 'node:fs';
|
|
@@ -39,6 +40,14 @@ import { decideReconnect, advanceBackoff, freshReconnectState, resetReconnectSta
|
|
|
39
40
|
// Timing Constants
|
|
40
41
|
// ============================================================================
|
|
41
42
|
import { EXEC_TIMEOUT_MS } from './config/exec-timeout.js';
|
|
43
|
+
/** How long a cached process snapshot stays usable. */
|
|
44
|
+
const PROC_SNAPSHOT_TTL_MS = 2000;
|
|
45
|
+
/**
|
|
46
|
+
* How long the kill path waits for a fresh snapshot before giving up on it.
|
|
47
|
+
* Shorter than EXEC_TIMEOUT_MS on purpose: killSession has two further strategies
|
|
48
|
+
* (process group, tmux kill-session) and must reach them even when `ps` is wedged.
|
|
49
|
+
*/
|
|
50
|
+
const PROC_SNAPSHOT_WAIT_MS = 1500;
|
|
42
51
|
import { DEFAULT_TMUX_HISTORY_LIMIT, DEFAULT_TERMINAL_BUFFER_MAX_BYTES } from './config/terminal-history.js';
|
|
43
52
|
/**
|
|
44
53
|
* Extra stdout headroom for the full-history `capture-pane` child process on
|
|
@@ -1817,28 +1826,102 @@ export class TmuxManager extends EventEmitter {
|
|
|
1817
1826
|
return false;
|
|
1818
1827
|
}
|
|
1819
1828
|
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1829
|
+
/** One `ps` snapshot of the whole process table, cached briefly. */
|
|
1830
|
+
static procSnapshot = null;
|
|
1831
|
+
/** Single-flight guard so a hung `ps` cannot pile up parallel refreshes. */
|
|
1832
|
+
static procRefresh = null;
|
|
1833
|
+
/**
|
|
1834
|
+
* Fork ONE `ps` asynchronously and cache the parent -> children map.
|
|
1835
|
+
*
|
|
1836
|
+
* Async on purpose: a synchronous fork here would block the event loop on every
|
|
1837
|
+
* stats tick, and under the procfs pathology this module exists to survive,
|
|
1838
|
+
* `execSync`'s timeout cannot return at all (spawnSync waits for the unkillable
|
|
1839
|
+
* child) — freezing the whole server where a hung async poll only costs staleness.
|
|
1840
|
+
*/
|
|
1841
|
+
static refreshProcSnapshot() {
|
|
1842
|
+
const inFlight = TmuxManager.procRefresh;
|
|
1843
|
+
// Reuse an in-flight refresh — unless it is old enough to be presumed stuck.
|
|
1844
|
+
if (inFlight && Date.now() - inFlight.started < EXEC_TIMEOUT_MS * 2)
|
|
1845
|
+
return inFlight.promise;
|
|
1846
|
+
const started = Date.now();
|
|
1847
|
+
const promise = new Promise((resolve) => {
|
|
1848
|
+
execFile('ps', ['-eo', 'pid=,ppid='], { timeout: EXEC_TIMEOUT_MS, maxBuffer: 8 * 1024 * 1024 }, (err, out) => {
|
|
1849
|
+
if (TmuxManager.procRefresh?.started === started)
|
|
1850
|
+
TmuxManager.procRefresh = null;
|
|
1851
|
+
if (err) {
|
|
1852
|
+
// ANY error, not just an empty one: a timed-out or truncated `ps` yields
|
|
1853
|
+
// partial output, and caching that as fresh would make whole subtrees
|
|
1854
|
+
// invisible — including to the kill path. Stale beats wrong.
|
|
1855
|
+
console.error('[TmuxManager] process snapshot failed:', err);
|
|
1856
|
+
resolve(TmuxManager.procSnapshot?.byParent ?? new Map());
|
|
1857
|
+
return;
|
|
1835
1858
|
}
|
|
1836
|
-
|
|
1859
|
+
const byParent = new Map();
|
|
1860
|
+
for (const line of String(out).split('\n')) {
|
|
1861
|
+
const parts = line.trim().split(/\s+/);
|
|
1862
|
+
if (parts.length < 2)
|
|
1863
|
+
continue;
|
|
1864
|
+
const pid = parseInt(parts[0], 10);
|
|
1865
|
+
const ppid = parseInt(parts[1], 10);
|
|
1866
|
+
if (Number.isNaN(pid) || Number.isNaN(ppid))
|
|
1867
|
+
continue;
|
|
1868
|
+
const list = byParent.get(ppid);
|
|
1869
|
+
if (list)
|
|
1870
|
+
list.push(pid);
|
|
1871
|
+
else
|
|
1872
|
+
byParent.set(ppid, [pid]);
|
|
1873
|
+
}
|
|
1874
|
+
TmuxManager.procSnapshot = { at: Date.now(), byParent };
|
|
1875
|
+
resolve(byParent);
|
|
1876
|
+
});
|
|
1877
|
+
});
|
|
1878
|
+
TmuxManager.procRefresh = { started, promise };
|
|
1879
|
+
return promise;
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* Best snapshot WITHOUT forking: returns the cache, kicking off a background
|
|
1883
|
+
* refresh when it has gone stale, and never blocks. Stats and window-title
|
|
1884
|
+
* consumers tolerate data one interval old; nothing that KILLS may use this.
|
|
1885
|
+
*/
|
|
1886
|
+
childrenByParent() {
|
|
1887
|
+
const cached = TmuxManager.procSnapshot;
|
|
1888
|
+
if (!cached || Date.now() - cached.at >= PROC_SNAPSHOT_TTL_MS) {
|
|
1889
|
+
void TmuxManager.refreshProcSnapshot();
|
|
1890
|
+
}
|
|
1891
|
+
return cached?.byParent ?? new Map();
|
|
1892
|
+
}
|
|
1893
|
+
/**
|
|
1894
|
+
* Descendants from a snapshot that is not the cached one — the kill path's variant.
|
|
1895
|
+
*
|
|
1896
|
+
* killSession re-scans for survivors between SIGTERM and SIGKILL, and the wait in
|
|
1897
|
+
* between (200ms) sits far inside the cache TTL (2000ms): reading the cache there
|
|
1898
|
+
* returns the pre-SIGTERM state verbatim, so children spawned since are invisible
|
|
1899
|
+
* and SIGKILL aims at stale PIDs, guarded only by kill(pid, 0) — which cannot
|
|
1900
|
+
* detect PID reuse.
|
|
1901
|
+
*
|
|
1902
|
+
* It forces a refresh rather than guaranteeing recency: an already-running refresh
|
|
1903
|
+
* is reused, so the snapshot can predate this call by up to one `ps` runtime. A
|
|
1904
|
+
* strict postdate guarantee would mean chaining a second `ps` behind every
|
|
1905
|
+
* in-flight one, which is the fork storm this code exists to avoid.
|
|
1906
|
+
*
|
|
1907
|
+
* Bounded by design: waiting forever would freeze killSession before it reaches
|
|
1908
|
+
* its process-group and tmux fallbacks.
|
|
1909
|
+
*/
|
|
1910
|
+
async getChildPidsFresh(pid) {
|
|
1911
|
+
let byParent;
|
|
1912
|
+
try {
|
|
1913
|
+
byParent = await Promise.race([
|
|
1914
|
+
TmuxManager.refreshProcSnapshot(),
|
|
1915
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('proc snapshot timeout')), PROC_SNAPSHOT_WAIT_MS)),
|
|
1916
|
+
]);
|
|
1837
1917
|
}
|
|
1838
1918
|
catch {
|
|
1839
|
-
|
|
1919
|
+
console.warn('[TmuxManager] process snapshot did not return in time; using the cached one');
|
|
1920
|
+
byParent = TmuxManager.procSnapshot?.byParent ?? new Map();
|
|
1840
1921
|
}
|
|
1841
|
-
return
|
|
1922
|
+
return collectDescendants(pid, byParent, {
|
|
1923
|
+
onTruncated: (root, cap, reason) => console.warn(`[TmuxManager] descendant walk for ${root} hit the ${cap}-${reason} cap; truncating`),
|
|
1924
|
+
});
|
|
1842
1925
|
}
|
|
1843
1926
|
// Check if a process is still alive
|
|
1844
1927
|
isProcessAlive(pid) {
|
|
@@ -1934,7 +2017,7 @@ export class TmuxManager extends EventEmitter {
|
|
|
1934
2017
|
console.log(`[TmuxManager] Killing session ${session.muxName} (PID ${currentPid})`);
|
|
1935
2018
|
const allPids = [currentPid];
|
|
1936
2019
|
// Strategy 1: Kill all child processes recursively
|
|
1937
|
-
let childPids = this.
|
|
2020
|
+
let childPids = await this.getChildPidsFresh(currentPid);
|
|
1938
2021
|
if (childPids.length > 0) {
|
|
1939
2022
|
console.log(`[TmuxManager] Found ${childPids.length} child processes to kill`);
|
|
1940
2023
|
allPids.push(...childPids);
|
|
@@ -1949,7 +2032,7 @@ export class TmuxManager extends EventEmitter {
|
|
|
1949
2032
|
}
|
|
1950
2033
|
}
|
|
1951
2034
|
await new Promise((resolve) => setTimeout(resolve, TMUX_KILL_WAIT_MS));
|
|
1952
|
-
childPids = this.
|
|
2035
|
+
childPids = await this.getChildPidsFresh(currentPid);
|
|
1953
2036
|
for (const childPid of childPids) {
|
|
1954
2037
|
if (this.isProcessAlive(childPid)) {
|
|
1955
2038
|
try {
|
|
@@ -2148,16 +2231,14 @@ export class TmuxManager extends EventEmitter {
|
|
|
2148
2231
|
timeout: EXEC_TIMEOUT_MS,
|
|
2149
2232
|
})).stdout.trim();
|
|
2150
2233
|
const [rss, cpu] = psOutput.split(/\s+/).map((x) => parseFloat(x) || 0);
|
|
2234
|
+
// From the shared snapshot: this runs per session on every stats tick, and a
|
|
2235
|
+
// pgrep per session was a fork per session per interval.
|
|
2151
2236
|
let childCount = 0;
|
|
2152
2237
|
try {
|
|
2153
|
-
|
|
2154
|
-
encoding: 'utf-8',
|
|
2155
|
-
timeout: EXEC_TIMEOUT_MS,
|
|
2156
|
-
})).stdout.trim();
|
|
2157
|
-
childCount = parseInt(childOutput, 10) || 0;
|
|
2238
|
+
childCount = (this.childrenByParent().get(session.pid) ?? []).length;
|
|
2158
2239
|
}
|
|
2159
2240
|
catch {
|
|
2160
|
-
// No children or
|
|
2241
|
+
// No children or snapshot unavailable
|
|
2161
2242
|
}
|
|
2162
2243
|
return {
|
|
2163
2244
|
memoryMB: Math.round((rss / 1024) * 10) / 10,
|
|
@@ -2186,11 +2267,11 @@ export class TmuxManager extends EventEmitter {
|
|
|
2186
2267
|
try {
|
|
2187
2268
|
// Step 1: Get descendant PIDs
|
|
2188
2269
|
const descendantMap = new Map();
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
})).
|
|
2193
|
-
for (const line of
|
|
2270
|
+
// Derived from the ONE snapshot instead of a shell loop that forks a pgrep
|
|
2271
|
+
// per session — the shape that turned into a fork storm under load.
|
|
2272
|
+
const byParent = this.childrenByParent();
|
|
2273
|
+
const childLines = sessionPids.map((p) => `${p}:${(byParent.get(p) ?? []).join(',')}`).join('\n');
|
|
2274
|
+
for (const line of childLines.split('\n')) {
|
|
2194
2275
|
const [pidStr, childrenStr] = line.split(':');
|
|
2195
2276
|
const sessionPid = parseInt(pidStr, 10);
|
|
2196
2277
|
if (!Number.isNaN(sessionPid)) {
|