@qduc/term2 0.15.0 → 0.17.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 (696) 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 +16 -64
  5. package/dist/agent.js.map +1 -1
  6. package/dist/app.d.ts +1 -1
  7. package/dist/app.d.ts.map +1 -1
  8. package/dist/app.js +129 -19
  9. package/dist/app.js.map +1 -1
  10. package/dist/cli.js +52 -17
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/auto-approve-command.d.ts +2 -1
  13. package/dist/commands/auto-approve-command.d.ts.map +1 -1
  14. package/dist/commands/auto-approve-command.js +16 -27
  15. package/dist/commands/auto-approve-command.js.map +1 -1
  16. package/dist/commands/compact-command.d.ts.map +1 -1
  17. package/dist/commands/compact-command.js +4 -0
  18. package/dist/commands/compact-command.js.map +1 -1
  19. package/dist/commands/effort-command.js +1 -1
  20. package/dist/commands/effort-command.js.map +1 -1
  21. package/dist/commands/guarded-settings-command.d.ts.map +1 -1
  22. package/dist/commands/guarded-settings-command.js +4 -8
  23. package/dist/commands/guarded-settings-command.js.map +1 -1
  24. package/dist/commands/model-command.js +1 -1
  25. package/dist/commands/model-command.js.map +1 -1
  26. package/dist/commands/resume-command.d.ts +11 -0
  27. package/dist/commands/resume-command.d.ts.map +1 -0
  28. package/dist/commands/resume-command.js +41 -0
  29. package/dist/commands/resume-command.js.map +1 -0
  30. package/dist/components/ErrorBoundary.d.ts.map +1 -1
  31. package/dist/components/ErrorBoundary.js +5 -4
  32. package/dist/components/ErrorBoundary.js.map +1 -1
  33. package/dist/components/InputBox.d.ts +2 -0
  34. package/dist/components/InputBox.d.ts.map +1 -1
  35. package/dist/components/InputBox.js +56 -18
  36. package/dist/components/InputBox.js.map +1 -1
  37. package/dist/components/MarkdownRenderer.d.ts.map +1 -1
  38. package/dist/components/MarkdownRenderer.js +16 -15
  39. package/dist/components/MarkdownRenderer.js.map +1 -1
  40. package/dist/components/common/MenuContainer.d.ts +25 -2
  41. package/dist/components/common/MenuContainer.d.ts.map +1 -1
  42. package/dist/components/common/MenuContainer.js +35 -11
  43. package/dist/components/common/MenuContainer.js.map +1 -1
  44. package/dist/components/common/ScrollableTabBar.d.ts.map +1 -1
  45. package/dist/components/common/ScrollableTabBar.js +5 -4
  46. package/dist/components/common/ScrollableTabBar.js.map +1 -1
  47. package/dist/components/input/ApplicationInputSurface.d.ts +7 -5
  48. package/dist/components/input/ApplicationInputSurface.d.ts.map +1 -1
  49. package/dist/components/input/ApplicationInputSurface.js +7 -0
  50. package/dist/components/input/ApplicationInputSurface.js.map +1 -1
  51. package/dist/components/input/FirstRunSetupPrompt.d.ts.map +1 -1
  52. package/dist/components/input/FirstRunSetupPrompt.js +5 -4
  53. package/dist/components/input/FirstRunSetupPrompt.js.map +1 -1
  54. package/dist/components/input/MenuSurface.d.ts.map +1 -1
  55. package/dist/components/input/MenuSurface.js +10 -3
  56. package/dist/components/input/MenuSurface.js.map +1 -1
  57. package/dist/components/input/ModelMenuSession.d.ts.map +1 -1
  58. package/dist/components/input/ModelMenuSession.js +2 -1
  59. package/dist/components/input/ModelMenuSession.js.map +1 -1
  60. package/dist/components/input/PendingQueueList.d.ts +2 -0
  61. package/dist/components/input/PendingQueueList.d.ts.map +1 -1
  62. package/dist/components/input/PendingQueueList.js +17 -14
  63. package/dist/components/input/PendingQueueList.js.map +1 -1
  64. package/dist/components/input/ResumeMenuSession.d.ts +17 -0
  65. package/dist/components/input/ResumeMenuSession.d.ts.map +1 -0
  66. package/dist/components/input/ResumeMenuSession.js +57 -0
  67. package/dist/components/input/ResumeMenuSession.js.map +1 -0
  68. package/dist/components/input/SettingsValueMenuSession.d.ts.map +1 -1
  69. package/dist/components/input/SettingsValueMenuSession.js +2 -1
  70. package/dist/components/input/SettingsValueMenuSession.js.map +1 -1
  71. package/dist/components/input/determine-active-menu.d.ts +3 -0
  72. package/dist/components/input/determine-active-menu.d.ts.map +1 -1
  73. package/dist/components/input/determine-active-menu.js +10 -5
  74. package/dist/components/input/determine-active-menu.js.map +1 -1
  75. package/dist/components/input/menu-registry.d.ts.map +1 -1
  76. package/dist/components/input/menu-registry.js +2 -0
  77. package/dist/components/input/menu-registry.js.map +1 -1
  78. package/dist/components/input/menu-types.d.ts +4 -0
  79. package/dist/components/input/menu-types.d.ts.map +1 -1
  80. package/dist/components/input/triggers.d.ts +1 -0
  81. package/dist/components/input/triggers.d.ts.map +1 -1
  82. package/dist/components/input/triggers.js +26 -0
  83. package/dist/components/input/triggers.js.map +1 -1
  84. package/dist/components/layout/BackgroundTaskManager.d.ts.map +1 -1
  85. package/dist/components/layout/BackgroundTaskManager.js +12 -11
  86. package/dist/components/layout/BackgroundTaskManager.js.map +1 -1
  87. package/dist/components/layout/BackgroundTasksPanel.d.ts +2 -2
  88. package/dist/components/layout/BackgroundTasksPanel.d.ts.map +1 -1
  89. package/dist/components/layout/BackgroundTasksPanel.js +10 -9
  90. package/dist/components/layout/BackgroundTasksPanel.js.map +1 -1
  91. package/dist/components/layout/Banner.d.ts +0 -1
  92. package/dist/components/layout/Banner.d.ts.map +1 -1
  93. package/dist/components/layout/Banner.js +43 -73
  94. package/dist/components/layout/Banner.js.map +1 -1
  95. package/dist/components/layout/BottomArea.d.ts +8 -5
  96. package/dist/components/layout/BottomArea.d.ts.map +1 -1
  97. package/dist/components/layout/BottomArea.js +17 -9
  98. package/dist/components/layout/BottomArea.js.map +1 -1
  99. package/dist/components/layout/DiffView.js +5 -5
  100. package/dist/components/layout/DiffView.js.map +1 -1
  101. package/dist/components/layout/StatusBar.d.ts +4 -1
  102. package/dist/components/layout/StatusBar.d.ts.map +1 -1
  103. package/dist/components/layout/StatusBar.js +305 -95
  104. package/dist/components/layout/StatusBar.js.map +1 -1
  105. package/dist/components/layout/background-task-clock.d.ts +43 -0
  106. package/dist/components/layout/background-task-clock.d.ts.map +1 -0
  107. package/dist/components/layout/background-task-clock.js +46 -0
  108. package/dist/components/layout/background-task-clock.js.map +1 -0
  109. package/dist/components/menu/CopyMenu.d.ts.map +1 -1
  110. package/dist/components/menu/CopyMenu.js +4 -3
  111. package/dist/components/menu/CopyMenu.js.map +1 -1
  112. package/dist/components/menu/MentorPoolSelectionMenu.d.ts.map +1 -1
  113. package/dist/components/menu/MentorPoolSelectionMenu.js +28 -21
  114. package/dist/components/menu/MentorPoolSelectionMenu.js.map +1 -1
  115. package/dist/components/menu/ModelSelectionMenu.d.ts.map +1 -1
  116. package/dist/components/menu/ModelSelectionMenu.js +26 -13
  117. package/dist/components/menu/ModelSelectionMenu.js.map +1 -1
  118. package/dist/components/menu/PathSelectionMenu.d.ts.map +1 -1
  119. package/dist/components/menu/PathSelectionMenu.js +4 -3
  120. package/dist/components/menu/PathSelectionMenu.js.map +1 -1
  121. package/dist/components/menu/ProviderSelectionMenu.d.ts.map +1 -1
  122. package/dist/components/menu/ProviderSelectionMenu.js +46 -26
  123. package/dist/components/menu/ProviderSelectionMenu.js.map +1 -1
  124. package/dist/components/menu/ResumeSelectionMenu.d.ts +11 -0
  125. package/dist/components/menu/ResumeSelectionMenu.d.ts.map +1 -0
  126. package/dist/components/menu/ResumeSelectionMenu.js +91 -0
  127. package/dist/components/menu/ResumeSelectionMenu.js.map +1 -0
  128. package/dist/components/menu/RewindMenu.d.ts.map +1 -1
  129. package/dist/components/menu/RewindMenu.js +4 -3
  130. package/dist/components/menu/RewindMenu.js.map +1 -1
  131. package/dist/components/menu/SettingsSelectionMenu.d.ts.map +1 -1
  132. package/dist/components/menu/SettingsSelectionMenu.js +26 -26
  133. package/dist/components/menu/SettingsSelectionMenu.js.map +1 -1
  134. package/dist/components/menu/SettingsValueSelectionMenu.d.ts.map +1 -1
  135. package/dist/components/menu/SettingsValueSelectionMenu.js +22 -20
  136. package/dist/components/menu/SettingsValueSelectionMenu.js.map +1 -1
  137. package/dist/components/menu/SkillSelectionMenu.d.ts.map +1 -1
  138. package/dist/components/menu/SkillSelectionMenu.js +33 -23
  139. package/dist/components/menu/SkillSelectionMenu.js.map +1 -1
  140. package/dist/components/menu/SlashCommandMenu.d.ts.map +1 -1
  141. package/dist/components/menu/SlashCommandMenu.js +11 -6
  142. package/dist/components/menu/SlashCommandMenu.js.map +1 -1
  143. package/dist/components/message/ChatMessage.js +2 -2
  144. package/dist/components/message/ChatMessage.js.map +1 -1
  145. package/dist/components/message/CodeContextSearchRenderer.d.ts.map +1 -1
  146. package/dist/components/message/CodeContextSearchRenderer.js +8 -11
  147. package/dist/components/message/CodeContextSearchRenderer.js.map +1 -1
  148. package/dist/components/message/CommandGroupSummary.d.ts.map +1 -1
  149. package/dist/components/message/CommandGroupSummary.js +21 -9
  150. package/dist/components/message/CommandGroupSummary.js.map +1 -1
  151. package/dist/components/message/CommandMessage.d.ts.map +1 -1
  152. package/dist/components/message/CommandMessage.js +111 -91
  153. package/dist/components/message/CommandMessage.js.map +1 -1
  154. package/dist/components/message/GrepRenderer.d.ts.map +1 -1
  155. package/dist/components/message/GrepRenderer.js +5 -8
  156. package/dist/components/message/GrepRenderer.js.map +1 -1
  157. package/dist/components/message/MemoryRenderer.d.ts +1 -0
  158. package/dist/components/message/MemoryRenderer.d.ts.map +1 -1
  159. package/dist/components/message/MemoryRenderer.js +19 -17
  160. package/dist/components/message/MemoryRenderer.js.map +1 -1
  161. package/dist/components/message/MessageList.d.ts +1 -2
  162. package/dist/components/message/MessageList.d.ts.map +1 -1
  163. package/dist/components/message/MessageList.js +12 -11
  164. package/dist/components/message/MessageList.js.map +1 -1
  165. package/dist/components/message/ReadFileRenderer.d.ts.map +1 -1
  166. package/dist/components/message/ReadFileRenderer.js +5 -6
  167. package/dist/components/message/ReadFileRenderer.js.map +1 -1
  168. package/dist/components/message/SubagentActivityMessage.d.ts.map +1 -1
  169. package/dist/components/message/SubagentActivityMessage.js +17 -13
  170. package/dist/components/message/SubagentActivityMessage.js.map +1 -1
  171. package/dist/components/message/WebFetchRenderer.d.ts.map +1 -1
  172. package/dist/components/message/WebFetchRenderer.js +7 -11
  173. package/dist/components/message/WebFetchRenderer.js.map +1 -1
  174. package/dist/components/message/WebSearchRenderer.d.ts.map +1 -1
  175. package/dist/components/message/WebSearchRenderer.js +5 -10
  176. package/dist/components/message/WebSearchRenderer.js.map +1 -1
  177. package/dist/components/message/command-grouping.d.ts +29 -6
  178. package/dist/components/message/command-grouping.d.ts.map +1 -1
  179. package/dist/components/message/command-grouping.js +62 -20
  180. package/dist/components/message/command-grouping.js.map +1 -1
  181. package/dist/components/message/command-message-helpers.d.ts +10 -37
  182. package/dist/components/message/command-message-helpers.d.ts.map +1 -1
  183. package/dist/components/message/command-message-helpers.js +26 -8
  184. package/dist/components/message/command-message-helpers.js.map +1 -1
  185. package/dist/components/message/useCommandVisibility.d.ts.map +1 -1
  186. package/dist/components/message/useCommandVisibility.js +5 -4
  187. package/dist/components/message/useCommandVisibility.js.map +1 -1
  188. package/dist/components/prompt/ApprovalPrompt.d.ts.map +1 -1
  189. package/dist/components/prompt/ApprovalPrompt.js +232 -106
  190. package/dist/components/prompt/ApprovalPrompt.js.map +1 -1
  191. package/dist/components/prompt/HandoffConfirmationPrompt.d.ts.map +1 -1
  192. package/dist/components/prompt/HandoffConfirmationPrompt.js +3 -2
  193. package/dist/components/prompt/HandoffConfirmationPrompt.js.map +1 -1
  194. package/dist/components/prompt/InputSurgeConfirmationPrompt.d.ts.map +1 -1
  195. package/dist/components/prompt/InputSurgeConfirmationPrompt.js +5 -4
  196. package/dist/components/prompt/InputSurgeConfirmationPrompt.js.map +1 -1
  197. package/dist/components/prompt/LargeUncachedConfirmationPrompt.d.ts.map +1 -1
  198. package/dist/components/prompt/LargeUncachedConfirmationPrompt.js +4 -3
  199. package/dist/components/prompt/LargeUncachedConfirmationPrompt.js.map +1 -1
  200. package/dist/components/prompt/ModeSwitchConfirmationPrompt.d.ts.map +1 -1
  201. package/dist/components/prompt/ModeSwitchConfirmationPrompt.js +4 -3
  202. package/dist/components/prompt/ModeSwitchConfirmationPrompt.js.map +1 -1
  203. package/dist/components/prompt/QueuePausedPrompt.d.ts.map +1 -1
  204. package/dist/components/prompt/QueuePausedPrompt.js +6 -5
  205. package/dist/components/prompt/QueuePausedPrompt.js.map +1 -1
  206. package/dist/components/prompt/StandardModeConfirmationPrompt.d.ts.map +1 -1
  207. package/dist/components/prompt/StandardModeConfirmationPrompt.js +3 -2
  208. package/dist/components/prompt/StandardModeConfirmationPrompt.js.map +1 -1
  209. package/dist/components/theme.d.ts +58 -3
  210. package/dist/components/theme.d.ts.map +1 -1
  211. package/dist/components/theme.js +84 -17
  212. package/dist/components/theme.js.map +1 -1
  213. package/dist/context/InputContext.d.ts +1 -1
  214. package/dist/context/InputContext.d.ts.map +1 -1
  215. package/dist/context/InputContext.js +2 -0
  216. package/dist/context/InputContext.js.map +1 -1
  217. package/dist/contracts/application-stream.d.ts +14 -0
  218. package/dist/contracts/application-stream.d.ts.map +1 -1
  219. package/dist/contracts/streamed-model-turn.d.ts +13 -1
  220. package/dist/contracts/streamed-model-turn.d.ts.map +1 -1
  221. package/dist/gateway/assertion.d.ts +4 -1
  222. package/dist/gateway/assertion.d.ts.map +1 -1
  223. package/dist/gateway/assertion.js +24 -2
  224. package/dist/gateway/assertion.js.map +1 -1
  225. package/dist/gateway/contracts.d.ts +21 -4
  226. package/dist/gateway/contracts.d.ts.map +1 -1
  227. package/dist/gateway/contracts.js +11 -0
  228. package/dist/gateway/contracts.js.map +1 -1
  229. package/dist/gateway/dynamic-workspace-registry.d.ts +76 -0
  230. package/dist/gateway/dynamic-workspace-registry.d.ts.map +1 -0
  231. package/dist/gateway/dynamic-workspace-registry.js +403 -0
  232. package/dist/gateway/dynamic-workspace-registry.js.map +1 -0
  233. package/dist/gateway/gateway.d.ts +24 -1
  234. package/dist/gateway/gateway.d.ts.map +1 -1
  235. package/dist/gateway/gateway.js +704 -21
  236. package/dist/gateway/gateway.js.map +1 -1
  237. package/dist/gateway/launcher-seam.d.ts +18 -0
  238. package/dist/gateway/launcher-seam.d.ts.map +1 -0
  239. package/dist/gateway/launcher-seam.js +43 -0
  240. package/dist/gateway/launcher-seam.js.map +1 -0
  241. package/dist/gateway/pairing.d.ts +25 -0
  242. package/dist/gateway/pairing.d.ts.map +1 -0
  243. package/dist/gateway/pairing.js +107 -0
  244. package/dist/gateway/pairing.js.map +1 -0
  245. package/dist/gateway/persistence/coordinator.d.ts +2 -0
  246. package/dist/gateway/persistence/coordinator.d.ts.map +1 -1
  247. package/dist/gateway/persistence/coordinator.js +13 -0
  248. package/dist/gateway/persistence/coordinator.js.map +1 -1
  249. package/dist/gateway/runtime-factory.d.ts +15 -6
  250. package/dist/gateway/runtime-factory.d.ts.map +1 -1
  251. package/dist/gateway/runtime-factory.js +38 -9
  252. package/dist/gateway/runtime-factory.js.map +1 -1
  253. package/dist/gateway/safe-log.d.ts.map +1 -1
  254. package/dist/gateway/safe-log.js +19 -0
  255. package/dist/gateway/safe-log.js.map +1 -1
  256. package/dist/gateway/server-session.d.ts.map +1 -1
  257. package/dist/gateway/server-session.js +36 -4
  258. package/dist/gateway/server-session.js.map +1 -1
  259. package/dist/gateway/server.d.ts +26 -3
  260. package/dist/gateway/server.d.ts.map +1 -1
  261. package/dist/gateway/server.js +105 -17
  262. package/dist/gateway/server.js.map +1 -1
  263. package/dist/gateway/settings-rpc.d.ts +95 -0
  264. package/dist/gateway/settings-rpc.d.ts.map +1 -0
  265. package/dist/gateway/settings-rpc.js +227 -0
  266. package/dist/gateway/settings-rpc.js.map +1 -0
  267. package/dist/gateway/trusted-clients.d.ts +27 -0
  268. package/dist/gateway/trusted-clients.d.ts.map +1 -0
  269. package/dist/gateway/trusted-clients.js +157 -0
  270. package/dist/gateway/trusted-clients.js.map +1 -0
  271. package/dist/gateway/worker-boundary.d.ts +6 -5
  272. package/dist/gateway/worker-boundary.d.ts.map +1 -1
  273. package/dist/gateway/worker-boundary.js +20 -10
  274. package/dist/gateway/worker-boundary.js.map +1 -1
  275. package/dist/gateway/workspace-admission.d.ts +11 -0
  276. package/dist/gateway/workspace-admission.d.ts.map +1 -1
  277. package/dist/gateway/workspace-admission.js +89 -16
  278. package/dist/gateway/workspace-admission.js.map +1 -1
  279. package/dist/gateway/workspace-boundary-probe.d.ts +18 -0
  280. package/dist/gateway/workspace-boundary-probe.d.ts.map +1 -0
  281. package/dist/gateway/workspace-boundary-probe.js +37 -0
  282. package/dist/gateway/workspace-boundary-probe.js.map +1 -0
  283. package/dist/hooks/conversation-ui-reducer.d.ts +6 -0
  284. package/dist/hooks/conversation-ui-reducer.d.ts.map +1 -1
  285. package/dist/hooks/conversation-ui-reducer.js +9 -1
  286. package/dist/hooks/conversation-ui-reducer.js.map +1 -1
  287. package/dist/hooks/settings-completion-config.d.ts.map +1 -1
  288. package/dist/hooks/settings-completion-config.js +11 -3
  289. package/dist/hooks/settings-completion-config.js.map +1 -1
  290. package/dist/hooks/use-app-commands.d.ts +6 -1
  291. package/dist/hooks/use-app-commands.d.ts.map +1 -1
  292. package/dist/hooks/use-app-commands.js +23 -14
  293. package/dist/hooks/use-app-commands.js.map +1 -1
  294. package/dist/hooks/use-app-keyboard-shortcuts.d.ts +1 -3
  295. package/dist/hooks/use-app-keyboard-shortcuts.d.ts.map +1 -1
  296. package/dist/hooks/use-app-keyboard-shortcuts.js +11 -9
  297. package/dist/hooks/use-app-keyboard-shortcuts.js.map +1 -1
  298. package/dist/hooks/use-conversation.d.ts +8 -0
  299. package/dist/hooks/use-conversation.d.ts.map +1 -1
  300. package/dist/hooks/use-conversation.js +27 -18
  301. package/dist/hooks/use-conversation.js.map +1 -1
  302. package/dist/hooks/use-opencode-go-usage.d.ts +8 -0
  303. package/dist/hooks/use-opencode-go-usage.d.ts.map +1 -0
  304. package/dist/hooks/use-opencode-go-usage.js +45 -0
  305. package/dist/hooks/use-opencode-go-usage.js.map +1 -0
  306. package/dist/hooks/use-resume-selection.d.ts +22 -0
  307. package/dist/hooks/use-resume-selection.d.ts.map +1 -0
  308. package/dist/hooks/use-resume-selection.js +76 -0
  309. package/dist/hooks/use-resume-selection.js.map +1 -0
  310. package/dist/hooks/use-shell-mode.d.ts +3 -4
  311. package/dist/hooks/use-shell-mode.d.ts.map +1 -1
  312. package/dist/hooks/use-shell-mode.js +14 -12
  313. package/dist/hooks/use-shell-mode.js.map +1 -1
  314. package/dist/hooks/use-terminal-columns.d.ts +15 -0
  315. package/dist/hooks/use-terminal-columns.d.ts.map +1 -0
  316. package/dist/hooks/use-terminal-columns.js +45 -0
  317. package/dist/hooks/use-terminal-columns.js.map +1 -0
  318. package/dist/lib/agent-client.d.ts +14 -1
  319. package/dist/lib/agent-client.d.ts.map +1 -1
  320. package/dist/lib/agent-client.js +112 -37
  321. package/dist/lib/agent-client.js.map +1 -1
  322. package/dist/lib/agent-configuration.d.ts +5 -0
  323. package/dist/lib/agent-configuration.d.ts.map +1 -1
  324. package/dist/lib/agent-configuration.js +14 -5
  325. package/dist/lib/agent-configuration.js.map +1 -1
  326. package/dist/lib/agent-factory.d.ts +7 -2
  327. package/dist/lib/agent-factory.d.ts.map +1 -1
  328. package/dist/lib/agent-factory.js +22 -11
  329. package/dist/lib/agent-factory.js.map +1 -1
  330. package/dist/lib/harness-input-idle.d.ts.map +1 -1
  331. package/dist/lib/harness-input-idle.js +1 -1
  332. package/dist/lib/harness-input-idle.js.map +1 -1
  333. package/dist/non-interactive.d.ts +3 -0
  334. package/dist/non-interactive.d.ts.map +1 -1
  335. package/dist/non-interactive.js +106 -22
  336. package/dist/non-interactive.js.map +1 -1
  337. package/dist/prompts/approval-model.md +22 -0
  338. package/dist/prompts/gpt-5.6.md +3 -2
  339. package/dist/prompts/mentor-mode-stub.md +3 -0
  340. package/dist/prompts/orchestrator-mode-stub.md +3 -0
  341. package/dist/prompts/prefix-quality.test.ts +10 -0
  342. package/dist/prompts/prompt-constructor.d.ts +2 -0
  343. package/dist/prompts/prompt-constructor.d.ts.map +1 -1
  344. package/dist/prompts/prompt-constructor.js +23 -13
  345. package/dist/prompts/prompt-constructor.js.map +1 -1
  346. package/dist/prompts/prompt-constructor.test.ts +39 -5
  347. package/dist/prompts/prompt-constructor.ts +27 -15
  348. package/dist/prompts/prompt-profiles.d.ts +1 -3
  349. package/dist/prompts/prompt-profiles.d.ts.map +1 -1
  350. package/dist/prompts/prompt-profiles.js +2 -7
  351. package/dist/prompts/prompt-profiles.js.map +1 -1
  352. package/dist/prompts/prompt-profiles.ts +3 -16
  353. package/dist/prompts/session-browser.md +3 -0
  354. package/dist/prompts/subagent-delegation.d.ts +4 -3
  355. package/dist/prompts/subagent-delegation.d.ts.map +1 -1
  356. package/dist/prompts/subagent-delegation.js +14 -18
  357. package/dist/prompts/subagent-delegation.js.map +1 -1
  358. package/dist/prompts/subagent-delegation.test.ts +2 -2
  359. package/dist/prompts/subagent-delegation.ts +13 -20
  360. package/dist/providers/chained-wire-state.d.ts +7 -2
  361. package/dist/providers/chained-wire-state.d.ts.map +1 -1
  362. package/dist/providers/chained-wire-state.js +16 -7
  363. package/dist/providers/chained-wire-state.js.map +1 -1
  364. package/dist/providers/codex-auth.d.ts +2 -5
  365. package/dist/providers/codex-auth.d.ts.map +1 -1
  366. package/dist/providers/codex-auth.js +2 -0
  367. package/dist/providers/codex-auth.js.map +1 -1
  368. package/dist/providers/codex-compact.d.ts +9 -0
  369. package/dist/providers/codex-compact.d.ts.map +1 -0
  370. package/dist/providers/codex-compact.js +23 -0
  371. package/dist/providers/codex-compact.js.map +1 -0
  372. package/dist/providers/codex-responses-model.d.ts +17 -1
  373. package/dist/providers/codex-responses-model.d.ts.map +1 -1
  374. package/dist/providers/codex-responses-model.js +75 -8
  375. package/dist/providers/codex-responses-model.js.map +1 -1
  376. package/dist/providers/codex-turn-converter.d.ts.map +1 -1
  377. package/dist/providers/codex-turn-converter.js +8 -4
  378. package/dist/providers/codex-turn-converter.js.map +1 -1
  379. package/dist/providers/codex.provider.js +2 -2
  380. package/dist/providers/codex.provider.js.map +1 -1
  381. package/dist/providers/grok-auth.d.ts +2 -5
  382. package/dist/providers/grok-auth.d.ts.map +1 -1
  383. package/dist/providers/grok-auth.js +2 -0
  384. package/dist/providers/grok-auth.js.map +1 -1
  385. package/dist/providers/oauth-account-store.d.ts +5 -0
  386. package/dist/providers/oauth-account-store.d.ts.map +1 -1
  387. package/dist/providers/oauth-account-store.js +56 -5
  388. package/dist/providers/oauth-account-store.js.map +1 -1
  389. package/dist/providers/oauth-pkce.d.ts +8 -0
  390. package/dist/providers/oauth-pkce.d.ts.map +1 -1
  391. package/dist/providers/oauth-pkce.js +91 -19
  392. package/dist/providers/oauth-pkce.js.map +1 -1
  393. package/dist/providers/openai-compatible.provider.d.ts.map +1 -1
  394. package/dist/providers/openai-compatible.provider.js +8 -1
  395. package/dist/providers/openai-compatible.provider.js.map +1 -1
  396. package/dist/providers/openai-responses-model.d.ts.map +1 -1
  397. package/dist/providers/openai-responses-model.js +2 -0
  398. package/dist/providers/openai-responses-model.js.map +1 -1
  399. package/dist/providers/opencode-go-usage.d.ts +24 -0
  400. package/dist/providers/opencode-go-usage.d.ts.map +1 -0
  401. package/dist/providers/opencode-go-usage.js +37 -0
  402. package/dist/providers/opencode-go-usage.js.map +1 -0
  403. package/dist/providers/openrouter.provider.d.ts.map +1 -1
  404. package/dist/providers/openrouter.provider.js +8 -1
  405. package/dist/providers/openrouter.provider.js.map +1 -1
  406. package/dist/providers/responses-websocket-sessions.d.ts +1 -0
  407. package/dist/providers/responses-websocket-sessions.d.ts.map +1 -1
  408. package/dist/providers/responses-websocket-sessions.js +16 -2
  409. package/dist/providers/responses-websocket-sessions.js.map +1 -1
  410. package/dist/providers/retrying-model.d.ts +1 -0
  411. package/dist/providers/retrying-model.d.ts.map +1 -1
  412. package/dist/providers/retrying-model.js +37 -3
  413. package/dist/providers/retrying-model.js.map +1 -1
  414. package/dist/services/agent-runtime/application-run-loop.d.ts +5 -1
  415. package/dist/services/agent-runtime/application-run-loop.d.ts.map +1 -1
  416. package/dist/services/agent-runtime/application-run-loop.js +231 -149
  417. package/dist/services/agent-runtime/application-run-loop.js.map +1 -1
  418. package/dist/services/agent-runtime/generation-guard.d.ts +39 -25
  419. package/dist/services/agent-runtime/generation-guard.d.ts.map +1 -1
  420. package/dist/services/agent-runtime/generation-guard.js +98 -100
  421. package/dist/services/agent-runtime/generation-guard.js.map +1 -1
  422. package/dist/services/agent-runtime/run-budget.d.ts +1 -1
  423. package/dist/services/agent-runtime/run-budget.d.ts.map +1 -1
  424. package/dist/services/agent-runtime/run-budget.js +4 -0
  425. package/dist/services/agent-runtime/run-budget.js.map +1 -1
  426. package/dist/services/agent-stream.d.ts.map +1 -1
  427. package/dist/services/agent-stream.js +1 -0
  428. package/dist/services/agent-stream.js.map +1 -1
  429. package/dist/services/approval/shell-auto-approval-evaluator.d.ts +3 -1
  430. package/dist/services/approval/shell-auto-approval-evaluator.d.ts.map +1 -1
  431. package/dist/services/approval/shell-auto-approval-evaluator.js +4 -2
  432. package/dist/services/approval/shell-auto-approval-evaluator.js.map +1 -1
  433. package/dist/services/approval/shell-auto-approval-resolver.d.ts +2 -0
  434. package/dist/services/approval/shell-auto-approval-resolver.d.ts.map +1 -1
  435. package/dist/services/approval/shell-auto-approval-resolver.js +2 -0
  436. package/dist/services/approval/shell-auto-approval-resolver.js.map +1 -1
  437. package/dist/services/conversation/conversation-adapter.d.ts +13 -2
  438. package/dist/services/conversation/conversation-adapter.d.ts.map +1 -1
  439. package/dist/services/conversation/conversation-adapter.js +35 -7
  440. package/dist/services/conversation/conversation-adapter.js.map +1 -1
  441. package/dist/services/conversation/conversation-admission-workflow.d.ts +3 -2
  442. package/dist/services/conversation/conversation-admission-workflow.d.ts.map +1 -1
  443. package/dist/services/conversation/conversation-admission-workflow.js +6 -1
  444. package/dist/services/conversation/conversation-admission-workflow.js.map +1 -1
  445. package/dist/services/conversation/conversation-events.d.ts +43 -2
  446. package/dist/services/conversation/conversation-events.d.ts.map +1 -1
  447. package/dist/services/conversation/conversation-orchestrator.d.ts +14 -1
  448. package/dist/services/conversation/conversation-orchestrator.d.ts.map +1 -1
  449. package/dist/services/conversation/conversation-orchestrator.js +142 -11
  450. package/dist/services/conversation/conversation-orchestrator.js.map +1 -1
  451. package/dist/services/conversation/conversation-orchestrator.types.d.ts +3 -1
  452. package/dist/services/conversation/conversation-orchestrator.types.d.ts.map +1 -1
  453. package/dist/services/conversation/conversation-persistence.d.ts +22 -1
  454. package/dist/services/conversation/conversation-persistence.d.ts.map +1 -1
  455. package/dist/services/conversation/conversation-persistence.js +61 -0
  456. package/dist/services/conversation/conversation-persistence.js.map +1 -1
  457. package/dist/services/conversation/conversation-service.d.ts.map +1 -1
  458. package/dist/services/conversation/conversation-service.js +45 -29
  459. package/dist/services/conversation/conversation-service.js.map +1 -1
  460. package/dist/services/conversation/session-audit.d.ts +70 -0
  461. package/dist/services/conversation/session-audit.d.ts.map +1 -0
  462. package/dist/services/conversation/session-audit.js +164 -0
  463. package/dist/services/conversation/session-audit.js.map +1 -0
  464. package/dist/services/conversation/session-browser.d.ts +49 -0
  465. package/dist/services/conversation/session-browser.d.ts.map +1 -0
  466. package/dist/services/conversation/session-browser.js +411 -0
  467. package/dist/services/conversation/session-browser.js.map +1 -0
  468. package/dist/services/input-surge-approval.d.ts +21 -0
  469. package/dist/services/input-surge-approval.d.ts.map +1 -0
  470. package/dist/services/input-surge-approval.js +42 -0
  471. package/dist/services/input-surge-approval.js.map +1 -0
  472. package/dist/services/large-uncached-input-guard.js +4 -4
  473. package/dist/services/large-uncached-input-guard.js.map +1 -1
  474. package/dist/services/logging/assistant-turn-journal.d.ts +15 -0
  475. package/dist/services/logging/assistant-turn-journal.d.ts.map +1 -1
  476. package/dist/services/logging/assistant-turn-journal.js +27 -0
  477. package/dist/services/logging/assistant-turn-journal.js.map +1 -1
  478. package/dist/services/memory/memory-capabilities.d.ts.map +1 -1
  479. package/dist/services/memory/memory-capabilities.js +7 -4
  480. package/dist/services/memory/memory-capabilities.js.map +1 -1
  481. package/dist/services/memory/memory-search.d.ts +16 -0
  482. package/dist/services/memory/memory-search.d.ts.map +1 -0
  483. package/dist/services/memory/memory-search.js +55 -0
  484. package/dist/services/memory/memory-search.js.map +1 -0
  485. package/dist/services/memory/memory-store.d.ts +12 -0
  486. package/dist/services/memory/memory-store.d.ts.map +1 -1
  487. package/dist/services/memory/memory-store.js +14 -35
  488. package/dist/services/memory/memory-store.js.map +1 -1
  489. package/dist/services/mode-notices.d.ts +11 -0
  490. package/dist/services/mode-notices.d.ts.map +1 -1
  491. package/dist/services/mode-notices.js +37 -3
  492. package/dist/services/mode-notices.js.map +1 -1
  493. package/dist/services/queue/queue-controller.d.ts +13 -0
  494. package/dist/services/queue/queue-controller.d.ts.map +1 -1
  495. package/dist/services/queue/queue-controller.js +32 -1
  496. package/dist/services/queue/queue-controller.js.map +1 -1
  497. package/dist/services/retry/in-loop-model-retry.d.ts +16 -0
  498. package/dist/services/retry/in-loop-model-retry.d.ts.map +1 -0
  499. package/dist/services/retry/in-loop-model-retry.js +125 -0
  500. package/dist/services/retry/in-loop-model-retry.js.map +1 -0
  501. package/dist/services/retry/retry-classifier.d.ts.map +1 -1
  502. package/dist/services/retry/retry-classifier.js +18 -12
  503. package/dist/services/retry/retry-classifier.js.map +1 -1
  504. package/dist/services/retry/retry-error-classification.d.ts.map +1 -1
  505. package/dist/services/retry/retry-error-classification.js +10 -6
  506. package/dist/services/retry/retry-error-classification.js.map +1 -1
  507. package/dist/services/retry/upstream-retry-policy.d.ts.map +1 -1
  508. package/dist/services/retry/upstream-retry-policy.js +40 -7
  509. package/dist/services/retry/upstream-retry-policy.js.map +1 -1
  510. package/dist/services/runtime-setting-router.d.ts.map +1 -1
  511. package/dist/services/runtime-setting-router.js +7 -2
  512. package/dist/services/runtime-setting-router.js.map +1 -1
  513. package/dist/services/session/background-check-in-scheduler.d.ts +44 -0
  514. package/dist/services/session/background-check-in-scheduler.d.ts.map +1 -0
  515. package/dist/services/session/background-check-in-scheduler.js +88 -0
  516. package/dist/services/session/background-check-in-scheduler.js.map +1 -0
  517. package/dist/services/session/background-task-control.js +4 -1
  518. package/dist/services/session/background-task-control.js.map +1 -1
  519. package/dist/services/session/initial-input-preparer.d.ts +2 -1
  520. package/dist/services/session/initial-input-preparer.d.ts.map +1 -1
  521. package/dist/services/session/initial-input-preparer.js +4 -1
  522. package/dist/services/session/initial-input-preparer.js.map +1 -1
  523. package/dist/services/session/repetition-detector.d.ts +0 -4
  524. package/dist/services/session/repetition-detector.d.ts.map +1 -1
  525. package/dist/services/session/repetition-detector.js +0 -7
  526. package/dist/services/session/repetition-detector.js.map +1 -1
  527. package/dist/services/session/session-access-state.d.ts +3 -0
  528. package/dist/services/session/session-access-state.d.ts.map +1 -1
  529. package/dist/services/session/session-access-state.js +12 -0
  530. package/dist/services/session/session-access-state.js.map +1 -1
  531. package/dist/services/session/session-client-factory.d.ts +3 -1
  532. package/dist/services/session/session-client-factory.d.ts.map +1 -1
  533. package/dist/services/session/session-client-factory.js +2 -1
  534. package/dist/services/session/session-client-factory.js.map +1 -1
  535. package/dist/services/session/session-composition.d.ts +6 -2
  536. package/dist/services/session/session-composition.d.ts.map +1 -1
  537. package/dist/services/session/session-composition.js +148 -29
  538. package/dist/services/session/session-composition.js.map +1 -1
  539. package/dist/services/session/session-input-planner.d.ts +9 -0
  540. package/dist/services/session/session-input-planner.d.ts.map +1 -1
  541. package/dist/services/session/session-input-planner.js +23 -0
  542. package/dist/services/session/session-input-planner.js.map +1 -1
  543. package/dist/services/session/session-lifecycle.d.ts +8 -0
  544. package/dist/services/session/session-lifecycle.d.ts.map +1 -1
  545. package/dist/services/session/session-lifecycle.js +4 -0
  546. package/dist/services/session/session-lifecycle.js.map +1 -1
  547. package/dist/services/session/session-stream-processor.d.ts.map +1 -1
  548. package/dist/services/session/session-stream-processor.js +5 -15
  549. package/dist/services/session/session-stream-processor.js.map +1 -1
  550. package/dist/services/session/turn-attempt-factory.d.ts +2 -1
  551. package/dist/services/session/turn-attempt-factory.d.ts.map +1 -1
  552. package/dist/services/session/turn-attempt-factory.js +1 -0
  553. package/dist/services/session/turn-attempt-factory.js.map +1 -1
  554. package/dist/services/session/turn-attempt.d.ts +3 -0
  555. package/dist/services/session/turn-attempt.d.ts.map +1 -1
  556. package/dist/services/session/turn-attempt.js +5 -0
  557. package/dist/services/session/turn-attempt.js.map +1 -1
  558. package/dist/services/session/turn-coordinator.d.ts +1 -1
  559. package/dist/services/session/turn-coordinator.d.ts.map +1 -1
  560. package/dist/services/session/turn-workflow.d.ts.map +1 -1
  561. package/dist/services/session/turn-workflow.js +4 -1
  562. package/dist/services/session/turn-workflow.js.map +1 -1
  563. package/dist/services/settings/settings-schema.d.ts +27 -3
  564. package/dist/services/settings/settings-schema.d.ts.map +1 -1
  565. package/dist/services/settings/settings-schema.js +35 -11
  566. package/dist/services/settings/settings-schema.js.map +1 -1
  567. package/dist/services/settings/settings-service.d.ts +9 -0
  568. package/dist/services/settings/settings-service.d.ts.map +1 -1
  569. package/dist/services/settings/settings-service.js +40 -0
  570. package/dist/services/settings/settings-service.js.map +1 -1
  571. package/dist/services/settings/settings-sources.d.ts.map +1 -1
  572. package/dist/services/settings/settings-sources.js +5 -0
  573. package/dist/services/settings/settings-sources.js.map +1 -1
  574. package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts +2 -1
  575. package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts.map +1 -1
  576. package/dist/services/settings/test-helpers/settings-consumer-inventory.js +6 -0
  577. package/dist/services/settings/test-helpers/settings-consumer-inventory.js.map +1 -1
  578. package/dist/services/shell/shell-interaction-session.d.ts +4 -5
  579. package/dist/services/shell/shell-interaction-session.d.ts.map +1 -1
  580. package/dist/services/shell/shell-interaction-session.js +8 -20
  581. package/dist/services/shell/shell-interaction-session.js.map +1 -1
  582. package/dist/services/stream-event-processor.d.ts.map +1 -1
  583. package/dist/services/stream-event-processor.js +15 -0
  584. package/dist/services/stream-event-processor.js.map +1 -1
  585. package/dist/services/subagents/mentor-runner.d.ts.map +1 -1
  586. package/dist/services/subagents/mentor-runner.js +2 -0
  587. package/dist/services/subagents/mentor-runner.js.map +1 -1
  588. package/dist/services/subagents/nested-runner.d.ts.map +1 -1
  589. package/dist/services/subagents/nested-runner.js +34 -1
  590. package/dist/services/subagents/nested-runner.js.map +1 -1
  591. package/dist/services/subagents/subagent-async-registry.js +1 -1
  592. package/dist/services/subagents/subagent-async-registry.js.map +1 -1
  593. package/dist/services/subagents/subagent-notification-store.d.ts +28 -1
  594. package/dist/services/subagents/subagent-notification-store.d.ts.map +1 -1
  595. package/dist/services/subagents/subagent-notification-store.js +11 -0
  596. package/dist/services/subagents/subagent-notification-store.js.map +1 -1
  597. package/dist/services/subagents/tool-policy.d.ts.map +1 -1
  598. package/dist/services/subagents/tool-policy.js +10 -5
  599. package/dist/services/subagents/tool-policy.js.map +1 -1
  600. package/dist/services/subagents/utils.d.ts +2 -0
  601. package/dist/services/subagents/utils.d.ts.map +1 -1
  602. package/dist/services/subagents/utils.js +29 -0
  603. package/dist/services/subagents/utils.js.map +1 -1
  604. package/dist/services/tool-execution-ledger.d.ts.map +1 -1
  605. package/dist/services/tool-execution-ledger.js +5 -1
  606. package/dist/services/tool-execution-ledger.js.map +1 -1
  607. package/dist/slash-commands.d.ts +3 -0
  608. package/dist/slash-commands.d.ts.map +1 -1
  609. package/dist/slash-commands.js.map +1 -1
  610. package/dist/tools/agent/ask-user.d.ts.map +1 -1
  611. package/dist/tools/agent/ask-user.js +2 -0
  612. package/dist/tools/agent/ask-user.js.map +1 -1
  613. package/dist/tools/agent/run-subagent-async.d.ts +0 -1
  614. package/dist/tools/agent/run-subagent-async.d.ts.map +1 -1
  615. package/dist/tools/agent/run-subagent-async.js +3 -3
  616. package/dist/tools/agent/run-subagent-async.js.map +1 -1
  617. package/dist/tools/agent/run-subagent.d.ts +2 -2
  618. package/dist/tools/agent/run-subagent.d.ts.map +1 -1
  619. package/dist/tools/agent/run-subagent.js +44 -28
  620. package/dist/tools/agent/run-subagent.js.map +1 -1
  621. package/dist/tools/file/apply-patch.d.ts.map +1 -1
  622. package/dist/tools/file/apply-patch.js +11 -3
  623. package/dist/tools/file/apply-patch.js.map +1 -1
  624. package/dist/tools/file/create-file.d.ts.map +1 -1
  625. package/dist/tools/file/create-file.js +12 -4
  626. package/dist/tools/file/create-file.js.map +1 -1
  627. package/dist/tools/file/search-replace.d.ts.map +1 -1
  628. package/dist/tools/file/search-replace.js +10 -3
  629. package/dist/tools/file/search-replace.js.map +1 -1
  630. package/dist/tools/memory/memory-tools.d.ts +5 -1
  631. package/dist/tools/memory/memory-tools.d.ts.map +1 -1
  632. package/dist/tools/memory/memory-tools.js +445 -62
  633. package/dist/tools/memory/memory-tools.js.map +1 -1
  634. package/dist/tools/session-browser/session-browser-tools.d.ts +4 -0
  635. package/dist/tools/session-browser/session-browser-tools.d.ts.map +1 -0
  636. package/dist/tools/session-browser/session-browser-tools.js +47 -0
  637. package/dist/tools/session-browser/session-browser-tools.js.map +1 -0
  638. package/dist/tools/system/shell.d.ts.map +1 -1
  639. package/dist/tools/system/shell.js +7 -0
  640. package/dist/tools/system/shell.js.map +1 -1
  641. package/dist/tools/types.d.ts +4 -0
  642. package/dist/tools/types.d.ts.map +1 -1
  643. package/dist/tools/types.js.map +1 -1
  644. package/dist/utils/busy-turn-guard.d.ts +17 -0
  645. package/dist/utils/busy-turn-guard.d.ts.map +1 -0
  646. package/dist/utils/busy-turn-guard.js +24 -0
  647. package/dist/utils/busy-turn-guard.js.map +1 -0
  648. package/dist/utils/conversation/conversation-event-handler.d.ts.map +1 -1
  649. package/dist/utils/conversation/conversation-event-handler.js +28 -7
  650. package/dist/utils/conversation/conversation-event-handler.js.map +1 -1
  651. package/dist/utils/output/bounded-json.d.ts +33 -0
  652. package/dist/utils/output/bounded-json.d.ts.map +1 -0
  653. package/dist/utils/output/bounded-json.js +59 -0
  654. package/dist/utils/output/bounded-json.js.map +1 -0
  655. package/dist/utils/output/output-trim.d.ts.map +1 -1
  656. package/dist/utils/output/output-trim.js +7 -7
  657. package/dist/utils/output/output-trim.js.map +1 -1
  658. package/dist/utils/output/text-snippet.d.ts +6 -0
  659. package/dist/utils/output/text-snippet.d.ts.map +1 -0
  660. package/dist/utils/output/text-snippet.js +106 -0
  661. package/dist/utils/output/text-snippet.js.map +1 -0
  662. package/dist/utils/resume-list.d.ts +3 -1
  663. package/dist/utils/resume-list.d.ts.map +1 -1
  664. package/dist/utils/resume-list.js +3 -2
  665. package/dist/utils/resume-list.js.map +1 -1
  666. package/dist/utils/settings-command.d.ts.map +1 -1
  667. package/dist/utils/settings-command.js +15 -0
  668. package/dist/utils/settings-command.js.map +1 -1
  669. package/dist/utils/shell/command-safety/handlers/index.d.ts.map +1 -1
  670. package/dist/utils/shell/command-safety/handlers/index.js +3 -0
  671. package/dist/utils/shell/command-safety/handlers/index.js.map +1 -1
  672. package/dist/utils/shell/command-safety/handlers/rm-handler.d.ts +3 -0
  673. package/dist/utils/shell/command-safety/handlers/rm-handler.d.ts.map +1 -0
  674. package/dist/utils/shell/command-safety/handlers/rm-handler.js +97 -0
  675. package/dist/utils/shell/command-safety/handlers/rm-handler.js.map +1 -0
  676. package/dist/utils/shell/command-safety/handlers/types.d.ts +1 -0
  677. package/dist/utils/shell/command-safety/handlers/types.d.ts.map +1 -1
  678. package/dist/utils/shell/command-safety/index.d.ts +6 -2
  679. package/dist/utils/shell/command-safety/index.d.ts.map +1 -1
  680. package/dist/utils/shell/command-safety/index.js +13 -12
  681. package/dist/utils/shell/command-safety/index.js.map +1 -1
  682. package/dist/utils/shell/sandbox/sandbox-policy.d.ts +2 -0
  683. package/dist/utils/shell/sandbox/sandbox-policy.d.ts.map +1 -1
  684. package/dist/utils/shell/sandbox/sandbox-policy.js.map +1 -1
  685. package/dist/utils/shell/sandbox/shell-sandbox-runner.d.ts +1 -0
  686. package/dist/utils/shell/sandbox/shell-sandbox-runner.d.ts.map +1 -1
  687. package/dist/utils/shell/sandbox/shell-sandbox-runner.js +20 -1
  688. package/dist/utils/shell/sandbox/shell-sandbox-runner.js.map +1 -1
  689. package/dist/utils/shell/temp-dir.d.ts +1 -0
  690. package/dist/utils/shell/temp-dir.d.ts.map +1 -1
  691. package/dist/utils/shell/temp-dir.js +12 -4
  692. package/dist/utils/shell/temp-dir.js.map +1 -1
  693. package/dist/utils/value-suggestions.d.ts.map +1 -1
  694. package/dist/utils/value-suggestions.js +1 -0
  695. package/dist/utils/value-suggestions.js.map +1 -1
  696. package/package.json +4 -2
