aicodeman 1.28.2 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +1 -1
  2. package/dist/attachment-registry.d.ts +20 -0
  3. package/dist/attachment-registry.d.ts.map +1 -1
  4. package/dist/attachment-registry.js +75 -10
  5. package/dist/attachment-registry.js.map +1 -1
  6. package/dist/config/cli-registry/schema.d.ts +25 -0
  7. package/dist/config/cli-registry/schema.d.ts.map +1 -1
  8. package/dist/config/cli-registry/schema.js +43 -0
  9. package/dist/config/cli-registry/schema.js.map +1 -1
  10. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  11. package/dist/config/cli-registry/stock.js +157 -2
  12. package/dist/config/cli-registry/stock.js.map +1 -1
  13. package/dist/config/cli-registry/types.d.ts +60 -0
  14. package/dist/config/cli-registry/types.d.ts.map +1 -1
  15. package/dist/custom-model-hosts.d.ts +39 -0
  16. package/dist/custom-model-hosts.d.ts.map +1 -0
  17. package/dist/custom-model-hosts.js +35 -0
  18. package/dist/custom-model-hosts.js.map +1 -0
  19. package/dist/custom-model-injection-apply.d.ts +49 -0
  20. package/dist/custom-model-injection-apply.d.ts.map +1 -0
  21. package/dist/custom-model-injection-apply.js +77 -0
  22. package/dist/custom-model-injection-apply.js.map +1 -0
  23. package/dist/custom-model-injection.d.ts +79 -0
  24. package/dist/custom-model-injection.d.ts.map +1 -0
  25. package/dist/custom-model-injection.js +169 -0
  26. package/dist/custom-model-injection.js.map +1 -0
  27. package/dist/docker-hosts.d.ts +42 -0
  28. package/dist/docker-hosts.d.ts.map +1 -1
  29. package/dist/docker-hosts.js +18 -0
  30. package/dist/docker-hosts.js.map +1 -1
  31. package/dist/generated-artifact-attachments.d.ts +3 -0
  32. package/dist/generated-artifact-attachments.d.ts.map +1 -1
  33. package/dist/generated-artifact-attachments.js +18 -8
  34. package/dist/generated-artifact-attachments.js.map +1 -1
  35. package/dist/mux-interface.d.ts +7 -0
  36. package/dist/mux-interface.d.ts.map +1 -1
  37. package/dist/remote-files.d.ts +145 -0
  38. package/dist/remote-files.d.ts.map +1 -0
  39. package/dist/remote-files.js +347 -0
  40. package/dist/remote-files.js.map +1 -0
  41. package/dist/remote-hosts.d.ts +12 -0
  42. package/dist/remote-hosts.d.ts.map +1 -1
  43. package/dist/remote-hosts.js +7 -1
  44. package/dist/remote-hosts.js.map +1 -1
  45. package/dist/remote-ssh-limiter.d.ts +42 -0
  46. package/dist/remote-ssh-limiter.d.ts.map +1 -0
  47. package/dist/remote-ssh-limiter.js +84 -0
  48. package/dist/remote-ssh-limiter.js.map +1 -0
  49. package/dist/session-manager.d.ts.map +1 -1
  50. package/dist/session-manager.js +8 -1
  51. package/dist/session-manager.js.map +1 -1
  52. package/dist/session.d.ts +79 -2
  53. package/dist/session.d.ts.map +1 -1
  54. package/dist/session.js +163 -2
  55. package/dist/session.js.map +1 -1
  56. package/dist/tmux-manager.d.ts.map +1 -1
  57. package/dist/tmux-manager.js +27 -13
  58. package/dist/tmux-manager.js.map +1 -1
  59. package/dist/types/api.d.ts +6 -0
  60. package/dist/types/api.d.ts.map +1 -1
  61. package/dist/types/api.js.map +1 -1
  62. package/dist/types/session.d.ts +30 -0
  63. package/dist/types/session.d.ts.map +1 -1
  64. package/dist/types/session.js.map +1 -1
  65. package/dist/web/middleware/auth.d.ts +11 -1
  66. package/dist/web/middleware/auth.d.ts.map +1 -1
  67. package/dist/web/middleware/auth.js +69 -1
  68. package/dist/web/middleware/auth.js.map +1 -1
  69. package/dist/web/public/admin-ui.js.gz +0 -0
  70. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  71. package/dist/web/public/{app.78bf0bf8.js → app.556be563.js} +7 -7
  72. package/dist/web/public/app.556be563.js.br +0 -0
  73. package/dist/web/public/app.556be563.js.gz +0 -0
  74. package/dist/web/public/approvals-ui.js.gz +0 -0
  75. package/dist/web/public/constants.258b140f.js.gz +0 -0
  76. package/dist/web/public/cron-ui.js.gz +0 -0
  77. package/dist/web/public/entrance-animations.js.gz +0 -0
  78. package/dist/web/public/home-sessions.js.gz +0 -0
  79. package/dist/web/public/i18n.561ca09c.js.gz +0 -0
  80. package/dist/web/public/image-input.cd4b97c4.js.gz +0 -0
  81. package/dist/web/public/index.html +14 -7
  82. package/dist/web/public/index.html.br +0 -0
  83. package/dist/web/public/index.html.gz +0 -0
  84. package/dist/web/public/input-cjk.8bc46081.js +1 -0
  85. package/dist/web/public/input-cjk.8bc46081.js.br +0 -0
  86. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  87. package/dist/web/public/{keyboard-accessory.1d0dda9b.js → keyboard-accessory.2cf04f17.js} +38 -3
  88. package/dist/web/public/keyboard-accessory.2cf04f17.js.br +0 -0
  89. package/dist/web/public/keyboard-accessory.2cf04f17.js.gz +0 -0
  90. package/dist/web/public/mobile-handlers.6f354a87.js.gz +0 -0
  91. package/dist/web/public/mobile-overview.js.gz +0 -0
  92. package/dist/web/public/mobile.e9d0b53e.css.gz +0 -0
  93. package/dist/web/public/notification-manager.36ea4624.js.gz +0 -0
  94. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  95. package/dist/web/public/panels-ui.5b07ad14.js.gz +0 -0
  96. package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
  97. package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
  98. package/dist/web/public/readmymind-ui.js.gz +0 -0
  99. package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
  100. package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
  101. package/dist/web/public/session-lineage.js.gz +0 -0
  102. package/dist/web/public/{session-ui.5d0a7b15.js → session-ui.42b81477.js} +13 -13
  103. package/dist/web/public/session-ui.42b81477.js.br +0 -0
  104. package/dist/web/public/session-ui.42b81477.js.gz +0 -0
  105. package/dist/web/public/settings-ui.e0c7f6b4.js.gz +0 -0
  106. package/dist/web/public/{styles.5d36726d.css → styles.6add175d.css} +1 -1
  107. package/dist/web/public/styles.6add175d.css.br +0 -0
  108. package/dist/web/public/{styles.5d36726d.css.gz → styles.6add175d.css.gz} +0 -0
  109. package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
  110. package/dist/web/public/sw.js.gz +0 -0
  111. package/dist/web/public/tab-rail-resize.42c24949.js.gz +0 -0
  112. package/dist/web/public/terminal-keycode229-recovery.6ea8fe37.js.gz +0 -0
  113. package/dist/web/public/terminal-ui.38c49244.js +2 -0
  114. package/dist/web/public/terminal-ui.38c49244.js.br +0 -0
  115. package/dist/web/public/terminal-ui.38c49244.js.gz +0 -0
  116. package/dist/web/public/ultracode-panel.js.gz +0 -0
  117. package/dist/web/public/ultracode-windows.js.gz +0 -0
  118. package/dist/web/public/upload.html.gz +0 -0
  119. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  120. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  121. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  122. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  123. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  124. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  125. package/dist/web/public/vendor/xterm-predictive-echo.bd6882b8.js.gz +0 -0
  126. package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js.gz +0 -0
  127. package/dist/web/public/vendor/xterm.css.gz +0 -0
  128. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  129. package/dist/web/public/voice-input.c4b51eb6.js.gz +0 -0
  130. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  131. package/dist/web/public/webview-tabs.js +56 -4
  132. package/dist/web/public/webview-tabs.js.br +0 -0
  133. package/dist/web/public/webview-tabs.js.gz +0 -0
  134. package/dist/web/route-helpers.d.ts +20 -0
  135. package/dist/web/route-helpers.d.ts.map +1 -1
  136. package/dist/web/route-helpers.js +29 -2
  137. package/dist/web/route-helpers.js.map +1 -1
  138. package/dist/web/routes/case-routes.d.ts.map +1 -1
  139. package/dist/web/routes/case-routes.js +23 -6
  140. package/dist/web/routes/case-routes.js.map +1 -1
  141. package/dist/web/routes/custom-model-routes.d.ts +18 -0
  142. package/dist/web/routes/custom-model-routes.d.ts.map +1 -0
  143. package/dist/web/routes/custom-model-routes.js +136 -0
  144. package/dist/web/routes/custom-model-routes.js.map +1 -0
  145. package/dist/web/routes/file-routes.d.ts.map +1 -1
  146. package/dist/web/routes/file-routes.js +484 -100
  147. package/dist/web/routes/file-routes.js.map +1 -1
  148. package/dist/web/routes/index.d.ts +1 -0
  149. package/dist/web/routes/index.d.ts.map +1 -1
  150. package/dist/web/routes/index.js +1 -0
  151. package/dist/web/routes/index.js.map +1 -1
  152. package/dist/web/routes/session-routes.d.ts.map +1 -1
  153. package/dist/web/routes/session-routes.js +81 -1
  154. package/dist/web/routes/session-routes.js.map +1 -1
  155. package/dist/web/routes/ws-routes.d.ts.map +1 -1
  156. package/dist/web/routes/ws-routes.js +26 -2
  157. package/dist/web/routes/ws-routes.js.map +1 -1
  158. package/dist/web/schemas.d.ts +20 -0
  159. package/dist/web/schemas.d.ts.map +1 -1
  160. package/dist/web/schemas.js +31 -0
  161. package/dist/web/schemas.js.map +1 -1
  162. package/dist/web/server.d.ts +8 -0
  163. package/dist/web/server.d.ts.map +1 -1
  164. package/dist/web/server.js +65 -3
  165. package/dist/web/server.js.map +1 -1
  166. package/dist/web/webview-proxy.d.ts +41 -0
  167. package/dist/web/webview-proxy.d.ts.map +1 -1
  168. package/dist/web/webview-proxy.js +102 -1
  169. package/dist/web/webview-proxy.js.map +1 -1
  170. package/package.json +2 -2
  171. package/dist/web/public/app.78bf0bf8.js.br +0 -0
  172. package/dist/web/public/app.78bf0bf8.js.gz +0 -0
  173. package/dist/web/public/input-cjk.87f14251.js +0 -1
  174. package/dist/web/public/input-cjk.87f14251.js.br +0 -0
  175. package/dist/web/public/input-cjk.87f14251.js.gz +0 -0
  176. package/dist/web/public/keyboard-accessory.1d0dda9b.js.br +0 -0
  177. package/dist/web/public/keyboard-accessory.1d0dda9b.js.gz +0 -0
  178. package/dist/web/public/session-ui.5d0a7b15.js.br +0 -0
  179. package/dist/web/public/session-ui.5d0a7b15.js.gz +0 -0
  180. package/dist/web/public/styles.5d36726d.css.br +0 -0
  181. package/dist/web/public/terminal-ui.0cbe8637.js +0 -2
  182. package/dist/web/public/terminal-ui.0cbe8637.js.br +0 -0
  183. package/dist/web/public/terminal-ui.0cbe8637.js.gz +0 -0
