yepanywhere 0.5.2 → 0.6.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 (858) hide show
  1. package/README.md +21 -5
  2. package/bundled/@yep-anywhere/shared/dist/agent-context.d.ts +9 -0
  3. package/bundled/@yep-anywhere/shared/dist/agent-context.d.ts.map +1 -0
  4. package/bundled/@yep-anywhere/shared/dist/agent-context.js +18 -0
  5. package/bundled/@yep-anywhere/shared/dist/agent-context.js.map +1 -0
  6. package/bundled/@yep-anywhere/shared/dist/app-types.d.ts +104 -1
  7. package/bundled/@yep-anywhere/shared/dist/app-types.d.ts.map +1 -1
  8. package/bundled/@yep-anywhere/shared/dist/app-types.js +4 -0
  9. package/bundled/@yep-anywhere/shared/dist/app-types.js.map +1 -1
  10. package/bundled/@yep-anywhere/shared/dist/binary-framing.d.ts +4 -1
  11. package/bundled/@yep-anywhere/shared/dist/binary-framing.d.ts.map +1 -1
  12. package/bundled/@yep-anywhere/shared/dist/binary-framing.js +8 -3
  13. package/bundled/@yep-anywhere/shared/dist/binary-framing.js.map +1 -1
  14. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/AssistantEntrySchema.d.ts +4 -0
  15. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/AssistantEntrySchema.d.ts.map +1 -1
  16. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/BaseEntrySchema.d.ts +4 -0
  17. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/BaseEntrySchema.d.ts.map +1 -1
  18. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/BaseEntrySchema.js +7 -0
  19. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/BaseEntrySchema.js.map +1 -1
  20. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/ProgressEntrySchema.d.ts +4 -0
  21. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/ProgressEntrySchema.d.ts.map +1 -1
  22. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/SystemEntrySchema.d.ts +64 -1
  23. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/SystemEntrySchema.d.ts.map +1 -1
  24. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/SystemEntrySchema.js +9 -0
  25. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/SystemEntrySchema.js.map +1 -1
  26. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/UserEntrySchema.d.ts +4 -0
  27. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/entry/UserEntrySchema.d.ts.map +1 -1
  28. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/guards.d.ts.map +1 -1
  29. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/guards.js +45 -1
  30. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/guards.js.map +1 -1
  31. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/index.d.ts +144 -2
  32. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/index.d.ts.map +1 -1
  33. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/tool/ToolResultSchemas.d.ts +6 -4
  34. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/tool/ToolResultSchemas.d.ts.map +1 -1
  35. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/tool/ToolResultSchemas.js +8 -1
  36. package/bundled/@yep-anywhere/shared/dist/claude-sdk-schema/tool/ToolResultSchemas.js.map +1 -1
  37. package/bundled/@yep-anywhere/shared/dist/codex-schema/index.d.ts +3 -2
  38. package/bundled/@yep-anywhere/shared/dist/codex-schema/index.d.ts.map +1 -1
  39. package/bundled/@yep-anywhere/shared/dist/codex-schema/index.js +3 -2
  40. package/bundled/@yep-anywhere/shared/dist/codex-schema/index.js.map +1 -1
  41. package/bundled/@yep-anywhere/shared/dist/codex-schema/session.d.ts +87 -3
  42. package/bundled/@yep-anywhere/shared/dist/codex-schema/session.d.ts.map +1 -1
  43. package/bundled/@yep-anywhere/shared/dist/codex-schema/session.js +39 -1
  44. package/bundled/@yep-anywhere/shared/dist/codex-schema/session.js.map +1 -1
  45. package/bundled/@yep-anywhere/shared/dist/dag.d.ts +31 -11
  46. package/bundled/@yep-anywhere/shared/dist/dag.d.ts.map +1 -1
  47. package/bundled/@yep-anywhere/shared/dist/dag.js +77 -33
  48. package/bundled/@yep-anywhere/shared/dist/dag.js.map +1 -1
  49. package/bundled/@yep-anywhere/shared/dist/git-status.d.ts +70 -1
  50. package/bundled/@yep-anywhere/shared/dist/git-status.d.ts.map +1 -1
  51. package/bundled/@yep-anywhere/shared/dist/git-status.js +6 -1
  52. package/bundled/@yep-anywhere/shared/dist/git-status.js.map +1 -1
  53. package/bundled/@yep-anywhere/shared/dist/ideMetadata.js +1 -1
  54. package/bundled/@yep-anywhere/shared/dist/ideMetadata.js.map +1 -1
  55. package/bundled/@yep-anywhere/shared/dist/index.d.ts +20 -11
  56. package/bundled/@yep-anywhere/shared/dist/index.d.ts.map +1 -1
  57. package/bundled/@yep-anywhere/shared/dist/index.js +8 -3
  58. package/bundled/@yep-anywhere/shared/dist/index.js.map +1 -1
  59. package/bundled/@yep-anywhere/shared/dist/local-resource.d.ts +1 -0
  60. package/bundled/@yep-anywhere/shared/dist/local-resource.d.ts.map +1 -1
  61. package/bundled/@yep-anywhere/shared/dist/local-resource.js +4 -0
  62. package/bundled/@yep-anywhere/shared/dist/local-resource.js.map +1 -1
  63. package/bundled/@yep-anywhere/shared/dist/opencode-schema/events.d.ts +136 -0
  64. package/bundled/@yep-anywhere/shared/dist/opencode-schema/events.d.ts.map +1 -1
  65. package/bundled/@yep-anywhere/shared/dist/opencode-schema/events.js +65 -3
  66. package/bundled/@yep-anywhere/shared/dist/opencode-schema/events.js.map +1 -1
  67. package/bundled/@yep-anywhere/shared/dist/opencode-schema/types.d.ts +1 -1
  68. package/bundled/@yep-anywhere/shared/dist/opencode-schema/types.d.ts.map +1 -1
  69. package/bundled/@yep-anywhere/shared/dist/project-queue.d.ts +153 -0
  70. package/bundled/@yep-anywhere/shared/dist/project-queue.d.ts.map +1 -0
  71. package/bundled/@yep-anywhere/shared/dist/project-queue.js +8 -0
  72. package/bundled/@yep-anywhere/shared/dist/project-queue.js.map +1 -0
  73. package/bundled/@yep-anywhere/shared/dist/relay-protocol.d.ts +26 -2
  74. package/bundled/@yep-anywhere/shared/dist/relay-protocol.d.ts.map +1 -1
  75. package/bundled/@yep-anywhere/shared/dist/relay-protocol.js +33 -0
  76. package/bundled/@yep-anywhere/shared/dist/relay-protocol.js.map +1 -1
  77. package/bundled/@yep-anywhere/shared/dist/relay.d.ts +45 -5
  78. package/bundled/@yep-anywhere/shared/dist/relay.d.ts.map +1 -1
  79. package/bundled/@yep-anywhere/shared/dist/relay.js.map +1 -1
  80. package/bundled/@yep-anywhere/shared/dist/safe-restart.d.ts +25 -0
  81. package/bundled/@yep-anywhere/shared/dist/safe-restart.d.ts.map +1 -0
  82. package/bundled/@yep-anywhere/shared/dist/safe-restart.js +2 -0
  83. package/bundled/@yep-anywhere/shared/dist/safe-restart.js.map +1 -0
  84. package/bundled/@yep-anywhere/shared/dist/session/SessionView.d.ts +2 -2
  85. package/bundled/@yep-anywhere/shared/dist/session/SessionView.js +3 -3
  86. package/bundled/@yep-anywhere/shared/dist/session/SessionView.js.map +1 -1
  87. package/bundled/@yep-anywhere/shared/dist/session/UnifiedSession.d.ts +10 -0
  88. package/bundled/@yep-anywhere/shared/dist/session/UnifiedSession.d.ts.map +1 -1
  89. package/bundled/@yep-anywhere/shared/dist/session-liveness.d.ts +18 -0
  90. package/bundled/@yep-anywhere/shared/dist/session-liveness.d.ts.map +1 -1
  91. package/bundled/@yep-anywhere/shared/dist/types.d.ts +253 -8
  92. package/bundled/@yep-anywhere/shared/dist/types.d.ts.map +1 -1
  93. package/bundled/@yep-anywhere/shared/dist/types.js +48 -5
  94. package/bundled/@yep-anywhere/shared/dist/types.js.map +1 -1
  95. package/bundled/@yep-anywhere/shared/dist/upload.d.ts +34 -2
  96. package/bundled/@yep-anywhere/shared/dist/upload.d.ts.map +1 -1
  97. package/bundled/@yep-anywhere/shared/dist/user-message-metadata.d.ts +47 -0
  98. package/bundled/@yep-anywhere/shared/dist/user-message-metadata.d.ts.map +1 -1
  99. package/bundled/@yep-anywhere/shared/dist/user-message-metadata.js +59 -1
  100. package/bundled/@yep-anywhere/shared/dist/user-message-metadata.js.map +1 -1
  101. package/bundled/@yep-anywhere/shared/dist/workstreams.d.ts +54 -0
  102. package/bundled/@yep-anywhere/shared/dist/workstreams.d.ts.map +1 -0
  103. package/bundled/@yep-anywhere/shared/dist/workstreams.js +8 -0
  104. package/bundled/@yep-anywhere/shared/dist/workstreams.js.map +1 -0
  105. package/bundled/@yep-anywhere/shared/package.json +1 -1
  106. package/client-dist/assets/alegreya-sans-latin-400-italic-BQIUBrX-.woff2 +0 -0
  107. package/client-dist/assets/alegreya-sans-latin-400-normal-BxeZdXas.woff2 +0 -0
  108. package/client-dist/assets/alegreya-sans-latin-500-normal-uodOEoAl.woff2 +0 -0
  109. package/client-dist/assets/alegreya-sans-latin-700-normal-DFYOGfC8.woff2 +0 -0
  110. package/client-dist/assets/de-CHMDbVD5.js +6 -0
  111. package/client-dist/assets/es-CK8MPF_C.js +6 -0
  112. package/client-dist/assets/fira-mono-latin-400-normal-DVTTRLHv.woff2 +0 -0
  113. package/client-dist/assets/fira-mono-latin-ext-400-normal-B2gPvaNr.woff2 +0 -0
  114. package/client-dist/assets/fira-mono-symbols2-400-normal-C6JptOil.woff2 +0 -0
  115. package/client-dist/assets/fr-49PXQiUL.js +6 -0
  116. package/client-dist/assets/index-B-09fVut.js +557 -0
  117. package/client-dist/assets/index-uJnfvD1f.css +1 -0
  118. package/client-dist/assets/inter-latin-400-italic-D1l0FflY.woff2 +0 -0
  119. package/client-dist/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  120. package/client-dist/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  121. package/client-dist/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
  122. package/client-dist/assets/ja-CrCGPmoH.js +6 -0
  123. package/client-dist/assets/zh-CN-AFJxv5ke.js +6 -0
  124. package/client-dist/index.html +3 -3
  125. package/client-dist/sw.js +96 -9
  126. package/dist/app.d.ts +25 -0
  127. package/dist/app.d.ts.map +1 -1
  128. package/dist/app.js +350 -35
  129. package/dist/app.js.map +1 -1
  130. package/dist/augments/augment-generator.d.ts +1 -1
  131. package/dist/augments/augment-generator.d.ts.map +1 -1
  132. package/dist/augments/augment-generator.js +2 -2
  133. package/dist/augments/augment-generator.js.map +1 -1
  134. package/dist/augments/markdown-augments.d.ts +1 -1
  135. package/dist/augments/markdown-augments.d.ts.map +1 -1
  136. package/dist/augments/markdown-augments.js +5 -5
  137. package/dist/augments/markdown-augments.js.map +1 -1
  138. package/dist/augments/safe-markdown.d.ts +10 -0
  139. package/dist/augments/safe-markdown.d.ts.map +1 -1
  140. package/dist/augments/safe-markdown.js +146 -3
  141. package/dist/augments/safe-markdown.js.map +1 -1
  142. package/dist/augments/stream-augmenter.d.ts +3 -0
  143. package/dist/augments/stream-augmenter.d.ts.map +1 -1
  144. package/dist/augments/stream-augmenter.js +6 -3
  145. package/dist/augments/stream-augmenter.js.map +1 -1
  146. package/dist/augments/stream-coordinator.d.ts +5 -1
  147. package/dist/augments/stream-coordinator.d.ts.map +1 -1
  148. package/dist/augments/stream-coordinator.js +6 -4
  149. package/dist/augments/stream-coordinator.js.map +1 -1
  150. package/dist/augments/task-list-augments.d.ts +27 -0
  151. package/dist/augments/task-list-augments.d.ts.map +1 -0
  152. package/dist/augments/task-list-augments.js +360 -0
  153. package/dist/augments/task-list-augments.js.map +1 -0
  154. package/dist/cli.d.ts +1 -17
  155. package/dist/cli.d.ts.map +1 -1
  156. package/dist/cli.js +22 -8
  157. package/dist/cli.js.map +1 -1
  158. package/dist/codex/correlationDebugLogger.d.ts.map +1 -1
  159. package/dist/codex/correlationDebugLogger.js +36 -8
  160. package/dist/codex/correlationDebugLogger.js.map +1 -1
  161. package/dist/codex/normalization.d.ts +1 -0
  162. package/dist/codex/normalization.d.ts.map +1 -1
  163. package/dist/codex/normalization.js +262 -7
  164. package/dist/codex/normalization.js.map +1 -1
  165. package/dist/config.d.ts +49 -6
  166. package/dist/config.d.ts.map +1 -1
  167. package/dist/config.js +55 -14
  168. package/dist/config.js.map +1 -1
  169. package/dist/defaults.d.ts +3 -0
  170. package/dist/defaults.d.ts.map +1 -0
  171. package/dist/defaults.js +3 -0
  172. package/dist/defaults.js.map +1 -0
  173. package/dist/device/DeviceBridgeService.js +1 -1
  174. package/dist/device/DeviceBridgeService.js.map +1 -1
  175. package/dist/envSettings.d.ts +64 -0
  176. package/dist/envSettings.d.ts.map +1 -0
  177. package/dist/envSettings.js +553 -0
  178. package/dist/envSettings.js.map +1 -0
  179. package/dist/frontend/static.d.ts.map +1 -1
  180. package/dist/frontend/static.js +3 -1
  181. package/dist/frontend/static.js.map +1 -1
  182. package/dist/index.d.ts +1 -1
  183. package/dist/index.d.ts.map +1 -1
  184. package/dist/index.js +190 -14
  185. package/dist/index.js.map +1 -1
  186. package/dist/indexes/SessionDiscoveryIndex.d.ts +78 -0
  187. package/dist/indexes/SessionDiscoveryIndex.d.ts.map +1 -0
  188. package/dist/indexes/SessionDiscoveryIndex.js +223 -0
  189. package/dist/indexes/SessionDiscoveryIndex.js.map +1 -0
  190. package/dist/indexes/SessionIndexService.d.ts +114 -1
  191. package/dist/indexes/SessionIndexService.d.ts.map +1 -1
  192. package/dist/indexes/SessionIndexService.js +875 -105
  193. package/dist/indexes/SessionIndexService.js.map +1 -1
  194. package/dist/indexes/index.d.ts +2 -1
  195. package/dist/indexes/index.d.ts.map +1 -1
  196. package/dist/indexes/index.js +1 -0
  197. package/dist/indexes/index.js.map +1 -1
  198. package/dist/indexes/types.d.ts +26 -0
  199. package/dist/indexes/types.d.ts.map +1 -1
  200. package/dist/logging/logger.d.ts.map +1 -1
  201. package/dist/logging/logger.js +2 -3
  202. package/dist/logging/logger.js.map +1 -1
  203. package/dist/maintenance/server.d.ts.map +1 -1
  204. package/dist/maintenance/server.js +8 -11
  205. package/dist/maintenance/server.js.map +1 -1
  206. package/dist/metadata/ProjectMetadataService.d.ts +7 -0
  207. package/dist/metadata/ProjectMetadataService.d.ts.map +1 -1
  208. package/dist/metadata/ProjectMetadataService.js +63 -19
  209. package/dist/metadata/ProjectMetadataService.js.map +1 -1
  210. package/dist/metadata/SessionMetadataService.d.ts +82 -3
  211. package/dist/metadata/SessionMetadataService.d.ts.map +1 -1
  212. package/dist/metadata/SessionMetadataService.js +233 -17
  213. package/dist/metadata/SessionMetadataService.js.map +1 -1
  214. package/dist/middleware/file-access.d.ts +66 -0
  215. package/dist/middleware/file-access.d.ts.map +1 -0
  216. package/dist/middleware/file-access.js +112 -0
  217. package/dist/middleware/file-access.js.map +1 -0
  218. package/dist/projects/codex-scanner.d.ts +28 -1
  219. package/dist/projects/codex-scanner.d.ts.map +1 -1
  220. package/dist/projects/codex-scanner.js +149 -39
  221. package/dist/projects/codex-scanner.js.map +1 -1
  222. package/dist/projects/gemini-scanner.d.ts.map +1 -1
  223. package/dist/projects/gemini-scanner.js +59 -6
  224. package/dist/projects/gemini-scanner.js.map +1 -1
  225. package/dist/projects/paths.d.ts +15 -1
  226. package/dist/projects/paths.d.ts.map +1 -1
  227. package/dist/projects/paths.js +69 -23
  228. package/dist/projects/paths.js.map +1 -1
  229. package/dist/projects/scanner.d.ts +5 -0
  230. package/dist/projects/scanner.d.ts.map +1 -1
  231. package/dist/projects/scanner.js +136 -28
  232. package/dist/projects/scanner.js.map +1 -1
  233. package/dist/push/InactivityPushNotifier.d.ts +61 -0
  234. package/dist/push/InactivityPushNotifier.d.ts.map +1 -0
  235. package/dist/push/InactivityPushNotifier.js +305 -0
  236. package/dist/push/InactivityPushNotifier.js.map +1 -0
  237. package/dist/push/PushNotifier.d.ts.map +1 -1
  238. package/dist/push/PushNotifier.js.map +1 -1
  239. package/dist/push/PushService.d.ts +7 -4
  240. package/dist/push/PushService.d.ts.map +1 -1
  241. package/dist/push/PushService.js +27 -7
  242. package/dist/push/PushService.js.map +1 -1
  243. package/dist/push/index.d.ts +2 -1
  244. package/dist/push/index.d.ts.map +1 -1
  245. package/dist/push/index.js +1 -0
  246. package/dist/push/index.js.map +1 -1
  247. package/dist/push/routes.d.ts.map +1 -1
  248. package/dist/push/routes.js +28 -1
  249. package/dist/push/routes.js.map +1 -1
  250. package/dist/push/types.d.ts +21 -3
  251. package/dist/push/types.d.ts.map +1 -1
  252. package/dist/push/types.js +2 -0
  253. package/dist/push/types.js.map +1 -1
  254. package/dist/routes/dev.d.ts +2 -0
  255. package/dist/routes/dev.d.ts.map +1 -1
  256. package/dist/routes/dev.js +25 -0
  257. package/dist/routes/dev.js.map +1 -1
  258. package/dist/routes/env-settings.d.ts +20 -0
  259. package/dist/routes/env-settings.d.ts.map +1 -0
  260. package/dist/routes/env-settings.js +25 -0
  261. package/dist/routes/env-settings.js.map +1 -0
  262. package/dist/routes/files.d.ts +9 -0
  263. package/dist/routes/files.d.ts.map +1 -1
  264. package/dist/routes/files.js +98 -10
  265. package/dist/routes/files.js.map +1 -1
  266. package/dist/routes/git-status.d.ts.map +1 -1
  267. package/dist/routes/git-status.js +621 -23
  268. package/dist/routes/git-status.js.map +1 -1
  269. package/dist/routes/global-sessions.d.ts +11 -1
  270. package/dist/routes/global-sessions.d.ts.map +1 -1
  271. package/dist/routes/global-sessions.js +53 -33
  272. package/dist/routes/global-sessions.js.map +1 -1
  273. package/dist/routes/inbox.d.ts +10 -1
  274. package/dist/routes/inbox.d.ts.map +1 -1
  275. package/dist/routes/inbox.js +30 -3
  276. package/dist/routes/inbox.js.map +1 -1
  277. package/dist/routes/local-file.d.ts +6 -2
  278. package/dist/routes/local-file.d.ts.map +1 -1
  279. package/dist/routes/local-file.js +13 -4
  280. package/dist/routes/local-file.js.map +1 -1
  281. package/dist/routes/local-image.d.ts +2 -1
  282. package/dist/routes/local-image.d.ts.map +1 -1
  283. package/dist/routes/local-image.js.map +1 -1
  284. package/dist/routes/local-resource-policy.d.ts +7 -1
  285. package/dist/routes/local-resource-policy.d.ts.map +1 -1
  286. package/dist/routes/local-resource-policy.js +0 -0
  287. package/dist/routes/local-resource-policy.js.map +1 -1
  288. package/dist/routes/processes.d.ts.map +1 -1
  289. package/dist/routes/processes.js +49 -11
  290. package/dist/routes/processes.js.map +1 -1
  291. package/dist/routes/project-queue-response.d.ts +26 -0
  292. package/dist/routes/project-queue-response.d.ts.map +1 -0
  293. package/dist/routes/project-queue-response.js +188 -0
  294. package/dist/routes/project-queue-response.js.map +1 -0
  295. package/dist/routes/project-queue.d.ts +5 -0
  296. package/dist/routes/project-queue.d.ts.map +1 -0
  297. package/dist/routes/project-queue.js +219 -0
  298. package/dist/routes/project-queue.js.map +1 -0
  299. package/dist/routes/projects.d.ts +6 -0
  300. package/dist/routes/projects.d.ts.map +1 -1
  301. package/dist/routes/projects.js +116 -28
  302. package/dist/routes/projects.js.map +1 -1
  303. package/dist/routes/providers.d.ts +5 -0
  304. package/dist/routes/providers.d.ts.map +1 -1
  305. package/dist/routes/providers.js +52 -33
  306. package/dist/routes/providers.js.map +1 -1
  307. package/dist/routes/public-shares.d.ts.map +1 -1
  308. package/dist/routes/public-shares.js +46 -17
  309. package/dist/routes/public-shares.js.map +1 -1
  310. package/dist/routes/recents.d.ts +3 -0
  311. package/dist/routes/recents.d.ts.map +1 -1
  312. package/dist/routes/recents.js +3 -1
  313. package/dist/routes/recents.js.map +1 -1
  314. package/dist/routes/server-admin.d.ts +9 -0
  315. package/dist/routes/server-admin.d.ts.map +1 -1
  316. package/dist/routes/server-admin.js +45 -7
  317. package/dist/routes/server-admin.js.map +1 -1
  318. package/dist/routes/session-claude-resume-guard.d.ts +16 -0
  319. package/dist/routes/session-claude-resume-guard.d.ts.map +1 -0
  320. package/dist/routes/session-claude-resume-guard.js +50 -0
  321. package/dist/routes/session-claude-resume-guard.js.map +1 -0
  322. package/dist/routes/session-compact-thresholds.d.ts +22 -0
  323. package/dist/routes/session-compact-thresholds.d.ts.map +1 -0
  324. package/dist/routes/session-compact-thresholds.js +35 -0
  325. package/dist/routes/session-compact-thresholds.js.map +1 -0
  326. package/dist/routes/session-index.d.ts +7 -0
  327. package/dist/routes/session-index.d.ts.map +1 -0
  328. package/dist/routes/session-index.js +9 -0
  329. package/dist/routes/session-index.js.map +1 -0
  330. package/dist/routes/session-list-options.d.ts +1 -1
  331. package/dist/routes/session-list-options.d.ts.map +1 -1
  332. package/dist/routes/session-list-options.js +1 -1
  333. package/dist/routes/session-list-options.js.map +1 -1
  334. package/dist/routes/session-request-helpers.d.ts +31 -0
  335. package/dist/routes/session-request-helpers.d.ts.map +1 -0
  336. package/dist/routes/session-request-helpers.js +212 -0
  337. package/dist/routes/session-request-helpers.js.map +1 -0
  338. package/dist/routes/sessions.d.ts +14 -1
  339. package/dist/routes/sessions.d.ts.map +1 -1
  340. package/dist/routes/sessions.js +2141 -551
  341. package/dist/routes/sessions.js.map +1 -1
  342. package/dist/routes/settings.d.ts +7 -1
  343. package/dist/routes/settings.d.ts.map +1 -1
  344. package/dist/routes/settings.js +771 -25
  345. package/dist/routes/settings.js.map +1 -1
  346. package/dist/routes/speech.d.ts +24 -2
  347. package/dist/routes/speech.d.ts.map +1 -1
  348. package/dist/routes/speech.js +539 -10
  349. package/dist/routes/speech.js.map +1 -1
  350. package/dist/routes/supervisor-queue.d.ts +6 -0
  351. package/dist/routes/supervisor-queue.d.ts.map +1 -0
  352. package/dist/routes/supervisor-queue.js +35 -0
  353. package/dist/routes/supervisor-queue.js.map +1 -0
  354. package/dist/routes/upload.d.ts +2 -0
  355. package/dist/routes/upload.d.ts.map +1 -1
  356. package/dist/routes/upload.js +190 -38
  357. package/dist/routes/upload.js.map +1 -1
  358. package/dist/routes/version.d.ts +18 -1
  359. package/dist/routes/version.d.ts.map +1 -1
  360. package/dist/routes/version.js +22 -1
  361. package/dist/routes/version.js.map +1 -1
  362. package/dist/routes/workstreams.d.ts +11 -0
  363. package/dist/routes/workstreams.d.ts.map +1 -0
  364. package/dist/routes/workstreams.js +144 -0
  365. package/dist/routes/workstreams.js.map +1 -0
  366. package/dist/routes/ws-message-router.d.ts +10 -1
  367. package/dist/routes/ws-message-router.d.ts.map +1 -1
  368. package/dist/routes/ws-message-router.js +43 -4
  369. package/dist/routes/ws-message-router.js.map +1 -1
  370. package/dist/routes/ws-relay-handlers.d.ts +27 -5
  371. package/dist/routes/ws-relay-handlers.d.ts.map +1 -1
  372. package/dist/routes/ws-relay-handlers.js +177 -19
  373. package/dist/routes/ws-relay-handlers.js.map +1 -1
  374. package/dist/routes/ws-relay.d.ts +19 -0
  375. package/dist/routes/ws-relay.d.ts.map +1 -1
  376. package/dist/routes/ws-relay.js +21 -7
  377. package/dist/routes/ws-relay.js.map +1 -1
  378. package/dist/sdk/cli-detection.d.ts +1 -1
  379. package/dist/sdk/cli-detection.d.ts.map +1 -1
  380. package/dist/sdk/cli-detection.js +47 -7
  381. package/dist/sdk/cli-detection.js.map +1 -1
  382. package/dist/sdk/messageLogger.d.ts.map +1 -1
  383. package/dist/sdk/messageLogger.js +38 -10
  384. package/dist/sdk/messageLogger.js.map +1 -1
  385. package/dist/sdk/messageQueue.d.ts.map +1 -1
  386. package/dist/sdk/messageQueue.js +26 -0
  387. package/dist/sdk/messageQueue.js.map +1 -1
  388. package/dist/sdk/providers/__mocks__/grok.d.ts +1 -1
  389. package/dist/sdk/providers/__mocks__/grok.d.ts.map +1 -1
  390. package/dist/sdk/providers/__mocks__/grok.js +1 -1
  391. package/dist/sdk/providers/__mocks__/grok.js.map +1 -1
  392. package/dist/sdk/providers/agentctl-session-env.d.ts +8 -0
  393. package/dist/sdk/providers/agentctl-session-env.d.ts.map +1 -0
  394. package/dist/sdk/providers/agentctl-session-env.js +52 -0
  395. package/dist/sdk/providers/agentctl-session-env.js.map +1 -0
  396. package/dist/sdk/providers/claude-ollama.d.ts +2 -1
  397. package/dist/sdk/providers/claude-ollama.d.ts.map +1 -1
  398. package/dist/sdk/providers/claude-ollama.js +1 -0
  399. package/dist/sdk/providers/claude-ollama.js.map +1 -1
  400. package/dist/sdk/providers/claude-retention.d.ts +19 -0
  401. package/dist/sdk/providers/claude-retention.d.ts.map +1 -0
  402. package/dist/sdk/providers/claude-retention.js +169 -0
  403. package/dist/sdk/providers/claude-retention.js.map +1 -0
  404. package/dist/sdk/providers/claude.d.ts +52 -5
  405. package/dist/sdk/providers/claude.d.ts.map +1 -1
  406. package/dist/sdk/providers/claude.js +593 -71
  407. package/dist/sdk/providers/claude.js.map +1 -1
  408. package/dist/sdk/providers/codex-protocol/generated/AgentMessageInputContent.d.ts +8 -0
  409. package/dist/sdk/providers/codex-protocol/generated/AgentMessageInputContent.d.ts.map +1 -0
  410. package/dist/sdk/providers/codex-protocol/generated/AgentMessageInputContent.js +3 -0
  411. package/dist/sdk/providers/codex-protocol/generated/AgentMessageInputContent.js.map +1 -0
  412. package/dist/sdk/providers/codex-protocol/generated/InternalChatMessageMetadataPassthrough.d.ts +10 -0
  413. package/dist/sdk/providers/codex-protocol/generated/InternalChatMessageMetadataPassthrough.d.ts.map +1 -0
  414. package/dist/sdk/providers/codex-protocol/generated/InternalChatMessageMetadataPassthrough.js +3 -0
  415. package/dist/sdk/providers/codex-protocol/generated/InternalChatMessageMetadataPassthrough.js.map +1 -0
  416. package/dist/sdk/providers/codex-protocol/generated/LegacyAppPathString.d.ts +23 -0
  417. package/dist/sdk/providers/codex-protocol/generated/LegacyAppPathString.d.ts.map +1 -0
  418. package/dist/sdk/providers/codex-protocol/generated/LegacyAppPathString.js +3 -0
  419. package/dist/sdk/providers/codex-protocol/generated/LegacyAppPathString.js.map +1 -0
  420. package/dist/sdk/providers/codex-protocol/generated/MultiAgentMode.d.ts +8 -0
  421. package/dist/sdk/providers/codex-protocol/generated/MultiAgentMode.d.ts.map +1 -0
  422. package/dist/sdk/providers/codex-protocol/generated/MultiAgentMode.js +3 -0
  423. package/dist/sdk/providers/codex-protocol/generated/MultiAgentMode.js.map +1 -0
  424. package/dist/sdk/providers/codex-protocol/generated/ReasoningEffort.d.ts +1 -1
  425. package/dist/sdk/providers/codex-protocol/generated/ReasoningEffort.d.ts.map +1 -1
  426. package/dist/sdk/providers/codex-protocol/generated/ResponseItem.d.ts +38 -1
  427. package/dist/sdk/providers/codex-protocol/generated/ResponseItem.d.ts.map +1 -1
  428. package/dist/sdk/providers/codex-protocol/generated/v2/AdditionalFileSystemPermissions.d.ts +3 -3
  429. package/dist/sdk/providers/codex-protocol/generated/v2/AdditionalFileSystemPermissions.d.ts.map +1 -1
  430. package/dist/sdk/providers/codex-protocol/generated/v2/CapabilityRootLocation.d.ts +9 -0
  431. package/dist/sdk/providers/codex-protocol/generated/v2/CapabilityRootLocation.d.ts.map +1 -0
  432. package/dist/sdk/providers/codex-protocol/generated/v2/CapabilityRootLocation.js +3 -0
  433. package/dist/sdk/providers/codex-protocol/generated/v2/CapabilityRootLocation.js.map +1 -0
  434. package/dist/sdk/providers/codex-protocol/generated/v2/CommandExecutionRequestApprovalParams.d.ts +6 -2
  435. package/dist/sdk/providers/codex-protocol/generated/v2/CommandExecutionRequestApprovalParams.d.ts.map +1 -1
  436. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolFunctionSpec.d.ts +8 -0
  437. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolFunctionSpec.d.ts.map +1 -0
  438. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolFunctionSpec.js +3 -0
  439. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolFunctionSpec.js.map +1 -0
  440. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolNamespaceSpec.d.ts +7 -0
  441. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolNamespaceSpec.d.ts.map +1 -0
  442. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolNamespaceSpec.js +3 -0
  443. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolNamespaceSpec.js.map +1 -0
  444. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolNamespaceTool.d.ts +5 -0
  445. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolNamespaceTool.d.ts.map +1 -0
  446. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolNamespaceTool.js +3 -0
  447. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolNamespaceTool.js.map +1 -0
  448. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolSpec.d.ts +6 -7
  449. package/dist/sdk/providers/codex-protocol/generated/v2/DynamicToolSpec.d.ts.map +1 -1
  450. package/dist/sdk/providers/codex-protocol/generated/v2/FileSystemPath.d.ts +2 -2
  451. package/dist/sdk/providers/codex-protocol/generated/v2/FileSystemPath.d.ts.map +1 -1
  452. package/dist/sdk/providers/codex-protocol/generated/v2/McpToolCallAppContext.d.ts +6 -0
  453. package/dist/sdk/providers/codex-protocol/generated/v2/McpToolCallAppContext.d.ts.map +1 -0
  454. package/dist/sdk/providers/codex-protocol/generated/v2/McpToolCallAppContext.js +3 -0
  455. package/dist/sdk/providers/codex-protocol/generated/v2/McpToolCallAppContext.js.map +1 -0
  456. package/dist/sdk/providers/codex-protocol/generated/v2/PermissionsRequestApprovalParams.d.ts +1 -0
  457. package/dist/sdk/providers/codex-protocol/generated/v2/PermissionsRequestApprovalParams.d.ts.map +1 -1
  458. package/dist/sdk/providers/codex-protocol/generated/v2/SelectedCapabilityRoot.d.ts +15 -0
  459. package/dist/sdk/providers/codex-protocol/generated/v2/SelectedCapabilityRoot.d.ts.map +1 -0
  460. package/dist/sdk/providers/codex-protocol/generated/v2/SelectedCapabilityRoot.js +3 -0
  461. package/dist/sdk/providers/codex-protocol/generated/v2/SelectedCapabilityRoot.js.map +1 -0
  462. package/dist/sdk/providers/codex-protocol/generated/v2/SortDirection.d.ts +2 -0
  463. package/dist/sdk/providers/codex-protocol/generated/v2/SortDirection.d.ts.map +1 -0
  464. package/dist/sdk/providers/codex-protocol/generated/v2/SortDirection.js +3 -0
  465. package/dist/sdk/providers/codex-protocol/generated/v2/SortDirection.js.map +1 -0
  466. package/dist/sdk/providers/codex-protocol/generated/v2/SubAgentActivityKind.d.ts +2 -0
  467. package/dist/sdk/providers/codex-protocol/generated/v2/SubAgentActivityKind.d.ts.map +1 -0
  468. package/dist/sdk/providers/codex-protocol/generated/v2/SubAgentActivityKind.js +3 -0
  469. package/dist/sdk/providers/codex-protocol/generated/v2/SubAgentActivityKind.js.map +1 -0
  470. package/dist/sdk/providers/codex-protocol/generated/v2/Thread.d.ts +8 -0
  471. package/dist/sdk/providers/codex-protocol/generated/v2/Thread.d.ts.map +1 -1
  472. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadCompactStartParams.d.ts +4 -0
  473. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadCompactStartParams.d.ts.map +1 -0
  474. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadCompactStartParams.js +3 -0
  475. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadCompactStartParams.js.map +1 -0
  476. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadCompactStartResponse.d.ts +2 -0
  477. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadCompactStartResponse.d.ts.map +1 -0
  478. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadCompactStartResponse.js +3 -0
  479. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadCompactStartResponse.js.map +1 -0
  480. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkParams.d.ts +64 -0
  481. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkParams.d.ts.map +1 -0
  482. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkParams.js +3 -0
  483. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkParams.js.map +1 -0
  484. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkResponse.d.ts +46 -0
  485. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkResponse.d.ts.map +1 -0
  486. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkResponse.js +3 -0
  487. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkResponse.js.map +1 -0
  488. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadItem.d.ts +19 -1
  489. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadItem.d.ts.map +1 -1
  490. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadReadResponse.d.ts +5 -0
  491. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadReadResponse.d.ts.map +1 -0
  492. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadReadResponse.js +3 -0
  493. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadReadResponse.js.map +1 -0
  494. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadResumeInitialTurnsPageParams.d.ts +17 -0
  495. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadResumeInitialTurnsPageParams.d.ts.map +1 -0
  496. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadResumeInitialTurnsPageParams.js +3 -0
  497. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadResumeInitialTurnsPageParams.js.map +1 -0
  498. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadResumeParams.d.ts +7 -7
  499. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadResumeParams.d.ts.map +1 -1
  500. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadResumeResponse.d.ts +13 -2
  501. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadResumeResponse.d.ts.map +1 -1
  502. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackParams.d.ts +11 -0
  503. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackParams.d.ts.map +1 -0
  504. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackParams.js +3 -0
  505. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackParams.js.map +1 -0
  506. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackResponse.d.ts +12 -0
  507. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackResponse.d.ts.map +1 -0
  508. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackResponse.js +3 -0
  509. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackResponse.js.map +1 -0
  510. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadSource.d.ts +1 -1
  511. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadSource.d.ts.map +1 -1
  512. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadStartParams.d.ts +13 -9
  513. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadStartParams.d.ts.map +1 -1
  514. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadStartResponse.d.ts +8 -2
  515. package/dist/sdk/providers/codex-protocol/generated/v2/ThreadStartResponse.d.ts.map +1 -1
  516. package/dist/sdk/providers/codex-protocol/generated/v2/ToolRequestUserInputParams.d.ts +1 -0
  517. package/dist/sdk/providers/codex-protocol/generated/v2/ToolRequestUserInputParams.d.ts.map +1 -1
  518. package/dist/sdk/providers/codex-protocol/generated/v2/TurnEnvironmentParams.d.ts +2 -2
  519. package/dist/sdk/providers/codex-protocol/generated/v2/TurnEnvironmentParams.d.ts.map +1 -1
  520. package/dist/sdk/providers/codex-protocol/generated/v2/TurnStartParams.d.ts +17 -5
  521. package/dist/sdk/providers/codex-protocol/generated/v2/TurnStartParams.d.ts.map +1 -1
  522. package/dist/sdk/providers/codex-protocol/generated/v2/TurnSteerParams.d.ts +8 -1
  523. package/dist/sdk/providers/codex-protocol/generated/v2/TurnSteerParams.d.ts.map +1 -1
  524. package/dist/sdk/providers/codex-protocol/generated/v2/TurnsPage.d.ts +7 -0
  525. package/dist/sdk/providers/codex-protocol/generated/v2/TurnsPage.d.ts.map +1 -0
  526. package/dist/sdk/providers/codex-protocol/generated/v2/TurnsPage.js +3 -0
  527. package/dist/sdk/providers/codex-protocol/generated/v2/TurnsPage.js.map +1 -0
  528. package/dist/sdk/providers/codex-protocol/index.d.ts +7 -0
  529. package/dist/sdk/providers/codex-protocol/index.d.ts.map +1 -1
  530. package/dist/sdk/providers/codex.d.ts +26 -4
  531. package/dist/sdk/providers/codex.d.ts.map +1 -1
  532. package/dist/sdk/providers/codex.js +457 -37
  533. package/dist/sdk/providers/codex.js.map +1 -1
  534. package/dist/sdk/providers/env-filter.d.ts.map +1 -1
  535. package/dist/sdk/providers/env-filter.js +19 -1
  536. package/dist/sdk/providers/env-filter.js.map +1 -1
  537. package/dist/sdk/providers/gemini-tools.d.ts +28 -0
  538. package/dist/sdk/providers/gemini-tools.d.ts.map +1 -0
  539. package/dist/sdk/providers/gemini-tools.js +57 -0
  540. package/dist/sdk/providers/gemini-tools.js.map +1 -0
  541. package/dist/sdk/providers/gemini.d.ts.map +1 -1
  542. package/dist/sdk/providers/gemini.js +4 -2
  543. package/dist/sdk/providers/gemini.js.map +1 -1
  544. package/dist/sdk/providers/grok-acp.d.ts +1 -1
  545. package/dist/sdk/providers/grok-acp.d.ts.map +1 -1
  546. package/dist/sdk/providers/grok-acp.js +1 -1
  547. package/dist/sdk/providers/grok-acp.js.map +1 -1
  548. package/dist/sdk/providers/index.d.ts +1 -0
  549. package/dist/sdk/providers/index.d.ts.map +1 -1
  550. package/dist/sdk/providers/index.js +6 -0
  551. package/dist/sdk/providers/index.js.map +1 -1
  552. package/dist/sdk/providers/opencode-tools.d.ts +36 -0
  553. package/dist/sdk/providers/opencode-tools.d.ts.map +1 -0
  554. package/dist/sdk/providers/opencode-tools.js +78 -0
  555. package/dist/sdk/providers/opencode-tools.js.map +1 -0
  556. package/dist/sdk/providers/opencode.d.ts +53 -5
  557. package/dist/sdk/providers/opencode.d.ts.map +1 -1
  558. package/dist/sdk/providers/opencode.js +379 -71
  559. package/dist/sdk/providers/opencode.js.map +1 -1
  560. package/dist/sdk/providers/pi-rpc-client.d.ts +90 -0
  561. package/dist/sdk/providers/pi-rpc-client.d.ts.map +1 -0
  562. package/dist/sdk/providers/pi-rpc-client.js +168 -0
  563. package/dist/sdk/providers/pi-rpc-client.js.map +1 -0
  564. package/dist/sdk/providers/pi-tools.d.ts +38 -0
  565. package/dist/sdk/providers/pi-tools.d.ts.map +1 -0
  566. package/dist/sdk/providers/pi-tools.js +214 -0
  567. package/dist/sdk/providers/pi-tools.js.map +1 -0
  568. package/dist/sdk/providers/pi.d.ts +84 -0
  569. package/dist/sdk/providers/pi.d.ts.map +1 -0
  570. package/dist/sdk/providers/pi.js +686 -0
  571. package/dist/sdk/providers/pi.js.map +1 -0
  572. package/dist/sdk/providers/staticSlashCommands.d.ts +4 -0
  573. package/dist/sdk/providers/staticSlashCommands.d.ts.map +1 -0
  574. package/dist/sdk/providers/staticSlashCommands.js +14 -0
  575. package/dist/sdk/providers/staticSlashCommands.js.map +1 -0
  576. package/dist/sdk/providers/types.d.ts +144 -17
  577. package/dist/sdk/providers/types.d.ts.map +1 -1
  578. package/dist/sdk/remote-spawn.d.ts.map +1 -1
  579. package/dist/sdk/remote-spawn.js.map +1 -1
  580. package/dist/sdk/slashCommandEmulation.d.ts +9 -0
  581. package/dist/sdk/slashCommandEmulation.d.ts.map +1 -1
  582. package/dist/sdk/slashCommandEmulation.js +15 -0
  583. package/dist/sdk/slashCommandEmulation.js.map +1 -1
  584. package/dist/sdk/types.d.ts +40 -0
  585. package/dist/sdk/types.d.ts.map +1 -1
  586. package/dist/security/approvalAuditLog.d.ts +3 -2
  587. package/dist/security/approvalAuditLog.d.ts.map +1 -1
  588. package/dist/security/approvalAuditLog.js +62 -2
  589. package/dist/security/approvalAuditLog.js.map +1 -1
  590. package/dist/services/BrowserProfileService.d.ts +21 -0
  591. package/dist/services/BrowserProfileService.d.ts.map +1 -1
  592. package/dist/services/BrowserProfileService.js +74 -1
  593. package/dist/services/BrowserProfileService.js.map +1 -1
  594. package/dist/services/CacheMissBillingMonitor.d.ts +25 -0
  595. package/dist/services/CacheMissBillingMonitor.d.ts.map +1 -0
  596. package/dist/services/CacheMissBillingMonitor.js +179 -0
  597. package/dist/services/CacheMissBillingMonitor.js.map +1 -0
  598. package/dist/services/CodexUpdateChecker.d.ts.map +1 -1
  599. package/dist/services/CodexUpdateChecker.js +3 -2
  600. package/dist/services/CodexUpdateChecker.js.map +1 -1
  601. package/dist/services/ModelInfoService.d.ts +58 -9
  602. package/dist/services/ModelInfoService.d.ts.map +1 -1
  603. package/dist/services/ModelInfoService.js +127 -14
  604. package/dist/services/ModelInfoService.js.map +1 -1
  605. package/dist/services/ProjectQueueScheduler.d.ts +91 -0
  606. package/dist/services/ProjectQueueScheduler.d.ts.map +1 -0
  607. package/dist/services/ProjectQueueScheduler.js +404 -0
  608. package/dist/services/ProjectQueueScheduler.js.map +1 -0
  609. package/dist/services/ProjectQueueService.d.ts +60 -0
  610. package/dist/services/ProjectQueueService.d.ts.map +1 -0
  611. package/dist/services/ProjectQueueService.js +804 -0
  612. package/dist/services/ProjectQueueService.js.map +1 -0
  613. package/dist/services/RelayClientService.d.ts +5 -0
  614. package/dist/services/RelayClientService.d.ts.map +1 -1
  615. package/dist/services/RelayClientService.js +26 -12
  616. package/dist/services/RelayClientService.js.map +1 -1
  617. package/dist/services/SafeRestartService.d.ts +48 -0
  618. package/dist/services/SafeRestartService.d.ts.map +1 -0
  619. package/dist/services/SafeRestartService.js +173 -0
  620. package/dist/services/SafeRestartService.js.map +1 -0
  621. package/dist/services/ServerSettingsService.d.ts +41 -1
  622. package/dist/services/ServerSettingsService.d.ts.map +1 -1
  623. package/dist/services/ServerSettingsService.js +110 -1
  624. package/dist/services/ServerSettingsService.js.map +1 -1
  625. package/dist/services/SessionQueuePersistenceService.d.ts +55 -0
  626. package/dist/services/SessionQueuePersistenceService.d.ts.map +1 -0
  627. package/dist/services/SessionQueuePersistenceService.js +264 -0
  628. package/dist/services/SessionQueuePersistenceService.js.map +1 -0
  629. package/dist/services/WorkstreamService.d.ts +92 -0
  630. package/dist/services/WorkstreamService.d.ts.map +1 -0
  631. package/dist/services/WorkstreamService.js +627 -0
  632. package/dist/services/WorkstreamService.js.map +1 -0
  633. package/dist/services/index.d.ts +4 -0
  634. package/dist/services/index.d.ts.map +1 -1
  635. package/dist/services/index.js +4 -0
  636. package/dist/services/index.js.map +1 -1
  637. package/dist/services/projectWorkIdle.d.ts +42 -0
  638. package/dist/services/projectWorkIdle.d.ts.map +1 -0
  639. package/dist/services/projectWorkIdle.js +50 -0
  640. package/dist/services/projectWorkIdle.js.map +1 -0
  641. package/dist/services/voice/SpeechBackend.d.ts +18 -1
  642. package/dist/services/voice/SpeechBackend.d.ts.map +1 -1
  643. package/dist/services/voice/SpeechBackend.js +3 -0
  644. package/dist/services/voice/SpeechBackend.js.map +1 -1
  645. package/dist/services/voice/audioRetention.d.ts +20 -0
  646. package/dist/services/voice/audioRetention.d.ts.map +1 -1
  647. package/dist/services/voice/audioRetention.js +2 -0
  648. package/dist/services/voice/audioRetention.js.map +1 -1
  649. package/dist/services/voice/deepgramBackend.d.ts.map +1 -1
  650. package/dist/services/voice/deepgramBackend.js +4 -1
  651. package/dist/services/voice/deepgramBackend.js.map +1 -1
  652. package/dist/services/voice/localNemoBackend.d.ts +31 -0
  653. package/dist/services/voice/localNemoBackend.d.ts.map +1 -0
  654. package/dist/services/voice/localNemoBackend.js +181 -0
  655. package/dist/services/voice/localNemoBackend.js.map +1 -0
  656. package/dist/services/voice/localParakeetBackend.d.ts +31 -0
  657. package/dist/services/voice/localParakeetBackend.d.ts.map +1 -0
  658. package/dist/services/voice/localParakeetBackend.js +180 -0
  659. package/dist/services/voice/localParakeetBackend.js.map +1 -0
  660. package/dist/services/voice/localSttRuntime.d.ts +21 -0
  661. package/dist/services/voice/localSttRuntime.d.ts.map +1 -0
  662. package/dist/services/voice/localSttRuntime.js +87 -0
  663. package/dist/services/voice/localSttRuntime.js.map +1 -0
  664. package/dist/services/voice/localWhisperBackend.d.ts +2 -1
  665. package/dist/services/voice/localWhisperBackend.d.ts.map +1 -1
  666. package/dist/services/voice/localWhisperBackend.js +47 -34
  667. package/dist/services/voice/localWhisperBackend.js.map +1 -1
  668. package/dist/services/voice/nemo_worker.py +232 -0
  669. package/dist/services/voice/parakeet_worker.py +151 -0
  670. package/dist/services/voice/registry.d.ts +19 -4
  671. package/dist/services/voice/registry.d.ts.map +1 -1
  672. package/dist/services/voice/registry.js +72 -22
  673. package/dist/services/voice/registry.js.map +1 -1
  674. package/dist/services/voice/serialQueue.d.ts +17 -0
  675. package/dist/services/voice/serialQueue.d.ts.map +1 -0
  676. package/dist/services/voice/serialQueue.js +24 -0
  677. package/dist/services/voice/serialQueue.js.map +1 -0
  678. package/dist/services/voice/whisper_worker.py +94 -0
  679. package/dist/services/voice/xaiSttBackend.d.ts +1 -1
  680. package/dist/services/voice/xaiSttBackend.d.ts.map +1 -1
  681. package/dist/services/voice/xaiSttBackend.js +15 -3
  682. package/dist/services/voice/xaiSttBackend.js.map +1 -1
  683. package/dist/sessions/agent-excerpt.d.ts +29 -0
  684. package/dist/sessions/agent-excerpt.d.ts.map +1 -0
  685. package/dist/sessions/agent-excerpt.js +128 -0
  686. package/dist/sessions/agent-excerpt.js.map +1 -0
  687. package/dist/sessions/claude-messages.d.ts.map +1 -1
  688. package/dist/sessions/claude-messages.js +75 -4
  689. package/dist/sessions/claude-messages.js.map +1 -1
  690. package/dist/sessions/claude-summary.d.ts +33 -0
  691. package/dist/sessions/claude-summary.d.ts.map +1 -0
  692. package/dist/sessions/claude-summary.js +461 -0
  693. package/dist/sessions/claude-summary.js.map +1 -0
  694. package/dist/sessions/codex-discovery.d.ts +46 -0
  695. package/dist/sessions/codex-discovery.d.ts.map +1 -0
  696. package/dist/sessions/codex-discovery.js +269 -0
  697. package/dist/sessions/codex-discovery.js.map +1 -0
  698. package/dist/sessions/codex-reader.d.ts +96 -13
  699. package/dist/sessions/codex-reader.d.ts.map +1 -1
  700. package/dist/sessions/codex-reader.js +1069 -141
  701. package/dist/sessions/codex-reader.js.map +1 -1
  702. package/dist/sessions/dag.d.ts +25 -4
  703. package/dist/sessions/dag.d.ts.map +1 -1
  704. package/dist/sessions/dag.js +37 -4
  705. package/dist/sessions/dag.js.map +1 -1
  706. package/dist/sessions/gemini-reader.d.ts +3 -1
  707. package/dist/sessions/gemini-reader.d.ts.map +1 -1
  708. package/dist/sessions/gemini-reader.js +17 -8
  709. package/dist/sessions/gemini-reader.js.map +1 -1
  710. package/dist/sessions/grok-reader.d.ts +1 -0
  711. package/dist/sessions/grok-reader.d.ts.map +1 -1
  712. package/dist/sessions/grok-reader.js +11 -5
  713. package/dist/sessions/grok-reader.js.map +1 -1
  714. package/dist/sessions/normalization.d.ts +3 -1
  715. package/dist/sessions/normalization.d.ts.map +1 -1
  716. package/dist/sessions/normalization.js +72 -16
  717. package/dist/sessions/normalization.js.map +1 -1
  718. package/dist/sessions/null-reader.d.ts +31 -0
  719. package/dist/sessions/null-reader.d.ts.map +1 -0
  720. package/dist/sessions/null-reader.js +30 -0
  721. package/dist/sessions/null-reader.js.map +1 -0
  722. package/dist/sessions/opencode-db-reader.d.ts +66 -0
  723. package/dist/sessions/opencode-db-reader.d.ts.map +1 -0
  724. package/dist/sessions/opencode-db-reader.js +333 -0
  725. package/dist/sessions/opencode-db-reader.js.map +1 -0
  726. package/dist/sessions/opencode-reader.d.ts +50 -0
  727. package/dist/sessions/opencode-reader.d.ts.map +1 -1
  728. package/dist/sessions/opencode-reader.js +375 -71
  729. package/dist/sessions/opencode-reader.js.map +1 -1
  730. package/dist/sessions/pagination.d.ts.map +1 -1
  731. package/dist/sessions/pagination.js +119 -3
  732. package/dist/sessions/pagination.js.map +1 -1
  733. package/dist/sessions/persisted-augments.d.ts +2 -1
  734. package/dist/sessions/persisted-augments.d.ts.map +1 -1
  735. package/dist/sessions/persisted-augments.js +2 -2
  736. package/dist/sessions/persisted-augments.js.map +1 -1
  737. package/dist/sessions/pi-fork.d.ts +12 -0
  738. package/dist/sessions/pi-fork.d.ts.map +1 -0
  739. package/dist/sessions/pi-fork.js +125 -0
  740. package/dist/sessions/pi-fork.js.map +1 -0
  741. package/dist/sessions/pi-reader.d.ts +81 -0
  742. package/dist/sessions/pi-reader.d.ts.map +1 -0
  743. package/dist/sessions/pi-reader.js +413 -0
  744. package/dist/sessions/pi-reader.js.map +1 -0
  745. package/dist/sessions/provider-resolution.d.ts +10 -3
  746. package/dist/sessions/provider-resolution.d.ts.map +1 -1
  747. package/dist/sessions/provider-resolution.js +62 -6
  748. package/dist/sessions/provider-resolution.js.map +1 -1
  749. package/dist/sessions/reader.d.ts +17 -24
  750. package/dist/sessions/reader.d.ts.map +1 -1
  751. package/dist/sessions/reader.js +86 -157
  752. package/dist/sessions/reader.js.map +1 -1
  753. package/dist/sessions/recap-overlays.d.ts +38 -0
  754. package/dist/sessions/recap-overlays.d.ts.map +1 -0
  755. package/dist/sessions/recap-overlays.js +176 -0
  756. package/dist/sessions/recap-overlays.js.map +1 -0
  757. package/dist/sessions/summary-parser-worker-client.d.ts +80 -0
  758. package/dist/sessions/summary-parser-worker-client.d.ts.map +1 -0
  759. package/dist/sessions/summary-parser-worker-client.js +539 -0
  760. package/dist/sessions/summary-parser-worker-client.js.map +1 -0
  761. package/dist/sessions/summary-parser-worker-entry.d.ts +2 -0
  762. package/dist/sessions/summary-parser-worker-entry.d.ts.map +1 -0
  763. package/dist/sessions/summary-parser-worker-entry.js +29 -0
  764. package/dist/sessions/summary-parser-worker-entry.js.map +1 -0
  765. package/dist/sessions/summary-parser-worker-protocol.d.ts +105 -0
  766. package/dist/sessions/summary-parser-worker-protocol.d.ts.map +1 -0
  767. package/dist/sessions/summary-parser-worker-protocol.js +35 -0
  768. package/dist/sessions/summary-parser-worker-protocol.js.map +1 -0
  769. package/dist/sessions/summary-parser-worker-runner.d.ts +3 -0
  770. package/dist/sessions/summary-parser-worker-runner.d.ts.map +1 -0
  771. package/dist/sessions/summary-parser-worker-runner.js +158 -0
  772. package/dist/sessions/summary-parser-worker-runner.js.map +1 -0
  773. package/dist/sessions/types.d.ts +30 -1
  774. package/dist/sessions/types.d.ts.map +1 -1
  775. package/dist/startupEnv.d.ts +2 -0
  776. package/dist/startupEnv.d.ts.map +1 -0
  777. package/dist/startupEnv.js +97 -0
  778. package/dist/startupEnv.js.map +1 -0
  779. package/dist/subscriptions.d.ts.map +1 -1
  780. package/dist/subscriptions.js +28 -18
  781. package/dist/subscriptions.js.map +1 -1
  782. package/dist/supervisor/ExternalSessionTracker.d.ts +5 -1
  783. package/dist/supervisor/ExternalSessionTracker.d.ts.map +1 -1
  784. package/dist/supervisor/ExternalSessionTracker.js +98 -6
  785. package/dist/supervisor/ExternalSessionTracker.js.map +1 -1
  786. package/dist/supervisor/Process.d.ts +252 -32
  787. package/dist/supervisor/Process.d.ts.map +1 -1
  788. package/dist/supervisor/Process.js +1233 -219
  789. package/dist/supervisor/Process.js.map +1 -1
  790. package/dist/supervisor/Supervisor.d.ts +201 -5
  791. package/dist/supervisor/Supervisor.d.ts.map +1 -1
  792. package/dist/supervisor/Supervisor.js +1074 -55
  793. package/dist/supervisor/Supervisor.js.map +1 -1
  794. package/dist/supervisor/WorkerQueue.d.ts +3 -1
  795. package/dist/supervisor/WorkerQueue.d.ts.map +1 -1
  796. package/dist/supervisor/WorkerQueue.js +1 -0
  797. package/dist/supervisor/WorkerQueue.js.map +1 -1
  798. package/dist/supervisor/composeTimeAnchor.d.ts +36 -0
  799. package/dist/supervisor/composeTimeAnchor.d.ts.map +1 -0
  800. package/dist/supervisor/composeTimeAnchor.js +51 -0
  801. package/dist/supervisor/composeTimeAnchor.js.map +1 -0
  802. package/dist/supervisor/deferredDeliverySettings.d.ts +23 -0
  803. package/dist/supervisor/deferredDeliverySettings.d.ts.map +1 -0
  804. package/dist/supervisor/deferredDeliverySettings.js +40 -0
  805. package/dist/supervisor/deferredDeliverySettings.js.map +1 -0
  806. package/dist/supervisor/liveness.d.ts +5 -2
  807. package/dist/supervisor/liveness.d.ts.map +1 -1
  808. package/dist/supervisor/liveness.js +40 -2
  809. package/dist/supervisor/liveness.js.map +1 -1
  810. package/dist/supervisor/types.d.ts +56 -5
  811. package/dist/supervisor/types.d.ts.map +1 -1
  812. package/dist/supervisor/types.js +0 -2
  813. package/dist/supervisor/types.js.map +1 -1
  814. package/dist/uploads/AttachmentStagingService.d.ts +94 -0
  815. package/dist/uploads/AttachmentStagingService.d.ts.map +1 -0
  816. package/dist/uploads/AttachmentStagingService.js +673 -0
  817. package/dist/uploads/AttachmentStagingService.js.map +1 -0
  818. package/dist/uploads/index.d.ts +2 -0
  819. package/dist/uploads/index.d.ts.map +1 -1
  820. package/dist/uploads/index.js +1 -0
  821. package/dist/uploads/index.js.map +1 -1
  822. package/dist/uploads/manager.d.ts +1 -0
  823. package/dist/uploads/manager.d.ts.map +1 -1
  824. package/dist/uploads/manager.js +72 -12
  825. package/dist/uploads/manager.js.map +1 -1
  826. package/dist/utils/codexRolloutFiles.d.ts +16 -0
  827. package/dist/utils/codexRolloutFiles.d.ts.map +1 -0
  828. package/dist/utils/codexRolloutFiles.js +45 -0
  829. package/dist/utils/codexRolloutFiles.js.map +1 -0
  830. package/dist/utils/jsonl.d.ts +8 -0
  831. package/dist/utils/jsonl.d.ts.map +1 -1
  832. package/dist/utils/jsonl.js +158 -5
  833. package/dist/utils/jsonl.js.map +1 -1
  834. package/dist/utils/publicShareViewerUrl.d.ts.map +1 -1
  835. package/dist/utils/publicShareViewerUrl.js +2 -15
  836. package/dist/utils/publicShareViewerUrl.js.map +1 -1
  837. package/dist/watcher/EventBus.d.ts +42 -4
  838. package/dist/watcher/EventBus.d.ts.map +1 -1
  839. package/dist/watcher/EventBus.js.map +1 -1
  840. package/dist/watcher/FileWatcher.d.ts +47 -0
  841. package/dist/watcher/FileWatcher.d.ts.map +1 -1
  842. package/dist/watcher/FileWatcher.js +185 -14
  843. package/dist/watcher/FileWatcher.js.map +1 -1
  844. package/dist/watcher/index.d.ts +2 -2
  845. package/dist/watcher/index.d.ts.map +1 -1
  846. package/dist/watcher/index.js.map +1 -1
  847. package/dist/yaModuleEnv.d.ts +6 -6
  848. package/dist/yaModuleEnv.d.ts.map +1 -1
  849. package/dist/yaModuleEnv.js +12 -12
  850. package/dist/yaModuleEnv.js.map +1 -1
  851. package/package.json +5 -6
  852. package/client-dist/assets/de-BuEb60Yc.js +0 -6
  853. package/client-dist/assets/es-CRlmPKnE.js +0 -6
  854. package/client-dist/assets/fr-Cglgjc2X.js +0 -6
  855. package/client-dist/assets/index-BNj7ibmq.js +0 -524
  856. package/client-dist/assets/index-CAmsUazi.css +0 -1
  857. package/client-dist/assets/ja-DMb9mFPv.js +0 -6
  858. package/client-dist/assets/zh-CN-D1tbfamz.js +0 -6
