aicodeman 1.33.3 → 1.35.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 (255) hide show
  1. package/README.md +3 -0
  2. package/dist/config/cli-registry/schema.d.ts +18 -0
  3. package/dist/config/cli-registry/schema.d.ts.map +1 -1
  4. package/dist/config/cli-registry/schema.js +27 -0
  5. package/dist/config/cli-registry/schema.js.map +1 -1
  6. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  7. package/dist/config/cli-registry/stock.js +35 -0
  8. package/dist/config/cli-registry/stock.js.map +1 -1
  9. package/dist/config/cli-registry/types.d.ts +33 -0
  10. package/dist/config/cli-registry/types.d.ts.map +1 -1
  11. package/dist/config/dependency-registry.d.ts +7 -0
  12. package/dist/config/dependency-registry.d.ts.map +1 -1
  13. package/dist/config/dependency-registry.js +15 -0
  14. package/dist/config/dependency-registry.js.map +1 -1
  15. package/dist/config/path-probe.d.ts +37 -0
  16. package/dist/config/path-probe.d.ts.map +1 -0
  17. package/dist/config/path-probe.js +43 -0
  18. package/dist/config/path-probe.js.map +1 -0
  19. package/dist/git-workspace-status.d.ts +220 -0
  20. package/dist/git-workspace-status.d.ts.map +1 -0
  21. package/dist/git-workspace-status.js +606 -0
  22. package/dist/git-workspace-status.js.map +1 -0
  23. package/dist/hooks-config.d.ts.map +1 -1
  24. package/dist/hooks-config.js +88 -14
  25. package/dist/hooks-config.js.map +1 -1
  26. package/dist/mcp-sync.d.ts +105 -0
  27. package/dist/mcp-sync.d.ts.map +1 -0
  28. package/dist/mcp-sync.js +619 -0
  29. package/dist/mcp-sync.js.map +1 -0
  30. package/dist/mux-interface.d.ts +4 -0
  31. package/dist/mux-interface.d.ts.map +1 -1
  32. package/dist/session-cli-builder.d.ts +20 -1
  33. package/dist/session-cli-builder.d.ts.map +1 -1
  34. package/dist/session-cli-builder.js +33 -3
  35. package/dist/session-cli-builder.js.map +1 -1
  36. package/dist/session-cli-registry-bridge.d.ts +2 -0
  37. package/dist/session-cli-registry-bridge.d.ts.map +1 -1
  38. package/dist/session-cli-registry-bridge.js +15 -8
  39. package/dist/session-cli-registry-bridge.js.map +1 -1
  40. package/dist/session.d.ts +19 -0
  41. package/dist/session.d.ts.map +1 -1
  42. package/dist/session.js +29 -2
  43. package/dist/session.js.map +1 -1
  44. package/dist/tmux-manager.d.ts +2 -0
  45. package/dist/tmux-manager.d.ts.map +1 -1
  46. package/dist/tmux-manager.js +4 -2
  47. package/dist/tmux-manager.js.map +1 -1
  48. package/dist/types/api.d.ts +7 -0
  49. package/dist/types/api.d.ts.map +1 -1
  50. package/dist/types/api.js.map +1 -1
  51. package/dist/types/index.d.ts +3 -1
  52. package/dist/types/index.d.ts.map +1 -1
  53. package/dist/types/index.js +3 -1
  54. package/dist/types/index.js.map +1 -1
  55. package/dist/types/mcp-sync.d.ts +40 -0
  56. package/dist/types/mcp-sync.d.ts.map +1 -0
  57. package/dist/types/mcp-sync.js +8 -0
  58. package/dist/types/mcp-sync.js.map +1 -0
  59. package/dist/types/push.d.ts +37 -2
  60. package/dist/types/push.d.ts.map +1 -1
  61. package/dist/types/push.js +10 -3
  62. package/dist/types/push.js.map +1 -1
  63. package/dist/types/session.d.ts +34 -1
  64. package/dist/types/session.d.ts.map +1 -1
  65. package/dist/types/session.js +25 -1
  66. package/dist/types/session.js.map +1 -1
  67. package/dist/utils/bounded-path-probe.d.ts +99 -0
  68. package/dist/utils/bounded-path-probe.d.ts.map +1 -0
  69. package/dist/utils/bounded-path-probe.js +228 -0
  70. package/dist/utils/bounded-path-probe.js.map +1 -0
  71. package/dist/utils/cli-executable-resolver.d.ts +2 -0
  72. package/dist/utils/cli-executable-resolver.d.ts.map +1 -1
  73. package/dist/utils/cli-executable-resolver.js +2 -1
  74. package/dist/utils/cli-executable-resolver.js.map +1 -1
  75. package/dist/utils/dependency-checker.d.ts +2 -0
  76. package/dist/utils/dependency-checker.d.ts.map +1 -1
  77. package/dist/utils/dependency-checker.js +37 -9
  78. package/dist/utils/dependency-checker.js.map +1 -1
  79. package/dist/utils/index.d.ts +2 -0
  80. package/dist/utils/index.d.ts.map +1 -1
  81. package/dist/utils/index.js +1 -0
  82. package/dist/utils/index.js.map +1 -1
  83. package/dist/web/case-path.d.ts +58 -0
  84. package/dist/web/case-path.d.ts.map +1 -0
  85. package/dist/web/case-path.js +182 -0
  86. package/dist/web/case-path.js.map +1 -0
  87. package/dist/web/public/admin-ui.js.gz +0 -0
  88. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  89. package/dist/web/public/app.b9516c7b.js +43 -0
  90. package/dist/web/public/app.b9516c7b.js.br +0 -0
  91. package/dist/web/public/app.b9516c7b.js.gz +0 -0
  92. package/dist/web/public/approvals-ui.js.gz +0 -0
  93. package/dist/web/public/constants.d95fade9.js.gz +0 -0
  94. package/dist/web/public/cron-ui.js.gz +0 -0
  95. package/dist/web/public/entrance-animations.js.gz +0 -0
  96. package/dist/web/public/git-status-ui.js +673 -0
  97. package/dist/web/public/git-status-ui.js.br +0 -0
  98. package/dist/web/public/git-status-ui.js.gz +0 -0
  99. package/dist/web/public/home-sessions.js.gz +0 -0
  100. package/dist/web/public/host-wake-ui.js.gz +0 -0
  101. package/dist/web/public/i18n.52f5b7cc.js +1 -0
  102. package/dist/web/public/i18n.52f5b7cc.js.br +0 -0
  103. package/dist/web/public/i18n.52f5b7cc.js.gz +0 -0
  104. package/dist/web/public/image-input.a216cf9e.js.gz +0 -0
  105. package/dist/web/public/index.html +190 -15
  106. package/dist/web/public/index.html.br +0 -0
  107. package/dist/web/public/index.html.gz +0 -0
  108. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  109. package/dist/web/public/keyboard-accessory.c1e7c7b7.js.gz +0 -0
  110. package/dist/web/public/mobile-handlers.23a85db1.js.gz +0 -0
  111. package/dist/web/public/mobile-ime-preview.2dbaf262.js +1 -0
  112. package/dist/web/public/mobile-ime-preview.2dbaf262.js.br +0 -0
  113. package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
  114. package/dist/web/public/mobile-overview.js.gz +0 -0
  115. package/dist/web/public/mobile.1aa4952d.css.gz +0 -0
  116. package/dist/web/public/notification-manager.50bb87d8.js.gz +0 -0
  117. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  118. package/dist/web/public/panels-ui.6a5898d9.js.gz +0 -0
  119. package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
  120. package/dist/web/public/{ralph-wizard.13a1831e.js → ralph-wizard.b6c0dd19.js} +2 -0
  121. package/dist/web/public/ralph-wizard.b6c0dd19.js.br +0 -0
  122. package/dist/web/public/{ralph-wizard.13a1831e.js.gz → ralph-wizard.b6c0dd19.js.gz} +0 -0
  123. package/dist/web/public/readmymind-ui.js.gz +0 -0
  124. package/dist/web/public/reboot-restore-ui.js.gz +0 -0
  125. package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
  126. package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
  127. package/dist/web/public/session-lineage.js +27 -11
  128. package/dist/web/public/session-lineage.js.br +0 -0
  129. package/dist/web/public/session-lineage.js.gz +0 -0
  130. package/dist/web/public/session-ui.6bddf916.js +89 -0
  131. package/dist/web/public/session-ui.6bddf916.js.br +0 -0
  132. package/dist/web/public/session-ui.6bddf916.js.gz +0 -0
  133. package/dist/web/public/settings-ui.6e798b7b.js +97 -0
  134. package/dist/web/public/settings-ui.6e798b7b.js.br +0 -0
  135. package/dist/web/public/settings-ui.6e798b7b.js.gz +0 -0
  136. package/dist/web/public/styles.2d175c60.css +1 -0
  137. package/dist/web/public/styles.2d175c60.css.br +0 -0
  138. package/dist/web/public/styles.2d175c60.css.gz +0 -0
  139. package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
  140. package/dist/web/public/sw.js +2 -2
  141. package/dist/web/public/sw.js.br +0 -0
  142. package/dist/web/public/sw.js.gz +0 -0
  143. package/dist/web/public/tab-layout-browser.065fcba4.js +1 -0
  144. package/dist/web/public/tab-layout-browser.065fcba4.js.br +0 -0
  145. package/dist/web/public/tab-layout-browser.065fcba4.js.gz +0 -0
  146. package/dist/web/public/{tab-rail-resize.dcdc5772.js → tab-rail-resize.94cd59f0.js} +1 -1
  147. package/dist/web/public/tab-rail-resize.94cd59f0.js.br +0 -0
  148. package/dist/web/public/tab-rail-resize.94cd59f0.js.gz +0 -0
  149. package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js.gz +0 -0
  150. package/dist/web/public/terminal-split.js +82 -34
  151. package/dist/web/public/terminal-split.js.br +0 -0
  152. package/dist/web/public/terminal-split.js.gz +0 -0
  153. package/dist/web/public/terminal-ui.a4535311.js +2 -0
  154. package/dist/web/public/terminal-ui.a4535311.js.br +0 -0
  155. package/dist/web/public/terminal-ui.a4535311.js.gz +0 -0
  156. package/dist/web/public/ultracode-panel.js.gz +0 -0
  157. package/dist/web/public/ultracode-windows.js.gz +0 -0
  158. package/dist/web/public/upload.html.gz +0 -0
  159. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  160. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  161. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  162. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  163. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  164. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  165. package/dist/web/public/vendor/{xterm-predictive-echo.bd6882b8.js → xterm-predictive-echo.ae5e3d5d.js} +1 -1
  166. package/dist/web/public/vendor/{xterm-predictive-echo.bd6882b8.js.br → xterm-predictive-echo.ae5e3d5d.js.br} +0 -0
  167. package/dist/web/public/vendor/{xterm-predictive-echo.bd6882b8.js.gz → xterm-predictive-echo.ae5e3d5d.js.gz} +0 -0
  168. package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js +4 -0
  169. package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js.br +0 -0
  170. package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js.gz +0 -0
  171. package/dist/web/public/vendor/xterm.css.gz +0 -0
  172. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  173. package/dist/web/public/voice-input.c4b51eb6.js.gz +0 -0
  174. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  175. package/dist/web/public/webview-tabs.js +21 -10
  176. package/dist/web/public/webview-tabs.js.br +0 -0
  177. package/dist/web/public/webview-tabs.js.gz +0 -0
  178. package/dist/web/reboot-restore-registry.d.ts +2 -1
  179. package/dist/web/reboot-restore-registry.d.ts.map +1 -1
  180. package/dist/web/reboot-restore-registry.js +2 -1
  181. package/dist/web/reboot-restore-registry.js.map +1 -1
  182. package/dist/web/routes/case-routes.d.ts.map +1 -1
  183. package/dist/web/routes/case-routes.js +136 -18
  184. package/dist/web/routes/case-routes.js.map +1 -1
  185. package/dist/web/routes/doctor-routes.d.ts +23 -0
  186. package/dist/web/routes/doctor-routes.d.ts.map +1 -0
  187. package/dist/web/routes/doctor-routes.js +83 -0
  188. package/dist/web/routes/doctor-routes.js.map +1 -0
  189. package/dist/web/routes/git-status-routes.d.ts +16 -0
  190. package/dist/web/routes/git-status-routes.d.ts.map +1 -0
  191. package/dist/web/routes/git-status-routes.js +71 -0
  192. package/dist/web/routes/git-status-routes.js.map +1 -0
  193. package/dist/web/routes/index.d.ts +4 -0
  194. package/dist/web/routes/index.d.ts.map +1 -1
  195. package/dist/web/routes/index.js +4 -0
  196. package/dist/web/routes/index.js.map +1 -1
  197. package/dist/web/routes/mcp-sync-routes.d.ts +29 -0
  198. package/dist/web/routes/mcp-sync-routes.d.ts.map +1 -0
  199. package/dist/web/routes/mcp-sync-routes.js +83 -0
  200. package/dist/web/routes/mcp-sync-routes.js.map +1 -0
  201. package/dist/web/routes/ralph-routes.d.ts.map +1 -1
  202. package/dist/web/routes/ralph-routes.js +2 -1
  203. package/dist/web/routes/ralph-routes.js.map +1 -1
  204. package/dist/web/routes/reboot-restore-routes.d.ts.map +1 -1
  205. package/dist/web/routes/reboot-restore-routes.js +2 -0
  206. package/dist/web/routes/reboot-restore-routes.js.map +1 -1
  207. package/dist/web/routes/session-routes.d.ts.map +1 -1
  208. package/dist/web/routes/session-routes.js +60 -25
  209. package/dist/web/routes/session-routes.js.map +1 -1
  210. package/dist/web/routes/webhook-routes.d.ts +21 -0
  211. package/dist/web/routes/webhook-routes.d.ts.map +1 -0
  212. package/dist/web/routes/webhook-routes.js +87 -0
  213. package/dist/web/routes/webhook-routes.js.map +1 -0
  214. package/dist/web/schemas.d.ts +48 -2
  215. package/dist/web/schemas.d.ts.map +1 -1
  216. package/dist/web/schemas.js +71 -0
  217. package/dist/web/schemas.js.map +1 -1
  218. package/dist/web/server.d.ts +4 -0
  219. package/dist/web/server.d.ts.map +1 -1
  220. package/dist/web/server.js +57 -25
  221. package/dist/web/server.js.map +1 -1
  222. package/dist/webhook-notify.d.ts +71 -0
  223. package/dist/webhook-notify.d.ts.map +1 -0
  224. package/dist/webhook-notify.js +282 -0
  225. package/dist/webhook-notify.js.map +1 -0
  226. package/package.json +2 -1
  227. package/skills/codeman/SKILL.md +26 -8
  228. package/skills/codeman/preamble.sh +16 -4
  229. package/skills/codeman/reference/endpoints.md +11 -3
  230. package/skills/codeman/reference/recipes.md +1 -1
  231. package/skills/codeman/reference/verbs.md +3 -0
  232. package/dist/web/public/app.0879466b.js +0 -43
  233. package/dist/web/public/app.0879466b.js.br +0 -0
  234. package/dist/web/public/app.0879466b.js.gz +0 -0
  235. package/dist/web/public/i18n.7f8be985.js +0 -1
  236. package/dist/web/public/i18n.7f8be985.js.br +0 -0
  237. package/dist/web/public/i18n.7f8be985.js.gz +0 -0
  238. package/dist/web/public/ralph-wizard.13a1831e.js.br +0 -0
  239. package/dist/web/public/session-ui.7575a231.js +0 -89
  240. package/dist/web/public/session-ui.7575a231.js.br +0 -0
  241. package/dist/web/public/session-ui.7575a231.js.gz +0 -0
  242. package/dist/web/public/settings-ui.c68e7f59.js +0 -95
  243. package/dist/web/public/settings-ui.c68e7f59.js.br +0 -0
  244. package/dist/web/public/settings-ui.c68e7f59.js.gz +0 -0
  245. package/dist/web/public/styles.f2b78b86.css +0 -1
  246. package/dist/web/public/styles.f2b78b86.css.br +0 -0
  247. package/dist/web/public/styles.f2b78b86.css.gz +0 -0
  248. package/dist/web/public/tab-rail-resize.dcdc5772.js.br +0 -0
  249. package/dist/web/public/tab-rail-resize.dcdc5772.js.gz +0 -0
  250. package/dist/web/public/terminal-ui.d5223c0e.js +0 -2
  251. package/dist/web/public/terminal-ui.d5223c0e.js.br +0 -0
  252. package/dist/web/public/terminal-ui.d5223c0e.js.gz +0 -0
  253. package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js +0 -4
  254. package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js.br +0 -0
  255. package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js.gz +0 -0
