aicodeman 1.40.0 → 1.41.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 (211) hide show
  1. package/README.md +25 -7
  2. package/dist/cli-agent.d.ts +225 -0
  3. package/dist/cli-agent.d.ts.map +1 -0
  4. package/dist/cli-agent.js +767 -0
  5. package/dist/cli-agent.js.map +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +6 -30
  8. package/dist/cli.js.map +1 -1
  9. package/dist/codeman-credentials.d.ts +27 -0
  10. package/dist/codeman-credentials.d.ts.map +1 -0
  11. package/dist/codeman-credentials.js +66 -0
  12. package/dist/codeman-credentials.js.map +1 -0
  13. package/dist/config/cli-registry/schema.d.ts +2 -0
  14. package/dist/config/cli-registry/schema.d.ts.map +1 -1
  15. package/dist/config/cli-registry/schema.js +3 -0
  16. package/dist/config/cli-registry/schema.js.map +1 -1
  17. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  18. package/dist/config/cli-registry/stock.js +5 -0
  19. package/dist/config/cli-registry/stock.js.map +1 -1
  20. package/dist/config/cli-registry/types.d.ts +12 -1
  21. package/dist/config/cli-registry/types.d.ts.map +1 -1
  22. package/dist/git-clone.d.ts.map +1 -1
  23. package/dist/git-clone.js +4 -0
  24. package/dist/git-clone.js.map +1 -1
  25. package/dist/image-watcher.d.ts.map +1 -1
  26. package/dist/image-watcher.js +6 -2
  27. package/dist/image-watcher.js.map +1 -1
  28. package/dist/mcp-sync-targets.d.ts +34 -0
  29. package/dist/mcp-sync-targets.d.ts.map +1 -0
  30. package/dist/mcp-sync-targets.js +55 -0
  31. package/dist/mcp-sync-targets.js.map +1 -0
  32. package/dist/mcp-sync.d.ts +2 -1
  33. package/dist/mcp-sync.d.ts.map +1 -1
  34. package/dist/mcp-sync.js +62 -1
  35. package/dist/mcp-sync.js.map +1 -1
  36. package/dist/session.d.ts.map +1 -1
  37. package/dist/session.js +10 -4
  38. package/dist/session.js.map +1 -1
  39. package/dist/subagent-watcher.d.ts.map +1 -1
  40. package/dist/subagent-watcher.js +29 -6
  41. package/dist/subagent-watcher.js.map +1 -1
  42. package/dist/templates/case-template.md +2 -0
  43. package/dist/tmux-manager.d.ts +5 -0
  44. package/dist/tmux-manager.d.ts.map +1 -1
  45. package/dist/tmux-manager.js +47 -22
  46. package/dist/tmux-manager.js.map +1 -1
  47. package/dist/tui/tui-client.d.ts +3 -17
  48. package/dist/tui/tui-client.d.ts.map +1 -1
  49. package/dist/tui/tui-client.js +3 -44
  50. package/dist/tui/tui-client.js.map +1 -1
  51. package/dist/utils/index.d.ts +1 -0
  52. package/dist/utils/index.d.ts.map +1 -1
  53. package/dist/utils/index.js +1 -0
  54. package/dist/utils/index.js.map +1 -1
  55. package/dist/utils/process-exit-wait.d.ts +40 -0
  56. package/dist/utils/process-exit-wait.d.ts.map +1 -0
  57. package/dist/utils/process-exit-wait.js +68 -0
  58. package/dist/utils/process-exit-wait.js.map +1 -0
  59. package/dist/web/paste-image-gc.d.ts +46 -6
  60. package/dist/web/paste-image-gc.d.ts.map +1 -1
  61. package/dist/web/paste-image-gc.js +106 -32
  62. package/dist/web/paste-image-gc.js.map +1 -1
  63. package/dist/web/public/admin-ui.js.gz +0 -0
  64. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  65. package/dist/web/public/app.6f8552e1.js +43 -0
  66. package/dist/web/public/app.6f8552e1.js.br +0 -0
  67. package/dist/web/public/app.6f8552e1.js.gz +0 -0
  68. package/dist/web/public/approvals-ui.js.gz +0 -0
  69. package/dist/web/public/{constants.c0f8f9de.js → constants.bc9c1f63.js} +295 -28
  70. package/dist/web/public/constants.bc9c1f63.js.br +0 -0
  71. package/dist/web/public/constants.bc9c1f63.js.gz +0 -0
  72. package/dist/web/public/cron-ui.js.gz +0 -0
  73. package/dist/web/public/entrance-animations.js +490 -43
  74. package/dist/web/public/entrance-animations.js.br +0 -0
  75. package/dist/web/public/entrance-animations.js.gz +0 -0
  76. package/dist/web/public/git-status-ui.js.gz +0 -0
  77. package/dist/web/public/home-sessions.js +2 -1
  78. package/dist/web/public/home-sessions.js.br +0 -0
  79. package/dist/web/public/home-sessions.js.gz +0 -0
  80. package/dist/web/public/host-wake-ui.js.gz +0 -0
  81. package/dist/web/public/i18n.a9840ea2.js +2 -0
  82. package/dist/web/public/i18n.a9840ea2.js.br +0 -0
  83. package/dist/web/public/i18n.a9840ea2.js.gz +0 -0
  84. package/dist/web/public/{image-input.898a538b.js → image-input.e00471c6.js} +3 -1
  85. package/dist/web/public/image-input.e00471c6.js.br +0 -0
  86. package/dist/web/public/image-input.e00471c6.js.gz +0 -0
  87. package/dist/web/public/index.html +128 -33
  88. package/dist/web/public/index.html.br +0 -0
  89. package/dist/web/public/index.html.gz +0 -0
  90. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  91. package/dist/web/public/keyboard-accessory.c1e7c7b7.js.gz +0 -0
  92. package/dist/web/public/mobile-handlers.0ef9c311.js.gz +0 -0
  93. package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
  94. package/dist/web/public/mobile-overview.js.gz +0 -0
  95. package/dist/web/public/mobile.111b187d.css.gz +0 -0
  96. package/dist/web/public/{notification-manager.50bb87d8.js → notification-manager.feb82c04.js} +19 -2
  97. package/dist/web/public/notification-manager.feb82c04.js.br +0 -0
  98. package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
  99. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  100. package/dist/web/public/{panels-ui.4735dfc2.js → panels-ui.71846fcb.js} +1 -1
  101. package/dist/web/public/panels-ui.71846fcb.js.br +0 -0
  102. package/dist/web/public/panels-ui.71846fcb.js.gz +0 -0
  103. package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
  104. package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
  105. package/dist/web/public/readmymind-ui.js.gz +0 -0
  106. package/dist/web/public/reboot-restore-ui.js.gz +0 -0
  107. package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
  108. package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
  109. package/dist/web/public/session-lineage.js.gz +0 -0
  110. package/dist/web/public/session-ui.f731602c.js.gz +0 -0
  111. package/dist/web/public/settings-ui.4e33390f.js +97 -0
  112. package/dist/web/public/settings-ui.4e33390f.js.br +0 -0
  113. package/dist/web/public/settings-ui.4e33390f.js.gz +0 -0
  114. package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
  115. package/dist/web/public/spreadsheet-preview.af82fa2f.js.gz +0 -0
  116. package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
  117. package/dist/web/public/styles.81a72906.css +1 -0
  118. package/dist/web/public/styles.81a72906.css.br +0 -0
  119. package/dist/web/public/styles.81a72906.css.gz +0 -0
  120. package/dist/web/public/{subagent-windows.e6ca799f.js → subagent-windows.07277a58.js} +7 -5
  121. package/dist/web/public/subagent-windows.07277a58.js.br +0 -0
  122. package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
  123. package/dist/web/public/sw.js +2 -2
  124. package/dist/web/public/sw.js.br +0 -0
  125. package/dist/web/public/sw.js.gz +0 -0
  126. package/dist/web/public/tab-layout-browser.065fcba4.js.gz +0 -0
  127. package/dist/web/public/tab-rail-resize.a5867793.js.gz +0 -0
  128. package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
  129. package/dist/web/public/terminal-split.js.gz +0 -0
  130. package/dist/web/public/terminal-tile.js +92 -15
  131. package/dist/web/public/terminal-tile.js.br +0 -0
  132. package/dist/web/public/terminal-tile.js.gz +0 -0
  133. package/dist/web/public/terminal-ui.b7267005.js +2 -0
  134. package/dist/web/public/terminal-ui.b7267005.js.br +0 -0
  135. package/dist/web/public/terminal-ui.b7267005.js.gz +0 -0
  136. package/dist/web/public/tile-grid.js +330 -119
  137. package/dist/web/public/tile-grid.js.br +0 -0
  138. package/dist/web/public/tile-grid.js.gz +0 -0
  139. package/dist/web/public/ultracode-panel.js.gz +0 -0
  140. package/dist/web/public/ultracode-windows.js +9 -6
  141. package/dist/web/public/ultracode-windows.js.br +0 -0
  142. package/dist/web/public/ultracode-windows.js.gz +0 -0
  143. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  144. package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
  145. package/dist/web/public/vendor/fflate.min.js.gz +0 -0
  146. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  147. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  148. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  149. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  150. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  151. package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
  152. package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js +4 -0
  153. package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.br +0 -0
  154. package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
  155. package/dist/web/public/vendor/xterm.css.gz +0 -0
  156. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  157. package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
  158. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  159. package/dist/web/public/webview-tabs.js.gz +0 -0
  160. package/dist/web/routes/cli-registry-routes.d.ts +23 -4
  161. package/dist/web/routes/cli-registry-routes.d.ts.map +1 -1
  162. package/dist/web/routes/cli-registry-routes.js +92 -7
  163. package/dist/web/routes/cli-registry-routes.js.map +1 -1
  164. package/dist/web/routes/mcp-sync-routes.d.ts +7 -2
  165. package/dist/web/routes/mcp-sync-routes.d.ts.map +1 -1
  166. package/dist/web/routes/mcp-sync-routes.js +10 -3
  167. package/dist/web/routes/mcp-sync-routes.js.map +1 -1
  168. package/dist/web/routes/reboot-restore-routes.js +1 -1
  169. package/dist/web/routes/reboot-restore-routes.js.map +1 -1
  170. package/dist/web/routes/session-routes.d.ts.map +1 -1
  171. package/dist/web/routes/session-routes.js +68 -35
  172. package/dist/web/routes/session-routes.js.map +1 -1
  173. package/dist/web/schemas.d.ts +3 -0
  174. package/dist/web/schemas.d.ts.map +1 -1
  175. package/dist/web/schemas.js +9 -0
  176. package/dist/web/schemas.js.map +1 -1
  177. package/dist/web/server.d.ts +1 -1
  178. package/dist/web/server.d.ts.map +1 -1
  179. package/dist/web/server.js +15 -10
  180. package/dist/web/server.js.map +1 -1
  181. package/package.json +4 -4
  182. package/skills/codeman/SKILL.md +6 -0
  183. package/README.zh-CN.md +0 -1147
  184. package/dist/web/public/app.abadc970.js +0 -43
  185. package/dist/web/public/app.abadc970.js.br +0 -0
  186. package/dist/web/public/app.abadc970.js.gz +0 -0
  187. package/dist/web/public/constants.c0f8f9de.js.br +0 -0
  188. package/dist/web/public/constants.c0f8f9de.js.gz +0 -0
  189. package/dist/web/public/i18n.a31747a9.js +0 -2
  190. package/dist/web/public/i18n.a31747a9.js.br +0 -0
  191. package/dist/web/public/i18n.a31747a9.js.gz +0 -0
  192. package/dist/web/public/image-input.898a538b.js.br +0 -0
  193. package/dist/web/public/image-input.898a538b.js.gz +0 -0
  194. package/dist/web/public/notification-manager.50bb87d8.js.br +0 -0
  195. package/dist/web/public/notification-manager.50bb87d8.js.gz +0 -0
  196. package/dist/web/public/panels-ui.4735dfc2.js.br +0 -0
  197. package/dist/web/public/panels-ui.4735dfc2.js.gz +0 -0
  198. package/dist/web/public/settings-ui.a97ab16f.js +0 -97
  199. package/dist/web/public/settings-ui.a97ab16f.js.br +0 -0
  200. package/dist/web/public/settings-ui.a97ab16f.js.gz +0 -0
  201. package/dist/web/public/styles.8ee12666.css +0 -1
  202. package/dist/web/public/styles.8ee12666.css.br +0 -0
  203. package/dist/web/public/styles.8ee12666.css.gz +0 -0
  204. package/dist/web/public/subagent-windows.e6ca799f.js.br +0 -0
  205. package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
  206. package/dist/web/public/terminal-ui.5059b30e.js +0 -2
  207. package/dist/web/public/terminal-ui.5059b30e.js.br +0 -0
  208. package/dist/web/public/terminal-ui.5059b30e.js.gz +0 -0
  209. package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js +0 -4
  210. package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js.br +0 -0
  211. package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js.gz +0 -0