@@ -1,8 +1,13 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { truncateSessionTitle, } from "../../bundled/@yep-anywhere/shared/dist/index.js";
2
+ import { DEFAULT_PROMPT_CACHE_KEEPALIVE_INACTIVITY_MINUTES, truncateSessionTitle, } from "../../bundled/@yep-anywhere/shared/dist/index.js";
3
3
  import { getLogger } from "../logging/logger.js";
4
+ import { getProjectName } from "../projects/paths.js";
4
5
  import { getProvider } from "../sdk/providers/index.js";
5
- import { Process } from "./Process.js";
6
+ import { CacheMissBillingMonitor } from "../services/CacheMissBillingMonitor.js";
7
+ import { formatAgentRecapExcerpt } from "../sessions/agent-excerpt.js";
8
+ import { isAwaySummaryMessage, latestRecapMessage, messageTimestampMs, toDurableRecapMessage, } from "../sessions/recap-overlays.js";
9
+ import { normalizeSlashCommandName } from "../sdk/slashCommandEmulation.js";
10
+ import { NATIVE_RECAP_FALLBACK_GRACE_MS, Process, } from "./Process.js";
6
11
  import { WorkerQueue, isQueueFullError, } from "./WorkerQueue.js";
7
12
  import { DEFAULT_IDLE_PREEMPT_THRESHOLD_MS, encodeProjectId, } from "./types.js";