@@ -1,4 +1,4 @@
1
- "use strict";var XtermPredictiveEcho=(()=>{var p=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var P=(o,t)=>{for(var e in t)p(o,e,{get:t[e],enumerable:!0})},M=(o,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of S(t))!w.call(o,i)&&i!==e&&p(o,i,{get:()=>t[i],enumerable:!(n=T(t,i))||n.enumerable});return o};var R=o=>M(p({},"__esModule",{value:!0}),o);var k={};P(k,{PredictiveEchoAddon:()=>m});function _(o){let t=o,e=typeof devicePixelRatio=="number"&&devicePixelRatio>0?devicePixelRatio:1;if(t.dimensions?.css?.cell){let n=t.dimensions.css.cell.height;return{width:t.dimensions.css.cell.width,height:n,charTop:(t.dimensions?.device?.char?.top??0)/e,charHeight:(t.dimensions?.device?.char?.height??n*e)/e}}try{let n=t._core?._renderService?.dimensions;if(n?.css?.cell){let i=n.css.cell.height;return{width:n.css.cell.width,height:i,charTop:(n.device?.char?.top??0)/e,charHeight:(n.device?.char?.height??i*e)/e}}}catch{}return null}function x(o,t){if(o?.unicode?.getStringCellWidth)return o.unicode.getStringCellWidth(t);let e=t.codePointAt(0);return e!==void 0&&e>=4352&&(e<=4447||e>=11904&&e<=12350||e>=12352&&e<=13247||e>=13312&&e<=19903||e>=19968&&e<=42191||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65072&&e<=65135||e>=65281&&e<=65376||e>=65504&&e<=65510||e>=126976&&e<=130047||e>=131072&&e<=196607||e>=196608&&e<=262143)?2:1}function b(o,t,e){let n=document.createElement("span");n.style.cssText=`position:absolute;left:${e.col*e.dims.width}px;top:${e.row*e.dims.height}px;width:${e.width*e.dims.width}px;height:${e.dims.height+1}px;line-height:${e.dims.height}px;text-align:center;pointer-events:none;font-family:${e.font.fontFamily};font-size:${e.font.fontSize};font-weight:${e.font.fontWeight};`+(e.font.letterSpacing?`letter-spacing:${e.font.letterSpacing};`:"")+`color:${e.font.color};background-color:${e.font.backgroundColor};font-feature-settings:'liga' 0,'calt' 0;`+(e.underline?"text-decoration:underline;":""),n.textContent=e.char,t.set(e.seq,n),o.appendChild(n)}function h(o,t){let e=o.get(t);e&&(e.remove(),o.delete(t))}function y(o){for(let t of o.values())t.remove();o.clear()}var a={zIndex:7,underlinePredictions:!1,ttlMs:1e3,maxPending:32,cursorGraceMs:150,edgeMarginCells:4},v="#000000",C="#ffffff",m=class{_terminal=null;_container=null;_spans=new Map;_outstanding=[];_anchor=null;_cursorOffRowSince=null;_seq=0;_confirmedTotal=0;_droppedTotal=0;_ttlTimer=null;_anchorHold=!1;_reconcileScheduled=!1;_disposables=[];_predictWhen;_options;_font={fontFamily:"monospace",fontSize:"14px",fontWeight:"normal",color:C,backgroundColor:v,letterSpacing:""};constructor(t){this._options={zIndex:t?.zIndex??a.zIndex,underlinePredictions:t?.underlinePredictions??a.underlinePredictions,ttlMs:t?.ttlMs??a.ttlMs,maxPending:t?.maxPending??a.maxPending,cursorGraceMs:t?.cursorGraceMs??a.cursorGraceMs,edgeMarginCells:t?.edgeMarginCells??a.edgeMarginCells,foregroundColor:t?.foregroundColor,backgroundColor:t?.backgroundColor},this._predictWhen=t?.predictWhen??null}activate(t){this._terminal=t,this._container=document.createElement("div"),this._container.setAttribute("data-predictive-echo",""),this._container.style.cssText=`position:absolute;left:0;top:0;z-index:${this._options.zIndex};pointer-events:none`;let e=t.element?.querySelector(".xterm-screen");if(e&&e.appendChild(this._container),this._readFontStyle(),typeof t.onWriteParsed=="function")try{this._disposables.push(t.onWriteParsed(()=>{this._reconcileScheduled||(this._reconcileScheduled=!0,queueMicrotask(()=>{this._reconcileScheduled=!1,this._anchorHold=!1,this._safeReconcile()}))}))}catch{}if(typeof t.onResize=="function")try{this._disposables.push(t.onResize(()=>this.clearPredictions()))}catch{}}dispose(){this.clearPredictions();for(let t of this._disposables)try{t.dispose()}catch{}this._disposables=[],this._container?.remove(),this._container=null,this._terminal=null}predictChar(t){try{if(this._reconcile(),this._anchorHold)return!1;let e=this._terminal;if(!e||!this._container)return!1;let n=_(e);if(!n)return!1;let i=e.buffer.active;if(typeof i.cursorX!="number"||typeof i.cursorY!="number"||i.viewportY!==i.baseY||this._predictWhen&&this._predictWhen(e)===!1)return!1;let l=Array.from(t);if(l.length!==1)return!1;let r=l[0].codePointAt(0);if(r<32||r===127)return!1;let s=x(e,l[0]);if(s!==1&&s!==2||s===2&&!this._hasGetCell()||this._outstanding.length>=this._options.maxPending)return!1;this._outstanding.length===0&&(this._anchor={row:i.cursorY,col:i.cursorX},this._cursorOffRowSince=null);let c=this._anchor,d=this._outstanding[this._outstanding.length-1],g=d?d.offsetCells+d.width:0,f=c.col+g;if(f+s>e.cols-this._options.edgeMarginCells)return!1;let u={seq:this._seq++,char:l[0],width:s,offsetCells:g,snapshot:this._readCell(c.row,f),sentAt:performance.now(),mismatches:0};return this._outstanding.push(u),b(this._container,this._spans,{seq:u.seq,row:c.row,col:f,char:u.char,width:s,dims:n,font:this._font,underline:this._options.underlinePredictions}),this._armTtl(),!0}catch{return!1}}predictBackspace(){try{let t=this._outstanding.pop();return t?(h(this._spans,t.seq),this._outstanding.length===0&&this._resetRun(),!0):(this._anchorHold=!0,!1)}catch{return!1}}clearPredictions(){try{this._anchorHold=!0,this._droppedTotal+=this._outstanding.length,this._outstanding=[],y(this._spans),this._resetRun()}catch{}}reconcile(){this._anchorHold=!1,this._safeReconcile()}setPredictWhen(t){this._predictWhen=t}refreshFont(){this._readFontStyle()}get hasPredictions(){return this._outstanding.length>0}get state(){return{outstanding:this._outstanding.length,confirmedTotal:this._confirmedTotal,droppedTotal:this._droppedTotal,anchor:this._anchor?{...this._anchor}:null}}_safeReconcile(){try{this._reconcile()}catch{}}_reconcile(){let t=this._terminal;if(!t||this._outstanding.length===0)return;let e=t.buffer.active;if(e.viewportY!==e.baseY){this.clearPredictions();return}if(typeof e.cursorX!="number"||typeof e.cursorY!="number")return;let n=this._anchor,i=performance.now();if(e.cursorY!==n.row){if(this._cursorOffRowSince??=i,i-this._cursorOffRowSince>this._options.cursorGraceMs){this.clearPredictions();return}}else this._cursorOffRowSince=null;for(;this._outstanding.length>0;){let r=this._outstanding[0];if(this._readCell(n.row,n.col+r.offsetCells)===r.char&&e.cursorY===n.row&&e.cursorX>=n.col+r.offsetCells+r.width)this._outstanding.shift(),h(this._spans,r.seq),this._confirmedTotal++;else break}let l=-1;for(let r=0;r<this._outstanding.length;r++){let s=this._outstanding[r],c=this._readCell(n.row,n.col+s.offsetCells);if(c!==s.snapshot&&c!==s.char&&c!==" "){if(s.mismatches++,s.mismatches>=2){l=r;break}}else s.mismatches=0}l!==-1&&this._dropFrom(l);for(let r=0;r<this._outstanding.length;r++)if(i-this._outstanding[r].sentAt>this._options.ttlMs){this._dropFrom(r);break}this._outstanding.length===0?this._resetRun():this._armTtl()}_dropFrom(t){let e=this._outstanding.splice(t);for(let n of e)h(this._spans,n.seq);this._droppedTotal+=e.length}_resetRun(){this._anchor=null,this._cursorOffRowSince=null,this._ttlTimer!==null&&(clearTimeout(this._ttlTimer),this._ttlTimer=null)}_armTtl(){if(this._ttlTimer!==null)return;let t=this._outstanding[0];if(!t)return;let e=Math.max(0,t.sentAt+this._options.ttlMs-performance.now())+1;this._ttlTimer=setTimeout(()=>{this._ttlTimer=null,this._safeReconcile(),this._armTtl()},e)}_hasGetCell(){let t=this._terminal?.buffer.active;return t?typeof t.getLine(t.baseY+(t.cursorY??0))?.getCell=="function":!1}_readCell(t,e){let n=this._terminal.buffer.active,i=n.getLine(n.baseY+t);if(!i)return" ";if(typeof i.getCell=="function"){let r=i.getCell(e)?.getChars()??"";return r===""?" ":r}return i.translateToString(!0)[e]??" "}_readFontStyle(){let t=this._terminal;if(!t)return;this._font.fontFamily=t.options.fontFamily||"monospace",this._font.fontSize=(t.options.fontSize||14)+"px",this._font.fontWeight=String(t.options.fontWeight||"normal"),this._font.backgroundColor=this._options.backgroundColor??t.options.theme?.background??v,this._font.color=this._options.foregroundColor??t.options.theme?.foreground??C,this._font.letterSpacing="";let e=t.element?.querySelector(".xterm-rows");if(e){let n=getComputedStyle(e);this._font.letterSpacing=n.letterSpacing,!this._options.foregroundColor&&n.color&&(this._font.color=n.color)}}};return R(k);})();
1
+ "use strict";var XtermPredictiveEcho=(()=>{var p=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var P=(o,t)=>{for(var e in t)p(o,e,{get:t[e],enumerable:!0})},M=(o,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of S(t))!w.call(o,i)&&i!==e&&p(o,i,{get:()=>t[i],enumerable:!(n=T(t,i))||n.enumerable});return o};var R=o=>M(p({},"__esModule",{value:!0}),o);var k={};P(k,{PredictiveEchoAddon:()=>m});function _(o){let t=o,e=typeof devicePixelRatio=="number"&&devicePixelRatio>0?devicePixelRatio:1;if(t.dimensions?.css?.cell){let n=t.dimensions.css.cell.height;return{width:t.dimensions.css.cell.width,height:n,charTop:(t.dimensions?.device?.char?.top??0)/e,charHeight:(t.dimensions?.device?.char?.height??n*e)/e}}try{let n=t._core?._renderService?.dimensions;if(n?.css?.cell){let i=n.css.cell.height;return{width:n.css.cell.width,height:i,charTop:(n.device?.char?.top??0)/e,charHeight:(n.device?.char?.height??i*e)/e}}}catch{}return null}function b(o,t){if(o?.unicode?.getStringCellWidth)return o.unicode.getStringCellWidth(t);let e=t.codePointAt(0);return e!==void 0&&e>=4352&&(e<=4447||e>=11904&&e<=12350||e>=12352&&e<=13247||e>=13312&&e<=19903||e>=19968&&e<=42191||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65072&&e<=65135||e>=65281&&e<=65376||e>=65504&&e<=65510||e>=126976&&e<=130047||e>=131072&&e<=196607||e>=196608&&e<=262143)?2:1}function x(o,t,e){let n=document.createElement("span");n.style.cssText=`position:absolute;left:${e.col*e.dims.width}px;top:${e.row*e.dims.height}px;width:${e.width*e.dims.width}px;height:${e.dims.height+1}px;line-height:${e.dims.height}px;text-align:center;pointer-events:none;font-family:${e.font.fontFamily};font-size:${e.font.fontSize};font-weight:${e.font.fontWeight};`+(e.font.letterSpacing?`letter-spacing:${e.font.letterSpacing};`:"")+`color:${e.font.color};background-color:${e.font.backgroundColor};font-feature-settings:'liga' 0,'calt' 0;`+(e.underline?"text-decoration:underline;":""),n.textContent=e.char,t.set(e.seq,n),o.appendChild(n)}function h(o,t){let e=o.get(t);e&&(e.remove(),o.delete(t))}function y(o){for(let t of o.values())t.remove();o.clear()}var a={zIndex:7,underlinePredictions:!1,ttlMs:1e3,maxPending:32,cursorGraceMs:150,edgeMarginCells:4},v="#000000",C="#ffffff",m=class{_terminal=null;_container=null;_spans=new Map;_outstanding=[];_anchor=null;_cursorOffRowSince=null;_seq=0;_confirmedTotal=0;_droppedTotal=0;_ttlTimer=null;_anchorHold=!1;_reconcileScheduled=!1;_disposables=[];_predictWhen;_options;_font={fontFamily:"monospace",fontSize:"14px",fontWeight:"normal",color:C,backgroundColor:v,letterSpacing:""};constructor(t){this._options={zIndex:t?.zIndex??a.zIndex,underlinePredictions:t?.underlinePredictions??a.underlinePredictions,ttlMs:t?.ttlMs??a.ttlMs,maxPending:t?.maxPending??a.maxPending,cursorGraceMs:t?.cursorGraceMs??a.cursorGraceMs,edgeMarginCells:t?.edgeMarginCells??a.edgeMarginCells,foregroundColor:t?.foregroundColor,backgroundColor:t?.backgroundColor},this._predictWhen=t?.predictWhen??null}activate(t){this._terminal=t,this._container=document.createElement("div"),this._container.setAttribute("data-predictive-echo",""),this._container.style.cssText=`position:absolute;left:0;top:0;z-index:${this._options.zIndex};pointer-events:none`;let e=t.element?.querySelector(".xterm-screen");if(e&&e.appendChild(this._container),this._readFontStyle(),typeof t.onWriteParsed=="function")try{this._disposables.push(t.onWriteParsed(()=>{this._reconcileScheduled||(this._reconcileScheduled=!0,queueMicrotask(()=>{this._reconcileScheduled=!1,this._anchorHold=!1,this._safeReconcile()}))}))}catch{}if(typeof t.onResize=="function")try{this._disposables.push(t.onResize(()=>this.clearPredictions()))}catch{}}dispose(){this.clearPredictions();for(let t of this._disposables)try{t.dispose()}catch{}this._disposables=[],this._container?.remove(),this._container=null,this._terminal=null}predictChar(t){try{if(this._reconcile(),this._anchorHold)return!1;let e=this._terminal;if(!e||!this._container)return!1;let n=_(e);if(!n)return!1;let i=e.buffer.active;if(typeof i.cursorX!="number"||typeof i.cursorY!="number"||i.viewportY!==i.baseY||this._predictWhen&&this._predictWhen(e)===!1)return!1;let l=Array.from(t);if(l.length!==1)return!1;let r=l[0].codePointAt(0);if(r<32||r===127)return!1;let s=b(e,l[0]);if(s!==1&&s!==2||s===2&&!this._hasGetCell()||this._outstanding.length>=this._options.maxPending)return!1;this._outstanding.length===0&&(this._anchor={row:i.cursorY,col:i.cursorX},this._cursorOffRowSince=null);let c=this._anchor,d=this._outstanding[this._outstanding.length-1],g=d?d.offsetCells+d.width:0,f=c.col+g;if(f+s>e.cols-this._options.edgeMarginCells)return!1;let u={seq:this._seq++,char:l[0],width:s,offsetCells:g,snapshot:this._readCell(c.row,f),sentAt:performance.now(),mismatches:0};return this._outstanding.push(u),x(this._container,this._spans,{seq:u.seq,row:c.row,col:f,char:u.char,width:s,dims:n,font:this._font,underline:this._options.underlinePredictions}),this._armTtl(),!0}catch{return!1}}predictBackspace(){try{let t=this._outstanding.pop();return t?(h(this._spans,t.seq),this._outstanding.length===0&&this._resetRun(),!0):(this._anchorHold=!0,!1)}catch{return!1}}clearPredictions(){try{this._anchorHold=!0,this._droppedTotal+=this._outstanding.length,this._outstanding=[],y(this._spans),this._resetRun()}catch{}}reconcile(){this._anchorHold=!1,this._safeReconcile()}setPredictWhen(t){this._predictWhen=t}refreshFont(){this._readFontStyle()}get hasPredictions(){return this._outstanding.length>0}get state(){return{outstanding:this._outstanding.length,confirmedTotal:this._confirmedTotal,droppedTotal:this._droppedTotal,anchor:this._anchor?{...this._anchor}:null}}_safeReconcile(){try{this._reconcile()}catch{}}_reconcile(){let t=this._terminal;if(!t||this._outstanding.length===0)return;let e=t.buffer.active;if(e.viewportY!==e.baseY){this.clearPredictions();return}if(typeof e.cursorX!="number"||typeof e.cursorY!="number")return;let n=this._anchor,i=performance.now();if(e.cursorY!==n.row){if(this._cursorOffRowSince??=i,i-this._cursorOffRowSince>this._options.cursorGraceMs){this.clearPredictions();return}}else this._cursorOffRowSince=null;for(;this._outstanding.length>0;){let r=this._outstanding[0];if(this._readCell(n.row,n.col+r.offsetCells)===r.char&&e.cursorY===n.row&&e.cursorX>=n.col+r.offsetCells+r.width)this._outstanding.shift(),h(this._spans,r.seq),this._confirmedTotal++;else break}let l=-1;for(let r=0;r<this._outstanding.length;r++){let s=this._outstanding[r],c=this._readCell(n.row,n.col+s.offsetCells);if(c!==s.snapshot&&c!==s.char&&c!==" "){if(s.mismatches++,s.mismatches>=2){l=r;break}}else s.mismatches=0}l!==-1&&this._dropFrom(l);for(let r=0;r<this._outstanding.length;r++)if(i-this._outstanding[r].sentAt>this._options.ttlMs){this._dropFrom(r);break}this._outstanding.length===0?this._resetRun():this._armTtl()}_dropFrom(t){let e=this._outstanding.splice(t);for(let n of e)h(this._spans,n.seq);this._droppedTotal+=e.length}_resetRun(){this._anchor=null,this._cursorOffRowSince=null,this._ttlTimer!==null&&(clearTimeout(this._ttlTimer),this._ttlTimer=null)}_armTtl(){if(this._ttlTimer!==null)return;let t=this._outstanding[0];if(!t)return;let e=Math.max(0,t.sentAt+this._options.ttlMs-performance.now())+1;this._ttlTimer=setTimeout(()=>{this._ttlTimer=null,this._safeReconcile(),this._armTtl()},e)}_hasGetCell(){let t=this._terminal?.buffer.active;return t?typeof t.getLine(t.baseY+(t.cursorY??0))?.getCell=="function":!1}_readCell(t,e){let n=this._terminal.buffer.active,i=n.getLine(n.baseY+t);if(!i)return" ";if(typeof i.getCell=="function"){let r=i.getCell(e)?.getChars()??"";return r===""?" ":r}return i.translateToString(!0)[e]??" "}_readFontStyle(){let t=this._terminal;if(!t)return;this._font.fontFamily=t.options.fontFamily||"monospace",this._font.fontSize=(t.options.fontSize||14)+"px",this._font.fontWeight=String(t.options.fontWeight||"normal"),this._font.backgroundColor=this._options.backgroundColor??t.options.theme?.background??v,this._font.color=this._options.foregroundColor??t.options.theme?.foreground??C,this._font.letterSpacing="";let e=t.element?.querySelector(".xterm-rows");if(e){let n=getComputedStyle(e);this._font.letterSpacing=n.letterSpacing,!this._options.foregroundColor&&n.color&&(this._font.color=n.color)}}};return R(k);})();
2
2
 