@@ -14,6 +14,18 @@ import { GatewayAdmissionPersistence } from './persistence/admission-persistence
14
14
  import { GATEWAY_EVENT_HEARTBEAT_INTERVAL_MS, GATEWAY_EVENT_STREAM_CONTENT_TYPE, GATEWAY_EVENT_STREAM_HEARTBEAT, } from './server.js';
15
15
  import { ServerSession } from './server-session.js';
16
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';
17
29
  const MAX_BUFFERED_SSE_EVENTS = 256;
18
30
  const NONCRITICAL_RUNTIME_EVENT_TYPES = new Set(['text_delta', 'reasoning_delta']);
19
31
  const isCriticalRuntimeEvent = (event) => !NONCRITICAL_RUNTIME_EVENT_TYPES.has(event.type);
@@ -80,6 +92,15 @@ const PUBLIC_EVENT_PAYLOAD_KEYS = new Set([
80
92
  'deniedRead',
81
93
  'runBudgetEvidence',
82
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
+ ]);
83
104
  export class GatewayStartupError extends Error {
84
105
  constructor() {
85
106
  super('gateway prerequisites unavailable');
@@ -87,16 +108,61 @@ export class GatewayStartupError extends Error {
87
108
  }
88
109
  }
89
110
  export function assertGatewayStartup(config, manifest) {
90
- if (!config.socketPath.startsWith('/') || !config.issuer || !config.audience || !config.replayDbPath)
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)
91
144
  throw new GatewayStartupError();
92
- if (!config.publicKeys ||
93
- (config.publicKeys instanceof Map ? config.publicKeys.size === 0 : Object.keys(config.publicKeys).length === 0))
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)
94
156
  throw new GatewayStartupError();
