@opengeni/api-router 3.0.1 → 3.1.2

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 (546) hide show
  1. package/dist/access-grant-rls.d.ts +8 -1
  2. package/dist/admission-trace.d.ts +8 -0
  3. package/dist/app.d.ts +50 -3
  4. package/dist/app.js +10 -1
  5. package/dist/artifact-catalog-cursor.d.ts +1 -0
  6. package/dist/attached-browser-viewer.d.ts +11 -0
  7. package/dist/auth/managed-auth-attempt-context.d.ts +2 -0
  8. package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
  9. package/dist/auth/managed-auth-session-adapter.d.ts +9 -1
  10. package/dist/auth/managed-auth.d.ts +72 -5
  11. package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
  12. package/dist/auth/new-signups-gate.d.ts +23 -0
  13. package/dist/auth/signup-funnel-metrics.d.ts +44 -0
  14. package/dist/azure-live.d.ts +28 -0
  15. package/dist/browser-action-fences.d.ts +13 -0
  16. package/dist/browser-controller-authority.d.ts +1 -61
  17. package/dist/browser-ephemeral.d.ts +5 -0
  18. package/dist/browser-lost-runtime-end.d.ts +24 -0
  19. package/dist/browser-state-authority.d.ts +1 -27
  20. package/dist/chunk-OGQDXVXY.js +18 -0
  21. package/dist/chunk-OGQDXVXY.js.map +1 -0
  22. package/dist/{chunk-AJ62T5QN.js → chunk-OT56OY4V.js} +80503 -39869
  23. package/dist/chunk-OT56OY4V.js.map +1 -0
  24. package/dist/claude-default-models.d.ts +19 -0
  25. package/dist/claude-subscription-core.d.ts +50 -0
  26. package/dist/claude-subscription-oauth.d.ts +36 -0
  27. package/dist/claude-subscription-profile.d.ts +9 -0
  28. package/dist/claude-subscription-usage.d.ts +6 -0
  29. package/dist/claude-workspace-connection.d.ts +15 -0
  30. package/dist/codemode.d.ts +40 -5
  31. package/dist/codex-realtime.d.ts +29 -3
  32. package/dist/codex-session-pointers.d.ts +19 -0
  33. package/dist/connection-ownership.d.ts +6 -3
  34. package/dist/controller-data-plane.d.ts +16 -0
  35. package/dist/credit-promotion-snapshot.d.ts +6 -0
  36. package/dist/editable-artifact-source-session.d.ts +3 -0
  37. package/dist/editable-artifact-websocket.d.ts +5 -3
  38. package/dist/fatal-process-boundary.d.ts +9 -1
  39. package/dist/github-access.d.ts +7 -1
  40. package/dist/github-browser-flow.d.ts +1 -1
  41. package/dist/http/acting-person.d.ts +36 -0
  42. package/dist/http/api-contract-compat.d.ts +19 -0
  43. package/dist/http/api-error.d.ts +50 -1
  44. package/dist/http/auth.d.ts +8 -1
  45. package/dist/http/cors.d.ts +12 -0
  46. package/dist/http/deprecation.d.ts +42 -0
  47. package/dist/http/keyed-admission.d.ts +12 -0
  48. package/dist/http/local-browser-boundary.d.ts +72 -0
  49. package/dist/http/metrics-listener.d.ts +22 -0
  50. package/dist/http/path-identifier.d.ts +17 -0
  51. package/dist/http/registered-route-label.d.ts +16 -0
  52. package/dist/http/rejection-telemetry.d.ts +34 -0
  53. package/dist/http/request-body.d.ts +27 -0
  54. package/dist/http/request-source.d.ts +41 -3
  55. package/dist/http/sse.d.ts +12 -1
  56. package/dist/http/unmatched-route.d.ts +18 -0
  57. package/dist/http/user-content.d.ts +36 -0
  58. package/dist/http/variable-sets-removed.d.ts +41 -0
  59. package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
  60. package/dist/index.js +1279 -108
  61. package/dist/index.js.map +1 -1
  62. package/dist/integration-connect-metrics.d.ts +35 -0
  63. package/dist/integration-endpoint-test.d.ts +20 -0
  64. package/dist/integrations/api-integrations.d.ts +2 -2
  65. package/dist/integrations/atlassian.d.ts +8 -3
  66. package/dist/integrations/fiken.d.ts +3 -1
  67. package/dist/integrations/github-lens-connect.d.ts +37 -66
  68. package/dist/integrations/google-drive.d.ts +2 -0
  69. package/dist/integrations/integration-commit-authority.d.ts +13 -0
  70. package/dist/integrations/marketplace-plugin.d.ts +43 -43
  71. package/dist/integrations/oauth-client.d.ts +171 -12
  72. package/dist/integrations/oauth-profiles.d.ts +42 -13
  73. package/dist/integrations/onepassword-vault-provider.d.ts +9 -0
  74. package/dist/integrations/slack-bot.d.ts +285 -7
  75. package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
  76. package/dist/integrations/slack-interactions.d.ts +89 -10
  77. package/dist/integrations/slack-mrkdwn.d.ts +41 -0
  78. package/dist/integrations/slack-routing.d.ts +1 -1
  79. package/dist/integrations/slack-session-defaults.d.ts +58 -0
  80. package/dist/integrations/slack-task-file-upload.d.ts +36 -0
  81. package/dist/integrations/slack-tool-review.d.ts +5 -0
  82. package/dist/interaction-agent-access.d.ts +13 -8
  83. package/dist/interaction-agent-version.d.ts +21 -0
  84. package/dist/interaction-holder-heartbeat.d.ts +5 -0
  85. package/dist/interaction-metrics.d.ts +27 -2
  86. package/dist/interaction-route-stages.d.ts +25 -0
  87. package/dist/interaction-secrets-vault.d.ts +20 -0
  88. package/dist/interaction-secrets.d.ts +103 -0
  89. package/dist/mcp/action-catalog-types.d.ts +14 -0
  90. package/dist/mcp/action-catalog.gen.d.ts +2 -0
  91. package/dist/mcp/action-descriptions.d.ts +4 -0
  92. package/dist/mcp/action-schema-imports.gen.d.ts +1 -0
  93. package/dist/mcp/capability-account-readiness.d.ts +7 -0
  94. package/dist/mcp/child-read-evidence.d.ts +9 -0
  95. package/dist/mcp/company-profile-agent-admin.d.ts +12 -0
  96. package/dist/mcp/contract-input.d.ts +13 -0
  97. package/dist/mcp/documents.d.ts +2 -0
  98. package/dist/mcp/first-party-tool-permissions.d.ts +3 -606
  99. package/dist/mcp/notification-tools.d.ts +26 -0
  100. package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
  101. package/dist/mcp/scheduled-task-input.d.ts +1309 -0
  102. package/dist/mcp/scheduled-task-view.d.ts +217 -3
  103. package/dist/mcp/secret-tools.d.ts +14 -0
  104. package/dist/mcp/server.d.ts +108 -5
  105. package/dist/mcp/session-admin-access-tools.d.ts +33 -0
  106. package/dist/mcp/session-event-errors.d.ts +28 -0
  107. package/dist/mcp/session-event-view.d.ts +62 -0
  108. package/dist/mcp/session-view.d.ts +15 -0
  109. package/dist/mcp/session-wait.d.ts +18 -0
  110. package/dist/mcp/site-agent-clamp-tools.d.ts +38 -0
  111. package/dist/mcp/site-data-tools.d.ts +22 -0
  112. package/dist/mcp/site-publication-tools.d.ts +19 -0
  113. package/dist/mcp/site-sql-tools.d.ts +27 -0
  114. package/dist/mcp-oauth.d.ts +37 -4
  115. package/dist/model-calls/chat-completions.d.ts +87 -0
  116. package/dist/model-calls/pending-usage-settlements.d.ts +57 -0
  117. package/dist/model-calls/service.d.ts +36 -0
  118. package/dist/model-catalog.d.ts +9 -3
  119. package/dist/native-push-dispatch.d.ts +69 -0
  120. package/dist/observability.d.ts +3 -1
  121. package/dist/organization-mcp.d.ts +82 -0
  122. package/dist/prepared-mcp-actor.d.ts +77 -0
  123. package/dist/prepared-mcp-permissions.d.ts +8 -0
  124. package/dist/routes/analytics-consent.d.ts +26 -0
  125. package/dist/routes/api-integrations.d.ts +11 -0
  126. package/dist/routes/api-keys.d.ts +7 -7
  127. package/dist/routes/automations.d.ts +2 -0
  128. package/dist/routes/billing.d.ts +59 -0
  129. package/dist/routes/browser-sessions.d.ts +65 -2
  130. package/dist/routes/chat-completions.d.ts +11 -0
  131. package/dist/routes/claude-core-usage.d.ts +20 -0
  132. package/dist/routes/claude-subscription-accounts.d.ts +3 -0
  133. package/dist/routes/claude-subscription-oauth.d.ts +3 -0
  134. package/dist/routes/client-errors.d.ts +182 -0
  135. package/dist/routes/codex-core.d.ts +401 -0
  136. package/dist/routes/codex.d.ts +64 -2
  137. package/dist/routes/computer-sessions.d.ts +6 -1
  138. package/dist/routes/desktop-distribution.d.ts +32 -0
  139. package/dist/routes/github-browser-fonts.gen.d.ts +2 -0
  140. package/dist/routes/github-browser-pages.d.ts +27 -0
  141. package/dist/routes/inbox.d.ts +13 -0
  142. package/dist/routes/insights-response-cache.d.ts +10 -0
  143. package/dist/routes/insights-usage.d.ts +12 -0
  144. package/dist/routes/insights.d.ts +28 -0
  145. package/dist/routes/interaction-placement-message.d.ts +7 -0
  146. package/dist/routes/managed-sign-in-methods.d.ts +6 -0
  147. package/dist/routes/model-account-choice.d.ts +13 -0
  148. package/dist/routes/model-account-settings.d.ts +19 -0
  149. package/dist/routes/native-app-auth.d.ts +12 -0
  150. package/dist/routes/organization-integration-policy.d.ts +8 -0
  151. package/dist/routes/organization-integrations.d.ts +6 -0
  152. package/dist/routes/organization-mcp-connections.d.ts +3 -0
  153. package/dist/routes/organization-model-defaults.d.ts +9 -0
  154. package/dist/routes/organization-service-accounts.d.ts +3 -0
  155. package/dist/routes/personal-api-keys.d.ts +3 -0
  156. package/dist/routes/session-admin-access.d.ts +3 -0
  157. package/dist/routes/session-artifact-associations.d.ts +4 -0
  158. package/dist/routes/session-history-imports.d.ts +20 -0
  159. package/dist/routes/sessions.d.ts +38 -2
  160. package/dist/routes/site-data.d.ts +18 -0
  161. package/dist/routes/site-publishing.d.ts +5 -0
  162. package/dist/routes/site-runtime.d.ts +31 -0
  163. package/dist/routes/site-sql.d.ts +16 -0
  164. package/dist/routes/slack-bot-access.d.ts +3 -0
  165. package/dist/routes/subscription-account-pools.d.ts +21 -0
  166. package/dist/routes/subscription-core-http.d.ts +5 -0
  167. package/dist/routes/subscription-pool-access.d.ts +37 -0
  168. package/dist/routes/subscription-pool-core.d.ts +153 -0
  169. package/dist/routes/supergrok.d.ts +6 -6
  170. package/dist/routes/usage-allowances.d.ts +12 -0
  171. package/dist/routes/variable-sets-removed.d.ts +2 -0
  172. package/dist/routes/vault-providers.d.ts +34 -0
  173. package/dist/routes/vaults.d.ts +3 -0
  174. package/dist/routes/workspace-integrations.d.ts +35 -0
  175. package/dist/routes/workspace-model-providers.d.ts +4 -0
  176. package/dist/routes/workspaces.d.ts +11 -2
  177. package/dist/sandbox/agent-update.d.ts +64 -0
  178. package/dist/sandbox/auth-callout.d.ts +8 -0
  179. package/dist/sandbox/channel-a.d.ts +15 -1
  180. package/dist/sandbox/enrollment.d.ts +26 -4
  181. package/dist/sandbox/machine-audience.d.ts +29 -0
  182. package/dist/sandbox/machines.d.ts +15 -2
  183. package/dist/sandbox/metrics-ingestion.d.ts +6 -2
  184. package/dist/sandbox/screen-control.d.ts +85 -0
  185. package/dist/sandbox/viewer.d.ts +5 -1
  186. package/dist/sandbox-file-artifacts.d.ts +17 -1
  187. package/dist/scheduled-task-blockers.d.ts +39 -0
  188. package/dist/scheduled-task-deletion.d.ts +3 -4
  189. package/dist/scheduled-task-lifecycle.d.ts +14 -0
  190. package/dist/secret-answers.d.ts +40 -0
  191. package/dist/session-create-observability.d.ts +5 -0
  192. package/dist/session-event-view-36GO3IL7.js +528 -0
  193. package/dist/session-event-view-36GO3IL7.js.map +1 -0
  194. package/dist/signed-state-secret.d.ts +18 -0
  195. package/dist/site-agent-guard.d.ts +53 -0
  196. package/dist/site-data/operations.d.ts +103 -0
  197. package/dist/site-data/service.d.ts +203 -0
  198. package/dist/site-frame-guard.d.ts +32 -0
  199. package/dist/site-publishing/agent-data-tools.d.ts +84 -0
  200. package/dist/site-publishing/agent-model.d.ts +58 -0
  201. package/dist/site-publishing/agent-session.d.ts +16 -0
  202. package/dist/site-publishing/content-scanner.d.ts +31 -0
  203. package/dist/site-publishing/edge-sync.d.ts +48 -0
  204. package/dist/site-publishing/gateway-signature.d.ts +56 -0
  205. package/dist/site-publishing/limits.d.ts +63 -0
  206. package/dist/site-publishing/page-tool-authority.d.ts +30 -0
  207. package/dist/site-publishing/platform-usage.d.ts +113 -0
  208. package/dist/site-publishing/platform.d.ts +21 -0
  209. package/dist/site-publishing/readiness.d.ts +62 -0
  210. package/dist/site-publishing/runtime.d.ts +179 -0
  211. package/dist/site-publishing/service.d.ts +264 -0
  212. package/dist/site-publishing/session-events.d.ts +22 -0
  213. package/dist/site-publishing/session-views.d.ts +36 -0
  214. package/dist/site-publishing/viewer.d.ts +40 -0
  215. package/dist/site-session-origin.d.ts +31 -6
  216. package/dist/site-sql/format.d.ts +47 -0
  217. package/dist/site-sql/gateway.d.ts +50 -0
  218. package/dist/site-sql/service.d.ts +213 -0
  219. package/dist/temporal-schedule-sync.d.ts +26 -0
  220. package/dist/transcription/billing-refusal.d.ts +8 -0
  221. package/dist/transcription/normalize.d.ts +23 -0
  222. package/dist/transcription/providers/azure-mai.d.ts +12 -0
  223. package/dist/transcription/providers/azure-openai.d.ts +4 -0
  224. package/dist/transcription/providers/openai.d.ts +16 -0
  225. package/dist/transcription/providers/subscription-core.d.ts +39 -0
  226. package/dist/transcription/service.d.ts +10 -1
  227. package/dist/transcription/wav-duration.d.ts +8 -0
  228. package/dist/workspace-tool-gateway-attestations.d.ts +37 -0
  229. package/dist/workspace-tool-gateway-observability.d.ts +16 -0
  230. package/dist/workspace-tool-gateway-secrets.d.ts +27 -0
  231. package/dist/workspace-tool-gateway.d.ts +102 -6
  232. package/dist/workspace-tool-target-fence.d.ts +116 -0
  233. package/dist/workspace-tool-target.d.ts +225 -0
  234. package/dist/workspace-webhook-dispatch.d.ts +26 -0
  235. package/dist/xai-subscription-core.d.ts +60 -0
  236. package/package.json +25 -20
  237. package/src/access-grant-rls.ts +64 -14
  238. package/src/admission-trace.ts +14 -0
  239. package/src/app.ts +1684 -252
  240. package/src/artifact-catalog-cursor.ts +1 -0
  241. package/src/attached-browser-viewer.ts +26 -0
  242. package/src/auth/managed-auth-attempt-context.ts +9 -0
  243. package/src/auth/managed-auth-rate-limits.ts +252 -0
  244. package/src/auth/managed-auth-session-adapter.ts +64 -29
  245. package/src/auth/managed-auth.ts +303 -35
  246. package/src/auth/managed-email.ts +18 -1
  247. package/src/auth/managed-sign-in-notifications.ts +81 -0
  248. package/src/auth/new-signups-gate.ts +49 -0
  249. package/src/auth/organization-user-setup.ts +3 -3
  250. package/src/auth/signup-funnel-metrics.ts +164 -0
  251. package/src/azure-live.ts +103 -0
  252. package/src/browser-action-fences.ts +45 -0
  253. package/src/browser-controller-authority.ts +1 -186
  254. package/src/browser-ephemeral.ts +39 -0
  255. package/src/browser-lost-runtime-end.ts +71 -0
  256. package/src/browser-state-authority.ts +1 -236
  257. package/src/claude-default-models.ts +37 -0
  258. package/src/claude-subscription-core.ts +154 -0
  259. package/src/claude-subscription-oauth.ts +352 -0
  260. package/src/claude-subscription-profile.ts +73 -0
  261. package/src/claude-subscription-usage.ts +51 -0
  262. package/src/claude-workspace-connection.ts +82 -0
  263. package/src/codemode.ts +236 -39
  264. package/src/codex-realtime.ts +181 -53
  265. package/src/codex-session-pointers.ts +80 -0
  266. package/src/company-brain-okf.ts +1 -1
  267. package/src/connected-machine-computer-access.ts +2 -1
  268. package/src/connection-ownership.ts +19 -13
  269. package/src/controller-data-plane.ts +34 -0
  270. package/src/credit-promotion-snapshot.ts +36 -0
  271. package/src/editable-artifact-production.ts +10 -0
  272. package/src/editable-artifact-source-session.ts +123 -0
  273. package/src/editable-artifact-websocket.ts +16 -3
  274. package/src/fatal-process-boundary.ts +67 -3
  275. package/src/gateway-realtime.ts +12 -8
  276. package/src/github-access.ts +31 -5
  277. package/src/github-browser-flow.ts +1 -1
  278. package/src/http/acting-person.ts +105 -0
  279. package/src/http/api-contract-compat.ts +49 -0
  280. package/src/http/api-error.ts +210 -2
  281. package/src/http/auth.ts +68 -4
  282. package/src/http/cors.ts +37 -5
  283. package/src/http/deprecation.ts +118 -0
  284. package/src/http/keyed-admission.ts +29 -0
  285. package/src/http/local-browser-boundary.ts +343 -0
  286. package/src/http/metrics-listener.ts +57 -0
  287. package/src/http/path-identifier.ts +54 -0
  288. package/src/http/registered-route-label.ts +34 -0
  289. package/src/http/rejection-telemetry.ts +120 -0
  290. package/src/http/request-body.ts +127 -0
  291. package/src/http/request-source.ts +154 -13
  292. package/src/http/sse.ts +88 -28
  293. package/src/http/unmatched-route.ts +60 -0
  294. package/src/http/user-content.ts +158 -0
  295. package/src/http/variable-sets-removed.ts +122 -0
  296. package/src/http/websocket-upgrade-dispatch.ts +29 -0
  297. package/src/index.ts +107 -57
  298. package/src/integration-connect-metrics.ts +228 -0
  299. package/src/integration-endpoint-test.ts +291 -0
  300. package/src/integrations/api-integrations.ts +81 -7
  301. package/src/integrations/atlassian.ts +202 -83
  302. package/src/integrations/fiken.ts +66 -38
  303. package/src/integrations/github-app-connect.ts +64 -18
  304. package/src/integrations/github-lens-connect.ts +8 -29
  305. package/src/integrations/google-drive.ts +448 -152
  306. package/src/integrations/integration-commit-authority.ts +69 -0
  307. package/src/integrations/marketplace-plugin.ts +1 -1
  308. package/src/integrations/oauth-client.ts +733 -193
  309. package/src/integrations/oauth-profiles.ts +116 -45
  310. package/src/integrations/onepassword-vault-provider.ts +16 -0
  311. package/src/integrations/personal-github-repositories.ts +1 -1
  312. package/src/integrations/personal-github.ts +61 -35
  313. package/src/integrations/provider-oauth.ts +67 -85
  314. package/src/integrations/slack-app-home.ts +5 -5
  315. package/src/integrations/slack-bot.ts +893 -201
  316. package/src/integrations/slack-file-upload-flow.ts +147 -0
  317. package/src/integrations/slack-install.ts +7 -7
  318. package/src/integrations/slack-interactions.ts +1589 -299
  319. package/src/integrations/slack-mrkdwn.ts +193 -0
  320. package/src/integrations/slack-routing.ts +2 -2
  321. package/src/integrations/slack-session-defaults.ts +224 -0
  322. package/src/integrations/slack-task-file-upload.ts +323 -0
  323. package/src/integrations/slack-tool-review.ts +65 -0
  324. package/src/integrations/social-oauth.ts +90 -58
  325. package/src/interaction-agent-access.ts +40 -20
  326. package/src/interaction-agent-version.ts +85 -0
  327. package/src/interaction-holder-heartbeat.ts +24 -8
  328. package/src/interaction-metrics.ts +164 -2
  329. package/src/interaction-route-stages.ts +94 -0
  330. package/src/interaction-secrets-vault.ts +213 -0
  331. package/src/interaction-secrets.ts +426 -0
  332. package/src/mcp/action-catalog-types.ts +14 -0
  333. package/src/mcp/action-catalog.gen.ts +8014 -0
  334. package/src/mcp/action-descriptions.ts +299 -0
  335. package/src/mcp/action-schema-imports.gen.ts +304 -0
  336. package/src/mcp/capability-account-readiness.ts +17 -0
  337. package/src/mcp/child-read-evidence.ts +19 -0
  338. package/src/mcp/company-profile-agent-admin.ts +13 -0
  339. package/src/mcp/contract-input.ts +165 -0
  340. package/src/mcp/documents.ts +9 -2
  341. package/src/mcp/editable-artifacts.ts +29 -11
  342. package/src/mcp/files.ts +5 -1
  343. package/src/mcp/first-party-tool-permissions.ts +7 -285
  344. package/src/mcp/knowledge-entries.ts +108 -34
  345. package/src/mcp/notification-tools.ts +480 -0
  346. package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
  347. package/src/mcp/scheduled-task-input.ts +89 -0
  348. package/src/mcp/scheduled-task-view.ts +63 -3
  349. package/src/mcp/secret-tools.ts +185 -0
  350. package/src/mcp/server.ts +2213 -1116
  351. package/src/mcp/session-admin-access-tools.ts +163 -0
  352. package/src/mcp/session-event-errors.ts +123 -0
  353. package/src/mcp/session-event-view.ts +395 -13
  354. package/src/mcp/session-view.ts +3 -0
  355. package/src/mcp/session-wait.ts +67 -7
  356. package/src/mcp/site-agent-clamp-tools.ts +140 -0
  357. package/src/mcp/site-data-tools.ts +339 -0
  358. package/src/mcp/site-publication-tools.ts +201 -0
  359. package/src/mcp/site-sql-tools.ts +427 -0
  360. package/src/mcp-oauth.ts +635 -45
  361. package/src/model-calls/chat-completions.ts +352 -0
  362. package/src/model-calls/pending-usage-settlements.ts +125 -0
  363. package/src/model-calls/service.ts +694 -0
  364. package/src/model-catalog.ts +68 -17
  365. package/src/native-push-dispatch.ts +457 -0
  366. package/src/observability.ts +15 -1
  367. package/src/organization-mcp.ts +485 -0
  368. package/src/prepared-mcp-actor.ts +154 -0
  369. package/src/prepared-mcp-permissions.ts +38 -0
  370. package/src/routes/analytics-consent.ts +123 -0
  371. package/src/routes/api-integrations.ts +268 -9
  372. package/src/routes/api-keys.ts +164 -25
  373. package/src/routes/artifact-catalog.ts +111 -0
  374. package/src/routes/automations.ts +163 -90
  375. package/src/routes/billing.ts +535 -59
  376. package/src/routes/browser-sessions.ts +966 -342
  377. package/src/routes/canonical-human-identities.ts +61 -0
  378. package/src/routes/capabilities.ts +112 -5
  379. package/src/routes/channels.ts +4 -3
  380. package/src/routes/chat-completions.ts +235 -0
  381. package/src/routes/claude-core-usage.ts +147 -0
  382. package/src/routes/claude-subscription-accounts.ts +233 -0
  383. package/src/routes/claude-subscription-oauth.ts +175 -0
  384. package/src/routes/client-errors.ts +394 -0
  385. package/src/routes/codex-core.ts +687 -0
  386. package/src/routes/codex.ts +1277 -1119
  387. package/src/routes/company-brain.ts +4 -0
  388. package/src/routes/computer-sessions.ts +319 -85
  389. package/src/routes/connect.ts +277 -175
  390. package/src/routes/connections.ts +690 -363
  391. package/src/routes/desktop-distribution.ts +217 -0
  392. package/src/routes/documents.ts +13 -7
  393. package/src/routes/editable-artifacts.ts +74 -4
  394. package/src/routes/enrollments.ts +110 -16
  395. package/src/routes/external-identity-links.ts +13 -12
  396. package/src/routes/files.ts +41 -16
  397. package/src/routes/github-browser-fonts.gen.ts +12 -0
  398. package/src/routes/github-browser-pages.ts +258 -0
  399. package/src/routes/github.ts +200 -75
  400. package/src/routes/inbox.ts +353 -0
  401. package/src/routes/insights-response-cache.ts +83 -0
  402. package/src/routes/insights-usage.ts +345 -0
  403. package/src/routes/insights.ts +103 -8
  404. package/src/routes/install.ts +51 -10
  405. package/src/routes/integration-facets.ts +70 -28
  406. package/src/routes/interaction-placement-message.ts +12 -0
  407. package/src/routes/knowledge.ts +136 -27
  408. package/src/routes/machines.ts +189 -135
  409. package/src/routes/managed-auth-session-sets.ts +43 -10
  410. package/src/routes/managed-onboarding.ts +39 -19
  411. package/src/routes/managed-sign-in-methods.ts +433 -0
  412. package/src/routes/memory-slack-publications.ts +3 -2
  413. package/src/routes/model-account-choice.ts +194 -0
  414. package/src/routes/model-account-settings.ts +235 -0
  415. package/src/routes/model-connection-access.ts +210 -48
  416. package/src/routes/native-app-auth.ts +296 -0
  417. package/src/routes/organization-integration-policy.ts +116 -0
  418. package/src/routes/organization-integrations.ts +326 -0
  419. package/src/routes/organization-mcp-connections.ts +183 -0
  420. package/src/routes/organization-memberships.ts +205 -19
  421. package/src/routes/organization-model-defaults.ts +110 -0
  422. package/src/routes/organization-model-providers.ts +74 -3
  423. package/src/routes/organization-service-accounts.ts +128 -0
  424. package/src/routes/organization-sessions.ts +21 -5
  425. package/src/routes/personal-api-keys.ts +184 -0
  426. package/src/routes/personal-github-git-broker.ts +2 -2
  427. package/src/routes/personal-github.ts +9 -4
  428. package/src/routes/plugins.ts +46 -7
  429. package/src/routes/pr-review-github.ts +105 -118
  430. package/src/routes/pr-review.ts +88 -82
  431. package/src/routes/preference-registry.ts +18 -0
  432. package/src/routes/rigs.ts +48 -13
  433. package/src/routes/scheduled-tasks.ts +347 -27
  434. package/src/routes/session-admin-access.ts +271 -0
  435. package/src/routes/session-artifact-associations.ts +164 -0
  436. package/src/routes/session-history-imports.ts +305 -0
  437. package/src/routes/sessions.ts +1682 -363
  438. package/src/routes/site-data.ts +340 -0
  439. package/src/routes/site-publishing.ts +584 -0
  440. package/src/routes/site-runtime.ts +1944 -0
  441. package/src/routes/site-sql.ts +263 -0
  442. package/src/routes/skill-content.ts +72 -7
  443. package/src/routes/skills.ts +5 -4
  444. package/src/routes/slack-bot-access.ts +108 -0
  445. package/src/routes/social.ts +27 -15
  446. package/src/routes/subscription-account-pools.ts +209 -0
  447. package/src/routes/subscription-core-http.ts +18 -0
  448. package/src/routes/subscription-pool-access.ts +180 -0
  449. package/src/routes/subscription-pool-core.ts +552 -0
  450. package/src/routes/supergrok.ts +174 -655
  451. package/src/routes/transcription-recordings.ts +71 -4
  452. package/src/routes/transcriptions.ts +26 -2
  453. package/src/routes/usage-allowances.ts +381 -0
  454. package/src/routes/variable-sets-removed.ts +19 -0
  455. package/src/routes/vault-providers.ts +782 -0
  456. package/src/routes/vaults.ts +421 -0
  457. package/src/routes/video-generation.ts +30 -12
  458. package/src/routes/workspace-artifacts.ts +165 -53
  459. package/src/routes/workspace-integrations.ts +576 -0
  460. package/src/routes/workspace-model-providers.ts +148 -0
  461. package/src/routes/workspace-state.ts +4 -0
  462. package/src/routes/workspaces.ts +625 -117
  463. package/src/sandbox/agent-update.ts +315 -0
  464. package/src/sandbox/auth-callout.ts +104 -21
  465. package/src/sandbox/channel-a.ts +165 -55
  466. package/src/sandbox/enrollment.ts +131 -22
  467. package/src/sandbox/machine-audience.ts +192 -0
  468. package/src/sandbox/machines.ts +75 -31
  469. package/src/sandbox/metrics-ingestion.ts +133 -2
  470. package/src/sandbox/rematerialize.ts +51 -21
  471. package/src/sandbox/screen-control.ts +289 -0
  472. package/src/sandbox/viewer.ts +33 -58
  473. package/src/sandbox-file-artifacts.ts +53 -27
  474. package/src/scheduled-task-blockers.ts +293 -0
  475. package/src/scheduled-task-deletion.ts +13 -3
  476. package/src/scheduled-task-lifecycle.ts +84 -0
  477. package/src/secret-answers.ts +119 -0
  478. package/src/session-create-observability.ts +46 -0
  479. package/src/session-realtime-context.ts +26 -4
  480. package/src/signed-state-secret.ts +58 -0
  481. package/src/site-agent-guard.ts +261 -0
  482. package/src/site-data/operations.ts +777 -0
  483. package/src/site-data/service.ts +1043 -0
  484. package/src/site-frame-guard.ts +107 -0
  485. package/src/site-publishing/agent-data-tools.ts +250 -0
  486. package/src/site-publishing/agent-model.ts +127 -0
  487. package/src/site-publishing/agent-session.ts +148 -0
  488. package/src/site-publishing/content-scanner.ts +93 -0
  489. package/src/site-publishing/edge-sync.ts +148 -0
  490. package/src/site-publishing/gateway-signature.ts +198 -0
  491. package/src/site-publishing/limits.ts +315 -0
  492. package/src/site-publishing/page-tool-authority.ts +111 -0
  493. package/src/site-publishing/platform-usage.ts +479 -0
  494. package/src/site-publishing/platform.ts +98 -0
  495. package/src/site-publishing/readiness.ts +330 -0
  496. package/src/site-publishing/runtime.ts +831 -0
  497. package/src/site-publishing/service.ts +1282 -0
  498. package/src/site-publishing/session-events.ts +262 -0
  499. package/src/site-publishing/session-views.ts +262 -0
  500. package/src/site-publishing/viewer.ts +75 -0
  501. package/src/site-session-origin.ts +91 -6
  502. package/src/site-sql/format.ts +134 -0
  503. package/src/site-sql/gateway.ts +168 -0
  504. package/src/site-sql/service.ts +1636 -0
  505. package/src/site-uploads.ts +27 -5
  506. package/src/temporal-schedule-sync.ts +74 -0
  507. package/src/transcription/billing-refusal.ts +14 -0
  508. package/src/transcription/normalize.ts +77 -0
  509. package/src/transcription/providers/azure-mai.ts +98 -0
  510. package/src/transcription/providers/azure-openai.ts +16 -7
  511. package/src/transcription/providers/codex-subscription.ts +190 -67
  512. package/src/transcription/providers/openai.ts +79 -5
  513. package/src/transcription/providers/subscription-core.ts +125 -0
  514. package/src/transcription/providers/xai-subscription.ts +81 -83
  515. package/src/transcription/segmenter.ts +7 -1
  516. package/src/transcription/service.ts +239 -10
  517. package/src/transcription/wav-duration.ts +39 -0
  518. package/src/workspace-deletion.ts +25 -1
  519. package/src/workspace-tool-gateway-attestations.ts +133 -0
  520. package/src/workspace-tool-gateway-observability.ts +64 -0
  521. package/src/workspace-tool-gateway-secrets.ts +104 -0
  522. package/src/workspace-tool-gateway.ts +921 -103
  523. package/src/workspace-tool-target-fence.ts +380 -0
  524. package/src/workspace-tool-target.ts +554 -0
  525. package/src/workspace-webhook-dispatch.ts +225 -0
  526. package/src/xai-realtime.ts +85 -81
  527. package/src/xai-subscription-core.ts +172 -0
  528. package/dist/browser-auth-broker.d.ts +0 -20
  529. package/dist/chunk-AJ62T5QN.js.map +0 -1
  530. package/dist/connection-authority-owner.d.ts +0 -59
  531. package/dist/routes/connection-authorities.d.ts +0 -3
  532. package/dist/routes/environments.d.ts +0 -5
  533. package/dist/routes/host-mcp-bindings.d.ts +0 -5
  534. package/dist/routes/host-mcp-resolvers.d.ts +0 -3
  535. package/dist/routes/packs.d.ts +0 -3
  536. package/dist/session-event-view-MU3HMNV3.js +0 -264
  537. package/dist/session-event-view-MU3HMNV3.js.map +0 -1
  538. package/dist/xai-subscription-auth.d.ts +0 -23
  539. package/src/browser-auth-broker.ts +0 -155
  540. package/src/connection-authority-owner.ts +0 -61
  541. package/src/routes/connection-authorities.ts +0 -139
  542. package/src/routes/environments.ts +0 -388
  543. package/src/routes/host-mcp-bindings.ts +0 -122
  544. package/src/routes/host-mcp-resolvers.ts +0 -41
  545. package/src/routes/packs.ts +0 -784
  546. package/src/xai-subscription-auth.ts +0 -139