@@ -0,0 +1,347 @@
1
+ /**
2
+ * @fileoverview Remote (SSH) file access for remote-SSH cases.
3
+ *
4
+ * A remote case's `workingDir` is an absolute path on ANOTHER host
5
+ * (`Session.workingDir = RemoteCase.remotePath`, see docs/remote-sessions.md). Every
6
+ * file route used to read it with local `fs`, which cannot work: the local
7
+ * `realpathSync` in `validateSessionFilePath` fails first, so the request died as a
8
+ * 404 "File not found" before a byte was read (#415). This module is the ONE place
9
+ * that reads remote bytes, mirroring how `remote-hosts.ts` is the one place that
10
+ * builds an ssh command line.
11
+ *
12
+ * Connection options come from `buildSshConnectionArgs()` — never a hand-built ssh
13
+ * line (the COD-107 discipline in docs/remote-sessions.md) — so a proxied,
14
+ * custom-port or jump-hosted case reaches its files with exactly the credentials the
15
+ * launch used, and `BatchMode=yes` means a host that needs a passphrase fails fast
16
+ * instead of hanging on a prompt nothing can answer.
17
+ *
18
+ * ⚠️ The path is the injection surface: it arrives from the browser (`?path=`). It is
19
+ * always interpolated as a single `shellescape`d token, and the whole remote command
20
+ * is itself shellescaped into the ssh line, so the local shell and the remote shell
21
+ * each see one opaque argument. Never build a command here by concatenating a raw
22
+ * path into the string.
23
+ *
24
+ * Read-only by design: previews, text reads and streaming. Writing to a remote file
25
+ * is deliberately NOT implemented (docs/file-viewer-edit-plan.md §6), nor are the
26
+ * office-conversion/thumbnail paths that would need the bytes on the server's disk.
27
+ */
28
+ import { exec, spawn } from 'node:child_process';
29
+ import { promisify } from 'node:util';
30
+ import { PassThrough } from 'node:stream';
31
+ import { buildSshConnectionArgs, remoteSshTarget, shellescape } from './remote-hosts.js';
32
+ import { runWithRemoteSshLimit } from './remote-ssh-limiter.js';
33
+ const execAsync = promisify(exec);
34
+ /**
35
+ * Bound on the probe (realpath + stat) round trip. The connect itself is already
36
+ * bounded by `buildSshConnectionArgs`'s default `-o ConnectTimeout=10`; this covers
37
+ * a host that accepts the TCP connection and then never answers.
38
+ */
39
+ const REMOTE_PROBE_TIMEOUT_MS = 20_000;
40
+ /** Bound on a buffered remote read (`cat`), on top of the caller's own size cap. */
41
+ const REMOTE_READ_TIMEOUT_MS = 30_000;
42
+ /** Slack over the caller's byte cap so a file exactly at the limit still fits. */
43
+ const READ_BUFFER_SLACK_BYTES = 64 * 1024;
44
+ /** Marker a probe prints when the path does not exist on the remote host. */
45
+ const NOT_FOUND_MARKER = 'n';
46
+ /**
47
+ * Marker a probe prints when the path exists but could NOT be canonicalized (no
48
+ * `readlink -f`, and the portable fallback hit its hop cap or a `readlink` failure).
49
+ * Parsed as `null`, i.e. 404: a path whose real target is unknown must never be
50
+ * served, because every containment and blocklist check runs on the resolved path.
51
+ */
52
+ const UNRESOLVABLE_MARKER = 'x';
53
+ /**
54
+ * Paths per ssh round trip. The whole remote script is ONE shellescaped argument,
55
+ * and Linux caps a single argv string at 128 KiB, so a 100-entry attachment history
56
+ * of long paths is split rather than risking `E2BIG` on the local `sh`.
57
+ */
58
+ const REMOTE_PROBE_CHUNK_SIZE = 40;
59
+ /** Symlink hops the portable resolver follows before giving up (Linux uses 40). */
60
+ const REMOTE_SYMLINK_MAX_HOPS = 40;
61
+ /**
62
+ * Under vitest no real ssh connection may ever be opened (mirrors
63
+ * `checkRemoteTmuxAvailable` and friends in remote-hosts.ts). The route tests mock
64
+ * this module, so nothing reaches here today; this is what keeps the NEXT
65
+ * remote-session test that touches a file route from opening a connection from CI.
66
+ * A clear 502-shaped error, never a fake success: there are no fake bytes to return.
67
+ */
68
+ function assertNotUnderTest() {
69
+ if (process.env.VITEST) {
70
+ throw new RemoteFileAccessError('remote file access is disabled under test');
71
+ }
72
+ }
73
+ /**
74
+ * A remote file access failed for a reason that is NOT "the file is missing" —
75
+ * unreachable host, timeout, ssh error, unexpected probe output. Callers map this to
76
+ * a 5xx with the remote reason in the message; a missing file is reported separately
77
+ * as `null`/404 so the two cannot be confused.
78
+ */
79
+ export class RemoteFileAccessError extends Error {
80
+ constructor(message) {
81
+ super(message);
82
+ this.name = 'RemoteFileAccessError';
83
+ }
84
+ }
85
+ /**
86
+ * Wrap a remote shell command in the shared, shellescaped ssh line.
87
+ *
88
+ * The single entry point for "run this on the remote host": connection args (port,
89
+ * identity, jump host, SOCKS ProxyCommand, extra `-o`) all come from
90
+ * `buildSshConnectionArgs`, and the command is ONE shellescaped token, so a path with
91
+ * spaces, quotes or `$(…)` cannot escape into the ssh command line.
92
+ */
93
+ export function buildRemoteFileCommand(remote, shellCommand) {
94
+ return [...buildSshConnectionArgs(remote), remoteSshTarget(remote), shellescape(shellCommand)].join(' ');
95
+ }
96
+ /**
97
+ * `realpath + stat + existence` for one or more paths, in a SINGLE ssh round trip.
98
+ *
99
+ * One call instead of three matters: without a shared connection (no ControlMaster)
100
+ * every extra `ssh` is a fresh handshake, and the file routes need the path AND the
101
+ * workspace root canonicalized to compare them.
102
+ *
103
+ * Output format: the script first prints a lone NUL, then one NUL-terminated record
104
+ * per path, `<index>|n` (missing), `<index>|x` (exists but cannot be canonicalized) or
105
+ * `<index>|kind|size|mtime|realPath`. Records are keyed by INDEX and separated by NUL
106
+ * rather than newline so that a remote filename containing a newline cannot shift the
107
+ * alignment, and the leading NUL is what separates a login banner or an eager rc-file
108
+ * `echo` (which land before the script runs) from the records without any "last N
109
+ * lines" guesswork. `realPath` is the last field, so a `|` in a path still parses.
110
+ *
111
+ * Symlink resolution is portable AND fails closed. `readlink -f` where available
112
+ * (Linux, macOS >= 12.3); otherwise the fallback canonicalizes the directory chain
113
+ * with `cd -P`/`pwd -P` and then follows the LAST component with plain `readlink`
114
+ * (which the systems lacking `-f` do have) for a bounded number of hops. A path the
115
+ * fallback cannot resolve prints `x`, never the unresolved string: every containment
116
+ * and blocklist check downstream runs on `realPath`, and an earlier version of this
117
+ * fallback returned the directory-resolved path with the final symlink still in it,
118
+ * so `ws/notes.txt -> ~/.ssh/id_rsa` passed containment while `cat` served the key.
119
+ */
120
+ export function buildRemoteProbeCommand(paths) {
121
+ const probes = paths.map((path, index) => `probe ${index} ${shellescape(path)}`).join('\n');
122
+ return [
123
+ 'resolve_last() {',
124
+ ' q=$1',
125
+ ' hops=0',
126
+ ' while :; do',
127
+ ' d=$(cd -P "$(dirname "$q")" 2>/dev/null && pwd -P) || return 1',
128
+ ' q=$d/$(basename "$q")',
129
+ ' [ -L "$q" ] || break',
130
+ ' hops=$((hops + 1))',
131
+ ` [ "$hops" -le ${REMOTE_SYMLINK_MAX_HOPS} ] || return 1`,
132
+ ' l=$(readlink "$q" 2>/dev/null) || return 1',
133
+ ' [ -n "$l" ] || return 1',
134
+ ' case $l in /*) q=$l ;; *) q=$d/$l ;; esac',
135
+ ' done',
136
+ ' if [ -d "$q" ]; then q=$(cd -P "$q" 2>/dev/null && pwd -P) || return 1; fi',
137
+ ' printf %s "$q"',
138
+ '}',
139
+ 'probe() {',
140
+ ' i=$1',
141
+ ' p=$2',
142
+ ` if [ ! -e "$p" ]; then printf '%s|${NOT_FOUND_MARKER}\\0' "$i"; return; fi`,
143
+ ` r=$(readlink -f "$p" 2>/dev/null) || r=$(resolve_last "$p") || { printf '%s|${UNRESOLVABLE_MARKER}\\0' "$i"; return; }`,
144
+ ` [ -n "$r" ] || { printf '%s|${UNRESOLVABLE_MARKER}\\0' "$i"; return; }`,
145
+ ' if [ -d "$r" ]; then t=d; elif [ -f "$r" ]; then t=f; else t=o; fi',
146
+ ' s=0',
147
+ ' if [ "$t" = f ]; then s=$(stat -c %s "$r" 2>/dev/null || stat -f %z "$r" 2>/dev/null); [ -n "$s" ] || s=0; fi',
148
+ ' m=$(stat -c %Y "$r" 2>/dev/null || stat -f %m "$r" 2>/dev/null || printf 0)',
149
+ ` printf '%s|%s|%s|%s|%s\\0' "$i" "$t" "$s" "$m" "$r"`,
150
+ '}',
151
+ "printf '\\0'",
152
+ probes,
153
+ ].join('\n');
154
+ }
155
+ /**
156
+ * Parse one probe record (index prefix already stripped). `null` for the not-found
157
+ * and unresolvable markers or anything malformed.
158
+ */
159
+ export function parseRemoteProbeRecord(record) {
160
+ if (!record || record === NOT_FOUND_MARKER || record === UNRESOLVABLE_MARKER)
161
+ return null;
162
+ const parts = record.split('|');
163
+ if (parts.length < 4)
164
+ return null;
165
+ const [kindRaw, sizeRaw, mtimeRaw] = parts;
166
+ const kind = kindRaw === 'f' ? 'file' : kindRaw === 'd' ? 'directory' : kindRaw === 'o' ? 'other' : null;
167
+ if (!kind)
168
+ return null;
169
+ const realPath = parts.slice(3).join('|');
170
+ if (!realPath)
171
+ return null;
172
+ const size = Number.parseInt(sizeRaw, 10);
173
+ const mtimeSeconds = Number.parseInt(mtimeRaw, 10);
174
+ return {
175
+ realPath,
176
+ kind,
177
+ size: Number.isFinite(size) && size > 0 ? size : 0,
178
+ mtimeMs: Number.isFinite(mtimeSeconds) && mtimeSeconds > 0 ? mtimeSeconds * 1000 : 0,
179
+ };
180
+ }
181
+ /**
182
+ * Parse the output of {@link buildRemoteProbeCommand} into one entry per requested
183
+ * path, in order. Throws when a path's record is missing: that means the transport
184
+ * or the remote shell did something unexpected, and silently treating it as "not
185
+ * found" would turn an infrastructure failure into a wrong 404.
186
+ *
187
+ * Everything before the first NUL is the remote shell's own chatter (banner, rc-file
188
+ * output) and is discarded; records are matched by their index prefix, so neither
189
+ * extra output nor a newline inside a filename can shift the mapping.
190
+ */
191
+ export function parseRemoteProbeOutput(stdout, paths) {
192
+ const records = stdout.split('\0').slice(1);
193
+ const byIndex = new Map();
194
+ for (const record of records) {
195
+ const match = /^(\d+)\|([\s\S]*)$/.exec(record);
196
+ if (!match)
197
+ continue;
198
+ const index = Number.parseInt(match[1], 10);
199
+ if (!byIndex.has(index))
200
+ byIndex.set(index, match[2]);
201
+ }
202
+ return paths.map((_, index) => {
203
+ const record = byIndex.get(index);
204
+ if (record === undefined) {
205
+ throw new RemoteFileAccessError('remote host returned no usable file information');
206
+ }
207
+ return parseRemoteProbeRecord(record);
208
+ });
209
+ }
210
+ /**
211
+ * Probe one or more remote paths. Entry is `null` for a path that does not exist (or
212
+ * could not be canonicalized, which is refused the same way).
213
+ *
214
+ * Large batches are split into round trips of {@link REMOTE_PROBE_CHUNK_SIZE}, each
215
+ * counted against the global ssh limiter, so an attachment history of 100 entries
216
+ * costs three connections in sequence rather than 100 at once.
217
+ */
218
+ export async function remoteProbePaths(remote, paths) {
219
+ assertNotUnderTest();
220
+ const results = [];
221
+ for (let offset = 0; offset < paths.length; offset += REMOTE_PROBE_CHUNK_SIZE) {
222
+ const chunk = paths.slice(offset, offset + REMOTE_PROBE_CHUNK_SIZE);
223
+ const command = buildRemoteFileCommand(remote, buildRemoteProbeCommand(chunk));
224
+ let stdout;
225
+ try {
226
+ const result = await runWithRemoteSshLimit(() => execAsync(command, { timeout: REMOTE_PROBE_TIMEOUT_MS, maxBuffer: 256 * 1024 }));
227
+ stdout = result.stdout;
228
+ }
229
+ catch (err) {
230
+ throw new RemoteFileAccessError(`remote host ${remote.label || remote.host} unreachable: ${describeExecError(err)}`);
231
+ }
232
+ results.push(...parseRemoteProbeOutput(stdout, chunk));
233
+ }
234
+ return results;
235
+ }
236
+ /** Read a whole remote file into memory, capped by `maxBytes`. */
237
+ export async function remoteReadFile(remote, remotePath, maxBytes) {
238
+ assertNotUnderTest();
239
+ const command = buildRemoteFileCommand(remote, `cat ${shellescape(remotePath)}`);
240
+ try {
241
+ const result = await runWithRemoteSshLimit(() => execAsync(command, {
242
+ timeout: REMOTE_READ_TIMEOUT_MS,
243
+ maxBuffer: maxBytes + READ_BUFFER_SLACK_BYTES,
244
+ encoding: 'buffer',
245
+ }));
246
+ return Buffer.isBuffer(result.stdout) ? result.stdout : Buffer.from(result.stdout);
247
+ }
248
+ catch (err) {
249
+ throw new RemoteFileAccessError(`failed to read remote file: ${describeExecError(err)}`);
250
+ }
251
+ }
252
+ /**
253
+ * Command that writes a remote file's bytes to stdout.
254
+ *
255
+ * ⚠️ Range reads use `tail -c +N | head -c L` (both POSIX, constant memory) because
256
+ * the alternative — `dd bs=1` — issues one read syscall per byte and would make video
257
+ * seeking unusable. The trade-off is that a `tail` failure (the file vanished
258
+ * mid-request) reports `head`'s exit status, i.e. a short body on an already-sent
259
+ * 206; the client retries. The uncompressed path (`cat`) reports its own failure
260
+ * correctly, so the streaming error path is still covered by the normal case.
261
+ */
262
+ export function buildRemoteReadCommand(remotePath, range) {
263
+ const quoted = shellescape(remotePath);
264
+ if (!range)
265
+ return `cat ${quoted}`;
266
+ const length = range.end - range.start + 1;
267
+ return `tail -c +${range.start + 1} ${quoted} | head -c ${length}`;
268
+ }
269
+ /**
270
+ * Stream a remote file (optionally a byte range) as a Node Readable.
271
+ *
272
+ * Nothing is buffered in server memory: the bytes go from `ssh`'s stdout straight to
273
+ * the HTTP response, which is what makes a multi-GB remote video cost one pipe.
274
+ */
275
+ export function remoteCreateReadStream(remote, remotePath, range) {
276
+ if (process.env.VITEST) {
277
+ // Same rule as the buffered calls, in stream form: the consumer sees the error
278
+ // through the stream's normal failure path instead of a connection attempt.
279
+ const stream = new PassThrough();
280
+ process.nextTick(() => stream.destroy(new RemoteFileAccessError('remote file access is disabled under test')));
281
+ return { stream, close: () => stream.destroy() };
282
+ }
283
+ const command = buildRemoteFileCommand(remote, buildRemoteReadCommand(remotePath, range));
284
+ const child = spawn(command, { shell: true, stdio: ['ignore', 'pipe', 'pipe'] });
285
+ let stderr = '';
286
+ child.stderr?.on('data', (chunk) => {
287
+ if (stderr.length < 2000)
288
+ stderr += chunk.toString();
289
+ });
290
+ const stream = child.stdout;
291
+ let ended = false;
292
+ stream.on('end', () => {
293
+ ended = true;
294
+ });
295
+ stream.on('error', () => {
296
+ ended = true;
297
+ });
298
+ child.on('error', (err) => {
299
+ stream.destroy(err);
300
+ });
301
+ child.on('close', (code) => {
302
+ // Only a truncated transfer is an error. A non-zero exit AFTER the body finished
303
+ // (e.g. a signal delivered as the last byte was flushed) must not destroy an
304
+ // already-complete response, or the browser reports a broken body for a file it
305
+ // received in full.
306
+ if (ended || code === 0 || code === null)
307
+ return;
308
+ const detail = stderr.trim().split('\n')[0];
309
+ stream.destroy(new RemoteFileAccessError(`remote read failed (ssh exit ${code})${detail ? `: ${detail}` : ''}`));
310
+ });
311
+ return {
312
+ stream,
313
+ close() {
314
+ if (!stream.destroyed)
315
+ stream.destroy();
316
+ child.kill('SIGTERM');
317
+ },
318
+ };
319
+ }
320
+ /**
321
+ * First useful line of an exec/stderr error, for a user-facing message.
322
+ *
323
+ * ⚠️ Never Node's `err.message`: for a failed `exec` it is `Command failed: <the whole
324
+ * ssh line>`, which carries the identity-file path and the probe script, and this
325
+ * string goes out in a 502 body. stderr, the timeout flag and the exit/spawn code are
326
+ * everything a user can act on.
327
+ */
328
+ function describeExecError(err) {
329
+ if (typeof err === 'object' && err !== null) {
330
+ const record = err;
331
+ const stderr = typeof record.stderr === 'string' ? record.stderr : Buffer.isBuffer(record.stderr) ? String(record.stderr) : '';
332
+ const line = stderr
333
+ .split('\n')
334
+ .map((entry) => entry.trim())
335
+ .find((entry) => entry.length > 0);
336
+ if (line)
337
+ return line.slice(0, 300);
338
+ if (record.killed)
339
+ return 'timed out';
340
+ if (typeof record.code === 'number')
341
+ return `ssh exit ${record.code}`;
342
+ if (typeof record.code === 'string')
343
+ return `ssh could not be started (${record.code})`;
344
+ }
345
+ return 'unknown error';
346
+ }
347
+ //# sourceMappingURL=remote-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-files.js","sourceRoot":"","sources":["../src/remote-files.ts"],"names":[],"mappings":"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"}
@@ -43,6 +43,18 @@ export declare function remoteLoginShellCommand(command: string): string;
43
43
  */
