aicodeman 1.19.6 → 1.19.7
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/utils/file-query.d.ts +39 -0
- package/dist/utils/file-query.d.ts.map +1 -0
- package/dist/utils/file-query.js +90 -0
- package/dist/utils/file-query.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.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.e538c4dd.js → app.56c520ff.js} +1 -1
- package/dist/web/public/app.56c520ff.js.br +0 -0
- package/dist/web/public/app.56c520ff.js.gz +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/{constants.1dc77e55.js → constants.dc5d04bb.js} +144 -0
- package/dist/web/public/constants.dc5d04bb.js.br +0 -0
- package/dist/web/public/constants.dc5d04bb.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/fonts/LICENSE-nerd-fonts.txt +21 -0
- package/dist/web/public/fonts/symbols-nerd-font-mono.woff2 +0 -0
- package/dist/web/public/home-sessions.js.gz +0 -0
- package/dist/web/public/i18n.6a46f014.js +1 -0
- package/dist/web/public/i18n.6a46f014.js.br +0 -0
- package/dist/web/public/i18n.6a46f014.js.gz +0 -0
- package/dist/web/public/image-input.ee16ad88.js.gz +0 -0
- package/dist/web/public/index.html +28 -12
- 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.0454a3e9.js.gz +0 -0
- package/dist/web/public/{mobile-handlers.05b89237.js → mobile-handlers.0f83a608.js} +38 -1
- package/dist/web/public/mobile-handlers.0f83a608.js.br +0 -0
- package/dist/web/public/mobile-handlers.0f83a608.js.gz +0 -0
- package/dist/web/public/mobile-overview.js.gz +0 -0
- package/dist/web/public/mobile.49aeb17e.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.c5a82b6e.js → panels-ui.5e97a36e.js} +1 -1
- package/dist/web/public/panels-ui.5e97a36e.js.br +0 -0
- package/dist/web/public/panels-ui.5e97a36e.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/readmymind-ui.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-lineage.js.gz +0 -0
- package/dist/web/public/session-ui.71a0ce9a.js.gz +0 -0
- package/dist/web/public/settings-ui.b62c70a3.js +67 -0
- package/dist/web/public/settings-ui.b62c70a3.js.br +0 -0
- package/dist/web/public/settings-ui.b62c70a3.js.gz +0 -0
- package/dist/web/public/styles.68f9e118.css +1 -0
- package/dist/web/public/styles.68f9e118.css.br +0 -0
- package/dist/web/public/styles.68f9e118.css.gz +0 -0
- package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/terminal-ui.4723f5d4.js +4 -0
- package/dist/web/public/terminal-ui.4723f5d4.js.br +0 -0
- package/dist/web/public/terminal-ui.4723f5d4.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-predictive-echo.6cec0fba.js → xterm-predictive-echo.bd6882b8.js} +1 -1
- package/dist/web/public/vendor/xterm-predictive-echo.bd6882b8.js.br +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.bd6882b8.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js +4 -0
- package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.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.4ec670b0.js.gz +0 -0
- package/dist/web/public/voice-pcm-worklet.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 +90 -1
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +17 -4
- package/dist/web/server.js.map +1 -1
- package/package.json +2 -2
- package/dist/web/public/app.e538c4dd.js.br +0 -0
- package/dist/web/public/app.e538c4dd.js.gz +0 -0
- package/dist/web/public/constants.1dc77e55.js.br +0 -0
- package/dist/web/public/constants.1dc77e55.js.gz +0 -0
- package/dist/web/public/i18n.4bff95df.js +0 -1
- package/dist/web/public/i18n.4bff95df.js.br +0 -0
- package/dist/web/public/i18n.4bff95df.js.gz +0 -0
- package/dist/web/public/mobile-handlers.05b89237.js.br +0 -0
- package/dist/web/public/mobile-handlers.05b89237.js.gz +0 -0
- package/dist/web/public/panels-ui.c5a82b6e.js.br +0 -0
- package/dist/web/public/panels-ui.c5a82b6e.js.gz +0 -0
- package/dist/web/public/settings-ui.6cb12d4b.js +0 -67
- package/dist/web/public/settings-ui.6cb12d4b.js.br +0 -0
- package/dist/web/public/settings-ui.6cb12d4b.js.gz +0 -0
- package/dist/web/public/styles.1d72c88f.css +0 -1
- package/dist/web/public/styles.1d72c88f.css.br +0 -0
- package/dist/web/public/styles.1d72c88f.css.gz +0 -0
- package/dist/web/public/terminal-ui.02b89e2c.js +0 -4
- package/dist/web/public/terminal-ui.02b89e2c.js.br +0 -0
- package/dist/web/public/terminal-ui.02b89e2c.js.gz +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.6cec0fba.js.br +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.6cec0fba.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js +0 -4
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure file-name/path query matcher for the Files panel search
|
|
3
|
+
* (COD-236). Compiles a user query string into a reusable predicate so the
|
|
4
|
+
* server-side file walk can prune to matching entries instead of streaming the
|
|
5
|
+
* whole tree.
|
|
6
|
+
*
|
|
7
|
+
* Semantics:
|
|
8
|
+
* - Empty / whitespace-only query → `compileFileQuery` returns `null` (the
|
|
9
|
+
* caller treats this as "no search", falling back to the full tree). A query
|
|
10
|
+
* longer than `MAX_QUERY_LENGTH` compiles to `null` too: no honest filename
|
|
11
|
+
* search is that long, and the glob walk below is O(text · pattern).
|
|
12
|
+
* - A query containing a glob metachar (`*` or `?`) matches anchored and
|
|
13
|
+
* case-insensitively, `*` spanning any run (slashes included) and `?` exactly
|
|
14
|
+
* one character; every other character matches literally.
|
|
15
|
+
* - Otherwise the query is a plain case-insensitive substring.
|
|
16
|
+
* - When the query contains a `/` it matches against the relative path; else it
|
|
17
|
+
* matches against the bare entry name.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ Globs are matched by `globMatch` below, never by compiling the query into
|
|
20
|
+
* a RegExp: `*a*a*a…` translated to `^.*a.*a.*a…$` is a classic backtracking
|
|
21
|
+
* blowup, evaluated synchronously against every walked path — a pathological
|
|
22
|
+
* query could freeze the event loop for the whole server (the same reason
|
|
23
|
+
* `search-service.ts` is regex-free). The two-pointer wildcard walk is
|
|
24
|
+
* O(text · pattern) worst case, with both operands short by construction.
|
|
25
|
+
*
|
|
26
|
+
* No fs / IO — safe to unit-test directly.
|
|
27
|
+
*/
|
|
28
|
+
export type FileQueryMatcher = (name: string, relativePath: string) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Compile a query string into a matcher predicate, or `null` when the query is
|
|
31
|
+
* empty/whitespace or overlong (caller treats null as "no search").
|
|
32
|
+
*/
|
|
33
|
+
export declare function compileFileQuery(query: string): FileQueryMatcher | null;
|
|
34
|
+
/**
|
|
35
|
+
* Convenience: compile the query and apply it in one call. Returns false when
|
|
36
|
+
* the query compiles to null (empty).
|
|
37
|
+
*/
|
|
38
|
+
export declare function matchFileQuery(query: string, name: string, relativePath: string): boolean;
|
|
39
|
+
//# sourceMappingURL=file-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-query.d.ts","sourceRoot":"","sources":["../../src/utils/file-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;AAqC/E;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAcvE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAGzF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure file-name/path query matcher for the Files panel search
|
|
3
|
+
* (COD-236). Compiles a user query string into a reusable predicate so the
|
|
4
|
+
* server-side file walk can prune to matching entries instead of streaming the
|
|
5
|
+
* whole tree.
|
|
6
|
+
*
|
|
7
|
+
* Semantics:
|
|
8
|
+
* - Empty / whitespace-only query → `compileFileQuery` returns `null` (the
|
|
9
|
+
* caller treats this as "no search", falling back to the full tree). A query
|
|
10
|
+
* longer than `MAX_QUERY_LENGTH` compiles to `null` too: no honest filename
|
|
11
|
+
* search is that long, and the glob walk below is O(text · pattern).
|
|
12
|
+
* - A query containing a glob metachar (`*` or `?`) matches anchored and
|
|
13
|
+
* case-insensitively, `*` spanning any run (slashes included) and `?` exactly
|
|
14
|
+
* one character; every other character matches literally.
|
|
15
|
+
* - Otherwise the query is a plain case-insensitive substring.
|
|
16
|
+
* - When the query contains a `/` it matches against the relative path; else it
|
|
17
|
+
* matches against the bare entry name.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ Globs are matched by `globMatch` below, never by compiling the query into
|
|
20
|
+
* a RegExp: `*a*a*a…` translated to `^.*a.*a.*a…$` is a classic backtracking
|
|
21
|
+
* blowup, evaluated synchronously against every walked path — a pathological
|
|
22
|
+
* query could freeze the event loop for the whole server (the same reason
|
|
23
|
+
* `search-service.ts` is regex-free). The two-pointer wildcard walk is
|
|
24
|
+
* O(text · pattern) worst case, with both operands short by construction.
|
|
25
|
+
*
|
|
26
|
+
* No fs / IO — safe to unit-test directly.
|
|
27
|
+
*/
|
|
28
|
+
// Longer than any honest file search; bounds the O(text · pattern) glob walk.
|
|
29
|
+
const MAX_QUERY_LENGTH = 256;
|
|
30
|
+
/**
|
|
31
|
+
* Anchored glob match, linear-space two-pointer walk (no RegExp — see the
|
|
32
|
+
* fileoverview). `pattern` must already be lowercased; `text` is lowercased
|
|
33
|
+
* here so one compiled matcher serves many entries.
|
|
34
|
+
*/
|
|
35
|
+
function globMatch(pattern, rawText) {
|
|
36
|
+
const text = rawText.toLowerCase();
|
|
37
|
+
let p = 0;
|
|
38
|
+
let t = 0;
|
|
39
|
+
let starP = -1;
|
|
40
|
+
let starT = -1;
|
|
41
|
+
while (t < text.length) {
|
|
42
|
+
const pc = p < pattern.length ? pattern[p] : '';
|
|
43
|
+
if (pc === '?' || pc === text[t]) {
|
|
44
|
+
p++;
|
|
45
|
+
t++;
|
|
46
|
+
}
|
|
47
|
+
else if (pc === '*') {
|
|
48
|
+
// Remember the star; try matching zero characters first, and on a later
|
|
49
|
+
// mismatch re-expand it one character at a time from here.
|
|
50
|
+
starP = p++;
|
|
51
|
+
starT = t;
|
|
52
|
+
}
|
|
53
|
+
else if (starP !== -1) {
|
|
54
|
+
p = starP + 1;
|
|
55
|
+
t = ++starT;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
while (p < pattern.length && pattern[p] === '*')
|
|
62
|
+
p++;
|
|
63
|
+
return p === pattern.length;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Compile a query string into a matcher predicate, or `null` when the query is
|
|
67
|
+
* empty/whitespace or overlong (caller treats null as "no search").
|
|
68
|
+
*/
|
|
69
|
+
export function compileFileQuery(query) {
|
|
70
|
+
const trimmed = query.trim();
|
|
71
|
+
if (trimmed === '' || trimmed.length > MAX_QUERY_LENGTH)
|
|
72
|
+
return null;
|
|
73
|
+
const matchesPath = trimmed.includes('/');
|
|
74
|
+
const isGlob = trimmed.includes('*') || trimmed.includes('?');
|
|
75
|
+
if (isGlob) {
|
|
76
|
+
const pattern = trimmed.toLowerCase();
|
|
77
|
+
return (name, relativePath) => globMatch(pattern, matchesPath ? relativePath : name);
|
|
78
|
+
}
|
|
79
|
+
const needle = trimmed.toLowerCase();
|
|
80
|
+
return (name, relativePath) => (matchesPath ? relativePath : name).toLowerCase().includes(needle);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Convenience: compile the query and apply it in one call. Returns false when
|
|
84
|
+
* the query compiles to null (empty).
|
|
85
|
+
*/
|
|
86
|
+
export function matchFileQuery(query, name, relativePath) {
|
|
87
|
+
const matcher = compileFileQuery(query);
|
|
88
|
+
return matcher ? matcher(name, relativePath) : false;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=file-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-query.js","sourceRoot":"","sources":["../../src/utils/file-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;GAIG;AACH,SAAS,SAAS,CAAC,OAAe,EAAE,OAAe;IACjD,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IACf,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IACf,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACjC,CAAC,EAAE,CAAC;YACJ,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACtB,wEAAwE;YACxE,2DAA2D;YAC3D,KAAK,GAAG,CAAC,EAAE,CAAC;YACZ,KAAK,GAAG,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACxB,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YACd,CAAC,GAAG,EAAE,KAAK,CAAC;QACd,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,CAAC,EAAE,CAAC;IACrD,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,CAAC,MAAM,GAAG,gBAAgB;QAAE,OAAO,IAAI,CAAC;IAErE,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE9D,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACpG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,IAAY,EAAE,YAAoB;IAC9E,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACvD,CAAC"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -25,4 +25,6 @@ export { resolveCodexDir, isCodexAvailable } from './codex-cli-resolver.js';
|
|
|
25
25
|
export { resolveGeminiDir, isGeminiAvailable } from './gemini-cli-resolver.js';
|
|
26
26
|
export { resolveAntigravityDir, isAntigravityAvailable } from './antigravity-cli-resolver.js';
|
|
27
27
|
export { resolvePiDir, isPiAvailable, getPiCliVersion } from './pi-cli-resolver.js';
|
|
28
|
+
export { compileFileQuery, matchFileQuery } from './file-query.js';
|
|
29
|
+
export type { FileQueryMatcher } from './file-query.js';
|
|
28
30
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,aAAa,EACb,eAAe,EACf,2BAA2B,EAC3B,SAAS,EACT,iBAAiB,EACjB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,aAAa,EACb,eAAe,EACf,2BAA2B,EAC3B,SAAS,EACT,iBAAiB,EACjB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/utils/index.js
CHANGED
|
@@ -24,4 +24,5 @@ export { resolveCodexDir, isCodexAvailable } from './codex-cli-resolver.js';
|
|
|
24
24
|
export { resolveGeminiDir, isGeminiAvailable } from './gemini-cli-resolver.js';
|
|
25
25
|
export { resolveAntigravityDir, isAntigravityAvailable } from './antigravity-cli-resolver.js';
|
|
26
26
|
export { resolvePiDir, isPiAvailable, getPiCliVersion } from './pi-cli-resolver.js';
|
|
27
|
+
export { compileFileQuery, matchFileQuery } from './file-query.js';
|
|
27
28
|
//# sourceMappingURL=index.js.map
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,aAAa,EACb,eAAe,EACf,2BAA2B,EAC3B,SAAS,EACT,iBAAiB,EACjB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,aAAa,EACb,eAAe,EACf,2BAA2B,EAC3B,SAAS,EACT,iBAAiB,EACjB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACrH,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
|
Binary file
|
|
Binary file
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
`).replace(/[ \t]+$/gm,"").replace(/\n{4,}/g,`
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
`).trim()}_preprocessAsciiArt(e){const t=/[─-╿▀-▟]/,s=/```[\s\S]*?```/g,i=[];return e.replace(s,a=>(i.push(a),`__CODEMAN_FENCE_${i.length-1}__`)).split(/(\n{2,})/).map(a=>/^\n{2,}$/.test(a)||!a.trim()||a.includes("__CODEMAN_FENCE_")?a:t.test(a)?"\n```\n"+a+"\n```\n":a).join("").replace(/__CODEMAN_FENCE_(\d+)__/g,(a,r)=>i[Number(r)])}_renderMarkdown(e){const t=e||"";if(typeof marked<"u"&&marked.parse)try{const i=this._preprocessAsciiArt(t);let n=this._sanitizeHtml(marked.parse(i,{breaks:!0,gfm:!0}));n=n.replace(/<table>/g,'<div class="rv-table-wrap"><table>').replace(/<\/table>/g,"</table></div>");const o=/[─-╿▀-▟]/,a=document.createElement("template");return a.innerHTML=n,a.content.querySelectorAll("pre > code").forEach(r=>{const l=r.parentElement,c=o.test(r.textContent||""),h=document.createElement("div");h.className=c?"rv-code-wrap rv-diagram-wrap":"rv-code-wrap";const d=document.createElement("div");d.className="rv-code-actions";const _=document.createElement("button");if(_.className="rv-copy-btn",_.type="button",_.setAttribute("aria-label","Copy code"),_.setAttribute("title","Copy code"),d.appendChild(_),c){l.classList.add("rv-diagram");const S=document.createElement("button");S.className="rv-wrap-toggle",S.type="button",S.setAttribute("aria-label","Toggle line wrapping"),S.setAttribute("title","Toggle line wrapping"),d.appendChild(S)}l.parentNode.insertBefore(h,l),h.appendChild(d),h.appendChild(l)}),a.innerHTML}catch{}return`<pre style="white-space:pre-wrap;word-break:break-word">${t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}</pre>`}_bindResponseViewerInteractions(e){!e||e.dataset.rvBound==="1"||(e.dataset.rvBound="1",e.addEventListener("click",async t=>{const s=t.target.closest("a.rv-path");if(s){t.preventDefault(),t.stopPropagation();const l=s.dataset.path;l&&this.openFilePreview(l,this.activeSessionId);return}const i=t.target.closest(".rv-copy-btn");if(i){t.preventDefault(),t.stopPropagation();const l=i.closest(".rv-code-wrap")?.querySelector("pre code"),c=l?await this._copyText(l.textContent||""):!1;i.classList.remove("rv-copied","rv-copy-failed"),i.classList.add(c?"rv-copied":"rv-copy-failed"),clearTimeout(i._resetTimer),i._resetTimer=setTimeout(()=>{i.classList.remove("rv-copied","rv-copy-failed")},1500);return}const n=t.target.closest(".rv-wrap-toggle");if(!n)return;t.preventDefault(),t.stopPropagation();const o=n.closest(".rv-diagram-wrap"),a=o?.querySelector("pre.rv-diagram");if(!a||!o)return;const r=a.classList.toggle("rv-nowrap");o.classList.toggle("rv-wrap-nowrap",r)}))}async _copyText(e){if(!e)return!1;try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.cssText="position:fixed;top:0;left:0;opacity:0;pointer-events:none",document.body.appendChild(t),t.select();const s=document.execCommand("copy");return document.body.removeChild(t),s}catch{return!1}}_buildResponseViewerMessage(e,t,s){const i=document.createElement("div"),n=t==="user";i.className="rv-message "+(n?"rv-msg-user":"rv-msg-assistant");const o=document.createElement("div");o.className="rv-role "+(n?"rv-role-user":"rv-role-assistant"),o.textContent=n?"You":s,i.appendChild(o);const a=document.createElement("div");return a.className="rv-text",a.innerHTML=this._renderMarkdown(e),this._linkifyFilePaths(a),i.appendChild(a),i}_linkifyFilePaths(e){if(!e||typeof document>"u"||typeof absoluteFilePathPattern!="function")return;const t=absoluteFilePathPattern(),s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT),i=[];for(let n=s.nextNode();n;n=s.nextNode())n.parentElement?.closest("a")||(t.lastIndex=0,t.test(n.nodeValue||"")&&i.push(n));for(const n of i){const o=n.nodeValue,a=document.createDocumentFragment();let r=0,l;for(t.lastIndex=0;(l=t.exec(o))!==null;){const c=l[1];l.index>r&&a.appendChild(document.createTextNode(o.slice(r,l.index)));const h=document.createElement("a");h.className="rv-path",h.href="#",h.dataset.path=c,h.title=c,h.textContent=c,a.appendChild(h),r=l.index+c.length}r<o.length&&a.appendChild(document.createTextNode(o.slice(r))),n.parentNode?.replaceChild(a,n)}}_getResponseViewerAgentLabel(){const e=this.sessions.get(this.activeSessionId)?.mode;return e==="codex"?"Codex":e==="gemini"?"Gemini":e==="antigravity"?"Antigravity":e==="pi"?"Pi":e==="opencode"?"OpenCode":"Claude"}async toggleResponseViewer(){const e=document.getElementById("responseViewer"),t=document.getElementById("responseViewerBackdrop");if(!e)return;if(e.classList.contains("visible")){e.classList.remove("visible"),t.classList.remove("visible");return}if(this.activeSessionId)try{let o=((await(await fetch(`/api/sessions/${this.activeSessionId}/last-response`)).json())?.data??{}).text||"";const a=this.sessions.get(this.activeSessionId)?.mode||"claude";if(!o&&(a==="claude"||a==="shell")){const d=(await(await fetch(`/api/sessions/${this.activeSessionId}/terminal`)).json())?.data??{};d.terminalBuffer&&(o=this._cleanTerminalBuffer(d.terminalBuffer))}const r=document.getElementById("responseViewerBody");o?(r.innerHTML="",r.appendChild(this._buildResponseViewerMessage(o,"assistant",this._getResponseViewerAgentLabel())),this._bindResponseViewerInteractions(r)):r.textContent=window.codemanT?.("No response yet \u2014 send a message in this session first.")||"No response yet \u2014 send a message in this session first.";const l=document.getElementById("responseViewerTitle"),c=document.getElementById("responseViewerMore");l&&(l.textContent="Last Response"),c&&(c.style.display="",c.textContent="More"),e.classList.add("visible"),t.classList.add("visible"),r.scrollTop=0}catch(i){console.error("Failed to load response:",i)}}async loadFullContext(){if(!this.activeSessionId)return;const e=document.getElementById("responseViewerMore");e&&(e.textContent="...");try{const i=((await(await fetch(`/api/sessions/${this.activeSessionId}/last-response?context=full`)).json())?.data??{}).messages||[],n=document.getElementById("responseViewerBody"),o=document.getElementById("responseViewerTitle");if(!n)return;if(i.length===0){n.textContent="No conversation history available";return}const a=this._getResponseViewerAgentLabel();n.innerHTML="";for(const r of i)n.appendChild(this._buildResponseViewerMessage(r.text,r.role,a));this._bindResponseViewerInteractions(n),o&&(o.textContent=`Conversation (${i.length} messages)`),e&&(e.style.display="none"),n.scrollTop=n.scrollHeight}catch(t){console.error("Failed to load context:",t)}finally{e&&(e.textContent="More")}}async _onSessionNeedsRefresh(){if(!this.activeSessionId||!this.terminal||this._isLoadingBuffer)return;const e=this.activeSessionId;try{let t=await fetch(`/api/sessions/${e}/terminal?full=1`),s=(await t.json())?.data??{};if(s.terminalBuffer&&this._replayWouldShrinkBuffer(s.terminalBuffer)&&(t=await fetch(`/api/sessions/${e}/terminal?tail=${TERMINAL_TAIL_SIZE}`),s=(await t.json())?.data??{}),this.activeSessionId!==e)return;if(s.terminalBuffer){const i=this.terminal.buffer?.active,n=i?Math.max(0,(i.baseY||0)-(i.viewportY||0)):0;this.terminal.clear(),this.terminal.reset(),await this.chunkedTerminalWrite(s.terminalBuffer),this._setHistoryTruncation(e,s);const o=computeRewriteScrollLine({linesFromBottom:n,baseY:this.terminal.buffer?.active?.baseY??0});o===null||typeof this.terminal.scrollToLine!="function"?this.terminal.scrollToBottom():this.terminal.scrollToLine(o),this._localEchoOverlay?.rerender(),this.activeSessionId&&this.sendResize(this.activeSessionId)}}catch(t){console.error("needsRefresh reload failed:",t)}}async _onSessionClearTerminal(e){if(e.id===this.activeSessionId){if(this._isLoadingBuffer)return;try{const s=(await(await fetch(`/api/sessions/${e.id}/terminal`)).json())?.data??{};if(this.terminal.clear(),this.terminal.reset(),s.terminalBuffer){const i=s.terminalBuffer.replace(DEC_SYNC_STRIP_RE,"");await this.chunkedTerminalWrite(i)}this.sendResize(e.id),this._localEchoOverlay?.rerender()}catch(t){console.error("clearTerminal refresh failed:",t)}}}_onSessionCompletion(e){this.totalCost+=e.cost||0,this.updateCost(),e.id===this.activeSessionId&&(this.terminal.writeln(""),this.terminal.writeln(`\x1B[1;32m Done (Cost: $${(e.cost||0).toFixed(4)})\x1B[0m`))}_onSessionError(e){e.id===this.activeSessionId&&this.terminal.writeln(`\x1B[1;31m Error: ${e.error}\x1B[0m`),this._notifySession(e.id,"critical","session-error","Session Error",e.error||"Unknown error")}_onSessionExit(e){this._wsSessionId===e.id&&this._disconnectWs();const t=this.sessions.get(e.id);t&&(t.status="stopped",this.renderSessionTabs(),e.id===this.activeSessionId&&this._updateLocalEchoState()),e.code&&e.code!==0&&this._notifySession(e.id,"critical","session-crash","Session Crashed",`Exited with code ${e.code}`)}_onSessionIdle(e){const t=this.sessions.get(e.id);if(t&&(t.status="idle",this.renderSessionTabs(),this.sendPendingCtrlL(e.id),e.id===this.activeSessionId&&this._updateLocalEchoState()),!this.respawnStatus[e.id]?.enabled){const s=this.notificationManager?.preferences?.stuckThresholdMs||6e5;clearTimeout(this.idleTimers.get(e.id)),this.idleTimers.set(e.id,setTimeout(()=>{this._notifySession(e.id,"warning","session-stuck","Session Idle",`Idle for ${Math.round(s/6e4)}+ minutes`),this.idleTimers.delete(e.id)},s))}}_onSessionWorking(e){const t=this.sessions.get(e.id);t&&(t.status="busy",this.pendingHooks.has(e.id)||this.tabAlerts.delete(e.id),this.renderSessionTabs(),this.sendPendingCtrlL(e.id),e.id===this.activeSessionId&&this._updateLocalEchoState());const s=this.idleTimers.get(e.id);s&&(clearTimeout(s),this.idleTimers.delete(e.id))}_onSessionAutoClear(e){e.sessionId===this.activeSessionId&&(this.showToast(`Auto-cleared at ${e.tokens.toLocaleString()} tokens`,"info"),this.updateRespawnTokens(0)),this._notifySession(e.sessionId,"info","auto-clear","Auto-Cleared",`Context reset at ${(e.tokens||0).toLocaleString()} tokens`)}_onSessionLimitPauseScheduled(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=e.resumeAt);const s=new Date(e.resumeAt).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});e.sessionId===this.activeSessionId&&this.showToast(`Usage limit reached \u2014 auto-resume at ${s}`,"warning"),this._notifySession(e.sessionId,"warning","limit-pause","Usage Limit Reached",`Auto-resume scheduled for ${s}`),this.updateAutoResumeStatus(e.sessionId)}_onSessionLimitResume(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=void 0),e.sessionId===this.activeSessionId&&this.showToast("Usage limit reset \u2014 work resumed automatically","success"),this._notifySession(e.sessionId,"info","limit-resume","Auto-Resumed","Usage limit reset \u2014 continuing work"),this.updateAutoResumeStatus(e.sessionId)}_onSessionLimitResumeCancelled(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=void 0),this.updateAutoResumeStatus(e.sessionId)}_onSessionRespawnBreakerTripped(e){const s=this.sessions.get(e.sessionId)?.name||"Session";this.showToast?.(`${s} stopped: repeated crashes detected. Restart to retry.`,"error")}_onSessionCliInfo(e){const t=this.sessions.get(e.sessionId);t&&(e.version&&(t.cliVersion=e.version),e.model&&(t.cliModel=e.model),e.accountType&&(t.cliAccountType=e.accountType),e.latestVersion&&(t.cliLatestVersion=e.latestVersion)),e.sessionId===this.activeSessionId&&this.updateCliInfoDisplay()}_onSessionStatusTelemetry(e){this.updatePlanUsageChip(e);try{localStorage.setItem("codeman:planUsage",JSON.stringify({t:Date.now(),data:e}))}catch{}}restorePlanUsageChip(){try{const e=localStorage.getItem("codeman:planUsage");if(!e)return;const t=JSON.parse(e);t?.data&&Date.now()-(t.t||0)<12*3600*1e3&&this.updatePlanUsageChip(t.data)}catch{}}updatePlanUsageChip(e){const t=document.getElementById("planUsageChip");if(!t||!e)return;const s=l=>l&&typeof l.usedPercentage=="number"?Math.round(l.usedPercentage):null,i=s(e.fiveHour),n=s(e.sevenDay);if(i===null&&n===null)return;const o=l=>l>=85?"pu-red":l>=60?"pu-yellow":"pu-green",a=(l,c)=>{if(c===null)return"";const h=Math.round(Number(c));return Number.isFinite(h)?`<span class="pu-win"><span class="pu-label">${l}</span><span class="pu-val ${o(h)}">${h}%</span></span>`:""};t.innerHTML=[a("5h",i),a("7d",n)].filter(Boolean).join('<span class="pu-sep">\xB7</span>');const r=l=>l&&l.resetAt?new Date(l.resetAt).toLocaleString():"\u2014";t.title=`Claude plan usage
|
|
14
|
+
`).trim()}_preprocessAsciiArt(e){const t=/[─-╿▀-▟]/,s=/```[\s\S]*?```/g,i=[];return e.replace(s,a=>(i.push(a),`__CODEMAN_FENCE_${i.length-1}__`)).split(/(\n{2,})/).map(a=>/^\n{2,}$/.test(a)||!a.trim()||a.includes("__CODEMAN_FENCE_")?a:t.test(a)?"\n```\n"+a+"\n```\n":a).join("").replace(/__CODEMAN_FENCE_(\d+)__/g,(a,r)=>i[Number(r)])}_renderMarkdown(e){const t=e||"";if(typeof marked<"u"&&marked.parse)try{const i=this._preprocessAsciiArt(t);let n=this._sanitizeHtml(marked.parse(i,{breaks:!0,gfm:!0}));n=n.replace(/<table>/g,'<div class="rv-table-wrap"><table>').replace(/<\/table>/g,"</table></div>");const o=/[─-╿▀-▟]/,a=document.createElement("template");return a.innerHTML=n,a.content.querySelectorAll("pre > code").forEach(r=>{const l=r.parentElement,c=o.test(r.textContent||""),h=document.createElement("div");h.className=c?"rv-code-wrap rv-diagram-wrap":"rv-code-wrap";const d=document.createElement("div");d.className="rv-code-actions";const _=document.createElement("button");if(_.className="rv-copy-btn",_.type="button",_.setAttribute("aria-label","Copy code"),_.setAttribute("title","Copy code"),d.appendChild(_),c){l.classList.add("rv-diagram");const S=document.createElement("button");S.className="rv-wrap-toggle",S.type="button",S.setAttribute("aria-label","Toggle line wrapping"),S.setAttribute("title","Toggle line wrapping"),d.appendChild(S)}l.parentNode.insertBefore(h,l),h.appendChild(d),h.appendChild(l)}),a.content.querySelectorAll("a[href]").forEach(r=>{const l=r.getAttribute("href")||"";!l||l.startsWith("#")||/^(?:mailto|tel):/i.test(l)||(r.setAttribute("target","_blank"),r.setAttribute("rel","noopener noreferrer"))}),a.innerHTML}catch{}return`<pre style="white-space:pre-wrap;word-break:break-word">${t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}</pre>`}_bindResponseViewerInteractions(e){!e||e.dataset.rvBound==="1"||(e.dataset.rvBound="1",e.addEventListener("click",async t=>{const s=t.target.closest("a.rv-path");if(s){t.preventDefault(),t.stopPropagation();const l=s.dataset.path;l&&this.openFilePreview(l,this.activeSessionId);return}const i=t.target.closest(".rv-copy-btn");if(i){t.preventDefault(),t.stopPropagation();const l=i.closest(".rv-code-wrap")?.querySelector("pre code"),c=l?await this._copyText(l.textContent||""):!1;i.classList.remove("rv-copied","rv-copy-failed"),i.classList.add(c?"rv-copied":"rv-copy-failed"),clearTimeout(i._resetTimer),i._resetTimer=setTimeout(()=>{i.classList.remove("rv-copied","rv-copy-failed")},1500);return}const n=t.target.closest(".rv-wrap-toggle");if(!n)return;t.preventDefault(),t.stopPropagation();const o=n.closest(".rv-diagram-wrap"),a=o?.querySelector("pre.rv-diagram");if(!a||!o)return;const r=a.classList.toggle("rv-nowrap");o.classList.toggle("rv-wrap-nowrap",r)}))}async _copyText(e){if(!e)return!1;try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.cssText="position:fixed;top:0;left:0;opacity:0;pointer-events:none",document.body.appendChild(t),t.select();const s=document.execCommand("copy");return document.body.removeChild(t),s}catch{return!1}}_buildResponseViewerMessage(e,t,s){const i=document.createElement("div"),n=t==="user";i.className="rv-message "+(n?"rv-msg-user":"rv-msg-assistant");const o=document.createElement("div");o.className="rv-role "+(n?"rv-role-user":"rv-role-assistant"),o.textContent=n?"You":s,i.appendChild(o);const a=document.createElement("div");return a.className="rv-text",a.innerHTML=this._renderMarkdown(e),this._linkifyFilePaths(a),i.appendChild(a),i}_linkifyFilePaths(e){if(!e||typeof document>"u"||typeof absoluteFilePathPattern!="function")return;const t=absoluteFilePathPattern(),s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT),i=[];for(let n=s.nextNode();n;n=s.nextNode())n.parentElement?.closest("a")||(t.lastIndex=0,t.test(n.nodeValue||"")&&i.push(n));for(const n of i){const o=n.nodeValue,a=document.createDocumentFragment();let r=0,l;for(t.lastIndex=0;(l=t.exec(o))!==null;){const c=l[1];l.index>r&&a.appendChild(document.createTextNode(o.slice(r,l.index)));const h=document.createElement("a");h.className="rv-path",h.href="#",h.dataset.path=c,h.title=c,h.textContent=c,a.appendChild(h),r=l.index+c.length}r<o.length&&a.appendChild(document.createTextNode(o.slice(r))),n.parentNode?.replaceChild(a,n)}}_getResponseViewerAgentLabel(){const e=this.sessions.get(this.activeSessionId)?.mode;return e==="codex"?"Codex":e==="gemini"?"Gemini":e==="antigravity"?"Antigravity":e==="pi"?"Pi":e==="opencode"?"OpenCode":"Claude"}async toggleResponseViewer(){const e=document.getElementById("responseViewer"),t=document.getElementById("responseViewerBackdrop");if(!e)return;if(e.classList.contains("visible")){e.classList.remove("visible"),t.classList.remove("visible");return}if(this.activeSessionId)try{let o=((await(await fetch(`/api/sessions/${this.activeSessionId}/last-response`)).json())?.data??{}).text||"";const a=this.sessions.get(this.activeSessionId)?.mode||"claude";if(!o&&(a==="claude"||a==="shell")){const d=(await(await fetch(`/api/sessions/${this.activeSessionId}/terminal`)).json())?.data??{};d.terminalBuffer&&(o=this._cleanTerminalBuffer(d.terminalBuffer))}const r=document.getElementById("responseViewerBody");o?(r.innerHTML="",r.appendChild(this._buildResponseViewerMessage(o,"assistant",this._getResponseViewerAgentLabel())),this._bindResponseViewerInteractions(r)):r.textContent=window.codemanT?.("No response yet \u2014 send a message in this session first.")||"No response yet \u2014 send a message in this session first.";const l=document.getElementById("responseViewerTitle"),c=document.getElementById("responseViewerMore");l&&(l.textContent="Last Response"),c&&(c.style.display="",c.textContent="More"),e.classList.add("visible"),t.classList.add("visible"),r.scrollTop=0}catch(i){console.error("Failed to load response:",i)}}async loadFullContext(){if(!this.activeSessionId)return;const e=document.getElementById("responseViewerMore");e&&(e.textContent="...");try{const i=((await(await fetch(`/api/sessions/${this.activeSessionId}/last-response?context=full`)).json())?.data??{}).messages||[],n=document.getElementById("responseViewerBody"),o=document.getElementById("responseViewerTitle");if(!n)return;if(i.length===0){n.textContent="No conversation history available";return}const a=this._getResponseViewerAgentLabel();n.innerHTML="";for(const r of i)n.appendChild(this._buildResponseViewerMessage(r.text,r.role,a));this._bindResponseViewerInteractions(n),o&&(o.textContent=`Conversation (${i.length} messages)`),e&&(e.style.display="none"),n.scrollTop=n.scrollHeight}catch(t){console.error("Failed to load context:",t)}finally{e&&(e.textContent="More")}}async _onSessionNeedsRefresh(){if(!this.activeSessionId||!this.terminal||this._isLoadingBuffer)return;const e=this.activeSessionId;try{let t=await fetch(`/api/sessions/${e}/terminal?full=1`),s=(await t.json())?.data??{};if(s.terminalBuffer&&this._replayWouldShrinkBuffer(s.terminalBuffer)&&(t=await fetch(`/api/sessions/${e}/terminal?tail=${TERMINAL_TAIL_SIZE}`),s=(await t.json())?.data??{}),this.activeSessionId!==e)return;if(s.terminalBuffer){const i=this.terminal.buffer?.active,n=i?Math.max(0,(i.baseY||0)-(i.viewportY||0)):0;this.terminal.clear(),this.terminal.reset(),await this.chunkedTerminalWrite(s.terminalBuffer),this._setHistoryTruncation(e,s);const o=computeRewriteScrollLine({linesFromBottom:n,baseY:this.terminal.buffer?.active?.baseY??0});o===null||typeof this.terminal.scrollToLine!="function"?this.terminal.scrollToBottom():this.terminal.scrollToLine(o),this._localEchoOverlay?.rerender(),this.activeSessionId&&this.sendResize(this.activeSessionId)}}catch(t){console.error("needsRefresh reload failed:",t)}}async _onSessionClearTerminal(e){if(e.id===this.activeSessionId){if(this._isLoadingBuffer)return;try{const s=(await(await fetch(`/api/sessions/${e.id}/terminal`)).json())?.data??{};if(this.terminal.clear(),this.terminal.reset(),s.terminalBuffer){const i=s.terminalBuffer.replace(DEC_SYNC_STRIP_RE,"");await this.chunkedTerminalWrite(i)}this.sendResize(e.id),this._localEchoOverlay?.rerender()}catch(t){console.error("clearTerminal refresh failed:",t)}}}_onSessionCompletion(e){this.totalCost+=e.cost||0,this.updateCost(),e.id===this.activeSessionId&&(this.terminal.writeln(""),this.terminal.writeln(`\x1B[1;32m Done (Cost: $${(e.cost||0).toFixed(4)})\x1B[0m`))}_onSessionError(e){e.id===this.activeSessionId&&this.terminal.writeln(`\x1B[1;31m Error: ${e.error}\x1B[0m`),this._notifySession(e.id,"critical","session-error","Session Error",e.error||"Unknown error")}_onSessionExit(e){this._wsSessionId===e.id&&this._disconnectWs();const t=this.sessions.get(e.id);t&&(t.status="stopped",this.renderSessionTabs(),e.id===this.activeSessionId&&this._updateLocalEchoState()),e.code&&e.code!==0&&this._notifySession(e.id,"critical","session-crash","Session Crashed",`Exited with code ${e.code}`)}_onSessionIdle(e){const t=this.sessions.get(e.id);if(t&&(t.status="idle",this.renderSessionTabs(),this.sendPendingCtrlL(e.id),e.id===this.activeSessionId&&this._updateLocalEchoState()),!this.respawnStatus[e.id]?.enabled){const s=this.notificationManager?.preferences?.stuckThresholdMs||6e5;clearTimeout(this.idleTimers.get(e.id)),this.idleTimers.set(e.id,setTimeout(()=>{this._notifySession(e.id,"warning","session-stuck","Session Idle",`Idle for ${Math.round(s/6e4)}+ minutes`),this.idleTimers.delete(e.id)},s))}}_onSessionWorking(e){const t=this.sessions.get(e.id);t&&(t.status="busy",this.pendingHooks.has(e.id)||this.tabAlerts.delete(e.id),this.renderSessionTabs(),this.sendPendingCtrlL(e.id),e.id===this.activeSessionId&&this._updateLocalEchoState());const s=this.idleTimers.get(e.id);s&&(clearTimeout(s),this.idleTimers.delete(e.id))}_onSessionAutoClear(e){e.sessionId===this.activeSessionId&&(this.showToast(`Auto-cleared at ${e.tokens.toLocaleString()} tokens`,"info"),this.updateRespawnTokens(0)),this._notifySession(e.sessionId,"info","auto-clear","Auto-Cleared",`Context reset at ${(e.tokens||0).toLocaleString()} tokens`)}_onSessionLimitPauseScheduled(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=e.resumeAt);const s=new Date(e.resumeAt).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});e.sessionId===this.activeSessionId&&this.showToast(`Usage limit reached \u2014 auto-resume at ${s}`,"warning"),this._notifySession(e.sessionId,"warning","limit-pause","Usage Limit Reached",`Auto-resume scheduled for ${s}`),this.updateAutoResumeStatus(e.sessionId)}_onSessionLimitResume(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=void 0),e.sessionId===this.activeSessionId&&this.showToast("Usage limit reset \u2014 work resumed automatically","success"),this._notifySession(e.sessionId,"info","limit-resume","Auto-Resumed","Usage limit reset \u2014 continuing work"),this.updateAutoResumeStatus(e.sessionId)}_onSessionLimitResumeCancelled(e){const t=this.sessions.get(e.sessionId);t&&(t.autoResumeAt=void 0),this.updateAutoResumeStatus(e.sessionId)}_onSessionRespawnBreakerTripped(e){const s=this.sessions.get(e.sessionId)?.name||"Session";this.showToast?.(`${s} stopped: repeated crashes detected. Restart to retry.`,"error")}_onSessionCliInfo(e){const t=this.sessions.get(e.sessionId);t&&(e.version&&(t.cliVersion=e.version),e.model&&(t.cliModel=e.model),e.accountType&&(t.cliAccountType=e.accountType),e.latestVersion&&(t.cliLatestVersion=e.latestVersion)),e.sessionId===this.activeSessionId&&this.updateCliInfoDisplay()}_onSessionStatusTelemetry(e){this.updatePlanUsageChip(e);try{localStorage.setItem("codeman:planUsage",JSON.stringify({t:Date.now(),data:e}))}catch{}}restorePlanUsageChip(){try{const e=localStorage.getItem("codeman:planUsage");if(!e)return;const t=JSON.parse(e);t?.data&&Date.now()-(t.t||0)<12*3600*1e3&&this.updatePlanUsageChip(t.data)}catch{}}updatePlanUsageChip(e){const t=document.getElementById("planUsageChip");if(!t||!e)return;const s=l=>l&&typeof l.usedPercentage=="number"?Math.round(l.usedPercentage):null,i=s(e.fiveHour),n=s(e.sevenDay);if(i===null&&n===null)return;const o=l=>l>=85?"pu-red":l>=60?"pu-yellow":"pu-green",a=(l,c)=>{if(c===null)return"";const h=Math.round(Number(c));return Number.isFinite(h)?`<span class="pu-win"><span class="pu-label">${l}</span><span class="pu-val ${o(h)}">${h}%</span></span>`:""};t.innerHTML=[a("5h",i),a("7d",n)].filter(Boolean).join('<span class="pu-sep">\xB7</span>');const r=l=>l&&l.resetAt?new Date(l.resetAt).toLocaleString():"\u2014";t.title=`Claude plan usage
|
|
15
15
|
5-hour limit: ${i??"\u2014"}% used (resets ${r(e.fiveHour)})
|
|
16
16
|
Weekly limit: ${n??"\u2014"}% used (resets ${r(e.sevenDay)})`}_onScheduledCreated(e){this.currentRun=e,this.showTimer()}_onScheduledUpdated(e){this.currentRun=e,this.updateTimer()}_onScheduledCompleted(e){this.currentRun=e,this.hideTimer(),this.showToast("Scheduled run completed!","success")}_onScheduledStopped(){this.currentRun=null,this.hideTimer()}setConnectionStatus(e){this._connectionStatus=e,e==="connected"?(this._connDownSince=null,this._nextSseRetryAt=null,this._offlineOverlayDismissed=!1):this._connDownSince===null&&(this._connDownSince=Date.now()),this._updateConnectionIndicator(),this._updateConnectionLossUi(),e==="connected"&&this._redeliverSweep()}_connectWs(e){this._disconnectWs(),this._wsState="connecting",this._updateConnectionIndicator();const t=location.protocol==="https:"?"wss:":"ws:",s=this._clientId?`${this._clientId}:${this._wsTabNonce}`:"",i=s?`?cid=${encodeURIComponent(s)}`:"",n=`${t}//${location.host}/ws/sessions/${e}/terminal${i}`,o=new WebSocket(n);this._ws=o,this._wsSessionId=e,o.onopen=()=>{this._ws===o&&(this._wsReady=!0,this._wsState="connected",this._wsReconnectAttempts=0,this._updateConnectionIndicator(),this.sendResize(e)?.catch?.(()=>{}),this._startMobileResizeRetry(e),this._onWsReady(e))},o.onmessage=a=>{if(this._ws===o){this._wsLastRecvAt=Date.now();try{const r=JSON.parse(a.data);r.t==="o"?this._onSessionTerminal({id:e,data:r.d}):r.t==="c"?this._onSessionClearTerminal({id:e}):r.t==="r"?this._onSessionNeedsRefresh({id:e}):r.t==="ia"&&this._onWsInputAck(r.seq)}catch{}}},o.onclose=a=>{if(this._ws!==o)return;this._ws=null,this._wsSessionId=null,this._wsReady=!1,this._stopMobileResizeRetry();const r=window.CodemanWsReconnect.plan(a.code,this._wsReconnectAttempts||0);_crashDiag.log(`WS CLOSE code=${a.code} reason=${a.reason||""} action=${r.action} attempts=${this._wsReconnectAttempts||0}`);const l=this.activeSessionId===e;if(r.action==="give-up")this._wsState=l?"fallback":"disconnected",this._updateConnectionIndicator();else if(r.action==="reconnect")if(l){this._wsState="reconnecting",this._updateConnectionIndicator();const c=r.delayMs+Math.floor(Math.random()*250);this._wsReconnectAttempts=(this._wsReconnectAttempts||0)+1,this._wsReconnectTimer=setTimeout(()=>{this._wsReconnectTimer=null,this.activeSessionId===e&&this._connectWs(e)},c)}else this._wsState="disconnected",this._updateConnectionIndicator();else this._wsState=l?"fallback":"disconnected",this._updateConnectionIndicator(),l&&(this._wsReconnectAttempts=(this._wsReconnectAttempts||0)+1,this._wsReconnectTimer=setTimeout(()=>{this._wsReconnectTimer=null,this.activeSessionId===e&&this._connectWs(e)},r.delayMs))},o.onerror=()=>{}}_disconnectWs(){this._clearTimer("_wsReconnectTimer"),this._wsState="disconnected",this._stopMobileResizeRetry(),this._ws&&(this._ws.onclose=null,this._ws.close(),this._ws=null,this._wsSessionId=null,this._wsReady=!1)}_startMobileResizeRetry(e){this._stopMobileResizeRetry(),(typeof MobileDetection<"u"&&MobileDetection.getDeviceType?MobileDetection.getDeviceType():"desktop")!=="desktop"&&(this._mobileResizeRetryTimer=setInterval(()=>{document.visibilityState==="visible"&&(!this._wsReady||this._wsSessionId!==e||typeof KeyboardHandler<"u"&&KeyboardHandler.keyboardVisible||this.sendResize(e)?.catch?.(()=>{}))},MOBILE_RESIZE_RETRY_MS))}_stopMobileResizeRetry(){this._mobileResizeRetryTimer&&(clearInterval(this._mobileResizeRetryTimer),this._mobileResizeRetryTimer=null)}_sendInputAsync(e,t,s){!e||!t||this._reliableSend(e,t,s?.useMux===!0)}_sendInputEphemeral(e,t){if(!(!e||!t)){if(this._ws&&this._ws.readyState===WebSocket.OPEN&&this._wsSessionId===e)try{this._ws.send(JSON.stringify({t:"i",d:t}));return}catch{}try{fetch(`/api/sessions/${e}/input`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input:t}),keepalive:!0}).catch(()=>{})}catch{}}}_reliableSend(e,t,s){const n={seq:this._nextSeq(e),data:t,useMux:!!s,ts:Date.now(),tries:0,sentAt:0};let o=this._pendingDeliveries.get(e);o||(o=[],this._pendingDeliveries.set(e,o)),o.push(n),this._persistReliableState(),this._updateConnectionIndicator(),this._drainSession(e)}_nextSeq(e){const t=(this._seqCounters.get(e)||0)+1;return this._seqCounters.set(e,t),t}_drainSession(e){const t=this._pendingDeliveries.get(e);if(!(!t||t.length===0)){if(this._ws&&this._ws.readyState===WebSocket.OPEN&&this._wsSessionId===e){for(const s of t)if(s.sentAt===0)try{this._ws.send(JSON.stringify({t:"i",d:s.data,seq:s.seq,cid:this._clientId})),s.sentAt=Date.now(),s.tries++}catch{break}return}this._postDraining.has(e)||(this._postDraining.add(e),(async()=>{try{for(;;){const s=this._pendingDeliveries.get(e);if(!s||s.length===0||this._ws&&this._ws.readyState===WebSocket.OPEN&&this._wsSessionId===e)break;const i=s[0];i.tries++,i.sentAt=Date.now();let n=null;try{const o={input:i.data,seq:i.seq,clientId:this._clientId};i.useMux&&(o.useMux=!0),n=await fetch(`/api/sessions/${e}/input`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o),keepalive:i.data.length<65536})}catch{n=null}if(n&&n.ok)this._ackDelivery(e,i.seq);else if(n&&(n.status===404||n.status===410))this._ackDelivery(e,i.seq);else break}}finally{this._postDraining.delete(e)}})())}}_ackDelivery(e,t){const s=this._pendingDeliveries.get(e);if(s){const i=s.findIndex(n=>n.seq===t);i!==-1&&(s.splice(i,1),s.length===0&&this._pendingDeliveries.delete(e),this._pendingDeliveries.size===0?this._persistReliableNow():this._persistReliableState(),this._updateConnectionIndicator())}this.markIdleAlertSeen?.(e)}_onWsInputAck(e){this._wsSessionId&&Number.isInteger(e)&&this._ackDelivery(this._wsSessionId,e)}_onWsReady(e){const t=this._pendingDeliveries.get(e);if(t)for(const s of t)s.sentAt=0;this._drainSession(e)}_redeliverSweep(){if(this._pendingDeliveries.size!==0)for(const e of[...this._pendingDeliveries.keys()]){const t=this._pendingDeliveries.get(e);if(!t||t.length===0)continue;if(this._ws&&this._ws.readyState===WebSocket.OPEN&&this._wsSessionId===e){const i=t[0],n=i&&i.sentAt&&Date.now()-i.sentAt>this._reliableAckTimeoutMs,o=Date.now()-this._wsLastRecvAt>this._reliableAckTimeoutMs;if(n&&o){try{this._ws.close()}catch{}continue}if(n)for(const a of t)a.sentAt&&Date.now()-a.sentAt>this._reliableAckTimeoutMs&&(a.sentAt=0)}this._drainSession(e)}}_pendingBytes(){let e=0,t=0;for(const s of this._pendingDeliveries.values())for(const i of s)e+=i.data.length,t++;return{bytes:e,count:t}}_loadReliableState(){try{this._clientId=localStorage.getItem("codeman:clientId")||""}catch{this._clientId=""}if(!this._clientId){this._clientId="c-"+Math.random().toString(36).slice(2)+"-"+Date.now().toString(36);try{localStorage.setItem("codeman:clientId",this._clientId)}catch{}}try{const e=localStorage.getItem("codeman:pendingInput");if(!e)return;const t=JSON.parse(e);if(t&&t.seqs)for(const[s,i]of Object.entries(t.seqs))Number.isFinite(i)&&this._seqCounters.set(s,i);if(t&&t.pending)for(const[s,i]of Object.entries(t.pending))Array.isArray(i)&&i.length&&this._pendingDeliveries.set(s,i.filter(n=>n&&typeof n.data=="string"&&Number.isInteger(n.seq)).map(n=>({seq:n.seq,data:n.data,useMux:!!n.useMux,ts:n.ts||Date.now(),tries:0,sentAt:0})))}catch{}}_persistReliableState(){this._persistReliableTimer||(this._persistReliableTimer=setTimeout(()=>{this._persistReliableTimer=null,this._persistReliableNow()},250))}_persistReliableNow(){this._persistReliableTimer&&(clearTimeout(this._persistReliableTimer),this._persistReliableTimer=null);try{const e={};for(const[n,o]of this._seqCounters)e[n]=o;const t={};let s=0;for(const[n,o]of this._pendingDeliveries)if(o.length){t[n]=o.map(a=>({seq:a.seq,data:a.data,useMux:a.useMux,ts:a.ts,tries:a.tries}));for(const a of o)s+=a.data.length}const i=s>this._reliableMaxBytes?{seqs:e}:{seqs:e,pending:t};localStorage.setItem("codeman:pendingInput",JSON.stringify(i))}catch{}}_computeConnectionDescriptor(){const{bytes:e,count:t}=this._pendingBytes(),s=t>0,n=e>4,o=r=>r<1024?`${r}B`:`${(r/1024).toFixed(1)}KB`,a=n?` \xB7 ${o(e)} queued`:"";if(!this.isOnline||this._connectionStatus==="offline")return{display:"flex",dotClass:"connection-dot offline",text:n?`Offline (${o(e)} queued)`:"Offline",title:"No network connection"};if(this.activeSessionId){let r,l,c;switch(this._wsState){case"connected":r="connected",l="WS",c="Terminal connected over WebSocket";break;case"fallback":r="fallback",l="HTTP",c="WebSocket unavailable \u2014 input sent over HTTP";break;case"reconnecting":r="reconnecting",l="WS\u2026",c="Reconnecting WebSocket";break;default:r="reconnecting",l="WS\u2026",c="Connecting WebSocket";break}return{display:"flex",dotClass:`connection-dot ${r}`,text:`${l}${a}`,title:c}}return this._connectionStatus==="reconnecting"||this._connectionStatus==="disconnected"?{display:"flex",dotClass:"connection-dot reconnecting",text:n?`Reconnecting (${o(e)} queued)`:"Reconnecting...",title:"Reconnecting to server"}:s?{display:"flex",dotClass:"connection-dot draining",text:n?`Sending ${o(e)}...`:"Sending...",title:"Delivering queued input"}:{display:"none",dotClass:"",text:"",title:""}}_updateConnectionIndicator(){const e=this.$("connectionIndicator"),t=this.$("connectionDot"),s=this.$("connectionText");if(!e||!t||!s)return;const i=this._computeConnectionDescriptor(),n=this._lastIndicatorDescriptor;n&&n.display===i.display&&n.dotClass===i.dotClass&&n.text===i.text&&n.title===i.title||(this._lastIndicatorDescriptor=i,e.style.display=i.display,i.display!=="none"&&(t.className=i.dotClass,s.textContent=i.text,e.title=i.title))}setupOnlineDetection(){window.addEventListener("online",()=>{this.isOnline=!0,this.reconnectAttempts=0,this._connDownSince=Date.now(),this.connectSSE(),this._redeliverSweep()}),window.addEventListener("offline",()=>{this.isOnline=!1,this.setConnectionStatus("offline")})}_updateConnectionLossUi(){const e=window.CodemanConnectionLoss,t=this.$("offlineBanner"),s=this.$("offlineOverlay");if(!e||!t||!s)return;const i=e.compute({isOnline:this.isOnline,status:this._connectionStatus,everLoaded:this._initGeneration>0,downSince:this._connDownSince,now:Date.now(),nextRetryAt:this._nextSseRetryAt,overlayDismissed:this._offlineOverlayDismissed,retryPending:this._offlineRetryPending});this._connDownSince===null?this._stopOfflineTicker():this._startOfflineTicker();const n=this._offlineRetryPending?"Reconnecting\u2026":i.retryInSec!=null&&i.retryInSec>0?`Retrying in ${i.retryInSec}s`:"Retrying\u2026",o=`${i.mode}|${i.kind}|${n}`;if(o!==this._lastOfflineUiKey){if(this._lastOfflineUiKey=o,t.hidden=i.mode!=="banner",s.hidden=i.mode!=="overlay",document.body.classList.toggle("connection-lost",i.mode!=="hidden"),i.mode==="banner"){const a=this.$("offlineBannerText"),r=this.$("offlineBannerDetail");a&&(a.textContent=i.title),r&&(r.textContent=n)}else if(i.mode==="overlay"){const a=this.$("offlineOverlayTitle"),r=this.$("offlineOverlayBody"),l=this.$("offlineOverlayHost"),c=this.$("offlineOverlayStatus");a&&(a.textContent=i.title),r&&(r.textContent=i.detail),l&&(l.textContent=location.host),c&&(c.textContent=n)}}}_startOfflineTicker(){this._offlineUiTicker||(this._offlineUiTicker=setInterval(()=>this._updateConnectionLossUi(),1e3))}_stopOfflineTicker(){this._offlineUiTicker&&(clearInterval(this._offlineUiTicker),this._offlineUiTicker=null)}retryConnection(){this._offlineRetryPending=!0,this._nextSseRetryAt=null,this.reconnectAttempts=0,this._clearTimer("sseReconnectTimeout"),this.isOnline=navigator.onLine,this._lastOfflineUiKey="",this._updateConnectionLossUi(),this.connectSSE(),this.activeSessionId&&this._wsState!=="connected"&&(this._wsReconnectAttempts=0,this._connectWs(this.activeSessionId)),this._clearTimer("_offlineRetryTimer"),this._offlineRetryTimer=setTimeout(()=>{this._offlineRetryPending=!1,this._lastOfflineUiKey="",this._updateConnectionLossUi()},1500)}dismissOfflineOverlay(){this._offlineOverlayDismissed=!0,this._lastOfflineUiKey="",this._updateConnectionLossUi()}_updateCjkInputState(){const e=document.getElementById("cjkInput");if(!e)return;const t=this.loadAppSettingsFromStorage(),s=this.getDefaultSettings?.()||{},n=(this._serverCjkOverride||(t.cjkInputEnabled??s.cjkInputEnabled??!1))&&!!this.activeSessionId;e.classList.toggle("cjk-input-visible",!!n),document.body.classList.toggle("cjk-input-visible",!!n),e.style.display=n?"block":"none",e.setAttribute("aria-hidden",n?"false":"true"),n||(window.cjkActive=!1),typeof KeyboardHandler<"u"&&KeyboardHandler.updateLayoutForKeyboard()}_resetAllAppState(){this.sessions.clear(),this.ralphStates.clear(),this.terminalBuffers.clear(),this.terminalBufferCache.clear(),this._xtermSnapshots?.clear(),this.projectInsights.clear(),this.teams.clear(),this.teamTasks.clear();for(const e of this.idleTimers.values())clearTimeout(e);if(this.idleTimers.clear(),this._clearTimer("flickerFilterTimeout"),this.flickerFilterBuffer="",this.flickerFilterActive=!1,this._clearTimer("syncWaitTimeout"),this.pendingWrites=[],this.writeFrameScheduled=!1,this._isLoadingBuffer=!1,this._loadBufferQueue=null,this._bufferLoadOwner=null,this._chunkedWriteGen=(this._chunkedWriteGen||0)+1,this._localEchoOverlay?.rerender(),this._predictiveEcho?.clearPredictions(),this.pendingHooks.clear(),this.approvals?.clear(),this._parentNameCache&&this._parentNameCache.clear(),this.subagentActivity.clear(),this.subagentToolResults.clear(),this.workflowRuns&&this.workflowRuns.clear(),this.workflowRunDetails&&this.workflowRunDetails.clear(),this.activeWorkflowRunId=null,this.activeWorkflowPhaseIndex=null,MobileDetection.cleanup(),KeyboardHandler.cleanup(),MobileDetection.init(),KeyboardHandler.init(),this.tabAlerts.clear(),this.attachmentHistoryCounts.clear(),this._shownCompletions&&this._shownCompletions.clear(),this.notificationManager?.titleFlashInterval&&(clearInterval(this.notificationManager.titleFlashInterval),this.notificationManager.titleFlashInterval=null),this.notificationManager?.groupingMap){for(const{timeout:e}of this.notificationManager.groupingMap.values())clearTimeout(e);this.notificationManager.groupingMap.clear()}this.terminalResizeObserver&&(this.terminalResizeObserver.disconnect(),this.terminalResizeObserver=null),this.planLoadingTimer&&(clearInterval(this.planLoadingTimer),this.planLoadingTimer=null),this.timerCountdownInterval&&(clearInterval(this.timerCountdownInterval),this.timerCountdownInterval=null),this.runSummaryAutoRefreshTimer&&(clearInterval(this.runSummaryAutoRefreshTimer),this.runSummaryAutoRefreshTimer=null)}handleInit(e){this._clearTimer("_initFallbackTimer");const t=++this._initGeneration;if(this._serverCjkOverride=e.inputCjkForm||!1,this._updateCjkInputState(),e.planUsage&&this.updatePlanUsageChip(e.planUsage),e.version){const n=this.$("versionDisplay"),o=this.$("headerVersion");n&&(n.textContent=`v${e.version}`,n.title=`Codeman v${e.version}`),o&&(o.textContent=`v${e.version}`,o.title=`Codeman v${e.version}`)}VoiceInput.cleanup(),this._resetAllAppState(),e.sessions.forEach(n=>{this.sessions.set(n.id,n),(n.ralphLoop||n.ralphTodos)&&!this.ralphClosedSessions.has(n.id)&&this.ralphStates.set(n.id,{loop:n.ralphLoop||null,todos:n.ralphTodos||[]})});try{localStorage.removeItem("codeman-tab-meta")}catch{}if(Array.isArray(e.sessionOrder)&&e.sessionOrder.length)try{localStorage.setItem("codeman-session-order",JSON.stringify(e.sessionOrder))}catch{}this.syncSessionOrder(),e.respawnStatus?this.respawnStatus=e.respawnStatus:this.respawnStatus={},this.respawnTimers={},this.respawnCountdownTimers={},this.respawnActionLogs={},e.globalStats&&(this.globalStats=e.globalStats),this.totalCost=e.sessions.reduce((n,o)=>n+(o.totalCost||0),0),this.totalCost+=e.scheduledRuns.reduce((n,o)=>n+(o.totalCost||0),0);const s=e.scheduledRuns.find(n=>n.status==="running");if(s&&(this.currentRun=s,this.showTimer()),this.updateCost(),this.renderSessionTabs(),this.seedApprovals?.(),this.sessions.size>0?this.startSystemStatsPolling():this.stopSystemStatsPolling(),this.cleanupAllFloatingWindows(),e.subagents&&(this.subagents.clear(),this.subagentActivity.clear(),this.subagentToolResults.clear(),e.subagents.forEach(n=>{this.subagents.set(n.agentId,n)}),this.renderSubagentPanel(),this.subagentParentMap.clear(),this.loadSubagentParentMap().then(()=>{for(const[n,o]of this.subagentParentMap){const a=this.subagents.get(n);if(a&&this.sessions.has(o)){a.parentSessionId=o;const r=this.sessions.get(o);r&&(a.parentSessionName=this.getSessionName(r)),this.subagents.set(n,a)}}for(const[n]of this.subagents)this.subagentParentMap.has(n)||this.findParentSessionForSubagent(n);this.restoreSubagentWindowStates()})),e.workflowRuns&&this.seedWorkflowRuns(e.workflowRuns),t!==this._initGeneration)return;if(this.isSoloWindow){this._applySoloMode();return}const i=this.activeSessionId;if(this.activeSessionId=null,this.sessionOrder.length>0){let n=i;if(!n||!this.sessions.has(n))try{n=localStorage.getItem("codeman-active-session")}catch{}n&&this.sessions.has(n)?this.selectSession(n,{auto:!0}):this.selectSession(this.sessionOrder[0],{auto:!0})}}async loadState(){try{const t=await(await fetch("/api/status")).json();this.handleInit(t?.data??{})}catch(e){console.error("Failed to load state:",e)}}_debouncedCall(e,t,s=100){this._debounceTimers[e]&&clearTimeout(this._debounceTimers[e]),this._debounceTimers[e]=setTimeout(()=>{this._debounceTimers[e]=null,t.call(this)},s)}getSessionListLayout(){if(this.soloSessionId)return"header";const e=this.loadAppSettingsFromStorage(),t=this.getDefaultSettings(),s=e.sessionListLayout??t.sessionListLayout??"header";return s==="sidebar"||s==="sidebar-rich"?s:"header"}isSessionSidebarActive(){return document.documentElement.dataset.sessionList==="sidebar"}isSessionSidebarRich(){const e=document.documentElement;return e.dataset.sessionList==="sidebar"&&e.dataset.sidebarDetail==="rich"}_isSessionSidebarOverlay(){return window.innerWidth<1024}isSessionSidebarCollapsed(){if(this._sidebarCollapsedOverride!==void 0)return this._sidebarCollapsedOverride;let e=null;try{e=localStorage.getItem("codeman-sidebar-collapsed")}catch{}return e===null?this._isSessionSidebarOverlay():e==="1"}shouldToggleSessionSidebarFromShortcut(e){if(!e||!e.ctrlKey&&!e.metaKey&&!e.altKey||!this.isSessionSidebarActive()||typeof this.getShortcutRegistry!="function"||typeof this.matchesShortcutEvent!="function")return!1;const t=this.getShortcutRegistry().find(s=>s.id==="toggle-session-sidebar");return!t||t.disabled?!1:this.matchesShortcutEvent(e,t)}applySessionListLayout(){const e=this.getSessionListLayout(),t=e==="sidebar"||e==="sidebar-rich",s=this.isSessionSidebarCollapsed(),i=document.documentElement.dataset.sessionList,n=document.documentElement.dataset.sidebarDetail,o=document.getElementById("sessionTabs"),a=document.getElementById("sessionTabsHost"),r=document.getElementById("sessionSidebarList");if(!o||!a||!r)return;const l=t?r:a;o.parentElement!==l&&l.appendChild(o),document.documentElement.dataset.sessionList=t?"sidebar":"header",document.documentElement.dataset.sidebarDetail=e==="sidebar-rich"?"rich":"simple",document.documentElement.dataset.sidebar=s?"collapsed":"expanded",o.setAttribute("aria-orientation",t?"vertical":"horizontal");const c=document.getElementById("sidebarToggleBtn");if(c){c.classList.toggle("btn-sidebar-toggle--hidden",!t);const S=s?"Expand session sidebar":"Collapse session sidebar";c.setAttribute("aria-expanded",s?"false":"true"),c.setAttribute("aria-label",S),c.setAttribute("title",S)}const h=document.getElementById("sessionSidebar");if(h){h.classList.toggle("open",t&&!s);const S=t&&s&&this._isSessionSidebarOverlay();h.toggleAttribute("inert",S),S?h.setAttribute("aria-hidden","true"):h.removeAttribute("aria-hidden")}if(!t){this._sidebarFilter="";const S=document.getElementById("sessionSidebarFilter");S&&(S.value="")}const d=this._tallTabsEnabled;this.applyTabWrapSettings(),(i!==document.documentElement.dataset.sessionList||n!==document.documentElement.dataset.sidebarDetail)&&d===this._tallTabsEnabled&&this._fullRenderSessionTabs(),t&&o.classList.remove("tabs-auto-wrap"),this.applySidebarFilter(this._sidebarFilter),this.updateConnectionLines(),document.getElementById("welcomeOverlay")?.classList.contains("visible")&&this.showHomeSessions?.(),this.isSessionSidebarRich()?this._startSidebarRichClock():this._stopSidebarRichClock()}toggleSessionSidebar(){if(!this.isSessionSidebarActive())return;const e=!this.isSessionSidebarCollapsed();this._sidebarCollapsedOverride=e;try{localStorage.setItem("codeman-sidebar-collapsed",e?"1":"0")}catch{}e&&this.$("sessionSidebar")?.contains(document.activeElement)&&document.getElementById("sidebarToggleBtn")?.focus(),this.applySessionListLayout(),!e&&this._isSessionSidebarOverlay()&&this.$("sessionTabs")?.querySelector(".session-tab.active")?.focus()}closeSessionSidebarOnHandheld(){this._isSessionSidebarOverlay()&&(!this.isSessionSidebarActive()||this.isSessionSidebarCollapsed()||this.toggleSessionSidebar())}updateSidebarCount(){const e=document.getElementById("sessionSidebarCount");if(!e)return;const t=this.$("sessionTabs"),s=t?t.querySelectorAll(".session-tab:not(.tab-filtered-out)").length:this.sessions?.size??0;e.textContent=String(s)}applySidebarFilter(e){this._sidebarFilter=(e??"").trim().toLowerCase();const t=this.$("sessionTabs");if(!t)return;const i=this.isSessionSidebarActive()&&document.documentElement.dataset.sidebar!=="collapsed"?this._sidebarFilter:"";for(const n of t.querySelectorAll(".session-tab")){if(!i){n.classList.remove("tab-filtered-out");continue}const o=`${n.getAttribute("aria-label")||""} ${n.getAttribute("title")||""}`.toLowerCase();n.classList.toggle("tab-filtered-out",!o.includes(i))}this.updateSidebarCount()}_sidebarRichPillLabel(e){return{needs:"needs you",error:"error",waiting:"waiting",working:"working",idle:"idle",done:"done"}[e]||e}_sidebarRichRow(e,t){if(typeof this._mobileOverviewState!="function")return null;const s=this._mobileOverviewState(t,this.pendingHooks?.get(e));return{state:s,pill:this._sidebarRichPillLabel(s),createdAt:Number(t.createdAt)||0,since:this._mobileOverviewSince?this._mobileOverviewSince(s,t):null}}_sidebarRichMetaHTML(e){if(!e)return"";const t=(i,n,o,a)=>{const r=this._sidebarRichStampText(n,o),l=n?` title="${escapeHtml(`${i==="created"?"First created":i}: ${new Date(n).toLocaleString()}`)}"`:"";return`<span class="tab-meta-item ${a}"${l}><span class="tab-meta-key">${escapeHtml(i)}</span><span data-tab-ts="${n||0}" data-tab-fmt="${o}">${escapeHtml(r)}</span></span>`},s=[t("created",e.createdAt,"ago","tab-meta-created")];return e.since&&(s.push('<span class="tab-meta-sep" aria-hidden="true">\xB7</span>'),s.push(t(e.since.key,e.since.at,"for","tab-meta-since"))),s.push(`<span class="tab-pill tab-pill--${escapeHtml(e.state)}">${escapeHtml(e.pill)}</span>`),`<span class="tab-meta" data-i18n-skip>${s.join("")}</span>`}_sidebarRichStampText(e,t){return this._mobileOverviewStampText?this._mobileOverviewStampText(e,t):"\u2014"}_updateSidebarRichRow(e,t,s){const i=this._sidebarRichRow(t,s);if(!i)return;const n=e.dataset.tabState,o=`${i.state}:${i.since?i.since.at:0}:${i.createdAt}`;if(e.dataset.tabMetaSig===o)return;e.dataset.tabMetaSig=o,e.dataset.tabState=i.state,n&&e.classList.remove(`tab-state-${n}`),e.classList.add(`tab-state-${i.state}`);const a=e.querySelector(".tab-info");if(!a)return;const r=this._sidebarRichMetaHTML(i),l=a.querySelector(".tab-meta");l?l.outerHTML=r:a.insertAdjacentHTML("beforeend",r)}_startSidebarRichClock(){this._sidebarRichClock||(this._sidebarRichClock=setInterval(()=>{if(!this.isSessionSidebarRich()){this._stopSidebarRichClock();return}this._tickSidebarRichTimes()},SIDEBAR_RICH_CLOCK_MS))}_stopSidebarRichClock(){this._sidebarRichClock&&(clearInterval(this._sidebarRichClock),this._sidebarRichClock=null)}_tickSidebarRichTimes(){const e=this.$("sessionTabs");if(e)for(const t of e.querySelectorAll("[data-tab-ts]")){const s=this._sidebarRichStampText(Number(t.dataset.tabTs)||0,t.dataset.tabFmt);t.textContent!==s&&(t.textContent=s)}}renderSessionTabs(){this._inlineRenameActive||this._debouncedCall("sessionTabs",this._renderSessionTabsImmediate)}_updateActiveTabImmediate(e){const t=this.$("sessionTabs");if(!t)return;const s=t.querySelectorAll(".session-tab[data-id]");for(const i of s)i.dataset.id===e?i.classList.add("active"):i.classList.remove("active");this._scrollActiveTabIntoView(e)}_scrollActiveTabIntoView(e,t="smooth"){const s=this.$("sessionTabs");if(!s)return;const i=e&&s.querySelector(`.session-tab[data-id="${e}"]`)||s.querySelector(".session-tab.active");if(!i)return;if(this.isSessionSidebarActive()){i.scrollIntoView({block:"nearest"});return}const n=window.CodemanTabOverflow?.computeTabScrollLeft;if(!n)return;const o=s.getBoundingClientRect(),a=i.getBoundingClientRect(),r=n({scrollLeft:s.scrollLeft,clientWidth:s.clientWidth,scrollWidth:s.scrollWidth,tabLeft:a.left-o.left+s.scrollLeft,tabWidth:a.width});if(Math.abs(r-s.scrollLeft)<1)return;const l=window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;typeof s.scrollTo=="function"?s.scrollTo({left:r,behavior:l?"auto":t}):s.scrollLeft=r}_tabAnchor(e){return this.isSessionSidebarActive()?{x:e.right,y:e.top+e.height/2,spawnLeft:e.right+14,spawnTop:e.top,vertical:!1}:{x:e.left+e.width/2,y:e.bottom,spawnLeft:e.left,spawnTop:e.bottom,vertical:!0}}_tabConnectorPath(e,t){if(e.vertical){const o=t.left+t.width/2,a=t.top,r=(e.y+a)/2;return`M ${e.x} ${e.y} C ${e.x} ${r}, ${o} ${r}, ${o} ${a}`}const s=t.left,i=t.top+t.height/2,n=(e.x+s)/2;return`M ${e.x} ${e.y} C ${n} ${e.y}, ${n} ${i}, ${s} ${i}`}_setTerminalLoadState(e,t,s){this.terminalLoadStates.set(e,{generation:t,phase:s}),this._updateTerminalLoadTab(e)}_clearTerminalLoadState(e,t){const s=this.terminalLoadStates.get(e);s&&s.generation!==t||(this.terminalLoadStates.delete(e),this._updateTerminalLoadTab(e))}_updateTerminalLoadTab(e){const t=this.$("sessionTabs")?.querySelector(`.session-tab[data-id="${e}"]`);if(!t)return;const s=this.terminalLoadStates.get(e);if(t.classList.toggle("tab-loading",!!s),s){if(t.setAttribute("aria-busy","true"),t.dataset.loadPhase=s.phase,!t.querySelector(".tab-load-spinner")){const i=document.createElement("span");i.className="tab-load-spinner",i.setAttribute("aria-hidden","true");const n=t.querySelector(".tab-number");n?n.insertAdjacentElement("afterend",i):t.insertBefore(i,t.firstChild)}}else t.setAttribute("aria-busy","false"),delete t.dataset.loadPhase,t.querySelector(".tab-load-spinner")?.remove()}_renderSessionTabsImmediate(){if(this._inlineRenameActive)return;const e=this.$("sessionTabs"),t=e.querySelectorAll(".session-tab[data-id]"),s=new Set([...t].map(l=>l.dataset.id)),i=new Set(this.sessions.keys()),n=[...e.querySelectorAll(".session-tab[data-webview-id]")].map(l=>l.dataset.webviewId),o=(this.webviewOrder||[]).filter(l=>this.webviews?.has(l)),a=n.length===o.length&&n.every((l,c)=>l===o[c]);if(s.size===i.size&&[...s].every(l=>i.has(l))&&a){const l=this.isSessionSidebarRich();for(const[c,h]of this.sessions){const d=e.querySelector(`.session-tab[data-id="${c}"]`);if(!d)continue;const _=c===this.activeSessionId&&!this.activeWebviewId,S=h.status||"idle",T=this.getSessionName(h),R=h.taskStats||{running:0,total:0},C=R.running>0,L=this.terminalLoadStates.get(c);if(_&&!d.classList.contains("active")?d.classList.add("active"):!_&&d.classList.contains("active")&&d.classList.remove("active"),d.classList.toggle("tab-loading",!!L),L){if(d.setAttribute("aria-busy","true"),d.dataset.loadPhase=L.phase,!d.querySelector(".tab-load-spinner")){const f=document.createElement("span");f.className="tab-load-spinner",f.setAttribute("aria-hidden","true");const g=d.querySelector(".tab-number");g?g.insertAdjacentElement("afterend",f):d.insertBefore(f,d.firstChild)}}else d.setAttribute("aria-busy","false"),delete d.dataset.loadPhase,d.querySelector(".tab-load-spinner")?.remove();const A=this.tabAlerts.get(c),N=A==="action",E=A==="idle",k=d.classList.contains("tab-alert-action"),p=d.classList.contains("tab-alert-idle");if(N&&!k?(d.classList.add("tab-alert-action"),d.classList.remove("tab-alert-idle")):E&&!p?(d.classList.add("tab-alert-idle"),d.classList.remove("tab-alert-action")):!A&&(k||p)&&d.classList.remove("tab-alert-action","tab-alert-idle"),!d.querySelector(".tab-number")){const f=this.sessionOrder.indexOf(c);if(f>=0&&f<9){const g=document.createElement("span");g.className="tab-number",g.textContent=String(f+1),d.insertBefore(g,d.firstChild)}}const y=d.querySelector(".tab-status");y&&!y.classList.contains(S)&&(y.className=`tab-status ${S}`),l?this._updateSidebarRichRow(d,c,h):d.dataset.tabState&&(d.querySelector(".tab-meta")?.remove(),d.classList.remove(`tab-state-${d.dataset.tabState}`),delete d.dataset.tabState,delete d.dataset.tabMetaSig);const I=d.querySelector(".tab-name");if(I){const f=parseSessionPrefix(T),g=f&&f.suffix?f.suffix:T;I.textContent!==g&&(I.textContent=g,d.title=f&&f.suffix?h.workingDir?`${f.prefix} (${h.workingDir})`:f.prefix:h.workingDir||"")}const m=d.querySelector(".tab-badge");if(C)if(m)m.textContent!==String(R.running)&&(m.textContent=R.running);else{this._fullRenderSessionTabs();return}else if(m){this._fullRenderSessionTabs();return}const w=d.querySelector(".tab-subagent-badge"),O=this.minimizedSubagents.get(c),b=O?.size||0;if(b>0&&w){const f=w.querySelector(".subagent-label"),g=b===1?"AGENT":`AGENTS (${b})`;f&&f.textContent!==g&&(f.textContent=g);const v=w.querySelector(".subagent-dropdown");if(v){const M=this.renderSubagentTabBadge(c,O),D=document.createElement("div");D.innerHTML=M;const x=D.querySelector(".subagent-dropdown");x&&(v.innerHTML=x.innerHTML)}}else if(b>0&&!w){const f=this.renderSubagentTabBadge(c,O),g=d.querySelector(".tab-actions");g&&g.insertAdjacentHTML("beforebegin",f)}else b===0&&w&&w.remove()}}else this._fullRenderSessionTabs();this._lastRenderedActiveTabId=this.activeSessionId,this.updateTabOverflowMode(),this._applyTabEntrances?.(),this._refreshMobileOverviewIfVisible?.(),this._refreshHomeSessionsIfVisible?.(),(this._lineageEdgeCount>0||this.isSessionSidebarActive())&&this.updateConnectionLines(),this.applySidebarFilter(this._sidebarFilter)}updateTabOverflowMode(){const e=this.$("sessionTabs");if(!e)return;if(this.isSessionSidebarActive()){e.classList.remove("tabs-auto-wrap");return}const t=MobileDetection.getDeviceType(),s=this.loadAppSettingsFromStorage(),i=this.getDefaultSettings(),n=t==="desktop"?s.tabTwoRows??i.tabTwoRows??!1:!1;if(n||t!=="desktop"){e.classList.remove("tabs-auto-wrap");return}e.classList.remove("tabs-auto-wrap");const o=window.CodemanTabOverflow?.shouldAutoWrapTabs?window.CodemanTabOverflow.shouldAutoWrapTabs({deviceType:t,manualTwoRows:n,tabCount:this.sessions.size,scrollWidth:e.scrollWidth,clientWidth:e.clientWidth}):e.scrollWidth>e.clientWidth+1;e.classList.toggle("tabs-auto-wrap",o)}_setupTabMiddleClickClose(){const e=this.$("sessionTabs");!e||this._tabAuxClickBound||(this._tabAuxClickBound=!0,e.addEventListener("auxclick",t=>{if(t.button!==1)return;const s=t.target.closest?.(".session-tab");s&&(t.preventDefault(),t.stopPropagation(),s.dataset.id?this.requestCloseSession(s.dataset.id):s.dataset.webviewId&&this.closeWebviewTab?.(s.dataset.webviewId))}))}_fullRenderSessionTabs(){if(this._inlineRenameActive)return;const e=this.$("sessionTabs");this.isSessionSidebarActive()&&(this._tallTabsEnabled=!0,e.classList.add("tabs-show-folder"),e.classList.remove("tabs-two-rows","tabs-auto-wrap")),document.querySelectorAll("body > .subagent-dropdown").forEach(c=>c.remove()),this.cancelHideSubagentDropdown();const t=e.scrollLeft,s=e.scrollTop,i=this._lastRenderedActiveTabId,n=!e.querySelector(".session-tab"),o=[],a=this.sessionOrder,r=this.isSessionSidebarRich();let l=0;for(const c of a){const h=this.sessions.get(c);if(!h)continue;const d=c===this.activeSessionId&&!this.activeWebviewId,_=h.status||"idle",S=this.getSessionName(h),T=h.mode||"claude",R=h.color||"default",C=h.taskStats||{running:0,total:0},L=C.running>0,A=this.tabAlerts.get(c),N=A==="action"?" tab-alert-action":A==="idle"?" tab-alert-idle":"",E=this.terminalLoadStates.get(c),k=this.minimizedSubagents.get(c),y=(k?.size||0)>0?this.renderSubagentTabBadge(c,k):"",I=this.renderUltracodeTabBadge?this.renderUltracodeTabBadge(c):"",m=h.workingDir&&h.workingDir.split("/").pop()||"",O=(this._tallTabsEnabled??!1)&&h.name&&m&&m!==S,b=parseSessionPrefix(S),f=b&&b.suffix?b.suffix:S,g=b&&b.suffix?h.workingDir?`${b.prefix} (${h.workingDir})`:b.prefix:h.workingDir||"",v=r?this._sidebarRichRow(c,h):null,M=this._sidebarRichMetaHTML(v),D=v?` tab-state-${v.state}`:"",x=v?` data-tab-state="${v.state}" data-tab-meta-sig="${v.state}:${v.since?v.since.at:0}:${v.createdAt}"`:"";o.push(`<div class="session-tab ${d?"active":""}${N}${D}${E?" tab-loading":""}${this.hasTabDetachOverride(c)?" tab-show-detach":""}"${x} data-id="${c}" data-color="${R}" ${E?`data-load-phase="${escapeHtml(E.phase)}"`:""} onclick="app.handleSessionTabClick(event, ${escapeHtml(JSON.stringify(c))})" oncontextmenu="event.preventDefault(); app.startInlineRename(${escapeHtml(JSON.stringify(c))})" tabindex="0" role="tab" aria-selected="${d?"true":"false"}" aria-busy="${E?"true":"false"}" aria-label="${escapeHtml(S)} session" ${g?`title="${escapeHtml(g)}"`:""}>
|
|
17
17
|
${l<9?'<span class="tab-number">'+(l+1)+"</span>":""}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -527,6 +527,41 @@ function sortSessionsByActivity(rows) {
|
|
|
527
527
|
return (Array.isArray(rows) ? rows.slice() : []).sort(compareSessionActivity);
|
|
528
528
|
}
|
|
529
529
|
|
|
530
|
+
// Terminal font stack — the single source for every xterm surface (the main
|
|
531
|
+
// terminal in terminal-ui.js, the log-viewer terminal in panels-ui.js).
|
|
532
|
+
// "Symbols Nerd Font Mono" is a bundled icons-only webfont (fonts/ +
|
|
533
|
+
// @font-face in styles.css): browsers fall back PER GLYPH, so Nerd Font
|
|
534
|
+
// prompt icons (powerline segments, folder/git glyphs from p10k, starship,
|
|
535
|
+
// oh-my-posh) render even though the text fonts carry no private-use-area
|
|
536
|
+
// symbols — while all readable text keeps coming from the text fonts.
|
|
537
|
+
const TERMINAL_FONT_DEFAULT_STACK =
|
|
538
|
+
'"Fira Code", "Cascadia Code", "JetBrains Mono", "SF Mono", Monaco, "Symbols Nerd Font Mono", monospace';
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Resolve the xterm fontFamily from the per-device `terminalFontFamily`
|
|
542
|
+
* setting. A user-set family (or comma-separated list) is PREPENDED to the
|
|
543
|
+
* built-in stack, never a replacement — the symbols fallback and a final
|
|
544
|
+
* `monospace` must survive whatever the user types. Blank input yields the
|
|
545
|
+
* default. Unquoted names that need quoting for CSS (spaces, digits leading,
|
|
546
|
+
* etc.) are quoted; embedded quotes are stripped rather than escaped, since
|
|
547
|
+
* a font name cannot contain them anyway.
|
|
548
|
+
*/
|
|
549
|
+
function resolveTerminalFontFamily(custom) {
|
|
550
|
+
const raw = typeof custom === 'string' ? custom.trim() : '';
|
|
551
|
+
if (!raw) return TERMINAL_FONT_DEFAULT_STACK;
|
|
552
|
+
const families = raw
|
|
553
|
+
.split(',')
|
|
554
|
+
.map((f) => f.trim().replace(/^["']|["']$/g, '').replace(/["']/g, '').trim())
|
|
555
|
+
.filter(Boolean)
|
|
556
|
+
// Drop generic families the user may append — the default stack already
|
|
557
|
+
// ends in `monospace`, and a duplicate earlier entry would shadow the
|
|
558
|
+
// symbols fallback behind it.
|
|
559
|
+
.filter((f) => !/^(monospace|serif|sans-serif|system-ui)$/i.test(f))
|
|
560
|
+
.map((f) => (/^[A-Za-z][A-Za-z0-9-]*$/.test(f) ? f : `"${f}"`));
|
|
561
|
+
if (!families.length) return TERMINAL_FONT_DEFAULT_STACK;
|
|
562
|
+
return `${families.join(', ')}, ${TERMINAL_FONT_DEFAULT_STACK}`;
|
|
563
|
+
}
|
|
564
|
+
|
|
530
565
|
if (typeof window !== 'undefined') {
|
|
531
566
|
window.WEBGL_FALLBACK = WEBGL_FALLBACK;
|
|
532
567
|
window.evaluateWebGLLongTaskTrip = evaluateWebGLLongTaskTrip;
|
|
@@ -560,6 +595,10 @@ if (typeof window !== 'undefined') {
|
|
|
560
595
|
compare: compareSessionActivity,
|
|
561
596
|
sort: sortSessionsByActivity,
|
|
562
597
|
};
|
|
598
|
+
window.CodemanTerminalFont = {
|
|
599
|
+
DEFAULT_STACK: TERMINAL_FONT_DEFAULT_STACK,
|
|
600
|
+
resolve: resolveTerminalFontFamily,
|
|
601
|
+
};
|
|
563
602
|
}
|
|
564
603
|
|
|
565
604
|
// Scheduler API — prioritize terminal writes over background UI updates.
|
|
@@ -1035,7 +1074,112 @@ function previewsInFileViewer(filePath) {
|
|
|
1035
1074
|
return FILE_PREVIEW_EXTENSIONS.has(ext);
|
|
1036
1075
|
}
|
|
1037
1076
|
|
|
1077
|
+
|
|
1078
|
+
/**
|
|
1079
|
+
* The LOGICAL line a terminal row belongs to — the rows it spans, its text as one
|
|
1080
|
+
* string, and a two-way map between that string and terminal cells.
|
|
1081
|
+
*
|
|
1082
|
+
* One definition, two consumers: the link provider matches its patterns over this
|
|
1083
|
+
* text (`registerFilePathLinkProvider`) and touch selection measures words and
|
|
1084
|
+
* whole lines with it (`_touchSelectionLogicalLine`). They MUST agree — a link that
|
|
1085
|
+
* spans a wrap and a "Line" that stops at the screen edge is the same bug twice.
|
|
1086
|
+
*
|
|
1087
|
+
* Two kinds of continuation, and handling only the first is not enough:
|
|
1088
|
+
*
|
|
1089
|
+
* 1. **Soft wrap** — the emulator ran out of columns and flags the next row
|
|
1090
|
+
* `isWrapped`. It inserts nothing, so the row's text is joined verbatim.
|
|
1091
|
+
* 2. **Hard wrap** — the program wrapped the text itself and emitted a real
|
|
1092
|
+
* newline, so nothing is flagged. A row that fills the last column is taken
|
|
1093
|
+
* as continuing into the next; that is the only trace a hard wrap leaves.
|
|
1094
|
+
*
|
|
1095
|
+
* ⚠️ A hard-wrapped continuation may carry the program's own INDENT, and joining
|
|
1096
|
+
* that verbatim puts whitespace in the middle of the token being stitched. That is
|
|
1097
|
+
* why an agent's numbered list —
|
|
1098
|
+
*
|
|
1099
|
+
* 1. https://github.com/users/someone/packages/container/p
|
|
1100
|
+
* ackage/thing
|
|
1101
|
+
*
|
|
1102
|
+
* — opened only `…/container/p`: the URL pattern stops at the space the indent
|
|
1103
|
+
* contributed. So the leading whitespace of a HARD continuation is dropped, and
|
|
1104
|
+
* `colStart` on that segment records how much, keeping the cell mapping exact. A
|
|
1105
|
+
* soft continuation keeps its leading whitespace, since the terminal never adds
|
|
1106
|
+
* any and it is therefore real content.
|
|
1107
|
+
*
|
|
1108
|
+
* ⚠️ Only the final row is trimmed. Continuation rows are read UNTRIMMED so each
|
|
1109
|
+
* contributes exactly `cols` cells; trimming one would shift every later offset.
|
|
1110
|
+
*
|
|
1111
|
+
* The row span is bounded by `maxRows` (12 by default): this runs on every hover,
|
|
1112
|
+
* and a screenful of full-width output would otherwise re-scan the viewport each
|
|
1113
|
+
* time.
|
|
1114
|
+
*
|
|
1115
|
+
* @param {{getLine: (row: number) => any, length: number}} buffer xterm buffer.
|
|
1116
|
+
* @param {number} row 0-based ABSOLUTE buffer row to expand around.
|
|
1117
|
+
* @param {number} cols Terminal width.
|
|
1118
|
+
* @param {number} [maxRows] Row-span bound.
|
|
1119
|
+
* @returns {{startRow: number, endRow: number, text: string,
|
|
1120
|
+
* offsetToCell: (offset: number) => {row: number, col: number},
|
|
1121
|
+
* cellToOffset: (row: number, col: number) => number} | null}
|
|
1122
|
+
* 0-based rows and columns throughout; null when the row does not exist.
|
|
1123
|
+
*/
|
|
1124
|
+
function terminalLogicalLine(buffer, row, cols, maxRows) {
|
|
1125
|
+
if (!buffer || typeof buffer.getLine !== 'function') return null;
|
|
1126
|
+
const width = Math.max(1, cols || 1);
|
|
1127
|
+
const bound = Math.max(1, maxRows || 12);
|
|
1128
|
+
const lineAt = (r) => (r >= 0 ? buffer.getLine(r) : undefined);
|
|
1129
|
+
if (!lineAt(row)) return null;
|
|
1130
|
+
|
|
1131
|
+
const continuesPrevious = (r) => {
|
|
1132
|
+
if (r <= 0) return false;
|
|
1133
|
+
if (lineAt(r)?.isWrapped) return true;
|
|
1134
|
+
const prev = lineAt(r - 1);
|
|
1135
|
+
return !!prev && (prev.translateToString(true) || '').length >= width;
|
|
1136
|
+
};
|
|
1137
|
+
|
|
1138
|
+
let startRow = row;
|
|
1139
|
+
while (startRow > 0 && row - startRow < bound && continuesPrevious(startRow)) startRow--;
|
|
1140
|
+
let endRow = row;
|
|
1141
|
+
const length = Number.isFinite(buffer.length) ? buffer.length : endRow + 1;
|
|
1142
|
+
while (endRow + 1 < length && endRow - startRow < bound && continuesPrevious(endRow + 1)) endRow++;
|
|
1143
|
+
|
|
1144
|
+
const segments = [];
|
|
1145
|
+
let text = '';
|
|
1146
|
+
for (let r = startRow; r <= endRow; r++) {
|
|
1147
|
+
const line = lineAt(r);
|
|
1148
|
+
if (!line) break;
|
|
1149
|
+
let rowText = line.translateToString(r === endRow) || '';
|
|
1150
|
+
let colStart = 0;
|
|
1151
|
+
if (r > startRow && !line.isWrapped) {
|
|
1152
|
+
const indent = rowText.length - rowText.replace(/^\s+/, '').length;
|
|
1153
|
+
colStart = indent;
|
|
1154
|
+
rowText = rowText.slice(indent);
|
|
1155
|
+
}
|
|
1156
|
+
segments.push({ row: r, textStart: text.length, colStart, length: rowText.length });
|
|
1157
|
+
text += rowText;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
const offsetToCell = (offset) => {
|
|
1161
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
1162
|
+
const seg = segments[i];
|
|
1163
|
+
if (offset >= seg.textStart || i === 0) {
|
|
1164
|
+
return { row: seg.row, col: seg.colStart + (offset - seg.textStart) };
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
return { row: startRow, col: offset };
|
|
1168
|
+
};
|
|
1169
|
+
|
|
1170
|
+
const cellToOffset = (targetRow, targetCol) => {
|
|
1171
|
+
for (const seg of segments) {
|
|
1172
|
+
if (seg.row !== targetRow) continue;
|
|
1173
|
+
return seg.textStart + Math.max(0, targetCol - seg.colStart);
|
|
1174
|
+
}
|
|
1175
|
+
return -1;
|
|
1176
|
+
};
|
|
1177
|
+
|
|
1178
|
+
return { startRow, endRow, text, offsetToCell, cellToOffset };
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1038
1181
|
if (typeof window !== 'undefined') {
|
|
1039
1182
|
window.CodemanHistoryFormat = { formatHistoryBytes, computeHistoryTruncationNotice, computeRewriteScrollLine };
|
|
1040
1183
|
window.CodemanFilePaths = { absoluteFilePathPattern, previewsInFileViewer, FILE_PREVIEW_EXTENSIONS };
|
|
1184
|
+
window.CodemanTerminalLines = { terminalLogicalLine };
|
|
1041
1185
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014 Ryan L McIntyre
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
Binary file
|
|
Binary file
|