@@ -55,6 +55,7 @@ import { scanCodexSessionsHistory, codexThreadBySessionId } from '../../codex-tr
55
55
  import { getLastTranscriptResponse, isExternalCliTranscriptMode, parseExternalCliTranscript, selectLastAnsweredTurn, } from '../response-viewer-transcript.js';
56
56
  import { readDeepSeekLastResponse } from '../../deepseek-transcript.js';
57
57
  import { appendClaudeCustomTitle } from '../../claude-session-title.js';
58
+ import { UPLOADS_DIR } from '../paste-image-gc.js';
58
59
  // Path to linked-cases registry (same file used by case-routes resolveCasePath)
59
60
  const LINKED_CASES_FILE = dataPath('linked-cases.json');
60
61
  const CODEMAN_CONFIG_DIR = getDataDir();
@@ -222,6 +223,58 @@ export function imageMagicMatchesExt(data, ext) {
222
223
  return false;
223
224
  }
224
225
  }
226
+ /**
227
+ * Create or re-verify `{workingDir}/.codeman-uploads` for a prompt upload, or
228
+ * null when something other than a regular directory sits there. An agent or
229
+ * postinstall script could plant `.codeman-uploads -> ~/.ssh/` and redirect
230
+ * future writes outside workingDir: lstat (not stat) sees the symlink itself,
231
+ * and mkdir without `recursive` does not follow one for the leaf either;
232
+ * O_EXCL|O_NOFOLLOW on the file open makes the write itself symlink-safe.
233
+ * The folder ignores itself: a `.gitignore` of `*`, written once with O_EXCL,
234
+ * so the user's repository never sees uploads, their own ignore file is never
235
+ * touched, and a file already there is theirs and stays as it is.
236
+ */
237
+ async function ensureUploadDir(workingDir) {
238
+ // workingDir is guaranteed to exist (live session).
239
+ const uploadDir = join(workingDir, UPLOADS_DIR);
240
+ try {
241
+ const dirStat = await fs.lstat(uploadDir);
242
+ if (dirStat.isSymbolicLink() || !dirStat.isDirectory())
243
+ return null;
244
+ }
245
+ catch (err) {
246
+ if (err.code !== 'ENOENT')
247
+ throw err;
248
+ try {
249
+ await fs.mkdir(uploadDir);
250
+ }
251
+ catch (mkErr) {
252
+ // Concurrent uploads (a batch of photos) race to create the dir — the
253
+ // losers get EEXIST. Treat an already-present REAL directory as success,
254
+ // but re-verify it isn't a symlink a racing actor planted.
255
+ if (mkErr.code !== 'EEXIST')
256
+ throw mkErr;
257
+ const raceStat = await fs.lstat(uploadDir);
258
+ if (raceStat.isSymbolicLink() || !raceStat.isDirectory())
259
+ return null;
260
+ }
261
+ }
262
+ const ignoreFile = join(uploadDir, '.gitignore');
263
+ try {
264
+ // 'wx' = O_CREAT|O_EXCL, which also fails on a symlink at the path.
265
+ await fs.writeFile(ignoreFile, '*\n', { flag: 'wx' });
266
+ }
267
+ catch (err) {
268
+ if (err.code === 'EEXIST')
269
+ return uploadDir;
270
+ // The create can succeed before the write fails (ENOSPC): an empty ignore
271
+ // file would read as the user's on the next upload, so take it back; its own
272
+ // failure must not replace the cause.
273
+ await fs.rm(ignoreFile, { force: true }).catch(() => { });
274
+ throw err;
275
+ }
276
+ return uploadDir;
277
+ }
225
278
  // Per-(IP, sessionId) token bucket for paste-image. 30 requests/minute.
