@qduc/term2 0.14.0 → 0.16.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 (1166) hide show
  1. package/README.md +324 -316
  2. package/dist/agent.d.ts +5 -0
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +23 -61
  5. package/dist/agent.js.map +1 -1
  6. package/dist/app-helpers.d.ts +4 -0
  7. package/dist/app-helpers.d.ts.map +1 -1
  8. package/dist/app-helpers.js +6 -0
  9. package/dist/app-helpers.js.map +1 -1
  10. package/dist/app.d.ts +2 -2
  11. package/dist/app.d.ts.map +1 -1
  12. package/dist/app.js +265 -27
  13. package/dist/app.js.map +1 -1
  14. package/dist/cli.js +123 -30
  15. package/dist/cli.js.map +1 -1
  16. package/dist/commands/auto-approve-command.js +3 -3
  17. package/dist/commands/auto-approve-command.js.map +1 -1
  18. package/dist/commands/compact-command.d.ts.map +1 -1
  19. package/dist/commands/compact-command.js +4 -0
  20. package/dist/commands/compact-command.js.map +1 -1
  21. package/dist/commands/effort-command.js +1 -1
  22. package/dist/commands/effort-command.js.map +1 -1
  23. package/dist/commands/guarded-settings-command.d.ts +3 -1
  24. package/dist/commands/guarded-settings-command.d.ts.map +1 -1
  25. package/dist/commands/guarded-settings-command.js +17 -5
  26. package/dist/commands/guarded-settings-command.js.map +1 -1
  27. package/dist/commands/mode-commands.d.ts +9 -2
  28. package/dist/commands/mode-commands.d.ts.map +1 -1
  29. package/dist/commands/mode-commands.js +12 -3
  30. package/dist/commands/mode-commands.js.map +1 -1
  31. package/dist/commands/model-command.js +1 -1
  32. package/dist/commands/model-command.js.map +1 -1
  33. package/dist/commands/resume-command.d.ts +10 -0
  34. package/dist/commands/resume-command.d.ts.map +1 -0
  35. package/dist/commands/resume-command.js +40 -0
  36. package/dist/commands/resume-command.js.map +1 -0
  37. package/dist/commands/usage-command.d.ts +10 -1
  38. package/dist/commands/usage-command.d.ts.map +1 -1
  39. package/dist/commands/usage-command.js +11 -1
  40. package/dist/commands/usage-command.js.map +1 -1
  41. package/dist/components/ErrorBoundary.d.ts.map +1 -1
  42. package/dist/components/ErrorBoundary.js +5 -4
  43. package/dist/components/ErrorBoundary.js.map +1 -1
  44. package/dist/components/InputBox.d.ts +2 -0
  45. package/dist/components/InputBox.d.ts.map +1 -1
  46. package/dist/components/InputBox.js +59 -8
  47. package/dist/components/InputBox.js.map +1 -1
  48. package/dist/components/MarkdownRenderer.d.ts.map +1 -1
  49. package/dist/components/MarkdownRenderer.js +16 -15
  50. package/dist/components/MarkdownRenderer.js.map +1 -1
  51. package/dist/components/common/MenuContainer.d.ts +25 -2
  52. package/dist/components/common/MenuContainer.d.ts.map +1 -1
  53. package/dist/components/common/MenuContainer.js +35 -11
  54. package/dist/components/common/MenuContainer.js.map +1 -1
  55. package/dist/components/common/ScrollableTabBar.d.ts.map +1 -1
  56. package/dist/components/common/ScrollableTabBar.js +5 -4
  57. package/dist/components/common/ScrollableTabBar.js.map +1 -1
  58. package/dist/components/input/ApplicationInputSurface.d.ts +4 -5
  59. package/dist/components/input/ApplicationInputSurface.d.ts.map +1 -1
  60. package/dist/components/input/ApplicationInputSurface.js.map +1 -1
  61. package/dist/components/input/FirstRunSetupPrompt.d.ts.map +1 -1
  62. package/dist/components/input/FirstRunSetupPrompt.js +5 -4
  63. package/dist/components/input/FirstRunSetupPrompt.js.map +1 -1
  64. package/dist/components/input/MenuSurface.d.ts.map +1 -1
  65. package/dist/components/input/MenuSurface.js +10 -3
  66. package/dist/components/input/MenuSurface.js.map +1 -1
  67. package/dist/components/input/ModelMenuSession.d.ts.map +1 -1
  68. package/dist/components/input/ModelMenuSession.js +2 -1
  69. package/dist/components/input/ModelMenuSession.js.map +1 -1
  70. package/dist/components/input/PendingQueueList.d.ts +2 -0
  71. package/dist/components/input/PendingQueueList.d.ts.map +1 -1
  72. package/dist/components/input/PendingQueueList.js +26 -6
  73. package/dist/components/input/PendingQueueList.js.map +1 -1
  74. package/dist/components/input/ProviderMenuSession.d.ts.map +1 -1
  75. package/dist/components/input/ProviderMenuSession.js +1 -0
  76. package/dist/components/input/ProviderMenuSession.js.map +1 -1
  77. package/dist/components/input/SettingsValueMenuSession.d.ts.map +1 -1
  78. package/dist/components/input/SettingsValueMenuSession.js +8 -1
  79. package/dist/components/input/SettingsValueMenuSession.js.map +1 -1
  80. package/dist/components/layout/BackgroundTaskManager.d.ts +2 -0
  81. package/dist/components/layout/BackgroundTaskManager.d.ts.map +1 -1
  82. package/dist/components/layout/BackgroundTaskManager.js +166 -73
  83. package/dist/components/layout/BackgroundTaskManager.js.map +1 -1
  84. package/dist/components/layout/BackgroundTasksPanel.d.ts +12 -3
  85. package/dist/components/layout/BackgroundTasksPanel.d.ts.map +1 -1
  86. package/dist/components/layout/BackgroundTasksPanel.js +197 -62
  87. package/dist/components/layout/BackgroundTasksPanel.js.map +1 -1
  88. package/dist/components/layout/Banner.d.ts +0 -1
  89. package/dist/components/layout/Banner.d.ts.map +1 -1
  90. package/dist/components/layout/Banner.js +43 -73
  91. package/dist/components/layout/Banner.js.map +1 -1
  92. package/dist/components/layout/BottomArea.d.ts +17 -6
  93. package/dist/components/layout/BottomArea.d.ts.map +1 -1
  94. package/dist/components/layout/BottomArea.js +44 -19
  95. package/dist/components/layout/BottomArea.js.map +1 -1
  96. package/dist/components/layout/DiffView.js +5 -5
  97. package/dist/components/layout/DiffView.js.map +1 -1
  98. package/dist/components/layout/StatusBar.d.ts +9 -1
  99. package/dist/components/layout/StatusBar.d.ts.map +1 -1
  100. package/dist/components/layout/StatusBar.js +332 -80
  101. package/dist/components/layout/StatusBar.js.map +1 -1
  102. package/dist/components/layout/background-task-clock.d.ts +43 -0
  103. package/dist/components/layout/background-task-clock.d.ts.map +1 -0
  104. package/dist/components/layout/background-task-clock.js +46 -0
  105. package/dist/components/layout/background-task-clock.js.map +1 -0
  106. package/dist/components/layout/live-task-rows.d.ts +16 -0
  107. package/dist/components/layout/live-task-rows.d.ts.map +1 -0
  108. package/dist/components/layout/live-task-rows.js +28 -0
  109. package/dist/components/layout/live-task-rows.js.map +1 -0
  110. package/dist/components/layout/terminal-text-budget.d.ts +4 -0
  111. package/dist/components/layout/terminal-text-budget.d.ts.map +1 -0
  112. package/dist/components/layout/terminal-text-budget.js +18 -0
  113. package/dist/components/layout/terminal-text-budget.js.map +1 -0
  114. package/dist/components/menu/CopyMenu.d.ts.map +1 -1
  115. package/dist/components/menu/CopyMenu.js +4 -3
  116. package/dist/components/menu/CopyMenu.js.map +1 -1
  117. package/dist/components/menu/MentorPoolSelectionMenu.d.ts.map +1 -1
  118. package/dist/components/menu/MentorPoolSelectionMenu.js +28 -21
  119. package/dist/components/menu/MentorPoolSelectionMenu.js.map +1 -1
  120. package/dist/components/menu/ModelSelectionMenu.d.ts.map +1 -1
  121. package/dist/components/menu/ModelSelectionMenu.js +43 -17
  122. package/dist/components/menu/ModelSelectionMenu.js.map +1 -1
  123. package/dist/components/menu/PathSelectionMenu.d.ts.map +1 -1
  124. package/dist/components/menu/PathSelectionMenu.js +4 -3
  125. package/dist/components/menu/PathSelectionMenu.js.map +1 -1
  126. package/dist/components/menu/ProviderSelectionMenu.d.ts.map +1 -1
  127. package/dist/components/menu/ProviderSelectionMenu.js +71 -26
  128. package/dist/components/menu/ProviderSelectionMenu.js.map +1 -1
  129. package/dist/components/menu/RewindMenu.d.ts.map +1 -1
  130. package/dist/components/menu/RewindMenu.js +4 -3
  131. package/dist/components/menu/RewindMenu.js.map +1 -1
  132. package/dist/components/menu/SettingsSelectionMenu.d.ts.map +1 -1
  133. package/dist/components/menu/SettingsSelectionMenu.js +30 -25
  134. package/dist/components/menu/SettingsSelectionMenu.js.map +1 -1
  135. package/dist/components/menu/SettingsValueSelectionMenu.d.ts.map +1 -1
  136. package/dist/components/menu/SettingsValueSelectionMenu.js +22 -20
  137. package/dist/components/menu/SettingsValueSelectionMenu.js.map +1 -1
  138. package/dist/components/menu/SkillSelectionMenu.d.ts.map +1 -1
  139. package/dist/components/menu/SkillSelectionMenu.js +33 -23
  140. package/dist/components/menu/SkillSelectionMenu.js.map +1 -1
  141. package/dist/components/menu/SlashCommandMenu.d.ts.map +1 -1
  142. package/dist/components/menu/SlashCommandMenu.js +11 -6
  143. package/dist/components/menu/SlashCommandMenu.js.map +1 -1
  144. package/dist/components/message/ChatMessage.js +2 -2
  145. package/dist/components/message/ChatMessage.js.map +1 -1
  146. package/dist/components/message/CodeContextSearchRenderer.d.ts.map +1 -1
  147. package/dist/components/message/CodeContextSearchRenderer.js +8 -11
  148. package/dist/components/message/CodeContextSearchRenderer.js.map +1 -1
  149. package/dist/components/message/CommandGroupSummary.d.ts +9 -0
  150. package/dist/components/message/CommandGroupSummary.d.ts.map +1 -0
  151. package/dist/components/message/CommandGroupSummary.js +39 -0
  152. package/dist/components/message/CommandGroupSummary.js.map +1 -0
  153. package/dist/components/message/CommandMessage.d.ts +8 -0
  154. package/dist/components/message/CommandMessage.d.ts.map +1 -1
  155. package/dist/components/message/CommandMessage.js +159 -110
  156. package/dist/components/message/CommandMessage.js.map +1 -1
  157. package/dist/components/message/GrepRenderer.d.ts.map +1 -1
  158. package/dist/components/message/GrepRenderer.js +5 -8
  159. package/dist/components/message/GrepRenderer.js.map +1 -1
  160. package/dist/components/message/MemoryRenderer.d.ts +1 -0
  161. package/dist/components/message/MemoryRenderer.d.ts.map +1 -1
  162. package/dist/components/message/MemoryRenderer.js +19 -17
  163. package/dist/components/message/MemoryRenderer.js.map +1 -1
  164. package/dist/components/message/MessageList.d.ts +6 -3
  165. package/dist/components/message/MessageList.d.ts.map +1 -1
  166. package/dist/components/message/MessageList.js +68 -13
  167. package/dist/components/message/MessageList.js.map +1 -1
  168. package/dist/components/message/ReadFileRenderer.d.ts.map +1 -1
  169. package/dist/components/message/ReadFileRenderer.js +5 -6
  170. package/dist/components/message/ReadFileRenderer.js.map +1 -1
  171. package/dist/components/message/SubagentActivityMessage.d.ts.map +1 -1
  172. package/dist/components/message/SubagentActivityMessage.js +21 -15
  173. package/dist/components/message/SubagentActivityMessage.js.map +1 -1
  174. package/dist/components/message/WebFetchRenderer.d.ts.map +1 -1
  175. package/dist/components/message/WebFetchRenderer.js +7 -11
  176. package/dist/components/message/WebFetchRenderer.js.map +1 -1
  177. package/dist/components/message/WebSearchRenderer.d.ts.map +1 -1
  178. package/dist/components/message/WebSearchRenderer.js +5 -10
  179. package/dist/components/message/WebSearchRenderer.js.map +1 -1
  180. package/dist/components/message/command-grouping.d.ts +66 -0
  181. package/dist/components/message/command-grouping.d.ts.map +1 -0
  182. package/dist/components/message/command-grouping.js +184 -0
  183. package/dist/components/message/command-grouping.js.map +1 -0
  184. package/dist/components/message/command-message-helpers.d.ts +11 -37
  185. package/dist/components/message/command-message-helpers.d.ts.map +1 -1
  186. package/dist/components/message/command-message-helpers.js +62 -8
  187. package/dist/components/message/command-message-helpers.js.map +1 -1
  188. package/dist/components/message/useCommandVisibility.d.ts.map +1 -1
  189. package/dist/components/message/useCommandVisibility.js +5 -4
  190. package/dist/components/message/useCommandVisibility.js.map +1 -1
  191. package/dist/components/prompt/ApprovalPrompt.d.ts +1 -1
  192. package/dist/components/prompt/ApprovalPrompt.d.ts.map +1 -1
  193. package/dist/components/prompt/ApprovalPrompt.js +286 -156
  194. package/dist/components/prompt/ApprovalPrompt.js.map +1 -1
  195. package/dist/components/prompt/HandoffConfirmationPrompt.d.ts.map +1 -1
  196. package/dist/components/prompt/HandoffConfirmationPrompt.js +3 -2
  197. package/dist/components/prompt/HandoffConfirmationPrompt.js.map +1 -1
  198. package/dist/components/prompt/InputSurgeConfirmationPrompt.d.ts.map +1 -1
  199. package/dist/components/prompt/InputSurgeConfirmationPrompt.js +5 -4
  200. package/dist/components/prompt/InputSurgeConfirmationPrompt.js.map +1 -1
  201. package/dist/components/prompt/LargeUncachedConfirmationPrompt.d.ts.map +1 -1
  202. package/dist/components/prompt/LargeUncachedConfirmationPrompt.js +4 -3
  203. package/dist/components/prompt/LargeUncachedConfirmationPrompt.js.map +1 -1
  204. package/dist/components/prompt/ModeSwitchConfirmationPrompt.d.ts +11 -0
  205. package/dist/components/prompt/ModeSwitchConfirmationPrompt.d.ts.map +1 -0
  206. package/dist/components/prompt/ModeSwitchConfirmationPrompt.js +51 -0
  207. package/dist/components/prompt/ModeSwitchConfirmationPrompt.js.map +1 -0
  208. package/dist/components/prompt/QueuePausedPrompt.d.ts.map +1 -1
  209. package/dist/components/prompt/QueuePausedPrompt.js +15 -8
  210. package/dist/components/prompt/QueuePausedPrompt.js.map +1 -1
  211. package/dist/components/prompt/StandardModeConfirmationPrompt.d.ts.map +1 -1
  212. package/dist/components/prompt/StandardModeConfirmationPrompt.js +3 -2
  213. package/dist/components/prompt/StandardModeConfirmationPrompt.js.map +1 -1
  214. package/dist/components/theme.d.ts +58 -3
  215. package/dist/components/theme.d.ts.map +1 -1
  216. package/dist/components/theme.js +84 -17
  217. package/dist/components/theme.js.map +1 -1
  218. package/dist/contracts/application-stream.d.ts +21 -0
  219. package/dist/contracts/application-stream.d.ts.map +1 -1
  220. package/dist/contracts/conversation.d.ts +24 -1
  221. package/dist/contracts/conversation.d.ts.map +1 -1
  222. package/dist/contracts/conversation.js +8 -0
  223. package/dist/contracts/conversation.js.map +1 -1
  224. package/dist/contracts/streamed-model-turn.d.ts +22 -1
  225. package/dist/contracts/streamed-model-turn.d.ts.map +1 -1
  226. package/dist/core/index.d.ts +9 -0
  227. package/dist/core/index.d.ts.map +1 -0
  228. package/dist/core/index.js +8 -0
  229. package/dist/core/index.js.map +1 -0
  230. package/dist/core/session-runtime.d.ts +10 -0
  231. package/dist/core/session-runtime.d.ts.map +1 -0
  232. package/dist/core/session-runtime.js +9 -0
  233. package/dist/core/session-runtime.js.map +1 -0
  234. package/dist/gateway/assertion.d.ts +41 -0
  235. package/dist/gateway/assertion.d.ts.map +1 -0
  236. package/dist/gateway/assertion.js +168 -0
  237. package/dist/gateway/assertion.js.map +1 -0
  238. package/dist/gateway/contracts.d.ts +141 -0
  239. package/dist/gateway/contracts.d.ts.map +1 -0
  240. package/dist/gateway/contracts.js +24 -0
  241. package/dist/gateway/contracts.js.map +1 -0
  242. package/dist/gateway/dynamic-workspace-registry.d.ts +76 -0
  243. package/dist/gateway/dynamic-workspace-registry.d.ts.map +1 -0
  244. package/dist/gateway/dynamic-workspace-registry.js +403 -0
  245. package/dist/gateway/dynamic-workspace-registry.js.map +1 -0
  246. package/dist/gateway/gateway.d.ts +95 -0
  247. package/dist/gateway/gateway.d.ts.map +1 -0
  248. package/dist/gateway/gateway.js +1960 -0
  249. package/dist/gateway/gateway.js.map +1 -0
  250. package/dist/gateway/index.d.ts +22 -0
  251. package/dist/gateway/index.d.ts.map +1 -0
  252. package/dist/gateway/index.js +22 -0
  253. package/dist/gateway/index.js.map +1 -0
  254. package/dist/gateway/interaction-protocol.d.ts +76 -0
  255. package/dist/gateway/interaction-protocol.d.ts.map +1 -0
  256. package/dist/gateway/interaction-protocol.js +548 -0
  257. package/dist/gateway/interaction-protocol.js.map +1 -0
  258. package/dist/gateway/launcher-seam.d.ts +18 -0
  259. package/dist/gateway/launcher-seam.d.ts.map +1 -0
  260. package/dist/gateway/launcher-seam.js +43 -0
  261. package/dist/gateway/launcher-seam.js.map +1 -0
  262. package/dist/gateway/launcher.d.ts +8 -0
  263. package/dist/gateway/launcher.d.ts.map +1 -0
  264. package/dist/gateway/launcher.js +20 -0
  265. package/dist/gateway/launcher.js.map +1 -0
  266. package/dist/gateway/lifecycle.d.ts +12 -0
  267. package/dist/gateway/lifecycle.d.ts.map +1 -0
  268. package/dist/gateway/lifecycle.js +38 -0
  269. package/dist/gateway/lifecycle.js.map +1 -0
  270. package/dist/gateway/pairing.d.ts +25 -0
  271. package/dist/gateway/pairing.d.ts.map +1 -0
  272. package/dist/gateway/pairing.js +107 -0
  273. package/dist/gateway/pairing.js.map +1 -0
  274. package/dist/gateway/persistence/admission-persistence.d.ts +82 -0
  275. package/dist/gateway/persistence/admission-persistence.d.ts.map +1 -0
  276. package/dist/gateway/persistence/admission-persistence.js +215 -0
  277. package/dist/gateway/persistence/admission-persistence.js.map +1 -0
  278. package/dist/gateway/persistence/contracts.d.ts +94 -0
  279. package/dist/gateway/persistence/contracts.d.ts.map +1 -0
  280. package/dist/gateway/persistence/contracts.js +32 -0
  281. package/dist/gateway/persistence/contracts.js.map +1 -0
  282. package/dist/gateway/persistence/coordinator.d.ts +27 -0
  283. package/dist/gateway/persistence/coordinator.d.ts.map +1 -0
  284. package/dist/gateway/persistence/coordinator.js +194 -0
  285. package/dist/gateway/persistence/coordinator.js.map +1 -0
  286. package/dist/gateway/persistence/event-journal.d.ts +31 -0
  287. package/dist/gateway/persistence/event-journal.d.ts.map +1 -0
  288. package/dist/gateway/persistence/event-journal.js +378 -0
  289. package/dist/gateway/persistence/event-journal.js.map +1 -0
  290. package/dist/gateway/persistence/interaction-checkpoint.d.ts +17 -0
  291. package/dist/gateway/persistence/interaction-checkpoint.d.ts.map +1 -0
  292. package/dist/gateway/persistence/interaction-checkpoint.js +75 -0
  293. package/dist/gateway/persistence/interaction-checkpoint.js.map +1 -0
  294. package/dist/gateway/persistence/projection.d.ts +53 -0
  295. package/dist/gateway/persistence/projection.d.ts.map +1 -0
  296. package/dist/gateway/persistence/projection.js +226 -0
  297. package/dist/gateway/persistence/projection.js.map +1 -0
  298. package/dist/gateway/persistence/retention.d.ts +16 -0
  299. package/dist/gateway/persistence/retention.d.ts.map +1 -0
  300. package/dist/gateway/persistence/retention.js +93 -0
  301. package/dist/gateway/persistence/retention.js.map +1 -0
  302. package/dist/gateway/persistence/session-index.d.ts +34 -0
  303. package/dist/gateway/persistence/session-index.d.ts.map +1 -0
  304. package/dist/gateway/persistence/session-index.js +348 -0
  305. package/dist/gateway/persistence/session-index.js.map +1 -0
  306. package/dist/gateway/persistence/session-persistence.d.ts +68 -0
  307. package/dist/gateway/persistence/session-persistence.d.ts.map +1 -0
  308. package/dist/gateway/persistence/session-persistence.js +165 -0
  309. package/dist/gateway/persistence/session-persistence.js.map +1 -0
  310. package/dist/gateway/persistence/storage.d.ts +13 -0
  311. package/dist/gateway/persistence/storage.d.ts.map +1 -0
  312. package/dist/gateway/persistence/storage.js +87 -0
  313. package/dist/gateway/persistence/storage.js.map +1 -0
  314. package/dist/gateway/replay-ledger.d.ts +30 -0
  315. package/dist/gateway/replay-ledger.d.ts.map +1 -0
  316. package/dist/gateway/replay-ledger.js +83 -0
  317. package/dist/gateway/replay-ledger.js.map +1 -0
  318. package/dist/gateway/runtime-factory.d.ts +93 -0
  319. package/dist/gateway/runtime-factory.d.ts.map +1 -0
  320. package/dist/gateway/runtime-factory.js +242 -0
  321. package/dist/gateway/runtime-factory.js.map +1 -0
  322. package/dist/gateway/safe-log.d.ts +15 -0
  323. package/dist/gateway/safe-log.d.ts.map +1 -0
  324. package/dist/gateway/safe-log.js +108 -0
  325. package/dist/gateway/safe-log.js.map +1 -0
  326. package/dist/gateway/server-session.d.ts +65 -0
  327. package/dist/gateway/server-session.d.ts.map +1 -0
  328. package/dist/gateway/server-session.js +284 -0
  329. package/dist/gateway/server-session.js.map +1 -0
  330. package/dist/gateway/server.d.ts +65 -0
  331. package/dist/gateway/server.d.ts.map +1 -0
  332. package/dist/gateway/server.js +214 -0
  333. package/dist/gateway/server.js.map +1 -0
  334. package/dist/gateway/settings-rpc.d.ts +95 -0
  335. package/dist/gateway/settings-rpc.d.ts.map +1 -0
  336. package/dist/gateway/settings-rpc.js +227 -0
  337. package/dist/gateway/settings-rpc.js.map +1 -0
  338. package/dist/gateway/trusted-clients.d.ts +27 -0
  339. package/dist/gateway/trusted-clients.d.ts.map +1 -0
  340. package/dist/gateway/trusted-clients.js +157 -0
  341. package/dist/gateway/trusted-clients.js.map +1 -0
  342. package/dist/gateway/worker-boundary.d.ts +41 -0
  343. package/dist/gateway/worker-boundary.d.ts.map +1 -0
  344. package/dist/gateway/worker-boundary.js +159 -0
  345. package/dist/gateway/worker-boundary.js.map +1 -0
  346. package/dist/gateway/workspace-admission.d.ts +48 -0
  347. package/dist/gateway/workspace-admission.d.ts.map +1 -0
  348. package/dist/gateway/workspace-admission.js +358 -0
  349. package/dist/gateway/workspace-admission.js.map +1 -0
  350. package/dist/gateway/workspace-boundary-probe.d.ts +18 -0
  351. package/dist/gateway/workspace-boundary-probe.d.ts.map +1 -0
  352. package/dist/gateway/workspace-boundary-probe.js +37 -0
  353. package/dist/gateway/workspace-boundary-probe.js.map +1 -0
  354. package/dist/hooks/conversation-ui-reducer.d.ts +12 -0
  355. package/dist/hooks/conversation-ui-reducer.d.ts.map +1 -1
  356. package/dist/hooks/conversation-ui-reducer.js +12 -1
  357. package/dist/hooks/conversation-ui-reducer.js.map +1 -1
  358. package/dist/hooks/settings-completion-config.d.ts.map +1 -1
  359. package/dist/hooks/settings-completion-config.js +39 -3
  360. package/dist/hooks/settings-completion-config.js.map +1 -1
  361. package/dist/hooks/use-app-commands.d.ts +9 -1
  362. package/dist/hooks/use-app-commands.d.ts.map +1 -1
  363. package/dist/hooks/use-app-commands.js +34 -14
  364. package/dist/hooks/use-app-commands.js.map +1 -1
  365. package/dist/hooks/use-app-keyboard-shortcuts.d.ts +6 -3
  366. package/dist/hooks/use-app-keyboard-shortcuts.d.ts.map +1 -1
  367. package/dist/hooks/use-app-keyboard-shortcuts.js +22 -9
  368. package/dist/hooks/use-app-keyboard-shortcuts.js.map +1 -1
  369. package/dist/hooks/use-conversation.d.ts +9 -0
  370. package/dist/hooks/use-conversation.d.ts.map +1 -1
  371. package/dist/hooks/use-conversation.js +34 -14
  372. package/dist/hooks/use-conversation.js.map +1 -1
  373. package/dist/hooks/use-grok-credit-usage.d.ts +20 -0
  374. package/dist/hooks/use-grok-credit-usage.d.ts.map +1 -0
  375. package/dist/hooks/use-grok-credit-usage.js +48 -0
  376. package/dist/hooks/use-grok-credit-usage.js.map +1 -0
  377. package/dist/hooks/use-opencode-go-usage.d.ts +8 -0
  378. package/dist/hooks/use-opencode-go-usage.d.ts.map +1 -0
  379. package/dist/hooks/use-opencode-go-usage.js +45 -0
  380. package/dist/hooks/use-opencode-go-usage.js.map +1 -0
  381. package/dist/hooks/use-provider-selection.d.ts +10 -0
  382. package/dist/hooks/use-provider-selection.d.ts.map +1 -1
  383. package/dist/hooks/use-provider-selection.js +105 -6
  384. package/dist/hooks/use-provider-selection.js.map +1 -1
  385. package/dist/hooks/use-settings-value-completion.d.ts.map +1 -1
  386. package/dist/hooks/use-settings-value-completion.js +10 -2
  387. package/dist/hooks/use-settings-value-completion.js.map +1 -1
  388. package/dist/hooks/use-shell-mode.d.ts +3 -4
  389. package/dist/hooks/use-shell-mode.d.ts.map +1 -1
  390. package/dist/hooks/use-shell-mode.js +14 -12
  391. package/dist/hooks/use-shell-mode.js.map +1 -1
  392. package/dist/hooks/use-terminal-columns.d.ts +15 -0
  393. package/dist/hooks/use-terminal-columns.d.ts.map +1 -0
  394. package/dist/hooks/use-terminal-columns.js +45 -0
  395. package/dist/hooks/use-terminal-columns.js.map +1 -0
  396. package/dist/lib/agent-client.d.ts +12 -3
  397. package/dist/lib/agent-client.d.ts.map +1 -1
  398. package/dist/lib/agent-client.js +116 -23
  399. package/dist/lib/agent-client.js.map +1 -1
  400. package/dist/lib/agent-configuration.d.ts +5 -0
  401. package/dist/lib/agent-configuration.d.ts.map +1 -1
  402. package/dist/lib/agent-configuration.js +10 -2
  403. package/dist/lib/agent-configuration.js.map +1 -1
  404. package/dist/lib/agent-factory.d.ts +5 -0
  405. package/dist/lib/agent-factory.d.ts.map +1 -1
  406. package/dist/lib/agent-factory.js +36 -11
  407. package/dist/lib/agent-factory.js.map +1 -1
  408. package/dist/lib/editor-impl.d.ts.map +1 -1
  409. package/dist/lib/editor-impl.js +14 -17
  410. package/dist/lib/editor-impl.js.map +1 -1
  411. package/dist/lib/harness-input-idle.d.ts +16 -0
  412. package/dist/lib/harness-input-idle.d.ts.map +1 -0
  413. package/dist/lib/harness-input-idle.js +51 -0
  414. package/dist/lib/harness-input-idle.js.map +1 -0
  415. package/dist/lib/input-owner.d.ts +3 -0
  416. package/dist/lib/input-owner.d.ts.map +1 -1
  417. package/dist/lib/input-owner.js +2 -0
  418. package/dist/lib/input-owner.js.map +1 -1
  419. package/dist/lib/subagent-bridge.d.ts +3 -3
  420. package/dist/lib/subagent-bridge.d.ts.map +1 -1
  421. package/dist/lib/subagent-bridge.js +16 -9
  422. package/dist/lib/subagent-bridge.js.map +1 -1
  423. package/dist/lib/tool-invoke.d.ts +2 -0
  424. package/dist/lib/tool-invoke.d.ts.map +1 -1
  425. package/dist/lib/tool-invoke.js +3 -0
  426. package/dist/lib/tool-invoke.js.map +1 -1
  427. package/dist/non-interactive.d.ts.map +1 -1
  428. package/dist/non-interactive.js +12 -0
  429. package/dist/non-interactive.js.map +1 -1
  430. package/dist/prompts/approval-model.md +22 -0
  431. package/dist/prompts/explorer-delegation-contract.test.ts +22 -0
  432. package/dist/prompts/gpt-5.6.md +4 -3
  433. package/dist/prompts/kimi.md +1 -1
  434. package/dist/prompts/mentor-mode-stub.md +3 -0
  435. package/dist/prompts/orchestrator-mode-stub.md +3 -0
  436. package/dist/prompts/orchestrator.md +10 -1
  437. package/dist/prompts/plan-mode-info.md +3 -3
  438. package/dist/prompts/plan-mode-stub.md +7 -0
  439. package/dist/prompts/prefix-quality.test.ts +112 -0
  440. package/dist/prompts/prompt-constructor.d.ts +2 -0
  441. package/dist/prompts/prompt-constructor.d.ts.map +1 -1
  442. package/dist/prompts/prompt-constructor.js +24 -11
  443. package/dist/prompts/prompt-constructor.js.map +1 -1
  444. package/dist/prompts/prompt-constructor.test.ts +48 -6
  445. package/dist/prompts/prompt-constructor.ts +28 -13
  446. package/dist/prompts/prompt-profiles.d.ts +1 -3
  447. package/dist/prompts/prompt-profiles.d.ts.map +1 -1
  448. package/dist/prompts/prompt-profiles.js +2 -7
  449. package/dist/prompts/prompt-profiles.js.map +1 -1
  450. package/dist/prompts/prompt-profiles.ts +3 -16
  451. package/dist/prompts/session-browser.md +3 -0
  452. package/dist/prompts/subagent-delegation.d.ts +3 -2
  453. package/dist/prompts/subagent-delegation.d.ts.map +1 -1
  454. package/dist/prompts/subagent-delegation.js +9 -13
  455. package/dist/prompts/subagent-delegation.js.map +1 -1
  456. package/dist/prompts/subagent-delegation.ts +9 -13
  457. package/dist/prompts/subagents/explorer.md +7 -1
  458. package/dist/prompts/subagents/librarian.md +2 -0
  459. package/dist/prompts/subagents/mentor.md +2 -0
  460. package/dist/prompts/subagents/worker.md +2 -0
  461. package/dist/providers/ai-sdk-streamed-model.d.ts +5 -0
  462. package/dist/providers/ai-sdk-streamed-model.d.ts.map +1 -1
  463. package/dist/providers/ai-sdk-streamed-model.js +64 -1
  464. package/dist/providers/ai-sdk-streamed-model.js.map +1 -1
  465. package/dist/providers/chained-wire-state.d.ts +13 -2
  466. package/dist/providers/chained-wire-state.d.ts.map +1 -1
  467. package/dist/providers/chained-wire-state.js +17 -10
  468. package/dist/providers/chained-wire-state.js.map +1 -1
  469. package/dist/providers/codex-auth.d.ts +70 -2
  470. package/dist/providers/codex-auth.d.ts.map +1 -1
  471. package/dist/providers/codex-auth.js +168 -2
  472. package/dist/providers/codex-auth.js.map +1 -1
  473. package/dist/providers/codex-responses-model.d.ts +3 -0
  474. package/dist/providers/codex-responses-model.d.ts.map +1 -1
  475. package/dist/providers/codex-responses-model.js +314 -162
  476. package/dist/providers/codex-responses-model.js.map +1 -1
  477. package/dist/providers/codex-turn-converter.d.ts.map +1 -1
  478. package/dist/providers/codex-turn-converter.js +7 -1
  479. package/dist/providers/codex-turn-converter.js.map +1 -1
  480. package/dist/providers/codex.provider.d.ts +25 -2
  481. package/dist/providers/codex.provider.d.ts.map +1 -1
  482. package/dist/providers/codex.provider.js +83 -71
  483. package/dist/providers/codex.provider.js.map +1 -1
  484. package/dist/providers/common/provider-errors.d.ts +20 -0
  485. package/dist/providers/common/provider-errors.d.ts.map +1 -1
  486. package/dist/providers/common/provider-errors.js +35 -0
  487. package/dist/providers/common/provider-errors.js.map +1 -1
  488. package/dist/providers/grok-auth.d.ts +102 -0
  489. package/dist/providers/grok-auth.d.ts.map +1 -0
  490. package/dist/providers/grok-auth.js +318 -0
  491. package/dist/providers/grok-auth.js.map +1 -0
  492. package/dist/providers/grok-credit-usage.d.ts +53 -0
  493. package/dist/providers/grok-credit-usage.d.ts.map +1 -0
  494. package/dist/providers/grok-credit-usage.js +108 -0
  495. package/dist/providers/grok-credit-usage.js.map +1 -0
  496. package/dist/providers/grok.provider.d.ts +24 -0
  497. package/dist/providers/grok.provider.d.ts.map +1 -0
  498. package/dist/providers/grok.provider.js +153 -0
  499. package/dist/providers/grok.provider.js.map +1 -0
  500. package/dist/providers/index.d.ts +1 -0
  501. package/dist/providers/index.d.ts.map +1 -1
  502. package/dist/providers/index.js +1 -0
  503. package/dist/providers/index.js.map +1 -1
  504. package/dist/providers/jwt-claims.d.ts +12 -0
  505. package/dist/providers/jwt-claims.d.ts.map +1 -0
  506. package/dist/providers/jwt-claims.js +25 -0
  507. package/dist/providers/jwt-claims.js.map +1 -0
  508. package/dist/providers/luna-responses-lite-wire-protocol.d.ts +1 -0
  509. package/dist/providers/luna-responses-lite-wire-protocol.d.ts.map +1 -1
  510. package/dist/providers/luna-responses-lite-wire-protocol.js +19 -0
  511. package/dist/providers/luna-responses-lite-wire-protocol.js.map +1 -1
  512. package/dist/providers/model-catalog/catalog.generated.d.ts +360 -232
  513. package/dist/providers/model-catalog/catalog.generated.d.ts.map +1 -1
  514. package/dist/providers/model-catalog/catalog.generated.js +360 -232
  515. package/dist/providers/model-catalog/catalog.generated.js.map +1 -1
  516. package/dist/providers/model-catalog/generate-catalog.d.ts.map +1 -1
  517. package/dist/providers/model-catalog/generate-catalog.js +21 -1
  518. package/dist/providers/model-catalog/generate-catalog.js.map +1 -1
  519. package/dist/providers/oauth-account-store.d.ts +89 -0
  520. package/dist/providers/oauth-account-store.d.ts.map +1 -0
  521. package/dist/providers/oauth-account-store.js +193 -0
  522. package/dist/providers/oauth-account-store.js.map +1 -0
  523. package/dist/providers/oauth-accounts.d.ts +24 -0
  524. package/dist/providers/oauth-accounts.d.ts.map +1 -0
  525. package/dist/providers/oauth-accounts.js +37 -0
  526. package/dist/providers/oauth-accounts.js.map +1 -0
  527. package/dist/providers/oauth-pkce.d.ts +61 -0
  528. package/dist/providers/oauth-pkce.d.ts.map +1 -0
  529. package/dist/providers/oauth-pkce.js +272 -0
  530. package/dist/providers/oauth-pkce.js.map +1 -0
  531. package/dist/providers/oauth-session-account.d.ts +5 -0
  532. package/dist/providers/oauth-session-account.d.ts.map +1 -0
  533. package/dist/providers/oauth-session-account.js +24 -0
  534. package/dist/providers/oauth-session-account.js.map +1 -0
  535. package/dist/providers/openai-chat-completions-model.d.ts.map +1 -1
  536. package/dist/providers/openai-chat-completions-model.js +37 -16
  537. package/dist/providers/openai-chat-completions-model.js.map +1 -1
  538. package/dist/providers/openai-compatible-lazy.js.map +1 -1
  539. package/dist/providers/openai-compatible.provider.d.ts +5 -0
  540. package/dist/providers/openai-compatible.provider.d.ts.map +1 -1
  541. package/dist/providers/openai-compatible.provider.js +40 -3
  542. package/dist/providers/openai-compatible.provider.js.map +1 -1
  543. package/dist/providers/openai-responses-model.d.ts +13 -3
  544. package/dist/providers/openai-responses-model.d.ts.map +1 -1
  545. package/dist/providers/openai-responses-model.js +92 -39
  546. package/dist/providers/openai-responses-model.js.map +1 -1
  547. package/dist/providers/openai.provider.d.ts.map +1 -1
  548. package/dist/providers/openai.provider.js +23 -2
  549. package/dist/providers/openai.provider.js.map +1 -1
  550. package/dist/providers/opencode-go-usage.d.ts +24 -0
  551. package/dist/providers/opencode-go-usage.d.ts.map +1 -0
  552. package/dist/providers/opencode-go-usage.js +37 -0
  553. package/dist/providers/opencode-go-usage.js.map +1 -0
  554. package/dist/providers/opencode-routing.d.ts +2 -0
  555. package/dist/providers/opencode-routing.d.ts.map +1 -1
  556. package/dist/providers/opencode-routing.js +12 -6
  557. package/dist/providers/opencode-routing.js.map +1 -1
  558. package/dist/providers/opencode-transport-discovery.d.ts +18 -0
  559. package/dist/providers/opencode-transport-discovery.d.ts.map +1 -0
  560. package/dist/providers/opencode-transport-discovery.js +115 -0
  561. package/dist/providers/opencode-transport-discovery.js.map +1 -0
  562. package/dist/providers/openrouter.provider.d.ts.map +1 -1
  563. package/dist/providers/openrouter.provider.js +8 -1
  564. package/dist/providers/openrouter.provider.js.map +1 -1
  565. package/dist/providers/provider-opaque-compatibility.d.ts +58 -0
  566. package/dist/providers/provider-opaque-compatibility.d.ts.map +1 -0
  567. package/dist/providers/provider-opaque-compatibility.js +80 -0
  568. package/dist/providers/provider-opaque-compatibility.js.map +1 -0
  569. package/dist/providers/provider-service.d.ts +1 -1
  570. package/dist/providers/provider-service.d.ts.map +1 -1
  571. package/dist/providers/provider-service.js.map +1 -1
  572. package/dist/providers/registry.d.ts +10 -1
  573. package/dist/providers/registry.d.ts.map +1 -1
  574. package/dist/providers/registry.js.map +1 -1
  575. package/dist/providers/responses-websocket-sessions.d.ts +26 -0
  576. package/dist/providers/responses-websocket-sessions.d.ts.map +1 -0
  577. package/dist/providers/responses-websocket-sessions.js +116 -0
  578. package/dist/providers/responses-websocket-sessions.js.map +1 -0
  579. package/dist/providers/retrying-model.d.ts.map +1 -1
  580. package/dist/providers/retrying-model.js +31 -3
  581. package/dist/providers/retrying-model.js.map +1 -1
  582. package/dist/providers/websocket-close-evidence.d.ts +45 -0
  583. package/dist/providers/websocket-close-evidence.d.ts.map +1 -0
  584. package/dist/providers/websocket-close-evidence.js +78 -0
  585. package/dist/providers/websocket-close-evidence.js.map +1 -0
  586. package/dist/providers/websocket-receive-watchdog.d.ts +9 -1
  587. package/dist/providers/websocket-receive-watchdog.d.ts.map +1 -1
  588. package/dist/providers/websocket-receive-watchdog.js +27 -1
  589. package/dist/providers/websocket-receive-watchdog.js.map +1 -1
  590. package/dist/providers/websocket-request-dispatch.d.ts +35 -0
  591. package/dist/providers/websocket-request-dispatch.d.ts.map +1 -0
  592. package/dist/providers/websocket-request-dispatch.js +23 -0
  593. package/dist/providers/websocket-request-dispatch.js.map +1 -0
  594. package/dist/scripts/eval-context-compaction/runner.js +1 -1
  595. package/dist/scripts/eval-context-compaction/runner.js.map +1 -1
  596. package/dist/services/agent-runtime/agent-handle.d.ts.map +1 -1
  597. package/dist/services/agent-runtime/agent-handle.js +8 -5
  598. package/dist/services/agent-runtime/agent-handle.js.map +1 -1
  599. package/dist/services/agent-runtime/agent-runtime.d.ts +1 -1
  600. package/dist/services/agent-runtime/agent-runtime.js +1 -1
  601. package/dist/services/agent-runtime/application-run-loop.d.ts +37 -9
  602. package/dist/services/agent-runtime/application-run-loop.d.ts.map +1 -1
  603. package/dist/services/agent-runtime/application-run-loop.js +512 -219
  604. package/dist/services/agent-runtime/application-run-loop.js.map +1 -1
  605. package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts +6 -1
  606. package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts.map +1 -1
  607. package/dist/services/agent-runtime/context-compaction/local-context-compactor.js +72 -4
  608. package/dist/services/agent-runtime/context-compaction/local-context-compactor.js.map +1 -1
  609. package/dist/services/agent-runtime/executor.d.ts +1 -1
  610. package/dist/services/agent-runtime/executor.d.ts.map +1 -1
  611. package/dist/services/agent-runtime/executor.js +5 -5
  612. package/dist/services/agent-runtime/executor.js.map +1 -1
  613. package/dist/services/agent-runtime/generation-guard.d.ts +39 -24
  614. package/dist/services/agent-runtime/generation-guard.d.ts.map +1 -1
  615. package/dist/services/agent-runtime/generation-guard.js +100 -97
  616. package/dist/services/agent-runtime/generation-guard.js.map +1 -1
  617. package/dist/services/agent-runtime/run-budget.d.ts +131 -0
  618. package/dist/services/agent-runtime/run-budget.d.ts.map +1 -0
  619. package/dist/services/agent-runtime/run-budget.js +272 -0
  620. package/dist/services/agent-runtime/run-budget.js.map +1 -0
  621. package/dist/services/agent-runtime/tool-invocation-context.d.ts +12 -0
  622. package/dist/services/agent-runtime/tool-invocation-context.d.ts.map +1 -1
  623. package/dist/services/agent-runtime/tool-invocation-context.js.map +1 -1
  624. package/dist/services/agent-runtime/types.d.ts +5 -4
  625. package/dist/services/agent-runtime/types.d.ts.map +1 -1
  626. package/dist/services/agent-stream.d.ts.map +1 -1
  627. package/dist/services/agent-stream.js +3 -1
  628. package/dist/services/agent-stream.js.map +1 -1
  629. package/dist/services/approval/approval-decision-executor.d.ts +6 -1
  630. package/dist/services/approval/approval-decision-executor.d.ts.map +1 -1
  631. package/dist/services/approval/approval-decision-executor.js +15 -3
  632. package/dist/services/approval/approval-decision-executor.js.map +1 -1
  633. package/dist/services/approval/approval-decision-policy.d.ts.map +1 -1
  634. package/dist/services/approval/approval-decision-policy.js +3 -0
  635. package/dist/services/approval/approval-decision-policy.js.map +1 -1
  636. package/dist/services/approval/approval-flow-coordinator.d.ts +2 -0
  637. package/dist/services/approval/approval-flow-coordinator.d.ts.map +1 -1
  638. package/dist/services/approval/approval-flow-coordinator.js +14 -2
  639. package/dist/services/approval/approval-flow-coordinator.js.map +1 -1
  640. package/dist/services/approval/background-subagent-approval-controller.d.ts +3 -1
  641. package/dist/services/approval/background-subagent-approval-controller.d.ts.map +1 -1
  642. package/dist/services/approval/background-subagent-approval-controller.js +7 -4
  643. package/dist/services/approval/background-subagent-approval-controller.js.map +1 -1
  644. package/dist/services/approval/shell-auto-approval-resolver.d.ts +5 -0
  645. package/dist/services/approval/shell-auto-approval-resolver.d.ts.map +1 -1
  646. package/dist/services/approval/shell-auto-approval-resolver.js +8 -0
  647. package/dist/services/approval/shell-auto-approval-resolver.js.map +1 -1
  648. package/dist/services/approval/tool-approval-batch-coordinator.d.ts.map +1 -1
  649. package/dist/services/approval/tool-approval-batch-coordinator.js +20 -11
  650. package/dist/services/approval/tool-approval-batch-coordinator.js.map +1 -1
  651. package/dist/services/approval/tool-ownership-registry.d.ts +5 -1
  652. package/dist/services/approval/tool-ownership-registry.d.ts.map +1 -1
  653. package/dist/services/approval/tool-ownership-registry.js +5 -22
  654. package/dist/services/approval/tool-ownership-registry.js.map +1 -1
  655. package/dist/services/background-task-activity.d.ts +79 -0
  656. package/dist/services/background-task-activity.d.ts.map +1 -0
  657. package/dist/services/background-task-activity.js +34 -0
  658. package/dist/services/background-task-activity.js.map +1 -0
  659. package/dist/services/command-message-streaming.d.ts +4 -2
  660. package/dist/services/command-message-streaming.d.ts.map +1 -1
  661. package/dist/services/command-message-streaming.js +2 -2
  662. package/dist/services/command-message-streaming.js.map +1 -1
  663. package/dist/services/conversation/conversation-adapter-factory.d.ts +6 -2
  664. package/dist/services/conversation/conversation-adapter-factory.d.ts.map +1 -1
  665. package/dist/services/conversation/conversation-adapter-factory.js +5 -1
  666. package/dist/services/conversation/conversation-adapter-factory.js.map +1 -1
  667. package/dist/services/conversation/conversation-adapter.d.ts +53 -10
  668. package/dist/services/conversation/conversation-adapter.d.ts.map +1 -1
  669. package/dist/services/conversation/conversation-adapter.js +252 -43
  670. package/dist/services/conversation/conversation-adapter.js.map +1 -1
  671. package/dist/services/conversation/conversation-admission-workflow.d.ts +3 -2
  672. package/dist/services/conversation/conversation-admission-workflow.d.ts.map +1 -1
  673. package/dist/services/conversation/conversation-admission-workflow.js +6 -1
  674. package/dist/services/conversation/conversation-admission-workflow.js.map +1 -1
  675. package/dist/services/conversation/conversation-decoder.d.ts.map +1 -1
  676. package/dist/services/conversation/conversation-decoder.js +4 -0
  677. package/dist/services/conversation/conversation-decoder.js.map +1 -1
  678. package/dist/services/conversation/conversation-events.d.ts +97 -3
  679. package/dist/services/conversation/conversation-events.d.ts.map +1 -1
  680. package/dist/services/conversation/conversation-orchestrator.d.ts +14 -1
  681. package/dist/services/conversation/conversation-orchestrator.d.ts.map +1 -1
  682. package/dist/services/conversation/conversation-orchestrator.js +245 -22
  683. package/dist/services/conversation/conversation-orchestrator.js.map +1 -1
  684. package/dist/services/conversation/conversation-orchestrator.types.d.ts +6 -1
  685. package/dist/services/conversation/conversation-orchestrator.types.d.ts.map +1 -1
  686. package/dist/services/conversation/conversation-persistence.d.ts +60 -3
  687. package/dist/services/conversation/conversation-persistence.d.ts.map +1 -1
  688. package/dist/services/conversation/conversation-persistence.js +221 -16
  689. package/dist/services/conversation/conversation-persistence.js.map +1 -1
  690. package/dist/services/conversation/conversation-replay.d.ts.map +1 -1
  691. package/dist/services/conversation/conversation-replay.js +27 -0
  692. package/dist/services/conversation/conversation-replay.js.map +1 -1
  693. package/dist/services/conversation/conversation-result-builder.d.ts +6 -2
  694. package/dist/services/conversation/conversation-result-builder.d.ts.map +1 -1
  695. package/dist/services/conversation/conversation-result-builder.js +60 -1
  696. package/dist/services/conversation/conversation-result-builder.js.map +1 -1
  697. package/dist/services/conversation/conversation-runtime-factory.d.ts +9 -1
  698. package/dist/services/conversation/conversation-runtime-factory.d.ts.map +1 -1
  699. package/dist/services/conversation/conversation-runtime-factory.js +5 -1
  700. package/dist/services/conversation/conversation-runtime-factory.js.map +1 -1
  701. package/dist/services/conversation/conversation-service.d.ts +32 -3
  702. package/dist/services/conversation/conversation-service.d.ts.map +1 -1
  703. package/dist/services/conversation/conversation-service.js +122 -32
  704. package/dist/services/conversation/conversation-service.js.map +1 -1
  705. package/dist/services/conversation/conversation-state-projector.d.ts +2 -1
  706. package/dist/services/conversation/conversation-state-projector.d.ts.map +1 -1
  707. package/dist/services/conversation/conversation-state-projector.js +31 -3
  708. package/dist/services/conversation/conversation-state-projector.js.map +1 -1
  709. package/dist/services/conversation/run-item-normalizer.d.ts.map +1 -1
  710. package/dist/services/conversation/run-item-normalizer.js +24 -1
  711. package/dist/services/conversation/run-item-normalizer.js.map +1 -1
  712. package/dist/services/conversation/session-audit.d.ts +70 -0
  713. package/dist/services/conversation/session-audit.d.ts.map +1 -0
  714. package/dist/services/conversation/session-audit.js +164 -0
  715. package/dist/services/conversation/session-audit.js.map +1 -0
  716. package/dist/services/conversation/session-browser.d.ts +46 -0
  717. package/dist/services/conversation/session-browser.d.ts.map +1 -0
  718. package/dist/services/conversation/session-browser.js +380 -0
  719. package/dist/services/conversation/session-browser.js.map +1 -0
  720. package/dist/services/conversation-agent-client.d.ts +21 -2
  721. package/dist/services/conversation-agent-client.d.ts.map +1 -1
  722. package/dist/services/cost/model-cost.d.ts +13 -1
  723. package/dist/services/cost/model-cost.d.ts.map +1 -1
  724. package/dist/services/cost/model-cost.js +59 -0
  725. package/dist/services/cost/model-cost.js.map +1 -1
  726. package/dist/services/cost/subscription-providers.d.ts +2 -0
  727. package/dist/services/cost/subscription-providers.d.ts.map +1 -0
  728. package/dist/services/cost/subscription-providers.js +14 -0
  729. package/dist/services/cost/subscription-providers.js.map +1 -0
  730. package/dist/services/grok/grok-credit-usage-service.d.ts +62 -0
  731. package/dist/services/grok/grok-credit-usage-service.d.ts.map +1 -0
  732. package/dist/services/grok/grok-credit-usage-service.js +137 -0
  733. package/dist/services/grok/grok-credit-usage-service.js.map +1 -0
  734. package/dist/services/history-service.d.ts +9 -0
  735. package/dist/services/history-service.d.ts.map +1 -1
  736. package/dist/services/history-service.js +49 -2
  737. package/dist/services/history-service.js.map +1 -1
  738. package/dist/services/hooks/hook-composition.d.ts +17 -0
  739. package/dist/services/hooks/hook-composition.d.ts.map +1 -0
  740. package/dist/services/hooks/hook-composition.js +19 -0
  741. package/dist/services/hooks/hook-composition.js.map +1 -0
  742. package/dist/services/input-surge-approval.d.ts +21 -0
  743. package/dist/services/input-surge-approval.d.ts.map +1 -0
  744. package/dist/services/input-surge-approval.js +42 -0
  745. package/dist/services/input-surge-approval.js.map +1 -0
  746. package/dist/services/large-uncached-input-guard.js +4 -4
  747. package/dist/services/large-uncached-input-guard.js.map +1 -1
  748. package/dist/services/logging/assistant-turn-journal.d.ts +15 -0
  749. package/dist/services/logging/assistant-turn-journal.d.ts.map +1 -1
  750. package/dist/services/logging/assistant-turn-journal.js +27 -0
  751. package/dist/services/logging/assistant-turn-journal.js.map +1 -1
  752. package/dist/services/logging/conversation-log-events.d.ts +35 -1
  753. package/dist/services/logging/conversation-log-events.d.ts.map +1 -1
  754. package/dist/services/logging/conversation-log-events.js +17 -0
  755. package/dist/services/logging/conversation-log-events.js.map +1 -1
  756. package/dist/services/logging/conversation-log-writer.d.ts +8 -1
  757. package/dist/services/logging/conversation-log-writer.d.ts.map +1 -1
  758. package/dist/services/logging/conversation-log-writer.js +145 -10
  759. package/dist/services/logging/conversation-log-writer.js.map +1 -1
  760. package/dist/services/logging/conversation-logger.d.ts.map +1 -1
  761. package/dist/services/logging/conversation-logger.js +18 -0
  762. package/dist/services/logging/conversation-logger.js.map +1 -1
  763. package/dist/services/logging/logging-service.d.ts +6 -6
  764. package/dist/services/logging/logging-service.d.ts.map +1 -1
  765. package/dist/services/logging/logging-service.js.map +1 -1
  766. package/dist/services/logging/provider-traffic.d.ts +17 -1
  767. package/dist/services/logging/provider-traffic.d.ts.map +1 -1
  768. package/dist/services/logging/provider-traffic.js +283 -139
  769. package/dist/services/logging/provider-traffic.js.map +1 -1
  770. package/dist/services/memory/memory-capabilities.d.ts.map +1 -1
  771. package/dist/services/memory/memory-capabilities.js +22 -3
  772. package/dist/services/memory/memory-capabilities.js.map +1 -1
  773. package/dist/services/memory/memory-search.d.ts +16 -0
  774. package/dist/services/memory/memory-search.d.ts.map +1 -0
  775. package/dist/services/memory/memory-search.js +55 -0
  776. package/dist/services/memory/memory-search.js.map +1 -0
  777. package/dist/services/memory/memory-store.d.ts +12 -0
  778. package/dist/services/memory/memory-store.d.ts.map +1 -1
  779. package/dist/services/memory/memory-store.js +14 -35
  780. package/dist/services/memory/memory-store.js.map +1 -1
  781. package/dist/services/mode-notices.d.ts +12 -6
  782. package/dist/services/mode-notices.d.ts.map +1 -1
  783. package/dist/services/mode-notices.js +51 -4
  784. package/dist/services/mode-notices.js.map +1 -1
  785. package/dist/services/model-service.d.ts +2 -2
  786. package/dist/services/model-service.d.ts.map +1 -1
  787. package/dist/services/model-service.js.map +1 -1
  788. package/dist/services/queue/queue-controller.d.ts +14 -1
  789. package/dist/services/queue/queue-controller.d.ts.map +1 -1
  790. package/dist/services/queue/queue-controller.js +51 -6
  791. package/dist/services/queue/queue-controller.js.map +1 -1
  792. package/dist/services/retry/chain-recovery-fingerprint.d.ts +10 -0
  793. package/dist/services/retry/chain-recovery-fingerprint.d.ts.map +1 -0
  794. package/dist/services/retry/chain-recovery-fingerprint.js +23 -0
  795. package/dist/services/retry/chain-recovery-fingerprint.js.map +1 -0
  796. package/dist/services/retry/in-loop-model-retry.d.ts +12 -0
  797. package/dist/services/retry/in-loop-model-retry.d.ts.map +1 -0
  798. package/dist/services/retry/in-loop-model-retry.js +115 -0
  799. package/dist/services/retry/in-loop-model-retry.js.map +1 -0
  800. package/dist/services/retry/recovery-executor.d.ts.map +1 -1
  801. package/dist/services/retry/recovery-executor.js +2 -0
  802. package/dist/services/retry/recovery-executor.js.map +1 -1
  803. package/dist/services/retry/recovery-policy.d.ts.map +1 -1
  804. package/dist/services/retry/recovery-policy.js +4 -0
  805. package/dist/services/retry/recovery-policy.js.map +1 -1
  806. package/dist/services/retry/retry-classifier.d.ts.map +1 -1
  807. package/dist/services/retry/retry-classifier.js +42 -4
  808. package/dist/services/retry/retry-classifier.js.map +1 -1
  809. package/dist/services/retry/retry-contracts.d.ts +14 -0
  810. package/dist/services/retry/retry-contracts.d.ts.map +1 -1
  811. package/dist/services/retry/retry-error-classification.d.ts +17 -3
  812. package/dist/services/retry/retry-error-classification.d.ts.map +1 -1
  813. package/dist/services/retry/retry-error-classification.js +58 -13
  814. package/dist/services/retry/retry-error-classification.js.map +1 -1
  815. package/dist/services/retry/retry-errors.d.ts +4 -0
  816. package/dist/services/retry/retry-errors.d.ts.map +1 -1
  817. package/dist/services/retry/retry-errors.js +7 -0
  818. package/dist/services/retry/retry-errors.js.map +1 -1
  819. package/dist/services/retry/retry-event-presenter.d.ts.map +1 -1
  820. package/dist/services/retry/retry-event-presenter.js +20 -0
  821. package/dist/services/retry/retry-event-presenter.js.map +1 -1
  822. package/dist/services/retry/upstream-retry-policy.d.ts.map +1 -1
  823. package/dist/services/retry/upstream-retry-policy.js +40 -7
  824. package/dist/services/retry/upstream-retry-policy.js.map +1 -1
  825. package/dist/services/runtime-setting-router.d.ts.map +1 -1
  826. package/dist/services/runtime-setting-router.js +13 -2
  827. package/dist/services/runtime-setting-router.js.map +1 -1
  828. package/dist/services/service-interfaces.d.ts +96 -13
  829. package/dist/services/service-interfaces.d.ts.map +1 -1
  830. package/dist/services/session/background-check-in-scheduler.d.ts +44 -0
  831. package/dist/services/session/background-check-in-scheduler.d.ts.map +1 -0
  832. package/dist/services/session/background-check-in-scheduler.js +88 -0
  833. package/dist/services/session/background-check-in-scheduler.js.map +1 -0
  834. package/dist/services/session/background-task-control.d.ts +6 -0
  835. package/dist/services/session/background-task-control.d.ts.map +1 -1
  836. package/dist/services/session/background-task-control.js +35 -7
  837. package/dist/services/session/background-task-control.js.map +1 -1
  838. package/dist/services/session/background-task-liveness.d.ts +2 -18
  839. package/dist/services/session/background-task-liveness.d.ts.map +1 -1
  840. package/dist/services/session/background-task-liveness.js +7 -22
  841. package/dist/services/session/background-task-liveness.js.map +1 -1
  842. package/dist/services/session/continuation-plan-applier.d.ts.map +1 -1
  843. package/dist/services/session/continuation-plan-applier.js +23 -0
  844. package/dist/services/session/continuation-plan-applier.js.map +1 -1
  845. package/dist/services/session/continuation-recovery-handler.d.ts +2 -0
  846. package/dist/services/session/continuation-recovery-handler.d.ts.map +1 -1
  847. package/dist/services/session/continuation-recovery-handler.js +7 -1
  848. package/dist/services/session/continuation-recovery-handler.js.map +1 -1
  849. package/dist/services/session/initial-input-preparer.d.ts +2 -1
  850. package/dist/services/session/initial-input-preparer.d.ts.map +1 -1
  851. package/dist/services/session/initial-input-preparer.js +3 -1
  852. package/dist/services/session/initial-input-preparer.js.map +1 -1
  853. package/dist/services/session/initial-turn-recovery-handler.d.ts +1 -0
  854. package/dist/services/session/initial-turn-recovery-handler.d.ts.map +1 -1
  855. package/dist/services/session/initial-turn-recovery-handler.js +12 -2
  856. package/dist/services/session/initial-turn-recovery-handler.js.map +1 -1
  857. package/dist/services/session/repetition-detector.d.ts +0 -4
  858. package/dist/services/session/repetition-detector.d.ts.map +1 -1
  859. package/dist/services/session/repetition-detector.js +0 -7
  860. package/dist/services/session/repetition-detector.js.map +1 -1
  861. package/dist/services/session/session-client-factory.d.ts +3 -1
  862. package/dist/services/session/session-client-factory.d.ts.map +1 -1
  863. package/dist/services/session/session-client-factory.js +2 -2
  864. package/dist/services/session/session-client-factory.js.map +1 -1
  865. package/dist/services/session/session-composition.d.ts +9 -2
  866. package/dist/services/session/session-composition.d.ts.map +1 -1
  867. package/dist/services/session/session-composition.js +151 -37
  868. package/dist/services/session/session-composition.js.map +1 -1
  869. package/dist/services/session/session-lifecycle.d.ts +8 -0
  870. package/dist/services/session/session-lifecycle.d.ts.map +1 -1
  871. package/dist/services/session/session-lifecycle.js +4 -0
  872. package/dist/services/session/session-lifecycle.js.map +1 -1
  873. package/dist/services/session/session-stream-processor.d.ts +2 -0
  874. package/dist/services/session/session-stream-processor.d.ts.map +1 -1
  875. package/dist/services/session/session-stream-processor.js +9 -15
  876. package/dist/services/session/session-stream-processor.js.map +1 -1
  877. package/dist/services/session/terminal-result-collector.d.ts +2 -2
  878. package/dist/services/session/terminal-result-collector.d.ts.map +1 -1
  879. package/dist/services/session/terminal-result-collector.js +2 -1
  880. package/dist/services/session/terminal-result-collector.js.map +1 -1
  881. package/dist/services/session/turn-attempt-factory.d.ts +3 -1
  882. package/dist/services/session/turn-attempt-factory.d.ts.map +1 -1
  883. package/dist/services/session/turn-attempt-factory.js +1 -0
  884. package/dist/services/session/turn-attempt-factory.js.map +1 -1
  885. package/dist/services/session/turn-attempt.d.ts +3 -0
  886. package/dist/services/session/turn-attempt.d.ts.map +1 -1
  887. package/dist/services/session/turn-attempt.js +5 -0
  888. package/dist/services/session/turn-attempt.js.map +1 -1
  889. package/dist/services/session/turn-coordinator.d.ts +2 -2
  890. package/dist/services/session/turn-coordinator.d.ts.map +1 -1
  891. package/dist/services/session/turn-coordinator.js +31 -6
  892. package/dist/services/session/turn-coordinator.js.map +1 -1
  893. package/dist/services/session/turn-workflow.d.ts +4 -1
  894. package/dist/services/session/turn-workflow.d.ts.map +1 -1
  895. package/dist/services/session/turn-workflow.js +52 -8
  896. package/dist/services/session/turn-workflow.js.map +1 -1
  897. package/dist/services/settings/settings-persistence.d.ts +33 -0
  898. package/dist/services/settings/settings-persistence.d.ts.map +1 -1
  899. package/dist/services/settings/settings-persistence.js +102 -4
  900. package/dist/services/settings/settings-persistence.js.map +1 -1
  901. package/dist/services/settings/settings-schema.d.ts +92 -0
  902. package/dist/services/settings/settings-schema.d.ts.map +1 -1
  903. package/dist/services/settings/settings-schema.js +119 -9
  904. package/dist/services/settings/settings-schema.js.map +1 -1
  905. package/dist/services/settings/settings-service.d.ts +66 -3
  906. package/dist/services/settings/settings-service.d.ts.map +1 -1
  907. package/dist/services/settings/settings-service.js +211 -28
  908. package/dist/services/settings/settings-service.js.map +1 -1
  909. package/dist/services/settings/settings-service.mock.d.ts +1 -1
  910. package/dist/services/settings/settings-service.mock.d.ts.map +1 -1
  911. package/dist/services/settings/settings-service.mock.js +3 -6
  912. package/dist/services/settings/settings-service.mock.js.map +1 -1
  913. package/dist/services/settings/settings-sources.d.ts.map +1 -1
  914. package/dist/services/settings/settings-sources.js +21 -0
  915. package/dist/services/settings/settings-sources.js.map +1 -1
  916. package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts +28 -0
  917. package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts.map +1 -0
  918. package/dist/services/settings/test-helpers/settings-consumer-inventory.js +171 -0
  919. package/dist/services/settings/test-helpers/settings-consumer-inventory.js.map +1 -0
  920. package/dist/services/shell/background-shell-registry.d.ts +10 -0
  921. package/dist/services/shell/background-shell-registry.d.ts.map +1 -1
  922. package/dist/services/shell/background-shell-registry.js +9 -1
  923. package/dist/services/shell/background-shell-registry.js.map +1 -1
  924. package/dist/services/shell/background-shell-watches.d.ts +28 -3
  925. package/dist/services/shell/background-shell-watches.d.ts.map +1 -1
  926. package/dist/services/shell/background-shell-watches.js +41 -9
  927. package/dist/services/shell/background-shell-watches.js.map +1 -1
  928. package/dist/services/shell/shell-interaction-session.d.ts +4 -5
  929. package/dist/services/shell/shell-interaction-session.d.ts.map +1 -1
  930. package/dist/services/shell/shell-interaction-session.js +8 -20
  931. package/dist/services/shell/shell-interaction-session.js.map +1 -1
  932. package/dist/services/ssh-service.d.ts +81 -9
  933. package/dist/services/ssh-service.d.ts.map +1 -1
  934. package/dist/services/ssh-service.js +211 -37
  935. package/dist/services/ssh-service.js.map +1 -1
  936. package/dist/services/stream-event-processor.d.ts +2 -0
  937. package/dist/services/stream-event-processor.d.ts.map +1 -1
  938. package/dist/services/stream-event-processor.js +32 -7
  939. package/dist/services/stream-event-processor.js.map +1 -1
  940. package/dist/services/subagents/execution-runner.d.ts +1 -1
  941. package/dist/services/subagents/execution-runner.d.ts.map +1 -1
  942. package/dist/services/subagents/execution-runner.js +34 -22
  943. package/dist/services/subagents/execution-runner.js.map +1 -1
  944. package/dist/services/subagents/foreground-subagent-lease.d.ts +11 -1
  945. package/dist/services/subagents/foreground-subagent-lease.d.ts.map +1 -1
  946. package/dist/services/subagents/foreground-subagent-lease.js +10 -1
  947. package/dist/services/subagents/foreground-subagent-lease.js.map +1 -1
  948. package/dist/services/subagents/mentor-runner.d.ts +1 -1
  949. package/dist/services/subagents/mentor-runner.d.ts.map +1 -1
  950. package/dist/services/subagents/mentor-runner.js +12 -3
  951. package/dist/services/subagents/mentor-runner.js.map +1 -1
  952. package/dist/services/subagents/nested-runner.d.ts +11 -1
  953. package/dist/services/subagents/nested-runner.d.ts.map +1 -1
  954. package/dist/services/subagents/nested-runner.js +79 -11
  955. package/dist/services/subagents/nested-runner.js.map +1 -1
  956. package/dist/services/subagents/runtime.d.ts.map +1 -1
  957. package/dist/services/subagents/runtime.js +7 -0
  958. package/dist/services/subagents/runtime.js.map +1 -1
  959. package/dist/services/subagents/subagent-async-registry.d.ts +4 -0
  960. package/dist/services/subagents/subagent-async-registry.d.ts.map +1 -1
  961. package/dist/services/subagents/subagent-async-registry.js +81 -17
  962. package/dist/services/subagents/subagent-async-registry.js.map +1 -1
  963. package/dist/services/subagents/subagent-manager.d.ts +1 -1
  964. package/dist/services/subagents/subagent-manager.d.ts.map +1 -1
  965. package/dist/services/subagents/subagent-manager.js +4 -4
  966. package/dist/services/subagents/subagent-manager.js.map +1 -1
  967. package/dist/services/subagents/subagent-notification-store.d.ts +47 -2
  968. package/dist/services/subagents/subagent-notification-store.d.ts.map +1 -1
  969. package/dist/services/subagents/subagent-notification-store.js +33 -0
  970. package/dist/services/subagents/subagent-notification-store.js.map +1 -1
  971. package/dist/services/subagents/subagent-run-control.d.ts +9 -1
  972. package/dist/services/subagents/subagent-run-control.d.ts.map +1 -1
  973. package/dist/services/subagents/subagent-run-control.js +12 -13
  974. package/dist/services/subagents/subagent-run-control.js.map +1 -1
  975. package/dist/services/subagents/tool-policy.d.ts.map +1 -1
  976. package/dist/services/subagents/tool-policy.js +20 -7
  977. package/dist/services/subagents/tool-policy.js.map +1 -1
  978. package/dist/services/subagents/types.d.ts +25 -2
  979. package/dist/services/subagents/types.d.ts.map +1 -1
  980. package/dist/services/subagents/types.js.map +1 -1
  981. package/dist/services/subagents/utils.d.ts +5 -1
  982. package/dist/services/subagents/utils.d.ts.map +1 -1
  983. package/dist/services/subagents/utils.js +33 -2
  984. package/dist/services/subagents/utils.js.map +1 -1
  985. package/dist/services/tool-execution-ledger.d.ts.map +1 -1
  986. package/dist/services/tool-execution-ledger.js +5 -1
  987. package/dist/services/tool-execution-ledger.js.map +1 -1
  988. package/dist/services/workspace/active-workspace-root.d.ts +6 -0
  989. package/dist/services/workspace/active-workspace-root.d.ts.map +1 -1
  990. package/dist/services/workspace/active-workspace-root.js +22 -0
  991. package/dist/services/workspace/active-workspace-root.js.map +1 -1
  992. package/dist/test-helpers/ink-testing.d.ts.map +1 -1
  993. package/dist/test-helpers/ink-testing.js +4 -1
  994. package/dist/test-helpers/ink-testing.js.map +1 -1
  995. package/dist/test-helpers/terminal-e2e.d.ts.map +1 -1
  996. package/dist/test-helpers/terminal-e2e.js +12 -2
  997. package/dist/test-helpers/terminal-e2e.js.map +1 -1
  998. package/dist/tools/agent/activate-skill.d.ts.map +1 -1
  999. package/dist/tools/agent/activate-skill.js +2 -2
  1000. package/dist/tools/agent/activate-skill.js.map +1 -1
  1001. package/dist/tools/agent/ask-mentor.d.ts.map +1 -1
  1002. package/dist/tools/agent/ask-mentor.js +2 -2
  1003. package/dist/tools/agent/ask-mentor.js.map +1 -1
  1004. package/dist/tools/agent/ask-user-constants.d.ts +2 -2
  1005. package/dist/tools/agent/ask-user-constants.d.ts.map +1 -1
  1006. package/dist/tools/agent/ask-user-constants.js +1 -1
  1007. package/dist/tools/agent/ask-user-constants.js.map +1 -1
  1008. package/dist/tools/agent/ask-user.d.ts.map +1 -1
  1009. package/dist/tools/agent/ask-user.js +2 -0
  1010. package/dist/tools/agent/ask-user.js.map +1 -1
  1011. package/dist/tools/agent/run-subagent-async.d.ts +2 -11
  1012. package/dist/tools/agent/run-subagent-async.d.ts.map +1 -1
  1013. package/dist/tools/agent/run-subagent-async.js +8 -2
  1014. package/dist/tools/agent/run-subagent-async.js.map +1 -1
  1015. package/dist/tools/agent/run-subagent.d.ts.map +1 -1
  1016. package/dist/tools/agent/run-subagent.js +44 -29
  1017. package/dist/tools/agent/run-subagent.js.map +1 -1
  1018. package/dist/tools/file/apply-patch.d.ts +2 -0
  1019. package/dist/tools/file/apply-patch.d.ts.map +1 -1
  1020. package/dist/tools/file/apply-patch.js +58 -14
  1021. package/dist/tools/file/apply-patch.js.map +1 -1
  1022. package/dist/tools/file/code-context.d.ts +5 -0
  1023. package/dist/tools/file/code-context.d.ts.map +1 -1
  1024. package/dist/tools/file/code-context.js +18 -6
  1025. package/dist/tools/file/code-context.js.map +1 -1
  1026. package/dist/tools/file/create-file.d.ts.map +1 -1
  1027. package/dist/tools/file/create-file.js +11 -5
  1028. package/dist/tools/file/create-file.js.map +1 -1
  1029. package/dist/tools/file/edit-healing.d.ts +7 -0
  1030. package/dist/tools/file/edit-healing.d.ts.map +1 -1
  1031. package/dist/tools/file/edit-healing.js +7 -7
  1032. package/dist/tools/file/edit-healing.js.map +1 -1
  1033. package/dist/tools/file/glob.d.ts +3 -0
  1034. package/dist/tools/file/glob.d.ts.map +1 -1
  1035. package/dist/tools/file/glob.js +9 -3
  1036. package/dist/tools/file/glob.js.map +1 -1
  1037. package/dist/tools/file/grep.d.ts +5 -0
  1038. package/dist/tools/file/grep.d.ts.map +1 -1
  1039. package/dist/tools/file/grep.js +10 -6
  1040. package/dist/tools/file/grep.js.map +1 -1
  1041. package/dist/tools/file/patch-healing.d.ts +31 -0
  1042. package/dist/tools/file/patch-healing.d.ts.map +1 -0
  1043. package/dist/tools/file/patch-healing.js +231 -0
  1044. package/dist/tools/file/patch-healing.js.map +1 -0
  1045. package/dist/tools/file/read-file.d.ts +3 -0
  1046. package/dist/tools/file/read-file.d.ts.map +1 -1
  1047. package/dist/tools/file/read-file.js +9 -3
  1048. package/dist/tools/file/read-file.js.map +1 -1
  1049. package/dist/tools/file/search-replace.d.ts.map +1 -1
  1050. package/dist/tools/file/search-replace.js +24 -6
  1051. package/dist/tools/file/search-replace.js.map +1 -1
  1052. package/dist/tools/format-helpers.d.ts +6 -0
  1053. package/dist/tools/format-helpers.d.ts.map +1 -1
  1054. package/dist/tools/format-helpers.js +23 -0
  1055. package/dist/tools/format-helpers.js.map +1 -1
  1056. package/dist/tools/memory/memory-tools.d.ts.map +1 -1
  1057. package/dist/tools/memory/memory-tools.js +324 -61
  1058. package/dist/tools/memory/memory-tools.js.map +1 -1
  1059. package/dist/tools/session-browser/session-browser-tools.d.ts +4 -0
  1060. package/dist/tools/session-browser/session-browser-tools.d.ts.map +1 -0
  1061. package/dist/tools/session-browser/session-browser-tools.js +47 -0
  1062. package/dist/tools/session-browser/session-browser-tools.js.map +1 -0
  1063. package/dist/tools/system/shell.d.ts +16 -1
  1064. package/dist/tools/system/shell.d.ts.map +1 -1
  1065. package/dist/tools/system/shell.js +97 -25
  1066. package/dist/tools/system/shell.js.map +1 -1
  1067. package/dist/tools/types.d.ts +8 -0
  1068. package/dist/tools/types.d.ts.map +1 -1
  1069. package/dist/tools/types.js.map +1 -1
  1070. package/dist/tools/web/web-fetch.d.ts.map +1 -1
  1071. package/dist/tools/web/web-fetch.js +2 -2
  1072. package/dist/tools/web/web-fetch.js.map +1 -1
  1073. package/dist/tools/web/web-search.d.ts.map +1 -1
  1074. package/dist/tools/web/web-search.js +2 -2
  1075. package/dist/tools/web/web-search.js.map +1 -1
  1076. package/dist/types/message.d.ts +1 -1
  1077. package/dist/types/message.d.ts.map +1 -1
  1078. package/dist/utils/ai/provider-credentials.d.ts +1 -1
  1079. package/dist/utils/ai/provider-credentials.d.ts.map +1 -1
  1080. package/dist/utils/ai/provider-credentials.js +18 -2
  1081. package/dist/utils/ai/provider-credentials.js.map +1 -1
  1082. package/dist/utils/ai/token-usage.d.ts +3 -1
  1083. package/dist/utils/ai/token-usage.d.ts.map +1 -1
  1084. package/dist/utils/ai/token-usage.js +7 -2
  1085. package/dist/utils/ai/token-usage.js.map +1 -1
  1086. package/dist/utils/apply-diff.d.ts.map +1 -1
  1087. package/dist/utils/apply-diff.js +8 -0
  1088. package/dist/utils/apply-diff.js.map +1 -1
  1089. package/dist/utils/busy-turn-guard.d.ts +17 -0
  1090. package/dist/utils/busy-turn-guard.d.ts.map +1 -0
  1091. package/dist/utils/busy-turn-guard.js +24 -0
  1092. package/dist/utils/busy-turn-guard.js.map +1 -0
  1093. package/dist/utils/conversation/conversation-event-handler.d.ts.map +1 -1
  1094. package/dist/utils/conversation/conversation-event-handler.js +88 -9
  1095. package/dist/utils/conversation/conversation-event-handler.js.map +1 -1
  1096. package/dist/utils/error-helpers.d.ts.map +1 -1
  1097. package/dist/utils/error-helpers.js +8 -0
  1098. package/dist/utils/error-helpers.js.map +1 -1
  1099. package/dist/utils/inject-warning-into-tool-output.d.ts +30 -0
  1100. package/dist/utils/inject-warning-into-tool-output.d.ts.map +1 -1
  1101. package/dist/utils/inject-warning-into-tool-output.js +39 -0
  1102. package/dist/utils/inject-warning-into-tool-output.js.map +1 -1
  1103. package/dist/utils/output/bounded-json.d.ts +33 -0
  1104. package/dist/utils/output/bounded-json.d.ts.map +1 -0
  1105. package/dist/utils/output/bounded-json.js +59 -0
  1106. package/dist/utils/output/bounded-json.js.map +1 -0
  1107. package/dist/utils/output/output-trim.d.ts.map +1 -1
  1108. package/dist/utils/output/output-trim.js +7 -7
  1109. package/dist/utils/output/output-trim.js.map +1 -1
  1110. package/dist/utils/output/text-snippet.d.ts +6 -0
  1111. package/dist/utils/output/text-snippet.d.ts.map +1 -0
  1112. package/dist/utils/output/text-snippet.js +106 -0
  1113. package/dist/utils/output/text-snippet.js.map +1 -0
  1114. package/dist/utils/output/tty-osc.d.ts +1 -1
  1115. package/dist/utils/output/tty-osc.js +1 -1
  1116. package/dist/utils/resume-list.d.ts +3 -1
  1117. package/dist/utils/resume-list.d.ts.map +1 -1
  1118. package/dist/utils/resume-list.js +3 -2
  1119. package/dist/utils/resume-list.js.map +1 -1
  1120. package/dist/utils/settings-command.d.ts.map +1 -1
  1121. package/dist/utils/settings-command.js +120 -6
  1122. package/dist/utils/settings-command.js.map +1 -1
  1123. package/dist/utils/shell/execute-shell.d.ts +8 -0
  1124. package/dist/utils/shell/execute-shell.d.ts.map +1 -1
  1125. package/dist/utils/shell/execute-shell.js +36 -30
  1126. package/dist/utils/shell/execute-shell.js.map +1 -1
  1127. package/dist/utils/shell/sandbox/sandbox-env.d.ts +1 -0
  1128. package/dist/utils/shell/sandbox/sandbox-env.d.ts.map +1 -1
  1129. package/dist/utils/shell/sandbox/sandbox-env.js +2 -0
  1130. package/dist/utils/shell/sandbox/sandbox-env.js.map +1 -1
  1131. package/dist/utils/shell/sandbox/sandbox-policy.d.ts +4 -0
  1132. package/dist/utils/shell/sandbox/sandbox-policy.d.ts.map +1 -1
  1133. package/dist/utils/shell/sandbox/sandbox-policy.js +1 -1
  1134. package/dist/utils/shell/sandbox/sandbox-policy.js.map +1 -1
  1135. package/dist/utils/shell/sandbox/shell-sandbox-runner.d.ts +1 -0
  1136. package/dist/utils/shell/sandbox/shell-sandbox-runner.d.ts.map +1 -1
  1137. package/dist/utils/shell/sandbox/shell-sandbox-runner.js +21 -3
  1138. package/dist/utils/shell/sandbox/shell-sandbox-runner.js.map +1 -1
  1139. package/dist/utils/shell/shell-child-registry.d.ts +11 -0
  1140. package/dist/utils/shell/shell-child-registry.d.ts.map +1 -0
  1141. package/dist/utils/shell/shell-child-registry.js +40 -0
  1142. package/dist/utils/shell/shell-child-registry.js.map +1 -0
  1143. package/dist/utils/shell/shell-output.d.ts.map +1 -1
  1144. package/dist/utils/shell/shell-output.js +10 -6
  1145. package/dist/utils/shell/shell-output.js.map +1 -1
  1146. package/dist/utils/shell/temp-sweep.d.ts +28 -0
  1147. package/dist/utils/shell/temp-sweep.d.ts.map +1 -0
  1148. package/dist/utils/shell/temp-sweep.js +140 -0
  1149. package/dist/utils/shell/temp-sweep.js.map +1 -0
  1150. package/dist/utils/streaming/extract-command-messages.d.ts +12 -5
  1151. package/dist/utils/streaming/extract-command-messages.d.ts.map +1 -1
  1152. package/dist/utils/streaming/extract-command-messages.js +29 -33
  1153. package/dist/utils/streaming/extract-command-messages.js.map +1 -1
  1154. package/dist/utils/streaming/streaming-session-factory.d.ts +8 -0
  1155. package/dist/utils/streaming/streaming-session-factory.d.ts.map +1 -1
  1156. package/dist/utils/streaming/streaming-session-factory.js +3 -0
  1157. package/dist/utils/streaming/streaming-session-factory.js.map +1 -1
  1158. package/dist/utils/value-suggestions.d.ts +8 -0
  1159. package/dist/utils/value-suggestions.d.ts.map +1 -1
  1160. package/dist/utils/value-suggestions.js +72 -0
  1161. package/dist/utils/value-suggestions.js.map +1 -1
  1162. package/package.json +17 -11
  1163. package/dist/utils/output/synchronized-output.d.ts +0 -35
  1164. package/dist/utils/output/synchronized-output.d.ts.map +0 -1
  1165. package/dist/utils/output/synchronized-output.js +0 -66
  1166. package/dist/utils/output/synchronized-output.js.map +0 -1
