@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
@@ -26,19 +26,18 @@ import {
26
26
  hasGitHubRepositorySelection,
27
27
  resolveStreamTokenSecret,
28
28
  sandboxLifecycleTransitionWaitMs,
29
+ sandboxWarmRateMicrosPerSecond,
29
30
  stableSandboxEnvironmentForRun,
30
31
  } from "@opengeni/config";
31
32
  import type { Settings } from "@opengeni/config";
32
33
  import { githubAppBotIdentity } from "@opengeni/github";
33
- import { type Session, type StreamUrlRotatedPayload } from "@opengeni/contracts";
34
+ import { type AccessGrant, type Session, type StreamUrlRotatedPayload } from "@opengeni/contracts";
34
35
  import {
35
36
  acquireLease,
36
37
  getLiveEnrollmentConnection,
37
38
  getSandbox,
38
- getScheduledScopedRigVersionMetadata,
39
39
  getSandboxSessionEnvelope,
40
- heartbeatLeaseHolder,
41
- loadWorkspaceEnvironmentForRun,
40
+ heartbeatLeaseHolderStatus,
42
41
  markSandboxProviderReady,
43
42
  markWarmLeaseInstanceLost,
44
43
  readLease,
@@ -47,6 +46,7 @@ import {
47
46
  releaseLeaseHolder,
48
47
  SandboxLeaseSupersededError,
49
48
  SandboxViewerAdmissionBlockedError,
49
+ SandboxPaidComputeAdmissionError,
50
50
  type Database,
51
51
  type LeaseSnapshot,
52
52
  type SandboxRecord,
@@ -154,51 +154,9 @@ export async function sessionAttachEnvironment(
154
154
  * the materialization audit fact. Null records the legacy service sentinel. */
155
155
  attachSubjectId: string | null,
156
156
  ): Promise<Record<string, string>> {
157
- const workspaceEnvironmentValues: Record<string, string> = {};
158
- const rigVersion =
159
- session.rigId && session.rigVersionId
160
- ? await getScheduledScopedRigVersionMetadata(
161
- services.db,
162
- {
163
- accountId: session.accountId,
164
- workspaceId,
165
- subjectId: attachSubjectId ?? "session-attach",
166
- },
167
- session.rigId,
168
- session.rigVersionId,
169
- )
170
- : null;
171
- for (const variableSetId of rigVersion?.version.defaultVariableSetIds ?? []) {
172
- const workspaceEnvironment = await loadWorkspaceEnvironmentForRun(
173
- services.db,
174
- services.settings,
175
- {
176
- accountId: session.accountId,
177
- workspaceId,
178
- variableSetId,
179
- authority: { kind: "session_attach", sessionId: session.id, subjectId: attachSubjectId },
180
- },
181
- );
182
- Object.assign(workspaceEnvironmentValues, workspaceEnvironment?.values ?? {});
183
- }
184
- // Older persisted/test projections can omit the plural field. Preserve the
185
- // legacy final alias as the single explicit selection until every caller is
186
- // guaranteed to have crossed the plural contract boundary.
187
- const explicitVariableSetIds =
188
- session.variableSetIds ?? (session.variableSetId ? [session.variableSetId] : []);
189
- for (const variableSetId of explicitVariableSetIds) {
190
- const workspaceEnvironment = await loadWorkspaceEnvironmentForRun(
191
- services.db,
192
- services.settings,
193
- {
194
- accountId: session.accountId,
195
- workspaceId,
196
- variableSetId,
197
- authority: { kind: "session_attach", sessionId: session.id, subjectId: attachSubjectId },
198
- },
199
- );
200
- Object.assign(workspaceEnvironmentValues, workspaceEnvironment?.values ?? {});
201
- }
157
+ // The manifest carries deployment constants only (W1): user secrets are
158
+ // resolved per command from `{{secret:…}}` references, never seeded here.
159
+ void attachSubjectId;
202
160
  // Build the env with the SESSION's backend, not the deployment default: the
203
161
  // stable base is backend-aware (HOME = the descriptor workspaceRoot, and the
204
162
  // git token-file/askpass pointers derive from HOME), the box is established
@@ -211,11 +169,7 @@ export async function sessionAttachEnvironment(
211
169
  session.sandboxBackend !== services.settings.sandboxBackend
212
170
  ? { ...services.settings, sandboxBackend: session.sandboxBackend }
213
171
  : services.settings;
214
- const environment = stableSandboxEnvironmentForRun(
215
- settingsForSession,
216
- workspaceEnvironmentValues,
217
- { workspaceId },
218
- );
172
+ const environment = stableSandboxEnvironmentForRun(settingsForSession, { workspaceId });
219
173
  if (hasGitCredentialRepositorySelection(session.resources)) {
220
174
  applyGitAuthPointerEnvironment(
221
175
  environment,
@@ -245,6 +199,10 @@ export async function attachViewer(
245
199
  /** The authenticated subject attaching this viewer (0281): recorded on
246
200
  * the holder row together with the live session authority epoch. */
247
201
  viewerSubjectId?: string;
202
+ /** The authenticated route grant, when one drives the attach. It resolves
203
+ * the session's Sandbox Environment for an agent attempt as its
204
+ * initiating human. */
205
+ grant?: AccessGrant;
248
206
  /** Cancel lifecycle waiting when the originating HTTP request disconnects. */
249
207
  waitSignal?: AbortSignal;
250
208
  },
@@ -275,7 +233,12 @@ export async function attachViewer(
275
233
  : null;
276
234
  const leaseTtlMs = settings.sandboxLeaseTtlMs;
277
235
  const sandboxGroupId = session.sandboxGroupId;
278
- const sandboxRuntime = await resolveSessionSandboxRuntime(db, settings, session);
236
+ const sandboxRuntime = await resolveSessionSandboxRuntime(
237
+ db,
238
+ settings,
239
+ session,
240
+ input.grant ? { grant: input.grant } : { subjectId: attachSubjectId },
241
+ );
279
242
 
280
243
  const release = async (): Promise<void> => {
281
244
  await releaseLeaseHolder(db, {
@@ -300,8 +263,13 @@ export async function attachViewer(
300
263
  ...(attachSubjectId ? { viewerSubjectId: attachSubjectId } : {}),
301
264
  ...(attachAuthorityEpoch !== null ? { viewerAuthorityEpoch: attachAuthorityEpoch } : {}),
302
265
  backend: session.sandboxBackend,
266
+ warmBilling: {
267
+ mode: settings.sandboxWarmBillingMode,
268
+ rateMicrosPerSecond: sandboxWarmRateMicrosPerSecond(settings, session.sandboxBackend),
269
+ },
303
270
  os: session.sandboxOs,
304
271
  image: sandboxRuntime.image,
272
+ imagePolicy: "new_creates_only",
305
273
  rigVersionId: session.rigVersionId,
306
274
  leaseTtlMs,
307
275
  warmingLeaseTtlMs: settings.sandboxWarmingTimeoutMs,
@@ -309,11 +277,14 @@ export async function attachViewer(
309
277
  ...(input.waitSignal ? { waitSignal: input.waitSignal } : {}),
310
278
  });
311
279
  } catch (error) {
280
+ if (error instanceof SandboxPaidComputeAdmissionError) {
281
+ throw new HTTPException(402, { message: error.message, cause: error });
282
+ }
312
283
  if (error instanceof SandboxViewerAdmissionBlockedError) {
313
284
  throw new HTTPException(error.reason === "balance" ? 402 : 429, {
314
285
  message:
315
286
  error.reason === "balance"
316
- ? "insufficient OpenGeni credits for an idle sandbox viewer"
287
+ ? "insufficient Opengeni credits for an idle sandbox viewer"
317
288
  : "workspace sandbox warm allowance exhausted",
318
289
  cause: error,
319
290
  });
@@ -592,7 +563,7 @@ export async function heartbeatViewer(
592
563
  expectedEpoch: number;
593
564
  },
594
565
  ): Promise<boolean> {
595
- const alive = await heartbeatLeaseHolder(services.db, {
566
+ const status = await heartbeatLeaseHolderStatus(services.db, {
596
567
  accountId: input.accountId,
597
568
  workspaceId: input.workspaceId,
598
569
  sandboxGroupId: input.sandboxGroupId,
@@ -600,8 +571,12 @@ export async function heartbeatViewer(
600
571
  holderId: input.viewerId,
601
572
  leaseTtlMs: services.settings.sandboxLeaseTtlMs,
602
573
  expectedEpoch: input.expectedEpoch,
574
+ billingMode: services.settings.sandboxWarmBillingMode,
603
575
  });
604
- if (!alive) return false;
576
+ // A funding fence stops renewing paid provider time, but the holder is
577
+ // deliberately kept alive while the viewer winds down or adds funds. Other
578
+ // fences (epoch/rotation/drain) still require the client to re-attach.
579
+ if (!status.leaseExtended) return status.holderAlive && status.fence === "funding";
605
580
  const lease = await readLease(services.db, input.workspaceId, input.sandboxGroupId);
606
581
  if (lease?.liveness === "warm" && lease.leaseEpoch === input.expectedEpoch && lease.instanceId) {
607
582
  await renewSandboxProviderExpiration({
@@ -27,6 +27,12 @@ import {
27
27
  } from "@opengeni/db";
28
28
  import { retryWhileMissing, type ObjectHead, type ObjectStorage } from "@opengeni/storage";
29
29
  import { HTTPException } from "hono/http-exception";
30
+ import {
31
+ isConnectedMachineAbsolutePath,
32
+ relativeConnectedMachinePath,
33
+ resolveConnectedMachinePath,
34
+ type SandboxChannelAService,
35
+ } from "@opengeni/runtime/sandbox";
30
36
 
31
37
  import { withChannelARead } from "./sandbox/channel-a";
32
38
  import { sanitizeFilename } from "./routes/files";
@@ -98,13 +104,12 @@ async function publishSandboxFileArtifactInScope(
98
104
  });
99
105
  }
100
106
 
101
- const path = sandboxArtifactRelativePath(input.path);
102
107
  const maxArtifactBytes = Math.min(SANDBOX_FILE_ARTIFACT_MAX_BYTES, storage.maxSinglePutSizeBytes);
103
108
  if (maxArtifactBytes < 1) {
104
109
  throw new HTTPException(503, { message: "object storage cannot accept artifact files" });
105
110
  }
106
111
  const readLimit = Math.min(25 * 1024 * 1024, maxArtifactBytes + FILE_READ_SENTINEL_BYTES);
107
- const read = await withChannelARead(
112
+ const { path, sandboxPath, read } = await withChannelARead(
108
113
  {
109
114
  db: deps.db,
110
115
  settings: deps.settings,
@@ -116,10 +121,11 @@ async function publishSandboxFileArtifactInScope(
116
121
  workspaceId: input.grant.workspaceId,
117
122
  session: input.session,
118
123
  subjectId: input.grant.subjectId,
124
+ grant: input.grant,
119
125
  ...(input.signal ? { waitSignal: input.signal } : {}),
120
126
  operation: "artifact.publish",
121
127
  },
122
- ({ service }) => service.fsRead({ path, encoding: "base64", maxBytes: readLimit }),
128
+ ({ service }) => readSandboxArtifactFile(service, input.path, readLimit),
123
129
  );
124
130
  if (read.truncated || read.sizeBytes > maxArtifactBytes) {
125
131
  throw new HTTPException(413, {
@@ -234,48 +240,54 @@ async function publishSandboxFileArtifactInScope(
234
240
  });
235
241
  return SandboxFileArtifactReceipt.parse({
236
242
  type: "sandbox_file",
237
- sandboxPath: `/workspace/${path}`,
243
+ sandboxPath,
238
244
  filename,
239
245
  artifact,
240
246
  });
241
247
  }
242
248
 
243
- export function sandboxArtifactRelativePath(value: string): string {
249
+ /** Use the root captured by the same fenced Channel-A service that reads bytes,
250
+ * not the session's placement-home label or a caller-supplied root. */
251
+ export async function readSandboxArtifactFile(
252
+ service: Pick<SandboxChannelAService, "capabilities" | "fsRead">,
253
+ value: string,
254
+ maxBytes: number,
255
+ ) {
256
+ const root = service.capabilities().FileSystem.root;
257
+ const path = sandboxArtifactRelativePath(value, root);
258
+ const sandboxPath = resolveConnectedMachinePath(root, path);
259
+ const read = await service.fsRead({ path, encoding: "base64", maxBytes });
260
+ return { path, sandboxPath, read };
261
+ }
262
+
263
+ export function sandboxArtifactRelativePath(value: string, workspaceRoot = "/workspace"): string {
244
264
  let path = value.trim();
245
265
  if (path.startsWith("sandbox:")) {
246
266
  path = path.slice("sandbox:".length);
247
267
  }
248
- if (path === "/workspace" || path === "/workspace/") {
268
+ if (!path || /[\\/]$/.test(path)) {
249
269
  throw new HTTPException(400, { message: "sandbox artifact path must name a file" });
250
270
  }
251
- if (path.startsWith("/workspace/")) {
252
- path = path.slice("/workspace/".length);
253
- } else if (path.startsWith("/")) {
271
+ let absolute: string;
272
+ let relative: string | null;
273
+ try {
274
+ if (!isConnectedMachineAbsolutePath(workspaceRoot)) throw new Error("Missing workspace root");
275
+ absolute = resolveConnectedMachinePath(workspaceRoot, path);
276
+ relative = relativeConnectedMachinePath(workspaceRoot, absolute);
277
+ } catch {
254
278
  throw new HTTPException(400, {
255
- message: "sandbox artifact path must be inside /workspace",
279
+ message: "sandbox artifact path is invalid for this workspace",
256
280
  });
257
281
  }
258
- if (!path) {
259
- throw new HTTPException(400, { message: "sandbox artifact path must name a file" });
260
- }
261
- if (path.includes("\0")) {
262
- throw new HTTPException(400, { message: "sandbox artifact path is invalid" });
263
- }
264
- const normalized = posix.normalize(path);
265
- if (
266
- normalized === "." ||
267
- normalized === ".." ||
268
- normalized.startsWith("../") ||
269
- normalized.endsWith("/")
270
- ) {
282
+ if (!relative) {
271
283
  throw new HTTPException(400, {
272
- message: "sandbox artifact path must canonically name a file inside /workspace",
284
+ message: "sandbox artifact path must name a file inside the active workspace root",
273
285
  });
274
286
  }
275
- if (`/workspace/${normalized}`.length > SANDBOX_ARTIFACT_ABSOLUTE_PATH_MAX_CHARS) {
287
+ if (absolute.length > SANDBOX_ARTIFACT_ABSOLUTE_PATH_MAX_CHARS) {
276
288
  throw new HTTPException(400, { message: "sandbox artifact path is too long" });
277
289
  }
278
- return normalized;
290
+ return relative;
279
291
  }
280
292
 
281
293
  export function sandboxArtifactSafeFilename(filename: string): string {
@@ -295,6 +307,14 @@ export function sandboxFileContentType(filename: string): string {
295
307
  ".jpg": "image/jpeg",
296
308
  ".json": "application/json",
297
309
  ".md": "text/markdown",
310
+ ".mp4": "video/mp4",
311
+ ".webm": "video/webm",
312
+ ".ogv": "video/ogg",
313
+ ".mp3": "audio/mpeg",
314
+ ".m4a": "audio/mp4",
315
+ ".ogg": "audio/ogg",
316
+ ".wav": "audio/wav",
317
+ ".flac": "audio/flac",
298
318
  ".pdf": "application/pdf",
299
319
  ".png": "image/png",
300
320
  ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
@@ -314,7 +334,13 @@ export function sandboxArtifactIdentity(input: {
314
334
  sha256: string;
315
335
  }): { fileId: string; uploadId: string } {
316
336
  const digest = createHash("sha256")
317
- .update("opengeni-sandbox-file-artifact-v1\0")
337
+ // Newly classified media must not collide with old binary-typed publications.
338
+ // Preserve the v1 identity for every previously supported format.
339
+ .update(
340
+ /^(audio|video)\//.test(sandboxFileContentType(input.path))
341
+ ? "opengeni-sandbox-media-artifact-v1\0"
342
+ : "opengeni-sandbox-file-artifact-v1\0",
343
+ )
318
344
  .update(input.workspaceId)
319
345
  .update("\0")
320
346
  .update(input.sessionId)
@@ -0,0 +1,293 @@
1
+ import {
2
+ NOTIFICATION_SUBTITLE_MAX_CHARS,
3
+ SessionNotificationPostedPayload,
4
+ SessionNotificationWithdrawnPayload,
5
+ } from "@opengeni/contracts";
6
+ import {
7
+ getPendingScheduledTaskBlockerNotice,
8
+ listScheduledTaskBlockerReviews,
9
+ reviewScheduledTaskBlockers,
10
+ settleScheduledTaskBlockerNotice,
11
+ type Database,
12
+ type ScheduledTaskBlockerDecision,
13
+ type ScheduledTaskBlockerFacts,
14
+ type ScheduledTaskBlockerRun,
15
+ } from "@opengeni/db";
16
+ import { appendAndPublishEvents, type EventBus } from "@opengeni/events";
17
+ import type { Observability } from "@opengeni/observability";
18
+
19
+ /**
20
+ * A schedule must never stay stuck without its owner knowing. After each
21
+ * settled scheduled run:
22
+ *
23
+ * - When the platform knows no later run can start until a person acts (its
24
+ * chat is paused or gone, a pinned account or other resource it needs is
25
+ * unavailable, or it was refused as non-retryable), the schedule pauses
26
+ * itself with that reason and its owner is told once.
27
+ * - When runs keep failing or being skipped for a reason that may clear by
28
+ * itself, the owner is told once, after {@link SCHEDULED_TASK_BLOCKER_STREAK}
29
+ * in a row; the schedule keeps running. A single skip or failure is normal.
30
+ *
31
+ * The notice is withdrawn when a later run succeeds or a person resumes,
32
+ * pauses or deletes the schedule. Only scheduled (not manual) runs count, and
33
+ * only runs since the schedule was last edited or resumed.
34
+ */
35
+ export const SCHEDULED_TASK_BLOCKER_STREAK = 3;
36
+
37
+ const SETTLED = new Set(["succeeded", "failed", "skipped"]);
38
+
39
+ type Blocker = { reason: string; text: string };
40
+
41
+ const RESUME = "then resume the schedule.";
42
+
43
+ const NON_RETRYABLE_REFUSAL_TEXT: Record<string, string> = {
44
+ scheduled_authority_unavailable: `The access it was set up with is no longer valid. Refresh the schedule's access, ${RESUME}`,
45
+ machine_target_unavailable: `The machine it runs on is no longer available. Choose another machine or reconnect this one, ${RESUME}`,
46
+ machine_enrollment_inactive: `The machine it runs on is disconnected from Opengeni. Reconnect the machine, ${RESUME}`,
47
+ variable_set_unavailable: `A variable set it uses no longer exists or can't be used. Edit the schedule, ${RESUME}`,
48
+ rig_version_unavailable: `Its rig has no usable version. Publish a rig version or edit the schedule, ${RESUME}`,
49
+ scheduled_model_unavailable: `Its model is no longer available. Edit the schedule to choose another model, ${RESUME}`,
50
+ };
51
+
52
+ const RETRYABLE_REFUSAL_TEXT: Record<string, string> = {
53
+ machine_enrollment_inactive: "the machine it runs on is disconnected",
54
+ insufficient_credits: "the workspace is out of credits",
55
+ allowance_exhausted: "the usage allowance is used up",
56
+ monthly_model_cost_limit: "the monthly model cost limit was reached",
57
+ monthly_agent_run_limit: "the monthly run limit was reached",
58
+ session_usage_limit: "the schedule reached its usage limit",
59
+ };
60
+
61
+ /** A blocker no later run can get past until a person acts, or null. */
62
+ export function scheduledRunHardBlocker(
63
+ task: Pick<ScheduledTaskBlockerFacts["task"], "runMode">,
64
+ run: ScheduledTaskBlockerRun,
65
+ ): Blocker | null {
66
+ if (run.admissionDiagnostic) {
67
+ return {
68
+ reason: "connection_account_unavailable",
69
+ text: `A connected account it needs can no longer be used. Reconnect that account or refresh the schedule's access, ${RESUME}`,
70
+ };
71
+ }
72
+ if (run.admissionRefusal && !run.admissionRefusal.retryable) {
73
+ const reason = run.admissionRefusal.reason;
74
+ return {
75
+ reason,
76
+ text:
77
+ NON_RETRYABLE_REFUSAL_TEXT[reason] ??
78
+ `Every run is refused before it starts (${reason}). Fix that, ${RESUME}`,
79
+ };
80
+ }
81
+ switch (run.error) {
82
+ case "scheduled_session_paused":
83
+ return {
84
+ reason: run.error,
85
+ text: `Its chat is paused, so no run can start there. Resume the chat, ${RESUME}`,
86
+ };
87
+ case "session_cancelled":
88
+ // A run that starts a new chat each time is not blocked by one ended chat.
89
+ return task.runMode === "new_session_per_run"
90
+ ? null
91
+ : {
92
+ reason: run.error,
93
+ text: `The chat it runs in has ended, so no run can start there. Point the schedule at another chat or let it start a new chat each run, ${RESUME}`,
94
+ };
95
+ case "scheduled_target_session_unavailable":
96
+ return {
97
+ reason: run.error,
98
+ text: `The chat it runs in no longer exists. Point the schedule at another chat or let it start a new chat each run, ${RESUME}`,
99
+ };
100
+ case "scheduled_model_unavailable":
101
+ return { reason: run.error, text: NON_RETRYABLE_REFUSAL_TEXT.scheduled_model_unavailable! };
102
+ default:
103
+ return null;
104
+ }
105
+ }
106
+
107
+ function streakBlocker(streak: readonly ScheduledTaskBlockerRun[]): Blocker {
108
+ const count = streak.length;
109
+ if (streak.every((run) => run.error === "scheduled_session_not_idle")) {
110
+ return {
111
+ reason: "scheduled_session_not_idle",
112
+ text: `The last ${count} scheduled runs were skipped because its chat was still busy with earlier work. Check whether that chat is stuck. The schedule keeps trying.`,
113
+ };
114
+ }
115
+ const refusal = streak[0]?.admissionRefusal;
116
+ if (
117
+ refusal?.retryable &&
118
+ streak.every(
119
+ (run) => run.admissionRefusal?.retryable && run.admissionRefusal.reason === refusal.reason,
120
+ )
121
+ ) {
122
+ return {
123
+ reason: refusal.reason,
124
+ text: `The last ${count} scheduled runs were skipped because ${
125
+ RETRYABLE_REFUSAL_TEXT[refusal.reason] ?? `they were refused (${refusal.reason})`
126
+ }. Runs start again once that clears.`,
127
+ };
128
+ }
129
+ const latest = streak[0]!;
130
+ return {
131
+ reason: latest.error ?? latest.status,
132
+ text: `The last ${count} scheduled runs failed or were skipped. Open the latest run to see why. The schedule keeps trying.`,
133
+ };
134
+ }
135
+
136
+ export function scheduledTaskBlockerNoticeKey(taskId: string): string {
137
+ return `schedule-${taskId}`;
138
+ }
139
+
140
+ function clip(text: string, max: number): string {
141
+ return text.length <= max ? text : `${text.slice(0, max - 1).trimEnd()}…`;
142
+ }
143
+
144
+ function notice(
145
+ facts: ScheduledTaskBlockerFacts,
146
+ run: ScheduledTaskBlockerRun,
147
+ state: "notified" | "paused",
148
+ blocker: Blocker,
149
+ ): Extract<ScheduledTaskBlockerDecision, { kind: "block" }>["notice"] {
150
+ // The chat the owner opens from the notice: the blocked run's own, else the
151
+ // chat the schedule runs in, else the most recent run's.
152
+ const sessionId =
153
+ run.sessionId ??
154
+ facts.task.reusableSessionId ??
155
+ facts.runs.find((candidate) => candidate.sessionId !== null)?.sessionId ??
156
+ null;
157
+ if (!sessionId) return null;
158
+ const key = scheduledTaskBlockerNoticeKey(facts.task.id);
159
+ const payload = SessionNotificationPostedPayload.parse({
160
+ key,
161
+ title: state === "paused" ? "Schedule paused itself" : "Schedule needs attention",
162
+ subtitle: clip(facts.task.name.trim() || "Scheduled task", NOTIFICATION_SUBTITLE_MAX_CHARS),
163
+ body:
164
+ state === "paused"
165
+ ? `${blocker.text} It stays paused until someone resumes it.`
166
+ : blocker.text,
167
+ urgency: "normal",
168
+ replaced: false,
169
+ });
170
+ return { sessionId, key, payload };
171
+ }
172
+
173
+ /** The pure review of one schedule's newest settled scheduled run. */
174
+ export function decideScheduledTaskBlocker(
175
+ facts: ScheduledTaskBlockerFacts,
176
+ ): ScheduledTaskBlockerDecision {
177
+ const { task, review, runs } = facts;
178
+ const blocked = review !== null && review.state !== "clear";
179
+ // A person acted: resumed a self-paused schedule, or paused or deleted one
180
+ // they were told about. Keep the reviewed run; a new one is reviewed next.
181
+ if (task.deleted) return blocked ? { kind: "clear", reviewedRunId: null } : none(null);
182
+ if (review?.state === "paused" && task.status === "active") {
183
+ return { kind: "clear", reviewedRunId: null };
184
+ }
185
+ if (review?.state === "notified" && task.status !== "active") {
186
+ return { kind: "clear", reviewedRunId: null };
187
+ }
188
+ if (task.status !== "active") return none(null);
189
+ const latest = runs[0];
190
+ if (!latest || !SETTLED.has(latest.status) || latest.id === review?.reviewedRunId) {
191
+ return none(null);
192
+ }
193
+ if (latest.status === "succeeded") {
194
+ return review?.state === "notified"
195
+ ? { kind: "clear", reviewedRunId: latest.id }
196
+ : none(latest.id);
197
+ }
198
+ // Runs before the last edit or resume say nothing about the schedule now.
199
+ const current = (run: ScheduledTaskBlockerRun) => run.createdAt >= task.updatedAt;
200
+ const hard = current(latest) ? scheduledRunHardBlocker(task, latest) : null;
201
+ if (hard) {
202
+ return {
203
+ kind: "block",
204
+ state: "paused",
205
+ reason: hard.reason,
206
+ message: hard.text,
207
+ blockedRunId: latest.id,
208
+ blockedSince: latest.createdAt,
209
+ reviewedRunId: latest.id,
210
+ notice: notice(facts, latest, "paused", hard),
211
+ };
212
+ }
213
+ if (review?.state === "notified") return none(latest.id);
214
+ const streak: ScheduledTaskBlockerRun[] = [];
215
+ for (const run of runs) {
216
+ if (!SETTLED.has(run.status) || run.status === "succeeded" || !current(run)) break;
217
+ streak.push(run);
218
+ }
219
+ if (streak.length < SCHEDULED_TASK_BLOCKER_STREAK) return none(latest.id);
220
+ const soft = streakBlocker(streak);
221
+ const first = streak.at(-1)!;
222
+ return {
223
+ kind: "block",
224
+ state: "notified",
225
+ reason: soft.reason,
226
+ message: soft.text,
227
+ blockedRunId: first.id,
228
+ blockedSince: first.createdAt,
229
+ reviewedRunId: latest.id,
230
+ notice: notice(facts, latest, "notified", soft),
231
+ };
232
+ }
233
+
234
+ function none(reviewedRunId: string | null): ScheduledTaskBlockerDecision {
235
+ return { kind: "none", reviewedRunId };
236
+ }
237
+
238
+ type Dependencies = {
239
+ db: Database;
240
+ bus: EventBus;
241
+ observability?: Pick<Observability, "error"> | undefined;
242
+ };
243
+
244
+ function sessionMissing(error: unknown): boolean {
245
+ return error instanceof Error && /^Session not found: /u.test(error.message);
246
+ }
247
+
248
+ /** Post or withdraw the owner notice a review left pending. */
249
+ export async function deliverScheduledTaskBlockerNotice(
250
+ deps: Dependencies,
251
+ workspaceId: string,
252
+ taskId: string,
253
+ ): Promise<void> {
254
+ const pending = await getPendingScheduledTaskBlockerNotice(deps.db, workspaceId, taskId);
255
+ if (!pending) return;
256
+ try {
257
+ await appendAndPublishEvents(deps.db, deps.bus, workspaceId, pending.sessionId, [
258
+ pending.pending === "post"
259
+ ? {
260
+ type: "session.notification.posted",
261
+ payload: SessionNotificationPostedPayload.parse(pending.payload),
262
+ }
263
+ : {
264
+ type: "session.notification.withdrawn",
265
+ payload: SessionNotificationWithdrawnPayload.parse({ key: pending.key }),
266
+ },
267
+ ] as Parameters<typeof appendAndPublishEvents>[4]);
268
+ } catch (error) {
269
+ // A deleted chat cannot carry the notice; the schedule page still shows why.
270
+ if (!sessionMissing(error)) throw error;
271
+ }
272
+ await settleScheduledTaskBlockerNotice(deps.db, workspaceId, taskId, pending);
273
+ }
274
+
275
+ /** One bounded pass over schedules with a run to review or a notice to deliver. */
276
+ export async function reviewScheduledTaskBlockerInventory(deps: Dependencies): Promise<void> {
277
+ for (const candidate of await listScheduledTaskBlockerReviews(deps.db)) {
278
+ try {
279
+ await reviewScheduledTaskBlockers(
280
+ deps.db,
281
+ candidate.workspace_id,
282
+ candidate.id,
283
+ decideScheduledTaskBlocker,
284
+ );
285
+ await deliverScheduledTaskBlockerNotice(deps, candidate.workspace_id, candidate.id);
286
+ } catch (error) {
287
+ deps.observability?.error("Scheduled task blocker review will retry", {
288
+ taskId: candidate.id,
289
+ error: error instanceof Error ? error.message : String(error),
290
+ });
291
+ }
292
+ }
293
+ }
@@ -1,6 +1,10 @@
1
1
  import { scheduledTaskKnowledgeSource } from "@opengeni/contracts";
2
- import type { ScheduledTask as ScheduledTaskValue } from "@opengeni/contracts";
3
- import { deleteScheduledTaskLifecycle, type ApiRouteDeps } from "@opengeni/core";
2
+ import type { AccessGrant, ScheduledTask as ScheduledTaskValue } from "@opengeni/contracts";
3
+ import {
4
+ assertScheduledTaskMutationOwner,
5
+ deleteScheduledTaskLifecycle,
6
+ type ApiRouteDeps,
7
+ } from "@opengeni/core";
4
8
  import type { TemporalScheduleCleanupClaim } from "@opengeni/db";
5
9
  import { HTTPException } from "hono/http-exception";
6
10
  import * as z4 from "zod/v4";
@@ -100,13 +104,19 @@ export async function cleanupScheduledTaskConnectorAuthorization(
100
104
  /** Shared HTTP/MCP domain operation: authorize, tombstone, persist, then accelerate cleanup. */
101
105
  export async function deleteScheduledTaskWithDurableCleanup(
102
106
  deps: ApiRouteDeps,
103
- input: { workspaceId: string; taskId: string; subjectId: string },
107
+ request: { grant: AccessGrant; taskId: string },
104
108
  ): Promise<{ task: ScheduledTaskValue; changed: boolean }> {
109
+ const input = {
110
+ workspaceId: request.grant.workspaceId,
111
+ subjectId: request.grant.subjectId,
112
+ taskId: request.taskId,
113
+ };
105
114
  const result = await deleteScheduledTaskLifecycle({
106
115
  db: deps.db,
107
116
  workspaceId: input.workspaceId,
108
117
  taskId: input.taskId,
109
118
  subjectId: input.subjectId,
119
+ beforeDeleteCommit: (tx) => assertScheduledTaskMutationOwner(tx, request.grant, request.taskId),
110
120
  preflightConnectorAuthorization: async (task) =>
111
121
  await preflightConnectorAuthorization(deps, task, input.subjectId),
112
122
  cleanupConnectorAuthorization: async (db, task) =>