8
13
  /** Maximum number of terminated processes to retain */
@@ -20,6 +25,32 @@ const LIVENESS_PROBE_CHECK_INTERVAL_MS = 30 * 1000;
20
25
  const LIVENESS_PROBE_REFRESH_MS = 60 * 1000;
21
26
  const DEFAULT_HEARTBEAT_TURN_TEXT = "continue";
22
27
  const DEFAULT_HEARTBEAT_TURNS_AFTER_MINUTES = 5;
28
+ function thinkingConfigsEqual(current, next) {
29
+ if (current?.type !== next?.type)
30
+ return false;
31
+ if (!current || !next)
32
+ return true;
33
+ if (current.type === "adaptive" && next.type === "adaptive") {
34
+ return current.display === next.display;
35
+ }
36
+ if (current.type === "enabled" && next.type === "enabled") {
37
+ return (current.budgetTokens === next.budgetTokens &&
38
+ current.display === next.display);
39
+ }
40
+ return true;
41
+ }
42
+ function isDynamicThinkingModeConfig(thinking) {
43
+ return (!thinking ||
44
+ thinking.type === "disabled" ||
45
+ (thinking.type === "adaptive" && thinking.display === undefined));
46
+ }
47
+ function canApplyThinkingConfigDynamically(current, next) {
48
+ if (!isDynamicThinkingModeConfig(current))
49
+ return false;
50
+ if (!isDynamicThinkingModeConfig(next))
51
+ return false;
52
+ return current?.type !== next?.type;
53
+ }
23
54
  const DEFAULT_INTERRUPT_TIMEOUT_MS = 2000;