95
157
  if (!manifest)
96
158
  throw new GatewayStartupError();
97
159
  if (!config.manifestSha256 || !/^[a-f0-9]{64}$/i.test(config.manifestSha256))
98
160
  throw new GatewayStartupError();
99
- if (!config.providerBroker || !config.providerProbe?.available || !config.providerProbe.secretFree)
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)
100
166
  throw new GatewayStartupError();
101
167
  if (config.workerSandboxAvailable !== true || typeof config.workspaceBoundaryProbe !== 'function')
102
168
  throw new GatewayStartupError();
@@ -104,7 +170,8 @@ export function assertGatewayStartup(config, manifest) {
104
170
  throw new GatewayStartupError();
105
171
  if (typeof config.auditWriter !== 'function')
106
172
  throw new GatewayStartupError();
107
- assertProviderBrokerReady(config.providerBroker, config.providerProbe);
173
+ if (!realProviderStack)
174
+ assertProviderBrokerReady(config.providerBroker, config.providerProbe);
108
175
  if (!config.tmpDir?.startsWith('/'))
109
176
  throw new GatewayStartupError();
110
177
  return manifest;
@@ -112,7 +179,6 @@ export function assertGatewayStartup(config, manifest) {
112
179
  /** Gateway control plane. Runtime/session protocols remain private RPC consumers. */
113
180
  export class Term2Gateway {
114
181
  #config;
115
- #manifest;
116
182
  #replay;
117
183
  #admission;
118
184
  #verifier;
@@ -125,27 +191,94 @@ export class Term2Gateway {
125
191
  #interactionCounters = new Map();
126
192
  #eventPersistenceTails = new Map();
127
193
  #shutdownInProgress = false;
194
+ #shutdownPromise;
128
195
  #server;
196
+ #modelCatalog;
197
+ #workspaceRegistry;
198
+ #pairing;
199
+ #oauthMutation = Promise.resolve();
200
+ #settingsMutation = Promise.resolve();
129
201
  constructor(config, manifest) {
130
202
  this.#config = config;
131
- this.#manifest = manifest;
132
203
  this.#replay = new SqliteReplayLedger(config.replayDbPath);
133
- this.#admission = new WorkspaceAdmission(manifest, {
134
- allowWrite: config.allowWrite === true,
135
- boundaryProbe: config.workspaceBoundaryProbe,
136
- });
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);
137
224
  this.#verifier = new AssertionVerifier({
138
225
  issuer: config.issuer,
139
226
  audience: config.audience,
140
- publicKeys: config.publicKeys,
227
+ publicKeys: assertionKeys,
228
+ allowEmptyKeys: config.pairing?.enabled === true,
141
229
  replayLedger: this.#replay,
142
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;
143
239
  this.#audit = new GatewayAuditLog(config.auditWriter);
144
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 };
145
252
  this.#server = new GatewayServer({
146
- socketPath: config.socketPath,
253
+ ...transport,
147
254
  verifier: this.#verifier,
148
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
+ : {}),
149
282
  handler: (input) => this.#handleRpc(input),
