@opengeni/api-router 0.30.3 → 1.0.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 (434) hide show
  1. package/dist/access-grant-rls.d.ts +3 -0
  2. package/dist/admission-trace.d.ts +8 -0
  3. package/dist/api-websocket.d.ts +18 -0
  4. package/dist/app.d.ts +50 -2
  5. package/dist/app.js +12 -1
  6. package/dist/artifact-catalog-cursor.d.ts +27 -0
  7. package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
  8. package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
  9. package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
  10. package/dist/auth/managed-auth.d.ts +102 -3
  11. package/dist/auth/managed-email.d.ts +29 -0
  12. package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
  13. package/dist/auth/new-signups-gate.d.ts +23 -0
  14. package/dist/auth/organization-user-setup.d.ts +80 -0
  15. package/dist/auth/signup-funnel-metrics.d.ts +44 -0
  16. package/dist/browser-controller-authority.d.ts +1 -61
  17. package/dist/browser-ephemeral.d.ts +5 -0
  18. package/dist/browser-state-authority.d.ts +1 -27
  19. package/dist/chunk-6TZ5LG3O.js +123948 -0
  20. package/dist/chunk-6TZ5LG3O.js.map +1 -0
  21. package/dist/chunk-OGQDXVXY.js +18 -0
  22. package/dist/chunk-OGQDXVXY.js.map +1 -0
  23. package/dist/claude-subscription-account-conflicts.d.ts +1 -0
  24. package/dist/claude-subscription-account-usage.d.ts +39 -0
  25. package/dist/claude-subscription-oauth.d.ts +25 -0
  26. package/dist/claude-subscription-profile.d.ts +9 -0
  27. package/dist/claude-subscription-usage.d.ts +44 -0
  28. package/dist/claude-workspace-connection.d.ts +15 -0
  29. package/dist/codemode.d.ts +32 -1
  30. package/dist/company-brain-okf.d.ts +24 -0
  31. package/dist/connected-machine-computer-access.d.ts +11 -0
  32. package/dist/connection-ownership.d.ts +54 -0
  33. package/dist/controller-data-plane.d.ts +32 -0
  34. package/dist/editable-artifact-source-session.d.ts +3 -0
  35. package/dist/editable-artifact-websocket.d.ts +10 -18
  36. package/dist/editable-artifact-workspace-files.d.ts +1 -1
  37. package/dist/fatal-process-boundary.d.ts +25 -0
  38. package/dist/github-access.d.ts +31 -2
  39. package/dist/http/acting-person.d.ts +24 -0
  40. package/dist/http/api-contract-compat.d.ts +19 -0
  41. package/dist/http/api-error.d.ts +27 -1
  42. package/dist/http/cors.d.ts +17 -0
  43. package/dist/http/deprecation.d.ts +42 -0
  44. package/dist/http/interaction-control-error.d.ts +13 -0
  45. package/dist/http/keyed-admission.d.ts +12 -0
  46. package/dist/http/local-browser-boundary.d.ts +72 -0
  47. package/dist/http/metrics-listener.d.ts +22 -0
  48. package/dist/http/path-identifier.d.ts +17 -0
  49. package/dist/http/registered-route-label.d.ts +16 -0
  50. package/dist/http/request-body.d.ts +27 -0
  51. package/dist/http/request-source.d.ts +52 -0
  52. package/dist/http/sse.d.ts +17 -6
  53. package/dist/http/unmatched-route.d.ts +18 -0
  54. package/dist/http/user-content.d.ts +36 -0
  55. package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
  56. package/dist/index.d.ts +10 -3
  57. package/dist/index.js +1091 -162
  58. package/dist/index.js.map +1 -1
  59. package/dist/integration-endpoint-test.d.ts +20 -0
  60. package/dist/integrations/api-integrations.d.ts +2 -2
  61. package/dist/integrations/atlassian.d.ts +29 -3
  62. package/dist/integrations/connect-authority.d.ts +1 -0
  63. package/dist/integrations/connect-callback-return.d.ts +6 -0
  64. package/dist/integrations/fiken.d.ts +16 -2
  65. package/dist/integrations/github-app-connect.d.ts +47 -0
  66. package/dist/integrations/github-installation-proof.d.ts +3 -0
  67. package/dist/integrations/github-lens-connect.d.ts +116 -0
  68. package/dist/integrations/github-skill-source.d.ts +1 -5
  69. package/dist/integrations/google-drive.d.ts +24 -0
  70. package/dist/integrations/integration-commit-authority.d.ts +13 -0
  71. package/dist/integrations/marketplace-plugin.d.ts +2691 -0
  72. package/dist/integrations/oauth-client.d.ts +178 -18
  73. package/dist/integrations/oauth-profiles.d.ts +222 -0
  74. package/dist/integrations/oauth-return-path.d.ts +1 -0
  75. package/dist/integrations/personal-github-repositories.d.ts +84 -0
  76. package/dist/integrations/personal-github.d.ts +42 -0
  77. package/dist/integrations/pr-review-provider.d.ts +22 -0
  78. package/dist/integrations/provider-oauth.d.ts +19 -1
  79. package/dist/integrations/slack-app-home.d.ts +24 -0
  80. package/dist/integrations/slack-bot.d.ts +367 -12
  81. package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
  82. package/dist/integrations/slack-install.d.ts +20 -0
  83. package/dist/integrations/slack-interactions.d.ts +107 -9
  84. package/dist/integrations/slack-mrkdwn.d.ts +41 -0
  85. package/dist/integrations/slack-routing.d.ts +120 -0
  86. package/dist/integrations/slack-session-defaults.d.ts +58 -0
  87. package/dist/integrations/slack-task-file-upload.d.ts +36 -0
  88. package/dist/integrations/social-oauth.d.ts +7 -0
  89. package/dist/interaction-agent-access.d.ts +15 -0
  90. package/dist/interaction-frame-proxy.d.ts +68 -0
  91. package/dist/interaction-metrics.d.ts +2 -0
  92. package/dist/mcp/action-catalog-types.d.ts +9 -0
  93. package/dist/mcp/action-catalog.gen.d.ts +2 -0
  94. package/dist/mcp/capability-account-readiness.d.ts +7 -0
  95. package/dist/mcp/child-read-evidence.d.ts +9 -0
  96. package/dist/mcp/command-read.d.ts +24 -0
  97. package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
  98. package/dist/mcp/contract-input.d.ts +11 -0
  99. package/dist/mcp/documents.d.ts +7 -5
  100. package/dist/mcp/files.d.ts +2 -2
  101. package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
  102. package/dist/mcp/knowledge-entries.d.ts +5 -0
  103. package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
  104. package/dist/mcp/receipts.d.ts +9 -0
  105. package/dist/mcp/request-abort.d.ts +19 -0
  106. package/dist/mcp/scheduled-task-input.d.ts +1189 -0
  107. package/dist/mcp/scheduled-task-view.d.ts +22 -4
  108. package/dist/mcp/server.d.ts +255 -3
  109. package/dist/mcp/session-event-view.d.ts +94 -0
  110. package/dist/mcp/session-view.d.ts +66 -2
  111. package/dist/mcp/session-wait.d.ts +174 -0
  112. package/dist/mcp-oauth.d.ts +52 -0
  113. package/dist/model-catalog.d.ts +11 -31
  114. package/dist/observability.d.ts +3 -1
  115. package/dist/organization-mcp.d.ts +52 -0
  116. package/dist/organization-recovery-notifications.d.ts +41 -0
  117. package/dist/routes/analytics-consent.d.ts +26 -0
  118. package/dist/routes/api-integrations.d.ts +25 -0
  119. package/dist/routes/api-keys.d.ts +17 -0
  120. package/dist/routes/artifact-catalog.d.ts +6 -0
  121. package/dist/routes/automations.d.ts +19 -0
  122. package/dist/routes/billing.d.ts +49 -0
  123. package/dist/routes/browser-sessions.d.ts +59 -2
  124. package/dist/routes/claude-subscription-accounts.d.ts +3 -0
  125. package/dist/routes/claude-subscription-oauth.d.ts +3 -0
  126. package/dist/routes/client-errors.d.ts +146 -0
  127. package/dist/routes/codex.d.ts +76 -2
  128. package/dist/routes/company-brain.d.ts +3 -0
  129. package/dist/routes/company-profile.d.ts +2 -1
  130. package/dist/routes/computer-sessions.d.ts +14 -0
  131. package/dist/routes/connect.d.ts +5 -0
  132. package/dist/routes/editable-artifacts.d.ts +2 -0
  133. package/dist/routes/external-identity-links.d.ts +6 -0
  134. package/dist/routes/feedback.d.ts +3 -0
  135. package/dist/routes/github-browser-pages.d.ts +12 -0
  136. package/dist/routes/github.d.ts +2 -0
  137. package/dist/routes/insights-response-cache.d.ts +10 -0
  138. package/dist/routes/insights-usage.d.ts +12 -0
  139. package/dist/routes/insights.d.ts +30 -1
  140. package/dist/routes/knowledge.d.ts +3 -0
  141. package/dist/routes/managed-auth-session-sets.d.ts +26 -0
  142. package/dist/routes/managed-onboarding.d.ts +29 -0
  143. package/dist/routes/managed-sign-in-methods.d.ts +6 -0
  144. package/dist/routes/model-connection-access.d.ts +3 -0
  145. package/dist/routes/organization-integration-policy.d.ts +3 -0
  146. package/dist/routes/organization-integrations.d.ts +6 -0
  147. package/dist/routes/organization-mcp-connections.d.ts +3 -0
  148. package/dist/routes/organization-model-providers.d.ts +3 -0
  149. package/dist/routes/organization-recovery.d.ts +19 -0
  150. package/dist/routes/organization-service-accounts.d.ts +3 -0
  151. package/dist/routes/organization-sessions.d.ts +26 -0
  152. package/dist/routes/personal-github-git-broker.d.ts +29 -0
  153. package/dist/routes/personal-github.d.ts +3 -0
  154. package/dist/routes/pr-review-github.d.ts +3 -0
  155. package/dist/routes/pr-review.d.ts +3 -0
  156. package/dist/routes/session-artifact-associations.d.ts +4 -0
  157. package/dist/routes/session-history-imports.d.ts +9 -0
  158. package/dist/routes/sessions.d.ts +44 -6
  159. package/dist/routes/skill-content.d.ts +4 -0
  160. package/dist/routes/skill-install-authority.d.ts +6 -0
  161. package/dist/routes/subscription-account-pools.d.ts +34 -0
  162. package/dist/routes/subscription-pool-access.d.ts +16 -0
  163. package/dist/routes/supergrok.d.ts +6 -1
  164. package/dist/routes/usage-allowances.d.ts +12 -0
  165. package/dist/routes/user-resource-authorities.d.ts +3 -0
  166. package/dist/routes/workspace-artifacts.d.ts +2 -1
  167. package/dist/routes/workspace-capture.d.ts +10 -2
  168. package/dist/routes/workspace-integrations.d.ts +35 -0
  169. package/dist/routes/workspace-learning.d.ts +3 -0
  170. package/dist/routes/workspace-model-providers.d.ts +4 -0
  171. package/dist/routes/workspaces.d.ts +29 -0
  172. package/dist/sandbox/auth-callout.d.ts +8 -0
  173. package/dist/sandbox/channel-a.d.ts +19 -1
  174. package/dist/sandbox/connection-authority.d.ts +3 -0
  175. package/dist/sandbox/enrollment.d.ts +9 -1
  176. package/dist/sandbox/machines.d.ts +5 -2
  177. package/dist/sandbox/metrics-ingestion.d.ts +28 -20
  178. package/dist/sandbox/rematerialize.d.ts +2 -0
  179. package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
  180. package/dist/sandbox/viewer.d.ts +26 -1
  181. package/dist/sandbox-file-artifacts.d.ts +50 -0
  182. package/dist/scheduled-task-deletion.d.ts +13 -0
  183. package/dist/session-create-observability.d.ts +5 -0
  184. package/dist/session-event-view-MPS2OZD3.js +292 -0
  185. package/dist/session-event-view-MPS2OZD3.js.map +1 -0
  186. package/dist/site-session-origin.d.ts +13 -0
  187. package/dist/site-uploads.d.ts +41 -0
  188. package/dist/slack-reaction-files.d.ts +1 -1
  189. package/dist/temporal-schedule-cleanup.d.ts +1 -0
  190. package/dist/temporal-schedule-sync.d.ts +26 -0
  191. package/dist/transcription/providers/xai-subscription.d.ts +1 -0
  192. package/dist/transcription/service.d.ts +2 -1
  193. package/dist/work-discovery-observability.d.ts +33 -0
  194. package/dist/workspace-artifact-content.d.ts +28 -0
  195. package/dist/workspace-artifact-provenance.d.ts +7 -0
  196. package/dist/workspace-delete-observability.d.ts +10 -0
  197. package/dist/workspace-deletion.d.ts +6 -0
  198. package/dist/workspace-state-projection.d.ts +3 -5
  199. package/dist/workspace-tool-gateway-observability.d.ts +17 -0
  200. package/dist/workspace-tool-gateway.d.ts +123 -0
  201. package/dist/workspace-webhook-dispatch.d.ts +26 -0
  202. package/package.json +23 -19
  203. package/src/access-grant-rls.ts +75 -0
  204. package/src/admission-trace.ts +14 -0
  205. package/src/api-websocket.ts +23 -0
  206. package/src/app.ts +1967 -252
  207. package/src/artifact-catalog-cursor.ts +60 -0
  208. package/src/auth/managed-auth-attempt-context.ts +70 -0
  209. package/src/auth/managed-auth-rate-limits.ts +252 -0
  210. package/src/auth/managed-auth-session-adapter.ts +222 -0
  211. package/src/auth/managed-auth.ts +536 -60
  212. package/src/auth/managed-email.ts +174 -0
  213. package/src/auth/managed-sign-in-notifications.ts +81 -0
  214. package/src/auth/new-signups-gate.ts +49 -0
  215. package/src/auth/organization-user-setup.ts +307 -0
  216. package/src/auth/signup-funnel-metrics.ts +164 -0
  217. package/src/browser-controller-authority.ts +1 -186
  218. package/src/browser-ephemeral.ts +39 -0
  219. package/src/browser-state-authority.ts +1 -236
  220. package/src/claude-subscription-account-conflicts.ts +12 -0
  221. package/src/claude-subscription-account-usage.ts +48 -0
  222. package/src/claude-subscription-oauth.ts +362 -0
  223. package/src/claude-subscription-profile.ts +73 -0
  224. package/src/claude-subscription-usage.ts +97 -0
  225. package/src/claude-workspace-connection.ts +82 -0
  226. package/src/codemode.ts +194 -30
  227. package/src/codex-realtime.ts +8 -2
  228. package/src/company-brain-okf.ts +340 -0
  229. package/src/connected-machine-computer-access.ts +33 -0
  230. package/src/connection-ownership.ts +199 -0
  231. package/src/controller-data-plane.ts +81 -0
  232. package/src/editable-artifact-native-kernel.ts +26 -15
  233. package/src/editable-artifact-office-import.ts +28 -3
  234. package/src/editable-artifact-production.ts +23 -7
  235. package/src/editable-artifact-source-session.ts +123 -0
  236. package/src/editable-artifact-websocket.ts +27 -21
  237. package/src/editable-artifact-workspace-files.ts +31 -6
  238. package/src/fatal-process-boundary.ts +246 -0
  239. package/src/gateway-realtime.ts +1 -1
  240. package/src/github-access.ts +147 -5
  241. package/src/http/acting-person.ts +71 -0
  242. package/src/http/api-contract-compat.ts +49 -0
  243. package/src/http/api-error.ts +115 -1
  244. package/src/http/auth.ts +48 -0
  245. package/src/http/cors.ts +67 -0
  246. package/src/http/deprecation.ts +118 -0
  247. package/src/http/interaction-control-error.ts +164 -0
  248. package/src/http/keyed-admission.ts +29 -0
  249. package/src/http/local-browser-boundary.ts +343 -0
  250. package/src/http/metrics-listener.ts +57 -0
  251. package/src/http/path-identifier.ts +54 -0
  252. package/src/http/registered-route-label.ts +34 -0
  253. package/src/http/request-body.ts +127 -0
  254. package/src/http/request-source.ts +178 -0
  255. package/src/http/sse.ts +486 -132
  256. package/src/http/unmatched-route.ts +60 -0
  257. package/src/http/user-content.ts +158 -0
  258. package/src/http/websocket-upgrade-dispatch.ts +29 -0
  259. package/src/index.ts +157 -52
  260. package/src/integration-endpoint-test.ts +291 -0
  261. package/src/integrations/api-integrations.ts +98 -11
  262. package/src/integrations/atlassian.ts +474 -136
  263. package/src/integrations/connect-authority.ts +2 -0
  264. package/src/integrations/connect-callback-return.ts +86 -0
  265. package/src/integrations/fiken.ts +354 -64
  266. package/src/integrations/github-app-connect.ts +435 -0
  267. package/src/integrations/github-installation-proof.ts +60 -0
  268. package/src/integrations/github-lens-connect.ts +76 -0
  269. package/src/integrations/github-skill-source.ts +2 -142
  270. package/src/integrations/google-drive.ts +717 -225
  271. package/src/integrations/integration-commit-authority.ts +69 -0
  272. package/src/integrations/marketplace-plugin.ts +48 -0
  273. package/src/integrations/oauth-client.ts +1356 -459
  274. package/src/integrations/oauth-profiles.ts +537 -0
  275. package/src/integrations/oauth-return-path.ts +18 -0
  276. package/src/integrations/personal-github-repositories.ts +674 -0
  277. package/src/integrations/personal-github.ts +825 -0
  278. package/src/integrations/pr-review-provider.ts +246 -0
  279. package/src/integrations/provider-oauth.ts +250 -22
  280. package/src/integrations/slack-app-home.ts +300 -0
  281. package/src/integrations/slack-bot.ts +963 -239
  282. package/src/integrations/slack-file-upload-flow.ts +147 -0
  283. package/src/integrations/slack-install.ts +83 -0
  284. package/src/integrations/slack-interactions.ts +3167 -474
  285. package/src/integrations/slack-mrkdwn.ts +193 -0
  286. package/src/integrations/slack-routing.ts +337 -0
  287. package/src/integrations/slack-session-defaults.ts +224 -0
  288. package/src/integrations/slack-task-file-upload.ts +323 -0
  289. package/src/integrations/social-oauth.ts +213 -15
  290. package/src/interaction-agent-access.ts +48 -0
  291. package/src/interaction-frame-proxy.ts +409 -0
  292. package/src/interaction-metrics.ts +30 -0
  293. package/src/mcp/action-catalog-types.ts +9 -0
  294. package/src/mcp/action-catalog.gen.ts +6696 -0
  295. package/src/mcp/capability-account-readiness.ts +17 -0
  296. package/src/mcp/child-read-evidence.ts +19 -0
  297. package/src/mcp/command-read.ts +109 -0
  298. package/src/mcp/company-profile-agent-admin.ts +198 -0
  299. package/src/mcp/contract-input.ts +141 -0
  300. package/src/mcp/documents.ts +65 -377
  301. package/src/mcp/editable-artifacts.ts +12 -6
  302. package/src/mcp/files.ts +80 -43
  303. package/src/mcp/first-party-tool-permissions.ts +305 -0
  304. package/src/mcp/knowledge-entries.ts +322 -0
  305. package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
  306. package/src/mcp/receipts.ts +34 -0
  307. package/src/mcp/request-abort.ts +44 -0
  308. package/src/mcp/scheduled-task-input.ts +76 -0
  309. package/src/mcp/scheduled-task-view.ts +44 -3
  310. package/src/mcp/server.ts +3030 -1267
  311. package/src/mcp/session-event-view.ts +383 -0
  312. package/src/mcp/session-view.ts +84 -3
  313. package/src/mcp/session-wait.ts +665 -0
  314. package/src/mcp-oauth.ts +1123 -0
  315. package/src/model-catalog.ts +91 -333
  316. package/src/observability.ts +15 -1
  317. package/src/organization-mcp.ts +397 -0
  318. package/src/organization-recovery-notifications.ts +103 -0
  319. package/src/routes/analytics-consent.ts +123 -0
  320. package/src/routes/api-integrations.ts +364 -74
  321. package/src/routes/api-keys.ts +336 -10
  322. package/src/routes/artifact-catalog.ts +279 -0
  323. package/src/routes/automations.ts +768 -0
  324. package/src/routes/billing.ts +461 -46
  325. package/src/routes/browser-sessions.ts +780 -112
  326. package/src/routes/canonical-human-identities.ts +90 -14
  327. package/src/routes/capabilities.ts +107 -6
  328. package/src/routes/channels.ts +20 -3
  329. package/src/routes/claude-subscription-accounts.ts +334 -0
  330. package/src/routes/claude-subscription-oauth.ts +142 -0
  331. package/src/routes/client-errors.ts +362 -0
  332. package/src/routes/codex.ts +833 -116
  333. package/src/routes/company-brain.ts +322 -0
  334. package/src/routes/company-profile.ts +65 -1
  335. package/src/routes/computer-sessions.ts +557 -106
  336. package/src/routes/connect.ts +1938 -0
  337. package/src/routes/connections.ts +1039 -349
  338. package/src/routes/documents.ts +488 -287
  339. package/src/routes/editable-artifacts.ts +79 -9
  340. package/src/routes/enrollments.ts +135 -39
  341. package/src/routes/environments.ts +154 -58
  342. package/src/routes/external-identity-links.ts +201 -0
  343. package/src/routes/feedback.ts +113 -0
  344. package/src/routes/files.ts +267 -33
  345. package/src/routes/github-browser-pages.ts +162 -0
  346. package/src/routes/github.ts +446 -144
  347. package/src/routes/insights-response-cache.ts +83 -0
  348. package/src/routes/insights-usage.ts +345 -0
  349. package/src/routes/insights.ts +153 -19
  350. package/src/routes/install.ts +133 -38
  351. package/src/routes/integration-facets.ts +107 -33
  352. package/src/routes/interaction-resources.ts +30 -3
  353. package/src/routes/knowledge.ts +488 -0
  354. package/src/routes/machines.ts +313 -15
  355. package/src/routes/managed-auth-session-sets.ts +1218 -0
  356. package/src/routes/managed-onboarding.ts +337 -0
  357. package/src/routes/managed-sign-in-methods.ts +433 -0
  358. package/src/routes/memory-slack-publications.ts +3 -2
  359. package/src/routes/model-connection-access.ts +208 -0
  360. package/src/routes/organization-integration-policy.ts +116 -0
  361. package/src/routes/organization-integrations.ts +326 -0
  362. package/src/routes/organization-mcp-connections.ts +178 -0
  363. package/src/routes/organization-memberships.ts +1019 -27
  364. package/src/routes/organization-model-providers.ts +293 -0
  365. package/src/routes/organization-recovery.ts +325 -0
  366. package/src/routes/organization-service-accounts.ts +128 -0
  367. package/src/routes/organization-sessions.ts +350 -0
  368. package/src/routes/personal-github-git-broker.ts +785 -0
  369. package/src/routes/personal-github.ts +370 -0
  370. package/src/routes/plugins.ts +251 -22
  371. package/src/routes/pr-review-github.ts +881 -0
  372. package/src/routes/pr-review.ts +622 -0
  373. package/src/routes/preference-registry.ts +12 -93
  374. package/src/routes/rigs.ts +167 -50
  375. package/src/routes/scheduled-tasks.ts +346 -41
  376. package/src/routes/session-artifact-associations.ts +87 -0
  377. package/src/routes/session-history-imports.ts +280 -0
  378. package/src/routes/sessions.ts +2306 -264
  379. package/src/routes/skill-content.ts +297 -0
  380. package/src/routes/skill-install-authority.ts +64 -0
  381. package/src/routes/skills.ts +62 -9
  382. package/src/routes/social.ts +46 -18
  383. package/src/routes/subscription-account-pools.ts +436 -0
  384. package/src/routes/subscription-pool-access.ts +126 -0
  385. package/src/routes/supergrok.ts +219 -303
  386. package/src/routes/transcription-recordings.ts +38 -3
  387. package/src/routes/transcriptions.ts +4 -0
  388. package/src/routes/usage-allowances.ts +378 -0
  389. package/src/routes/user-resource-authorities.ts +138 -0
  390. package/src/routes/video-generation.ts +14 -10
  391. package/src/routes/workspace-artifacts.ts +275 -69
  392. package/src/routes/workspace-capture.ts +21 -0
  393. package/src/routes/workspace-integrations.ts +576 -0
  394. package/src/routes/workspace-learning.ts +159 -0
  395. package/src/routes/workspace-model-providers.ts +148 -0
  396. package/src/routes/workspace-state.ts +38 -25
  397. package/src/routes/workspaces.ts +1004 -127
  398. package/src/sandbox/auth-callout.ts +96 -19
  399. package/src/sandbox/channel-a.ts +323 -24
  400. package/src/sandbox/connection-authority.ts +3 -0
  401. package/src/sandbox/enrollment.ts +81 -6
  402. package/src/sandbox/machines.ts +218 -76
  403. package/src/sandbox/metrics-ingestion.ts +411 -62
  404. package/src/sandbox/rematerialize.ts +121 -19
  405. package/src/sandbox/session-attach-variable-sets.ts +131 -0
  406. package/src/sandbox/viewer.ts +280 -25
  407. package/src/sandbox-file-artifacts.ts +413 -0
  408. package/src/scheduled-task-deletion.ts +138 -0
  409. package/src/session-create-observability.ts +46 -0
  410. package/src/session-realtime-context.ts +6 -3
  411. package/src/site-session-origin.ts +48 -0
  412. package/src/site-uploads.ts +224 -0
  413. package/src/slack-reaction-files.ts +16 -5
  414. package/src/temporal-schedule-cleanup.ts +13 -0
  415. package/src/temporal-schedule-sync.ts +74 -0
  416. package/src/transcription/providers/codex-subscription.ts +2 -0
  417. package/src/transcription/providers/openai.ts +1 -0
  418. package/src/transcription/providers/xai-subscription.ts +49 -3
  419. package/src/transcription/segmenter.ts +8 -2
  420. package/src/transcription/service.ts +43 -6
  421. package/src/work-discovery-observability.ts +121 -0
  422. package/src/workspace-artifact-content.ts +144 -0
  423. package/src/workspace-artifact-provenance.ts +104 -0
  424. package/src/workspace-delete-observability.ts +75 -0
  425. package/src/workspace-deletion.ts +73 -0
  426. package/src/workspace-state-projection.ts +18 -148
  427. package/src/workspace-tool-gateway-observability.ts +100 -0
  428. package/src/workspace-tool-gateway.ts +870 -0
  429. package/src/workspace-webhook-dispatch.ts +190 -0
  430. package/src/xai-subscription-auth.ts +9 -2
  431. package/dist/chunk-WCXHI3FF.js +0 -49920
  432. package/dist/chunk-WCXHI3FF.js.map +0 -1
  433. package/dist/routes/packs.d.ts +0 -3
  434. package/src/routes/packs.ts +0 -729