24
55
  const FORCED_HEARTBEAT_INTERRUPT_PREAMBLE = "interrupted for heartbeat; resume interrupted command after responding:";
25
56
  const HEARTBEAT_RESET_PROBE_STATUSES = new Set(["active", "idle", "waiting-input"]);
@@ -28,6 +59,73 @@ const ACTIVE_HEARTBEAT_DOUBT_STATUSES = new Set([
28
59
  "recently-active-unverified",
29
60
  "long-silent-unverified",
30
61
  ]);
62
+ const RESUME_COMPACT_WAIT_MS = 3 * 60 * 1000;
63
+ export class ResumeCompactionError extends Error {
64
+ sessionId;
65
+ provider;
66
+ attempt;
67
+ recovery = "full-resume";
68
+ constructor(params) {
69
+ super(describeResumeCompactionAttempt(params.attempt));
70
+ this.name = "ResumeCompactionError";
71
+ this.sessionId = params.sessionId;
72
+ this.provider = params.provider;
73
+ this.attempt = params.attempt;
74
+ }
75
+ }
76
+ function describeResumeCompactionAttempt(attempt) {
77
+ switch (attempt.status) {
78
+ case "completed":
79
+ return `Compact-first resume completed with /${attempt.command}`;
80
+ case "timed-out":
81
+ return `Compact-first resume timed out after ${attempt.timeoutMs}ms waiting for /${attempt.command}`;
82
+ case "failed":
83
+ return attempt.command
84
+ ? `Compact-first resume failed after /${attempt.command}: ${attempt.reason}`
85
+ : `Compact-first resume failed: ${attempt.reason}`;
86
+ case "unavailable":
87
+ return `Compact-first resume unavailable: ${attempt.reason}`;
88
+ case "skipped":
89
+ return `Compact-first resume skipped: ${attempt.reason}`;
90
+ }
91
+ }
92
+ function isCompactBoundaryMessage(message) {
93
+ return message.type === "system" && message.subtype === "compact_boundary";
94
+ }
95
+ function compactFailureReason(message) {
96
+ if (message.type !== "system" ||
97
+ message.subtype !== "status" ||
98
+ message.compact_result !== "failed") {
99
+ return null;
100
+ }
101
+ return typeof message.compact_error === "string" && message.compact_error
102
+ ? message.compact_error
103
+ : "provider reported compaction failure";
104
+ }
105
+ function isCompactSuccessStatus(message) {
106
+ return (message.type === "system" &&
107
+ message.subtype === "status" &&
108
+ message.compact_result === "success");
109
+ }
110
+ /**
111
+ * Pure gate for the per-model compact-early threshold (task 029): true when a
112
+ * valid percent (1–99) and a known context window put live usage at or over
113
+ * the token threshold (percent% × window). Anything unknown or out of range
114
+ * yields false — the trigger never fires on missing usage. Semantics are
115
+ * "current usage already crosses the threshold", not a prediction of the next
116
+ * turn's size.
117
+ */
118
+ export function crossesCompactThreshold(percent, contextWindow, inputTokens) {
119
+ if (typeof percent !== "number" || percent <= 0 || percent >= 100) {
120
+ return false;
121
+ }
122
+ if (typeof contextWindow !== "number" || contextWindow <= 0)
123
+ return false;
124
+ if (typeof inputTokens !== "number" || !Number.isFinite(inputTokens)) {
125
+ return false;
126
+ }
127
+ return inputTokens >= (percent / 100) * contextWindow;
128
+ }
31
129
  function getStaleInTurnThresholdMs(provider) {
32
130
  return provider === "codex" || provider === "codex-oss"
33
131
  ? CODEX_STALE_IN_TURN_THRESHOLD_MS
@@ -100,6 +198,7 @@ const INITIAL_RECONCILE_DELAYS_MS = [1000, 3000];
100
198
  export class Supervisor {
101
199
  processes = new Map();
102
200
  sessionToProcess = new Map(); // sessionId -> processId
201
+ sessionActivationInFlight = new Map();
103
202
  observedProcessIds = new Set();
104
203
  everOwnedSessions = new Set(); // Sessions we've ever owned (for orphan detection)
105
204
  terminatedProcesses = []; // Recently terminated processes
@@ -113,14 +212,30 @@ export class Supervisor {
113
212
  idlePreemptThresholdMs;
114
213
  workerQueue;
115
214
  onSessionExecutor;
215
+ onContextWindowObserved;
116
216
  onSessionSummary;
117
217
  staleCheckTimer;
118
218
  getHeartbeatTurnSettings;
119
219
  getHeartbeatTurnCandidates;
220
+ getPromptCacheKeepaliveSettings;
221
+ cacheMissBillingMonitor;
120
222
  heartbeatTurnInFlight = false;
121
223
  heartbeatTurnTimer;
122
224
  livenessProbeTimer;
225
+ /**
226
+ * One-shot patient-queue re-checks keyed by process id. Bounded: armed only
227
+ * while a process holds patient deferred entries; cleared on unregister.
228
+ */
229
+ patientCheckTimers = new Map();
123
230
  interruptTimeoutMs;
231
+ sessionMetadataService;
232
+ sessionQueuePersistenceService;
233
+ // In-flight forked recaps, keyed by process id. The AbortController cancels
234
+ // the generator-fork helper turn when the parent becomes active again, so a
235
+ // returning user's new turn is never shadowed by a stale recap. See
236
+ // topics/recaps.md.
237
+ forkedRecapInFlight = new Map();
238
+ pendingForkedRecapRequests = new Map();
124
239
  constructor(options) {
125
240
  this.provider = options.provider ?? null;
126
241
  this.sdk = options.sdk ?? null;
@@ -136,11 +251,22 @@ export class Supervisor {
136
251
  maxQueueSize: options.maxQueueSize,
137
252
  });
138
253
  this.onSessionExecutor = options.onSessionExecutor;
254
+ this.onContextWindowObserved = options.onContextWindowObserved;
139
255
  this.onSessionSummary = options.onSessionSummary;
140
256
  this.getHeartbeatTurnSettings = options.getHeartbeatTurnSettings;
141
257
  this.getHeartbeatTurnCandidates = options.getHeartbeatTurnCandidates;
258
+ this.getPromptCacheKeepaliveSettings =
259
+ options.getPromptCacheKeepaliveSettings;
260
+ this.cacheMissBillingMonitor = new CacheMissBillingMonitor({
261
+ eventBus: options.eventBus,
262
+ sessionMetadataService: options.sessionMetadataService,
263
+ getSettings: options.getCacheMissBillingSettings,
264
+ });
142
265
  this.interruptTimeoutMs =
143
266
  options.interruptTimeoutMs ?? DEFAULT_INTERRUPT_TIMEOUT_MS;
267
+ this.sessionMetadataService = options.sessionMetadataService;
268
+ this.sessionQueuePersistenceService =
269
+ options.sessionQueuePersistenceService;
144
270
  this.staleCheckTimer = setInterval(() => this.terminateStaleProcesses(), STALE_CHECK_INTERVAL_MS);
145
271
  this.staleCheckTimer.unref(); // Don't keep process alive for cleanup
146
272
  this.heartbeatTurnTimer = setInterval(() => {
@@ -176,8 +302,52 @@ export class Supervisor {
176
302
  }
177
303
  return "off";
178
304
  }
179
- async startSession(projectPath, message, permissionMode, modelSettings) {
180
- const projectId = encodeProjectId(projectPath);
305
+ async waitForSessionActivation(sessionId) {
306
+ const activation = this.sessionActivationInFlight.get(sessionId);
307
+ if (!activation) {
308
+ return false;
309
+ }
310
+ try {
311
+ await activation;
312
+ }
313
+ catch {
314
+ // The caller will retry the ordinary resume path, which can surface the
315
+ // fresh failure or recover if the transient activation failed.
316
+ }
317
+ return true;
318
+ }
319
+ async startSessionActivation(sessionId, activate) {
320
+ const activation = Promise.resolve().then(activate);
321
+ this.sessionActivationInFlight.set(sessionId, activation);
322
+ try {
323
+ return (await activation);
324
+ }
325
+ finally {
326
+ if (this.sessionActivationInFlight.get(sessionId) === activation) {
327
+ this.sessionActivationInFlight.delete(sessionId);
328
+ }
329
+ }
330
+ }
331
+ registerPromptCacheKeepaliveViewer(process) {
332
+ if (!process.supportsPromptCacheKeepalive()) {
333
+ return () => { };
334
+ }
335
+ return process.registerPromptCacheKeepaliveLease({
336
+ getInactivityMs: () => {
337
+ const setting = this.getPromptCacheKeepaliveSettings?.(process.provider);
338
+ if (!setting?.enabled) {
339
+ return null;
340
+ }
341
+ const inactivityMinutes = Number.isFinite(setting.inactivityMinutes) &&
342
+ setting.inactivityMinutes > 0
343
+ ? setting.inactivityMinutes
344
+ : DEFAULT_PROMPT_CACHE_KEEPALIVE_INACTIVITY_MINUTES;
345
+ return inactivityMinutes * 60_000;
346
+ },
347
+ });
348
+ }
349
+ async startSession(projectPath, message, permissionMode, modelSettings, launchOptions) {
350
+ const projectId = launchOptions?.projectId ?? encodeProjectId(projectPath);
181
351
  // Check if at capacity
182
352
  if (this.isAtCapacity()) {
183
353
  // Try to preempt an idle worker
@@ -192,6 +362,7 @@ export class Supervisor {
192
362
  type: "new-session",
193
363
  projectPath,
194
364
  projectId,
365
+ workstreamId: launchOptions?.workstreamId,
195
366
  message,
196
367
  permissionMode,
197
368
  modelSettings,
@@ -223,8 +394,8 @@ export class Supervisor {
223
394
  * Used for two-phase flow: create session first, upload files, then send message.
224
395
  * The agent will wait for a message to be pushed to the queue.
225
396
  */
226
- async createSession(projectPath, permissionMode, modelSettings) {
227
- const projectId = encodeProjectId(projectPath);
397
+ async createSession(projectPath, permissionMode, modelSettings, launchOptions) {
398
+ const projectId = launchOptions?.projectId ?? encodeProjectId(projectPath);
228
399
  // Check if at capacity
229
400
  if (this.isAtCapacity()) {
230
401
  // Try to preempt an idle worker
@@ -239,6 +410,7 @@ export class Supervisor {
239
410
  type: "new-session",
240
411
  projectPath,
241
412
  projectId,
413
+ workstreamId: launchOptions?.workstreamId,
242
414
  message: { text: "" }, // Placeholder, will be replaced when first message sent
243
415
  permissionMode,
244
416
  modelSettings,
@@ -265,6 +437,60 @@ export class Supervisor {
265
437
  // Fall back to legacy mock SDK - not supported for create-only
266
438
  throw new Error("createSession requires provider or real SDK - legacy mock SDK not supported");
267
439
  }
440
+ /**
441
+ * Reactivate an existing session: spawn a live harness process bound to the
442
+ * session id WITHOUT delivering a user turn. The process resumes the session
443
+ * and idles on the queue (the same state it occupies after a completed turn),
444
+ * so the client can read live process state (model options, config) before
445
+ * any message is sent. Idempotent: returns the existing live process if the
446
+ * session is already owned.
447
+ *
448
+ * Provider-agnostic: rides the existing message-less resume path
449
+ * (`createProviderSession`/`createRealSession` with `resumeSessionId`), so
450
+ * Claude and Codex reactivate with no synthetic turn.
451
+ */
452
+ async reactivateSession(projectPath, resumeSessionId, permissionMode, modelSettings, options) {
453
+ const existing = this.getProcessForSession(resumeSessionId);
454
+ if (existing) {
455
+ if (!existing.isTerminated) {
456
+ return existing;
457
+ }
458
+ this.unregisterProcess(existing);
459
+ }
460
+ const activeActivation = this.sessionActivationInFlight.get(resumeSessionId);
461
+ if (activeActivation) {
462
+ return activeActivation;
463
+ }
464
+ return this.startSessionActivation(resumeSessionId, async () => {
465
+ const activated = this.getProcessForSession(resumeSessionId);
466
+ if (activated) {
467
+ if (!activated.isTerminated) {
468
+ return activated;
469
+ }
470
+ this.unregisterProcess(activated);
471
+ }
472
+ if (this.isAtCapacity()) {
473
+ const preemptable = options?.preempt === false ? undefined : this.findPreemptableWorker();
474
+ if (preemptable) {
475
+ await this.preemptWorker(preemptable);
476
+ }
477
+ else {
478
+ // A background away-recap passes preempt:false: it should never evict
479
+ // a live worker just to revive a different session for a recap.
480
+ throw new Error("Cannot reactivate: server is at worker capacity and no idle process can be preempted");
481
+ }
482
+ }
483
+ const projectId = encodeProjectId(projectPath);
484
+ const provider = this.resolveProvider(modelSettings);
485
+ if (provider) {
486
+ return this.createProviderSession(projectPath, projectId, permissionMode, modelSettings, provider, resumeSessionId);
487
+ }
488
+ if (this.realSdk) {
489
+ return this.createRealSession(projectPath, projectId, permissionMode, modelSettings, resumeSessionId);
490
+ }
491
+ throw new Error("reactivateSession requires provider or real SDK - legacy mock SDK not supported");
492
+ });
493
+ }
268
494
  /**
269
495
  * Create a session using the real SDK without an initial message.
270
496
  * The session is created and waits for a message to be queued.
@@ -288,6 +514,7 @@ export class Supervisor {
288
514
  clientName: modelSettings?.clientName,
289
515
  globalInstructions: modelSettings?.globalInstructions,
290
516
  promptSuggestions: promptSuggestionMode === "native",
517
+ onProviderRetentionChange: () => this.handleProviderRetentionChanged(processHolder),
291
518
  onToolApproval: async (toolName, input, opts) => {
292
519
  if (!processHolder.process) {
293
520
  return { behavior: "deny", message: "Process not ready" };
@@ -295,7 +522,7 @@ export class Supervisor {
295
522
  return processHolder.process.handleToolApproval(toolName, input, opts);
296
523
  },
297
524
  });
298
- const { iterator, queue, abort, isProcessAlive, probeLiveness, getProviderActivity, setMaxThinkingTokens, interrupt, supportedModels, supportedCommands, setModel, } = result;
525
+ const { iterator, queue, abort, isProcessAlive, probeLiveness, getProviderActivity, getProviderRetention, setMaxThinkingTokens, interrupt, supportedModels, supportedCommands, setModel, publishAgentctlSessionId, } = result;
299
526
  const tempSessionId = resumeSessionId ?? randomUUID();
300
527
  const options = {
301
528
  projectPath,
@@ -303,11 +530,13 @@ export class Supervisor {
303
530
  sessionId: tempSessionId,
304
531
  idleTimeoutMs: this.idleTimeoutMs,
305
532
  queue,
533
+ sessionQueuePersistenceService: this.sessionQueuePersistenceService,
306
534
  abortFn: abort,
307
535
  isProcessAlive,
308
536
  shouldRetainIdleProcess: (sessionId) => this.shouldRetainIdleProcess(sessionId),
309
537
  probeLivenessFn: probeLiveness,
310
538
  getProviderActivityFn: getProviderActivity,
539
+ getProviderRetentionFn: getProviderRetention,
311
540
  pid: () => {
312
541
  const p = result.pid;
313
542
  return typeof p === "function" ? p() : p;
@@ -317,6 +546,7 @@ export class Supervisor {
317
546
  supportedModelsFn: supportedModels,
318
547
  supportedCommandsFn: supportedCommands,
319
548
  setModelFn: setModel,
549
+ publishAgentctlSessionIdFn: publishAgentctlSessionId,
320
550
  permissionMode: effectiveMode,
321
551
  provider: "claude", // Real SDK is always Claude
322
552
  model: modelSettings?.model,
@@ -326,6 +556,7 @@ export class Supervisor {
326
556
  executor: modelSettings?.executor,
327
557
  permissions: modelSettings?.permissions,
328
558
  recapMode: modelSettings?.recapMode,
559
+ recapAfterSeconds: modelSettings?.recapAfterSeconds,
329
560
  promptSuggestionMode,
330
561
  helperSideModel: modelSettings?.helperSideModel,
331
562
  };
@@ -344,6 +575,254 @@ export class Supervisor {
344
575
  await process.primeSupportedCommandsForMessage(message);
345
576
  return process.queueMessage(message, options);
346
577
  }
578
+ watchResumeCompaction(process, command, timeoutMs = RESUME_COMPACT_WAIT_MS) {
579
+ let finished = false;
580
+ let timeout;
581
+ let unsubscribe;
582
+ const finish = (attempt) => {
583
+ if (finished) {
584
+ return;
585
+ }
586
+ finished = true;
587
+ if (timeout) {
588
+ clearTimeout(timeout);
589
+ }
590
+ unsubscribe?.();
591
+ resolve(attempt);
592
+ };
593
+ let resolve;
594
+ const promise = new Promise((innerResolve) => {
595
+ resolve = innerResolve;
596
+ });
597
+ timeout = setTimeout(() => finish({ status: "timed-out", command, timeoutMs }), timeoutMs);
598
+ timeout.unref?.();
599
+ unsubscribe = process.subscribe((event) => {
600
+ if (event.type === "message") {
601
+ const failedReason = compactFailureReason(event.message);
602
+ if (failedReason) {
603
+ finish({ status: "failed", command, reason: failedReason });
604
+ return;
605
+ }
606
+ if (isCompactBoundaryMessage(event.message) ||
607
+ isCompactSuccessStatus(event.message)) {
608
+ finish({ status: "completed", command });
609
+ }
610
+ return;
611
+ }
612
+ if (event.type === "error") {
613
+ finish({
614
+ status: "failed",
615
+ command,
616
+ reason: event.error.message,
617
+ });
618
+ return;
619
+ }
620
+ if (event.type === "terminated") {
621
+ finish({
622
+ status: "failed",
623
+ command,
624
+ reason: event.reason,
625
+ });
626
+ }
627
+ });
628
+ return {
629
+ promise,
630
+ cancel: () => finish({
631
+ status: "failed",
632
+ command,
633
+ reason: "compact command was not queued",
634
+ }),
635
+ };
636
+ }
637
+ async findResumeCompactCommand(process) {
638
+ if (!process.supportsDynamicCommands) {
639
+ return {
640
+ ok: false,
641
+ attempt: {
642
+ status: "unavailable",
643
+ reason: "provider process does not advertise slash commands",
644
+ },
645
+ };
646
+ }
647
+ let commands;
648
+ try {
649
+ commands = await process.supportedCommands();
650
+ }
651
+ catch (error) {
652
+ return {
653
+ ok: false,
654
+ attempt: {
655
+ status: "failed",
656
+ reason: error instanceof Error ? error.message : String(error),
657
+ },
658
+ };
659
+ }
660
+ const command = commands
661
+ ?.map((candidate) => normalizeSlashCommandName(candidate.name))
662
+ .find((name) => name === "compact" || name === "compress");
663
+ if (!command) {
664
+ return {
665
+ ok: false,
666
+ attempt: {
667
+ status: "unavailable",
668
+ reason: "no compact/compress slash command advertised",
669
+ },
670
+ };
671
+ }
672
+ return { ok: true, command };
673
+ }
674
+ async tryResumeCompaction(process, options) {
675
+ if (process.provider !== "claude" && process.provider !== "claude-ollama") {
676
+ return {
677
+ status: "unavailable",
678
+ reason: `${process.provider} does not support compact-first resume`,
679
+ };
680
+ }
681
+ if (!options?.allowNonIdleStart && process.state.type !== "idle") {
682
+ return {
683
+ status: "skipped",
684
+ reason: `process was ${process.state.type}`,
685
+ };
686
+ }
687
+ const command = await this.findResumeCompactCommand(process);
688
+ if (!command.ok) {
689
+ return command.attempt;
690
+ }
691
+ const watcher = this.watchResumeCompaction(process, command.command);
692
+ const queued = process.queueMessage(
693
+ // Hidden: native compaction shows no `/compact` user turn, so neither
694
+ // should YA-initiated compaction (resume-time or threshold-triggered).
695
+ { text: `/${command.command}`, metadata: { hidden: true } }, { allowSteer: false });
696
+ if (!queued.success) {
697
+ watcher.cancel();
698
+ return {
699
+ status: "failed",
700
+ command: command.command,
701
+ reason: queued.error ?? "compact command was not accepted",
702
+ };
703
+ }
704
+ return watcher.promise;
705
+ }
706
+ /**
707
+ * Threshold-triggered preemptive compaction (task 029). When the per-model
708
+ * compact-at-% is set and live context already sits at/over that fraction of
709
+ * the model's window, run a `/compact` before delivering the next turn — the
710
+ * same native compaction the harness would eventually auto-fire, just
711
+ * earlier. Conservative per task 002: claude only, idle process only, only
712
+ * when usage is known. Best-effort — the turn is delivered regardless of the
713
+ * compaction outcome, and there is no retry loop. Reuses
714
+ * `tryResumeCompaction`, so the boundary the client renders is the native
715
+ * `compact_boundary` and the `/compact` carries no visible user echo.
716
+ *
717
+ * No double compaction: live usage is re-read and re-tested immediately
718
+ * before executing (there is no deferral gap between decide and run), so a
719
+ * prior compaction — the harness's enforced one or a previous voluntary one —
720
+ * that dropped usage below the threshold makes the next evaluation a no-op.
721
+ * The voluntary threshold also sits well below the harness's enforced point,
722
+ * so in steady state the two never fire together.
723
+ */
724
+ async maybeCompactBeforeDelivery(process, sessionId, modelSettings) {
725
+ const percent = modelSettings?.compactAtContextPercent;
726
+ if (typeof percent !== "number" || percent <= 0 || percent >= 100)
727
+ return;
728
+ // Only an idle claude process can be safely compacted before delivery;
729
+ // tryResumeCompaction also self-guards, but skip the usage read otherwise.
730
+ if (process.state.type !== "idle")
731
+ return;
732
+ if (process.provider !== "claude" && process.provider !== "claude-ollama") {
733
+ return;
734
+ }
735
+ // Prefer the route-resolved window; process.contextWindow is often
736
+ // undefined and ignores always-1M for opus/sonnet.
737
+ const contextWindow = modelSettings?.compactAtContextWindow ?? process.contextWindow;
738
+ if (!contextWindow || contextWindow <= 0)
739
+ return;
740
+ let inputTokens;
741
+ try {
742
+ const summary = await this.onSessionSummary?.(sessionId, process.projectId);
743
+ inputTokens = summary?.contextUsage?.inputTokens;
744
+ }
745
+ catch {
746
+ // Usage unavailable → never block the turn.
747
+ return;
748
+ }
749
+ if (!crossesCompactThreshold(percent, contextWindow, inputTokens))
750
+ return;
751
+ try {
752
+ const attempt = await this.tryResumeCompaction(process);
753
+ if (attempt.status !== "completed") {
754
+ getLogger().info({
755
+ event: "threshold_compaction_skipped",
756
+ sessionId,
757
+ processId: process.id,
758
+ status: attempt.status,
759
+ percent,
760
+ inputTokens,
761
+ thresholdTokens: Math.round((percent / 100) * contextWindow),
762
+ }, "Threshold compaction did not complete; delivering turn as-is");
763
+ }
764
+ }
765
+ catch (error) {
766
+ getLogger().warn({
767
+ event: "threshold_compaction_failed",
768
+ sessionId,
769
+ processId: process.id,
770
+ error: error instanceof Error ? error.message : String(error),
771
+ }, "Threshold compaction errored; delivering turn as-is");
772
+ }
773
+ }
774
+ async queueAfterResumeCompaction(params) {
775
+ const attempt = await this.tryResumeCompaction(params.process, {
776
+ allowNonIdleStart: params.allowNonIdleStart,
777
+ });
778
+ if (attempt.status !== "completed") {
779
+ throw new ResumeCompactionError({
780
+ sessionId: params.sessionId,
781
+ provider: params.process.provider,
782
+ attempt,
783
+ });
784
+ }
785
+ const queued = await this.queueProcessMessage(params.process, params.message, {
786
+ allowSteer: false,
787
+ });
788
+ if (!queued.success) {
789
+ throw new Error(queued.error ?? "Failed to queue message after compact");
790
+ }
791
+ }
792
+ async startCompactFirstProviderResume(projectPath, projectId, message, resumeSessionId, permissionMode, modelSettings, provider) {
793
+ const process = await this.createProviderSession(projectPath, projectId, permissionMode, modelSettings, provider, resumeSessionId);
794
+ try {
795
+ await this.queueAfterResumeCompaction({
796
+ process,
797
+ sessionId: resumeSessionId,
798
+ message,
799
+ allowNonIdleStart: true,
800
+ });
801
+ return process;
802
+ }
803
+ catch (error) {
804
+ await process.abort();
805
+ this.unregisterProcess(process);
806
+ throw error;
807
+ }
808
+ }
809
+ async startCompactFirstRealResume(projectPath, projectId, message, resumeSessionId, permissionMode, modelSettings) {
810
+ const process = await this.createRealSession(projectPath, projectId, permissionMode, modelSettings, resumeSessionId);
811
+ try {
812
+ await this.queueAfterResumeCompaction({
813
+ process,
814
+ sessionId: resumeSessionId,
815
+ message,
816
+ allowNonIdleStart: true,
817
+ });
818
+ return process;
819
+ }
820
+ catch (error) {
821
+ await process.abort();
822
+ this.unregisterProcess(process);
823
+ throw error;
824
+ }
825
+ }
347
826
  /**
348
827
  * Start a session using the real SDK with full features.
349
828
  */
@@ -371,6 +850,7 @@ export class Supervisor {
371
850
  remoteEnv: modelSettings?.remoteEnv,
372
851
  globalInstructions: modelSettings?.globalInstructions,
373
852
  promptSuggestions: promptSuggestionMode === "native",
853
+ onProviderRetentionChange: () => this.handleProviderRetentionChanged(processHolder),
374
854
  onToolApproval: async (toolName, input, opts) => {
375
855
  // Delegate to the process's handleToolApproval
376
856
  if (!processHolder.process) {
@@ -379,18 +859,20 @@ export class Supervisor {
379
859
  return processHolder.process.handleToolApproval(toolName, input, opts);
380
860
  },
381
861
  });
382
- const { iterator, queue, abort, isProcessAlive, probeLiveness, getProviderActivity, setMaxThinkingTokens, interrupt, supportedModels, supportedCommands, setModel, } = result;
862
+ const { iterator, queue, abort, isProcessAlive, probeLiveness, getProviderActivity, getProviderRetention, setMaxThinkingTokens, interrupt, supportedModels, supportedCommands, setModel, publishAgentctlSessionId, } = result;
383
863
  const options = {
384
864
  projectPath,
385
865
  projectId,
386
866
  sessionId: tempSessionId,
387
867
  idleTimeoutMs: this.idleTimeoutMs,
388
868
  queue,
869
+ sessionQueuePersistenceService: this.sessionQueuePersistenceService,
389
870
  abortFn: abort,
390
871
  isProcessAlive,
391
872
  shouldRetainIdleProcess: (sessionId) => this.shouldRetainIdleProcess(sessionId),
392
873
  probeLivenessFn: probeLiveness,
393
874
  getProviderActivityFn: getProviderActivity,
875
+ getProviderRetentionFn: getProviderRetention,
394
876
  pid: () => {
395
877
  const p = result.pid;
396
878
  return typeof p === "function" ? p() : p;
@@ -400,6 +882,7 @@ export class Supervisor {
400
882
  supportedModelsFn: supportedModels,
401
883
  supportedCommandsFn: supportedCommands,
402
884
  setModelFn: setModel,
885
+ publishAgentctlSessionIdFn: publishAgentctlSessionId,
403
886
  permissionMode: effectiveMode,
404
887
  provider: "claude", // Real SDK is always Claude
405
888
  model: modelSettings?.model,
@@ -409,6 +892,7 @@ export class Supervisor {
409
892
  executor: modelSettings?.executor,
410
893
  permissions: modelSettings?.permissions,
411
894
  recapMode: modelSettings?.recapMode,
895
+ recapAfterSeconds: modelSettings?.recapAfterSeconds,
412
896
  promptSuggestionMode,
413
897
  helperSideModel: modelSettings?.helperSideModel,
414
898
  };
@@ -458,6 +942,7 @@ export class Supervisor {
458
942
  globalInstructions: modelSettings?.globalInstructions,
459
943
  promptSuggestions: promptSuggestionMode === "native",
460
944
  shouldEmitLiveDeltas: () => processHolder.process?.hasLiveDeltaSubscribers() ?? false,
945
+ onProviderRetentionChange: () => this.handleProviderRetentionChanged(processHolder),
461
946
  onToolApproval: async (toolName, input, opts) => {
462
947
  if (!processHolder.process) {
463
948
  return { behavior: "deny", message: "Process not ready" };
@@ -465,7 +950,7 @@ export class Supervisor {
465
950
  return processHolder.process.handleToolApproval(toolName, input, opts);
466
951
  },
467
952
  });
468
- const { iterator, queue, abort, isProcessAlive, probeLiveness, getProviderActivity, setMaxThinkingTokens, interrupt, steer, supportedModels, supportedCommands, setModel, } = result;
953
+ const { iterator, queue, abort, isProcessAlive, probeLiveness, getProviderActivity, getProviderRetention, setMaxThinkingTokens, interrupt, steer, supportedModels, supportedCommands, setModel, runProviderCommand, publishAgentctlSessionId, } = result;
469
954
  const tempSessionId = resumeSessionId ?? randomUUID();
470
955
  const options = {
471
956
  projectPath,
@@ -473,11 +958,14 @@ export class Supervisor {
473
958
  sessionId: tempSessionId,
474
959
  idleTimeoutMs: this.idleTimeoutMs,
475
960
  queue,
961
+ sessionQueuePersistenceService: this.sessionQueuePersistenceService,
476
962
  abortFn: abort,
477
963
  isProcessAlive,
478
964
  shouldRetainIdleProcess: (sessionId) => this.shouldRetainIdleProcess(sessionId),
479
965
  probeLivenessFn: probeLiveness,
480
966
  getProviderActivityFn: getProviderActivity,
967
+ getProviderRetentionFn: getProviderRetention,
968
+ refreshPromptCacheFn: result.refreshPromptCache,
481
969
  pid: () => {
482
970
  const p = result.pid;
483
971
  return typeof p === "function" ? p() : p;
@@ -488,6 +976,8 @@ export class Supervisor {
488
976
  supportedModelsFn: supportedModels,
489
977
  supportedCommandsFn: supportedCommands,
490
978
  setModelFn: setModel,
979
+ runProviderCommandFn: runProviderCommand,
980
+ publishAgentctlSessionIdFn: publishAgentctlSessionId,
491
981
  permissionMode: effectiveMode,
492
982
  provider: activeProvider.name,
493
983
  model: modelSettings?.model,
@@ -497,6 +987,7 @@ export class Supervisor {
497
987
  executor: modelSettings?.executor,
498
988
  permissions: modelSettings?.permissions,
499
989
  recapMode: modelSettings?.recapMode,
990
+ recapAfterSeconds: modelSettings?.recapAfterSeconds,
500
991
  promptSuggestionMode,
501
992
  helperSideModel: modelSettings?.helperSideModel,
502
993
  };
@@ -527,6 +1018,9 @@ export class Supervisor {
527
1018
  const result = await activeProvider.startSession({
528
1019
  cwd: projectPath,
529
1020
  resumeSessionId,
1021
+ resumeSessionAt: resumeSessionId
1022
+ ? modelSettings?.resumeSessionAt
1023
+ : undefined,
530
1024
  permissionMode: effectiveMode,
531
1025
  model: modelSettings?.model,
532
1026
  serviceTier: modelSettings?.serviceTier,
@@ -537,6 +1031,7 @@ export class Supervisor {
537
1031
  globalInstructions: modelSettings?.globalInstructions,
538
1032
  promptSuggestions: promptSuggestionMode === "native",
539
1033
  shouldEmitLiveDeltas: () => processHolder.process?.hasLiveDeltaSubscribers() ?? false,
1034
+ onProviderRetentionChange: () => this.handleProviderRetentionChanged(processHolder),
540
1035
  onToolApproval: async (toolName, input, opts) => {
541
1036
  if (!processHolder.process) {
542
1037
  return { behavior: "deny", message: "Process not ready" };
@@ -544,7 +1039,7 @@ export class Supervisor {
544
1039
  return processHolder.process.handleToolApproval(toolName, input, opts);
545
1040
  },
546
1041
  });
547
- const { iterator, queue, abort, isProcessAlive, probeLiveness, getProviderActivity, setMaxThinkingTokens, interrupt, steer, supportedModels, supportedCommands, setModel, } = result;
1042
+ const { iterator, queue, abort, isProcessAlive, probeLiveness, getProviderActivity, getProviderRetention, setMaxThinkingTokens, interrupt, steer, supportedModels, supportedCommands, setModel, runProviderCommand, publishAgentctlSessionId, } = result;
548
1043
  const tempSessionId = resumeSessionId ?? randomUUID();
549
1044
  const options = {
550
1045
  projectPath,
@@ -552,11 +1047,14 @@ export class Supervisor {
552
1047
  sessionId: tempSessionId,
553
1048
  idleTimeoutMs: this.idleTimeoutMs,
554
1049
  queue,
1050
+ sessionQueuePersistenceService: this.sessionQueuePersistenceService,
555
1051
  abortFn: abort,
556
1052
  isProcessAlive,
557
1053
  shouldRetainIdleProcess: (sessionId) => this.shouldRetainIdleProcess(sessionId),
558
1054
  probeLivenessFn: probeLiveness,
559
1055
  getProviderActivityFn: getProviderActivity,
1056
+ getProviderRetentionFn: getProviderRetention,
1057
+ refreshPromptCacheFn: result.refreshPromptCache,
560
1058
  pid: () => {
561
1059
  const p = result.pid;
562
1060
  return typeof p === "function" ? p() : p;
@@ -567,6 +1065,8 @@ export class Supervisor {
567
1065
  supportedModelsFn: supportedModels,
568
1066
  supportedCommandsFn: supportedCommands,
569
1067
  setModelFn: setModel,
1068
+ runProviderCommandFn: runProviderCommand,
1069
+ publishAgentctlSessionIdFn: publishAgentctlSessionId,
570
1070
  permissionMode: effectiveMode,
571
1071
  provider: activeProvider.name,
572
1072
  model: modelSettings?.model,
@@ -576,6 +1076,7 @@ export class Supervisor {
576
1076
  executor: modelSettings?.executor,
577
1077
  permissions: modelSettings?.permissions,
578
1078
  recapMode: modelSettings?.recapMode,
1079
+ recapAfterSeconds: modelSettings?.recapAfterSeconds,
579
1080
  promptSuggestionMode,
580
1081
  helperSideModel: modelSettings?.helperSideModel,
581
1082
  };
@@ -626,6 +1127,7 @@ export class Supervisor {
626
1127
  return process;
627
1128
  }
628
1129
  async resumeSession(sessionId, projectPath, message, permissionMode, modelSettings) {
1130
+ await this.waitForSessionActivation(sessionId);
629
1131
  // Check if already have a process for this session
630
1132
  const existingProcessId = this.sessionToProcess.get(sessionId);
631
1133
  if (existingProcessId) {
@@ -636,13 +1138,14 @@ export class Supervisor {
636
1138
  this.unregisterProcess(existingProcess);
637
1139
  }
638
1140
  else {
1141
+ let restartExistingProcess = false;
639
1142
  // Check if thinking/effort settings changed
640
- const thinkingChanged = existingProcess.thinking?.type !==
641
- (modelSettings?.thinking?.type ?? undefined);
1143
+ const thinkingChanged = !thinkingConfigsEqual(existingProcess.thinking, modelSettings?.thinking);
642
1144
  const effortChanged = existingProcess.effort !== modelSettings?.effort;
643
1145
  if (thinkingChanged || effortChanged) {
644
1146
  if (thinkingChanged &&
645
1147
  !effortChanged &&
1148
+ canApplyThinkingConfigDynamically(existingProcess.thinking, modelSettings?.thinking) &&
646
1149
  existingProcess.supportsThinkingModeChange) {
647
1150
  // Toggle adaptive/disabled dynamically via deprecated API
648
1151
  const tokens = modelSettings?.thinking?.type === "disabled" ? 0 : 1;
@@ -667,21 +1170,38 @@ export class Supervisor {
667
1170
  sessionId,
668
1171
  processId: existingProcess.id,
669
1172
  oldThinking: existingProcess.thinking?.type,
1173
+ oldThinkingDisplay: existingProcess.thinking?.type === "adaptive" ||
1174
+ existingProcess.thinking?.type === "enabled"
1175
+ ? existingProcess.thinking.display
1176
+ : undefined,
670
1177
  oldEffort: existingProcess.effort,
671
1178
  newThinking: modelSettings?.thinking?.type,
1179
+ newThinkingDisplay: modelSettings?.thinking?.type === "adaptive" ||
1180
+ modelSettings?.thinking?.type === "enabled"
1181
+ ? modelSettings.thinking.display
1182
+ : undefined,
672
1183
  newEffort: modelSettings?.effort,
673
1184
  }, "Thinking/effort changed, restarting process");
674
1185
  await existingProcess.abort();
675
1186
  this.unregisterProcess(existingProcess);
1187
+ restartExistingProcess = true;
676
1188
  // Fall through to start a new session with the updated settings
677
1189
  }
678
1190
  }
679
1191
  // Update permission mode if specified
680
- if (permissionMode) {
1192
+ if (!restartExistingProcess && permissionMode) {
681
1193
  existingProcess.setPermissionMode(permissionMode);
682
1194
  }
683
1195
  // Queue message to existing process (if we didn't fall through to restart)
684
- if (!existingProcess.isTerminated) {
1196
+ if (!restartExistingProcess && !existingProcess.isTerminated) {
1197
+ if (modelSettings?.resumeMode === "compact-first") {
1198
+ await this.queueAfterResumeCompaction({
1199
+ process: existingProcess,
1200
+ sessionId,
1201
+ message,
1202
+ });
1203
+ return existingProcess;
1204
+ }
685
1205
  const result = await this.queueProcessMessage(existingProcess, message);
686
1206
  if (result.success) {
687
1207
  return existingProcess;
@@ -704,46 +1224,322 @@ export class Supervisor {
704
1224
  };
705
1225
  }
706
1226
  const projectId = encodeProjectId(projectPath);
707
- // Check if at capacity
708
- if (this.isAtCapacity()) {
709
- // Try to preempt an idle worker
710
- const preemptable = this.findPreemptableWorker();
711
- if (preemptable) {
712
- await this.preemptWorker(preemptable);
713
- // Fall through to start session normally
1227
+ if (this.isAtCapacity() && !this.findPreemptableWorker()) {
1228
+ const result = this.workerQueue.enqueue({
1229
+ type: "resume-session",
1230
+ projectPath,
1231
+ projectId,
1232
+ sessionId,
1233
+ message,
1234
+ permissionMode,
1235
+ modelSettings,
1236
+ });
1237
+ if (isQueueFullError(result)) {
1238
+ return result;
714
1239
  }
715
- else {
716
- // Queue the request
717
- const result = this.workerQueue.enqueue({
718
- type: "resume-session",
719
- projectPath,
720
- projectId,
1240
+ return {
1241
+ queued: true,
1242
+ queueId: result.queueId,
1243
+ position: result.position,
1244
+ };
1245
+ }
1246
+ if (await this.waitForSessionActivation(sessionId)) {
1247
+ return this.resumeSession(sessionId, projectPath, message, permissionMode, modelSettings);
1248
+ }
1249
+ return this.startSessionActivation(sessionId, async () => {
1250
+ if (this.isAtCapacity()) {
1251
+ const preemptable = this.findPreemptableWorker();
1252
+ if (preemptable) {
1253
+ await this.preemptWorker(preemptable);
1254
+ }
1255
+ else {
1256
+ throw new Error("Cannot resume: server is at worker capacity and no idle process can be preempted");
1257
+ }
1258
+ }
1259
+ const provider = this.resolveProvider(modelSettings);
1260
+ const resumeMode = modelSettings?.resumeMode ?? "full";
1261
+ // Use provider if available (preferred)
1262
+ if (provider) {
1263
+ if (resumeMode === "compact-first") {
1264
+ return this.startCompactFirstProviderResume(projectPath, projectId, message, sessionId, permissionMode, modelSettings, provider);
1265
+ }
1266
+ return this.startProviderSession(projectPath, projectId, message, sessionId, permissionMode, modelSettings, provider);
1267
+ }
1268
+ // Use real SDK if available
1269
+ if (this.realSdk) {
1270
+ if (resumeMode === "compact-first") {
1271
+ return this.startCompactFirstRealResume(projectPath, projectId, message, sessionId, permissionMode, modelSettings);
1272
+ }
1273
+ return this.startRealSession(projectPath, projectId, message, sessionId, permissionMode, modelSettings);
1274
+ }
1275
+ // Fall back to legacy mock SDK
1276
+ if (resumeMode === "compact-first") {
1277
+ throw new ResumeCompactionError({
721
1278
  sessionId,
722
- message,
723
- permissionMode,
724
- modelSettings,
1279
+ provider: "claude",
1280
+ attempt: {
1281
+ status: "unavailable",
1282
+ reason: "legacy mock SDK does not support compact-first resume",
1283
+ },
725
1284
  });
726
- if (isQueueFullError(result)) {
727
- return result;
1285
+ }
1286
+ return this.startLegacySession(projectPath, projectId, message, sessionId, permissionMode);
1287
+ });
1288
+ }
1289
+ /** Whether the resolved provider has a real transcript-fork primitive. */
1290
+ supportsForkSession(providerName) {
1291
+ const provider = this.resolveProvider(providerName ? { providerName } : undefined);
1292
+ return typeof provider?.forkSession === "function";
1293
+ }
1294
+ /**
1295
+ * Fork a session's transcript into a new resumable session, optionally
1296
+ * sliced at a message UUID. Throws when the provider has no fork
1297
+ * primitive — fork must not be emulated (see
1298
+ * topics/session-context-actions.md).
1299
+ */
1300
+ async forkSession(options) {
1301
+ const provider = this.resolveProvider(options.providerName ? { providerName: options.providerName } : undefined);
1302
+ if (!provider) {
1303
+ throw new Error("provider is not available");
1304
+ }
1305
+ if (typeof provider.forkSession !== "function") {
1306
+ throw new Error(`${provider.name} does not support transcript fork`);
1307
+ }
1308
+ return provider.forkSession({
1309
+ sessionId: options.sessionId,
1310
+ cwd: options.projectPath,
1311
+ upToMessageId: options.upToMessageId,
1312
+ title: options.title,
1313
+ });
1314
+ }
1315
+ async generateSummary(providerName, request) {
1316
+ const provider = this.resolveProvider(providerName ? { providerName } : undefined);
1317
+ if (!provider) {
1318
+ throw new Error("provider is not available");
1319
+ }
1320
+ if (typeof provider.generateSummary !== "function") {
1321
+ throw new Error(`${provider.name} does not support summary generation`);
1322
+ }
1323
+ return provider.generateSummary(request);
1324
+ }
1325
+ async archiveHelperFork(childSessionId, parentSessionId, title, providerName, process) {
1326
+ if (!this.sessionMetadataService) {
1327
+ return;
1328
+ }
1329
+ await this.sessionMetadataService.updateMetadata(childSessionId, {
1330
+ title,
1331
+ archived: true,
1332
+ parentSessionId,
1333
+ });
1334
+ await this.sessionMetadataService.setProvider(childSessionId, providerName);
1335
+ await this.sessionMetadataService.setExecutor(childSessionId, process.executor);
1336
+ await this.sessionMetadataService.setRequestedModel(childSessionId, process.requestedModel);
1337
+ }
1338
+ publishRecapListUpdate(process, text, timestamp = new Date().toISOString()) {
1339
+ if (!this.eventBus) {
1340
+ return;
1341
+ }
1342
+ const lastAgentText = formatAgentRecapExcerpt(text);
1343
+ if (!lastAgentText) {
1344
+ return;
1345
+ }
1346
+ const event = {
1347
+ type: "session-updated",
1348
+ sessionId: process.sessionId,
1349
+ projectId: process.projectId,
1350
+ updatedAt: timestamp,
1351
+ lastAgentText,
1352
+ timestamp: new Date().toISOString(),
1353
+ };
1354
+ this.eventBus.emit(event);
1355
+ }
1356
+ async persistRecapOverlay(process, message) {
1357
+ if (!this.sessionMetadataService) {
1358
+ return;
1359
+ }
1360
+ try {
1361
+ await this.sessionMetadataService.addRecapMessage(process.sessionId, message);
1362
+ }
1363
+ catch (error) {
1364
+ getLogger().warn({
1365
+ event: "session_recap_overlay_persist_failed",
1366
+ sessionId: process.sessionId,
1367
+ processId: process.id,
1368
+ projectId: process.projectId,
1369
+ error: error instanceof Error ? error.message : String(error),
1370
+ }, `Failed to persist recap overlay: ${process.sessionId}`);
1371
+ }
1372
+ }
1373
+ async handleRecapResult(process, result) {
1374
+ if (result.syntheticMessage) {
1375
+ await this.persistRecapOverlay(process, result.syntheticMessage);
1376
+ }
1377
+ if (result.emitted && result.text) {
1378
+ this.publishRecapListUpdate(process, result.text, result.syntheticMessage?.timestamp);
1379
+ }
1380
+ }
1381
+ /**
1382
+ * Raise a recap's "summarize since" floor to the latest already-emitted
1383
+ * recap for the session. A recap covers the transcript through (about) its
1384
+ * own timestamp, so a second return event with no assistant output after
1385
+ * the last recap has nothing new to say — regenerating the same summary
1386
+ * from the same context is wasted work and stacks duplicate recap rows.
1387
+ */
1388
+ recapFloorMs(sessionId, sinceMs) {
1389
+ const recaps = this.sessionMetadataService?.getRecapMessages(sessionId);
1390
+ const latest = recaps ? latestRecapMessage(recaps) : undefined;
1391
+ const lastRecapMs = latest ? messageTimestampMs(latest) : null;
1392
+ if (lastRecapMs === null) {
1393
+ return sinceMs;
1394
+ }
1395
+ return sinceMs === null ? lastRecapMs : Math.max(sinceMs, lastRecapMs);
1396
+ }
1397
+ async requestForkedRecap(process, provider, sinceMs, options) {
1398
+ if (!provider.supportsRecaps || !provider.generateSummary) {
1399
+ return {
1400
+ supported: false,
1401
+ emitted: false,
1402
+ reason: "provider does not support recaps",
1403
+ };
1404
+ }
1405
+ sinceMs = this.recapFloorMs(process.sessionId, sinceMs);
1406
+ if (typeof provider.forkSession !== "function") {
1407
+ return process.requestTailedRecapFallback(provider, { sinceMs });
1408
+ }
1409
+ if (this.forkedRecapInFlight.has(process.id)) {
1410
+ return {
1411
+ supported: true,
1412
+ emitted: false,
1413
+ reason: "recap already in flight",
1414
+ };
1415
+ }
1416
+ if (process.state.type === "in-turn") {
1417
+ this.pendingForkedRecapRequests.set(process.id, sinceMs);
1418
+ return {
1419
+ supported: true,
1420
+ emitted: false,
1421
+ reason: "recap deferred until turn completes",
1422
+ };
1423
+ }
1424
+ // A process freshly revived for this recap has an empty in-memory recap
1425
+ // buffer (it never streamed) and will not emit a native away_summary on its
1426
+ // own, so the native wait and the recent-text emptiness gate below would
1427
+ // both wrongly suppress. Skip them: the fork reads the transcript from disk,
1428
+ // and its own empty-text fallback handles a genuinely empty transcript.
1429
+ if (options?.revived !== true) {
1430
+ const nativeRecap = await process.waitForNativeRecapSince(sinceMs, provider.supportsNativeRecaps ? NATIVE_RECAP_FALLBACK_GRACE_MS : 0);
1431
+ if (nativeRecap) {
1432
+ return {
1433
+ supported: true,
1434
+ emitted: true,
1435
+ reason: "native recap emitted",
1436
+ text: nativeRecap.text,
1437
+ };
1438
+ }
1439
+ const recent = process.getRecentAssistantText(sinceMs);
1440
+ if (recent.length === 0) {
1441
+ return {
1442
+ supported: true,
1443
+ emitted: false,
1444
+ reason: "no recent assistant activity to summarize",
1445
+ };
1446
+ }
1447
+ }
1448
+ const abortController = new AbortController();
1449
+ this.forkedRecapInFlight.set(process.id, abortController);
1450
+ let generatorSessionId;
1451
+ try {
1452
+ const generator = await this.forkSession({
1453
+ sessionId: process.sessionId,
1454
+ projectPath: process.projectPath,
1455
+ providerName: process.provider,
1456
+ title: "Recap generator",
1457
+ });
1458
+ generatorSessionId = generator.sessionId;
1459
+ await this.archiveHelperFork(generator.sessionId, process.sessionId, "Recap generator", process.provider, process);
1460
+ const text = (await provider.generateSummary({
1461
+ purpose: "recap",
1462
+ strategy: "fork",
1463
+ generatorSessionId: generator.sessionId,
1464
+ cwd: process.projectPath,
1465
+ signal: abortController.signal,
1466
+ })).text.trim();
1467
+ if (!text) {
1468
+ return process.requestTailedRecapFallback(provider, { sinceMs });
1469
+ }
1470
+ const lateNativeRecap = process.getNativeRecapSince(sinceMs);
1471
+ if (lateNativeRecap) {
1472
+ return {
1473
+ supported: true,
1474
+ emitted: true,
1475
+ reason: "native recap emitted",
1476
+ text: lateNativeRecap.text,
1477
+ };
1478
+ }
1479
+ const syntheticMessage = process.emitSyntheticSystemMessage("away_summary", text);
1480
+ return { supported: true, emitted: true, text, syntheticMessage };
1481
+ }
1482
+ catch (error) {
1483
+ // Cancellation on parent activity is expected, not a failure.
1484
+ if (abortController.signal.aborted) {
1485
+ const nativeRecap = process.getNativeRecapSince(sinceMs);
1486
+ if (nativeRecap) {
1487
+ return {
1488
+ supported: true,
1489
+ emitted: true,
1490
+ reason: "native recap emitted",
1491
+ text: nativeRecap.text,
1492
+ };
728
1493
  }
729
1494
  return {
730
- queued: true,
731
- queueId: result.queueId,
732
- position: result.position,
1495
+ supported: true,
1496
+ emitted: false,
1497
+ reason: "recap cancelled by new activity",
733
1498
  };
734
1499
  }
1500
+ const reason = error instanceof Error ? error.message : String(error);
1501
+ getLogger().warn({
1502
+ event: "session_forked_recap_failed",
1503
+ sessionId: process.sessionId,
1504
+ processId: process.id,
1505
+ projectId: process.projectId,
1506
+ providerName: process.provider,
1507
+ generatorSessionId,
1508
+ error: reason,
1509
+ }, `Forked recap generation failed: ${reason}`);
1510
+ return process.requestTailedRecapFallback(provider, { sinceMs });
735
1511
  }
736
- const provider = this.resolveProvider(modelSettings);
737
- // Use provider if available (preferred)
738
- if (provider) {
739
- return this.startProviderSession(projectPath, projectId, message, sessionId, permissionMode, modelSettings, provider);
1512
+ finally {
1513
+ this.forkedRecapInFlight.delete(process.id);
740
1514
  }
741
- // Use real SDK if available
742
- if (this.realSdk) {
743
- return this.startRealSession(projectPath, projectId, message, sessionId, permissionMode, modelSettings);
1515
+ }
1516
+ /**
1517
+ * Parent became active again: abort any in-flight forked recap (cancelling
1518
+ * the generator-fork helper turn) and drop a not-yet-started deferred
1519
+ * request, so a returning user's new turn is never shadowed by a stale
1520
+ * recap. See topics/fork-recap.md.
1521
+ */
1522
+ cancelInFlightForkedRecap(process) {
1523
+ const abortController = this.forkedRecapInFlight.get(process.id);
1524
+ if (abortController && !abortController.signal.aborted) {
1525
+ abortController.abort();
744
1526
  }
745
- // Fall back to legacy mock SDK
746
- return this.startLegacySession(projectPath, projectId, message, sessionId, permissionMode);
1527
+ this.pendingForkedRecapRequests.delete(process.id);
1528
+ }
1529
+ flushPendingForkedRecapRequest(process) {
1530
+ if (process.recapMode !== "fork" ||
1531
+ process.state.type !== "idle" ||
1532
+ this.forkedRecapInFlight.has(process.id) ||
1533
+ !this.pendingForkedRecapRequests.has(process.id)) {
1534
+ return;
1535
+ }
1536
+ const sinceMs = this.pendingForkedRecapRequests.get(process.id) ?? null;
1537
+ this.pendingForkedRecapRequests.delete(process.id);
1538
+ const provider = getProvider(process.provider);
1539
+ if (!provider) {
1540
+ return;
1541
+ }
1542
+ void this.requestForkedRecap(process, provider, sinceMs).then((result) => this.handleRecapResult(process, result));
747
1543
  }
748
1544
  getProcess(processId) {
749
1545
  return this.processes.get(processId);
@@ -767,7 +1563,7 @@ export class Supervisor {
767
1563
  const nextEffort = hasEffortUpdate ? updates.effort : process.effort;
768
1564
  const modelChanged = nextModel !== process.resolvedModel;
769
1565
  const serviceTierChanged = nextServiceTier !== process.serviceTier;
770
- const thinkingChanged = nextThinking?.type !== process.thinking?.type;
1566
+ const thinkingChanged = !thinkingConfigsEqual(process.thinking, nextThinking);
771
1567
  const effortChanged = nextEffort !== process.effort;
772
1568
  if (!modelChanged &&
773
1569
  !serviceTierChanged &&
@@ -796,6 +1592,7 @@ export class Supervisor {
796
1592
  providerName: process.provider,
797
1593
  executor: process.executor,
798
1594
  recapMode: process.recapMode,
1595
+ recapAfterSeconds: process.recapAfterSeconds,
799
1596
  promptSuggestionMode: process.promptSuggestionMode,
800
1597
  helperSideModel: process.helperSideModel,
801
1598
  };
@@ -809,6 +1606,13 @@ export class Supervisor {
809
1606
  return null;
810
1607
  }
811
1608
  process.setRecapConfig(config);
1609
+ this.emitOwnershipChange(process.sessionId, process.projectId, {
1610
+ owner: "self",
1611
+ processId: process.id,
1612
+ permissionMode: process.permissionMode,
1613
+ modeVersion: process.modeVersion,
1614
+ recapAfterSeconds: process.recapAfterSeconds,
1615
+ });
812
1616
  return process;
813
1617
  }
814
1618
  getProcessForSession(sessionId) {
@@ -836,12 +1640,18 @@ export class Supervisor {
836
1640
  }
837
1641
  const isActiveSteeringMessage = message.metadata?.deliveryIntent === "steer" &&
838
1642
  process.state.type === "in-turn";
1643
+ const hasExplicitThinkingSettings = modelSettings?.thinking !== undefined ||
1644
+ modelSettings?.effort !== undefined;
839
1645
  const requestedThinking = isActiveSteeringMessage
840
1646
  ? process.thinking
841
- : modelSettings?.thinking;
1647
+ : hasExplicitThinkingSettings
1648
+ ? modelSettings?.thinking
1649
+ : process.thinking;
842
1650
  const requestedEffort = isActiveSteeringMessage
843
1651
  ? process.effort
844
- : modelSettings?.effort;
1652
+ : hasExplicitThinkingSettings
1653
+ ? modelSettings?.effort
1654
+ : process.effort;
845
1655
  const requestedServiceTier = isActiveSteeringMessage
846
1656
  ? process.serviceTier
847
1657
  : (modelSettings?.serviceTier ?? process.serviceTier);
@@ -849,12 +1659,13 @@ export class Supervisor {
849
1659
  // Service tier is cost-affecting, so changes require an explicit restart
850
1660
  // rather than being inferred from a normal prompt.
851
1661
  const serviceTierChanged = process.serviceTier !== requestedServiceTier;
852
- const thinkingChanged = process.thinking?.type !== (requestedThinking?.type ?? undefined);
1662
+ const thinkingChanged = !thinkingConfigsEqual(process.thinking, requestedThinking);
853
1663
  const effortChanged = process.effort !== requestedEffort;
854
1664
  if (serviceTierChanged || thinkingChanged || effortChanged) {
855
1665
  if (!serviceTierChanged &&
856
1666
  thinkingChanged &&
857
1667
  !effortChanged &&
1668
+ canApplyThinkingConfigDynamically(process.thinking, requestedThinking) &&
858
1669
  process.supportsThinkingModeChange) {
859
1670
  // Toggle thinking dynamically via deprecated API (works for auto↔off)
860
1671
  const tokens = requestedThinking?.type === "disabled" ? 0 : 1;
@@ -891,6 +1702,7 @@ export class Supervisor {
891
1702
  ...modelSettings,
892
1703
  serviceTier: requestedServiceTier,
893
1704
  recapMode: modelSettings?.recapMode ?? process.recapMode,
1705
+ recapAfterSeconds: modelSettings?.recapAfterSeconds ?? process.recapAfterSeconds,
894
1706
  promptSuggestionMode: modelSettings?.promptSuggestionMode ?? process.promptSuggestionMode,
895
1707
  helperSideModel: modelSettings?.helperSideModel ?? process.helperSideModel,
896
1708
  };
@@ -905,6 +1717,10 @@ export class Supervisor {
905
1717
  if (permissionMode) {
906
1718
  process.setPermissionMode(permissionMode);
907
1719
  }
1720
+ // Preemptively compact when this turn would push an already-near-threshold
1721
+ // session over its per-model compact-early limit (task 029). No-op unless
1722
+ // the threshold is set and the idle process is over it.
1723
+ await this.maybeCompactBeforeDelivery(process, sessionId, modelSettings);
908
1724
  const result = await this.queueProcessMessage(process, message);
909
1725
  if (result.success) {
910
1726
  return { success: true, process, restarted: false };
@@ -923,6 +1739,9 @@ export class Supervisor {
923
1739
  const log = getLogger();
924
1740
  try {
925
1741
  for (const process of this.processes.values()) {
1742
+ if (this.queuePatientDeferredMessagesForProcess(process, now, log)) {
1743
+ continue;
1744
+ }
926
1745
  await this.queueHeartbeatTurnForProcess(process, now, log);
927
1746
  }
928
1747
  if (!this.getHeartbeatTurnCandidates) {
@@ -938,7 +1757,68 @@ export class Supervisor {
938
1757
  }
939
1758
  }
940
1759
  shouldRetainIdleProcess(sessionId) {
941
- return this.getHeartbeatTurnSettings?.(sessionId)?.enabled === true;
1760
+ const process = this.getProcessForSession(sessionId);
1761
+ return (process?.hasPatientDeferredMessages() === true ||
1762
+ this.getHeartbeatTurnSettings?.(sessionId)?.enabled === true);
1763
+ }
1764
+ queuePatientDeferredMessagesForProcess(process, now, log) {
1765
+ if (!process.hasPatientDeferredMessages() ||
1766
+ process.isTerminated ||
1767
+ process.state.type !== "idle" ||
1768
+ process.queueDepth > 0 ||
1769
+ process.isProcessAlive === false) {
1770
+ return false;
1771
+ }
1772
+ const liveness = process.getLivenessSnapshot(new Date(now));
1773
+ if (liveness.derivedStatus !== "verified-idle") {
1774
+ return false;
1775
+ }
1776
+ const fallbackMs = process.state.since.getTime();
1777
+ const quietSinceMs = getHeartbeatResetAtMs(liveness, fallbackMs);
1778
+ if (!Number.isFinite(quietSinceMs)) {
1779
+ return false;
1780
+ }
1781
+ // Each patient entry carries its own patience window (seconds of
1782
+ // verified quiet); promote the elapsed ones and schedule a precise
1783
+ // re-check for the shortest remaining wait.
1784
+ const { promoted, nextPatienceMsRemaining } = process.promoteEligiblePatientDeferredMessages({ quietSinceMs, now });
1785
+ if (nextPatienceMsRemaining !== null) {
1786
+ this.schedulePatientDeferredCheck(process, nextPatienceMsRemaining);
1787
+ }
1788
+ if (!promoted) {
1789
+ return false;
1790
+ }
1791
+ log.info({
1792
+ event: "patient_deferred_messages_promoted",
1793
+ sessionId: process.sessionId,
1794
+ processId: process.id,
1795
+ projectId: process.projectId,
1796
+ quietMs: Math.max(0, now - quietSinceMs),
1797
+ quietSince: new Date(quietSinceMs).toISOString(),
1798
+ livenessStatus: liveness.derivedStatus,
1799
+ }, `Promoted patient deferred messages for session: ${process.sessionId}`);
1800
+ return true;
1801
+ }
1802
+ /**
1803
+ * Arm (or re-arm) the one-shot patient-queue re-check for a process. The
1804
+ * check itself re-derives eligibility and re-arms only while patient
1805
+ * entries remain, so the timer cannot become a standing poll.
1806
+ */
1807
+ schedulePatientDeferredCheck(process, delayMs) {
1808
+ const existing = this.patientCheckTimers.get(process.id);
1809
+ if (existing) {
1810
+ clearTimeout(existing);
1811
+ }
1812
+ const delay = Math.max(250, Math.min(delayMs, 60 * 60 * 1000));
1813
+ const timer = setTimeout(() => {
1814
+ this.patientCheckTimers.delete(process.id);
1815
+ if (!this.processes.has(process.id)) {
1816
+ return;
1817
+ }
1818
+ this.queuePatientDeferredMessagesForProcess(process, Date.now(), getLogger());
1819
+ }, delay);
1820
+ timer.unref();
1821
+ this.patientCheckTimers.set(process.id, timer);
942
1822
  }
943
1823
  async queueHeartbeatTurnForProcess(process, now, log) {
944
1824
  const settings = this.getHeartbeatTurnSettings?.(process.sessionId);
@@ -1304,7 +2184,15 @@ export class Supervisor {
1304
2184
  reason: "provider not found",
1305
2185
  };
1306
2186
  }
1307
- return process.requestRecap(provider, options);
2187
+ const result = process.recapMode === "fork"
2188
+ ? await this.requestForkedRecap(process, provider, options?.sinceMs ?? null, { revived: options?.revived === true })
2189
+ : await process.requestRecap(provider, {
2190
+ ...options,
2191
+ sinceMs: this.recapFloorMs(process.sessionId, options?.sinceMs ?? null),
2192
+ });
2193
+ await this.handleRecapResult(process, result);
2194
+ const { syntheticMessage: _syntheticMessage, ...publicResult } = result;
2195
+ return publicResult;
1308
2196
  }
1309
2197
  async interruptProcessWithTimeout(process, options) {
1310
2198
  const log = getLogger();
@@ -1371,6 +2259,7 @@ export class Supervisor {
1371
2259
  providerName,
1372
2260
  executor: sourceProcess.executor,
1373
2261
  permissions: sourceProcess.permissions,
2262
+ recapAfterSeconds: sourceProcess.recapAfterSeconds,
1374
2263
  });
1375
2264
  const log = getLogger();
1376
2265
  if (!("id" in result)) {
@@ -1424,6 +2313,24 @@ export class Supervisor {
1424
2313
  else if (event.type === "complete") {
1425
2314
  this.unregisterProcess(process);
1426
2315
  }
2316
+ else if (event.type === "message") {
2317
+ this.cacheMissBillingMonitor.observeMessage(process, event.message);
2318
+ if (isAwaySummaryMessage(event.message) &&
2319
+ event.message.isSynthetic !== true) {
2320
+ const durable = toDurableRecapMessage(event.message, "provider-native");
2321
+ if (durable) {
2322
+ void this.persistRecapOverlay(process, durable);
2323
+ this.publishRecapListUpdate(process, durable.content, durable.timestamp);
2324
+ this.cancelInFlightForkedRecap(process);
2325
+ }
2326
+ }
2327
+ }
2328
+ else if (event.type === "recap-result") {
2329
+ void this.handleRecapResult(process, event.result);
2330
+ }
2331
+ else if (event.type === "context-window-observed") {
2332
+ this.onContextWindowObserved?.(event.model, event.contextWindow, event.provider);
2333
+ }
1427
2334
  else if (event.type === "session-id-changed") {
1428
2335
  // Update session→process mapping when temp ID is replaced by real ID from SDK
1429
2336
  // This is critical for ExternalSessionTracker to correctly identify owned sessions
@@ -1459,6 +2366,7 @@ export class Supervisor {
1459
2366
  processId: process.id,
1460
2367
  permissionMode: process.permissionMode,
1461
2368
  modeVersion: process.modeVersion,
2369
+ recapAfterSeconds: process.recapAfterSeconds,
1462
2370
  };
1463
2371
  this.emitOwnershipChange(event.newSessionId, process.projectId, ownership);
1464
2372
  // Retry early metadata reconciliation with authoritative session ID.
@@ -1480,14 +2388,45 @@ export class Supervisor {
1480
2388
  ? "tool-approval"
1481
2389
  : "user-question";
1482
2390
  }
1483
- this.emitAgentActivityChange(process.sessionId, process.projectId, event.state.type, pendingInputType);
2391
+ // A turn that settles to idle while the provider still has background
2392
+ // work retained should report as active, not idle.
2393
+ const activity = event.state.type === "idle" && process.isRetainingProviderWork()
2394
+ ? "in-turn"
2395
+ : event.state.type;
2396
+ this.emitAgentActivityChange(process.sessionId, process.projectId, activity, pendingInputType);
1484
2397
  }
1485
2398
  // Emit worker activity on any state change (affects hasActiveWork)
1486
2399
  this.emitWorkerActivity();
2400
+ // A fresh idle boundary starts the patient-queue quiet clock; arm a
2401
+ // prompt re-check so seconds-scale patience does not wait for the
2402
+ // 30s heartbeat tick.
2403
+ if (event.state.type === "idle" &&
2404
+ process.hasPatientDeferredMessages()) {
2405
+ this.schedulePatientDeferredCheck(process, 250);
2406
+ }
2407
+ if (event.state.type === "idle") {
2408
+ this.flushPendingForkedRecapRequest(process);
2409
+ }
2410
+ // Parent started a new turn: cancel any in-flight/deferred forked recap
2411
+ // so a returning user's live turn is not shadowed by a stale recap.
2412
+ if (event.state.type === "in-turn") {
2413
+ this.cancelInFlightForkedRecap(process);
2414
+ }
2415
+ }
2416
+ else if (event.type === "deferred-queue") {
2417
+ if (event.reason === "queued" &&
2418
+ process.state.type === "idle" &&
2419
+ process.hasPatientDeferredMessages()) {
2420
+ this.schedulePatientDeferredCheck(process, 250);
2421
+ }
2422
+ this.emitWorkerActivity();
1487
2423
  }
1488
2424
  else if (event.type === "terminated") {
1489
2425
  this.emitProcessTerminated(process.sessionId, process.projectId, process.id, process.provider, event.reason);
1490
2426
  }
2427
+ else if (event.type === "provider-runtime-status-change") {
2428
+ this.emitProviderRuntimeStatusChange(process.sessionId, process.projectId, event.status);
2429
+ }
1491
2430
  });
1492
2431
  }
1493
2432
  registerProcess(process, isNewSession) {
@@ -1510,6 +2449,7 @@ export class Supervisor {
1510
2449
  processId: process.id,
1511
2450
  permissionMode: process.permissionMode,
1512
2451
  modeVersion: process.modeVersion,
2452
+ recapAfterSeconds: process.recapAfterSeconds,
1513
2453
  };
1514
2454
  // Emit session created event for new sessions
1515
2455
  if (isNewSession) {
@@ -1536,6 +2476,15 @@ export class Supervisor {
1536
2476
  }
1537
2477
  unregisterProcess(process) {
1538
2478
  this.observedProcessIds.delete(process.id);
2479
+ this.cacheMissBillingMonitor.forgetProcess(process.id);
2480
+ this.pendingForkedRecapRequests.delete(process.id);
2481
+ this.forkedRecapInFlight.get(process.id)?.abort();
2482
+ this.forkedRecapInFlight.delete(process.id);
2483
+ const patientTimer = this.patientCheckTimers.get(process.id);
2484
+ if (patientTimer) {
2485
+ clearTimeout(patientTimer);
2486
+ this.patientCheckTimers.delete(process.id);
2487
+ }
1539
2488
  if (!this.processes.has(process.id)) {
1540
2489
  return;
1541
2490
  }
@@ -1624,6 +2573,7 @@ export class Supervisor {
1624
2573
  const session = {
1625
2574
  id: process.sessionId,
1626
2575
  projectId: process.projectId,
2576
+ projectName: getProjectName(process.projectPath),
1627
2577
  title: optimistic.title,
1628
2578
  fullTitle: optimistic.fullTitle,
1629
2579
  createdAt: now,
@@ -1676,6 +2626,7 @@ export class Supervisor {
1676
2626
  updatedAt: summary.updatedAt,
1677
2627
  contextUsage: summary.contextUsage,
1678
2628
  model: summary.model,
2629
+ lastAgentText: summary.lastAgentText,
1679
2630
  timestamp: new Date().toISOString(),
1680
2631
  };
1681
2632
  this.eventBus.emit(event);
@@ -1707,6 +2658,37 @@ export class Supervisor {
1707
2658
  };
1708
2659
  this.eventBus.emit(event);
1709
2660
  }
2661
+ emitProviderRuntimeStatusChange(sessionId, projectId, providerRuntimeStatus) {
2662
+ if (!this.eventBus)
2663
+ return;
2664
+ const event = {
2665
+ type: "provider-runtime-status-changed",
2666
+ sessionId,
2667
+ projectId,
2668
+ providerRuntimeStatus,
2669
+ timestamp: new Date().toISOString(),
2670
+ };
2671
+ this.eventBus.emit(event);
2672
+ }
2673
+ handleProviderRetentionChanged(processHolder) {
2674
+ const process = processHolder.process;
2675
+ process?.handleProviderRetentionChanged();
2676
+ this.emitWorkerActivity();
2677
+ // Background work starting/finishing flips an idle session between active
2678
+ // and truly idle without a state-change event. Surface that so inbox/sidebar
2679
+ // activity indicators update live rather than only on the next refresh.
2680
+ if (process && process.state.type === "idle") {
2681
+ this.emitAgentActivityChange(process.sessionId, process.projectId, process.isRetainingProviderWork() ? "in-turn" : "idle");
2682
+ }
2683
+ }
2684
+ processHasActiveWork(process) {
2685
+ if (process.state.type === "in-turn" ||
2686
+ process.state.type === "waiting-input") {
2687
+ return true;
2688
+ }
2689
+ return (process.getLivenessSnapshot().derivedStatus ===
2690
+ "verified-waiting-provider");
2691
+ }
1710
2692
  /**
1711
2693
  * Emit worker activity event for safe restart indicator.
1712
2694
  * Called when workers are added, removed, or change state.
@@ -1714,16 +2696,48 @@ export class Supervisor {
1714
2696
  emitWorkerActivity() {
1715
2697
  if (!this.eventBus)
1716
2698
  return;
1717
- const hasActiveWork = Array.from(this.processes.values()).some((p) => p.state.type === "in-turn" || p.state.type === "waiting-input");
2699
+ const interruptibleSessionCount = Array.from(this.processes.values()).filter((p) => this.processHasActiveWork(p)).length;
2700
+ const queuedSessionMessageCount = this.getQueuedSessionMessageCount();
1718
2701
  const event = {
1719
2702
  type: "worker-activity-changed",
1720
2703
  activeWorkers: this.processes.size,
2704
+ interruptibleSessionCount,
1721
2705
  queueLength: this.workerQueue.length,
1722
- hasActiveWork,
2706
+ queuedSessionMessageCount,
2707
+ hasActiveWork: interruptibleSessionCount > 0,
1723
2708
  timestamp: new Date().toISOString(),
1724
2709
  };
1725
2710
  this.eventBus.emit(event);
1726
2711
  }
2712
+ getQueuedSessionMessageCount() {
2713
+ let count = this.workerQueue.length;
2714
+ for (const process of this.processes.values()) {
2715
+ count += process.queueDepth;
2716
+ count += process.getDeferredQueueSummary().length;
2717
+ }
2718
+ return count;
2719
+ }
2720
+ async preserveRestartablePatientQueuesForRestart() {
2721
+ if (!this.sessionQueuePersistenceService || this.workerQueue.length > 0) {
2722
+ return 0;
2723
+ }
2724
+ const processes = Array.from(this.processes.values()).filter((process) => !process.isTerminated);
2725
+ if (processes.some((process) => this.processHasActiveWork(process))) {
2726
+ return 0;
2727
+ }
2728
+ if (processes.some((process) => process.queueDepth > 0 || process.hasVolatileDeferredMessages())) {
2729
+ return 0;
2730
+ }
2731
+ let preservedCount = 0;
2732
+ for (const process of processes) {
2733
+ preservedCount +=
2734
+ await process.preservePatientDeferredMessagesForRestart();
2735
+ }
2736
+ if (preservedCount > 0) {
2737
+ this.emitWorkerActivity();
2738
+ }
2739
+ return preservedCount;
2740
+ }
1727
2741
  // ============ Staleness Detection ============
1728
2742
  /**
1729
2743
  * Terminate processes stuck in "in-turn" with no SDK messages for too long.
@@ -1838,6 +2852,9 @@ export class Supervisor {
1838
2852
  const result = await this.startSessionInternal(request.projectPath, request.projectId, request.message, request.sessionId, request.permissionMode, request.modelSettings);
1839
2853
  process = result;
1840
2854
  }
2855
+ if (request.workstreamId) {
2856
+ await this.sessionMetadataService?.setWorkstream(process.sessionId, request.workstreamId);
2857
+ }
1841
2858
  // Emit queue removed event
1842
2859
  this.eventBus?.emit({
1843
2860
  type: "queue-request-removed",
@@ -1909,11 +2926,13 @@ export class Supervisor {
1909
2926
  * Returns whether any workers are actively processing or waiting for input.
1910
2927
  */
1911
2928
  getWorkerActivity() {
1912
- const hasActiveWork = Array.from(this.processes.values()).some((p) => p.state.type === "in-turn" || p.state.type === "waiting-input");
2929
+ const interruptibleSessionCount = Array.from(this.processes.values()).filter((p) => this.processHasActiveWork(p)).length;
1913
2930
  return {
1914
2931
  activeWorkers: this.processes.size,
2932
+ interruptibleSessionCount,
1915
2933
  queueLength: this.workerQueue.length,
1916
- hasActiveWork,
2934
+ queuedSessionMessageCount: this.getQueuedSessionMessageCount(),
2935
+ hasActiveWork: interruptibleSessionCount > 0,
1917
2936
  };
1918
2937
  }
1919
2938
  }