@aiworker/web 1.22.0 → 1.23.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 (415) hide show
  1. package/README.md +4 -4
  2. package/bin/cli.js +14 -4
  3. package/bin/cli.test.js +165 -73
  4. package/bin/lib/cli-api-target.js +2 -2
  5. package/bin/lib/cli-args.js +119 -119
  6. package/bin/lib/cli-lifecycle.js +9 -9
  7. package/bin/lib/cli-network.js +3 -3
  8. package/bin/lib/cli-paths.js +3 -3
  9. package/bin/lib/cli-ports.js +2 -2
  10. package/bin/lib/cli-process.js +4 -4
  11. package/bin/lib/cli-startup.js +64 -15
  12. package/bin/lib/cli-tunnel-profiles.js +1 -1
  13. package/bin/lib/cli-tunnel-utils.js +2 -2
  14. package/bin/lib/commands-connect-url.js +19 -19
  15. package/bin/lib/commands-lifecycle.js +27 -27
  16. package/bin/lib/commands-logs.js +5 -5
  17. package/bin/lib/commands-models.js +1 -1
  18. package/bin/lib/commands-projects.js +1 -1
  19. package/bin/lib/commands-schedule.js +1 -1
  20. package/bin/lib/commands-serve.js +29 -29
  21. package/bin/lib/commands-session.js +1 -1
  22. package/bin/lib/commands-startup.js +45 -10
  23. package/bin/lib/commands-status.js +1 -1
  24. package/bin/lib/commands-tunnel.js +40 -40
  25. package/bin/lib/commands-update.js +1 -1
  26. package/bin/lib/commands-update.test.js +6 -6
  27. package/dist/assets/{CodeMirrorCommentWidgets-B3u7UIcE.js → CodeMirrorCommentWidgets-B1Gizi3a.js} +1 -1
  28. package/dist/assets/DiffView-DXjVsEOw.js +4 -0
  29. package/dist/assets/DirtyBranchSwitchDialog-aig6zJjg.js +1 -0
  30. package/dist/assets/FilesView-CJdG0-wk.js +17 -0
  31. package/dist/assets/GitView-BXsS3jG6.js +6 -0
  32. package/dist/assets/{JsonTreeView-B0BdZEHG.js → JsonTreeView-D_hpXBnF.js} +1 -1
  33. package/dist/assets/LinearIssuesView-BoUiLQG1.js +1 -0
  34. package/dist/assets/MarkdownImageGallery-B_B_a9KS.js +1 -0
  35. package/dist/assets/MarkdownRendererImpl-xgyyLiBM.js +12 -0
  36. package/dist/assets/OnboardingScreen-DIp84OWt.js +1 -0
  37. package/dist/assets/{PatchDiff-DvfqDql7.js → PatchDiff-8p6nLJaU.js} +1 -1
  38. package/dist/assets/PierreDiffViewer-DjC8nTk9.js +161 -0
  39. package/dist/assets/PlanView-CJTmOF6I.js +5 -0
  40. package/dist/assets/SettingsView-DD-JqIJx.js +28 -0
  41. package/dist/assets/{SettingsWindow-i45U1Cy1.js → SettingsWindow-Cpb4hM6q.js} +1 -1
  42. package/dist/assets/SymbolsNerdFontMono-Regular-aK5vsLov.woff2 +0 -0
  43. package/dist/assets/{ToolOutputDialog-BTwyh5OF.js → ToolOutputDialog-DfaKZXNU.js} +6 -6
  44. package/dist/assets/ToolPartDiffPreview-DtZLzrSK.js +8 -0
  45. package/dist/assets/{VirtualizedFileDiff-DD8lDVej.js → VirtualizedFileDiff-C8i9HpTB.js} +1 -1
  46. package/dist/assets/WalkthroughView-DeKMvZlL.js +4 -0
  47. package/dist/assets/{computeVirtualFileMetrics-BMIRgMHv.js → computeVirtualFileMetrics-BBI7ZwrC.js} +2 -2
  48. package/dist/assets/contextPanelEmbeddedChat-BdA6bdky.js +1 -0
  49. package/dist/assets/de-DCrsQ5zS.js +10 -0
  50. package/dist/assets/es-Dwv4YfH6.js +16 -0
  51. package/dist/assets/fr-BCWg4Cnx.js +14 -0
  52. package/dist/assets/ghostty-vt-DdA0Zryv.wasm +0 -0
  53. package/dist/assets/index-B68h5S5B.css +1 -0
  54. package/dist/assets/index-DVwMarHI.js +39 -0
  55. package/dist/assets/{index-CODwDsU_.js → index-jXSK5RrB.js} +1 -1
  56. package/dist/assets/{isDiffPlainText-BqayB8d3.js → isDiffPlainText-B_x_rVon.js} +1 -1
  57. package/dist/assets/{isFilePlainText-QfoiKJNY.js → isFilePlainText-DW_xMer1.js} +1 -1
  58. package/dist/assets/ja-Bruw3RYC.js +16 -0
  59. package/dist/assets/ko-idhXGF8j.js +16 -0
  60. package/dist/assets/main-BkyaQhJX.js +930 -0
  61. package/dist/assets/{main-C5DVOxc6.js → main-CzdPuL0s.js} +2 -2
  62. package/dist/assets/markdownCore-Cn4Tyejo.js +5 -0
  63. package/dist/assets/{miniChat-DUJ4irZc.js → miniChat-CCkqKOLp.js} +2 -2
  64. package/dist/assets/{mobile-CcaxB0n4.js → mobile-mvxTo055.js} +2 -2
  65. package/dist/assets/patchFileDiff-Csk4iNUi.js +13 -0
  66. package/dist/assets/pl-CGZWUqZJ.js +16 -0
  67. package/dist/assets/pt-BR-B8V7u7tA.js +16 -0
  68. package/dist/assets/renderElectronMiniChatApp-BxoyujA5.js +2 -0
  69. package/dist/assets/renderMobileApp-B48CsP4r.js +25 -0
  70. package/dist/assets/runtimeEndpointReset-Bg5gx18H.js +17 -0
  71. package/dist/assets/scheduledTasksApi-BW0Etzwz.js +1 -0
  72. package/dist/assets/{shikiHighlight-DYOWuY65.js → shikiHighlight-CRl0SUC9.js} +1 -1
  73. package/dist/assets/surface-oMvhsog3.js +1 -0
  74. package/dist/assets/tr-BK_KiO2V.js +7 -0
  75. package/dist/assets/uk-CG74xV8N.js +16 -0
  76. package/dist/assets/useAppFontEffects-CPKeOpUo.js +7284 -0
  77. package/dist/assets/useGitComparison-DH220WmO.js +1 -0
  78. package/dist/assets/useInlineCommentController-BiWz4AVb.js +2 -0
  79. package/dist/assets/useRootScrollLock-BS4-kr7P.js +1 -0
  80. package/dist/assets/{vendor-base-ui-BeMD8X_w.js → vendor-base-ui-DdV8vhHn.js} +1 -1
  81. package/dist/assets/{vendor-codemirror-language-data-DFZik9R2.js → vendor-codemirror-language-data-Bg4AEeCr.js} +2 -2
  82. package/dist/assets/vendor-zod-BPAANqvH.js +39 -0
  83. package/dist/assets/{web-components-Bhg83tjf.js → web-components-z7hfnS8n.js} +1 -1
  84. package/dist/assets/zh-CN-T4AXofZI.js +16 -0
  85. package/dist/assets/zh-TW-Dte40sxp.js +16 -0
  86. package/dist/index.html +21 -59
  87. package/dist/mini-chat.html +7 -7
  88. package/dist/mobile.html +5 -5
  89. package/package.json +3 -4
  90. package/server/index.d.ts +15 -0
  91. package/server/index.js +158 -89
  92. package/server/lib/agent-memory/actions.js +2 -2
  93. package/server/lib/agent-memory/feature-flag.js +1 -1
  94. package/server/lib/agent-memory/feature-flag.test.js +8 -8
  95. package/server/lib/agent-memory/routes.js +2 -2
  96. package/server/lib/agent-tool/runtime.js +37 -54
  97. package/server/lib/agent-tool/runtime.test.js +59 -59
  98. package/server/lib/browser-control/broker.js +3 -3
  99. package/server/lib/browser-control/broker.test.js +1 -1
  100. package/server/lib/changelog/update-notes.js +82 -0
  101. package/server/lib/changelog/update-notes.test.js +59 -0
  102. package/server/lib/client-auth/remote-clients.test.js +5 -5
  103. package/server/lib/context-obligatory/runtime.js +7 -7
  104. package/server/lib/context-obligatory/runtime.test.js +5 -5
  105. package/server/lib/data-dir-migration.js +40 -0
  106. package/server/lib/data-dir-migration.test.js +59 -0
  107. package/server/lib/dev-servers/parse.js +2 -2
  108. package/server/lib/dev-servers/parse.test.js +2 -2
  109. package/server/lib/dev-servers/routes.js +1 -1
  110. package/server/lib/dev-tunnel/DOCUMENTATION.md +13 -4
  111. package/server/lib/dev-tunnel/client.js +1 -1
  112. package/server/lib/dev-tunnel/runtime.js +5 -5
  113. package/server/lib/dev-tunnel/tunnel.test.js +21 -1
  114. package/server/lib/dictation/local/model-catalog.js +1 -1
  115. package/server/lib/dictation/local/worker-process.js +2 -2
  116. package/server/lib/event-stream/directory-ws-bridge.js +1 -1
  117. package/server/lib/event-stream/global-ws-bridge.js +1 -1
  118. package/server/lib/event-stream/protocol.test.js +4 -4
  119. package/server/lib/event-stream/runtime.test.js +18 -18
  120. package/server/lib/fs/DOCUMENTATION.md +5 -0
  121. package/server/lib/fs/routes.js +68 -26
  122. package/server/lib/fs/routes.test.js +208 -22
  123. package/server/lib/git/DOCUMENTATION.md +32 -6
  124. package/server/lib/git/identity-storage.js +1 -1
  125. package/server/lib/git/issue-2746-longpaths.test.js +4 -4
  126. package/server/lib/git/routes.js +41 -5
  127. package/server/lib/git/service.js +300 -224
  128. package/server/lib/git/service.test.js +596 -28
  129. package/server/lib/github/auth.js +8 -8
  130. package/server/lib/github/pr-status.js +1 -1
  131. package/server/lib/github/routes.js +2 -2
  132. package/server/lib/inherited-env.js +17 -10
  133. package/server/lib/inherited-env.test.js +10 -11
  134. package/server/lib/linear/auth.js +8 -8
  135. package/server/lib/linear/auth.test.js +24 -24
  136. package/server/lib/linear/issues.test.js +6 -6
  137. package/server/lib/linear/mapping.test.js +4 -4
  138. package/server/lib/linear/oauth.js +2 -2
  139. package/server/lib/linear/oauth.test.js +14 -14
  140. package/server/lib/linear/routes.js +5 -5
  141. package/server/lib/linear/routes.test.js +16 -16
  142. package/server/lib/linear/status-runtime.test.js +9 -9
  143. package/server/lib/linear/status.js +1 -1
  144. package/server/lib/linear/status.test.js +15 -15
  145. package/server/lib/linear/teams.test.js +4 -4
  146. package/server/lib/magic-prompts/routes.js +2 -2
  147. package/server/lib/mcp-reconnect/DOCUMENTATION.md +55 -0
  148. package/server/lib/mcp-reconnect/runtime.js +122 -0
  149. package/server/lib/mcp-reconnect/runtime.test.js +140 -0
  150. package/server/lib/message-queue/DOCUMENTATION.md +161 -0
  151. package/server/lib/message-queue/runtime.js +870 -0
  152. package/server/lib/message-queue/runtime.test.js +482 -0
  153. package/server/lib/network-defaults.js +23 -0
  154. package/server/lib/network-defaults.test.js +52 -0
  155. package/server/lib/notifications/apns-runtime.js +17 -17
  156. package/server/lib/notifications/apns-runtime.test.js +11 -11
  157. package/server/lib/notifications/emitter-runtime.js +1 -1
  158. package/server/lib/notifications/emitter-runtime.test.js +1 -1
  159. package/server/lib/notifications/push-runtime.js +7 -7
  160. package/server/lib/notifications/routes.js +1 -1
  161. package/server/lib/notifications/runtime.js +1 -1
  162. package/server/lib/openchamber-control/action-resolution.test.js +10 -10
  163. package/server/lib/openchamber-control/actions.js +24 -24
  164. package/server/lib/openchamber-control/error.js +4 -4
  165. package/server/lib/openchamber-control/routes.js +2 -2
  166. package/server/lib/openchamber-control/routes.test.js +5 -5
  167. package/server/lib/openchamber-control/screenshots.js +1 -1
  168. package/server/lib/openchamber-control/screenshots.test.js +1 -1
  169. package/server/lib/openchamber-control/service.js +50 -50
  170. package/server/lib/openchamber-control/service.test.js +5 -5
  171. package/server/lib/openchamber-sessions/routes.js +124 -22
  172. package/server/lib/openchamber-sessions/routes.test.js +99 -11
  173. package/server/lib/opencode/DOCUMENTATION.md +30 -6
  174. package/server/lib/opencode/auth.js +1 -1
  175. package/server/lib/opencode/bootstrap-runtime.js +8 -6
  176. package/server/lib/opencode/cli-options.js +8 -8
  177. package/server/lib/opencode/config-paths.test.js +116 -0
  178. package/server/lib/opencode/core-routes.js +8 -7
  179. package/server/lib/opencode/core-routes.test.js +11 -11
  180. package/server/lib/opencode/env-config.js +5 -5
  181. package/server/lib/opencode/env-config.test.js +7 -7
  182. package/server/lib/opencode/env-runtime.js +10 -10
  183. package/server/lib/opencode/env-runtime.test.js +18 -18
  184. package/server/lib/opencode/feature-routes-runtime.js +19 -12
  185. package/server/lib/opencode/hmr-state-runtime.js +2 -2
  186. package/server/lib/opencode/hmr-state-runtime.test.js +1 -1
  187. package/server/lib/opencode/input-history-scope.js +14 -0
  188. package/server/lib/opencode/lifecycle.js +8 -8
  189. package/server/lib/opencode/lifecycle.test.js +4 -4
  190. package/server/lib/opencode/managed-plugin-config.js +35 -0
  191. package/server/lib/opencode/managed-process-registry.js +3 -3
  192. package/server/lib/opencode/mcp-oauth-callback.test.js +2 -2
  193. package/server/lib/opencode/openchamber-routes.js +79 -19
  194. package/server/lib/opencode/openchamber-routes.test.js +139 -12
  195. package/server/lib/opencode/plugins.js +2 -2
  196. package/server/lib/opencode/plugins.test.js +1 -1
  197. package/server/lib/opencode/project-icon-routes.js +2 -2
  198. package/server/lib/opencode/project-icon-routes.test.js +1 -1
  199. package/server/lib/opencode/providers.js +44 -2
  200. package/server/lib/opencode/providers.test.js +131 -4
  201. package/server/lib/opencode/proxy.js +2 -2
  202. package/server/lib/opencode/pwa-manifest-routes.js +1 -1
  203. package/server/lib/opencode/restart-session-recovery.test.js +1 -1
  204. package/server/lib/opencode/routes-upgrade.test.js +4 -4
  205. package/server/lib/opencode/routes.js +19 -17
  206. package/server/lib/opencode/server-startup-runtime.js +6 -6
  207. package/server/lib/opencode/session-runtime.js +3 -3
  208. package/server/lib/opencode/session-runtime.test.js +6 -6
  209. package/server/lib/opencode/settings-files.js +214 -0
  210. package/server/lib/opencode/settings-helpers.js +116 -44
  211. package/server/lib/opencode/settings-helpers.test.js +354 -12
  212. package/server/lib/opencode/settings-registry.json +747 -0
  213. package/server/lib/opencode/settings-runtime.js +141 -20
  214. package/server/lib/opencode/settings-runtime.test.js +191 -4
  215. package/server/lib/opencode/shared.js +5 -2
  216. package/server/lib/opencode/shared.test.js +7 -7
  217. package/server/lib/opencode/shutdown-runtime.js +2 -0
  218. package/server/lib/opencode/skill-routes.js +2 -1
  219. package/server/lib/opencode/snippets.js +1 -2
  220. package/server/lib/opencode/startup-performance.js +1 -1
  221. package/server/lib/opencode/startup-performance.test.js +6 -6
  222. package/server/lib/opencode/static-routes-runtime.js +8 -8
  223. package/server/lib/opencode/static-routes-runtime.test.js +7 -7
  224. package/server/lib/opencode/upgrade-capability.js +2 -2
  225. package/server/lib/opencode/upgrade-capability.test.js +3 -3
  226. package/server/lib/package-manager.js +17 -42
  227. package/server/lib/package-manager.test.js +19 -19
  228. package/server/lib/permission-auto-accept/runtime.js +1 -1
  229. package/server/lib/project-context/DOCUMENTATION.md +25 -1
  230. package/server/lib/project-context/routes.http.test.js +18 -0
  231. package/server/lib/project-context/routes.js +16 -1
  232. package/server/lib/project-context/runtime.js +248 -23
  233. package/server/lib/project-context/runtime.test.js +106 -3
  234. package/server/lib/projects/DOCUMENTATION.md +76 -0
  235. package/server/lib/projects/project-config.js +144 -11
  236. package/server/lib/projects/project-id.js +17 -0
  237. package/server/lib/projects/project-setup.js +409 -0
  238. package/server/lib/projects/project-setup.test.js +557 -0
  239. package/server/lib/projects/routes.js +59 -0
  240. package/server/lib/quota/DOCUMENTATION.md +40 -2
  241. package/server/lib/quota/credentials/providers.js +4 -0
  242. package/server/lib/quota/credentials/store.js +4 -4
  243. package/server/lib/quota/credentials/store.test.js +8 -8
  244. package/server/lib/quota/index.js +1 -0
  245. package/server/lib/quota/providers/cline-pass.js +125 -0
  246. package/server/lib/quota/providers/cline-pass.test.js +103 -0
  247. package/server/lib/quota/providers/exe-dev.js +75 -0
  248. package/server/lib/quota/providers/exe-dev.test.js +47 -0
  249. package/server/lib/quota/providers/hyper.js +118 -0
  250. package/server/lib/quota/providers/hyper.test.js +126 -0
  251. package/server/lib/quota/providers/index.js +22 -0
  252. package/server/lib/quota/providers/neuralwatt.js +3 -6
  253. package/server/lib/quota/providers/neuralwatt.test.js +7 -7
  254. package/server/lib/quota/providers/ollama-cloud.js +32 -1
  255. package/server/lib/quota/providers/ollama-cloud.test.js +33 -1
  256. package/server/lib/quota/providers/opencode-go.js +3 -2
  257. package/server/lib/quota/providers/opencode-go.test.js +35 -6
  258. package/server/lib/quota/providers/openrouter.js +119 -24
  259. package/server/lib/quota/providers/openrouter.test.js +330 -0
  260. package/server/lib/quota/providers/xai.js +1 -1
  261. package/server/lib/quota/routes.js +2 -0
  262. package/server/lib/quota/utils/auth.js +1 -1
  263. package/server/lib/relay/DOCUMENTATION.md +56 -1
  264. package/server/lib/relay/cross-compat.test.js +26 -0
  265. package/server/lib/relay/downstream-scheduler.js +154 -0
  266. package/server/lib/relay/downstream-scheduler.test.js +162 -0
  267. package/server/lib/relay/e2ee.js +10 -8
  268. package/server/lib/relay/flow-control.test.js +177 -0
  269. package/server/lib/relay/host-client.js +38 -9
  270. package/server/lib/relay/host-client.test.js +9 -1
  271. package/server/lib/relay/host-lock.js +1 -1
  272. package/server/lib/relay/service.js +5 -5
  273. package/server/lib/relay/tunnel-codec.js +9 -0
  274. package/server/lib/relay/tunnel-host.js +69 -18
  275. package/server/lib/relay/tunnel-host.test.js +9 -1
  276. package/server/lib/scheduled-tasks/issue-2710-double-execution.test.js +2 -2
  277. package/server/lib/scheduled-tasks/routes.js +5 -5
  278. package/server/lib/scheduled-tasks/service.js +25 -25
  279. package/server/lib/scheduled-tasks/service.test.js +1 -1
  280. package/server/lib/security/bind-host.js +4 -4
  281. package/server/lib/security/bind-host.test.js +1 -1
  282. package/server/lib/security/request-security.js +11 -5
  283. package/server/lib/security/request-security.test.js +14 -14
  284. package/server/lib/session-assist/runtime.js +15 -18
  285. package/server/lib/session-folders/routes.js +2 -2
  286. package/server/lib/session-folders/routes.test.js +8 -8
  287. package/server/lib/session-goal/DOCUMENTATION.md +20 -7
  288. package/server/lib/session-goal/create.js +4 -2
  289. package/server/lib/session-goal/create.test.js +1 -1
  290. package/server/lib/session-goal/objectives.js +4 -4
  291. package/server/lib/session-goal/routes.js +1 -1
  292. package/server/lib/session-goal/runtime.js +91 -30
  293. package/server/lib/session-goal/runtime.test.js +428 -2
  294. package/server/lib/session-knowledge/runtime.js +11 -11
  295. package/server/lib/session-knowledge/runtime.test.js +5 -5
  296. package/server/lib/skills-catalog/DOCUMENTATION.md +1 -1
  297. package/server/lib/skills-catalog/cache.test.js +2 -2
  298. package/server/lib/skills-catalog/disk-cache.js +5 -5
  299. package/server/lib/skills-catalog/github-meta.test.js +2 -2
  300. package/server/lib/skills-catalog/install.js +3 -2
  301. package/server/lib/small-model/DOCUMENTATION.md +7 -2
  302. package/server/lib/small-model/call.js +18 -7
  303. package/server/lib/small-model/call.test.js +58 -6
  304. package/server/lib/small-model/index.js +12 -16
  305. package/server/lib/small-model/index.test.js +1 -1
  306. package/server/lib/small-model/resolve.js +1 -1
  307. package/server/lib/small-model/resolve.test.js +1 -1
  308. package/server/lib/small-model/routes.js +2 -1
  309. package/server/lib/small-model/runtime-providers.js +15 -7
  310. package/server/lib/small-model/runtime-providers.test.js +7 -1
  311. package/server/lib/system-prompt/runtime.js +3 -22
  312. package/server/lib/system-prompt/runtime.test.js +3 -3
  313. package/server/lib/terminal/DOCUMENTATION.md +14 -10
  314. package/server/lib/terminal/runtime.js +190 -31
  315. package/server/lib/terminal/runtime.test.js +572 -38
  316. package/server/lib/terminal/shells.js +20 -3
  317. package/server/lib/terminal/shells.test.js +33 -2
  318. package/server/lib/tts/base-url.js +3 -3
  319. package/server/lib/tts/routes.test.js +20 -20
  320. package/server/lib/ui-auth/ui-auth.js +12 -9
  321. package/server/lib/ui-auth/ui-auth.test.js +19 -3
  322. package/server/lib/ui-auth/ui-passkeys.js +7 -7
  323. package/server/lib/walkthrough/DOCUMENTATION.md +33 -14
  324. package/server/lib/walkthrough/index.js +1 -0
  325. package/server/lib/walkthrough/jobs.test.js +1 -1
  326. package/server/lib/walkthrough/language.test.js +1 -1
  327. package/server/lib/walkthrough/model-settings.js +11 -15
  328. package/server/lib/walkthrough/model-settings.test.js +1 -1
  329. package/server/lib/walkthrough/prompt.js +3 -1
  330. package/server/lib/walkthrough/pull-request.test.js +5 -5
  331. package/server/lib/walkthrough/reproduce-2607.test.js +2 -2
  332. package/server/lib/walkthrough/routes.test.js +26 -5
  333. package/server/lib/walkthrough/sources.js +23 -2
  334. package/server/lib/walkthrough/store.js +3 -3
  335. package/server/lib/walkthrough/store.test.js +1 -1
  336. package/server/opencode-proxy.test.js +2 -2
  337. package/server/proxy-headers.js +1 -1
  338. package/server/sse-routes.test.js +4 -4
  339. package/README.md.bak +0 -250
  340. package/bin/lib/DOCUMENTATION.md.bak +0 -163
  341. package/dist/assets/CommitSection-SGBCAW0w.js +0 -1
  342. package/dist/assets/DiffView-DluiRSla.js +0 -4
  343. package/dist/assets/FilesView-Bdq8ppva.js +0 -17
  344. package/dist/assets/GitView-Znn7VJcP.js +0 -6
  345. package/dist/assets/LinearIssuesView-jP-hXyac.js +0 -1
  346. package/dist/assets/MarkdownImageGallery-ClOvuZxC.js +0 -1
  347. package/dist/assets/MarkdownRendererImpl-Dt9mjTRN.js +0 -12
  348. package/dist/assets/OnboardingScreen-D2DG7K6b.js +0 -1
  349. package/dist/assets/PierreDiffViewer-B7m3f0d7.js +0 -157
  350. package/dist/assets/PlanView-B0F3BtPZ.js +0 -5
  351. package/dist/assets/SettingsView-BBW-S-gh.js +0 -28
  352. package/dist/assets/ToolPartDiffPreview-CUNe28U1.js +0 -8
  353. package/dist/assets/WalkthroughView-egQgxel3.js +0 -4
  354. package/dist/assets/contextPanelEmbeddedChat-C3fjDbdg.js +0 -1
  355. package/dist/assets/de-C1P6X5Rs.js +0 -9
  356. package/dist/assets/es-CDgaF1_t.js +0 -15
  357. package/dist/assets/fr-Bgxqvvz_.js +0 -13
  358. package/dist/assets/index-C57jT0Sa.css +0 -1
  359. package/dist/assets/index-DW_E3rnL.js +0 -7
  360. package/dist/assets/ja-BDRrEcNP.js +0 -15
  361. package/dist/assets/ko-Ba8sQV79.js +0 -15
  362. package/dist/assets/main-Bv5Pkngh.js +0 -928
  363. package/dist/assets/markdownCore-CZwzz5gw.js +0 -3
  364. package/dist/assets/patchFileDiff-yNfWXN4E.js +0 -10
  365. package/dist/assets/pl-Dioz29BI.js +0 -15
  366. package/dist/assets/pt-BR-DIs6ElwV.js +0 -15
  367. package/dist/assets/renderElectronMiniChatApp-BcKLHXKe.js +0 -2
  368. package/dist/assets/renderMobileApp-D9yQJy0L.js +0 -25
  369. package/dist/assets/runtimeEndpointReset-CjhvxLH0.js +0 -16
  370. package/dist/assets/scheduledTasksApi-DLW0mkQK.js +0 -1
  371. package/dist/assets/tr-DFnMlPxY.js +0 -6
  372. package/dist/assets/uk-ZrCNjM7Y.js +0 -15
  373. package/dist/assets/useAppFontEffects-CjrntdL0.js +0 -7310
  374. package/dist/assets/useInlineCommentController-CDEuSlPH.js +0 -2
  375. package/dist/assets/useRootScrollLock-BHYPkrLv.js +0 -1
  376. package/dist/assets/vendor-ghostty-web-CrxinGGH.js +0 -13
  377. package/dist/assets/vendor-zod-BLfBSgBh.js +0 -39
  378. package/dist/assets/zh-CN-iv_AV4EC.js +0 -15
  379. package/dist/assets/zh-TW-CzEUk38j.js +0 -15
  380. package/server/index.d.ts.bak +0 -39
  381. package/server/lib/agent-tool/DOCUMENTATION.md.bak +0 -119
  382. package/server/lib/browser-control/DOCUMENTATION.md.bak +0 -50
  383. package/server/lib/context-obligatory/DOCUMENTATION.md.bak +0 -19
  384. package/server/lib/dev-tunnel/DOCUMENTATION.md.bak +0 -57
  385. package/server/lib/dictation/DOCUMENTATION.md.bak +0 -100
  386. package/server/lib/event-stream/DOCUMENTATION.md.bak +0 -62
  387. package/server/lib/fs/DOCUMENTATION.md.bak +0 -47
  388. package/server/lib/git/DOCUMENTATION.md.bak +0 -193
  389. package/server/lib/github/DOCUMENTATION.md.bak +0 -183
  390. package/server/lib/linear/DOCUMENTATION.md.bak +0 -97
  391. package/server/lib/linear/OAUTH-BROKER-HANDOFF.md.bak +0 -91
  392. package/server/lib/markdown-image-grants/DOCUMENTATION.md.bak +0 -40
  393. package/server/lib/notifications/APNS.md.bak +0 -135
  394. package/server/lib/notifications/DOCUMENTATION.md.bak +0 -138
  395. package/server/lib/openchamber-control/DOCUMENTATION.md.bak +0 -64
  396. package/server/lib/opencode/DOCUMENTATION.md.bak +0 -431
  397. package/server/lib/opencode/managed-process-registry.d.ts.bak +0 -13
  398. package/server/lib/opencode/provider-env-aliases.d.ts.bak +0 -3
  399. package/server/lib/permission-auto-accept/DOCUMENTATION.md.bak +0 -34
  400. package/server/lib/project-context/DOCUMENTATION.md.bak +0 -160
  401. package/server/lib/quota/DOCUMENTATION.md.bak +0 -123
  402. package/server/lib/relay/DOCUMENTATION.md.bak +0 -100
  403. package/server/lib/scheduled-tasks/DOCUMENTATION.md.bak +0 -182
  404. package/server/lib/session-assist/DOCUMENTATION.md.bak +0 -66
  405. package/server/lib/session-goal/DOCUMENTATION.md.bak +0 -213
  406. package/server/lib/session-knowledge/DOCUMENTATION.md.bak +0 -89
  407. package/server/lib/skills-catalog/DOCUMENTATION.md.bak +0 -151
  408. package/server/lib/small-model/DOCUMENTATION.md.bak +0 -212
  409. package/server/lib/system-prompt/DOCUMENTATION.md.bak +0 -36
  410. package/server/lib/terminal/DOCUMENTATION.md.bak +0 -50
  411. package/server/lib/text/DOCUMENTATION.md.bak +0 -35
  412. package/server/lib/tts/DOCUMENTATION.md.bak +0 -147
  413. package/server/lib/tunnels/DOCUMENTATION.md.bak +0 -21
  414. package/server/lib/ui-auth/DOCUMENTATION.md.bak +0 -44
  415. package/server/lib/walkthrough/DOCUMENTATION.md.bak +0 -411