@@ -0,0 +1,665 @@
1
+ /**
2
+ * `session_wait`: one blocking first-party MCP call that replaces the
3
+ * `sleep 55` plus three or four `session_events`/`session_get` probes an agent
4
+ * otherwise runs per loop while it waits for a child or peer session.
5
+ *
6
+ * The durable `session_events` table is the only authority. The NATS event bus
7
+ * is live fanout only, so every wake (bus, deadline, or the initial call) is
8
+ * followed by a database read and the returned rows are always the exact
9
+ * durable events, never the bus payload. Subscriptions are opened before the
10
+ * first read so an event committed between the read and the subscription
11
+ * cannot be missed.
12
+ *
13
+ * Timing facts: the built-in `opengeni` MCP server entry carries no
14
+ * `timeoutMs`, so the worker's MCP client uses the SDK default request timeout
15
+ * of 60 s and a longer call would surface as a `-32001` tool error. The wait is
16
+ * therefore capped at {@link SESSION_WAIT_MAX_SECONDS} both in the tool schema
17
+ * and inside {@link waitForSessionChanges}. The API's `Bun.serve`
18
+ * `idleTimeout` is 255 s, far above that cap.
19
+ *
20
+ * Cancellation: the API serves one transport per POST, so the worker's MCP
21
+ * `notifications/cancelled` never reaches this handler; instead the route binds
22
+ * the HTTP request's own abort to `transport.close()` (`request-abort.ts`),
23
+ * which aborts `extra.signal`. A worker that drops the call on Steer/Pause
24
+ * therefore ends the server-side wait promptly; the deadline bounds it anyway.
25
+ *
26
+ * The live bus is best-effort: a failed subscription degrades the wait to the
27
+ * durable pre-check plus the deadline re-check and is reported as
28
+ * `liveFanout: false` rather than failing the tool.
29
+ */
30
+
31
+ import type {
32
+ SessionEvent,
33
+ SessionEventSemanticClass,
34
+ SessionEventType,
35
+ } from "@opengeni/contracts";
36
+ import {
37
+ SESSION_EVENT_SEMANTIC_CLASS_TYPES,
38
+ SESSION_SYSTEM_UPDATE_WAKE_CLASS,
39
+ compactSessionEventResult,
40
+ isStreamedAssistantMessageCompletion,
41
+ turnCompletedReply,
42
+ type SessionSystemUpdateKind,
43
+ } from "@opengeni/contracts";
44
+ import { SESSION_EVENT_MCP_MAX_BYTES, capPayloadValue } from "./session-view";
45
+
46
+ export const SESSION_WAIT_MAX_TARGETS = 16;
47
+ export const SESSION_WAIT_MAX_SECONDS = 50;
48
+ export const SESSION_WAIT_DEFAULT_SECONDS = 45;
49
+ /** Newest-first durable rows read per target on every database check. */
50
+ export const SESSION_WAIT_EVENTS_PER_TARGET = 20;
51
+
52
+ /**
53
+ * The durable event types that matter to a waiter: turn lifecycle, completed
54
+ * agent messages, blocking failures, goal facts, and session status/control
55
+ * changes. Raw deltas, tool receipts, sandbox/machine diagnostics, and PTY
56
+ * noise never wake a waiter; `session_events` remains the drill-down for them.
57
+ * The change mode further drops per-message completions: see
58
+ * {@link sessionWaitChangeEventMatches}.
59
+ */
60
+ export const SESSION_WAIT_EVENT_TYPES = [
61
+ "turn.started",
62
+ "turn.completed",
63
+ "turn.failed",
64
+ "turn.cancelled",
65
+ "turn.superseded",
66
+ "turn.capacity_waiting",
67
+ "agent.message.completed",
68
+ "session.status.changed",
69
+ "session.requiresAction",
70
+ "session.humanInput.requested",
71
+ "session.control.paused",
72
+ "session.control.resumed",
73
+ "session.wait.started",
74
+ "session.wait.finished",
75
+ "tool.auth_needed",
76
+ "session.command.finished",
77
+ "credential.auth_needed",
78
+ "rig.setup.failed",
79
+ "goal.set",
80
+ "goal.updated",
81
+ "goal.progress",
82
+ "goal.rewrite.proposed",
83
+ "goal.rewrite.rejected",
84
+ "goal.completed",
85
+ "goal.paused",
86
+ "goal.resumed",
87
+ "goal.cleared",
88
+ "goal.continuation",
89
+ ] as const satisfies readonly SessionEventType[];
90
+
91
+ /**
92
+ * Settlement and blocking events that make a child result usable.
93
+ * Goal facts are deliberately absent: an agent can complete its durable goal
94
+ * before it emits the final assistant message and settles the turn. Completed
95
+ * agent messages are also absent because commentary messages use the same
96
+ * event type; an ordinary result-bearing `turn.completed` carries the
97
+ * authoritative final output.
98
+ */
99
+ export const SESSION_WAIT_COMPLETION_EVENT_TYPES = [
100
+ "turn.completed",
101
+ "turn.failed",
102
+ "turn.cancelled",
103
+ "turn.superseded",
104
+ "turn.capacity_waiting",
105
+ "session.requiresAction",
106
+ "session.humanInput.requested",
107
+ "session.control.paused",
108
+ "tool.auth_needed",
109
+ "credential.auth_needed",
110
+ "rig.setup.failed",
111
+ "goal.paused",
112
+ ] as const satisfies readonly SessionEventType[];
113
+
114
+ const SESSION_WAIT_COMPLETION_EVENT_TYPE_SET: ReadonlySet<string> = new Set(
115
+ SESSION_WAIT_COMPLETION_EVENT_TYPES,
116
+ );
117
+
118
+ /**
119
+ * A completed turn is result-bearing only when it carries the ordinary final
120
+ * output. Segment-limit and maintenance turns settle one execution segment
121
+ * while the session still has work to do, so they must not release a parent.
122
+ */
123
+ export function sessionWaitCompletionEventMatches(event: SessionEvent): boolean {
124
+ if (!SESSION_WAIT_COMPLETION_EVENT_TYPE_SET.has(event.type)) return false;
125
+ if (event.type !== "turn.completed") return true;
126
+ if (event.payload === null || typeof event.payload !== "object" || Array.isArray(event.payload)) {
127
+ return false;
128
+ }
129
+ const payload = event.payload as Record<string, unknown>;
130
+ return (
131
+ Object.prototype.hasOwnProperty.call(payload, "output") &&
132
+ !Object.prototype.hasOwnProperty.call(payload, "segmentLimit") &&
133
+ !Object.prototype.hasOwnProperty.call(payload, "maintenance")
134
+ );
135
+ }
136
+
137
+ /**
138
+ * `waitFor=change` wakes on settled changes. A per-message assistant completion
139
+ * (commentary, or a final message the turn is about to settle) is not one: the
140
+ * `turn.completed` that follows carries the answer. Waking on every progress
141
+ * note would only buy the waiter another poll. The phase-less, id-less
142
+ * completion older workers publish with `turn.completed` still matches.
143
+ * Readers pair this with `excludeStreamedAssistantMessages` in SQL.
144
+ */
145
+ export function sessionWaitChangeEventMatches(event: SessionEvent): boolean {
146
+ return !isStreamedAssistantMessageCompletion(event);
147
+ }
148
+
149
+ /** The self-session event that announces a newly pending machine input. */
150
+ export const SESSION_WAIT_OWN_PENDING_EVENT_TYPE =
151
+ "system.update.pending" satisfies SessionEventType;
152
+
153
+ /**
154
+ * Whether a pending own machine input of this kind ends the wait. Every
155
+ * pre-existing kind and `child_requires_action` are `immediate`; deferred
156
+ * child notices are reported but do not end the wait by themselves.
157
+ */
158
+ export function ownPendingKindWakes(kind: string): boolean {
159
+ const wakeClass = SESSION_SYSTEM_UPDATE_WAKE_CLASS[kind as SessionSystemUpdateKind];
160
+ return wakeClass === undefined || wakeClass === "immediate";
161
+ }
162
+
163
+ function ownPendingUpdateFacts(
164
+ kinds: readonly string[],
165
+ ): Pick<
166
+ SessionWaitResult,
167
+ | "ownPendingUpdates"
168
+ | "ownPendingUpdateKinds"
169
+ | "ownPendingImmediateUpdates"
170
+ | "ownPendingDeferredUpdateKinds"
171
+ > {
172
+ const ownKinds = [...new Set(kinds)].sort();
173
+ return {
174
+ ownPendingUpdates: kinds.length,
175
+ ownPendingUpdateKinds: ownKinds,
176
+ ownPendingImmediateUpdates: kinds.filter((kind) => ownPendingKindWakes(kind)).length,
177
+ ownPendingDeferredUpdateKinds: ownKinds.filter((kind) => !ownPendingKindWakes(kind)),
178
+ };
179
+ }
180
+
181
+ /**
182
+ * Re-derive the caller's own pending-input facts after the returned content
183
+ * consumed some of that input, keeping the same byte bound.
184
+ */
185
+ export function withOwnPendingUpdateKinds(
186
+ result: SessionWaitResult,
187
+ kinds: readonly string[],
188
+ ): SessionWaitResult {
189
+ const { truncated: _truncated, bytes: _bytes, maxBytes, ...rest } = result;
190
+ return boundSessionWaitResult({ ...rest, ...ownPendingUpdateFacts(kinds) }, maxBytes);
191
+ }
192
+
193
+ const SEMANTIC_CLASS_PRIORITY: readonly SessionEventSemanticClass[] = [
194
+ "terminal",
195
+ "failure",
196
+ "control",
197
+ "checkpoint",
198
+ "tool_receipt",
199
+ "provider_account",
200
+ ];
201
+
202
+ export function sessionWaitSemanticClass(type: SessionEventType): SessionEventSemanticClass {
203
+ for (const semanticClass of SEMANTIC_CLASS_PRIORITY) {
204
+ const types: readonly SessionEventType[] = SESSION_EVENT_SEMANTIC_CLASS_TYPES[semanticClass];
205
+ if (types.includes(type)) return semanticClass;
206
+ }
207
+ return "control";
208
+ }
209
+
210
+ export type SessionWaitTarget = { sessionId: string; afterSequence: number };
211
+
212
+ export type SessionWaitEventSummary = {
213
+ /** True only when every semantic result field survived all projections. */
214
+ contentComplete?: boolean;
215
+ id: string;
216
+ sequence: number;
217
+ type: SessionEventType;
218
+ occurredAt: string;
219
+ turnId: string | null;
220
+ turnGeneration: number | null;
221
+ status: string;
222
+ text: string | null;
223
+ failure: {
224
+ error: string | null;
225
+ code: string | null;
226
+ retryable: boolean | null;
227
+ recovery: string | null;
228
+ } | null;
229
+ result?: unknown;
230
+ };
231
+
232
+ export type SessionWaitTargetResult = {
233
+ sessionId: string;
234
+ afterSequence: number;
235
+ /** Cursor for the next `session_wait`/`session_events after=` call. */
236
+ latestSequence: number;
237
+ hasMore: boolean;
238
+ events: SessionWaitEventSummary[];
239
+ };
240
+
241
+ export type SessionWaitResult = {
242
+ changed: SessionWaitTargetResult[];
243
+ ownPendingUpdates: number;
244
+ ownPendingUpdateKinds: string[];
245
+ /**
246
+ * Pending own inputs whose kind wakes the session by itself (every
247
+ * pre-existing kind plus `child_requires_action`). Only these end the wait;
248
+ * `deferred` child notices (resolution, pause, capacity wait, progress) are
249
+ * reported but keep the wait on the targets.
250
+ */
251
+ ownPendingImmediateUpdates: number;
252
+ ownPendingDeferredUpdateKinds: string[];
253
+ waitedMs: number;
254
+ timedOut: boolean;
255
+ aborted: boolean;
256
+ /** False when at least one live-fanout subscription failed; the wait then relied on the deadline re-check. */
257
+ liveFanout: boolean;
258
+ truncated: boolean;
259
+ bytes: number;
260
+ maxBytes: number;
261
+ };
262
+
263
+ export type SessionWaitTargetRead = { events: readonly SessionEvent[]; hasMore: boolean };
264
+
265
+ export type SessionWaitSource = {
266
+ /** Durable forward read of matching events strictly after the target cursor. */
267
+ readTargetEvents: (target: SessionWaitTarget) => Promise<SessionWaitTargetRead>;
268
+ /** Kinds of the caller's own pending machine inputs; null disables self tracking. */
269
+ readOwnPendingUpdateKinds: (() => Promise<readonly string[]>) | null;
270
+ /** Live fanout subscription for one session; the returned function unsubscribes. */
271
+ subscribe: (
272
+ sessionId: string,
273
+ onEvents: (events: SessionEvent[]) => void | Promise<void>,
274
+ ) => Promise<() => void>;
275
+ /**
276
+ * Re-run target authorization for the sessions about to be returned after a
277
+ * wait (parity with SSE re-authorization). Throws to refuse the result.
278
+ */
279
+ reauthorizeTargets?: ((sessionIds: readonly string[]) => Promise<void>) | undefined;
280
+ };
281
+
282
+ export type SessionWaitInput = {
283
+ targets: readonly SessionWaitTarget[];
284
+ ownSessionId: string | null;
285
+ maxWaitMs: number;
286
+ /** Target events that end the wait. Defaults to the ordinary activity set. */
287
+ targetEventTypes?: readonly SessionEventType[] | undefined;
288
+ /** Optional payload-aware refinement applied after the event-type filter. */
289
+ targetEventMatches?: ((event: SessionEvent) => boolean) | undefined;
290
+ source: SessionWaitSource;
291
+ signal?: AbortSignal | undefined;
292
+ now?: (() => number) | undefined;
293
+ maxBytes?: number | undefined;
294
+ };
295
+
296
+ type WakeReason = "bus" | "deadline" | "abort";
297
+
298
+ export async function waitForSessionChanges(input: SessionWaitInput): Promise<SessionWaitResult> {
299
+ const now = input.now ?? Date.now;
300
+ const startedAt = now();
301
+ // The cap is enforced here as well as in the tool schema: no caller can hold
302
+ // the API past the worker's 60 s MCP request timeout.
303
+ const deadlineAt =
304
+ startedAt + Math.min(Math.max(0, input.maxWaitMs), SESSION_WAIT_MAX_SECONDS * 1_000);
305
+ let liveFanout = true;
306
+ let waited = false;
307
+ const ownSessionId = input.source.readOwnPendingUpdateKinds ? input.ownSessionId : null;
308
+ const targetEventTypeSet: ReadonlySet<string> = new Set(
309
+ input.targetEventTypes ?? SESSION_WAIT_EVENT_TYPES,
310
+ );
311
+ const targetEventMatches = (event: SessionEvent): boolean =>
312
+ targetEventTypeSet.has(event.type) && (input.targetEventMatches?.(event) ?? true);
313
+
314
+ // One subscription per distinct session; a session may be both a target and
315
+ // the caller's own session, in which case either condition wakes the wait.
316
+ const targetAfter = new Map<string, number>();
317
+ for (const target of input.targets) {
318
+ const existing = targetAfter.get(target.sessionId);
319
+ targetAfter.set(
320
+ target.sessionId,
321
+ existing === undefined ? target.afterSequence : Math.min(existing, target.afterSequence),
322
+ );
323
+ }
324
+ const subscribedSessionIds = new Set<string>(targetAfter.keys());
325
+ if (ownSessionId !== null) subscribedSessionIds.add(ownSessionId);
326
+
327
+ let wake: (() => void) | null = null;
328
+ let wakePending = false;
329
+ const signalWake = () => {
330
+ wakePending = true;
331
+ wake?.();
332
+ };
333
+ const matchesWake = (sessionId: string, events: SessionEvent[]): boolean => {
334
+ const after = targetAfter.get(sessionId);
335
+ for (const event of events) {
336
+ if (event.sessionId !== sessionId) continue;
337
+ if (after !== undefined && event.sequence > after && targetEventMatches(event)) {
338
+ return true;
339
+ }
340
+ if (sessionId === ownSessionId && event.type === SESSION_WAIT_OWN_PENDING_EVENT_TYPE) {
341
+ return true;
342
+ }
343
+ }
344
+ return false;
345
+ };
346
+
347
+ const unsubscribes: Array<() => void> = [];
348
+ const release = () => {
349
+ for (const unsubscribe of unsubscribes.splice(0)) {
350
+ try {
351
+ unsubscribe();
352
+ } catch {
353
+ // Releasing a live-fanout subscription is best-effort; the durable
354
+ // read already decided the result.
355
+ }
356
+ }
357
+ };
358
+
359
+ const readAll = async (): Promise<{
360
+ changed: SessionWaitTargetResult[];
361
+ ownPendingUpdateKinds: string[];
362
+ }> => {
363
+ const [targetReads, ownKinds] = await Promise.all([
364
+ Promise.all(
365
+ input.targets.map(async (target) => ({
366
+ target,
367
+ read: await input.source.readTargetEvents(target),
368
+ })),
369
+ ),
370
+ input.source.readOwnPendingUpdateKinds
371
+ ? input.source.readOwnPendingUpdateKinds()
372
+ : Promise.resolve([] as readonly string[]),
373
+ ]);
374
+ const changed: SessionWaitTargetResult[] = [];
375
+ for (const { target, read } of targetReads) {
376
+ const events = read.events.filter(
377
+ (event) => event.sequence > target.afterSequence && targetEventMatches(event),
378
+ );
379
+ if (events.length === 0) continue;
380
+ changed.push({
381
+ sessionId: target.sessionId,
382
+ afterSequence: target.afterSequence,
383
+ latestSequence: events[events.length - 1]!.sequence,
384
+ hasMore: read.hasMore,
385
+ events: events.map((event) => summarizeSessionWaitEvent(event)),
386
+ });
387
+ }
388
+ return { changed, ownPendingUpdateKinds: [...ownKinds] };
389
+ };
390
+
391
+ const finish = async (
392
+ read: { changed: SessionWaitTargetResult[]; ownPendingUpdateKinds: string[] },
393
+ outcome: { timedOut: boolean; aborted: boolean },
394
+ ): Promise<SessionWaitResult> => {
395
+ // Authorization ran immediately before the first durable read; a result
396
+ // produced after waiting re-proves every returned target first.
397
+ if (waited && read.changed.length > 0 && input.source.reauthorizeTargets) {
398
+ await input.source.reauthorizeTargets(read.changed.map((target) => target.sessionId));
399
+ }
400
+ return boundSessionWaitResult(
401
+ {
402
+ changed: read.changed,
403
+ ...ownPendingUpdateFacts(read.ownPendingUpdateKinds),
404
+ waitedMs: Math.max(0, now() - startedAt),
405
+ timedOut: outcome.timedOut,
406
+ aborted: outcome.aborted,
407
+ liveFanout,
408
+ },
409
+ input.maxBytes,
410
+ );
411
+ };
412
+
413
+ try {
414
+ if (input.signal?.aborted) {
415
+ return await finish(
416
+ { changed: [], ownPendingUpdateKinds: [] },
417
+ { timedOut: false, aborted: true },
418
+ );
419
+ }
420
+ // Subscribe first, then read: an event committed between the read and the
421
+ // subscription would otherwise be missed until the deadline re-check. A
422
+ // failed subscription degrades to pre-check plus deadline re-check.
423
+ for (const sessionId of subscribedSessionIds) {
424
+ try {
425
+ const unsubscribe = await input.source.subscribe(sessionId, (events) => {
426
+ if (matchesWake(sessionId, events)) signalWake();
427
+ });
428
+ unsubscribes.push(unsubscribe);
429
+ } catch {
430
+ liveFanout = false;
431
+ }
432
+ if (input.signal?.aborted) break;
433
+ }
434
+
435
+ for (;;) {
436
+ if (input.signal?.aborted) {
437
+ return await finish(
438
+ { changed: [], ownPendingUpdateKinds: [] },
439
+ { timedOut: false, aborted: true },
440
+ );
441
+ }
442
+ wakePending = false;
443
+ const read = await readAll();
444
+ if (
445
+ read.changed.length > 0 ||
446
+ read.ownPendingUpdateKinds.some((kind) => ownPendingKindWakes(kind))
447
+ ) {
448
+ return await finish(read, { timedOut: false, aborted: false });
449
+ }
450
+ const remainingMs = deadlineAt - now();
451
+ if (remainingMs <= 0) {
452
+ return await finish(read, { timedOut: true, aborted: false });
453
+ }
454
+ if (wakePending) continue;
455
+ const reason = await waitForWake(remainingMs, input.signal, (resolve) => {
456
+ wake = resolve;
457
+ });
458
+ wake = null;
459
+ waited = true;
460
+ if (reason === "abort") {
461
+ return await finish(
462
+ { changed: [], ownPendingUpdateKinds: [] },
463
+ { timedOut: false, aborted: true },
464
+ );
465
+ }
466
+ // "bus" and "deadline" both re-read durable state; the deadline branch is
467
+ // the final re-check that covers any lost live fanout.
468
+ }
469
+ } finally {
470
+ wake = null;
471
+ release();
472
+ }
473
+ }
474
+
475
+ function waitForWake(
476
+ timeoutMs: number,
477
+ signal: AbortSignal | undefined,
478
+ registerWake: (wake: () => void) => void,
479
+ ): Promise<WakeReason> {
480
+ return new Promise<WakeReason>((resolve) => {
481
+ let settled = false;
482
+ let timer: ReturnType<typeof setTimeout> | null = null;
483
+ const onAbort = () => settle("abort");
484
+ const settle = (reason: WakeReason) => {
485
+ if (settled) return;
486
+ settled = true;
487
+ if (timer !== null) clearTimeout(timer);
488
+ signal?.removeEventListener("abort", onAbort);
489
+ resolve(reason);
490
+ };
491
+ registerWake(() => settle("bus"));
492
+ timer = setTimeout(() => settle("deadline"), Math.max(1, Math.ceil(timeoutMs)));
493
+ if (signal) {
494
+ if (signal.aborted) {
495
+ settle("abort");
496
+ return;
497
+ }
498
+ signal.addEventListener("abort", onAbort, { once: true });
499
+ }
500
+ });
501
+ }
502
+
503
+ const SUMMARY_TEXT_TIERS = [2_000, 800, 200] as const;
504
+ const SUMMARY_FAILURE_CHARS = 500;
505
+ const SUMMARY_RESULT_CHARS = 1_000;
506
+
507
+ function truncationMarker(droppedChars: number): string {
508
+ return `…[${droppedChars} chars omitted from this session_wait summary; use session_events view=debug payloadMode=full for the exact event]`;
509
+ }
510
+
511
+ function clampSummaryString(value: string, maxChars: number): string {
512
+ if (value.length <= maxChars) return value;
513
+ const dropped = value.length - maxChars;
514
+ const headChars = Math.max(0, Math.floor(maxChars * 0.7));
515
+ const tailChars = Math.max(0, maxChars - headChars);
516
+ const tail = tailChars > 0 ? value.slice(value.length - tailChars) : "";
517
+ return `${value.slice(0, headChars)}${truncationMarker(dropped)}${tail}`;
518
+ }
519
+
520
+ /** One bounded, result-bearing summary of a durable event for a waiter. */
521
+ export function summarizeSessionWaitEvent(
522
+ event: SessionEvent,
523
+ textChars: number = SUMMARY_TEXT_TIERS[0],
524
+ ): SessionWaitEventSummary {
525
+ const compact = compactSessionEventResult(event, sessionWaitSemanticClass(event.type));
526
+ const text = compact.text === null ? null : clampSummaryString(compact.text, textChars);
527
+ const failure =
528
+ compact.failure === null
529
+ ? null
530
+ : {
531
+ error:
532
+ compact.failure.error === null
533
+ ? null
534
+ : clampSummaryString(compact.failure.error, SUMMARY_FAILURE_CHARS),
535
+ code:
536
+ compact.failure.code === null ? null : clampSummaryString(compact.failure.code, 128),
537
+ retryable: compact.failure.retryable,
538
+ recovery:
539
+ compact.failure.recovery === null
540
+ ? null
541
+ : clampSummaryString(compact.failure.recovery, SUMMARY_FAILURE_CHARS),
542
+ };
543
+ const summary: SessionWaitEventSummary = {
544
+ id: compact.id,
545
+ sequence: compact.sequence,
546
+ type: compact.type,
547
+ occurredAt: compact.occurredAt,
548
+ turnId: compact.turnId,
549
+ turnGeneration: compact.turnGeneration,
550
+ status: compact.status,
551
+ text,
552
+ failure,
553
+ };
554
+ // `result` repeats `text` for plain message/completion events; only carry a
555
+ // distinct structured result so the summary stays small.
556
+ if (
557
+ compact.result !== null &&
558
+ compact.result !== undefined &&
559
+ compact.result !== compact.text &&
560
+ typeof compact.result !== "string"
561
+ ) {
562
+ summary.result = capPayloadValue(compact.result, SUMMARY_RESULT_CHARS);
563
+ } else if (typeof compact.result === "string" && compact.result !== compact.text) {
564
+ summary.result = clampSummaryString(compact.result, textChars);
565
+ }
566
+ // Other wait summaries may omit actionable fields (e.g. human-input
567
+ // questions); absence of a truncation marker is not proof of full content.
568
+ // Neither is the empty output of a turn that ended waiting for input while
569
+ // it records the reply a human's message received.
570
+ summary.contentComplete =
571
+ ["turn.completed", "agent.message.completed"].includes(event.type) &&
572
+ turnCompletedReply(event.payload) === null &&
573
+ !compact.truncation.truncated &&
574
+ text === compact.text &&
575
+ JSON.stringify(failure) === JSON.stringify(compact.failure) &&
576
+ (compact.output === null ||
577
+ compact.output === compact.text ||
578
+ JSON.stringify(compact.output) === JSON.stringify(summary.result)) &&
579
+ (compact.result === null ||
580
+ compact.result === undefined ||
581
+ compact.result === compact.text ||
582
+ JSON.stringify(summary.result) === JSON.stringify(compact.result));
583
+ return summary;
584
+ }
585
+
586
+ function prettyJsonBytes(value: unknown): number {
587
+ return Buffer.byteLength(JSON.stringify(value, null, 2), "utf8");
588
+ }
589
+
590
+ function measure(result: SessionWaitResult): SessionWaitResult {
591
+ let measured = result.bytes;
592
+ for (let attempt = 0; attempt < 8; attempt += 1) {
593
+ result.bytes = measured;
594
+ const next = prettyJsonBytes(result);
595
+ if (next === measured) return result;
596
+ measured = next;
597
+ }
598
+ result.bytes = measured;
599
+ return result;
600
+ }
601
+
602
+ /**
603
+ * Keep the whole model-visible result at or below the `session_events` MCP
604
+ * envelope. Text is tightened first; only then are newest rows dropped from the
605
+ * largest target, which keeps each target's `latestSequence` an exact cursor
606
+ * for the rows actually delivered and marks the remainder as `hasMore`.
607
+ */
608
+ export function boundSessionWaitResult(
609
+ input: Omit<SessionWaitResult, "truncated" | "bytes" | "maxBytes">,
610
+ maxBytes: number = SESSION_EVENT_MCP_MAX_BYTES,
611
+ ): SessionWaitResult {
612
+ const envelopeMaxBytes = Math.max(8 * 1024, maxBytes);
613
+ const build = (changed: SessionWaitTargetResult[], truncated: boolean): SessionWaitResult =>
614
+ measure({
615
+ ...input,
616
+ changed,
617
+ truncated,
618
+ bytes: 0,
619
+ maxBytes: envelopeMaxBytes,
620
+ });
621
+
622
+ let candidate = build(input.changed, false);
623
+ if (candidate.bytes <= envelopeMaxBytes) return candidate;
624
+
625
+ // Tier 1: tighten text on every summary. Summaries carry their source id and
626
+ // sequence, so a tighter projection loses no identity.
627
+ const retextured = (textChars: number): SessionWaitTargetResult[] =>
628
+ input.changed.map((target) => ({
629
+ ...target,
630
+ events: target.events.map((event) => ({
631
+ ...event,
632
+ contentComplete: false,
633
+ text: event.text === null ? null : clampSummaryString(event.text, textChars),
634
+ ...(typeof event.result === "string"
635
+ ? { result: clampSummaryString(event.result, textChars) }
636
+ : {}),
637
+ })),
638
+ }));
639
+ let changed = input.changed;
640
+ for (const textChars of SUMMARY_TEXT_TIERS.slice(1)) {
641
+ changed = retextured(textChars);
642
+ candidate = build(changed, true);
643
+ if (candidate.bytes <= envelopeMaxBytes) return candidate;
644
+ }
645
+
646
+ // Tier 2: drop newest rows from the largest target until the envelope fits.
647
+ const working = changed.map((target) => ({ ...target, events: [...target.events] }));
648
+ for (;;) {
649
+ let largest: (typeof working)[number] | null = null;
650
+ for (const target of working) {
651
+ if (target.events.length === 0) continue;
652
+ if (largest === null || target.events.length > largest.events.length) largest = target;
653
+ }
654
+ if (largest === null) break;
655
+ largest.events.pop();
656
+ largest.hasMore = true;
657
+ largest.latestSequence =
658
+ largest.events.length > 0
659
+ ? largest.events[largest.events.length - 1]!.sequence
660
+ : largest.afterSequence;
661
+ candidate = build(working, true);
662
+ if (candidate.bytes <= envelopeMaxBytes) return candidate;
663
+ }
664
+ throw new RangeError(`session_wait result exceeds its ${envelopeMaxBytes}-byte envelope`);
665
+ }