@@ -0,0 +1,1960 @@
1
+ import crypto from 'node:crypto';
2
+ import { createGatewayAssertion } from './assertion.js';
3
+ import { GatewayLifecycle } from './lifecycle.js';
4
+ import { loadGatewayManifest, WorkspaceAdmission, WorkspaceAdmissionError, } from './workspace-admission.js';
5
+ import { assertProviderBrokerReady, composeGatewaySession, } from './worker-boundary.js';
6
+ import { createSafeLogMetadata, GatewayAuditLog } from './safe-log.js';
7
+ import { AssertionVerifier } from './assertion.js';
8
+ import { SqliteReplayLedger } from './replay-ledger.js';
9
+ import { GatewayServer } from './server.js';
10
+ import { FROZEN_AGENT_EVENT_TYPES, GatewayPersistenceError, TERMINAL_AGENT_EVENT_TYPES, } from './persistence/contracts.js';
11
+ import { createSessionProjectionSource, } from './persistence/projection.js';
12
+ import { decideInteraction, InteractionProtocolError, projectPendingInteraction, validatePendingInteractionDto, } from './interaction-protocol.js';
13
+ import { GatewayAdmissionPersistence } from './persistence/admission-persistence.js';
14
+ import { GATEWAY_EVENT_HEARTBEAT_INTERVAL_MS, GATEWAY_EVENT_STREAM_CONTENT_TYPE, GATEWAY_EVENT_STREAM_HEARTBEAT, } from './server.js';
15
+ import { ServerSession } from './server-session.js';
16
+ import { ServerSessionError } from './server-session.js';
17
+ import { DynamicWorkspaceRegistry, DynamicWorkspaceRegistryError } from './dynamic-workspace-registry.js';
18
+ import { accessSync, constants as fsConstants, realpathSync, statSync } from 'node:fs';
19
+ import { ModelCatalogSession } from '../services/models/model-catalog-session.js';
20
+ import { getAvailableProviderIds } from '../utils/ai/provider-credentials.js';
21
+ import { getProviderIds } from '../providers/index.js';
22
+ import { LoggingService } from '../services/logging/logging-service.js';
23
+ import { applySettingsChanges, buildSettingsProjection, deleteCredential, setCredential, SettingsRpcError, } from './settings-rpc.js';
24
+ import { GatewayPairing, PairingError } from './pairing.js';
25
+ import { TrustedClientsStore } from './trusted-clients.js';
26
+ import { isOAuthAccountProvider, listOAuthAccounts, removeOAuthAccount, setActiveOAuthAccount, } from '../providers/oauth-accounts.js';
27
+ import { loginToCodex } from '../providers/codex-auth.js';
28
+ import { loginToGrok } from '../providers/grok-auth.js';
29
+ const MAX_BUFFERED_SSE_EVENTS = 256;
30
+ const NONCRITICAL_RUNTIME_EVENT_TYPES = new Set(['text_delta', 'reasoning_delta']);
31
+ const isCriticalRuntimeEvent = (event) => !NONCRITICAL_RUNTIME_EVENT_TYPES.has(event.type);
32
+ const INTERACTION_METRICS = [
33
+ 'interaction_presented',
34
+ 'interaction_updated',
35
+ 'interaction_resolved',
36
+ 'interaction_stale',
37
+ 'interaction_duplicate',
38
+ 'interaction_sanitization_rejected',
39
+ 'interaction_continuation_failed',
40
+ ];
41
+ const PUBLIC_EVENT_PAYLOAD_KEYS = new Set([
42
+ 'turnId',
43
+ 'clientRequestId',
44
+ 'messageId',
45
+ 'delta',
46
+ 'callId',
47
+ 'toolName',
48
+ 'message',
49
+ 'interaction',
50
+ 'interactionId',
51
+ 'outcome',
52
+ 'reason',
53
+ 'variant',
54
+ 'revision',
55
+ 'text',
56
+ 'usage',
57
+ 'inputTokens',
58
+ 'outputTokens',
59
+ 'totalTokens',
60
+ 'version',
61
+ 'kind',
62
+ 'descriptor',
63
+ 'choices',
64
+ 'askUser',
65
+ 'questions',
66
+ 'answers',
67
+ 'currentQuestionIndex',
68
+ 'index',
69
+ 'question',
70
+ 'options',
71
+ 'multiSelect',
72
+ 'label',
73
+ 'description',
74
+ 'destructive',
75
+ 'id',
76
+ 'role',
77
+ 'agentName',
78
+ 'argumentsText',
79
+ 'checkIn',
80
+ 'display',
81
+ 'target',
82
+ 'scope',
83
+ 'warning',
84
+ 'displayPath',
85
+ 'displayParent',
86
+ 'sensitive',
87
+ 'llmAdvisory',
88
+ 'reasoning',
89
+ 'approved',
90
+ 'model',
91
+ 'riskLevel',
92
+ 'deniedRead',
93
+ 'runBudgetEvidence',
94
+ ]);
95
+ const LOCAL_OWNER_PURPOSES = new Set([
96
+ 'settings_read',
97
+ 'settings_write',
98
+ 'credential_write',
99
+ 'credential_delete',
100
+ 'oauth_login',
101
+ 'oauth_select',
102
+ 'oauth_delete',
103
+ ]);
104
+ export class GatewayStartupError extends Error {
105
+ constructor() {
106
+ super('gateway prerequisites unavailable');
107
+ this.name = 'GatewayStartupError';
108
+ }
109
+ }
110
+ export function assertGatewayStartup(config, manifest) {
111
+ const socketTransport = config.socketPath !== undefined;
112
+ const networkTransport = config.host !== undefined || config.port !== undefined || config.tls !== undefined;
113
+ if (socketTransport === networkTransport)
114
+ throw new GatewayStartupError();
115
+ if (socketTransport) {
116
+ if (!config.socketPath.startsWith('/'))
117
+ throw new GatewayStartupError();
118
+ }
119
+ else {
120
+ if ((config.host !== undefined && !config.host.trim()) ||
121
+ !Number.isSafeInteger(config.port) ||
122
+ config.port < 1 ||
123
+ config.port > 65_535 ||
124
+ !config.tls ||
125
+ !config.tls.certPath ||
126
+ !config.tls.keyPath ||
127
+ (config.tls.caPath !== undefined && !config.tls.caPath) ||
128
+ typeof config.tls.requireClientCert !== 'boolean')
129
+ throw new GatewayStartupError();
130
+ for (const filePath of [
131
+ config.tls.certPath,
132
+ config.tls.keyPath,
133
+ ...(config.tls.caPath ? [config.tls.caPath] : []),
134
+ ]) {
135
+ try {
136
+ accessSync(filePath, fsConstants.R_OK);
137
+ }
138
+ catch {
139
+ throw new GatewayStartupError();
140
+ }
141
+ }
142
+ }
143
+ if (!config.issuer || !config.audience || !config.replayDbPath)
144
+ throw new GatewayStartupError();
145
+ if (config.pairing?.enabled) {
146
+ if (!config.pairing.trustFilePath.startsWith('/') || config.pairing.trustFilePath.includes('\u0000'))
147
+ throw new GatewayStartupError();
148
+ if ((config.pairing.otpTtlMs !== undefined &&
149
+ (!Number.isSafeInteger(config.pairing.otpTtlMs) || config.pairing.otpTtlMs <= 0)) ||
150
+ (config.pairing.maxAttempts !== undefined &&
151
+ (!Number.isSafeInteger(config.pairing.maxAttempts) || config.pairing.maxAttempts <= 0)))
152
+ throw new GatewayStartupError();
153
+ }
154
+ const configuredKeyCount = config.publicKeys instanceof Map ? config.publicKeys.size : Object.keys(config.publicKeys ?? {}).length;
155
+ if (configuredKeyCount === 0 && !config.pairing?.enabled)
156
+ throw new GatewayStartupError();
157
+ if (!manifest)
158
+ throw new GatewayStartupError();
159
+ if (!config.manifestSha256 || !/^[a-f0-9]{64}$/i.test(config.manifestSha256))
160
+ throw new GatewayStartupError();
161
+ const realProviderStack = config.runtimeFactory?.usesRealProviderStack === true;
162
+ if (!realProviderStack &&
163
+ (!config.providerBroker || !config.providerProbe?.available || !config.providerProbe.secretFree))
164
+ throw new GatewayStartupError();
165
+ if (realProviderStack && !config.runtimeFactory?.settingsAuthority)
166
+ throw new GatewayStartupError();
167
+ if (config.workerSandboxAvailable !== true || typeof config.workspaceBoundaryProbe !== 'function')
168
+ throw new GatewayStartupError();
169
+ if (config.sshEnabled || config.autoApprove || config.allowUnsandboxed)
170
+ throw new GatewayStartupError();
171
+ if (typeof config.auditWriter !== 'function')
172
+ throw new GatewayStartupError();
173
+ if (!realProviderStack)
174
+ assertProviderBrokerReady(config.providerBroker, config.providerProbe);
175
+ if (!config.tmpDir?.startsWith('/'))
176
+ throw new GatewayStartupError();
177
+ return manifest;
178
+ }
179
+ /** Gateway control plane. Runtime/session protocols remain private RPC consumers. */
180
+ export class Term2Gateway {
181
+ #config;
182
+ #replay;
183
+ #admission;
184
+ #verifier;
185
+ #lifecycle = new GatewayLifecycle();
186
+ #audit;
187
+ #sessions = new Map();
188
+ #persisted = new Map();
189
+ #admissions;
190
+ #interactionBindings = new Map();
191
+ #interactionCounters = new Map();
192
+ #eventPersistenceTails = new Map();
193
+ #shutdownInProgress = false;
194
+ #shutdownPromise;
195
+ #server;
196
+ #modelCatalog;
197
+ #workspaceRegistry;
198
+ #pairing;
199
+ #oauthMutation = Promise.resolve();
200
+ #settingsMutation = Promise.resolve();
201
+ constructor(config, manifest) {
202
+ this.#config = config;
203
+ this.#replay = new SqliteReplayLedger(config.replayDbPath);
204
+ this.#admission =
205
+ config.workspaceRegistry?.admission ??
206
+ new WorkspaceAdmission(manifest, {
207
+ allowWrite: config.allowWrite === true,
208
+ boundaryProbe: config.workspaceBoundaryProbe,
209
+ });
210
+ this.#workspaceRegistry =
211
+ config.workspaceRegistry ??
212
+ new DynamicWorkspaceRegistry({
213
+ admission: this.#admission,
214
+ allowedRoots: config.workspaceAllowedRoots ?? deriveDynamicWorkspaceRoots(manifest),
215
+ });
216
+ const trustedStore = config.pairing?.enabled ? new TrustedClientsStore(config.pairing.trustFilePath) : undefined;
217
+ const assertionKeys = new Map();
218
+ for (const [kid, key] of config.publicKeys instanceof Map
219
+ ? config.publicKeys.entries()
220
+ : Object.entries(config.publicKeys))
221
+ assertionKeys.set(kid, key);
222
+ for (const trusted of trustedStore?.entries() ?? [])
223
+ assertionKeys.set(trusted.kid, trusted.publicKeyPem);
224
+ this.#verifier = new AssertionVerifier({
225
+ issuer: config.issuer,
226
+ audience: config.audience,
227
+ publicKeys: assertionKeys,
228
+ allowEmptyKeys: config.pairing?.enabled === true,
229
+ replayLedger: this.#replay,
230
+ });
231
+ this.#pairing = trustedStore
232
+ ? new GatewayPairing({
233
+ enabled: config.pairing.enabled,
234
+ otpTtlMs: config.pairing.otpTtlMs,
235
+ maxAttempts: config.pairing.maxAttempts,
236
+ trustStore: trustedStore,
237
+ })
238
+ : undefined;
239
+ this.#audit = new GatewayAuditLog(config.auditWriter);
240
+ this.#admissions = config.persistence ? new GatewayAdmissionPersistence(config.persistence.index) : null;
241
+ const settingsAuthority = config.runtimeFactory?.settingsAuthority;
242
+ if (settingsAuthority) {
243
+ this.#modelCatalog = new ModelCatalogSession({
244
+ settingsService: settingsAuthority,
245
+ loggingService: config.runtimeFactory?.modelCatalogLogger ??
246
+ new LoggingService({ disableLogging: true, suppressConsoleOutput: true }),
247
+ });
248
+ }
249
+ const transport = config.socketPath
250
+ ? { socketPath: config.socketPath }
251
+ : { host: config.host, port: config.port, tls: config.tls };
252
+ this.#server = new GatewayServer({
253
+ ...transport,
254
+ verifier: this.#verifier,
255
+ lifecycle: this.#lifecycle,
256
+ ...(this.#pairing
257
+ ? {
258
+ pairingHandler: async ({ body }) => {
259
+ if (!isPairingRegisterBody(body))
260
+ return publicError(401, 'pairing_invalid', 'pairing request is invalid');
261
+ try {
262
+ const result = await this.#pairing.register(body.publicKeyPem, body.otp);
263
+ const publicKeyPem = trustedStore.entries().find((entry) => entry.kid === result.kid)?.publicKeyPem;
264
+ if (!publicKeyPem)
265
+ return publicError(503, 'pairing_unavailable', 'pairing is unavailable', true);
266
+ this.#verifier.addTrustedKey(result.kid, publicKeyPem);
267
+ return { status: 200, body: result };
268
+ }
269
+ catch (error) {
270
+ if (error instanceof PairingError) {
271
+ if (error.code === 'pairing_unavailable')
272
+ return publicError(503, 'pairing_unavailable', 'pairing is unavailable', true);
273
+ return publicError(401, error.code === 'pairing_required' || error.code === 'pairing_not_allowed'
274
+ ? 'pairing_required'
275
+ : 'pairing_invalid', 'pairing rejected');
276
+ }
277
+ throw error;
278
+ }
279
+ },
280
+ }
281
+ : {}),
282
+ handler: (input) => this.#handleRpc(input),
283
+ });
284
+ }
285
+ async #handleRpc(input) {
286
+ const { claims, url } = input;
287
+ const route = matchPrivateRoute(input.request.method ?? 'GET', url.pathname);
288
+ if (!route || (route.legacy && claims.purpose !== 'session_create')) {
289
+ return publicError(404, 'not_found', 'gateway route not found');
290
+ }
291
+ if (!route.legacy && route.sessionId && route.sessionId !== claims.sessionId)
292
+ return publicError(400, 'protocol_conflict', 'gateway path and assertion session do not match');
293
+ if (!route.legacy && route.purpose !== claims.purpose)
294
+ return publicError(400, 'protocol_conflict', 'gateway purpose does not match route');
295
+ if (LOCAL_OWNER_PURPOSES.has(claims.purpose) && claims.sub !== this.#config.localOwnerUserId)
296
+ return publicError(403, 'settings_forbidden', 'local owner authorization is required');
297
+ try {
298
+ if (claims.purpose === 'workspace_list') {
299
+ await this.#audit.write(createSafeLogMetadata({
300
+ operation: 'workspace_list',
301
+ outcome: 'allowed',
302
+ reasonCode: 'accepted',
303
+ ...(input.correlationId ? { correlationId: input.correlationId } : {}),
304
+ }));
305
+ const limit = parseQueryLimit(url.searchParams.get('limit')) ?? 20;
306
+ if (limit < 1 || limit > 50 || url.searchParams.get('cursor') !== null)
307
+ return publicError(400, 'invalid_cursor', 'workspace cursor is invalid');
308
+ return {
309
+ status: 200,
310
+ body: { workspaces: this.#admission.listAliases(claims.sub).slice(0, limit), nextCursor: null },
311
+ };
312
+ }
313
+ if (claims.purpose === 'session_create') {
314
+ if (hasDeferredModelSelectionField(input.body))
315
+ return publicError(422, 'model_selection_deferred', 'Model selection is not available');
316
+ if (!isSessionCreateBody(input.body, claims.workspaceId, route.legacy))
317
+ return publicError(400, 'validation_error', 'session request is invalid');
318
+ const session = await this.createSession(claims, undefined, input.correlationId);
319
+ if (this.#config.persistence) {
320
+ const projection = await this.#projectionFor(claims.sub, session.sessionId);
321
+ return { status: 201, body: { session: toSessionProjection(projection) } };
322
+ }
323
+ return {
324
+ status: 201,
325
+ body: { sessionId: session.sessionId, workspaceId: session.binding.workspaceId, accepted: true },
326
+ };
327
+ }
328
+ if (claims.purpose === 'session_list') {
329
+ if (!this.#config.persistence)
330
+ return publicError(503, 'gateway_unavailable', 'gateway persistence unavailable', true);
331
+ const limit = parseQueryLimit(url.searchParams.get('limit'));
332
+ const cursor = url.searchParams.get('cursor') ?? undefined;
333
+ try {
334
+ return { status: 200, body: this.#config.persistence.index.list(claims.sub, { limit, cursor }) };
335
+ }
336
+ catch (error) {
337
+ if (error instanceof GatewayPersistenceError && error.code === 'cursor_invalid')
338
+ return publicError(400, 'invalid_cursor', 'session cursor is invalid');
339
+ throw error;
340
+ }
341
+ }
342
+ if (claims.purpose === 'model_list')
343
+ return await this.#modelList(input.correlationId);
344
+ if (claims.purpose === 'workspace_candidate_validate')
345
+ return await this.#workspaceCandidateValidate(claims, input.body, input.correlationId);
346
+ if (claims.purpose === 'workspace_candidate_browse')
347
+ return await this.#workspaceCandidateBrowse(claims, input.body, input.correlationId);
348
+ if (claims.purpose === 'workspace_candidate_select')
349
+ return await this.#workspaceCandidateSelect(claims, input.body, input.correlationId);
350
+ if (claims.purpose === 'settings_read')
351
+ return await this.#settingsRead(input.correlationId);
352
+ if (claims.purpose === 'settings_write')
353
+ return await this.#settingsWrite(input.body, input.correlationId);
354
+ if (claims.purpose === 'credential_write')
355
+ return await this.#credentialWrite(route.interactionId, input.body, input.correlationId);
356
+ if (claims.purpose === 'credential_delete')
357
+ return await this.#credentialDelete(route.interactionId, input.correlationId);
358
+ if (claims.purpose === 'oauth_login')
359
+ return await this.#oauthLogin(route.interactionId, input.correlationId);
360
+ if (claims.purpose === 'oauth_select')
361
+ return await this.#oauthSelect(route.interactionId, input.body, input.correlationId);
362
+ if (claims.purpose === 'oauth_delete')
363
+ return await this.#oauthDelete(route.interactionId, input.correlationId);
364
+ if (!claims.sessionId)
365
+ return publicError(400, 'protocol_conflict', 'session assertion is incomplete');
366
+ if (claims.purpose === 'session_update')
367
+ return await this.#sessionUpdate(claims, input.body, input.correlationId);
368
+ if (claims.purpose === 'session_read') {
369
+ const projection = await this.#projectionFor(claims.sub, claims.sessionId);
370
+ return { status: 200, body: { session: toSessionProjection(projection) } };
371
+ }
372
+ if (claims.purpose === 'message_submit')
373
+ return await this.#submitMessage(claims, input.body);
374
+ if (claims.purpose === 'abort')
375
+ return await this.#abortSession(claims, input.body);
376
+ if (claims.purpose === 'interaction_resolve')
377
+ return await this.#resolveInteraction(claims, route.interactionId, input.body);
378
+ if (claims.purpose === 'events_connect')
379
+ return await this.#eventsResponse(claims, url, input.request);
380
+ return publicError(403, 'gateway_unavailable', 'gateway operation is unavailable');
381
+ }
382
+ catch (error) {
383
+ return this.#mapError(error);
384
+ }
385
+ }
386
+ async #modelList(correlationId) {
387
+ const catalog = this.#modelCatalog;
388
+ const settings = this.#config.runtimeFactory?.settingsAuthority;
389
+ if (!catalog || !settings)
390
+ return publicError(503, 'model_catalog_unavailable', 'model catalog unavailable', true);
391
+ await this.#audit.write(createSafeLogMetadata({
392
+ operation: 'model_list',
393
+ outcome: 'allowed',
394
+ reasonCode: 'accepted',
395
+ ...(correlationId ? { correlationId } : {}),
396
+ }));
397
+ const models = [];
398
+ for (const provider of getAvailableProviderIds(settings, getProviderIds())) {
399
+ try {
400
+ const result = await catalog.load(provider);
401
+ for (const model of result.models) {
402
+ models.push({
403
+ provider,
404
+ id: model.id,
405
+ ...(model.name === undefined ? {} : { name: model.name }),
406
+ ...(model.default_reasoning_level === undefined
407
+ ? {}
408
+ : { default_reasoning_level: model.default_reasoning_level }),
409
+ ...(model.contextWindow === undefined ? {} : { contextWindow: model.contextWindow }),
410
+ });
411
+ }
412
+ }
413
+ catch {
414
+ // Provider errors can include credential values or request headers.
415
+ // The redacted model surface simply omits that provider.
416
+ }
417
+ }
418
+ return { status: 200, body: { models } };
419
+ }
420
+ async #workspaceCandidateValidate(claims, body, correlationId) {
421
+ if (!isWorkspaceCandidateValidateBody(body))
422
+ return publicError(400, 'validation_error', 'workspace request is invalid');
423
+ const result = this.#workspaceRegistry.validateCandidate(body.absolutePath, claims.sub);
424
+ await this.#audit.write(createSafeLogMetadata({
425
+ operation: 'workspace_candidate_validate',
426
+ outcome: result.valid ? 'allowed' : 'denied',
427
+ reasonCode: result.valid ? 'accepted' : result.reasonCode,
428
+ ...(correlationId ? { correlationId } : {}),
429
+ }));
430
+ return { status: 200, body: result };
431
+ }
432
+ async #workspaceCandidateBrowse(claims, body, correlationId) {
433
+ if (!isWorkspaceCandidateBrowseBody(body))
434
+ return publicError(400, 'validation_error', 'workspace request is invalid');
435
+ const result = this.#workspaceRegistry.browse(body.candidateId, body.child, claims.sub);
436
+ await this.#audit.write(createSafeLogMetadata({
437
+ operation: 'workspace_candidate_browse',
438
+ outcome: 'allowed',
439
+ reasonCode: 'accepted',
440
+ ...(correlationId ? { correlationId } : {}),
441
+ }));
442
+ return { status: 200, body: result };
443
+ }
444
+ async #workspaceCandidateSelect(claims, body, correlationId) {
445
+ if (!isWorkspaceCandidateSelectBody(body))
446
+ return publicError(400, 'validation_error', 'workspace request is invalid');
447
+ const result = this.#workspaceRegistry.select(body.candidateId, body.access, claims.sub);
448
+ await this.#audit.write(createSafeLogMetadata({
449
+ operation: 'workspace_candidate_select',
450
+ outcome: 'allowed',
451
+ reasonCode: 'accepted',
452
+ workspaceId: result.workspaceId,
453
+ grantVersion: result.binding.grantVersion,
454
+ access: result.binding.access,
455
+ ...(correlationId ? { correlationId } : {}),
456
+ }));
457
+ return {
458
+ status: 200,
459
+ body: {
460
+ workspaceId: result.workspaceId,
461
+ displayName: result.displayName,
462
+ binding: {
463
+ sessionId: result.binding.sessionId,
464
+ ownerUserId: result.binding.ownerUserId,
465
+ workspaceId: result.binding.workspaceId,
466
+ grantVersion: result.binding.grantVersion,
467
+ canonicalRoot: result.binding.canonicalRoot,
468
+ access: result.binding.access,
469
+ },
470
+ },
471
+ };
472
+ }
473
+ #settingsAuthority() {
474
+ const settings = this.#config.runtimeFactory?.settingsAuthority;
475
+ return settings ? settings : undefined;
476
+ }
477
+ async #settingsRead(correlationId) {
478
+ const settings = this.#settingsAuthority();
479
+ if (!settings)
480
+ return publicError(503, 'settings_unavailable', 'settings unavailable', true);
481
+ const projection = buildSettingsProjection(settings, this.#config.allowWrite ? 'read_write' : 'read');
482
+ await this.#audit.write(createSafeLogMetadata({
483
+ operation: 'settings_read',
484
+ outcome: 'allowed',
485
+ reasonCode: 'accepted',
486
+ ...(correlationId ? { correlationId } : {}),
487
+ }));
488
+ return { status: 200, body: projection };
489
+ }
490
+ async #settingsWrite(body, correlationId) {
491
+ const settings = this.#settingsAuthority();
492
+ if (!settings)
493
+ return publicError(503, 'settings_unavailable', 'settings unavailable', true);
494
+ if (!isSettingsWriteBody(body))
495
+ return publicError(400, 'validation_error', 'settings request is invalid');
496
+ return await this.#withSettingsMutation(async () => {
497
+ const projection = applySettingsChanges(settings, body.expectedRevision, body.changes);
498
+ await this.#audit.write(createSafeLogMetadata({
499
+ operation: 'settings_write',
500
+ outcome: 'allowed',
501
+ reasonCode: 'accepted',
502
+ ...(correlationId ? { correlationId } : {}),
503
+ }));
504
+ return { status: 200, body: { committed: true, revision: projection.revision, projection } };
505
+ });
506
+ }
507
+ async #credentialWrite(credentialId, body, correlationId) {
508
+ const settings = this.#settingsAuthority();
509
+ if (!settings)
510
+ return publicError(503, 'settings_unavailable', 'settings unavailable', true);
511
+ if (!isCredentialWriteBody(body))
512
+ return publicError(400, 'validation_error', 'credential request is invalid');
513
+ return await this.#withSettingsMutation(async () => {
514
+ const result = setCredential(settings, credentialId, body.value);
515
+ await this.#audit.write(createSafeLogMetadata({
516
+ operation: 'credential_write',
517
+ outcome: 'allowed',
518
+ reasonCode: 'accepted',
519
+ ...(correlationId ? { correlationId } : {}),
520
+ }));
521
+ return { status: 200, body: result };
522
+ });
523
+ }
524
+ async #credentialDelete(credentialId, correlationId) {
525
+ const settings = this.#settingsAuthority();
526
+ if (!settings)
527
+ return publicError(503, 'settings_unavailable', 'settings unavailable', true);
528
+ return await this.#withSettingsMutation(async () => {
529
+ const result = deleteCredential(settings, credentialId);
530
+ await this.#audit.write(createSafeLogMetadata({
531
+ operation: 'credential_delete',
532
+ outcome: 'allowed',
533
+ reasonCode: 'accepted',
534
+ ...(correlationId ? { correlationId } : {}),
535
+ }));
536
+ return { status: 200, body: result };
537
+ });
538
+ }
539
+ async #withSettingsMutation(operation) {
540
+ const previous = this.#settingsMutation;
541
+ let release;
542
+ this.#settingsMutation = new Promise((resolve) => {
543
+ release = resolve;
544
+ });
545
+ await previous;
546
+ try {
547
+ return await operation();
548
+ }
549
+ finally {
550
+ release();
551
+ }
552
+ }
553
+ async #oauthLogin(resource, correlationId) {
554
+ const [provider] = resource.split('\u0000');
555
+ if (!isOAuthAccountProvider(provider))
556
+ return publicError(400, 'validation_error', 'OAuth provider is invalid');
557
+ return await this.#withOAuthMutation(async () => {
558
+ try {
559
+ if (this.#config.oauthLogin)
560
+ await this.#config.oauthLogin(provider);
561
+ else if (provider === 'codex')
562
+ await loginToCodex();
563
+ else
564
+ await loginToGrok();
565
+ return {
566
+ status: 200,
567
+ body: { status: 'completed', configured: listOAuthAccounts(provider).length > 0 },
568
+ };
569
+ }
570
+ catch {
571
+ return { status: 200, body: { status: 'not_completed' } };
572
+ }
573
+ }, 'oauth_login', correlationId);
574
+ }
575
+ async #oauthSelect(resource, body, correlationId) {
576
+ const [provider] = resource.split('\u0000');
577
+ if (!isOAuthAccountProvider(provider) || !isOAuthSelectBody(body))
578
+ return publicError(400, 'validation_error', 'OAuth request is invalid');
579
+ return await this.#withOAuthMutation(async () => {
580
+ const ok = setActiveOAuthAccount(provider, body.accountId);
581
+ const account = listOAuthAccounts(provider).find((item) => item.id === body.accountId);
582
+ return {
583
+ status: 200,
584
+ body: { ok, isSelected: account?.isSelected === true, isInUse: account?.isInUse === true },
585
+ };
586
+ }, 'oauth_select', correlationId);
587
+ }
588
+ async #oauthDelete(resource, correlationId) {
589
+ const [provider, accountId] = resource.split('\u0000');
590
+ if (!isOAuthAccountProvider(provider) || !accountId)
591
+ return publicError(400, 'validation_error', 'OAuth request is invalid');
592
+ return await this.#withOAuthMutation(async () => {
593
+ const ok = removeOAuthAccount(provider, accountId);
594
+ return { status: 200, body: { ok } };
595
+ }, 'oauth_delete', correlationId);
596
+ }
597
+ async #withOAuthMutation(operation, auditOperation, correlationId) {
598
+ const previous = this.#oauthMutation;
599
+ let release;
600
+ this.#oauthMutation = new Promise((resolve) => {
601
+ release = resolve;
602
+ });
603
+ await previous;
604
+ try {
605
+ const result = await operation();
606
+ await this.#audit.write(createSafeLogMetadata({
607
+ operation: auditOperation,
608
+ outcome: 'allowed',
609
+ reasonCode: 'accepted',
610
+ ...(correlationId ? { correlationId } : {}),
611
+ }));
612
+ return result;
613
+ }
614
+ finally {
615
+ release();
616
+ }
617
+ }
618
+ async #sessionUpdate(claims, body, correlationId) {
619
+ if (!isSessionUpdateBody(body))
620
+ return publicError(400, 'validation_error', 'session config is invalid');
621
+ const session = this.#sessions.get(claims.sessionId);
622
+ if (!(session instanceof ServerSession) || session.binding.ownerUserId !== claims.sub)
623
+ return publicError(404, 'not_found', 'session not found');
624
+ if (session.status === 'running' || session.status === 'awaiting_interaction')
625
+ return publicError(409, 'session_busy', 'session is busy');
626
+ const settings = session.resources.sessionSettingsService;
627
+ if (!settings)
628
+ return publicError(503, 'settings_unavailable', 'session settings unavailable', true);
629
+ if (body.model !== undefined) {
630
+ if (!this.#modelCatalog)
631
+ return publicError(503, 'settings_unavailable', 'model catalog unavailable', true);
632
+ const provider = String(settings.getDynamic('agent.provider') ?? '');
633
+ const models = await this.#modelCatalog.load(provider);
634
+ if (!models.models.some((model) => model.id === body.model))
635
+ return publicError(422, 'validation_error', 'model is unavailable');
636
+ session.service.setModel(body.model);
637
+ }
638
+ if (body.reasoningEffort !== undefined)
639
+ session.service.setReasoningEffort(body.reasoningEffort);
640
+ if (body.mode !== undefined) {
641
+ const modes = { mentorMode: false, liteMode: false, planMode: false, orchestratorMode: false };
642
+ const key = body.mode === 'mentor'
643
+ ? 'mentorMode'
644
+ : body.mode === 'lite'
645
+ ? 'liteMode'
646
+ : body.mode === 'plan'
647
+ ? 'planMode'
648
+ : body.mode === 'orchestrator'
649
+ ? 'orchestratorMode'
650
+ : undefined;
651
+ if (key)
652
+ modes[key] = true;
653
+ for (const [modeKey, value] of Object.entries(modes))
654
+ settings.setDynamic(`app.${modeKey}`, value, { persist: false });
655
+ }
656
+ const result = sessionConfigProjection(session);
657
+ await this.#audit.write(createSafeLogMetadata({
658
+ operation: 'session_update',
659
+ outcome: 'allowed',
660
+ reasonCode: 'accepted',
661
+ sessionId: session.sessionId,
662
+ workspaceId: session.binding.workspaceId,
663
+ ...(correlationId ? { correlationId } : {}),
664
+ }));
665
+ return { status: 200, body: result };
666
+ }
667
+ #interactionBindingFor(sessionId, snapshot, turnId) {
668
+ const current = this.#interactionBindings.get(sessionId);
669
+ if (current && current.expectedInteractionId === snapshot.interactionId)
670
+ return current;
671
+ const publicInteractionId = crypto.randomUUID();
672
+ const dto = projectPendingInteraction(snapshot.approval, publicInteractionId, 1);
673
+ const binding = {
674
+ publicInteractionId,
675
+ expectedInteractionId: snapshot.interactionId,
676
+ continuationGeneration: crypto.randomUUID(),
677
+ revision: 1,
678
+ turnId,
679
+ variant: dto.variant,
680
+ dto,
681
+ };
682
+ this.#interactionBindings.set(sessionId, binding);
683
+ this.#countInteraction('interaction_presented');
684
+ return binding;
685
+ }
686
+ #countInteraction(metric) {
687
+ this.#interactionCounters.set(metric, (this.#interactionCounters.get(metric) ?? 0) + 1);
688
+ }
689
+ async #ensurePersistedSession(ownerUserId, sessionId) {
690
+ const existing = this.#persisted.get(sessionId);
691
+ if (existing) {
692
+ if (existing.record.ownerUserId !== ownerUserId)
693
+ throw new GatewayPersistenceError('owner_mismatch');
694
+ return existing;
695
+ }
696
+ const persistence = this.#config.persistence;
697
+ if (!persistence)
698
+ throw new GatewayPersistenceError('not_found', 'session not found');
699
+ const record = persistence.index.getForOwner(ownerUserId, sessionId);
700
+ const grantVersion = Number(record.grantVersion);
701
+ if (!Number.isSafeInteger(grantVersion))
702
+ throw new GatewayPersistenceError('readonly', 'session grant version is invalid');
703
+ let binding;
704
+ try {
705
+ binding = this.#admission.restore(sessionId, ownerUserId, record.workspaceId, grantVersion);
706
+ }
707
+ catch {
708
+ throw new GatewayPersistenceError('not_found', 'session not found');
709
+ }
710
+ try {
711
+ const reopened = await persistence.open(binding);
712
+ this.#persisted.set(sessionId, reopened);
713
+ return reopened;
714
+ }
715
+ catch (error) {
716
+ this.#admission.remove(sessionId);
717
+ throw error;
718
+ }
719
+ }
720
+ async #projectionFor(ownerUserId, sessionId) {
721
+ const persistence = this.#config.persistence;
722
+ const persisted = await this.#ensurePersistedSession(ownerUserId, sessionId);
723
+ if (!persistence)
724
+ throw new GatewayPersistenceError('not_found', 'session not found');
725
+ return await createSessionProjectionSource({
726
+ index: persistence.index,
727
+ layout: persistence.layout,
728
+ ownerUserId,
729
+ sessionId,
730
+ journal: persisted.persistence.journal,
731
+ liveInteraction: () => {
732
+ const session = this.#sessions.get(sessionId);
733
+ if (!(session instanceof ServerSession))
734
+ return null;
735
+ const snapshot = session.service.getPendingInteractionSnapshot();
736
+ if (!snapshot)
737
+ return null;
738
+ const existingBinding = this.#interactionBindings.get(sessionId);
739
+ const turnId = session.activeTurnId ?? existingBinding?.turnId;
740
+ if (!turnId)
741
+ return null;
742
+ // A projection/read is observational. Only the approval event path
743
+ // may create a public binding; reconnects must never mint or replace
744
+ // the ID that the first viewport was given.
745
+ if (!existingBinding || existingBinding.expectedInteractionId !== snapshot.interactionId)
746
+ return null;
747
+ const binding = existingBinding;
748
+ return Promise.resolve({
749
+ state: 'pending',
750
+ interaction: interactionDtoFromSnapshot(snapshot, binding.publicInteractionId, binding.revision),
751
+ turnId: binding.turnId,
752
+ });
753
+ },
754
+ });
755
+ }
756
+ async #submitMessage(claims, body) {
757
+ if (hasAttachments(body))
758
+ return publicError(422, 'attachments_not_enabled', 'Attachments are not available');
759
+ if (!this.#admissions || !this.#config.persistence)
760
+ return publicError(503, 'persistence_unavailable', 'gateway persistence unavailable', true);
761
+ if (!isMessageBody(body))
762
+ return publicError(400, 'validation_error', 'message request is invalid');
763
+ const session = this.#sessions.get(claims.sessionId);
764
+ const persisted = this.#persisted.get(claims.sessionId);
765
+ if (!(session instanceof ServerSession) || !persisted)
766
+ return publicError(409, 'session_not_admitting', 'session is not admitting messages');
767
+ const turnId = crypto.randomUUID();
768
+ try {
769
+ const result = await this.#admissions.admit({
770
+ ownerUserId: claims.sub,
771
+ sessionId: claims.sessionId,
772
+ clientRequestId: body.clientRequestId,
773
+ body,
774
+ turnId,
775
+ runtime: session,
776
+ persistence: persisted.persistence.critical,
777
+ term2Fact: { type: 'user_message', message: { id: turnId, sender: 'user', text: body.text } },
778
+ acceptedEvent: {
779
+ sessionId: claims.sessionId,
780
+ type: 'user_message_accepted',
781
+ payload: { turnId, clientRequestId: body.clientRequestId, messageId: turnId },
782
+ },
783
+ beforeCommit: () => this.#enqueueEventPersistence(claims.sessionId, async () => {
784
+ await persisted.persistence.critical.appendJournalCritical({
785
+ sessionId: claims.sessionId,
786
+ type: 'assistant_started',
787
+ payload: { turnId },
788
+ });
789
+ }),
790
+ });
791
+ if (result.kind === 'rejected') {
792
+ return result.reason === 'queue_full'
793
+ ? publicError(429, 'queue_full', 'message queue is full', true)
794
+ : publicError(409, 'session_not_admitting', 'session is not admitting messages');
795
+ }
796
+ return {
797
+ status: 202,
798
+ body: {
799
+ sessionId: claims.sessionId,
800
+ clientRequestId: body.clientRequestId,
801
+ turnId: result.record.turnId,
802
+ accepted: true,
803
+ replayed: result.replayed,
804
+ },
805
+ };
806
+ }
807
+ catch (error) {
808
+ return this.#mapError(error);
809
+ }
810
+ }
811
+ async #abortSession(claims, body) {
812
+ if (!isTurnBody(body))
813
+ return publicError(400, 'validation_error', 'abort request is invalid');
814
+ const session = this.#sessions.get(claims.sessionId);
815
+ if (!(session instanceof ServerSession))
816
+ return publicError(409, 'session_not_admitting', 'session is not admitting');
817
+ const outcome = await session.abort(body.turnId);
818
+ if (outcome.kind === 'aborted') {
819
+ const persisted = this.#persisted.get(claims.sessionId);
820
+ if (persisted) {
821
+ await this.#enqueueEventPersistence(claims.sessionId, async () => {
822
+ const admissions = this.#config.persistence?.index.listAdmissions(claims.sub, claims.sessionId) ?? [];
823
+ for (const discardedTurnId of outcome.discardedTurnIds) {
824
+ if (hasTerminalTurnEvent(persisted.persistence.journal.events(), discardedTurnId))
825
+ continue;
826
+ const admission = admissions.find((candidate) => candidate.turnId === discardedTurnId);
827
+ await persisted.persistence.journal.append({
828
+ sessionId: claims.sessionId,
829
+ type: 'user_message_rejected',
830
+ payload: {
831
+ turnId: discardedTurnId,
832
+ ...(admission ? { clientRequestId: admission.clientRequestId } : {}),
833
+ reason: 'queue_discarded',
834
+ },
835
+ }, { durability: 'critical' });
836
+ if (admission) {
837
+ this.#config.persistence?.index.updateAdmission(claims.sub, claims.sessionId, admission.clientRequestId, {
838
+ state: 'rejected',
839
+ result: 'queue_discarded',
840
+ });
841
+ }
842
+ }
843
+ await persisted.persistence.journal.append({
844
+ sessionId: claims.sessionId,
845
+ type: 'turn_aborted',
846
+ payload: { turnId: body.turnId, outcome: 'aborted' },
847
+ }, { durability: 'critical' });
848
+ });
849
+ }
850
+ return { status: 202, body: { sessionId: claims.sessionId, turnId: body.turnId, accepted: true } };
851
+ }
852
+ if (outcome.kind === 'already_settled' || outcome.kind === 'no_op')
853
+ return {
854
+ status: 200,
855
+ body: { sessionId: claims.sessionId, turnId: body.turnId, accepted: false, alreadySettled: true },
856
+ };
857
+ return publicError(409, 'session_not_admitting', 'session is interrupted');
858
+ }
859
+ async #resolveInteraction(claims, interactionId, body) {
860
+ if (!isInteractionResolveRequest(body))
861
+ return publicError(400, 'validation_error', 'interaction request is invalid');
862
+ const projection = await this.#projectionFor(claims.sub, claims.sessionId);
863
+ const session = this.#sessions.get(claims.sessionId);
864
+ const binding = this.#interactionBindings.get(claims.sessionId);
865
+ const snapshot = session instanceof ServerSession ? session.service.getPendingInteractionSnapshot() : null;
866
+ // A live runtime owns the current interaction. A public ID from an older
867
+ // presentation is stale even when the durable journal still says the
868
+ // interaction was recovered during startup.
869
+ if (snapshot !== null && (!binding || binding.publicInteractionId !== interactionId)) {
870
+ this.#countInteraction('interaction_stale');
871
+ return publicError(409, 'stale_interaction', 'interaction is stale');
872
+ }
873
+ if (projection.interaction?.state === 'recovered' && snapshot === null)
874
+ return publicError(409, 'interaction_not_resolvable', 'interaction is not resolvable');
875
+ if (!(session instanceof ServerSession))
876
+ return publicError(404, 'not_found', 'session not found');
877
+ if (projection.resolvedInteractionIds.has(interactionId)) {
878
+ this.#countInteraction('interaction_duplicate');
879
+ return publicError(409, 'interaction_already_resolved', 'interaction is already resolved');
880
+ }
881
+ if (!binding || binding.publicInteractionId !== interactionId) {
882
+ this.#countInteraction('interaction_stale');
883
+ return publicError(409, 'stale_interaction', 'interaction is stale');
884
+ }
885
+ const resolutionCode = classifyInteractionResolution(projection.interaction, snapshot !== null);
886
+ if (resolutionCode) {
887
+ this.#countInteraction(resolutionCode === 'interaction_already_resolved' ? 'interaction_duplicate' : 'interaction_stale');
888
+ return publicError(409, resolutionCode, resolutionCode === 'interaction_not_resolvable'
889
+ ? 'interaction is not resolvable'
890
+ : 'interaction is already resolved');
891
+ }
892
+ if (!snapshot) {
893
+ this.#countInteraction('interaction_duplicate');
894
+ return publicError(409, 'interaction_already_resolved', 'interaction is already resolved');
895
+ }
896
+ if (body.revision !== binding.revision) {
897
+ this.#countInteraction('interaction_stale');
898
+ return publicError(409, 'stale_interaction', 'interaction revision is stale');
899
+ }
900
+ const continuationAbortGeneration = session.abortGeneration;
901
+ let decision;
902
+ try {
903
+ decision = decideInteraction(binding.dto, body);
904
+ }
905
+ catch (error) {
906
+ if (error instanceof InteractionProtocolError) {
907
+ this.#countInteraction('interaction_sanitization_rejected');
908
+ return publicError(400, 'validation_error', 'interaction decision is invalid');
909
+ }
910
+ throw error;
911
+ }
912
+ try {
913
+ const result = session.resolvePendingInteraction({
914
+ expectedInteractionId: binding.expectedInteractionId,
915
+ answer: decision.answer,
916
+ rejectionReason: decision.rejectionReason,
917
+ approvalAnswer: decision.approvalAnswer,
918
+ });
919
+ if (result.kind === 'awaiting_next_question') {
920
+ binding.revision += 1;
921
+ binding.dto = projectPendingInteraction(result.snapshot.approval, binding.publicInteractionId, binding.revision, result.snapshot.askUserAnswers, result.snapshot.currentAskUserQuestionIndex);
922
+ await this.#enqueueEventPersistence(claims.sessionId, async () => {
923
+ const persisted = this.#persisted.get(claims.sessionId);
924
+ if (!persisted)
925
+ throw new GatewayPersistenceError('not_found', 'session persistence is unavailable');
926
+ persisted.persistence.interactionCheckpoint.save({
927
+ turnId: binding.turnId,
928
+ interaction: binding.dto,
929
+ revision: binding.revision,
930
+ generation: binding.continuationGeneration,
931
+ });
932
+ await persisted.persistence.journal.append({
933
+ sessionId: claims.sessionId,
934
+ type: 'interaction_updated',
935
+ payload: { turnId: binding.turnId, interaction: binding.dto },
936
+ }, { durability: 'critical' });
937
+ });
938
+ this.#countInteraction('interaction_updated');
939
+ return { status: 200, body: { accepted: false, interaction: binding.dto } };
940
+ }
941
+ if (result.kind === 'none')
942
+ return publicError(409, 'interaction_already_resolved', 'interaction is already resolved');
943
+ if (result.kind === 'stale_interaction')
944
+ return publicError(409, 'stale_interaction', 'interaction is stale');
945
+ await this.#enqueueEventPersistence(claims.sessionId, async () => {
946
+ const persisted = this.#persisted.get(claims.sessionId);
947
+ if (!persisted)
948
+ throw new GatewayPersistenceError('not_found', 'session persistence is unavailable');
949
+ await persisted.persistence.journal.append({
950
+ sessionId: claims.sessionId,
951
+ type: 'interaction_resolved',
952
+ payload: {
953
+ turnId: binding.turnId,
954
+ interactionId: binding.publicInteractionId,
955
+ outcome: decision.outcome,
956
+ variant: binding.variant,
957
+ },
958
+ }, { durability: 'critical' });
959
+ persisted.persistence.interactionCheckpoint.clear();
960
+ });
961
+ this.#interactionBindings.delete(claims.sessionId);
962
+ this.#countInteraction('interaction_resolved');
963
+ try {
964
+ if (session.abortGeneration !== continuationAbortGeneration || session.activeTurnId !== binding.turnId) {
965
+ throw new ServerSessionError('interrupted');
966
+ }
967
+ await session.service.handleApprovalDecision(decision.answer, decision.rejectionReason, {
968
+ approvalAnswer: decision.approvalAnswer,
969
+ });
970
+ }
971
+ catch (error) {
972
+ this.#countInteraction('interaction_continuation_failed');
973
+ await this.#recordContinuationFailure(claims.sessionId, binding);
974
+ throw error;
975
+ }
976
+ return {
977
+ status: 202,
978
+ body: {
979
+ sessionId: claims.sessionId,
980
+ turnId: binding.turnId,
981
+ interactionId: binding.publicInteractionId,
982
+ accepted: true,
983
+ },
984
+ };
985
+ }
986
+ catch (error) {
987
+ if (error instanceof ServerSessionError && error.code === 'stale_interaction')
988
+ return publicError(409, 'stale_interaction', 'interaction is stale');
989
+ throw error;
990
+ }
991
+ }
992
+ async #eventsResponse(claims, url, request) {
993
+ const queryCursor = url.searchParams.get('after');
994
+ const headerCursor = typeof request.headers['last-event-id'] === 'string' ? request.headers['last-event-id'] : null;
995
+ if (queryCursor !== null && headerCursor !== null && queryCursor !== headerCursor)
996
+ return publicError(400, 'protocol_conflict', 'event cursors do not match');
997
+ const after = parseEventCursor(queryCursor ?? headerCursor);
998
+ if (after.error)
999
+ return publicError(400, after.error, 'event cursor is invalid');
1000
+ const source = await this.#projectionFor(claims.sub, claims.sessionId);
1001
+ let activeResponse = null;
1002
+ let closed = false;
1003
+ let buffered = [];
1004
+ let unsubscribe = () => undefined;
1005
+ const closeSlowSubscriber = () => {
1006
+ if (closed)
1007
+ return;
1008
+ closed = true;
1009
+ unsubscribe();
1010
+ if (activeResponse && !activeResponse.writableEnded)
1011
+ activeResponse.destroy();
1012
+ };
1013
+ const writeEvent = (response, event) => {
1014
+ if (!isPublicEventEnvelope(event))
1015
+ return closeSlowSubscriber();
1016
+ const accepted = response.write(`id: ${event.id}\ndata: ${JSON.stringify(event)}\n\n`);
1017
+ if (!accepted)
1018
+ closeSlowSubscriber();
1019
+ };
1020
+ const live = source.subscribeFrom(after.value, (event) => {
1021
+ if (closed)
1022
+ return;
1023
+ if (!activeResponse) {
1024
+ if (buffered.length >= MAX_BUFFERED_SSE_EVENTS)
1025
+ return closeSlowSubscriber();
1026
+ buffered.push(event);
1027
+ return;
1028
+ }
1029
+ writeEvent(activeResponse, event);
1030
+ });
1031
+ if (live.kind === 'reload_required') {
1032
+ const status = live.reason === 'cursor_compacted' ? 410 : 503;
1033
+ const code = live.reason === 'cursor_compacted' ? 'cursor_compacted' : 'gateway_unavailable';
1034
+ return publicError(status, code, 'event replay requires a session reload', true, {
1035
+ reloadRequired: true,
1036
+ session: toSessionProjection(source),
1037
+ latestSequence: live.latestSequence,
1038
+ });
1039
+ }
1040
+ unsubscribe = live.unsubscribe;
1041
+ if (live.replay.some((event) => !isPublicEventEnvelope(event))) {
1042
+ live.unsubscribe();
1043
+ return publicError(503, 'gateway_unavailable', 'event stream is unavailable', true);
1044
+ }
1045
+ return {
1046
+ status: 200,
1047
+ body: null,
1048
+ headers: {
1049
+ 'content-type': GATEWAY_EVENT_STREAM_CONTENT_TYPE,
1050
+ 'cache-control': 'no-cache',
1051
+ connection: 'keep-alive',
1052
+ 'x-accel-buffering': 'no',
1053
+ },
1054
+ stream: {
1055
+ start: async (response, request) => {
1056
+ activeResponse = response;
1057
+ for (const event of live.replay) {
1058
+ if (closed)
1059
+ break;
1060
+ writeEvent(response, event);
1061
+ }
1062
+ const queued = buffered;
1063
+ buffered = [];
1064
+ for (const event of queued) {
1065
+ if (closed)
1066
+ break;
1067
+ writeEvent(response, event);
1068
+ }
1069
+ const heartbeat = setInterval(() => {
1070
+ if (!response.writableEnded) {
1071
+ const accepted = response.write(`${GATEWAY_EVENT_STREAM_HEARTBEAT} ${new Date().toISOString()}\n\n`);
1072
+ if (!accepted)
1073
+ closeSlowSubscriber();
1074
+ }
1075
+ }, GATEWAY_EVENT_HEARTBEAT_INTERVAL_MS);
1076
+ heartbeat.unref?.();
1077
+ await new Promise((resolve) => {
1078
+ const close = () => {
1079
+ clearInterval(heartbeat);
1080
+ unsubscribe();
1081
+ activeResponse = null;
1082
+ closed = true;
1083
+ resolve();
1084
+ };
1085
+ request.once('close', close);
1086
+ response.once('close', close);
1087
+ });
1088
+ },
1089
+ },
1090
+ };
1091
+ }
1092
+ async #recordContinuationFailure(sessionId, binding) {
1093
+ try {
1094
+ await this.#enqueueEventPersistence(sessionId, async () => {
1095
+ const persisted = this.#persisted.get(sessionId);
1096
+ if (!persisted)
1097
+ throw new GatewayPersistenceError('not_found', 'session persistence is unavailable');
1098
+ await persisted.persistence.journal.append({
1099
+ sessionId,
1100
+ type: 'turn_failed',
1101
+ payload: { turnId: binding.turnId, outcome: 'failed', reason: 'interaction_continuation_failed' },
1102
+ }, { durability: 'critical' });
1103
+ persisted.persistence.interactionCheckpoint.clear();
1104
+ });
1105
+ }
1106
+ catch {
1107
+ // If the truthful terminal fact cannot be appended, retain a sanitized
1108
+ // checkpoint so restart recovery does not lose the interaction entirely.
1109
+ try {
1110
+ this.#persisted.get(sessionId)?.persistence.interactionCheckpoint.save({
1111
+ turnId: binding.turnId,
1112
+ interaction: binding.dto,
1113
+ revision: binding.revision,
1114
+ generation: binding.continuationGeneration,
1115
+ });
1116
+ }
1117
+ catch {
1118
+ // The gateway owns this persistence failure boundary; admission
1119
+ // remains fail-closed rather than fabricating a recovery fact.
1120
+ }
1121
+ }
1122
+ }
1123
+ #enqueueEventPersistence(sessionId, work) {
1124
+ const previous = this.#eventPersistenceTails.get(sessionId) ?? Promise.resolve();
1125
+ const next = previous.catch(() => undefined).then(work);
1126
+ this.#eventPersistenceTails.set(sessionId, next);
1127
+ void next.then(() => {
1128
+ if (this.#eventPersistenceTails.get(sessionId) === next)
1129
+ this.#eventPersistenceTails.delete(sessionId);
1130
+ }, () => {
1131
+ if (this.#eventPersistenceTails.get(sessionId) === next)
1132
+ this.#eventPersistenceTails.delete(sessionId);
1133
+ });
1134
+ return next;
1135
+ }
1136
+ async #persistConversationEvent(sessionId, event, context) {
1137
+ return this.#enqueueEventPersistence(sessionId, async () => {
1138
+ const persisted = this.#persisted.get(sessionId);
1139
+ if (!persisted)
1140
+ return;
1141
+ const admissions = this.#config.persistence?.index.listAdmissions(persisted.record.ownerUserId, sessionId) ?? [];
1142
+ for (const discardedTurnId of new Set(context.discardedTurnIds)) {
1143
+ if (hasTerminalTurnEvent(persisted.persistence.journal.events(), discardedTurnId))
1144
+ continue;
1145
+ const admission = admissions.find((candidate) => candidate.turnId === discardedTurnId);
1146
+ await persisted.persistence.journal.append({
1147
+ sessionId,
1148
+ type: 'user_message_rejected',
1149
+ payload: {
1150
+ turnId: discardedTurnId,
1151
+ ...(admission ? { clientRequestId: admission.clientRequestId } : {}),
1152
+ reason: 'queue_discarded',
1153
+ },
1154
+ }, { durability: 'critical' });
1155
+ if (admission)
1156
+ this.#config.persistence?.index.updateAdmission(persisted.record.ownerUserId, sessionId, admission.clientRequestId, { state: 'rejected', result: 'queue_discarded' });
1157
+ }
1158
+ if (!context.turnId)
1159
+ return;
1160
+ const session = this.#sessions.get(sessionId);
1161
+ const snapshot = session instanceof ServerSession ? session.service.getPendingInteractionSnapshot() : null;
1162
+ const binding = event.type === 'approval_required' && snapshot
1163
+ ? this.#interactionBindingFor(sessionId, snapshot, context.turnId)
1164
+ : undefined;
1165
+ // An ask_user answer can advance the live binding before the original
1166
+ // awaitable approval sink reaches this queue. Do not republish that
1167
+ // old presentation as a second approval after interaction_updated.
1168
+ if (event.type === 'approval_required' && binding?.revision && binding.revision > 1)
1169
+ return;
1170
+ const mapped = mapConversationEvent(event, context.turnId, sessionId, binding, snapshot ?? undefined);
1171
+ if (!mapped)
1172
+ return;
1173
+ const transcriptFact = terminalTranscriptFact(event, context.turnId);
1174
+ if (transcriptFact)
1175
+ await persisted.persistence.critical.appendTranscriptCritical(transcriptFact);
1176
+ if ((mapped.type === 'approval_required' || mapped.type === 'interaction_updated') && binding) {
1177
+ persisted.persistence.interactionCheckpoint.save({
1178
+ turnId: binding.turnId,
1179
+ interaction: mapped.payload.interaction,
1180
+ revision: binding.revision,
1181
+ generation: binding.continuationGeneration,
1182
+ });
1183
+ }
1184
+ await persisted.persistence.journal.append(mapped, {
1185
+ durability: mapped.type === 'text_delta' || mapped.type === 'reasoning_delta' ? 'stream' : 'critical',
1186
+ });
1187
+ // Keep the sessions-list sequence counter live: stream deltas stay
1188
+ // non-blocking, but every critical event refreshes the index row so the
1189
+ // sidebar never reports a stale "1 events" for a running session.
1190
+ if (mapped.type !== 'text_delta' && mapped.type !== 'reasoning_delta') {
1191
+ this.#config.persistence?.index.update(sessionId, {
1192
+ lastPublishedSequence: persisted.persistence.journal.highWater().lastPublishedSequence,
1193
+ });
1194
+ }
1195
+ if (event.type === 'final' || event.type === 'error') {
1196
+ const admission = admissions.find((candidate) => candidate.turnId === context.turnId);
1197
+ if (admission && (admission.state === 'accepted' || admission.state === 'committed')) {
1198
+ try {
1199
+ this.#admissions?.markTerminal(persisted.record.ownerUserId, sessionId, admission.clientRequestId, event.type === 'final' ? 'accepted' : 'failed');
1200
+ }
1201
+ catch (error) {
1202
+ if (!(error instanceof GatewayPersistenceError) || error.code !== 'not_found')
1203
+ throw error;
1204
+ }
1205
+ }
1206
+ }
1207
+ });
1208
+ }
1209
+ #mapError(error) {
1210
+ if (error instanceof SettingsRpcError) {
1211
+ if (error.code === 'settings_conflict')
1212
+ return publicError(409, 'settings_conflict', 'settings changed; reload before retrying', false, {
1213
+ currentRevision: error.details?.currentRevision,
1214
+ ...(error.details?.projection ? { projection: error.details.projection } : {}),
1215
+ });
1216
+ if (error.code === 'settings_not_allowed')
1217
+ return publicError(403, 'settings_forbidden', 'settings change is not allowed');
1218
+ if (error.code === 'not_persisted')
1219
+ return publicError(503, 'settings_unavailable', 'settings could not be saved', true);
1220
+ return publicError(503, 'settings_unavailable', 'settings unavailable', true);
1221
+ }
1222
+ if (error instanceof DynamicWorkspaceRegistryError) {
1223
+ if (error.code === 'candidate_not_found' || error.code === 'candidate_expired')
1224
+ return publicError(404, 'not_found', 'workspace candidate not found');
1225
+ if (error.code === 'workspace_owner_mismatch' || error.code === 'workspace_path_escape')
1226
+ return publicError(403, 'workspace_forbidden', 'workspace access denied');
1227
+ if (error.code === 'candidate_registry_full')
1228
+ return publicError(429, 'candidate_registry_full', 'workspace candidate capacity is full', true);
1229
+ return publicError(422, 'validation_error', 'workspace candidate is unavailable');
1230
+ }
1231
+ if (error instanceof WorkspaceAdmissionError) {
1232
+ // One active session per workspace is a deliberate constraint; surface it
1233
+ // with a distinct code so clients can recover (e.g. select the existing
1234
+ // session) instead of seeing a generic protocol_conflict.
1235
+ if (error.code === 'workspace_session_exists')
1236
+ return publicError(409, 'session_busy', 'a session is already active for this workspace');
1237
+ return publicError(403, 'workspace_forbidden', 'workspace access denied');
1238
+ }
1239
+ if (error instanceof GatewayPersistenceError) {
1240
+ if (error.code === 'not_found' || error.code === 'owner_mismatch')
1241
+ return publicError(404, 'not_found', 'session not found');
1242
+ if (error.code === 'cursor_invalid')
1243
+ return publicError(400, 'invalid_cursor', 'cursor is invalid');
1244
+ if (error.code === 'conflict')
1245
+ return publicError(409, 'idempotency_conflict', 'request conflicts with an existing admission');
1246
+ return publicError(503, 'persistence_unavailable', 'gateway persistence unavailable', true);
1247
+ }
1248
+ if (error instanceof ServerSessionError) {
1249
+ if (error.code === 'stale_interaction')
1250
+ return publicError(409, 'stale_interaction', 'interaction is stale');
1251
+ return publicError(409, 'session_not_admitting', 'session is not admitting');
1252
+ }
1253
+ return publicError(503, 'gateway_unavailable', 'gateway unavailable', true);
1254
+ }
1255
+ static create(config) {
1256
+ let manifest;
1257
+ try {
1258
+ manifest = loadGatewayManifest(config.manifestPath, config.manifestSha256);
1259
+ }
1260
+ catch {
1261
+ throw new GatewayStartupError();
1262
+ }
1263
+ assertGatewayStartup(config, manifest);
1264
+ return new Term2Gateway(config, manifest);
1265
+ }
1266
+ get server() {
1267
+ return this.#server;
1268
+ }
1269
+ get admission() {
1270
+ return this.#admission;
1271
+ }
1272
+ get lifecycle() {
1273
+ return this.#lifecycle;
1274
+ }
1275
+ get manifestVersion() {
1276
+ return this.#admission.manifestVersion;
1277
+ }
1278
+ get interactionMetrics() {
1279
+ return Object.freeze(Object.fromEntries(INTERACTION_METRICS.map((metric) => [metric, this.#interactionCounters.get(metric) ?? 0])));
1280
+ }
1281
+ async start() {
1282
+ if (!this.#config.enabled)
1283
+ return;
1284
+ // Prove the audit path before binding the socket; a non-awaitable or
1285
+ // failing writer must never leave a seemingly-ready gateway behind.
1286
+ await this.#audit.write(createSafeLogMetadata({ operation: 'startup', outcome: 'allowed', reasonCode: 'accepted' }));
1287
+ await this.#server.start();
1288
+ }
1289
+ async createSession(claims, options, correlationId) {
1290
+ this.#lifecycle.assertAccepting();
1291
+ if (!this.#config.enabled)
1292
+ throw new GatewayStartupError();
1293
+ const binding = this.#admission.admit(claims);
1294
+ if (this.#config.runtimeFactory) {
1295
+ let persisted;
1296
+ try {
1297
+ persisted = await this.#config.persistence?.open(binding);
1298
+ const session = await this.#config.runtimeFactory.create(binding, {
1299
+ eventSink: (event, context) => {
1300
+ const persistence = this.#persistConversationEvent(binding.sessionId, event, context);
1301
+ if (isCriticalRuntimeEvent(event))
1302
+ return persistence;
1303
+ // Streaming deltas remain observationally non-blocking, but their
1304
+ // persistence failure must be consumed so it cannot become an
1305
+ // unhandled rejection. A later critical event observes the
1306
+ // journal's failure latch and is awaited by the runtime.
1307
+ void persistence.catch(() => undefined);
1308
+ return undefined;
1309
+ },
1310
+ });
1311
+ if (persisted) {
1312
+ this.#persisted.set(binding.sessionId, persisted);
1313
+ session.addDisposeHook(async () => {
1314
+ await persisted.persistence.close();
1315
+ this.#persisted.delete(binding.sessionId);
1316
+ this.#interactionBindings.delete(binding.sessionId);
1317
+ await this.#config.persistence?.close(binding.sessionId, this.#shutdownInProgress ? 'interrupted' : 'closed');
1318
+ });
1319
+ }
1320
+ const release = this.#lifecycle.registerWorker({ close: () => session.dispose() });
1321
+ session.addDisposeHook(() => {
1322
+ release();
1323
+ this.#admission.remove(binding.sessionId);
1324
+ this.#sessions.delete(binding.sessionId);
1325
+ this.#persisted.delete(binding.sessionId);
1326
+ this.#interactionBindings.delete(binding.sessionId);
1327
+ });
1328
+ this.#sessions.set(binding.sessionId, session);
1329
+ await this.#audit.write(createSafeLogMetadata({
1330
+ operation: 'session_create',
1331
+ outcome: 'allowed',
1332
+ reasonCode: 'accepted',
1333
+ sessionId: binding.sessionId,
1334
+ workspaceId: binding.workspaceId,
1335
+ grantVersion: binding.grantVersion,
1336
+ access: binding.access,
1337
+ ...(correlationId ? { correlationId } : {}),
1338
+ }));
1339
+ return session;
1340
+ }
1341
+ catch (error) {
1342
+ try {
1343
+ await persisted?.persistence.close();
1344
+ await this.#config.persistence?.close(binding.sessionId, 'interrupted');
1345
+ }
1346
+ catch {
1347
+ // Preserve the admission failure; persistence keeps its evidence.
1348
+ }
1349
+ this.#admission.remove(binding.sessionId);
1350
+ throw error;
1351
+ }
1352
+ }
1353
+ const providerProbe = this.#config.providerProbe;
1354
+ if (!providerProbe)
1355
+ throw new GatewayStartupError();
1356
+ const providerBroker = assertProviderBrokerReady(this.#config.providerBroker, providerProbe);
1357
+ const session = composeGatewaySession({
1358
+ binding,
1359
+ providerBroker,
1360
+ providerProbe,
1361
+ tmpDir: options?.tmpDir ?? this.#config.tmpDir,
1362
+ env: options?.env,
1363
+ sandboxAvailable: options?.sandboxAvailable ?? this.#config.workerSandboxAvailable,
1364
+ createRuntime: options?.createRuntime,
1365
+ });
1366
+ const release = this.#lifecycle.registerWorker({ close: () => session.dispose() });
1367
+ const originalDispose = session.dispose;
1368
+ session.dispose = () => {
1369
+ release();
1370
+ originalDispose();
1371
+ this.#admission.remove(binding.sessionId);
1372
+ this.#sessions.delete(binding.sessionId);
1373
+ };
1374
+ this.#sessions.set(binding.sessionId, session);
1375
+ await this.#audit.write(createSafeLogMetadata({
1376
+ operation: 'session_create',
1377
+ outcome: 'allowed',
1378
+ reasonCode: 'accepted',
1379
+ sessionId: binding.sessionId,
1380
+ workspaceId: binding.workspaceId,
1381
+ grantVersion: binding.grantVersion,
1382
+ access: binding.access,
1383
+ ...(correlationId ? { correlationId } : {}),
1384
+ }));
1385
+ return session;
1386
+ }
1387
+ async shutdown(graceMs = 5_000) {
1388
+ if (this.#shutdownPromise)
1389
+ return this.#shutdownPromise;
1390
+ this.#shutdownInProgress = true;
1391
+ const hardDeadlineMs = Math.max(1, graceMs);
1392
+ this.#shutdownPromise = (async () => {
1393
+ const deadline = Date.now() + hardDeadlineMs;
1394
+ let forced = false;
1395
+ const remaining = () => Math.max(1, deadline - Date.now());
1396
+ const waitBounded = async (work) => {
1397
+ let timer;
1398
+ const completed = await Promise.race([
1399
+ work.then(() => true, () => true),
1400
+ new Promise((resolve) => {
1401
+ timer = setTimeout(() => resolve(false), remaining());
1402
+ }),
1403
+ ]);
1404
+ if (timer)
1405
+ clearTimeout(timer);
1406
+ return completed;
1407
+ };
1408
+ const markForced = () => {
1409
+ if (forced)
1410
+ return;
1411
+ forced = true;
1412
+ for (const sessionId of this.#persisted.keys())
1413
+ this.#config.persistence?.markForcedShutdown(sessionId);
1414
+ };
1415
+ if (!(await waitBounded(this.#server.shutdown(remaining()))))
1416
+ markForced();
1417
+ if (!(await waitBounded(Promise.all([...this.#sessions.values()].map((session) => Promise.resolve(session.dispose()))))))
1418
+ markForced();
1419
+ if (this.#config.runtimeFactory && !(await waitBounded(this.#config.runtimeFactory.shutdown(remaining()))))
1420
+ markForced();
1421
+ this.#sessions.clear();
1422
+ this.#replay.close();
1423
+ // The audit record is bounded by the same deadline. A broken audit sink
1424
+ // must not keep the local owner process alive indefinitely.
1425
+ await waitBounded(this.#audit.write(createSafeLogMetadata({
1426
+ operation: 'shutdown',
1427
+ outcome: forced ? 'interrupted' : 'allowed',
1428
+ reasonCode: forced ? 'forced_shutdown' : 'shutdown',
1429
+ })));
1430
+ })();
1431
+ return this.#shutdownPromise;
1432
+ }
1433
+ }
1434
+ function matchPrivateRoute(method, pathname) {
1435
+ if (method === 'POST' && pathname === '/')
1436
+ return { purpose: 'session_create', legacy: true };
1437
+ // GET is canonical for workspace_list; POST is a tested compatibility alias for the pinned BFF wire.
1438
+ if ((method === 'GET' || method === 'POST') && pathname === '/private/agent/v1/workspaces')
1439
+ return { purpose: 'workspace_list' };
1440
+ if (method === 'POST' && pathname === '/private/agent/v1/workspace/candidates/validate')
1441
+ return { purpose: 'workspace_candidate_validate' };
1442
+ if (method === 'POST' && pathname === '/private/agent/v1/workspace/candidates/browse')
1443
+ return { purpose: 'workspace_candidate_browse' };
1444
+ if (method === 'POST' && pathname === '/private/agent/v1/workspace/candidates/select')
1445
+ return { purpose: 'workspace_candidate_select' };
1446
+ if (method === 'GET' && pathname === '/private/agent/v1/models')
1447
+ return { purpose: 'model_list' };
1448
+ if (method === 'GET' && pathname === '/private/agent/v1/settings')
1449
+ return { purpose: 'settings_read' };
1450
+ if (method === 'PUT' && pathname === '/private/agent/v1/settings')
1451
+ return { purpose: 'settings_write' };
1452
+ const credential = pathname.match(/^\/private\/agent\/v1\/credentials\/([A-Za-z0-9_-]{1,256})$/);
1453
+ if (credential && method === 'POST')
1454
+ return { purpose: 'credential_write', interactionId: credential[1] };
1455
+ if (credential && method === 'DELETE')
1456
+ return { purpose: 'credential_delete', interactionId: credential[1] };
1457
+ const oauth = pathname.match(/^\/private\/agent\/v1\/oauth\/([A-Za-z0-9_-]{1,256})\/(login|select)$/);
1458
+ if (oauth && method === 'POST')
1459
+ return {
1460
+ purpose: oauth[2] === 'login' ? 'oauth_login' : 'oauth_select',
1461
+ interactionId: `${oauth[1]}\u0000${oauth[2]}`,
1462
+ };
1463
+ const oauthDelete = pathname.match(/^\/private\/agent\/v1\/oauth\/([A-Za-z0-9_-]{1,256})\/accounts\/([A-Za-z0-9_-]{1,256})$/);
1464
+ if (oauthDelete && method === 'DELETE')
1465
+ return { purpose: 'oauth_delete', interactionId: `${oauthDelete[1]}\u0000${oauthDelete[2]}` };
1466
+ if (method === 'POST' && pathname === '/private/agent/v1/sessions')
1467
+ return { purpose: 'session_create' };
1468
+ if (method === 'GET' && pathname === '/private/agent/v1/sessions')
1469
+ return { purpose: 'session_list' };
1470
+ const match = pathname.match(/^\/private\/agent\/v1\/sessions\/([A-Za-z0-9_-]{1,256})(?:\/(messages|abort|events|config|interactions\/([A-Za-z0-9_-]{1,256})))?$/);
1471
+ if (!match)
1472
+ return null;
1473
+ const sessionId = match[1];
1474
+ if (method === 'POST' && !match[2])
1475
+ return { purpose: 'session_read', sessionId };
1476
+ if (method === 'POST' && match[2] === 'messages')
1477
+ return { purpose: 'message_submit', sessionId };
1478
+ if (method === 'POST' && match[2] === 'abort')
1479
+ return { purpose: 'abort', sessionId };
1480
+ if (method === 'GET' && match[2] === 'events')
1481
+ return { purpose: 'events_connect', sessionId };
1482
+ if (method === 'POST' && match[2] === 'config')
1483
+ return { purpose: 'session_update', sessionId };
1484
+ if (method === 'POST' && match[2]?.startsWith('interactions/'))
1485
+ return { purpose: 'interaction_resolve', sessionId, interactionId: match[3] };
1486
+ return null;
1487
+ }
1488
+ function deriveDynamicWorkspaceRoots(manifest) {
1489
+ const roots = new Set();
1490
+ for (const grant of manifest.grants) {
1491
+ if (grant.kind !== 'local' || !grant.localRoot)
1492
+ continue;
1493
+ try {
1494
+ const canonical = realpathSync(grant.localRoot);
1495
+ if (statSync(canonical).isDirectory())
1496
+ roots.add(canonical);
1497
+ }
1498
+ catch {
1499
+ // A stale manifest root remains a v1 admission error; it must not make
1500
+ // the otherwise-compatible gateway fail before the candidate route is used.
1501
+ }
1502
+ }
1503
+ return [...roots];
1504
+ }
1505
+ export function classifyInteractionResolution(interaction, hasLiveSnapshot) {
1506
+ if (hasLiveSnapshot)
1507
+ return null;
1508
+ if (interaction?.state === 'recovered')
1509
+ return 'interaction_not_resolvable';
1510
+ return 'interaction_already_resolved';
1511
+ }
1512
+ function hasDeferredModelSelectionField(body) {
1513
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1514
+ return false;
1515
+ return Object.keys(body).some((key) => ['model', 'reasoningEffort', 'mode'].includes(key));
1516
+ }
1517
+ function isSessionCreateBody(body, workspaceId, legacy = false) {
1518
+ if (legacy && body === null)
1519
+ return true;
1520
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1521
+ return false;
1522
+ const keys = Object.keys(body);
1523
+ if (keys.some((key) => key !== 'workspaceId'))
1524
+ return false;
1525
+ const requested = body.workspaceId;
1526
+ return typeof requested === 'string' && requested === workspaceId;
1527
+ }
1528
+ function isWorkspaceCandidateValidateBody(body) {
1529
+ return (!!body &&
1530
+ typeof body === 'object' &&
1531
+ !Array.isArray(body) &&
1532
+ Object.keys(body).length === 1 &&
1533
+ typeof body.absolutePath === 'string');
1534
+ }
1535
+ function isWorkspaceCandidateBrowseBody(body) {
1536
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1537
+ return false;
1538
+ const value = body;
1539
+ return (Object.keys(value).every((key) => key === 'candidateId' || key === 'child') &&
1540
+ isOpaqueId(value.candidateId) &&
1541
+ (value.child === undefined || isOpaqueId(value.child)));
1542
+ }
1543
+ function isWorkspaceCandidateSelectBody(body) {
1544
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1545
+ return false;
1546
+ const value = body;
1547
+ return (Object.keys(value).length === 2 &&
1548
+ Object.keys(value).every((key) => key === 'candidateId' || key === 'access') &&
1549
+ isOpaqueId(value.candidateId) &&
1550
+ (value.access === 'read' || value.access === 'read_write'));
1551
+ }
1552
+ function isSettingsWriteBody(body) {
1553
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1554
+ return false;
1555
+ const value = body;
1556
+ if (typeof value.expectedRevision !== 'string' || !Array.isArray(value.changes) || value.changes.length > 100)
1557
+ return false;
1558
+ return value.changes.every((change) => {
1559
+ if (!change || typeof change !== 'object' || Array.isArray(change))
1560
+ return false;
1561
+ const item = change;
1562
+ return (Object.keys(item).length === 2 &&
1563
+ typeof item.key === 'string' &&
1564
+ Object.prototype.hasOwnProperty.call(item, 'value') &&
1565
+ isSafeSettingsValue(item.value));
1566
+ });
1567
+ }
1568
+ function isPairingRegisterBody(body) {
1569
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1570
+ return false;
1571
+ const value = body;
1572
+ return (Object.keys(value).length === 2 &&
1573
+ typeof value.publicKeyPem === 'string' &&
1574
+ value.publicKeyPem.length > 0 &&
1575
+ value.publicKeyPem.length <= 16_384 &&
1576
+ typeof value.otp === 'string' &&
1577
+ /^\d{6}$/.test(value.otp));
1578
+ }
1579
+ function isSafeSettingsValue(value) {
1580
+ return (value === null ||
1581
+ typeof value === 'string' ||
1582
+ typeof value === 'number' ||
1583
+ typeof value === 'boolean' ||
1584
+ (Array.isArray(value) && value.every((item) => typeof item === 'string')));
1585
+ }
1586
+ function isCredentialWriteBody(body) {
1587
+ return (!!body &&
1588
+ typeof body === 'object' &&
1589
+ !Array.isArray(body) &&
1590
+ Object.keys(body).length === 1 &&
1591
+ typeof body.value === 'string' &&
1592
+ body.value.length > 0);
1593
+ }
1594
+ function isOAuthSelectBody(body) {
1595
+ return (!!body &&
1596
+ typeof body === 'object' &&
1597
+ !Array.isArray(body) &&
1598
+ Object.keys(body).length === 1 &&
1599
+ isOpaqueId(body.accountId));
1600
+ }
1601
+ function isSessionUpdateBody(body) {
1602
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1603
+ return false;
1604
+ const value = body;
1605
+ if (Object.keys(value).some((key) => !['model', 'reasoningEffort', 'mode'].includes(key)))
1606
+ return false;
1607
+ if (value.model !== undefined &&
1608
+ (typeof value.model !== 'string' || value.model.length === 0 || value.model.length > 512))
1609
+ return false;
1610
+ if (value.reasoningEffort !== undefined &&
1611
+ !['default', 'none', 'minimal', 'low', 'medium', 'high', 'xhigh'].includes(String(value.reasoningEffort)))
1612
+ return false;
1613
+ return (value.mode === undefined || ['standard', 'lite', 'plan', 'mentor', 'orchestrator'].includes(String(value.mode)));
1614
+ }
1615
+ export function sessionConfigProjection(session) {
1616
+ const snapshot = session.resources.settings;
1617
+ const service = session.resources.sessionSettingsService;
1618
+ const get = (key, fallback) => service?.getDynamic(key) ?? fallback;
1619
+ const snapshotPolicy = snapshot.toolPolicy ?? {};
1620
+ const sessionPolicy = session.resources.settings.toolPolicy ?? {};
1621
+ const toolPolicy = {
1622
+ allowWrite: sessionPolicy.allowWrite ?? snapshotPolicy.allowWrite ?? false,
1623
+ autoApprove: sessionPolicy.autoApprove ?? snapshotPolicy.autoApprove ?? false,
1624
+ allowUnsandboxed: sessionPolicy.allowUnsandboxed ?? snapshotPolicy.allowUnsandboxed ?? false,
1625
+ sshEnabled: sessionPolicy.sshEnabled ?? snapshotPolicy.sshEnabled ?? false,
1626
+ };
1627
+ const settings = {
1628
+ providerId: get('agent.provider', snapshot.providerId),
1629
+ modelId: get('agent.model', snapshot.modelId),
1630
+ reasoningEffort: get('agent.reasoningEffort', snapshot.reasoningEffort ?? 'default'),
1631
+ mode: get('app.orchestratorMode', false)
1632
+ ? 'orchestrator'
1633
+ : get('app.liteMode', false)
1634
+ ? 'lite'
1635
+ : get('app.planMode', false)
1636
+ ? 'plan'
1637
+ : get('app.mentorMode', false)
1638
+ ? 'mentor'
1639
+ : snapshot.mode ?? 'standard',
1640
+ toolPolicy,
1641
+ defaultsRevision: snapshot.defaultsRevision,
1642
+ };
1643
+ return {
1644
+ sessionId: session.sessionId,
1645
+ providerId: settings.providerId ?? 'unknown',
1646
+ modelId: settings.modelId ?? 'unknown',
1647
+ reasoningEffort: settings.reasoningEffort ?? 'default',
1648
+ mode: settings.mode ?? 'standard',
1649
+ toolPolicy,
1650
+ configRevision: crypto.createHash('sha256').update(JSON.stringify(settings)).digest('hex'),
1651
+ defaultsRevision: settings.defaultsRevision ?? 'unknown',
1652
+ };
1653
+ }
1654
+ function isOpaqueId(value) {
1655
+ return typeof value === 'string' && /^[A-Za-z0-9_-]{1,256}$/.test(value);
1656
+ }
1657
+ function hasAttachments(body) {
1658
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1659
+ return false;
1660
+ return Object.keys(body).some((key) => ['images', 'attachments', 'attachmentIds'].includes(key));
1661
+ }
1662
+ function isMessageBody(body) {
1663
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1664
+ return false;
1665
+ const value = body;
1666
+ return (Object.keys(value).every((key) => key === 'text' || key === 'clientRequestId') &&
1667
+ typeof value.text === 'string' &&
1668
+ value.text.length > 0 &&
1669
+ value.text.length <= 128_000 &&
1670
+ isOpaqueId(value.clientRequestId));
1671
+ }
1672
+ function isTurnBody(body) {
1673
+ return (!!body &&
1674
+ typeof body === 'object' &&
1675
+ !Array.isArray(body) &&
1676
+ Object.keys(body).length === 1 &&
1677
+ isOpaqueId(body.turnId));
1678
+ }
1679
+ export function isInteractionResolveRequest(body) {
1680
+ if (!body || typeof body !== 'object' || Array.isArray(body))
1681
+ return false;
1682
+ const value = body;
1683
+ return (Object.keys(value).every((key) => ['revision', 'answer', 'rejectionReason', 'approvalAnswer'].includes(key)) &&
1684
+ typeof value.revision === 'number' &&
1685
+ Number.isSafeInteger(value.revision) &&
1686
+ value.revision >= 1 &&
1687
+ typeof value.answer === 'string' &&
1688
+ value.answer.length <= 16_384 &&
1689
+ (value.rejectionReason === undefined || typeof value.rejectionReason === 'string') &&
1690
+ (value.approvalAnswer === undefined || typeof value.approvalAnswer === 'string'));
1691
+ }
1692
+ function parseQueryLimit(value) {
1693
+ if (value === null)
1694
+ return undefined;
1695
+ if (!/^[0-9]{1,3}$/.test(value))
1696
+ throw new GatewayPersistenceError('cursor_invalid', 'limit is invalid');
1697
+ return Number(value);
1698
+ }
1699
+ function parseEventCursor(value) {
1700
+ if (value === null)
1701
+ return { value: null };
1702
+ if (!/^(?:0|[1-9][0-9]{0,14})$/.test(value))
1703
+ return { value: null, error: 'cursor_invalid' };
1704
+ const parsed = Number(value);
1705
+ return Number.isSafeInteger(parsed) ? { value: parsed } : { value: null, error: 'cursor_invalid' };
1706
+ }
1707
+ function publicError(status, code, message, retryable, details) {
1708
+ return {
1709
+ status,
1710
+ body: {
1711
+ error: { code, message, ...(retryable === undefined ? {} : { retryable }), ...(details ? { details } : {}) },
1712
+ },
1713
+ };
1714
+ }
1715
+ function isPublicEventEnvelope(event) {
1716
+ if (event.schemaVersion !== 1 ||
1717
+ !Number.isSafeInteger(event.id) ||
1718
+ !isOpaqueId(event.sessionId) ||
1719
+ !FROZEN_AGENT_EVENT_TYPES.includes(event.type) ||
1720
+ typeof event.occurredAt !== 'string' ||
1721
+ !event.payload ||
1722
+ typeof event.payload !== 'object' ||
1723
+ Array.isArray(event.payload))
1724
+ return false;
1725
+ try {
1726
+ if (event.type === 'approval_required' ||
1727
+ event.type === 'interaction_updated' ||
1728
+ event.type === 'interaction_recovered') {
1729
+ if (!event.payload.interaction ||
1730
+ typeof event.payload.interaction !== 'object' ||
1731
+ !validatePendingInteractionDto(event.payload.interaction))
1732
+ return false;
1733
+ if (event.type === 'interaction_recovered' &&
1734
+ !['daemon_restart', 'forced_shutdown', 'persistence_recovery'].includes(String(event.payload.reason)))
1735
+ return false;
1736
+ }
1737
+ if (event.type === 'interaction_resolved') {
1738
+ const keys = Object.keys(event.payload).sort();
1739
+ if (keys.join(',') !== 'interactionId,outcome,turnId,variant')
1740
+ return false;
1741
+ if (!isOpaqueId(event.payload.interactionId) ||
1742
+ !['approved', 'rejected', 'cancelled', 'continued'].includes(String(event.payload.outcome)))
1743
+ return false;
1744
+ }
1745
+ }
1746
+ catch {
1747
+ return false;
1748
+ }
1749
+ const visit = (value, depth = 0) => {
1750
+ if (depth > 8)
1751
+ return false;
1752
+ if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean')
1753
+ return typeof value !== 'string' || value.length <= 32_000;
1754
+ if (Array.isArray(value))
1755
+ return value.length <= 512 && value.every((item) => visit(item, depth + 1));
1756
+ if (typeof value !== 'object')
1757
+ return false;
1758
+ return Object.entries(value).every(([key, child]) => PUBLIC_EVENT_PAYLOAD_KEYS.has(key) && visit(child, depth + 1));
1759
+ };
1760
+ return visit(event.payload);
1761
+ }
1762
+ function boundedText(value, max = 8_192) {
1763
+ return typeof value === 'string' ? value.slice(0, max) : '';
1764
+ }
1765
+ function interactionDtoFromApproval(approval, interactionId, revision) {
1766
+ return projectPendingInteraction(approval, interactionId, revision);
1767
+ }
1768
+ function interactionDtoFromSnapshot(snapshot, interactionId, revision) {
1769
+ return projectPendingInteraction(snapshot.approval, interactionId, revision, snapshot.askUserAnswers, snapshot.currentAskUserQuestionIndex);
1770
+ }
1771
+ function sanitizePublicInteraction(value) {
1772
+ return validatePendingInteractionDto(value);
1773
+ }
1774
+ const PROJECTION_COMMAND_STATUSES = new Set(['completed', 'failed', 'aborted', 'unknown']);
1775
+ function projectTranscriptMessages(transcript, journalCommands) {
1776
+ if (!transcript)
1777
+ return [];
1778
+ const commandsByTurn = new Map();
1779
+ const addCommand = (turnId, command) => {
1780
+ const commands = commandsByTurn.get(turnId) ?? [];
1781
+ if (!commands.some((candidate) => candidate.callId === command.callId))
1782
+ commands.push(command);
1783
+ commandsByTurn.set(turnId, commands.slice(0, 64));
1784
+ };
1785
+ for (const command of transcript.toolLedger) {
1786
+ if (!PROJECTION_COMMAND_STATUSES.has(command.status))
1787
+ continue;
1788
+ addCommand(command.turnId, {
1789
+ callId: boundedText(command.callId, 256),
1790
+ toolName: boundedText(command.toolName, 256),
1791
+ status: boundedText(command.status, 32),
1792
+ });
1793
+ }
1794
+ for (const [turnId, commands] of journalCommands) {
1795
+ for (const command of commands) {
1796
+ const existing = commandsByTurn.get(turnId)?.find((candidate) => candidate.callId === command.callId);
1797
+ if (existing) {
1798
+ const current = commandsByTurn.get(turnId);
1799
+ commandsByTurn.set(turnId, current.map((candidate) => (candidate.callId === command.callId ? command : candidate)));
1800
+ }
1801
+ else {
1802
+ addCommand(turnId, command);
1803
+ }
1804
+ }
1805
+ }
1806
+ const projected = [];
1807
+ let currentTurnId = null;
1808
+ const attachedTurns = new Set();
1809
+ for (const message of transcript.messages) {
1810
+ const record = message;
1811
+ const sender = typeof record.sender === 'string' ? record.sender : record.role;
1812
+ if (sender === 'user') {
1813
+ currentTurnId = typeof record.id === 'string' ? record.id : null;
1814
+ }
1815
+ if (sender === 'command' || sender === 'reasoning') {
1816
+ if (sender === 'command' &&
1817
+ currentTurnId &&
1818
+ typeof record.callId === 'string' &&
1819
+ typeof record.toolName === 'string' &&
1820
+ typeof record.status === 'string' &&
1821
+ !commandsByTurn.get(currentTurnId)?.some((command) => command.callId === record.callId)) {
1822
+ addCommand(currentTurnId, {
1823
+ callId: boundedText(record.callId, 256),
1824
+ toolName: boundedText(record.toolName, 256),
1825
+ status: boundedText(record.status, 32),
1826
+ });
1827
+ }
1828
+ continue;
1829
+ }
1830
+ const role = sender === 'user' ? 'user' : 'bot';
1831
+ const projectedMessage = {
1832
+ id: boundedText(record.id, 256),
1833
+ role,
1834
+ text: boundedText(record.text, 16_384),
1835
+ };
1836
+ const commands = role === 'bot' && currentTurnId ? commandsByTurn.get(currentTurnId) : undefined;
1837
+ if (commands && commands.length > 0 && !attachedTurns.has(currentTurnId)) {
1838
+ projectedMessage.commands = commands;
1839
+ attachedTurns.add(currentTurnId);
1840
+ }
1841
+ projected.push(projectedMessage);
1842
+ }
1843
+ return projected.slice(-200);
1844
+ }
1845
+ /**
1846
+ * Session transcript wire shape: messages have `id`, `role` (`user` or `bot`),
1847
+ * and bounded `text`. A completed turn's first bot message may carry a bounded
1848
+ * `commands` array of `{callId, toolName, status}` entries for its tool cards.
1849
+ */
1850
+ function toSessionProjection(source) {
1851
+ const transcript = source.transcript;
1852
+ const messages = projectTranscriptMessages(transcript, source.journalCommands);
1853
+ const interaction = source.interaction
1854
+ ? {
1855
+ ...source.interaction,
1856
+ interaction: sanitizePublicInteraction(source.interaction.interaction),
1857
+ }
1858
+ : null;
1859
+ return {
1860
+ id: source.session.id,
1861
+ workspaceId: source.session.workspaceId,
1862
+ status: source.session.status === 'initializing' ? 'idle' : source.session.status,
1863
+ createdAt: source.session.createdAt,
1864
+ updatedAt: source.session.updatedAt,
1865
+ latestSequence: source.latestSequence,
1866
+ earliestReplayableSequence: source.earliestReplayableSequence,
1867
+ projectionSequence: source.projectionSequence,
1868
+ transcript: { messages, ...(transcript?.updatedAt ? { updatedAt: transcript.updatedAt } : {}) },
1869
+ interaction,
1870
+ };
1871
+ }
1872
+ // Terminal runtime final/error events have two durable representations: the
1873
+ // public journal and the replay transcript. Aborts intentionally settle only
1874
+ // the journal so replay retains interruption semantics.
1875
+ function hasTerminalTurnEvent(events, turnId) {
1876
+ return events.some((event) => TERMINAL_AGENT_EVENT_TYPES.has(event.type) && event.payload.turnId === turnId);
1877
+ }
1878
+ function terminalTranscriptFact(event, turnId) {
1879
+ if (event.type === 'final') {
1880
+ const items = event.turnItems ? [...event.turnItems] : [];
1881
+ if (!items.some((item) => item.type === 'assistant_text')) {
1882
+ items.push({ type: 'assistant_text', text: boundedText(event.finalText, 16_384) });
1883
+ }
1884
+ return { type: 'assistant_turn', turnId, turn: { items } };
1885
+ }
1886
+ if (event.type === 'error') {
1887
+ return {
1888
+ type: 'assistant_turn',
1889
+ turnId,
1890
+ turn: { items: [{ type: 'assistant_text', text: boundedText(event.finalText ?? event.message, 16_384) }] },
1891
+ };
1892
+ }
1893
+ return null;
1894
+ }
1895
+ function mapConversationEvent(event, turnId, sessionId, interactionBinding, interactionSnapshot) {
1896
+ const base = { sessionId, payload: { turnId } };
1897
+ switch (event.type) {
1898
+ // The gateway-owned assistant_started admission marker is appended before
1899
+ // runtime commit in #submitMessage. ConversationEvent still has no provider
1900
+ // first-token signal, so this mapper never invents one from a delta.
1901
+ case 'text_delta':
1902
+ return { ...base, type: 'text_delta', payload: { turnId, delta: boundedText(event.delta) } };
1903
+ case 'reasoning_delta':
1904
+ return { ...base, type: 'reasoning_delta', payload: { turnId, delta: boundedText(event.delta) } };
1905
+ case 'tool_started':
1906
+ return {
1907
+ ...base,
1908
+ type: 'tool_started',
1909
+ payload: { turnId, callId: event.toolCallId, toolName: boundedText(event.toolName, 256) },
1910
+ };
1911
+ case 'command_message':
1912
+ return {
1913
+ ...base,
1914
+ type: 'command_message',
1915
+ payload: {
1916
+ turnId,
1917
+ message: {
1918
+ id: boundedText(event.message.id, 256),
1919
+ role: boundedText(event.message.sender ?? event.message.role, 32),
1920
+ text: boundedText(event.message.text, 16_384),
1921
+ },
1922
+ },
1923
+ };
1924
+ case 'approval_required': {
1925
+ if (!interactionBinding)
1926
+ return null;
1927
+ return {
1928
+ ...base,
1929
+ type: 'approval_required',
1930
+ payload: {
1931
+ turnId,
1932
+ interaction: interactionSnapshot
1933
+ ? interactionDtoFromSnapshot(interactionSnapshot, interactionBinding.publicInteractionId, interactionBinding.revision)
1934
+ : interactionDtoFromApproval(event.approval, interactionBinding.publicInteractionId, interactionBinding.revision),
1935
+ },
1936
+ };
1937
+ }
1938
+ case 'usage_update':
1939
+ return {
1940
+ ...base,
1941
+ type: 'usage_update',
1942
+ payload: {
1943
+ turnId,
1944
+ usage: { inputTokens: event.usage.prompt_tokens, outputTokens: event.usage.completion_tokens },
1945
+ },
1946
+ };
1947
+ case 'final':
1948
+ return {
1949
+ ...base,
1950
+ type: 'turn_completed',
1951
+ payload: { turnId, outcome: 'completed', text: boundedText(event.finalText, 16_384) },
1952
+ };
1953
+ case 'error':
1954
+ return { ...base, type: 'turn_failed', payload: { turnId, outcome: 'failed', reason: 'runtime_error' } };
1955
+ default:
1956
+ return null;
1957
+ }
1958
+ }
1959
+ export { createGatewayAssertion, interactionDtoFromSnapshot, isPublicEventEnvelope };
1960
+ //# sourceMappingURL=gateway.js.map