@@ -32,10 +32,10 @@ export const registerSessionFoldersRoutes = (app, dependencies) => {
32
32
  const {
33
33
  fsPromises,
34
34
  path,
35
- openchamberDataDir,
35
+ aiworkerDataDir,
36
36
  } = dependencies;
37
37
 
38
- const filePath = path.join(openchamberDataDir, 'sessions-directories.json');
38
+ const filePath = path.join(aiworkerDataDir, 'sessions-directories.json');
39
39
  let saveQueue = Promise.resolve();
40
40
 
41
41
  const ensureDir = async () => {
@@ -73,7 +73,7 @@ describe('session folders routes', () => {
73
73
  registerSessionFoldersRoutes(app, {
74
74
  fsPromises,
75
75
  path,
76
- openchamberDataDir: '/tmp/openchamber-test',
76
+ aiworkerDataDir: '/tmp/openchamber-test',
77
77
  });
78
78
 
79
79
  const handler = getRoute('POST', '/api/session-folders');
@@ -103,7 +103,7 @@ describe('session folders routes', () => {
103
103
  registerSessionFoldersRoutes(app, {
104
104
  fsPromises,
105
105
  path,
106
- openchamberDataDir: '/tmp/openchamber-test',
106
+ aiworkerDataDir: '/tmp/openchamber-test',
107
107
  });
108
108
 
109
109
  const handler = getRoute('POST', '/api/session-folders');
@@ -121,7 +121,7 @@ describe('session folders routes', () => {
121
121
  registerSessionFoldersRoutes(app, {
122
122
  fsPromises,
123
123
  path,
124
- openchamberDataDir: '/tmp/openchamber-test',
124
+ aiworkerDataDir: '/tmp/openchamber-test',
125
125
  });
126
126
 
127
127
  const response = createMockResponse();
@@ -137,7 +137,7 @@ describe('session folders routes', () => {
137
137
  registerSessionFoldersRoutes(app, {
138
138
  fsPromises,
139
139
  path,
140
- openchamberDataDir: '/tmp/openchamber-test',
140
+ aiworkerDataDir: '/tmp/openchamber-test',
141
141
  });
142
142
 
143
143
  const response = createMockResponse();
@@ -156,7 +156,7 @@ describe('session folders routes', () => {
156
156
  registerSessionFoldersRoutes(app, {
157
157
  fsPromises,
158
158
  path,
159
- openchamberDataDir: '/tmp/openchamber-test',
159
+ aiworkerDataDir: '/tmp/openchamber-test',
160
160
  });
161
161
 
162
162
  const response = createMockResponse();
@@ -181,7 +181,7 @@ describe('session folders routes', () => {
181
181
  registerSessionFoldersRoutes(app, {
182
182
  fsPromises,
183
183
  path,
184
- openchamberDataDir: '/tmp/openchamber-test',
184
+ aiworkerDataDir: '/tmp/openchamber-test',
185
185
  });
186
186
 
187
187
  const response = createMockResponse();
@@ -204,7 +204,7 @@ describe('session folders routes', () => {
204
204
  registerSessionFoldersRoutes(app, {
205
205
  fsPromises,
206
206
  path,
207
- openchamberDataDir: '/tmp/openchamber-test',
207
+ aiworkerDataDir: '/tmp/openchamber-test',
208
208
  });
209
209
 
210
210
  const response = createMockResponse();
@@ -227,7 +227,7 @@ describe('session folders routes', () => {
227
227
  registerSessionFoldersRoutes(app, {
228
228
  fsPromises,
229
229
  path,
230
- openchamberDataDir: '/tmp/openchamber-test',
230
+ aiworkerDataDir: '/tmp/openchamber-test',
231
231
  });
232
232
 
233
233
  const response = createMockResponse();
@@ -108,13 +108,26 @@ before touching the filesystem). Rationale: metadata rides every
108
108
  stop), with a tick-side safety net. Messages sent while paused leave
109
109
  the goal alone; Resume re-arms the loop, and resuming over an aborted
110
110
  tail skips the audit and goes straight to a continuation nudge;
111
- - terminal checks, cheapest first: assistant turn error → `blocked`;
112
- `tokensUsed >= tokenBudget` → `budgetLimited`;
113
- `turnsUsed >= MAX_AUTO_TURNS` (20) → `blocked`;
114
- - if the latest message is a compaction summary, skip the audit and
115
- continue unconditionally running into the context window mid-work is
116
- by definition "in progress, not finished" (the summary is a retelling,
117
- not evidence, and must not be judged);
111
+ - terminal checks, cheapest first: assistant turn error → `blocked`;
112
+ `tokensUsed >= tokenBudget` → `budgetLimited`;
113
+ `turnsUsed >= MAX_AUTO_TURNS` (20) → `blocked`;
114
+ - error classification is independent of `finish`: `MessageAbortedError`
115
+ keeps the pause/resume behavior; only a `finish: "length"` with no
116
+ error, or `MessageOutputLengthError`, is an in-progress truncation that
117
+ skips the audit and continues. Any other non-null error wins over a
118
+ length finish and blocks with its non-empty `error.name`, or
119
+ `assistant turn failed` when unnamed;
120
+ - length recovery is bounded separately from the token budget and
121
+ auto-continuation cap: the first truncation permits one continuation, but
122
+ a second consecutive completed, non-summary assistant turn that is also
123
+ truncated settles the goal as `blocked` (`repeated output truncation`).
124
+ The consecutive state is derived from the loaded message history, not
125
+ persisted, using `info.time.created` chronology rather than message IDs.
126
+ Summary messages are not agent turns; an ordinary completed assistant
127
+ turn naturally breaks the consecutive condition. Explicit Resume grants
128
+ one new recovery attempt over the same transcript; the continuation
129
+ consumes that permission, so another truncation blocks again. Resume
130
+ does not bypass assistant errors or the token budget;
118
131
  - otherwise, small-model audit of the objective + the last assistant turn
119
132
  only — no conversation history and no continuation prompts
120
133
  (`restrictToPreferredProvider`, session's own provider/model preferred):
@@ -14,7 +14,7 @@ export const buildGoalIntroText = (tokenBudget) => {
14
14
  + '\n</system-reminder>';
15
15
  };
16
16
 
17
- const fitObjective = async ({ objective, directory, providerID, modelID, warn }) => {
17
+ const fitObjective = async ({ objective, directory, sessionID, providerID, modelID, warn }) => {
18
18
  if (objective.length <= GOAL_OBJECTIVE_CHAR_LIMIT) return objective;
19
19
 
20
20
  let distilled = null;
@@ -32,6 +32,7 @@ const fitObjective = async ({ objective, directory, providerID, modelID, warn })
32
32
  'Write in the same language as the task text.',
33
33
  ].join('\n'),
34
34
  directory,
35
+ sessionID,
35
36
  preferredProviderID: providerID,
36
37
  preferredModelID: modelID,
37
38
  });
@@ -66,6 +67,7 @@ export const createSessionGoal = async ({
66
67
  const objectiveText = await fitObjective({
67
68
  objective: String(objective ?? '').trim(),
68
69
  directory,
70
+ sessionID,
69
71
  providerID,
70
72
  modelID,
71
73
  warn,
@@ -105,7 +107,7 @@ export const createSessionGoal = async ({
105
107
  'content-type': 'application/json',
106
108
  accept: 'application/json',
107
109
  },
108
- body: JSON.stringify({ metadata: { openchamber: { goal } } }),
110
+ body: JSON.stringify({ metadata: { aiworker: { goal } } }),
109
111
  });
110
112
  if (!response.ok) throw new Error(`goal metadata patch failed (${response.status})`);
111
113
  return goal;
@@ -64,7 +64,7 @@ describe('session goal creation', () => {
64
64
  });
65
65
 
66
66
  const payload = JSON.parse(fetchMock.mock.calls[0][1].body);
67
- expect(payload.metadata.openchamber.goal).toMatchObject({
67
+ expect(payload.metadata.aiworker.goal).toMatchObject({
68
68
  objective: 'Finish the migration',
69
69
  objectiveFile: false,
70
70
  });
@@ -1,6 +1,6 @@
1
1
  // File-backed goal objectives. Session metadata must stay light (it rides
2
2
  // every session.updated event), so the objective TEXT lives in a file under
3
- // the OpenChamber data dir, keyed by the SESSION ID: sessions are globally
3
+ // the AiWorker data dir, keyed by the SESSION ID: sessions are globally
4
4
  // unique and carry at most one goal at a time, so the mapping is fully
5
5
  // deterministic — the metadata only carries an `objectiveFile: true` flag,
6
6
  // never a path, and user-writable metadata cannot become a file-read vector.
@@ -16,9 +16,9 @@ export const GOAL_OBJECTIVE_CHAR_LIMIT = 5_000;
16
16
  const SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{4,128}$/;
17
17
 
18
18
  const goalsDir = () => path.join(
19
- process.env.OPENCHAMBER_DATA_DIR
20
- ? path.resolve(process.env.OPENCHAMBER_DATA_DIR)
21
- : path.join(os.homedir(), '.config', 'openchamber'),
19
+ process.env.AIWORKER_DATA_DIR
20
+ ? path.resolve(process.env.AIWORKER_DATA_DIR)
21
+ : path.join(os.homedir(), '.config', 'aiworker'),
22
22
  'goals',
23
23
  );
24
24
 
@@ -1,6 +1,6 @@
1
1
  import { deleteObjective, readObjective, writeObjective } from './objectives.js';
2
2
 
3
- // OpenChamber-owned routes for file-backed goal objectives, keyed by session
3
+ // AiWorker-owned routes for file-backed goal objectives, keyed by session
4
4
  // id (one goal per session; a new goal overwrites the old file). The UI
5
5
  // writes the objective file before stamping the goal metadata (which only
6
6
  // carries an `objectiveFile: true` flag), reads it back for display, and
@@ -1,5 +1,5 @@
1
1
  // Session goal: a persisted, self-continuing objective attached to a session
2
- // (metadata.openchamber.goal). While the goal is active, the server keeps the
2
+ // (metadata.aiworker.goal). While the goal is active, the server keeps the
3
3
  // session working toward it: after each busy→idle transition it accounts token
4
4
  // usage, asks the small model to audit progress (continue / complete /
5
5
  // blocked), and either re-prompts the session's own model with a continuation
@@ -19,23 +19,18 @@ import os from 'os';
19
19
  import path from 'path';
20
20
 
21
21
  import { GOAL_OBJECTIVE_CHAR_LIMIT, readObjective } from './objectives.js';
22
+ import { readMergedSettingsSync } from '../opencode/settings-files.js';
22
23
 
23
- const OPENCHAMBER_SETTINGS_FILE = path.join(
24
- process.env.OPENCHAMBER_DATA_DIR
25
- ? path.resolve(process.env.OPENCHAMBER_DATA_DIR)
26
- : path.join(os.homedir(), '.config', 'openchamber'),
24
+ const AIWORKER_SETTINGS_FILE = path.join(
25
+ process.env.AIWORKER_DATA_DIR
26
+ ? path.resolve(process.env.AIWORKER_DATA_DIR)
27
+ : path.join(os.homedir(), '.config', 'aiworker'),
27
28
  'settings.json',
28
29
  );
29
30
 
30
- const isSessionGoalEnabled = () => {
31
- try {
32
- const raw = fs.readFileSync(OPENCHAMBER_SETTINGS_FILE, 'utf8');
33
- const settings = JSON.parse(raw);
34
- return settings?.sessionGoalEnabled !== false;
35
- } catch {
36
- return true;
37
- }
38
- };
31
+ const isSessionGoalEnabled = () => (
32
+ readMergedSettingsSync({ fs, path, settingsFilePath: AIWORKER_SETTINGS_FILE }).sessionGoalEnabled !== false
33
+ );
39
34
 
40
35
  const IDLE_QUIET_MS = 15_000;
41
36
  // A goal set while the session is already idle should kick off promptly.
@@ -188,7 +183,7 @@ const extractSessionUpdate = (payload) => {
188
183
  const parseGoalMetadata = (session) => {
189
184
  const metadata = session?.metadata;
190
185
  if (!metadata || typeof metadata !== 'object') return null;
191
- const namespace = metadata.openchamber;
186
+ const namespace = metadata.aiworker;
192
187
  if (!namespace || typeof namespace !== 'object') return null;
193
188
  const goal = namespace.goal;
194
189
  if (!goal || typeof goal !== 'object') return null;
@@ -244,6 +239,57 @@ const messageTokenTotal = (info) => {
244
239
  return input + cachedRead + output;
245
240
  };
246
241
 
242
+ const getErrorName = (error) => error?.name?.trim?.() ?? '';
243
+
244
+ const isLengthTruncated = (info, errorName = getErrorName(info?.error)) => {
245
+ const error = info?.error;
246
+ const hasError = error !== null && error !== undefined;
247
+ return errorName === 'MessageOutputLengthError' || (!hasError && info?.finish === 'length');
248
+ };
249
+
250
+ // Summary messages are assistant-shaped, but they are compaction turns rather
251
+ // than agent turns. They must not break or satisfy the consecutive truncation
252
+ // check; only completed, non-summary assistant turns participate. Chronology
253
+ // comes from `time.created`, never from message IDs; array position is only a
254
+ // tie-breaker for equal timestamps.
255
+ const hasRepeatedLengthTail = (messages, latestAssistant, goalCreatedAt) => {
256
+ const latestInfo = latestAssistant?.info;
257
+ if (latestInfo?.summary === true) return false;
258
+ const latestIndex = messages.indexOf(latestAssistant);
259
+ const latestCreated = latestInfo?.time?.created;
260
+ if (
261
+ latestIndex < 0
262
+ || !(latestInfo?.time?.completed > 0)
263
+ || !(Number.isFinite(latestCreated) && latestCreated > 0)
264
+ || !isLengthTruncated(latestInfo)
265
+ ) return false;
266
+
267
+ let previous = null;
268
+ for (let i = 0; i < messages.length; i += 1) {
269
+ const info = messages[i]?.info;
270
+ if (info?.role !== 'assistant' || info.summary === true || !(info.time?.completed > 0)) continue;
271
+ const created = info.time?.created;
272
+ // An unknown timestamp cannot safely participate in chronology. Ignore it
273
+ // rather than letting an unrelated older message hide known chronology.
274
+ if (!(Number.isFinite(created) && created > 0)) continue;
275
+ if (i === latestIndex) continue;
276
+ if (created > latestCreated || (created === latestCreated && i > latestIndex)) continue;
277
+ if (
278
+ !previous
279
+ || created > previous.created
280
+ || (created === previous.created && i > previous.index)
281
+ ) {
282
+ previous = { info, created, index: i };
283
+ }
284
+ }
285
+
286
+ return Boolean(
287
+ previous
288
+ && previous.created > goalCreatedAt
289
+ && isLengthTruncated(previous.info),
290
+ );
291
+ };
292
+
247
293
  export const createSessionGoalRuntime = ({
248
294
  buildOpenCodeUrl,
249
295
  getOpenCodeAuthHeaders,
@@ -319,8 +365,8 @@ export const createSessionGoalRuntime = ({
319
365
  if (!currentGoal || currentGoal.id !== expectedGoalId) return null;
320
366
  const nextGoal = { ...currentGoal, ...mutate(currentGoal), updatedAt: Date.now() };
321
367
  const currentMetadata = session?.metadata && typeof session.metadata === 'object' ? session.metadata : {};
322
- const currentNamespace = currentMetadata.openchamber && typeof currentMetadata.openchamber === 'object'
323
- ? currentMetadata.openchamber
368
+ const currentNamespace = currentMetadata.aiworker && typeof currentMetadata.aiworker === 'object'
369
+ ? currentMetadata.aiworker
324
370
  : {};
325
371
  await openCodeFetch(`/session/${encodeURIComponent(sessionId)}`, {
326
372
  directory,
@@ -328,7 +374,7 @@ export const createSessionGoalRuntime = ({
328
374
  body: {
329
375
  metadata: {
330
376
  ...currentMetadata,
331
- openchamber: { ...currentNamespace, goal: nextGoal },
377
+ aiworker: { ...currentNamespace, goal: nextGoal },
332
378
  },
333
379
  },
334
380
  });
@@ -378,6 +424,7 @@ export const createSessionGoalRuntime = ({
378
424
  prompt: `The goal objective:\n\n<objective>\n${goal.objective}\n</objective>\n\nThe agent's latest turn:\n\n${assistantText}\n\nReturn the verdict JSON. Write the note in the SAME language as this sample from the objective: "${goal.objective.slice(0, 200).replace(/\s+/g, ' ').trim()}"`,
379
425
  system: buildAuditSystemPrompt(),
380
426
  directory,
427
+ sessionID: typeof lastAssistantInfo?.sessionID === 'string' ? lastAssistantInfo.sessionID : undefined,
381
428
  preferredProviderID: typeof lastAssistantInfo?.providerID === 'string' ? lastAssistantInfo.providerID : undefined,
382
429
  preferredModelID: typeof lastAssistantInfo?.modelID === 'string' ? lastAssistantInfo.modelID : undefined,
383
430
  });
@@ -460,7 +507,7 @@ export const createSessionGoalRuntime = ({
460
507
  if (!goal || goal.status !== 'active') return;
461
508
 
462
509
  // File-backed objectives: the metadata carries only a flag; the objective
463
- // TEXT lives under the OpenChamber data dir keyed by session id and is
510
+ // TEXT lives under the AiWorker data dir keyed by session id and is
464
511
  // read fresh on every tick (live-editable). A missing file falls back to
465
512
  // whatever inline objective the metadata still has — the goal must never
466
513
  // die just because a file went away.
@@ -608,7 +655,11 @@ export const createSessionGoalRuntime = ({
608
655
  // resumed over an aborted tail: that is an explicit "keep going", so it
609
656
  // falls through to the continuation below (skipping the audit — an
610
657
  // aborted reply is not evidence of anything).
611
- const abortedTail = lastAssistantInfo.error?.name === 'MessageAbortedError';
658
+ const error = lastAssistantInfo.error;
659
+ const errorName = getErrorName(error);
660
+ const hasError = error !== null && error !== undefined;
661
+ const abortedTail = errorName === 'MessageAbortedError';
662
+ const lengthTail = isLengthTruncated(lastAssistantInfo, errorName);
612
663
  if (abortedTail && goal.statusReason !== 'resumed') {
613
664
  await writeGoal(sessionId, directory, goal.id, () => ({
614
665
  status: 'paused',
@@ -622,13 +673,12 @@ export const createSessionGoalRuntime = ({
622
673
  return;
623
674
  }
624
675
 
625
- // Turn error → blocked (prevents runaway auto-continuation into failures).
626
- if (!abortedTail && lastAssistantInfo.error && typeof lastAssistantInfo.error === 'object') {
627
- const reason = typeof lastAssistantInfo.error.name === 'string' && lastAssistantInfo.error.name
628
- ? lastAssistantInfo.error.name
629
- : 'assistant turn failed';
676
+ // Non-length turn error → blocked (prevents runaway auto-continuation into
677
+ // failures). Recognized length cutoffs are in-progress continuations, not
678
+ // hard failures.
679
+ if (!abortedTail && !lengthTail && hasError) {
630
680
  await settleGoal({
631
- sessionId, directory, goal, status: 'blocked', statusReason: reason, tokensUsed, tokensBaseline, tokensCommitted, lastAccountedMessageID,
681
+ sessionId, directory, goal, status: 'blocked', statusReason: errorName || 'assistant turn failed', tokensUsed, tokensBaseline, tokensCommitted, lastAccountedMessageID,
632
682
  });
633
683
  return;
634
684
  }
@@ -649,17 +699,28 @@ export const createSessionGoalRuntime = ({
649
699
  return;
650
700
  }
651
701
 
702
+ // A second consecutive completed, non-summary length-truncated turn is a
703
+ // bounded recovery failure. Derive this from the loaded transcript rather
704
+ // than persisting another goal counter.
705
+ if (lengthTail && goal.statusReason !== 'resumed' && hasRepeatedLengthTail(messages, lastAssistant, goal.createdAt)) {
706
+ await settleGoal({
707
+ sessionId, directory, goal, status: 'blocked', statusReason: 'repeated output truncation', tokensUsed, tokensBaseline, tokensCommitted, lastAccountedMessageID,
708
+ });
709
+ return;
710
+ }
711
+
652
712
  // --- Small-model audit: the sole termination authority besides the hard
653
713
  // stops above (turn error, budget, continuation cap). The working agent
654
714
  // has no channel to settle its own goal.
655
715
  //
656
- // Exception: when the latest message is a compaction summary, the agent
657
- // by definition ran into the context window mid-work that IS
658
- // "in progress, not finished". No audit call; continue unconditionally.
716
+ // Exception: when the latest message is a compaction summary or was cut off
717
+ // by the output token limit (length stop), the agent by definition ran into
718
+ // the context/output limit mid-work — that IS "in progress, not finished".
719
+ // No audit call; continue unconditionally.
659
720
  let audit = null;
660
721
  let blockedStreak = 0;
661
722
  let auditFailStreak = goal.auditFailStreak;
662
- if (lastAssistantInfo.summary === true || abortedTail) {
723
+ if (lastAssistantInfo.summary === true || abortedTail || lengthTail) {
663
724
  blockedStreak = goal.blockedStreak;
664
725
  } else {
665
726
  audit = await runAudit({ goal: { ...goal, objective: effectiveObjective }, assistantText, directory, lastAssistantInfo: executionInfo ?? lastAssistantInfo });