44
44
  export declare function defaultRemoteCommandForMode(mode: SessionMode): string;
45
45
  export declare function remoteSshTarget(host: Pick<RemoteHost, 'username' | 'host'>): string;
46
+ /**
47
+ * POSIX single-quote shell-escaping (end-quote, escaped-quote, restart-quote).
48
+ * Mirrors the helper in tmux-manager.ts so a value with spaces/metachars stays a
49
+ * single shell token. Used here for identity paths and `-o KEY=VALUE` options.
50
+ *
51
+ * EXPORTED for `remote-files.ts` (#415, remote file access): that module wraps a
52
+ * remote shell command in the ssh line built by `buildSshConnectionArgs()`, so it
53
+ * needs the same escaping discipline for the remote command itself and for every
54
+ * path interpolated into it. A third private copy of this function is exactly how
55
+ * two escaping implementations drift apart.
56
+ */
57
+ export declare function shellescape(str: string): string;
46
58
  /**
47
59
  * COD-107 — build the ordered, shell-safe ssh CONNECTION tokens shared by both
48
60
  * the durable-launch command (`buildRemoteLaunchCommand`) and the tmux
@@ -1 +1 @@
1
- {"version":3,"file":"remote-hosts.d.ts","sourceRoot":"","sources":["../src/remote-hosts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"remote-hosts.d.ts","sourceRoot":"","sources":["../src/remote-hosts.ts"],"names":[],"mappings":"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"}
@@ -127,8 +127,14 @@ export function remoteSshTarget(host) {
127
127
  * POSIX single-quote shell-escaping (end-quote, escaped-quote, restart-quote).
128
128
  * Mirrors the helper in tmux-manager.ts so a value with spaces/metachars stays a
129
129
  * single shell token. Used here for identity paths and `-o KEY=VALUE` options.
130
+ *
131
+ * EXPORTED for `remote-files.ts` (#415, remote file access): that module wraps a
132
+ * remote shell command in the ssh line built by `buildSshConnectionArgs()`, so it
133
+ * needs the same escaping discipline for the remote command itself and for every
134
+ * path interpolated into it. A third private copy of this function is exactly how
135
+ * two escaping implementations drift apart.
130
136
  */