150
283
  });
151
284
  }
@@ -159,6 +292,8 @@ export class Term2Gateway {
159
292
  return publicError(400, 'protocol_conflict', 'gateway path and assertion session do not match');
160
293
  if (!route.legacy && route.purpose !== claims.purpose)
161
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');
162
297
  try {
163
298
  if (claims.purpose === 'workspace_list') {
164
299
  await this.#audit.write(createSafeLogMetadata({
@@ -204,8 +339,32 @@ export class Term2Gateway {
204
339
  throw error;
205
340
  }
206
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);
207
364
  if (!claims.sessionId)
208
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);
209
368
  if (claims.purpose === 'session_read') {
210
369
  const projection = await this.#projectionFor(claims.sub, claims.sessionId);
211
370
  return { status: 200, body: { session: toSessionProjection(projection) } };
@@ -224,6 +383,287 @@ export class Term2Gateway {
224
383
  return this.#mapError(error);
225
384
  }
226
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
+ }
227
667
  #interactionBindingFor(sessionId, snapshot, turnId) {
228
668
  const current = this.#interactionBindings.get(sessionId);
229
669
  if (current && current.expectedInteractionId === snapshot.interactionId)
@@ -744,6 +1184,14 @@ export class Term2Gateway {
744
1184
  await persisted.persistence.journal.append(mapped, {
745
1185
  durability: mapped.type === 'text_delta' || mapped.type === 'reasoning_delta' ? 'stream' : 'critical',
746
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
+ }
747
1195
  if (event.type === 'final' || event.type === 'error') {
748
1196
  const admission = admissions.find((candidate) => candidate.turnId === context.turnId);
749
1197
  if (admission && (admission.state === 'accepted' || admission.state === 'committed')) {
@@ -759,8 +1207,34 @@ export class Term2Gateway {
759
1207
  });
760
1208
  }
761
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
+ }
762
1231
  if (error instanceof WorkspaceAdmissionError) {
763
- return publicError(error.code === 'workspace_session_exists' ? 409 : 403, error.code === 'workspace_session_exists' ? 'protocol_conflict' : 'workspace_forbidden', 'workspace access denied');
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');
764
1238
  }
765
1239
  if (error instanceof GatewayPersistenceError) {
766
1240
  if (error.code === 'not_found' || error.code === 'owner_mismatch')
@@ -799,7 +1273,7 @@ export class Term2Gateway {
799
1273
  return this.#lifecycle;
800
1274
  }
801
1275
  get manifestVersion() {
802
- return this.#manifest.version;
1276
+ return this.#admission.manifestVersion;
803
1277
  }
804
1278
  get interactionMetrics() {
805
1279
  return Object.freeze(Object.fromEntries(INTERACTION_METRICS.map((metric) => [metric, this.#interactionCounters.get(metric) ?? 0])));
@@ -911,12 +1385,50 @@ export class Term2Gateway {
911
1385
  return session;
912
1386
  }
913
1387
  async shutdown(graceMs = 5_000) {
1388
+ if (this.#shutdownPromise)
1389
+ return this.#shutdownPromise;
914
1390
  this.#shutdownInProgress = true;
915
- await this.#server.shutdown(graceMs);
916
- await Promise.all([...this.#sessions.values()].map((session) => Promise.resolve(session.dispose())));
917
- this.#sessions.clear();
918
- this.#replay.close();
919
- await this.#audit.write(createSafeLogMetadata({ operation: 'shutdown', outcome: 'interrupted', reasonCode: 'shutdown' }));
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;
920
1432
  }
921
1433
  }
922
1434
  function matchPrivateRoute(method, pathname) {
@@ -925,11 +1437,37 @@ function matchPrivateRoute(method, pathname) {
925
1437
  // GET is canonical for workspace_list; POST is a tested compatibility alias for the pinned BFF wire.
926
1438
  if ((method === 'GET' || method === 'POST') && pathname === '/private/agent/v1/workspaces')
927
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]}` };
928
1466
  if (method === 'POST' && pathname === '/private/agent/v1/sessions')
929
1467
  return { purpose: 'session_create' };
930
1468
  if (method === 'GET' && pathname === '/private/agent/v1/sessions')
931
1469
  return { purpose: 'session_list' };
932
- const match = pathname.match(/^\/private\/agent\/v1\/sessions\/([A-Za-z0-9_-]{1,256})(?:\/(messages|abort|events|interactions\/([A-Za-z0-9_-]{1,256})))?$/);
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})))?$/);
933
1471
  if (!match)
934
1472
  return null;
935
1473
  const sessionId = match[1];
@@ -941,10 +1479,29 @@ function matchPrivateRoute(method, pathname) {
941
1479
  return { purpose: 'abort', sessionId };
942
1480
  if (method === 'GET' && match[2] === 'events')
943
1481
  return { purpose: 'events_connect', sessionId };
1482
+ if (method === 'POST' && match[2] === 'config')
1483
+ return { purpose: 'session_update', sessionId };
944
1484
  if (method === 'POST' && match[2]?.startsWith('interactions/'))
945
1485
  return { purpose: 'interaction_resolve', sessionId, interactionId: match[3] };
946
1486
  return null;
947
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
+ }
948
1505
  export function classifyInteractionResolution(interaction, hasLiveSnapshot) {
949
1506
  if (hasLiveSnapshot)
950
1507
  return null;
@@ -968,6 +1525,132 @@ function isSessionCreateBody(body, workspaceId, legacy = false) {
968
1525
  const requested = body.workspaceId;
969
1526
  return typeof requested === 'string' && requested === workspaceId;
970
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
+ }
971
1654
  function isOpaqueId(value) {
972
1655
  return typeof value === 'string' && /^[A-Za-z0-9_-]{1,256}$/.test(value);
973
1656
  }