3
3
  // Global aliases for browser usage
4
4
  if(typeof window!=="undefined"){window.PredictiveEchoAddon=XtermPredictiveEcho.PredictiveEchoAddon;window.PredictiveEchoOverlay=class extends XtermPredictiveEcho.PredictiveEchoAddon{constructor(terminal){super({});this.activate(terminal);}};}
@@ -0,0 +1,4 @@
1
+ "use strict";var XtermZerolagInput=(()=>{var D=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var $=(n,t)=>{for(var e in t)D(n,e,{get:t[e],enumerable:!0})},U=(n,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of B(t))!K.call(n,i)&&i!==e&&D(n,i,{get:()=>t[i],enumerable:!(s=I(t,i))||s.enumerable});return n};var Y=n=>U(D({},"__esModule",{value:!0}),n);var N={};$(N,{ZerolagInputAddon:()=>R});function E(n){let t=n,e=typeof devicePixelRatio=="number"&&devicePixelRatio>0?devicePixelRatio:1;if(t.dimensions?.css?.cell){let s=t.dimensions.css.cell.height;return{width:t.dimensions.css.cell.width,height:s,charTop:(t.dimensions?.device?.char?.top??0)/e,charHeight:(t.dimensions?.device?.char?.height??s*e)/e}}try{let s=t._core?._renderService?.dimensions;if(s?.css?.cell){let i=s.css.cell.height;return{width:s.css.cell.width,height:i,charTop:(s.device?.char?.top??0)/e,charHeight:(s.device?.char?.height??i*e)/e}}}catch{}return null}function H(n,t){try{let e=n.buffer.active,s=e.viewportY;switch(t.type){case"character":{for(let i=n.rows-1;i>=0;i--){let h=e.getLine(s+i);if(!h)continue;let c=h.translateToString(!0).lastIndexOf(t.char);if(c>=0)return{row:i,col:c}}return null}case"regex":{let i=t.pattern,h=i.global?new RegExp(i.source,i.flags.replace("g","")):i;for(let f=n.rows-1;f>=0;f--){let c=e.getLine(s+f);if(!c)continue;let d=c.translateToString(!0).match(h);if(d){let g=d.index??0;return{row:f,col:g}}}return null}case"custom":return t.find(n);default:return null}}catch{return null}}function L(n,t,e){try{let s=n.buffer.active,i=s.viewportY+t.row,h=s.getLine(i);return h?h.translateToString(!0).slice(t.col+e).trimEnd():""}catch{return""}}function S(n,t){if(n?.unicode?.getStringCellWidth)return n.unicode.getStringCellWidth(t);let e=t.codePointAt(0);return e!==void 0&&e>=4352&&(e<=4447||e>=11904&&e<=12350||e>=12352&&e<=13247||e>=13312&&e<=19903||e>=19968&&e<=42191||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65072&&e<=65135||e>=65281&&e<=65376||e>=65504&&e<=65510||e>=126976&&e<=130047||e>=131072&&e<=196607||e>=196608&&e<=262143)?2:1}function V(n,t){let e=0;for(let s of t)e+=S(n,s);return e}function k(n,t){let{lines:e,compositionStart:s,startCol:i,totalCols:h,cellW:f,cellH:c,charTop:u,charHeight:d,promptRow:g,totalRows:r,font:_,showCursor:v,cursorColor:P,terminal:T}=t,o=r&&r>0?r:T?.rows,b=[];{let p=0;for(let w of e)b.push(p),p+=[...w].length}let l=e,C=0,m=!0,a=g;o&&o>0&&(e.length>o?(C=e.length-o,l=e.slice(C),m=!1,a=0):g+e.length>o&&(a=o-e.length)),a=Math.max(0,a),n.style.left="0px",n.style.top=a*c+"px",n.innerHTML="";let x=h*f;for(let p=0;p<l.length;p++){let w=p===0&&m,O=w?i*f:0,y=w?x-O:x,A=p*c,W=s===void 0?void 0:s-b[C+p],z=Z(l[p],O,A,y,c,f,u,d,_,T,W);n.appendChild(z)}if(v){let p=l[l.length-1],O=(l.length===1&&m?i:0)+V(T,p);if(O<h){let y=document.createElement("span");y.style.cssText="position:absolute;display:inline-block",y.style.left=O*f+"px",y.style.top=(l.length-1)*c+"px",y.style.width=f+"px",y.style.height=c+"px",y.style.backgroundColor=P,n.appendChild(y)}}n.style.display=""}function Z(n,t,e,s,i,h,f,c,u,d,g){let r=document.createElement("div");r.style.cssText="position:absolute;pointer-events:none",r.style.backgroundColor=u.backgroundColor,r.style.left=t+"px",r.style.top=e+"px",r.style.width=s+"px",r.style.height=i+1+"px";let _=0,v=0;for(let P of n){let T=S(d,P),o=document.createElement("span");o.style.cssText="position:absolute;display:inline-block;text-align:center;pointer-events:none;font-feature-settings:'liga' 0,'calt' 0",o.style.left=_*h+"px",o.style.top="0px",o.style.width=T*h+"px",o.style.height=i+"px",o.style.lineHeight=i+"px",o.style.fontFamily=u.fontFamily,o.style.fontSize=u.fontSize,o.style.fontWeight=u.fontWeight,o.style.color=u.color,u.letterSpacing&&(o.style.letterSpacing=u.letterSpacing),g!==void 0&&v>=g&&(o.style.textDecoration="underline",o.setAttribute("data-zerolag-composition",""),o.setAttribute("aria-hidden","true")),o.textContent=P,r.appendChild(o),_+=T,v++}return r}var F={type:"character",char:">",offset:2},j=7,q=50,X="#0d0d0d",M="#eeeeee",G="#e0e0e0",R=class{_terminal=null;_overlay=null;_options;_pendingText="";_flushedOffset=0;_flushedText="";_bufferDetectDone=!1;_composition="";_lastRenderKey="";_lastPromptPos=null;_font={fontFamily:"monospace",fontSize:"14px",fontWeight:"normal",color:M,backgroundColor:X,letterSpacing:""};_scrollTimer=null;_scrollHandler=null;_scrollViewport=null;constructor(t){this._options={prompt:t?.prompt??F,zIndex:t?.zIndex??j,showCursor:t?.showCursor??!0,scrollDebounceMs:t?.scrollDebounceMs??q,backgroundColor:t?.backgroundColor,foregroundColor:t?.foregroundColor,cursorColor:t?.cursorColor}}activate(t){this._terminal=t,this._overlay=document.createElement("div"),this._overlay.style.cssText=`position:absolute;z-index:${this._options.zIndex};pointer-events:none;display:none`;let e=t.element?.querySelector(".xterm-screen");e&&e.appendChild(this._overlay),this._cacheFont(),this._scrollHandler=()=>{try{let i=this._terminal.buffer.active;i.viewportY!==i.baseY?(this._overlay.style.display="none",this._scrollTimer&&(clearTimeout(this._scrollTimer),this._scrollTimer=null)):this._hasContent()&&(this._scrollTimer&&clearTimeout(this._scrollTimer),this._scrollTimer=setTimeout(()=>{this._scrollTimer=null,this._lastRenderKey="",this._render()},this._options.scrollDebounceMs))}catch{}};let s=t.element?.querySelector(".xterm-viewport");s&&(s.addEventListener("scroll",this._scrollHandler,{passive:!0}),this._scrollViewport=s)}dispose(){this.clear(),this._scrollTimer&&(clearTimeout(this._scrollTimer),this._scrollTimer=null),this._scrollViewport&&this._scrollHandler&&this._scrollViewport.removeEventListener("scroll",this._scrollHandler),this._overlay?.remove(),this._overlay=null,this._scrollViewport=null,this._scrollHandler=null,this._terminal=null}addChar(t){!this._pendingText&&!this._flushedOffset&&this._detectBufferText(),this._pendingText+=t,this._render()}appendText(t){t&&(!this._pendingText&&!this._flushedOffset&&this._detectBufferText(),this._pendingText+=t,this._render())}removeChar(){let t=this._composition.length>0;return this._composition="",this._pendingText.length>0?(this._pendingText=this._pendingText.slice(0,-1),this._pendingText.length>0||this._flushedOffset>0?this._render():this._hide(),"pending"):this._flushedOffset>0?(this._flushedOffset--,this._flushedText=this._flushedText.slice(0,-1),this._flushedOffset>0?this._render():this._hide(),"flushed"):(this._detectBufferText(),this._flushedOffset>0?(this._flushedOffset--,this._flushedText=this._flushedText.slice(0,-1),this._flushedOffset>0?this._render():this._hide(),"flushed"):(t&&this._hide(),!1))}clear(){this._pendingText="",this._composition="",this._flushedOffset=0,this._flushedText="",this._bufferDetectDone=!1,this._lastRenderKey="",this._lastPromptPos=null,this._hide()}setFlushed(t,e,s=!0){this._flushedOffset=t,this._flushedText=e,s&&this._render()}getFlushed(){return{count:this._flushedOffset,text:this._flushedText}}clearFlushed(){this._flushedOffset=0,this._flushedText="",this._pendingText||this._composition?this._render():this._hide()}rerender(){this._hasContent()&&(this._lastRenderKey="",this._render())}refreshFont(){this._cacheFont(),this._lastRenderKey="",this._hasContent()&&this._render()}detectBufferText(){return this._detectBufferText()}resetBufferDetection(){this._bufferDetectDone=!1}undoDetection(){this._flushedOffset=0,this._flushedText="",this._bufferDetectDone=!1}suppressBufferDetection(){this._bufferDetectDone=!0}setPrompt(t){this._options.prompt=t,this._lastPromptPos=null,this._lastRenderKey="",this._hasContent()&&this._render()}setComposition(t){let e=typeof t=="string"?t.replace(/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/g,""):"";e!==this._composition&&(this._composition=e,this._hasContent()?this._render():this._hide())}get composition(){return this._composition}findPrompt(){return this._terminal?H(this._terminal,this._options.prompt??F):null}readPromptText(){if(!this._terminal)return null;let t=this.findPrompt();if(!t)return null;let e=this._getPromptOffset();return L(this._terminal,t,e)||null}get pendingText(){return this._pendingText}get hasPending(){return this._pendingText.length>0||this._flushedOffset>0}get state(){return{pendingText:this._pendingText,flushedLength:this._flushedOffset,flushedText:this._flushedText,visible:this._overlay!==null&&this._overlay.style.display!=="none",promptPosition:this._lastPromptPos?{...this._lastPromptPos}:null}}_hasContent(){return this._pendingText.length>0||this._flushedOffset>0||this._composition.length>0}_getPromptOffset(){return(this._options.prompt??F).offset??2}_detectBufferText(){if(this._bufferDetectDone||!this._terminal)return null;try{let t=this.findPrompt();if(!t)return null;let e=this._getPromptOffset(),s=L(this._terminal,t,e);if(s.length>0)return this._flushedOffset=s.length,this._flushedText=s,this._lastPromptPos=t,this._bufferDetectDone=!0,s}catch{}return null}_cacheFont(){if(!this._terminal)return;let t=this._terminal;this._font.fontFamily=t.options.fontFamily||"monospace",this._font.fontSize=(t.options.fontSize||14)+"px",this._font.fontWeight=String(t.options.fontWeight||"normal"),this._font.backgroundColor=this._options.backgroundColor??t.options.theme?.background??X,this._font.color=this._options.foregroundColor??t.options.theme?.foreground??M,this._font.letterSpacing="";let e=t.element?.querySelector(".xterm-rows");if(e){let s=getComputedStyle(e);this._font.letterSpacing=s.letterSpacing,!this._options.foregroundColor&&s.color&&(this._font.color=s.color)}}_hide(){this._overlay&&(this._lastRenderKey="",this._lastPromptPos=null,this._overlay.innerHTML="",this._overlay.style.display="none")}_render(){if(!(!this._terminal||!this._overlay)){if(!this._hasContent()){this._overlay.style.display="none";return}try{let t=this._terminal.buffer.active;if(t.viewportY!==t.baseY){this._overlay.style.display="none";return}let e=this.findPrompt();if(e)this._lastPromptPos&&this._flushedOffset>0?this._lastPromptPos={row:e.row,col:this._lastPromptPos.col}:this._lastPromptPos=e;else if(!this._lastPromptPos){this._overlay.style.display="none";return}let s=this._lastPromptPos,i=E(this._terminal);if(!i){this._overlay.style.display="none";return}let{width:h,height:f,charTop:c,charHeight:u}=i,d=this._terminal.cols,g=this._getPromptOffset(),r=s.col+g,_=this._pendingText;if(this._flushedOffset>0)if(this._flushedText&&this._flushedText.length===this._flushedOffset)_=this._flushedText+this._pendingText;else{let m=t.viewportY+s.row,a=t.getLine(m);a&&(_=a.translateToString(!0).slice(r,r+this._flushedOffset)+this._pendingText)}let v=[..._].length;_+=this._composition;let P=`${_}:${v}:${r}:${s.row}:${s.col}:${d}:${this._terminal.rows}:${this._flushedOffset}`;if(P===this._lastRenderKey&&this._overlay.style.display!=="none")return;this._lastRenderKey=P;let T=Math.max(1,d-r),o=[..._],b=[],l=0;{let m="",a=0;for(;l<o.length;){let x=S(this._terminal,o[l]);if(a+x>T)break;m+=o[l],a+=x,l++}b.push(m)}for(;l<o.length;){let m="",a=0;for(;l<o.length;){let x=S(this._terminal,o[l]);if(a+x>d)break;m+=o[l],a+=x,l++}b.push(m)}let C=this._options.cursorColor??this._terminal.options.theme?.cursor??G;k(this._overlay,{lines:b,compositionStart:this._composition?v:void 0,startCol:r,totalCols:d,cellW:h,cellH:f,charTop:c,charHeight:u,promptRow:s.row,totalRows:this._terminal.rows,font:this._font,showCursor:this._options.showCursor,cursorColor:C,terminal:this._terminal})}catch{this._overlay&&(this._overlay.innerHTML="",this._overlay.style.display="none")}}}};return Y(N);})();
2
+
3
+ // Global aliases for browser usage
4
+ if(typeof window!=="undefined"){window.ZerolagInputAddon=XtermZerolagInput.ZerolagInputAddon;window.LocalEchoOverlay=class extends XtermZerolagInput.ZerolagInputAddon{constructor(terminal){super({prompt:{type:"character",char:"\u276f",offset:2}});this.activate(terminal);}};}
Binary file
@@ -304,13 +304,26 @@ Object.assign(CodemanApp.prototype, {
304
304
  let idx = startIndex;
305
305
 
306
306
  for (const id of this.webviewOrder) {
307
- const webview = this.webviews.get(id);
308
- if (!webview) continue;
309
- const isActive = id === this.activeWebviewId;
310
- const jsonId = escapeHtml(JSON.stringify(id));
311
- const icon = webview.icon ? escapeHtml(webview.icon) : '';
307
+ if (!this.webviews.get(id)) continue;
308
+ parts.push(this.renderWebviewTab(id, idx));
309
+ idx++;
310
+ }
311
+ return parts.join('');
312
+ },
312
313
 
313
- parts.push(`<div class="session-tab session-tab--web ${isActive ? 'active' : ''}" data-webview-id="${escapeHtml(id)}"
314
+ /**
315
+ * One web tab's HTML; `idx` is its zero-based Alt+N slot (no badge from 9 up).
316
+ * The grouped vertical rail places single web tabs into their group with this,
317
+ * so a web tab's markup is the same in every layout.
318
+ */
319
+ renderWebviewTab(id, idx) {
320
+ const webview = this.webviews.get(id);
321
+ if (!webview) return '';
322
+ const isActive = id === this.activeWebviewId;
323
+ const jsonId = escapeHtml(JSON.stringify(id));
324
+ const icon = webview.icon ? escapeHtml(webview.icon) : '';
325
+
326
+ return `<div class="session-tab session-tab--web ${isActive ? 'active' : ''}" data-webview-id="${escapeHtml(id)}"
314
327
  onclick="app.handleWebviewTabClick(event, ${jsonId})"
315
328
  tabindex="0" role="tab" aria-selected="${isActive ? 'true' : 'false'}"
316
329
  aria-label="${escapeHtml(webview.name)} web tab" title="${escapeHtml(webview.url)}">
@@ -322,10 +335,7 @@ Object.assign(CodemanApp.prototype, {
322
335
  </span>
323
336
  </span>
324
337
  <span class="tab-actions"><span class="tab-gear" onclick="event.stopPropagation(); app.showWebviewModal(${jsonId})" title="URL settings" aria-label="URL settings" tabindex="0">&#x2699;</span><span class="tab-close" onclick="event.stopPropagation(); app.closeWebviewTab(${jsonId})" title="Close tab" aria-label="Close web tab" tabindex="0">&times;</span></span>
325
- </div>`);
326
- idx++;
327
- }
328
- return parts.join('');
338
+ </div>`;
329
339
  },
330
340
 
331
341
  _webviewGlobeIcon() {
@@ -348,6 +358,7 @@ Object.assign(CodemanApp.prototype, {
348
358
  // A web tab is active, so no session tab may also look active.
349
359
  for (const tab of container.querySelectorAll('.session-tab[data-id]')) tab.classList.remove('active');
350
360
  }
361
+ this._syncTabTreeSelection?.(container);
351
362
  },
352
363
 
353
364
  // ── Opening / closing ─────────────────────────────────────────────────────
Binary file
Binary file
@@ -18,7 +18,8 @@
18
18
  * session record involved. A dropped plan therefore returns the user to
19
19
  * resuming by hand, one at a time, which is where they are without this
20
20
  * feature. What the plan held that a transcript does not is the owner, the
21
- * name, the env overrides, the effort and the lineage.
21
+ * name, the env overrides, the effort, the model, the advisor model and the
22
+ * lineage.
22
23
  * - Module-level singleton in the style of `web/approval-inbox.ts`: no `Session`
23
24
  * import and no IO, which keeps it unit-testable and cycle-free.
24
25
  * - Spending is take-then-build: `take()` removes entries synchronously, before
@@ -1 +1 @@
1
- {"version":3,"file":"reboot-restore-registry.d.ts","sourceRoot":"","sources":["../../src/web/reboot-restore-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAQ/D,qBAAa,qBAAqB;IAChC,kEAAkE;IAClE,OAAO,CAAC,OAAO,CAAyC;IACxD,gEAAgE;IAChE,OAAO,CAAC,OAAO,CAAK;IACpB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAAM,CAAiF;IAC/F;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAiC;IAEjD,+EAA+E;IAC/E,GAAG,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI;IAOjD;;;;;;OAMG;IACH,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,GAAG,kBAAkB,EAAE;IAK7E;;;;;;;;OAQG;IACH,IAAI,CACF,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,EACjD,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACzC,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,kBAAkB,EAAE;IAgBvB;;;;;;;;OAQG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI;IAiBrF,gEAAgE;IAChE,KAAK,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,GAAG,MAAM;IAgBhE;;;;OAIG;IACH,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IAMtC,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAIjC,uEAAuE;IACvE,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,aAAa;CAStB;AAED,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,uBAA8B,CAAC"}
1
+ {"version":3,"file":"reboot-restore-registry.d.ts","sourceRoot":"","sources":["../../src/web/reboot-restore-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAQ/D,qBAAa,qBAAqB;IAChC,kEAAkE;IAClE,OAAO,CAAC,OAAO,CAAyC;IACxD,gEAAgE;IAChE,OAAO,CAAC,OAAO,CAAK;IACpB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAAM,CAAiF;IAC/F;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAiC;IAEjD,+EAA+E;IAC/E,GAAG,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI;IAOjD;;;;;;OAMG;IACH,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,GAAG,kBAAkB,EAAE;IAK7E;;;;;;;;OAQG;IACH,IAAI,CACF,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,EACjD,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACzC,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,kBAAkB,EAAE;IAgBvB;;;;;;;;OAQG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI;IAiBrF,gEAAgE;IAChE,KAAK,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,GAAG,MAAM;IAgBhE;;;;OAIG;IACH,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IAMtC,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAIjC,uEAAuE;IACvE,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,aAAa;CAStB;AAED,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,uBAA8B,CAAC"}
@@ -18,7 +18,8 @@
18
18
  * session record involved. A dropped plan therefore returns the user to
19
19
  * resuming by hand, one at a time, which is where they are without this
20
20
  * feature. What the plan held that a transcript does not is the owner, the
21
- * name, the env overrides, the effort and the lineage.
21
+ * name, the env overrides, the effort, the model, the advisor model and the
22
+ * lineage.
22
23
  * - Module-level singleton in the style of `web/approval-inbox.ts`: no `Session`
23
24
  * import and no IO, which keeps it unit-testable and cycle-free.
24
25
  * - Spending is take-then-build: `take()` removes entries synchronously, before
@@ -1 +1 @@
1
- {"version":3,"file":"reboot-restore-registry.js","sourceRoot":"","sources":["../../src/web/reboot-restore-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reboot-restore-registry.js","sourceRoot":"","sources":["../../src/web/reboot-restore-registry.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"case-routes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/case-routes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA6D1C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AA4D9C;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAE1E;AAsGD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,CAkmDxG"}
1
+ {"version":3,"file":"case-routes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/case-routes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA+D1C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AA4D9C;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAE1E;AAyGD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,CA+tDxG"}
@@ -16,6 +16,8 @@ import { CreateCaseSchema, CloneCaseSchema, ClonePreflightSchema, LinkCaseSchema
16
16
  import { exportDockerCase, importDockerBundle, listDockerExports, exportBundleName } from '../../docker-export.js';
17
17
  import { cloneRepository, isGitAvailable, isSafeGitRef, parseGitRepositoryUrl, probeGitRemote, } from '../../git-clone.js';
18
18
  import { generateClaudeMd } from '../../templates/claude-md.js';
19
+ import { prepareNewCasePath } from '../case-path.js';
20
+ import { boundedPathExists, describeUnknownPath, probePath } from '../../utils/index.js';
19
21
  import { readAgentCaseMarker } from '../../agent-case-marker.js';
20
22
  import { settingsWriteBlocker, writeHooksConfig } from '../../hooks-config.js';
21
23
  import { canAccessOwned, getAuthUser, isAdmin, isWorkingDirAllowed, ownerFor, resolveCasesDir, SETTINGS_PATH, validatePathWithinBase, parseBody, readJsonConfig, } from '../route-helpers.js';
@@ -81,6 +83,9 @@ function gitDiagnosticLine(stderr) {
81
83
  * the clone response says so out loud instead of silently merging into them.
82
84
  */
83
85
  function repoShipsClaudeSettings(casePath) {
86
+ // Deliberately NOT the bounded path probe: the tree was just cloned into the
87
+ // local case space (and lstat'ed synchronously moments ago), so a bound protects
88
+ // nothing here, while a probe answering "unknown" could silently drop this warning.
84
89
  return ['settings.json', 'settings.local.json'].some((file) => existsSync(join(casePath, '.claude', file)));
85
90
  }
86
91
  /**
@@ -170,7 +175,7 @@ export function registerCaseRoutes(app, ctx) {
170
175
  cases.push({
171
176
  name: e.name,
172
177
  path: casePath,
173
- hasClaudeMd: existsSync(join(casePath, 'CLAUDE.md')),
178
+ hasClaudeMd: await boundedPathExists(join(casePath, 'CLAUDE.md')),
174
179
  location: 'local',
175
180
  ...(marker ? { agentCreated: agentCreatedInfo(marker) } : {}),
176
181
  });
@@ -185,15 +190,21 @@ export function registerCaseRoutes(app, ctx) {
185
190
  const existingNames = new Set(cases.map((c) => c.name));
186
191
  if (admin) {
187
192
  for (const [name, path] of Object.entries(linkedCases)) {
188
- if (!existingNames.has(name) && SAFE_CASE_NAME.test(name) && existsSync(path)) {
189
- cases.push({
190
- name,
191
- path,
192
- hasClaudeMd: existsSync(join(path, 'CLAUDE.md')),
193
- linked: true,
194
- location: 'linked-local',
195
- });
196
- }
193
+ if (existingNames.has(name) || !SAFE_CASE_NAME.test(name))
194
+ continue;
195
+ const state = await probePath(path);
196
+ if (state === 'absent')
197
+ continue;
198
+ // An unreachable linked case (a dead network mount) stays listed and says
199
+ // so: dropping it would read as "deleted" and invite a same-name local case.
200
+ cases.push({
201
+ name,
202
+ path,
203
+ hasClaudeMd: state === 'present' && (await boundedPathExists(join(path, 'CLAUDE.md'))),
204
+ linked: true,
205
+ location: 'linked-local',
206
+ ...(state === 'unknown' ? { unreachable: true } : {}),
207
+ });
197
208
  }
198
209
  }
199
210
  // Get remote cases (owner-scoped; legacy no-owner = admin-only)
@@ -240,7 +251,7 @@ export function registerCaseRoutes(app, ctx) {
240
251
  const dockerCaseInfo = {
241
252
  name: dockerCase.name,
242
253
  path: dockerDisplayPath({ container, path: dockerCase.hostWorkspacePath }),
243
- hasClaudeMd: existsSync(join(dockerCase.hostWorkspacePath, 'CLAUDE.md')),
254
+ hasClaudeMd: await boundedPathExists(join(dockerCase.hostWorkspacePath, 'CLAUDE.md')),
244
255
  location: 'docker',
245
256
  docker: {
246
257
  hostId: host.id,
@@ -325,8 +336,98 @@ export function registerCaseRoutes(app, ctx) {
325
336
  summaries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
326
337
  return { success: true, data: { cases: summaries } };
327
338
  });
328
- app.post('/api/cases', async (req) => {
329
- const { name, description } = parseBody(CreateCaseSchema, req.body);
339
+ /**
340
+ * `POST /api/cases` with a `path`: create the folder (or fill an EMPTY existing one), scaffold it
341
+ * exactly like a normal case, and register it in the linked-cases registry so it lists, resolves
342
+ * and deletes (unlinks, never removes files) like any linked case. Everything is judged before
343
+ * anything is written; a failure after the first write undoes what this call created.
344
+ */
345
+ async function createCaseInCustomFolder(name, description, customPath, req, reply) {
346
+ const ownCasesDir = resolveCasesDir(getAuthUser(req));
347
+ if (existsSync(join(ownCasesDir, name))) {
348
+ reply.code(409);
349
+ return createErrorResponse(ApiErrorCode.ALREADY_EXISTS, 'A case with this name already exists in codeman-cases.');
350
+ }
351
+ const linkedCases = await readLinkedCases();
352
+ if (linkedCases[name]) {
353
+ reply.code(409);
354
+ return createErrorResponse(ApiErrorCode.ALREADY_EXISTS, `Case "${name}" is already linked to ${linkedCases[name]}`);
355
+ }
356
+ // The caller's own cases dir and the shared one (the same folder outside multi-user mode).
357
+ const casesDirs = [...new Set([ownCasesDir, resolveCasesDir()])];
358
+ const prepared = await prepareNewCasePath(customPath, { home: homedir(), dataDir: getDataDir(), casesDirs });
359
+ if (!prepared.ok) {
360
+ // A parent that did not answer is not a bad request: OPERATION_FAILED (422), like
361
+ // POST /api/sessions for a workingDir on a dead mount.
362
+ if (prepared.code === 'UNREACHABLE') {
363
+ reply.code(422);
364
+ return createErrorResponse(ApiErrorCode.OPERATION_FAILED, prepared.reason);
365
+ }
366
+ const status = prepared.code === 'NOT_FOUND' ? 404 : prepared.code === 'EXISTS' ? 409 : 400;
367
+ reply.code(status);
368
+ const code = prepared.code === 'NOT_FOUND'
369
+ ? ApiErrorCode.NOT_FOUND
370
+ : prepared.code === 'EXISTS'
371
+ ? ApiErrorCode.ALREADY_EXISTS
372
+ : ApiErrorCode.INVALID_INPUT;
373
+ return createErrorResponse(code, prepared.reason);
374
+ }
375
+ const casePath = prepared.path;
376
+ const alreadyAs = Object.entries(linkedCases).find(([, p]) => p === casePath)?.[0];
377
+ if (alreadyAs) {
378
+ reply.code(409);
379
+ return createErrorResponse(ApiErrorCode.ALREADY_EXISTS, `That folder is already the case "${alreadyAs}"`);
380
+ }
381
+ const made = [];
382
+ try {
383
+ if (!prepared.existedEmpty) {
384
+ mkdirSync(casePath);
385
+ made.push(casePath);
386
+ }
387
+ mkdirSync(join(casePath, 'src'));
388
+ made.push(join(casePath, 'src'));
389
+ const templatePath = await ctx.getDefaultClaudeMdPath();
390
+ writeFileSync(join(casePath, 'CLAUDE.md'), generateClaudeMd(name, description || '', templatePath));
391
+ made.push(join(casePath, 'CLAUDE.md'));
392
+ made.push(join(casePath, '.claude')); // before the write, so a half-written one is undone too
393
+ await writeHooksConfig(casePath);
394
+ const codemanDir = getDataDir();
395
+ if (!existsSync(codemanDir))
396
+ mkdirSync(codemanDir, { recursive: true });
397
+ // Re-read right before writing, so a case linked since the check above is not dropped. This only
398
+ // narrows the window: like POST /api/cases/link, the registry write is not serialized, and two
399
+ // requests that both read before either writes can still lose one entry.
400
+ const fresh = await readLinkedCases();
401
+ if (fresh[name])
402
+ throw Object.assign(new Error(`Case "${name}" was just linked`), { conflict: true });
403
+ fresh[name] = casePath;
404
+ await fs.writeFile(LINKED_CASES_FILE, JSON.stringify(fresh, null, 2));
405
+ ctx.broadcast(SseEvent.CaseCreated, { name, path: casePath });
406
+ return { success: true, data: { case: { name, path: casePath } } };
407
+ }
408
+ catch (err) {
409
+ // Undo only what this call made. The whole folder if we created it, otherwise the scaffold
410
+ // entries inside the empty folder the user picked; never anything else.
411
+ for (const p of made.reverse())
412
+ await fs.rm(p, { recursive: true, force: true }).catch(() => undefined);
413
+ if (err.conflict) {
414
+ reply.code(409);
415
+ return createErrorResponse(ApiErrorCode.ALREADY_EXISTS, getErrorMessage(err));
416
+ }
417
+ reply.code(500);
418
+ return createErrorResponse(ApiErrorCode.OPERATION_FAILED, getErrorMessage(err));
419
+ }
420
+ }
421
+ app.post('/api/cases', async (req, reply) => {
422
+ const { name, description, path: customPath } = parseBody(CreateCaseSchema, req.body);
423
+ // A custom folder writes outside the cases directory and registers the path in the shared,
424
+ // ownerless linked-cases registry, so it carries the same bar as POST /api/cases/link.
425
+ if (customPath !== undefined) {
426
+ const denied = adminOnly(req, reply);
427
+ if (denied)
428
+ return denied;
429
+ return createCaseInCustomFolder(name, description, customPath, req, reply);
430
+ }
330
431
  const casePath = validatePathWithinBase(name, resolveCasesDir(getAuthUser(req)));
331
432
  if (!casePath) {
332
433
  return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Invalid case path');
@@ -1328,7 +1429,7 @@ export function registerCaseRoutes(app, ctx) {
1328
1429
  return {
1329
1430
  name,
1330
1431
  path: dockerDisplayPath({ container, path: dockerCase.hostWorkspacePath }),
1331
- hasClaudeMd: existsSync(join(dockerCase.hostWorkspacePath, 'CLAUDE.md')),
1432
+ hasClaudeMd: await boundedPathExists(join(dockerCase.hostWorkspacePath, 'CLAUDE.md')),
1332
1433
  location: 'docker',
1333
1434
  docker: {
1334
1435
  hostId: host.id,
@@ -1342,14 +1443,27 @@ export function registerCaseRoutes(app, ctx) {
1342
1443
  };
1343
1444
  }
1344
1445
  const casePath = await resolveCasePath(name, getAuthUser(req));
1345
- if (!existsSync(casePath)) {
1446
+ const linked = casePath !== join(resolveCasesDir(getAuthUser(req)), name);
1447
+ // NOT_FOUND means DEFINITELY absent: the Run button creates a case on it, so
1448
+ // a path that merely did not answer (a dead network mount) must never get it.
1449
+ // One path, asked for explicitly: probe it even while unrelated mounts are dead.
1450
+ const state = await probePath(casePath, { pastCap: true });
1451
+ if (state === 'absent') {
1346
1452
  return createErrorResponse(ApiErrorCode.NOT_FOUND, 'Case not found');
1347
1453
  }
1348
- const linked = casePath !== join(resolveCasesDir(getAuthUser(req)), name);
1454
+ if (state === 'unknown') {
1455
+ // The linked registry knows where the case lives, so say where, and that
1456
+ // it is not answering. A local case has no such record to fall back on.
1457
+ if (!linked) {
1458
+ return createErrorResponse(ApiErrorCode.OPERATION_FAILED, describeUnknownPath('Case folder', casePath, { pastCap: true }));
1459
+ }
1460
+ return { name, path: casePath, hasClaudeMd: false, linked: true, unreachable: true };
1461
+ }
1349
1462
  return {
1350
1463
  name,
1351
1464
  path: casePath,
1352
- hasClaudeMd: existsSync(join(casePath, 'CLAUDE.md')),
1465
+ // Probed like the folder above, or a healthy case reads as having no CLAUDE.md under the cap.
1466
+ hasClaudeMd: (await probePath(join(casePath, 'CLAUDE.md'), { pastCap: true })) === 'present',
1353
1467
  ...(linked && { linked: true }),
1354
1468
  };
1355
1469
  });
@@ -1362,7 +1476,11 @@ export function registerCaseRoutes(app, ctx) {
1362
1476
  // Get case path (check linked cases first, then CASES_DIR)
1363
1477
  const casePath = await resolveCasePath(name, getAuthUser(req));
1364
1478
  const fixPlanPath = join(casePath, '@fix_plan.md');
1365
- if (!existsSync(fixPlanPath)) {
1479
+ const fixPlanState = await probePath(fixPlanPath, { pastCap: true });
1480
+ if (fixPlanState === 'unknown') {
1481
+ return createErrorResponse(ApiErrorCode.OPERATION_FAILED, 'Case folder is not responding or not readable');
1482
+ }
1483
+ if (fixPlanState === 'absent') {
1366
1484
  return { exists: false, content: null, todos: [] };
1367
1485
  }
1368
1486
  try {