131
- function shellescape(str) {
137
+ export function shellescape(str) {
132
138
  return "'" + str.replace(/'/g, "'\\''") + "'";
133
139
  }
134
140
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"remote-hosts.js","sourceRoot":"","sources":["../src/remote-hosts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"remote-hosts.js","sourceRoot":"","sources":["../src/remote-hosts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @fileoverview Global concurrency limiter for the short-lived `ssh` children that
3
+ * remote-case file access spawns (`src/remote-files.ts`: the realpath+stat probe and
4
+ * the buffered text read).
5
+ *
6
+ * Two paths can fan those out without a human behind each one:
7
+ *
8
+ * - `GET /api/sessions/:id/attachments` resolves every history entry (up to
9
+ * `ATTACHMENT_HISTORY_LIMIT`, 100), and the attachments drawer re-runs it on every
10
+ * `attachment:detected` event while it is open, which is exactly when an agent is
11
+ * writing files. The route now batches the probes, but a burst of drawers is still
12
+ * a burst.
13
+ * - A `codeman://attach?path=` magic link in terminal output registers the path
14
+ * fire-and-forget, once per distinct link per PTY chunk. In a remote session that
15
+ * output is written by a process on the remote host, so a prompt-injected agent can
16
+ * print hundreds of links and have the server fork one `ssh` per link, each holding
17
+ * a 20s probe timeout.
18
+ *
19
+ * Without a cap that is the fork-bomb shape `document-conversion-limiter.ts` exists to
20
+ * prevent, and it also trips OpenSSH's default `MaxStartups 10:30:100`, which starts
21
+ * dropping connections at ten unauthenticated handshakes. This is that limiter for
22
+ * ssh: a small fixed pool, FIFO queueing, and a slot handed straight to the next
23
+ * waiter on release so the active count can never exceed the cap under interleaved
24
+ * async resumption.
25
+ *
26
+ * Streams (`remoteCreateReadStream`) are deliberately NOT counted: one is opened per
27
+ * browser request and held for the life of a media playback, so four open videos
28
+ * would otherwise block every preview and the history list. They are already gated
29
+ * behind a counted probe (the guard re-probe runs first), so their spawn RATE is
30
+ * bounded here even though their concurrency is bounded by the browser.
31
+ *
32
+ * NOT re-entrant: never acquire from inside a task already holding a slot.
33
+ */
34
+ /** Test/diagnostic hook: remote calls currently holding a slot. */
35
+ export declare function getActiveRemoteSshCount(): number;
36
+ /** Test/diagnostic hook: remote calls queued behind the cap. */
37
+ export declare function getQueuedRemoteSshCount(): number;
38
+ /** The configured cap, so a test can assert against the real number. */
39
+ export declare function getRemoteSshLimit(): number;
40
+ /** Run `task` once an ssh slot is free, releasing the slot afterward. */
41
+ export declare function runWithRemoteSshLimit<T>(task: () => Promise<T>): Promise<T>;
42
+ //# sourceMappingURL=remote-ssh-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-ssh-limiter.d.ts","sourceRoot":"","sources":["../src/remote-ssh-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAeH,mEAAmE;AACnE,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,gEAAgE;AAChE,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAoBD,yEAAyE;AACzE,wBAAsB,qBAAqB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOjF"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @fileoverview Global concurrency limiter for the short-lived `ssh` children that
3
+ * remote-case file access spawns (`src/remote-files.ts`: the realpath+stat probe and
4
+ * the buffered text read).
5
+ *
6
+ * Two paths can fan those out without a human behind each one:
7
+ *
8
+ * - `GET /api/sessions/:id/attachments` resolves every history entry (up to
9
+ * `ATTACHMENT_HISTORY_LIMIT`, 100), and the attachments drawer re-runs it on every
10
+ * `attachment:detected` event while it is open, which is exactly when an agent is
11
+ * writing files. The route now batches the probes, but a burst of drawers is still
12
+ * a burst.
13
+ * - A `codeman://attach?path=` magic link in terminal output registers the path
14
+ * fire-and-forget, once per distinct link per PTY chunk. In a remote session that
15
+ * output is written by a process on the remote host, so a prompt-injected agent can
16
+ * print hundreds of links and have the server fork one `ssh` per link, each holding
17
+ * a 20s probe timeout.
18
+ *
19
+ * Without a cap that is the fork-bomb shape `document-conversion-limiter.ts` exists to
20
+ * prevent, and it also trips OpenSSH's default `MaxStartups 10:30:100`, which starts
21
+ * dropping connections at ten unauthenticated handshakes. This is that limiter for
22
+ * ssh: a small fixed pool, FIFO queueing, and a slot handed straight to the next
23
+ * waiter on release so the active count can never exceed the cap under interleaved
24
+ * async resumption.
25
+ *
26
+ * Streams (`remoteCreateReadStream`) are deliberately NOT counted: one is opened per
27
+ * browser request and held for the life of a media playback, so four open videos
28
+ * would otherwise block every preview and the history list. They are already gated
29
+ * behind a counted probe (the guard re-probe runs first), so their spawn RATE is
30
+ * bounded here even though their concurrency is bounded by the browser.
31
+ *
32
+ * NOT re-entrant: never acquire from inside a task already holding a slot.
33
+ */
34
+ /**
35
+ * Max remote probes/reads allowed to run concurrently across the whole process.
36
+ * Override with CODEMAN_MAX_REMOTE_FILE_SSH (clamped to >= 1). Four keeps a burst
37
+ * well under OpenSSH's ten-handshake default.
38
+ */
39
+ const MAX_CONCURRENT_REMOTE_SSH = (() => {
40
+ const raw = Number(process.env.CODEMAN_MAX_REMOTE_FILE_SSH);
41
+ return Number.isFinite(raw) && raw >= 1 ? Math.floor(raw) : 4;
42
+ })();
43
+ let active = 0;
44
+ const waiters = [];
45
+ /** Test/diagnostic hook: remote calls currently holding a slot. */
46
+ export function getActiveRemoteSshCount() {
47
+ return active;
48
+ }
49
+ /** Test/diagnostic hook: remote calls queued behind the cap. */
50
+ export function getQueuedRemoteSshCount() {
51
+ return waiters.length;
52
+ }
53
+ /** The configured cap, so a test can assert against the real number. */
54
+ export function getRemoteSshLimit() {
55
+ return MAX_CONCURRENT_REMOTE_SSH;
56
+ }
57
+ function acquire() {
58
+ if (active < MAX_CONCURRENT_REMOTE_SSH) {
59
+ active++;
60
+ return Promise.resolve();
61
+ }
62
+ return new Promise((resolve) => waiters.push(resolve));
63
+ }
64
+ function release() {
65
+ const next = waiters.shift();
66
+ if (next) {
67
+ // Hand the slot straight to the next waiter; `active` stays at the cap.
68
+ next();
69
+ }
70
+ else {
71
+ active--;
72
+ }
73
+ }
74
+ /** Run `task` once an ssh slot is free, releasing the slot afterward. */
75
+ export async function runWithRemoteSshLimit(task) {
76
+ await acquire();
77
+ try {
78
+ return await task();
79
+ }
80
+ finally {
81
+ release();
82
+ }
83
+ }
84
+ //# sourceMappingURL=remote-ssh-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-ssh-limiter.js","sourceRoot":"","sources":["../src/remote-ssh-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;GAIG;AACH,MAAM,yBAAyB,GAAG,CAAC,GAAG,EAAE;IACtC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,CAAC,EAAE,CAAC;AAEL,IAAI,MAAM,GAAG,CAAC,CAAC;AACf,MAAM,OAAO,GAAsB,EAAE,CAAC;AAEtC,mEAAmE;AACnE,MAAM,UAAU,uBAAuB;IACrC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,uBAAuB;IACrC,OAAO,OAAO,CAAC,MAAM,CAAC;AACxB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB;IAC/B,OAAO,yBAAyB,CAAC;AACnC,CAAC;AAED,SAAS,OAAO;IACd,IAAI,MAAM,GAAG,yBAAyB,EAAE,CAAC;QACvC,MAAM,EAAE,CAAC;QACT,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,OAAO;IACd,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC7B,IAAI,IAAI,EAAE,CAAC;QACT,wEAAwE;QACxE,IAAI,EAAE,CAAC;IACT,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,CAAC;IACX,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAI,IAAsB;IACnE,MAAM,OAAO,EAAE,CAAC;IAChB,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAgC1C,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,KAAK,CAAc;IAG3B,OAAO,CAAC,oBAAoB,CAA8B;IAE1D;;OAEG;;IAMH,OAAO,CAAC,aAAa;IAarB;;;;;;;OAOG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqEzD;;;;OAIG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B5C;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI3C,gCAAgC;IAChC,cAAc,IAAI,OAAO,EAAE;IAI3B,yDAAyD;IACzD,eAAe,IAAI,OAAO,EAAE;IAI5B,qDAAqD;IACrD,eAAe,IAAI,OAAO,EAAE;IAI5B,yCAAyC;IACzC,eAAe,IAAI,MAAM;IAIzB,wCAAwC;IACxC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI/B,OAAO,CAAC,kBAAkB;IAY1B,qEAAqE;IACrE,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAIjD;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpE,4CAA4C;IAC5C,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKlD,2CAA2C;IAC3C,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAIlD;AAKD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD"}
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAgC1C,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,KAAK,CAAc;IAG3B,OAAO,CAAC,oBAAoB,CAA8B;IAE1D;;OAEG;;IAMH,OAAO,CAAC,aAAa;IAarB;;;;;;;OAOG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqEzD;;;;OAIG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B5C;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI3C,gCAAgC;IAChC,cAAc,IAAI,OAAO,EAAE;IAI3B,yDAAyD;IACzD,eAAe,IAAI,OAAO,EAAE;IAI5B,qDAAqD;IACrD,eAAe,IAAI,OAAO,EAAE;IAI5B,yCAAyC;IACzC,eAAe,IAAI,MAAM;IAIzB,wCAAwC;IACxC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI/B,OAAO,CAAC,kBAAkB;IAmB1B,qEAAqE;IACrE,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IAIjD;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpE,4CAA4C;IAC5C,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKlD,2CAA2C;IAC3C,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAIlD;AAKD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD"}
@@ -197,7 +197,14 @@ export class SessionManager extends EventEmitter {
197
197
  // future reader of state.json.
198
198
  const state = session.toState();
199
199
  const envOverrides = session.getEnvOverridesForPersist();
200
- const toStore = envOverrides ? { ...state, __envOverrides: envOverrides } : state;
200
+ // __customModel: same convention, the disk-only bookkeeping of a custom-model
201
+ // selection (env KEYS, config dir, launch model; never the injected values).
202
+ const customModel = session.getCustomModelForPersist();
203
+ const toStore = {
204
+ ...state,
205
+ ...(envOverrides ? { __envOverrides: envOverrides } : {}),
206
+ ...(customModel ? { __customModel: customModel } : {}),
207
+ };
201
208
  this.store.setSession(session.id, toStore);
202
209
  }
203
210
  /** Gets all sessions from persistent storage (including stopped). */