226
279
  // Bucket map entries are pruned when they drift > 1h stale to bound memory
227
280
  // against a flood of unique IP keys.
@@ -4557,6 +4610,16 @@ options = {}) {
4557
4610
  return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Rate limit exceeded (30 uploads/min per session)');
4558
4611
  }
4559
4612
  const session = findSessionOrFail(ctx, id, req);
4613
+ // The file lands on THIS host under the session's working directory, which
4614
+ // for a remote (SSH) session is the remote path: the agent there could never
4615
+ // read it, and the write would land in a same-named local directory or fail.
4616
+ // An owned Docker case is fine, its workspace is bind-mounted at the same
4617
+ // absolute path; an adopted container (owned: false) mounts nothing, so its
4618
+ // agent reads the file only if the container exposes that host path.
4619
+ if (session.remote) {
4620
+ reply.code(400);
4621
+ return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Prompt uploads are not supported for remote (SSH) sessions');
4622
+ }
4560
4623
  if (!req.isMultipart()) {
4561
4624
  reply.code(400);
4562
4625
  return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Expected multipart/form-data');
@@ -4646,41 +4709,11 @@ options = {}) {
4646
4709
  reply.code(415);
4647
4710
  return createErrorResponse(ApiErrorCode.INVALID_INPUT, `Image bytes do not match declared type ${ext}`);
4648
4711
  }