package/src/codemode.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { siteRequestHeaders } from "@opengeni/contracts/site-session-http";
2
1
  import {
3
2
  codemodeDispatchSubject,
4
3
  decodeCodemodeDispatchAck,
@@ -14,29 +13,43 @@ import {
14
13
  type CodemodeOperation,
15
14
  } from "@opengeni/contracts";
16
15
  import type { ApiRouteDeps } from "@opengeni/core";
17
- import { hasPermission, requireSessionAuthorization } from "@opengeni/core";
16
+ import { hasPermission, isDeveloperSetupGrant, requireSessionAuthorization } from "@opengeni/core";
18
17
  import {
18
+ CodemodeToolApprovalRequiredError,
19
19
  getActiveSessionTurnForExecution,
20
20
  getAttemptToolCatalog,
21
21
  getCodemodeOperation,
22
+ readTurnCodemodeOperation,
22
23
  submitCodemodeOperation,
24
+ type SessionTurnForExecution,
23
25
  } from "@opengeni/db";
24
- import { getSession } from "@opengeni/db";
26
+ import { getSession, requireWorkspace } from "@opengeni/db";
25
27
  import {
26
28
  allowedFirstPartyMcpToolsForSession,
29
+ resolveSessionFirstPartyMcpTools,
27
30
  resolveFirstPartyDelegationSecret,
28
- type Settings,
31
+ type FirstPartyMcpToolPolicySettings,
29
32
  } from "@opengeni/config";
30
33
  import {
31
34
  DEFAULT_FIRST_PARTY_MCP_PERMISSIONS,
32
35
  signDelegatedAccessToken,
33
- siteSessionPath,
36
+ readTurnExecutionPolicyV1,
34
37
  OPENGENI_API_CONTRACT_HEADER,
35
38
  OPENGENI_API_CONTRACT_REVISION,
36
39
  type Permission,
37
40
  type Session,
38
41
  } from "@opengeni/contracts";
42
+ import {
43
+ SITE_FRAME_HEADER,
44
+ SITE_FRAME_ID_HEADER,
45
+ SITE_PREVIEW_FRAME,
46
+ siteFrameFromHeaders,
47
+ siteHostWorkspacePath,
48
+ siteRequestHeaders,
49
+ siteSessionPath,
50
+ } from "@opengeni/contracts/site-session-http";
39
51
  import { permissionsRequiredByFirstPartyTools } from "./mcp/first-party-tool-permissions";
52
+ import { isPreparedMcpConnectPath, preparedMcpProxyPermissions } from "./prepared-mcp-permissions";
40
53
 
41
54
  /** The REST authority a Codemode SDK proxy token may ever carry. */
42
55
  export const CODEMODE_SESSION_PROXY_PERMISSION_CEILING = [
@@ -55,7 +68,7 @@ export const CODEMODE_SESSION_PROXY_PERMISSION_CEILING = [
55
68
  * exactly as its MCP surface would.
56
69
  */
57
70
  export function codemodeSessionProxyPermissions(
58
- settings: Pick<Settings, "defaultFirstPartyMcpTools" | "allowedFirstPartyMcpTools">,
71
+ settings: FirstPartyMcpToolPolicySettings,
59
72
  session: Pick<Session, "firstPartyMcpTools" | "firstPartyMcpPermissions">,
60
73
  ): Permission[] {
61
74
  const sessionPermissions = session.firstPartyMcpPermissions ?? [
@@ -71,6 +84,34 @@ export function codemodeSessionProxyPermissions(
71
84
  );
72
85
  }
73
86
 
87
+ const FRAME_ID = /^[A-Za-z0-9_-]{1,64}$/u;
88
+
89
+ /**
90
+ * The route a Codemode SDK proxy request may take. The agent's own SDK calls
91
+ * keep the workspace prefix boundary under the proxy permission ceiling. A
92
+ * request a local Site preview forwarded from page code carries the frame
93
+ * marker and is held to the `SITE_OPERATIONS` allowlist; it stays marked as
94
+ * a preview frame (never a published Site) so the API records its origin and
95
+ * keeps it to the sessions it started.
96
+ */
97
+ function codemodeProxyRoute(request: Request, path: string) {
98
+ const frame = siteFrameFromHeaders((name) => request.headers.get(name));
99
+ if (!frame) {
100
+ return {
101
+ path: (workspaceId: string) => siteHostWorkspacePath(path, workspaceId),
102
+ frameHeaders: null,
103
+ };
104
+ }
105
+ const frameId = frame.frameId && FRAME_ID.test(frame.frameId) ? frame.frameId : null;
106
+ return {
107
+ path: (workspaceId: string) => siteSessionPath(path, workspaceId, request.method),
108
+ frameHeaders: {
109
+ [SITE_FRAME_HEADER]: SITE_PREVIEW_FRAME,
110
+ ...(frameId ? { [SITE_FRAME_ID_HEADER]: frameId } : {}),
111
+ },
112
+ };
113
+ }
114
+
74
115
  /** Reuse normal REST handlers, including their resource/command authorization.
75
116
  * The exact attempt is checked before issuing this internal-only credential. */
76
117
  export async function codemodeSessionRequest(
@@ -78,23 +119,56 @@ export async function codemodeSessionRequest(
78
119
  grant: AccessGrant,
79
120
  request: Request,
80
121
  path: string,
122
+ resolveProxySettings?: (session: Session) => FirstPartyMcpToolPolicySettings,
81
123
  ): Promise<Request> {
82
- siteSessionPath(path, grant.workspaceId, request.method);
83
- const { authority } = await requireActiveCodemodeCatalog(deps, grant);
124
+ const route = codemodeProxyRoute(request, path);
125
+ route.path(grant.workspaceId);
126
+ const { authority, turn, catalog } = await requireActiveCodemodeCatalog(deps, grant);
84
127
  const session = await getSession(deps.db, authority.workspaceId, authority.sessionId);
85
128
  const secret = resolveFirstPartyDelegationSecret(deps.settings);
86
129
  if (!session || !secret) throw new CodemodeAuthorityError("invalid_grant");
87
- const permissions = codemodeSessionProxyPermissions(deps.settings, session);
130
+ const selection = resolveSessionFirstPartyMcpTools(
131
+ resolveProxySettings?.(session) ?? deps.settings,
132
+ session,
133
+ (await requireWorkspace(deps.db, authority.workspaceId)).settings,
134
+ ).filter((name) =>
135
+ catalog.entries.some(
136
+ (entry) => entry.identity.serverId === "opengeni" && entry.identity.toolName === name,
137
+ ),
138
+ );
139
+ const permissions = codemodeSessionProxyPermissions(
140
+ resolveProxySettings?.(session) ?? deps.settings,
141
+ { ...session, firstPartyMcpTools: selection },
142
+ );
143
+ if (isPreparedMcpConnectPath(route.path(grant.workspaceId), request.method)) {
144
+ if (selection.includes("custom_mcp_setup_request"))
145
+ permissions.push(
146
+ ...preparedMcpProxyPermissions(
147
+ catalog,
148
+ session.firstPartyMcpPermissions ?? [...DEFAULT_FIRST_PARTY_MCP_PERMISSIONS],
149
+ ),
150
+ );
151
+ }
152
+ const turnPolicy = readTurnExecutionPolicyV1(turn.metadata);
153
+ const initialPolicy = readTurnExecutionPolicyV1(session.metadata);
154
+ const restricted =
155
+ isDeveloperSetupGrant(grant) ||
156
+ (turnPolicy.kind === "valid" &&
157
+ turnPolicy.policy.credentialRestriction === "developer_setup") ||
158
+ (initialPolicy.kind === "valid" &&
159
+ initialPolicy.policy.credentialRestriction === "developer_setup");
88
160
  const token = await signDelegatedAccessToken(secret, {
89
161
  ...authority,
90
162
  permissions,
91
163
  principalKind: "agent_attempt",
164
+ ...(restricted ? { credentialRestriction: "developer_setup" as const } : {}),
92
165
  exp: Math.floor(Date.now() / 1000) + 60,
93
166
  });
94
167
  const target = new URL(request.url);
95
- const rewritten = siteSessionPath(path, authority.workspaceId, request.method);
168
+ const rewritten = route.path(authority.workspaceId);
96
169
  const url = new URL(rewritten, target.origin);
97
170
  const headers = siteRequestHeaders(request.headers);
171
+ for (const [name, value] of Object.entries(route.frameHeaders ?? {})) headers.set(name, value);
98
172
  headers.set("authorization", `Bearer ${token}`);
99
173
  headers.set(OPENGENI_API_CONTRACT_HEADER, OPENGENI_API_CONTRACT_REVISION);
100
174
  return new Request(url, {
@@ -206,7 +280,11 @@ export function requireMatchingCodemodeCatalog(
206
280
  export async function requireActiveCodemodeCatalog(
207
281
  deps: ApiRouteDeps,
208
282
  grant: AccessGrant,
209
- ): Promise<{ authority: CodemodeGrantAuthority; catalog: AttemptToolCatalog }> {
283
+ ): Promise<{
284
+ authority: CodemodeGrantAuthority;
285
+ catalog: AttemptToolCatalog;
286
+ turn: SessionTurnForExecution;
287
+ }> {
210
288
  if (!isCodemodeGrant(grant)) throw new CodemodeAuthorityError("invalid_grant");
211
289
  const authority = codemodeAuthorityForGrant(grant)!;
212
290
  await requireSessionAuthorization(deps, grant, {
@@ -236,19 +314,21 @@ export async function requireActiveCodemodeCatalog(
236
314
  attemptId: authority.attemptId,
237
315
  }),
238
316
  );
239
- return { authority, catalog };
317
+ return { authority, catalog, turn: active };
240
318
  }
241
319
 
242
320
  export async function submitAndDispatchCodemodeCall(
243
321
  deps: ApiRouteDeps,
244
322
  grant: AccessGrant,
245
323
  rawRequest: unknown,
324
+ signal?: AbortSignal,
246
325
  ): Promise<CodemodeCallSubmissionValue> {
247
- const request = CodemodeCallRequest.parse(rawRequest);
326
+ const { durableApproval, ...request } = CodemodeCallRequest.parse(rawRequest);
248
327
  const { authority, catalog } = await requireActiveCodemodeCatalog(deps, grant);
249
328
  if (request.catalogDigest !== catalog.digest) throw new CodemodeCatalogStaleError();
250
329
  const submitted = await submitCodemodeOperation(deps.db, {
251
330
  ...authority,
331
+ ...(durableApproval ? { durableApproval: true } : {}),
252
332
  call: {
253
333
  ...request,
254
334
  caller: { kind: "codemode", subjectId: authority.subjectId },
@@ -261,36 +341,149 @@ export async function submitAndDispatchCodemodeCall(
261
341
  ? "already_running"
262
342
  : "unavailable";
263
343
  if (codemodeOperationNeedsDispatch(operation)) {
264
- try {
265
- const reply = await deps.bus.request(
266
- codemodeDispatchSubject(authority.workspaceId, authority.attemptId),
267
- encodeCodemodeDispatchRequest({
268
- version: 1,
269
- operationId: operation.operationId,
270
- catalogDigest: catalog.digest,
271
- }),
272
- { timeoutMs: CODEMODE_DISPATCH_TIMEOUT_MS },
273
- );
274
- dispatch = decodeCodemodeDispatchAck(reply.data).status;
275
- } catch {
276
- dispatch = "unavailable";
277
- }
278
- operation = await refreshAdmittedCodemodeOperation(operation, () =>
344
+ const readOperation = () =>
279
345
  getCodemodeOperation(deps.db, {
280
346
  accountId: authority.accountId,
281
347
  workspaceId: authority.workspaceId,
282
348
  attemptId: authority.attemptId,
283
349
  operationId: operation.operationId,
284
- }),
285
- );
286
- if (terminal(operation)) dispatch = "terminal";
287
- else if (operation.state === "running" && dispatch === "unavailable") {
288
- dispatch = "already_running";
350
+ });
351
+ // Listen before dispatching so a fast settlement cannot be missed. The
352
+ // settlement event is committed with the operation row, so its arrival
353
+ // means one read returns the terminal operation.
354
+ const wake = codemodeSettlementWake();
355
+ const unsubscribe = await deps.bus
356
+ .subscribe(authority.workspaceId, authority.sessionId, (events) => {
357
+ if (events.some((event) => isCodemodeSettlementEvent(event, operation.operationId))) {
358
+ wake.notify();
359
+ }
360
+ })
361
+ .catch(() => null);
362
+ try {
363
+ try {
364
+ const reply = await deps.bus.request(
365
+ codemodeDispatchSubject(authority.workspaceId, authority.attemptId),
366
+ encodeCodemodeDispatchRequest({
367
+ version: 1,
368
+ operationId: operation.operationId,
369
+ catalogDigest: catalog.digest,
370
+ }),
371
+ { timeoutMs: CODEMODE_DISPATCH_TIMEOUT_MS },
372
+ );
373
+ dispatch = decodeCodemodeDispatchAck(reply.data).status;
374
+ } catch {
375
+ dispatch = "unavailable";
376
+ }
377
+ operation = await refreshAdmittedCodemodeOperation(operation, readOperation);
378
+ // An executing call usually settles within moments. Return its result in
379
+ // this response so clients need no polling round; a longer call returns
380
+ // still running and is read as before.
381
+ if (
382
+ unsubscribe &&
383
+ !terminal(operation) &&
384
+ (dispatch === "accepted" || dispatch === "already_running")
385
+ ) {
386
+ operation = await awaitCodemodeSettlement({
387
+ operation,
388
+ read: readOperation,
389
+ wake,
390
+ budgetMs: CODEMODE_SUBMIT_SETTLE_WAIT_MS,
391
+ fallbackReadMs: CODEMODE_SETTLE_FALLBACK_READ_MS,
392
+ ...(signal ? { signal } : {}),
393
+ });
394
+ }
395
+ if (terminal(operation)) dispatch = "terminal";
396
+ else if (operation.state === "running" && dispatch === "unavailable") {
397
+ dispatch = "already_running";
398
+ }
399
+ } finally {
400
+ unsubscribe?.();
289
401
  }
290
402
  }
291
403
  return CodemodeCallSubmission.parse({ operation, dispatch });
292
404
  }
293
405
 
406
+ /**
407
+ * How long a submission holds its request open for the call to settle. Most
408
+ * tool calls finish well within it; a longer call returns still running.
409
+ */
410
+ export const CODEMODE_SUBMIT_SETTLE_WAIT_MS = 8_000;
411
+ /** Safety-net read cadence if the live settlement event is missed. */
412
+ export const CODEMODE_SETTLE_FALLBACK_READ_MS = 400;
413
+
414
+ export function isCodemodeSettlementEvent(
415
+ event: { type: string; payload?: unknown },
416
+ operationId: string,
417
+ ): boolean {
418
+ if (event.type !== "agent.toolCall.output") return false;
419
+ const payload = event.payload;
420
+ return (
421
+ typeof payload === "object" &&
422
+ payload !== null &&
423
+ (payload as { id?: unknown }).id === operationId
424
+ );
425
+ }
426
+
427
+ export type CodemodeSettlementWake = {
428
+ notify(): void;
429
+ /** Resolve on the next notification (or one already pending), a timeout or abort. */
430
+ wait(timeoutMs: number, signal?: AbortSignal): Promise<void>;
431
+ };
432
+
433
+ export function codemodeSettlementWake(): CodemodeSettlementWake {
434
+ let pending = false;
435
+ let release: (() => void) | null = null;
436
+ return {
437
+ notify() {
438
+ pending = true;
439
+ release?.();
440
+ },
441
+ async wait(timeoutMs, signal) {
442
+ if (!pending && !signal?.aborted) {
443
+ await new Promise<void>((resolve) => {
444
+ const done = () => {
445
+ clearTimeout(timer);
446
+ signal?.removeEventListener("abort", done);
447
+ release = null;
448
+ resolve();
449
+ };
450
+ const timer = setTimeout(done, Math.max(0, timeoutMs));
451
+ signal?.addEventListener("abort", done, { once: true });
452
+ release = done;
453
+ });
454
+ }
455
+ pending = false;
456
+ },
457
+ };
458
+ }
459
+
460
+ /**
461
+ * Wait, within a budget, for an executing operation to settle. Waits only
462
+ * while the operation is queued or running; approval and terminal states
463
+ * return at once. Read failures keep the last known row.
464
+ */
465
+ export async function awaitCodemodeSettlement(input: {
466
+ operation: CodemodeOperation;
467
+ read: () => Promise<CodemodeOperation | null>;
468
+ wake: CodemodeSettlementWake;
469
+ budgetMs: number;
470
+ fallbackReadMs: number;
471
+ signal?: AbortSignal;
472
+ now?: () => number;
473
+ }): Promise<CodemodeOperation> {
474
+ const now = input.now ?? (() => performance.now());
475
+ const deadline = now() + input.budgetMs;
476
+ let operation = input.operation;
477
+ while (operation.state === "queued" || operation.state === "running") {
478
+ const remaining = deadline - now();
479
+ if (remaining <= 0 || input.signal?.aborted) break;
480
+ await input.wake.wait(Math.min(input.fallbackReadMs, remaining), input.signal);
481
+ if (input.signal?.aborted) break;
482
+ operation = (await input.read().catch(() => null)) ?? operation;
483
+ }
484
+ return operation;
485
+ }
486
+
294
487
  export function codemodeOperationNeedsDispatch(operation: CodemodeOperation): boolean {
295
488
  return operation.state === "queued" || operation.state === "running";
296
489
  }
@@ -299,15 +492,19 @@ export async function readCodemodeOperation(
299
492
  deps: ApiRouteDeps,
300
493
  grant: AccessGrant,
301
494
  operationId: string,
495
+ options: { durableApproval?: boolean } = {},
302
496
  ): Promise<CodemodeOperation | null> {
303
- if (!isCodemodeGrant(grant)) throw new CodemodeAuthorityError("invalid_grant");
304
- const authority = codemodeAuthorityForGrant(grant)!;
305
- return await getCodemodeOperation(deps.db, {
306
- accountId: authority.accountId,
307
- workspaceId: authority.workspaceId,
308
- attemptId: authority.attemptId,
497
+ const { authority } = await requireActiveCodemodeCatalog(deps, grant);
498
+ const operation = await readTurnCodemodeOperation(deps.db, {
499
+ ...authority,
500
+ callerSubjectId: authority.subjectId,
309
501
  operationId,
310
502
  });
503
+ if (operation?.state === "waiting_for_approval" && !options.durableApproval)
504
+ throw new CodemodeToolApprovalRequiredError();
505
+ if (!operation || options.durableApproval) return operation;
506
+ const { durableApproval: _capability, approvalRequestId: _requestId, ...legacy } = operation;
507
+ return legacy;
311
508
  }
312
509
 
313
510
  function terminal(operation: CodemodeOperation): boolean {
@@ -13,12 +13,19 @@ import {
13
13
  type CodexRealtimeCallInput,
14
14
  } from "@opengeni/codex";
15
15
  import {
16
- buildCodexTokenResolver,
16
+ acquireSubscriptionCoreCodexOperationLease,
17
+ buildSubscriptionCoreCodexConnectionTokenResolver,
18
+ buildSubscriptionCoreCodexOperationFetch,
19
+ listSubscriptionCoreCodexOperationCandidates,
20
+ readCodexCutoverDisposition,
21
+ readSubscriptionCoreSessionOwner,
22
+ releaseSubscriptionCoreCodexOperationLease,
23
+ renewSubscriptionCoreCodexOperationLease,
24
+ subscriptionCoreCodexPlanHasVoice,
25
+ type SubscriptionCoreCodexOperationLeaseRef,
26
+ type SubscriptionCoreCodexOperationScope,
17
27
  getActiveSessionHistoryItems,
18
- getCodexCredentialStatus,
19
28
  getSessionRealtimeContinuityEntries,
20
- getSessionCodexState,
21
- listCodexAccountStatuses,
22
29
  type Database,
23
30
  } from "@opengeni/db";
24
31
  import { projectSessionRealtimeInitialItems } from "./session-realtime-context";
@@ -59,6 +66,13 @@ export type CodexRealtimeBrokerDependencies = {
59
66
  pinnedCredentialId: string | null;
60
67
  activeCredentialId: string | null;
61
68
  connectedCredentialIds: ReadonlySet<string>;
69
+ /**
70
+ * Connected credentials on a ChatGPT plan without voice (Free): the
71
+ * provider answers their realtime calls with 404.
72
+ */
73
+ voicelessCredentialIds?: ReadonlySet<string>;
74
+ /** Connected credentials open to new allocations whose plan has voice, in pool order. */
75
+ voiceCredentialIds?: readonly string[];
62
76
  }>;
63
77
  loadInitialItems(): Promise<CodexRealtimeInitialItem[]>;
64
78
  tokenResolver(credentialId: string): CodexTokenResolver;
@@ -104,12 +118,14 @@ The initial conversation items are authoritative context from the current sessio
104
118
 
105
119
  Live context wrapped in <session_user_message> is an authoritative user message already routed to the current session. A status of queued_for_execution means it is waiting behind existing work; accepted_for_execution means it is next with no existing work ahead; accepted_for_steering means it was given priority as a change of direction, while any prior work may still be yielding. Incorporate it immediately as conversation context, but never delegate it again or treat the wrapper metadata as user-authored text.
106
120
 
107
- Live context wrapped in <session_human_input_request> means current work is paused for the user's answer. Preserve the exact question meaning and options. Ask one question at a time when useful. The user may answer in the visible form or answer conversationally. If the user answers conversationally, create exactly one delegation containing the relevant question and the user's answer so the session agent can continue with complete context. If the user changes direction instead, delegate the new direction normally. Do not claim work resumed until session context confirms it.
121
+ Live context wrapped in <session_human_input_request> means current work is paused for the user's answer. Preserve the exact question meaning and options. Ask one question at a time when useful. The user may answer in the visible form or answer conversationally. If the user answers conversationally, create exactly one delegation containing the relevant question and the user's answer so the session agent can continue with complete context. If the user changes direction instead, delegate the new direction normally. Do not claim work resumed until session context confirms it. A secret question (a password, key or code) is answered only in the app: say "answer it in the app", never ask for the secret aloud, and never delegate a spoken secret.
108
122
 
109
123
  Live context wrapped in <session_human_input_response> is the authoritative outcome of that pending question. An answered or skipped response came through the structured session UI and is already routed; incorporate it, never delegate it again, and acknowledge briefly only if useful. An expired or cancelled response means the question is no longer active.
110
124
 
111
125
  Live session updates may describe work that started before this realtime conversation, work sent directly by the user, or work delegated during an earlier realtime connection. Treat those updates as part of this same session even when they have no current delegation identity.
112
126
 
127
+ For requests about another session, use the backend to find, select, inspect or act on it while staying in this conversation. Selecting a session alone does not authorize changing its work.
128
+
113
129
  ## Backend use
114
130
 
115
131
  For actions or tasks, always use the backend. If it is unclear whether backend use would help, use it.
@@ -189,11 +205,17 @@ export async function brokerSessionCodexRealtime(
189
205
  );
190
206
  }
191
207
  const selection = await deps.loadSelection();
192
- const credentialId = selectCodexCredentialId({
208
+ const selected = selectCodexCredentialId({
193
209
  sessionPinnedCredentialId: selection.pinnedCredentialId,
194
210
  activeCredentialId: selection.activeCredentialId,
195
211
  connectedIds: selection.connectedCredentialIds,
196
212
  });
213
+ // A turn may run on a plan without voice; a call then takes another
214
+ // connected subscription that has it, when there is one.
215
+ const credentialId =
216
+ selected && selection.voicelessCredentialIds?.has(selected)
217
+ ? (selection.voiceCredentialIds?.[0] ?? selected)
218
+ : selected;
197
219
  if (!credentialId) {
198
220
  throw new CodexRealtimeBrokerError(
199
221
  "credential_unavailable",
@@ -253,59 +275,163 @@ export async function brokerSessionCodexRealtime(
253
275
  }
254
276
  }
255
277
 
256
- /** Bind the pure broker to OpenGeni's encrypted DB credential lifecycle. */
257
- export function buildSessionCodexRealtimeBroker(
278
+ async function loadRealtimeInitialItems(
258
279
  db: Database,
259
- settings: Settings,
260
280
  workspaceId: string,
261
281
  sessionId: string,
282
+ ): Promise<CodexRealtimeInitialItem[]> {
283
+ const [history, continuity] = await Promise.all([
284
+ getActiveSessionHistoryItems(db, workspaceId, sessionId),
285
+ getSessionRealtimeContinuityEntries(db, workspaceId, sessionId),
286
+ ]);
287
+ return projectSessionRealtimeInitialItems(history, continuity);
288
+ }
289
+
290
+ async function createRealtimeCall(
291
+ fetchImpl: CodexFetch,
292
+ auth: CodexAuthHeaders,
293
+ callInput: CodexRealtimeCallInput,
294
+ options: { signal?: AbortSignal | undefined },
295
+ ): Promise<CodexRealtimeProviderAnswer> {
296
+ const providerConfig = await fetchCodexRealtimeProviderConfig(auth, fetchImpl, options);
297
+ return await createCodexRealtimeCall(auth, callInput, fetchImpl, {
298
+ ...options,
299
+ providerConfig,
300
+ });
301
+ }
302
+
303
+ /**
304
+ * Codex realtime on the shared subscription core (M3 PR 2c, EP-N05..N07):
305
+ * each call resolves the session's recorded owner, places one shared
306
+ * organization- or workspace-scoped connection (the session's explicit
307
+ * choice first, then the effective primary, preferring a plan with voice),
308
+ * and holds its own `realtime` operation lease (session-bound, no turn)
309
+ * through negotiation, with refresh under the per-connection lock. The chat
310
+ * binding is never written; the client protocol and HTTP error translation
311
+ * are the legacy broker's.
312
+ */
313
+ export async function brokerSessionCoreCodexRealtime(
314
+ db: Database,
315
+ settings: Settings,
316
+ context: { accountId: string; workspaceId: string; sessionId: string },
317
+ input: Omit<CodexRealtimeBrokerInput, "sessionId">,
262
318
  fetchImpl: CodexFetch = fetch,
263
- ): (input: Omit<CodexRealtimeBrokerInput, "sessionId">) => Promise<CodexRealtimeProviderAnswer> {
264
- return async (input) =>
265
- await brokerSessionCodexRealtime(
266
- {
267
- enabled: settings.codexSubscriptionEnabled,
268
- loadSelection: async () => {
269
- const [sessionState, status, accounts] = await Promise.all([
270
- getSessionCodexState(db, workspaceId, sessionId),
271
- getCodexCredentialStatus(db, workspaceId),
272
- listCodexAccountStatuses(db, workspaceId),
273
- ]);
274
- if (!sessionState) {
275
- throw new CodexRealtimeBrokerError(
276
- "credential_unavailable",
277
- "Session is unavailable for Codex realtime",
278
- );
279
- }
280
- return {
281
- pinnedCredentialId: sessionState.pinnedCredentialId,
282
- activeCredentialId: status?.credentialId ?? null,
283
- connectedCredentialIds: new Set(
284
- accounts
285
- .filter((account) => account.status === "active")
286
- .map((account) => account.id),
287
- ),
288
- };
289
- },
290
- loadInitialItems: async () => {
291
- const [history, continuity] = await Promise.all([
292
- getActiveSessionHistoryItems(db, workspaceId, sessionId),
293
- getSessionRealtimeContinuityEntries(db, workspaceId, sessionId),
294
- ]);
295
- return projectSessionRealtimeInitialItems(history, continuity);
296
- },
297
- tokenResolver: (credentialId) =>
298
- buildCodexTokenResolver(db, settings, workspaceId, credentialId),
299
- createCall: async (auth, callInput, options) => {
300
- const providerConfig = await fetchCodexRealtimeProviderConfig(auth, fetchImpl, options);
301
- return await createCodexRealtimeCall(auth, callInput, fetchImpl, {
302
- ...options,
303
- providerConfig,
304
- });
319
+ ): Promise<CodexRealtimeProviderAnswer> {
320
+ if (!settings.codexSubscriptionEnabled) {
321
+ throw new CodexRealtimeBrokerError(
322
+ "subscription_disabled",
323
+ "Connected Codex subscription realtime is disabled",
324
+ );
325
+ }
326
+ const owner = await readSubscriptionCoreSessionOwner(db, context);
327
+ if (!owner) {
328
+ throw new CodexRealtimeBrokerError(
329
+ "credential_unavailable",
330
+ "Session is unavailable for Codex realtime",
331
+ );
332
+ }
333
+ const scope: SubscriptionCoreCodexOperationScope = {
334
+ kind: "session",
335
+ ...context,
336
+ sessionOwnerSubjectId: owner.ownerSubjectId,
337
+ };
338
+ const candidates = await listSubscriptionCoreCodexOperationCandidates(db, scope);
339
+ // A turn may run on a plan without voice; a call takes a connection that
340
+ // has it whenever one exists (legacy parity).
341
+ const ordered = [
342
+ ...candidates.filter((candidate) => subscriptionCoreCodexPlanHasVoice(candidate.planType)),
343
+ ...candidates.filter((candidate) => !subscriptionCoreCodexPlanHasVoice(candidate.planType)),
344
+ ];
345
+ const operationId = crypto.randomUUID();
346
+ const attemptId = crypto.randomUUID();
347
+ for (const candidate of ordered) {
348
+ const ref: SubscriptionCoreCodexOperationLeaseRef = {
349
+ operationId,
350
+ attemptId,
351
+ operationKind: "realtime",
352
+ connectionId: candidate.connectionId,
353
+ holderId: `realtime:${context.sessionId}`,
354
+ generation: 1,
355
+ };
356
+ const lease = await acquireSubscriptionCoreCodexOperationLease(db, scope, ref);
357
+ if (lease.kind !== "acquired") continue;
358
+ try {
359
+ const resolver = buildSubscriptionCoreCodexConnectionTokenResolver(
360
+ db,
361
+ settings,
362
+ scope,
363
+ candidate.connectionId,
364
+ ref,
365
+ );
366
+ // Configuration and call creation are separate physical requests, as
367
+ // are both requests of the single authentication-only retry.
368
+ const requestFetch = buildSubscriptionCoreCodexOperationFetch(
369
+ db,
370
+ scope,
371
+ ref,
372
+ candidate.connectionId,
373
+ fetchImpl,
374
+ );
375
+ return await brokerSessionCodexRealtime(
376
+ {
377
+ enabled: true,
378
+ loadSelection: async () => ({
379
+ pinnedCredentialId: null,
380
+ activeCredentialId: candidate.connectionId,
381
+ connectedCredentialIds: new Set([candidate.connectionId]),
382
+ }),
383
+ loadInitialItems: () =>
384
+ loadRealtimeInitialItems(db, context.workspaceId, context.sessionId),
385
+ tokenResolver: () => resolver,
386
+ createCall: async (auth, callInput, options) => {
387
+ // Pre-dispatch fence on the exact operation lease.
388
+ if (!(await renewSubscriptionCoreCodexOperationLease(db, scope, ref))) {
389
+ throw new CodexRealtimeBrokerError(
390
+ "credential_unavailable",
391
+ "Codex subscription credential is unavailable",
392
+ );
393
+ }
394
+ return await createRealtimeCall(requestFetch, auth, callInput, options);
395
+ },
305
396
  },
306
- },
307
- { ...input, sessionId },
397
+ { ...input, sessionId: context.sessionId },
398
+ );
399
+ } finally {
400
+ await releaseSubscriptionCoreCodexOperationLease(db, scope, ref).catch(() => false);
401
+ }
402
+ }
403
+ throw new CodexRealtimeBrokerError(
404
+ "credential_unavailable",
405
+ "No connected Codex subscription is available for this session",
406
+ );
407
+ }
408
+
409
+ /** Bind the pure broker to Opengeni's encrypted DB credential lifecycle. */
410
+ export function buildSessionCodexRealtimeBroker(
411
+ db: Database,
412
+ settings: Settings,
413
+ context: { accountId: string; workspaceId: string; sessionId: string },
414
+ fetchImpl: CodexFetch = fetch,
415
+ ): (input: Omit<CodexRealtimeBrokerInput, "sessionId">) => Promise<CodexRealtimeProviderAnswer> {
416
+ const { accountId, workspaceId, sessionId } = context;
417
+ return async (input) => {
418
+ // The account is required: without it a disabled cutover could not fail closed.
419
+ const disposition = await readCodexCutoverDisposition(db, accountId, workspaceId);
420
+ if (disposition === "maintenance") {
421
+ // A disabled cutover row is maintenance: fail closed, no legacy read.
422
+ throw new CodexRealtimeBrokerError(
423
+ "subscription_disabled",
424
+ "Connected Codex subscription realtime is disabled",
425
+ );
426
+ }
427
+ return await brokerSessionCoreCodexRealtime(
428
+ db,
429
+ settings,
430
+ { accountId, workspaceId, sessionId },
431
+ input,
432
+ fetchImpl,
308
433
  );
434
+ };
309
435
  }
310
436
 
311
437
  function credentialError(error: unknown): CodexRealtimeBrokerError {
@@ -322,6 +448,8 @@ function credentialError(error: unknown): CodexRealtimeBrokerError {
322
448
  }
323
449
 
324
450
  function brokerProviderError(error: unknown): CodexRealtimeBrokerError {
451
+ // A core pre-dispatch fence refusal is already typed (legacy calls never raise one).
452
+ if (error instanceof CodexRealtimeBrokerError) return error;
325
453
  if (!(error instanceof CodexRealtimeError)) {
326
454
  return new CodexRealtimeBrokerError("network_error", "Codex realtime provider request failed");
327
455
  }