4649
- // Save to {workingDir}/.claude-images/
4650
- // Refuse symlinks at imageDir — an agent or postinstall script could plant
4651
- // `.claude-images -> ~/.ssh/` and redirect future writes outside workingDir.
4652
- // We lstat (not stat) so we see the symlink itself. Use mkdir without
4653
- // `recursive` so the leaf creation does not follow a symlink either, and
4654
- // O_EXCL|O_NOFOLLOW on the file open so the write itself is symlink-safe.
4655
- const imageDir = join(session.workingDir, '.claude-images');
4656
- try {
4657
- const dirStat = await fs.lstat(imageDir);
4658
- if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) {
4659
- reply.code(403);
4660
- return createErrorResponse(ApiErrorCode.INVALID_INPUT, '.claude-images is not a regular directory');
4661
- }
4662
- }
4663
- catch (err) {
4664
- if (err.code !== 'ENOENT')
4665
- throw err;
4666
- // Non-recursive mkdir: does not follow symlinks for the leaf.
4667
- // session.workingDir is guaranteed to exist (live session).
4668
- try {
4669
- await fs.mkdir(imageDir);
4670
- }
4671
- catch (mkErr) {
4672
- // Concurrent uploads (a batch of photos) race to create .claude-images —
4673
- // the losers get EEXIST. Treat an already-present REAL directory as
4674
- // success, but re-verify it isn't a symlink a racing actor planted
4675
- // (preserve the symlink-safety guarantee above).
4676
- if (mkErr.code !== 'EEXIST')
4677
- throw mkErr;
4678
- const raceStat = await fs.lstat(imageDir);
4679
- if (raceStat.isSymbolicLink() || !raceStat.isDirectory()) {
4680
- reply.code(403);
4681
- return createErrorResponse(ApiErrorCode.INVALID_INPUT, '.claude-images is not a regular directory');
4682
- }
4683
- }
4712
+ // {workingDir}/.codeman-uploads/, see ensureUploadDir.
4713
+ const imageDir = await ensureUploadDir(session.workingDir);
4714
+ if (!imageDir) {
4715
+ reply.code(403);
4716
+ return createErrorResponse(ApiErrorCode.INVALID_INPUT, `${UPLOADS_DIR} is not a regular directory`);
4684
4717
  }
4685
4718
  // Date.now() collides on same-ms uploads from two tabs (last-write wins
4686
4719
  // silently). Append 8 hex chars so concurrent pastes get distinct names.