@opengeni/api-router 3.0.1 → 3.0.2-canary.38894290271001
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.
- package/dist/access-grant-rls.d.ts +8 -1
- package/dist/admission-trace.d.ts +8 -0
- package/dist/app.d.ts +50 -3
- package/dist/app.js +10 -1
- package/dist/artifact-catalog-cursor.d.ts +1 -0
- package/dist/attached-browser-viewer.d.ts +11 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +2 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +9 -1
- package/dist/auth/managed-auth.d.ts +72 -5
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/azure-live.d.ts +28 -0
- package/dist/browser-action-fences.d.ts +13 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-lost-runtime-end.d.ts +24 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/{chunk-AJ62T5QN.js → chunk-GBUJ2DYZ.js} +80507 -39878
- package/dist/chunk-GBUJ2DYZ.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-default-models.d.ts +19 -0
- package/dist/claude-subscription-core.d.ts +50 -0
- package/dist/claude-subscription-oauth.d.ts +36 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +6 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +40 -5
- package/dist/codex-realtime.d.ts +29 -3
- package/dist/codex-session-pointers.d.ts +19 -0
- package/dist/connection-ownership.d.ts +6 -3
- package/dist/controller-data-plane.d.ts +16 -0
- package/dist/credit-promotion-snapshot.d.ts +6 -0
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +5 -3
- package/dist/fatal-process-boundary.d.ts +9 -1
- package/dist/github-access.d.ts +7 -1
- package/dist/github-browser-flow.d.ts +1 -1
- package/dist/http/acting-person.d.ts +36 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +50 -1
- package/dist/http/auth.d.ts +8 -1
- package/dist/http/cors.d.ts +12 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/keyed-admission.d.ts +12 -0
- package/dist/http/local-browser-boundary.d.ts +72 -0
- package/dist/http/metrics-listener.d.ts +22 -0
- package/dist/http/path-identifier.d.ts +17 -0
- package/dist/http/registered-route-label.d.ts +16 -0
- package/dist/http/rejection-telemetry.d.ts +34 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +41 -3
- package/dist/http/sse.d.ts +12 -1
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/variable-sets-removed.d.ts +41 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.js +1279 -108
- package/dist/index.js.map +1 -1
- package/dist/integration-connect-metrics.d.ts +35 -0
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +8 -3
- package/dist/integrations/fiken.d.ts +3 -1
- package/dist/integrations/github-lens-connect.d.ts +37 -66
- package/dist/integrations/google-drive.d.ts +2 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +43 -43
- package/dist/integrations/oauth-client.d.ts +171 -12
- package/dist/integrations/oauth-profiles.d.ts +42 -13
- package/dist/integrations/onepassword-vault-provider.d.ts +9 -0
- package/dist/integrations/slack-bot.d.ts +285 -7
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-interactions.d.ts +89 -10
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +1 -1
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/slack-tool-review.d.ts +5 -0
- package/dist/interaction-agent-access.d.ts +13 -8
- package/dist/interaction-agent-version.d.ts +21 -0
- package/dist/interaction-holder-heartbeat.d.ts +5 -0
- package/dist/interaction-metrics.d.ts +27 -2
- package/dist/interaction-route-stages.d.ts +25 -0
- package/dist/interaction-secrets-vault.d.ts +20 -0
- package/dist/interaction-secrets.d.ts +103 -0
- package/dist/mcp/action-catalog-types.d.ts +14 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/action-descriptions.d.ts +4 -0
- package/dist/mcp/action-schema-imports.gen.d.ts +1 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +12 -0
- package/dist/mcp/contract-input.d.ts +13 -0
- package/dist/mcp/documents.d.ts +2 -0
- package/dist/mcp/first-party-tool-permissions.d.ts +3 -606
- package/dist/mcp/notification-tools.d.ts +26 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/scheduled-task-input.d.ts +1309 -0
- package/dist/mcp/scheduled-task-view.d.ts +217 -3
- package/dist/mcp/secret-tools.d.ts +14 -0
- package/dist/mcp/server.d.ts +108 -5
- package/dist/mcp/session-admin-access-tools.d.ts +33 -0
- package/dist/mcp/session-event-errors.d.ts +28 -0
- package/dist/mcp/session-event-view.d.ts +62 -0
- package/dist/mcp/session-view.d.ts +15 -0
- package/dist/mcp/session-wait.d.ts +18 -0
- package/dist/mcp/site-agent-clamp-tools.d.ts +38 -0
- package/dist/mcp/site-data-tools.d.ts +22 -0
- package/dist/mcp/site-publication-tools.d.ts +19 -0
- package/dist/mcp/site-sql-tools.d.ts +27 -0
- package/dist/mcp-oauth.d.ts +37 -4
- package/dist/model-calls/chat-completions.d.ts +87 -0
- package/dist/model-calls/pending-usage-settlements.d.ts +57 -0
- package/dist/model-calls/service.d.ts +36 -0
- package/dist/model-catalog.d.ts +9 -3
- package/dist/native-push-dispatch.d.ts +69 -0
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +82 -0
- package/dist/prepared-mcp-actor.d.ts +77 -0
- package/dist/prepared-mcp-permissions.d.ts +8 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +11 -0
- package/dist/routes/api-keys.d.ts +7 -7
- package/dist/routes/automations.d.ts +2 -0
- package/dist/routes/billing.d.ts +59 -0
- package/dist/routes/browser-sessions.d.ts +65 -2
- package/dist/routes/chat-completions.d.ts +11 -0
- package/dist/routes/claude-core-usage.d.ts +20 -0
- package/dist/routes/claude-subscription-accounts.d.ts +3 -0
- package/dist/routes/claude-subscription-oauth.d.ts +3 -0
- package/dist/routes/client-errors.d.ts +182 -0
- package/dist/routes/codex-core.d.ts +401 -0
- package/dist/routes/codex.d.ts +64 -2
- package/dist/routes/computer-sessions.d.ts +6 -1
- package/dist/routes/desktop-distribution.d.ts +32 -0
- package/dist/routes/github-browser-fonts.gen.d.ts +2 -0
- package/dist/routes/github-browser-pages.d.ts +27 -0
- package/dist/routes/inbox.d.ts +13 -0
- package/dist/routes/insights-response-cache.d.ts +10 -0
- package/dist/routes/insights-usage.d.ts +12 -0
- package/dist/routes/insights.d.ts +28 -0
- package/dist/routes/interaction-placement-message.d.ts +7 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-account-choice.d.ts +13 -0
- package/dist/routes/model-account-settings.d.ts +19 -0
- package/dist/routes/native-app-auth.d.ts +12 -0
- package/dist/routes/organization-integration-policy.d.ts +8 -0
- package/dist/routes/organization-integrations.d.ts +6 -0
- package/dist/routes/organization-mcp-connections.d.ts +3 -0
- package/dist/routes/organization-model-defaults.d.ts +9 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/personal-api-keys.d.ts +3 -0
- package/dist/routes/session-admin-access.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +20 -0
- package/dist/routes/sessions.d.ts +38 -2
- package/dist/routes/site-data.d.ts +18 -0
- package/dist/routes/site-publishing.d.ts +5 -0
- package/dist/routes/site-runtime.d.ts +31 -0
- package/dist/routes/site-sql.d.ts +16 -0
- package/dist/routes/slack-bot-access.d.ts +3 -0
- package/dist/routes/subscription-account-pools.d.ts +21 -0
- package/dist/routes/subscription-core-http.d.ts +5 -0
- package/dist/routes/subscription-pool-access.d.ts +37 -0
- package/dist/routes/subscription-pool-core.d.ts +153 -0
- package/dist/routes/supergrok.d.ts +6 -6
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/variable-sets-removed.d.ts +2 -0
- package/dist/routes/vault-providers.d.ts +34 -0
- package/dist/routes/vaults.d.ts +3 -0
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +11 -2
- package/dist/sandbox/agent-update.d.ts +64 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +15 -1
- package/dist/sandbox/enrollment.d.ts +26 -4
- package/dist/sandbox/machine-audience.d.ts +29 -0
- package/dist/sandbox/machines.d.ts +15 -2
- package/dist/sandbox/metrics-ingestion.d.ts +6 -2
- package/dist/sandbox/screen-control.d.ts +85 -0
- package/dist/sandbox/viewer.d.ts +5 -1
- package/dist/sandbox-file-artifacts.d.ts +17 -1
- package/dist/scheduled-task-blockers.d.ts +39 -0
- package/dist/scheduled-task-deletion.d.ts +3 -4
- package/dist/scheduled-task-lifecycle.d.ts +14 -0
- package/dist/secret-answers.d.ts +40 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-36GO3IL7.js +528 -0
- package/dist/session-event-view-36GO3IL7.js.map +1 -0
- package/dist/signed-state-secret.d.ts +18 -0
- package/dist/site-agent-guard.d.ts +53 -0
- package/dist/site-data/operations.d.ts +103 -0
- package/dist/site-data/service.d.ts +203 -0
- package/dist/site-frame-guard.d.ts +32 -0
- package/dist/site-publishing/agent-data-tools.d.ts +84 -0
- package/dist/site-publishing/agent-model.d.ts +58 -0
- package/dist/site-publishing/agent-session.d.ts +16 -0
- package/dist/site-publishing/content-scanner.d.ts +31 -0
- package/dist/site-publishing/edge-sync.d.ts +48 -0
- package/dist/site-publishing/gateway-signature.d.ts +56 -0
- package/dist/site-publishing/limits.d.ts +63 -0
- package/dist/site-publishing/page-tool-authority.d.ts +30 -0
- package/dist/site-publishing/platform-usage.d.ts +113 -0
- package/dist/site-publishing/platform.d.ts +21 -0
- package/dist/site-publishing/readiness.d.ts +62 -0
- package/dist/site-publishing/runtime.d.ts +179 -0
- package/dist/site-publishing/service.d.ts +264 -0
- package/dist/site-publishing/session-events.d.ts +22 -0
- package/dist/site-publishing/session-views.d.ts +36 -0
- package/dist/site-publishing/viewer.d.ts +40 -0
- package/dist/site-session-origin.d.ts +31 -6
- package/dist/site-sql/format.d.ts +47 -0
- package/dist/site-sql/gateway.d.ts +50 -0
- package/dist/site-sql/service.d.ts +213 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/billing-refusal.d.ts +8 -0
- package/dist/transcription/normalize.d.ts +23 -0
- package/dist/transcription/providers/azure-mai.d.ts +12 -0
- package/dist/transcription/providers/azure-openai.d.ts +4 -0
- package/dist/transcription/providers/openai.d.ts +16 -0
- package/dist/transcription/providers/subscription-core.d.ts +39 -0
- package/dist/transcription/service.d.ts +10 -1
- package/dist/transcription/wav-duration.d.ts +8 -0
- package/dist/workspace-tool-gateway-attestations.d.ts +37 -0
- package/dist/workspace-tool-gateway-observability.d.ts +16 -0
- package/dist/workspace-tool-gateway-secrets.d.ts +27 -0
- package/dist/workspace-tool-gateway.d.ts +102 -6
- package/dist/workspace-tool-target-fence.d.ts +116 -0
- package/dist/workspace-tool-target.d.ts +225 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/dist/xai-subscription-core.d.ts +60 -0
- package/package.json +25 -20
- package/src/access-grant-rls.ts +64 -14
- package/src/admission-trace.ts +14 -0
- package/src/app.ts +1684 -252
- package/src/artifact-catalog-cursor.ts +1 -0
- package/src/attached-browser-viewer.ts +26 -0
- package/src/auth/managed-auth-attempt-context.ts +9 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +64 -29
- package/src/auth/managed-auth.ts +303 -35
- package/src/auth/managed-email.ts +18 -1
- package/src/auth/managed-sign-in-notifications.ts +81 -0
- package/src/auth/new-signups-gate.ts +49 -0
- package/src/auth/organization-user-setup.ts +3 -3
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/azure-live.ts +103 -0
- package/src/browser-action-fences.ts +45 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-lost-runtime-end.ts +71 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-default-models.ts +37 -0
- package/src/claude-subscription-core.ts +154 -0
- package/src/claude-subscription-oauth.ts +352 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +51 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +236 -39
- package/src/codex-realtime.ts +181 -53
- package/src/codex-session-pointers.ts +80 -0
- package/src/company-brain-okf.ts +1 -1
- package/src/connected-machine-computer-access.ts +2 -1
- package/src/connection-ownership.ts +19 -13
- package/src/controller-data-plane.ts +34 -0
- package/src/credit-promotion-snapshot.ts +36 -0
- package/src/editable-artifact-production.ts +10 -0
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +16 -3
- package/src/fatal-process-boundary.ts +67 -3
- package/src/gateway-realtime.ts +12 -8
- package/src/github-access.ts +31 -5
- package/src/github-browser-flow.ts +1 -1
- package/src/http/acting-person.ts +105 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +210 -2
- package/src/http/auth.ts +68 -4
- package/src/http/cors.ts +37 -5
- package/src/http/deprecation.ts +118 -0
- package/src/http/keyed-admission.ts +29 -0
- package/src/http/local-browser-boundary.ts +343 -0
- package/src/http/metrics-listener.ts +57 -0
- package/src/http/path-identifier.ts +54 -0
- package/src/http/registered-route-label.ts +34 -0
- package/src/http/rejection-telemetry.ts +120 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +154 -13
- package/src/http/sse.ts +88 -28
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/variable-sets-removed.ts +122 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +107 -57
- package/src/integration-connect-metrics.ts +228 -0
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +81 -7
- package/src/integrations/atlassian.ts +202 -83
- package/src/integrations/fiken.ts +66 -38
- package/src/integrations/github-app-connect.ts +64 -18
- package/src/integrations/github-lens-connect.ts +8 -29
- package/src/integrations/google-drive.ts +448 -152
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +1 -1
- package/src/integrations/oauth-client.ts +733 -193
- package/src/integrations/oauth-profiles.ts +116 -45
- package/src/integrations/onepassword-vault-provider.ts +16 -0
- package/src/integrations/personal-github-repositories.ts +1 -1
- package/src/integrations/personal-github.ts +61 -35
- package/src/integrations/provider-oauth.ts +67 -85
- package/src/integrations/slack-app-home.ts +5 -5
- package/src/integrations/slack-bot.ts +893 -201
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +7 -7
- package/src/integrations/slack-interactions.ts +1589 -299
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +2 -2
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/slack-tool-review.ts +65 -0
- package/src/integrations/social-oauth.ts +90 -58
- package/src/interaction-agent-access.ts +40 -20
- package/src/interaction-agent-version.ts +85 -0
- package/src/interaction-holder-heartbeat.ts +24 -8
- package/src/interaction-metrics.ts +164 -2
- package/src/interaction-route-stages.ts +94 -0
- package/src/interaction-secrets-vault.ts +213 -0
- package/src/interaction-secrets.ts +426 -0
- package/src/mcp/action-catalog-types.ts +14 -0
- package/src/mcp/action-catalog.gen.ts +8014 -0
- package/src/mcp/action-descriptions.ts +299 -0
- package/src/mcp/action-schema-imports.gen.ts +304 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/company-profile-agent-admin.ts +13 -0
- package/src/mcp/contract-input.ts +165 -0
- package/src/mcp/documents.ts +9 -2
- package/src/mcp/editable-artifacts.ts +29 -11
- package/src/mcp/files.ts +5 -1
- package/src/mcp/first-party-tool-permissions.ts +7 -285
- package/src/mcp/knowledge-entries.ts +108 -34
- package/src/mcp/notification-tools.ts +480 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/scheduled-task-input.ts +89 -0
- package/src/mcp/scheduled-task-view.ts +63 -3
- package/src/mcp/secret-tools.ts +185 -0
- package/src/mcp/server.ts +2213 -1116
- package/src/mcp/session-admin-access-tools.ts +163 -0
- package/src/mcp/session-event-errors.ts +123 -0
- package/src/mcp/session-event-view.ts +395 -13
- package/src/mcp/session-view.ts +3 -0
- package/src/mcp/session-wait.ts +67 -7
- package/src/mcp/site-agent-clamp-tools.ts +140 -0
- package/src/mcp/site-data-tools.ts +339 -0
- package/src/mcp/site-publication-tools.ts +201 -0
- package/src/mcp/site-sql-tools.ts +427 -0
- package/src/mcp-oauth.ts +635 -45
- package/src/model-calls/chat-completions.ts +352 -0
- package/src/model-calls/pending-usage-settlements.ts +125 -0
- package/src/model-calls/service.ts +694 -0
- package/src/model-catalog.ts +68 -17
- package/src/native-push-dispatch.ts +457 -0
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +485 -0
- package/src/prepared-mcp-actor.ts +154 -0
- package/src/prepared-mcp-permissions.ts +38 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +268 -9
- package/src/routes/api-keys.ts +164 -25
- package/src/routes/artifact-catalog.ts +111 -0
- package/src/routes/automations.ts +163 -90
- package/src/routes/billing.ts +535 -59
- package/src/routes/browser-sessions.ts +966 -342
- package/src/routes/canonical-human-identities.ts +61 -0
- package/src/routes/capabilities.ts +112 -5
- package/src/routes/channels.ts +4 -3
- package/src/routes/chat-completions.ts +235 -0
- package/src/routes/claude-core-usage.ts +147 -0
- package/src/routes/claude-subscription-accounts.ts +233 -0
- package/src/routes/claude-subscription-oauth.ts +175 -0
- package/src/routes/client-errors.ts +394 -0
- package/src/routes/codex-core.ts +687 -0
- package/src/routes/codex.ts +1277 -1119
- package/src/routes/company-brain.ts +4 -0
- package/src/routes/computer-sessions.ts +319 -85
- package/src/routes/connect.ts +277 -175
- package/src/routes/connections.ts +690 -363
- package/src/routes/desktop-distribution.ts +217 -0
- package/src/routes/documents.ts +13 -7
- package/src/routes/editable-artifacts.ts +74 -4
- package/src/routes/enrollments.ts +110 -16
- package/src/routes/external-identity-links.ts +13 -12
- package/src/routes/files.ts +41 -16
- package/src/routes/github-browser-fonts.gen.ts +12 -0
- package/src/routes/github-browser-pages.ts +258 -0
- package/src/routes/github.ts +200 -75
- package/src/routes/inbox.ts +353 -0
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +103 -8
- package/src/routes/install.ts +51 -10
- package/src/routes/integration-facets.ts +70 -28
- package/src/routes/interaction-placement-message.ts +12 -0
- package/src/routes/knowledge.ts +136 -27
- package/src/routes/machines.ts +189 -135
- package/src/routes/managed-auth-session-sets.ts +43 -10
- package/src/routes/managed-onboarding.ts +39 -19
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-account-choice.ts +194 -0
- package/src/routes/model-account-settings.ts +235 -0
- package/src/routes/model-connection-access.ts +210 -48
- package/src/routes/native-app-auth.ts +296 -0
- package/src/routes/organization-integration-policy.ts +116 -0
- package/src/routes/organization-integrations.ts +326 -0
- package/src/routes/organization-mcp-connections.ts +183 -0
- package/src/routes/organization-memberships.ts +205 -19
- package/src/routes/organization-model-defaults.ts +110 -0
- package/src/routes/organization-model-providers.ts +74 -3
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +21 -5
- package/src/routes/personal-api-keys.ts +184 -0
- package/src/routes/personal-github-git-broker.ts +2 -2
- package/src/routes/personal-github.ts +9 -4
- package/src/routes/plugins.ts +46 -7
- package/src/routes/pr-review-github.ts +105 -118
- package/src/routes/pr-review.ts +88 -82
- package/src/routes/preference-registry.ts +18 -0
- package/src/routes/rigs.ts +48 -13
- package/src/routes/scheduled-tasks.ts +347 -27
- package/src/routes/session-admin-access.ts +271 -0
- package/src/routes/session-artifact-associations.ts +164 -0
- package/src/routes/session-history-imports.ts +305 -0
- package/src/routes/sessions.ts +1682 -363
- package/src/routes/site-data.ts +340 -0
- package/src/routes/site-publishing.ts +584 -0
- package/src/routes/site-runtime.ts +1944 -0
- package/src/routes/site-sql.ts +263 -0
- package/src/routes/skill-content.ts +72 -7
- package/src/routes/skills.ts +5 -4
- package/src/routes/slack-bot-access.ts +108 -0
- package/src/routes/social.ts +27 -15
- package/src/routes/subscription-account-pools.ts +209 -0
- package/src/routes/subscription-core-http.ts +18 -0
- package/src/routes/subscription-pool-access.ts +180 -0
- package/src/routes/subscription-pool-core.ts +552 -0
- package/src/routes/supergrok.ts +174 -655
- package/src/routes/transcription-recordings.ts +71 -4
- package/src/routes/transcriptions.ts +26 -2
- package/src/routes/usage-allowances.ts +381 -0
- package/src/routes/variable-sets-removed.ts +19 -0
- package/src/routes/vault-providers.ts +782 -0
- package/src/routes/vaults.ts +421 -0
- package/src/routes/video-generation.ts +30 -12
- package/src/routes/workspace-artifacts.ts +165 -53
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +4 -0
- package/src/routes/workspaces.ts +625 -117
- package/src/sandbox/agent-update.ts +315 -0
- package/src/sandbox/auth-callout.ts +104 -21
- package/src/sandbox/channel-a.ts +150 -49
- package/src/sandbox/enrollment.ts +131 -22
- package/src/sandbox/machine-audience.ts +192 -0
- package/src/sandbox/machines.ts +75 -31
- package/src/sandbox/metrics-ingestion.ts +133 -2
- package/src/sandbox/rematerialize.ts +51 -21
- package/src/sandbox/screen-control.ts +289 -0
- package/src/sandbox/viewer.ts +33 -58
- package/src/sandbox-file-artifacts.ts +53 -27
- package/src/scheduled-task-blockers.ts +293 -0
- package/src/scheduled-task-deletion.ts +13 -3
- package/src/scheduled-task-lifecycle.ts +84 -0
- package/src/secret-answers.ts +119 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +26 -4
- package/src/signed-state-secret.ts +58 -0
- package/src/site-agent-guard.ts +261 -0
- package/src/site-data/operations.ts +777 -0
- package/src/site-data/service.ts +1043 -0
- package/src/site-frame-guard.ts +107 -0
- package/src/site-publishing/agent-data-tools.ts +250 -0
- package/src/site-publishing/agent-model.ts +127 -0
- package/src/site-publishing/agent-session.ts +148 -0
- package/src/site-publishing/content-scanner.ts +93 -0
- package/src/site-publishing/edge-sync.ts +148 -0
- package/src/site-publishing/gateway-signature.ts +198 -0
- package/src/site-publishing/limits.ts +315 -0
- package/src/site-publishing/page-tool-authority.ts +111 -0
- package/src/site-publishing/platform-usage.ts +479 -0
- package/src/site-publishing/platform.ts +98 -0
- package/src/site-publishing/readiness.ts +330 -0
- package/src/site-publishing/runtime.ts +831 -0
- package/src/site-publishing/service.ts +1282 -0
- package/src/site-publishing/session-events.ts +262 -0
- package/src/site-publishing/session-views.ts +262 -0
- package/src/site-publishing/viewer.ts +75 -0
- package/src/site-session-origin.ts +91 -6
- package/src/site-sql/format.ts +134 -0
- package/src/site-sql/gateway.ts +168 -0
- package/src/site-sql/service.ts +1636 -0
- package/src/site-uploads.ts +27 -5
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/billing-refusal.ts +14 -0
- package/src/transcription/normalize.ts +77 -0
- package/src/transcription/providers/azure-mai.ts +98 -0
- package/src/transcription/providers/azure-openai.ts +16 -7
- package/src/transcription/providers/codex-subscription.ts +190 -67
- package/src/transcription/providers/openai.ts +79 -5
- package/src/transcription/providers/subscription-core.ts +125 -0
- package/src/transcription/providers/xai-subscription.ts +81 -83
- package/src/transcription/segmenter.ts +7 -1
- package/src/transcription/service.ts +239 -10
- package/src/transcription/wav-duration.ts +39 -0
- package/src/workspace-deletion.ts +25 -1
- package/src/workspace-tool-gateway-attestations.ts +133 -0
- package/src/workspace-tool-gateway-observability.ts +64 -0
- package/src/workspace-tool-gateway-secrets.ts +104 -0
- package/src/workspace-tool-gateway.ts +921 -103
- package/src/workspace-tool-target-fence.ts +380 -0
- package/src/workspace-tool-target.ts +554 -0
- package/src/workspace-webhook-dispatch.ts +225 -0
- package/src/xai-realtime.ts +85 -81
- package/src/xai-subscription-core.ts +172 -0
- package/dist/browser-auth-broker.d.ts +0 -20
- package/dist/chunk-AJ62T5QN.js.map +0 -1
- package/dist/connection-authority-owner.d.ts +0 -59
- package/dist/routes/connection-authorities.d.ts +0 -3
- package/dist/routes/environments.d.ts +0 -5
- package/dist/routes/host-mcp-bindings.d.ts +0 -5
- package/dist/routes/host-mcp-resolvers.d.ts +0 -3
- package/dist/routes/packs.d.ts +0 -3
- package/dist/session-event-view-MU3HMNV3.js +0 -264
- package/dist/session-event-view-MU3HMNV3.js.map +0 -1
- package/dist/xai-subscription-auth.d.ts +0 -23
- package/src/browser-auth-broker.ts +0 -155
- package/src/connection-authority-owner.ts +0 -61
- package/src/routes/connection-authorities.ts +0 -139
- package/src/routes/environments.ts +0 -388
- package/src/routes/host-mcp-bindings.ts +0 -122
- package/src/routes/host-mcp-resolvers.ts +0 -41
- package/src/routes/packs.ts +0 -784
- package/src/xai-subscription-auth.ts +0 -139
|
@@ -0,0 +1,694 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildModelResolver,
|
|
3
|
+
CODEX_CLIENT_VERSION,
|
|
4
|
+
CodexReloginRequired,
|
|
5
|
+
codexRequestStorage,
|
|
6
|
+
type CodexFetch,
|
|
7
|
+
type CodexRequestContext,
|
|
8
|
+
type CodexUsagePayload,
|
|
9
|
+
} from "@opengeni/codex";
|
|
10
|
+
import { codexUpstreamModelSlugs, type ConfiguredModel, type Settings } from "@opengeni/config";
|
|
11
|
+
import type { EntitlementsPort } from "@opengeni/contracts";
|
|
12
|
+
import {
|
|
13
|
+
admissibleWorkspaceModel,
|
|
14
|
+
admitModelCall,
|
|
15
|
+
clampReasoningEffortForConfiguredModel,
|
|
16
|
+
isWorkspaceModelAdmissible,
|
|
17
|
+
ModelCallError,
|
|
18
|
+
resolveCallerWorkspaceModelSelections,
|
|
19
|
+
resolveDefaultSessionModelForSelections,
|
|
20
|
+
resolveWorkspaceCatalogSettings,
|
|
21
|
+
recordSessionUsageLimitEvent,
|
|
22
|
+
requireSessionUsageLimitAllows,
|
|
23
|
+
type SessionUsageLimitMetricsSink,
|
|
24
|
+
sessionUsageLimitRefusalFromError,
|
|
25
|
+
settingsWithModelProviderCredentials,
|
|
26
|
+
settleModelUsage,
|
|
27
|
+
type HeldSessionUsageReceipt,
|
|
28
|
+
type ModelCallCaller,
|
|
29
|
+
type ModelCallInput,
|
|
30
|
+
type ModelCallOutput,
|
|
31
|
+
type ModelCallService,
|
|
32
|
+
type WorkspaceModelSelection,
|
|
33
|
+
} from "@opengeni/core";
|
|
34
|
+
import {
|
|
35
|
+
acquireSubscriptionCoreCodexOperationLease,
|
|
36
|
+
buildSubscriptionCoreCodexConnectionTokenResolver,
|
|
37
|
+
ClaudeSubscriptionReconnectRequired,
|
|
38
|
+
connectionModelAllowed,
|
|
39
|
+
fetchSubscriptionCoreCodexUsage,
|
|
40
|
+
getWorkspace,
|
|
41
|
+
listSubscriptionCoreCodexOperationCandidates,
|
|
42
|
+
readCodexCutoverDisposition,
|
|
43
|
+
releaseSubscriptionCoreCodexOperationLease,
|
|
44
|
+
renewSubscriptionCoreCodexOperationLease,
|
|
45
|
+
reserveSubscriptionCoreCodexOperationRequest,
|
|
46
|
+
settleSubscriptionCoreCodexOperationRequest,
|
|
47
|
+
withCreditDebitAttribution,
|
|
48
|
+
fenceSessionUsageReceipt,
|
|
49
|
+
releaseSessionUsageReceipt,
|
|
50
|
+
settleSessionUsageReceipt,
|
|
51
|
+
type Database,
|
|
52
|
+
type SubscriptionCoreCodexOperationLeaseRef,
|
|
53
|
+
type SubscriptionCoreCodexOperationScope,
|
|
54
|
+
} from "@opengeni/db";
|
|
55
|
+
import {
|
|
56
|
+
MultiProviderModelProvider,
|
|
57
|
+
normalizeModelCallUsage,
|
|
58
|
+
runSingleModelCall,
|
|
59
|
+
SingleModelCallProviderError,
|
|
60
|
+
SingleModelCallUnsupportedError,
|
|
61
|
+
type SingleModelCallResult,
|
|
62
|
+
} from "@opengeni/runtime/model-call";
|
|
63
|
+
import { XaiSubscriptionReloginRequired } from "@opengeni/xai-subscription";
|
|
64
|
+
import { PendingUsageSettlements } from "./pending-usage-settlements";
|
|
65
|
+
import {
|
|
66
|
+
creditDebitAttributionForGrant,
|
|
67
|
+
withAccessGrantSessionRlsContext,
|
|
68
|
+
} from "../access-grant-rls";
|
|
69
|
+
|
|
70
|
+
export type ModelCallServiceDeps = {
|
|
71
|
+
db: Database;
|
|
72
|
+
settings: Settings;
|
|
73
|
+
/** Catalog source settings; defaults to `settings`. */
|
|
74
|
+
catalogSourceSettings?: Settings;
|
|
75
|
+
entitlements?: EntitlementsPort | null;
|
|
76
|
+
codexFetch?: CodexFetch;
|
|
77
|
+
log?: (message: string, attributes: Record<string, string | number | boolean>) => void;
|
|
78
|
+
/** Content-free task usage-limit counters (closed-set labels). */
|
|
79
|
+
usageLimitMetrics?: SessionUsageLimitMetricsSink | null;
|
|
80
|
+
/** Retained task usage receipts awaiting DB-only recovery (tests inject one). */
|
|
81
|
+
pendingUsageSettlements?: PendingUsageSettlements;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const PROVIDER_MESSAGE_MAX_LENGTH = 512;
|
|
85
|
+
|
|
86
|
+
export function createModelCallService(deps: ModelCallServiceDeps): ModelCallService {
|
|
87
|
+
const catalogSource = deps.catalogSourceSettings ?? deps.settings;
|
|
88
|
+
const pendingSettlements = deps.pendingUsageSettlements ?? new PendingUsageSettlements();
|
|
89
|
+
|
|
90
|
+
async function selections(caller: ModelCallCaller): Promise<{
|
|
91
|
+
catalogSettings: Settings;
|
|
92
|
+
selections: WorkspaceModelSelection[];
|
|
93
|
+
}> {
|
|
94
|
+
return await withAccessGrantSessionRlsContext(deps, caller.grant, async () => {
|
|
95
|
+
const catalogSettings = (
|
|
96
|
+
await resolveWorkspaceCatalogSettings(deps.db, catalogSource, {
|
|
97
|
+
accountId: caller.accountId,
|
|
98
|
+
workspaceId: caller.workspaceId,
|
|
99
|
+
})
|
|
100
|
+
).settings;
|
|
101
|
+
return {
|
|
102
|
+
catalogSettings,
|
|
103
|
+
selections: await resolveCallerWorkspaceModelSelections(deps.db, catalogSettings, {
|
|
104
|
+
accountId: caller.accountId,
|
|
105
|
+
workspaceId: caller.workspaceId,
|
|
106
|
+
subjectId: caller.subjectId,
|
|
107
|
+
}),
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function resolveModel(
|
|
113
|
+
caller: ModelCallCaller,
|
|
114
|
+
requested: string | null,
|
|
115
|
+
): Promise<{ selection: WorkspaceModelSelection; catalogSettings: Settings }> {
|
|
116
|
+
const resolved = await selections(caller);
|
|
117
|
+
let modelId = requested;
|
|
118
|
+
if (!modelId) {
|
|
119
|
+
const workspace = await getWorkspace(deps.db, caller.workspaceId);
|
|
120
|
+
modelId = (
|
|
121
|
+
await resolveDefaultSessionModelForSelections(deps.db, {
|
|
122
|
+
settings: resolved.catalogSettings,
|
|
123
|
+
accountId: caller.accountId,
|
|
124
|
+
workspaceSettings: workspace?.settings ?? {},
|
|
125
|
+
selections: resolved.selections,
|
|
126
|
+
})
|
|
127
|
+
).model;
|
|
128
|
+
}
|
|
129
|
+
const selection = admissibleWorkspaceModel(resolved.selections, modelId);
|
|
130
|
+
if (!selection || !servedBySingleModelCalls(selection)) {
|
|
131
|
+
throw new ModelCallError({
|
|
132
|
+
status: 404,
|
|
133
|
+
type: "not_found_error",
|
|
134
|
+
code: "model_not_found",
|
|
135
|
+
param: "model",
|
|
136
|
+
message: `The model '${modelId}' does not exist or is not available in this workspace.`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return { selection, catalogSettings: resolved.catalogSettings };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
async listModels(caller) {
|
|
144
|
+
const { selections: all } = await selections(caller);
|
|
145
|
+
return all
|
|
146
|
+
.filter((entry) => isWorkspaceModelAdmissible(entry) && servedBySingleModelCalls(entry))
|
|
147
|
+
.map(({ model }) => ({
|
|
148
|
+
id: model.id,
|
|
149
|
+
label: model.label,
|
|
150
|
+
providerLabel: model.providerLabel,
|
|
151
|
+
}));
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
async call(input) {
|
|
155
|
+
const { selection, catalogSettings } = await resolveModel(input, input.model);
|
|
156
|
+
const model = selection.model;
|
|
157
|
+
assertModelSupportsRequest(model, input.request);
|
|
158
|
+
const source = model.credentialSource;
|
|
159
|
+
const subscription = source.kind === "connected_subscription" ? source.provider : null;
|
|
160
|
+
const chargesOpenGeniCredits = model.billing.metering === "opengeni_credits";
|
|
161
|
+
const countsTowardTokenCap = model.billing.upstreamPayer === "deployment";
|
|
162
|
+
// a call made by a live agent attempt (its grant was verified
|
|
163
|
+
// by the attempt boundary) counts against that task's usage limit and is
|
|
164
|
+
// refused once the limit is reached. Other callers have no task.
|
|
165
|
+
const usageLimitSessionId = attemptSessionId(input.grant);
|
|
166
|
+
const sourceId = `model_call:${input.requestId}`;
|
|
167
|
+
if (usageLimitSessionId) {
|
|
168
|
+
if (pendingSettlements.full) {
|
|
169
|
+
// Never drop a retained receipt to make room for another call.
|
|
170
|
+
recordSessionUsageLimitEvent(deps.usageLimitMetrics, "single_call", "unavailable");
|
|
171
|
+
throw sessionUsageUnavailable();
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
await pendingSettlements.flush(usageLimitSessionId);
|
|
175
|
+
} catch {
|
|
176
|
+
recordSessionUsageLimitEvent(deps.usageLimitMetrics, "single_call", "unavailable");
|
|
177
|
+
throw sessionUsageUnavailable();
|
|
178
|
+
}
|
|
179
|
+
// Admission opens this call's durable custody marker in the same
|
|
180
|
+
// statement, so its usage is owed by the task on every replica until
|
|
181
|
+
// settlement fills it (or maintenance discloses it as unpriced).
|
|
182
|
+
await requireSingleCallSessionUsageLimit(deps, {
|
|
183
|
+
accountId: input.accountId,
|
|
184
|
+
workspaceId: input.workspaceId,
|
|
185
|
+
sessionId: usageLimitSessionId,
|
|
186
|
+
runtime: true,
|
|
187
|
+
openSourceId: sourceId,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const releaseMarker = async (): Promise<void> => {
|
|
191
|
+
if (!usageLimitSessionId) return;
|
|
192
|
+
await releaseSessionUsageReceipt(deps.db, {
|
|
193
|
+
accountId: input.accountId,
|
|
194
|
+
workspaceId: input.workspaceId,
|
|
195
|
+
sessionId: usageLimitSessionId,
|
|
196
|
+
sourceId,
|
|
197
|
+
}).catch(() => {
|
|
198
|
+
// An unreleased marker only blocks after the overdue window and is
|
|
199
|
+
// then disclosed as unpriced by maintenance; never fails the call.
|
|
200
|
+
});
|
|
201
|
+
};
|
|
202
|
+
// Everything between opening the marker and dispatching the request can
|
|
203
|
+
// refuse the call. No request was sent on those exits, so the marker is
|
|
204
|
+
// released; once dispatch starts, custody stays until settlement.
|
|
205
|
+
const prepareDispatch = async () => {
|
|
206
|
+
const admission = await admitModelCall(deps, {
|
|
207
|
+
accountId: input.accountId,
|
|
208
|
+
workspaceId: input.workspaceId,
|
|
209
|
+
model: model.id,
|
|
210
|
+
chargesOpenGeniCredits,
|
|
211
|
+
countsTowardTokenCap,
|
|
212
|
+
subjectId: input.subjectId,
|
|
213
|
+
});
|
|
214
|
+
if (!admission.allowed) {
|
|
215
|
+
throw new ModelCallError({
|
|
216
|
+
status: admission.denial === "insufficient_credits" ? 402 : 429,
|
|
217
|
+
type: "insufficient_quota",
|
|
218
|
+
code: admission.denial,
|
|
219
|
+
message: admission.message,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
const settings = await settingsWithModelProviderCredentials(deps.db, {
|
|
223
|
+
accountId: input.accountId,
|
|
224
|
+
workspaceId: input.workspaceId,
|
|
225
|
+
settings: catalogSettings,
|
|
226
|
+
productModelId: model.id,
|
|
227
|
+
codexSubscriptionActive: subscription === "codex",
|
|
228
|
+
});
|
|
229
|
+
// A single Claude subscription call has no shared-core operation path
|
|
230
|
+
// yet and the legacy Claude pool is deleted (C4): fail closed.
|
|
231
|
+
if (subscription === "claude") throw subscriptionCapacityUnavailable("Claude");
|
|
232
|
+
return { admission, settings };
|
|
233
|
+
};
|
|
234
|
+
let prepared: Awaited<ReturnType<typeof prepareDispatch>>;
|
|
235
|
+
try {
|
|
236
|
+
prepared = await prepareDispatch();
|
|
237
|
+
} catch (error) {
|
|
238
|
+
await releaseMarker();
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
const { admission, settings } = prepared;
|
|
242
|
+
const request = {
|
|
243
|
+
...input.request,
|
|
244
|
+
...reasoningEffortFor(model, input.request.reasoningEffort),
|
|
245
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
246
|
+
};
|
|
247
|
+
const execute = async (): Promise<SingleModelCallResult> => {
|
|
248
|
+
const binding = new MultiProviderModelProvider(settings).resolveBinding(model.id);
|
|
249
|
+
return await runSingleModelCall(
|
|
250
|
+
{ client: binding.client, provider: binding.provider, modelId: binding.modelId },
|
|
251
|
+
request,
|
|
252
|
+
input.onTextDelta ? { onTextDelta: input.onTextDelta } : {},
|
|
253
|
+
);
|
|
254
|
+
};
|
|
255
|
+
let result: SingleModelCallResult;
|
|
256
|
+
try {
|
|
257
|
+
result =
|
|
258
|
+
subscription === "codex"
|
|
259
|
+
? await withCodexOperation(deps, settings, input, model, execute)
|
|
260
|
+
: await execute();
|
|
261
|
+
} catch (error) {
|
|
262
|
+
// No response, so no reported usage to record for this call.
|
|
263
|
+
await releaseMarker();
|
|
264
|
+
const mapped = publicModelCallError(error);
|
|
265
|
+
if (mapped instanceof ModelCallError && mapped.status >= 500) {
|
|
266
|
+
// Names and statuses only: provider messages can echo prompt content.
|
|
267
|
+
deps.log?.("Model call failed", {
|
|
268
|
+
requestId: input.requestId,
|
|
269
|
+
model: model.id,
|
|
270
|
+
code: mapped.code ?? "unknown",
|
|
271
|
+
errorName: error instanceof Error ? error.name : typeof error,
|
|
272
|
+
providerStatus: providerStatus(error) ?? 0,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
throw mapped;
|
|
276
|
+
}
|
|
277
|
+
const usage = result.usage;
|
|
278
|
+
// Settlement failure must not discard a completed answer. Every write
|
|
279
|
+
// below is idempotent on the request's source identity.
|
|
280
|
+
let owedReceipt: HeldSessionUsageReceipt | null = null;
|
|
281
|
+
const logSettlementFailure = (error: unknown) => {
|
|
282
|
+
deps.log?.("Model call usage settlement failed", {
|
|
283
|
+
requestId: input.requestId,
|
|
284
|
+
model: model.id,
|
|
285
|
+
errorName: error instanceof Error ? error.name : typeof error,
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
if (usage) {
|
|
289
|
+
await withCreditDebitAttribution(creditDebitAttributionForGrant(input.grant), () =>
|
|
290
|
+
// Execution settings carry the workspace catalog the price resolves from.
|
|
291
|
+
settleModelUsage(settings, deps.db, {
|
|
292
|
+
accountId: input.accountId,
|
|
293
|
+
workspaceId: input.workspaceId,
|
|
294
|
+
model: model.id,
|
|
295
|
+
chargesOpenGeniCredits,
|
|
296
|
+
countsTowardTokenCap,
|
|
297
|
+
creditPolicyRevision: admission.creditPolicyRevision,
|
|
298
|
+
...(usage.gatewayBilling ? { gatewayBilling: usage.gatewayBilling } : {}),
|
|
299
|
+
normalizedUsage: normalizeModelCallUsage(usage.usage),
|
|
300
|
+
sourceId,
|
|
301
|
+
...(usageLimitSessionId ? { usageLimitSessionId } : {}),
|
|
302
|
+
usageLimitMetrics: deps.usageLimitMetrics ?? null,
|
|
303
|
+
// A failed task-usage receipt never suppresses the credit
|
|
304
|
+
// settlement that follows it; the receipt is owed below.
|
|
305
|
+
receiptCustody: (held, error) => {
|
|
306
|
+
owedReceipt = held;
|
|
307
|
+
logSettlementFailure(error);
|
|
308
|
+
},
|
|
309
|
+
debitMetadata: { modelCallId: input.requestId },
|
|
310
|
+
}),
|
|
311
|
+
).catch(async (error: unknown) => {
|
|
312
|
+
logSettlementFailure(error);
|
|
313
|
+
if (!usageLimitSessionId || owedReceipt) return;
|
|
314
|
+
// Settlement failed before or after the task receipt; the amount
|
|
315
|
+
// is unknown here. An unpriced receipt fills a still-open marker
|
|
316
|
+
// (disclosed, never free); a receipt already recorded for this
|
|
317
|
+
// source is kept and this write is a no-op conflict.
|
|
318
|
+
const unknownAmount: HeldSessionUsageReceipt = {
|
|
319
|
+
sessionId: usageLimitSessionId,
|
|
320
|
+
sourceId,
|
|
321
|
+
turnId: null,
|
|
322
|
+
amountMicros: null,
|
|
323
|
+
pricingSource: null,
|
|
324
|
+
model: model.id,
|
|
325
|
+
};
|
|
326
|
+
await writeOwedReceipt(deps.db, input, unknownAmount).catch(() => {
|
|
327
|
+
owedReceipt = unknownAmount;
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
} else if (usageLimitSessionId) {
|
|
331
|
+
// A response without a usage report is an unknown amount for the
|
|
332
|
+
// task: disclosed as unpriced, never counted as free.
|
|
333
|
+
const unreported: HeldSessionUsageReceipt = {
|
|
334
|
+
sessionId: usageLimitSessionId,
|
|
335
|
+
sourceId,
|
|
336
|
+
turnId: null,
|
|
337
|
+
amountMicros: null,
|
|
338
|
+
pricingSource: null,
|
|
339
|
+
model: model.id,
|
|
340
|
+
};
|
|
341
|
+
await writeOwedReceipt(deps.db, input, unreported).catch((error: unknown) => {
|
|
342
|
+
owedReceipt = unreported;
|
|
343
|
+
logSettlementFailure(error);
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
const owed = owedReceipt as HeldSessionUsageReceipt | null;
|
|
347
|
+
if (owed) {
|
|
348
|
+
// Whatever the failure class, this task's known usage is still owed.
|
|
349
|
+
// Retain the exact receipt for DB-only retry and fence the durable
|
|
350
|
+
// marker so every replica stops admitting this task's model requests
|
|
351
|
+
// until it lands. The provider is never called again.
|
|
352
|
+
const retained = pendingSettlements.retain(owed.sessionId, sourceId, () =>
|
|
353
|
+
writeOwedReceipt(deps.db, input, owed),
|
|
354
|
+
);
|
|
355
|
+
if (!retained) {
|
|
356
|
+
recordSessionUsageLimitEvent(deps.usageLimitMetrics, "single_call", "accounting_failure");
|
|
357
|
+
}
|
|
358
|
+
await fenceSessionUsageReceipt(deps.db, {
|
|
359
|
+
accountId: input.accountId,
|
|
360
|
+
workspaceId: input.workspaceId,
|
|
361
|
+
sessionId: owed.sessionId,
|
|
362
|
+
sourceId,
|
|
363
|
+
}).catch(() => {
|
|
364
|
+
// The unfilled marker still blocks once overdue.
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
return { model: model.id, result } satisfies ModelCallOutput;
|
|
368
|
+
},
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
async function writeOwedReceipt(
|
|
373
|
+
db: Database,
|
|
374
|
+
scope: { accountId: string; workspaceId: string },
|
|
375
|
+
receipt: HeldSessionUsageReceipt,
|
|
376
|
+
): Promise<void> {
|
|
377
|
+
await settleSessionUsageReceipt(db, {
|
|
378
|
+
accountId: scope.accountId,
|
|
379
|
+
workspaceId: scope.workspaceId,
|
|
380
|
+
sessionId: receipt.sessionId,
|
|
381
|
+
sourceId: receipt.sourceId,
|
|
382
|
+
turnId: receipt.turnId,
|
|
383
|
+
amountMicros: receipt.amountMicros,
|
|
384
|
+
pricingSource: receipt.amountMicros === null ? null : receipt.pricingSource,
|
|
385
|
+
model: receipt.model,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function sessionUsageUnavailable(): ModelCallError {
|
|
390
|
+
return new ModelCallError({
|
|
391
|
+
status: 503,
|
|
392
|
+
type: "service_unavailable",
|
|
393
|
+
code: "session_usage_limit_unavailable",
|
|
394
|
+
message: "Usage for this task is temporarily unavailable. Try again shortly.",
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/** The session of a verified live agent attempt, or null for every other caller. */
|
|
399
|
+
function attemptSessionId(grant: ModelCallInput["grant"]): string | null {
|
|
400
|
+
if (grant?.principalKind !== "agent_attempt") return null;
|
|
401
|
+
const sessionId = grant.metadata?.sessionId;
|
|
402
|
+
return typeof sessionId === "string" && sessionId.length > 0 ? sessionId : null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
async function requireSingleCallSessionUsageLimit(
|
|
406
|
+
deps: {
|
|
407
|
+
db: Parameters<typeof requireSessionUsageLimitAllows>[0];
|
|
408
|
+
usageLimitMetrics?: SessionUsageLimitMetricsSink | null;
|
|
409
|
+
},
|
|
410
|
+
input: {
|
|
411
|
+
accountId: string;
|
|
412
|
+
workspaceId: string;
|
|
413
|
+
sessionId: string;
|
|
414
|
+
runtime?: boolean;
|
|
415
|
+
openSourceId?: string;
|
|
416
|
+
},
|
|
417
|
+
): Promise<void> {
|
|
418
|
+
try {
|
|
419
|
+
await requireSessionUsageLimitAllows(deps.db, input, {
|
|
420
|
+
sink: deps.usageLimitMetrics,
|
|
421
|
+
boundary: "single_call",
|
|
422
|
+
});
|
|
423
|
+
} catch (error) {
|
|
424
|
+
const refusal = sessionUsageLimitRefusalFromError(error);
|
|
425
|
+
if (refusal) {
|
|
426
|
+
throw new ModelCallError({
|
|
427
|
+
status: 402,
|
|
428
|
+
type: "insufficient_quota",
|
|
429
|
+
code: "session_usage_limit_reached",
|
|
430
|
+
message: refusal.message,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
// Unreadable usage state is never treated as unlimited.
|
|
434
|
+
throw sessionUsageUnavailable();
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function assertModelSupportsRequest(model: ConfiguredModel, request: ModelCallInput["request"]) {
|
|
439
|
+
const hasImage = request.messages.some(
|
|
440
|
+
(message) =>
|
|
441
|
+
typeof message.content !== "string" && message.content.some((part) => part.type === "image"),
|
|
442
|
+
);
|
|
443
|
+
if (hasImage && !model.capabilities.inputModalities.includes("image")) {
|
|
444
|
+
throw new ModelCallError({
|
|
445
|
+
status: 400,
|
|
446
|
+
type: "invalid_request_error",
|
|
447
|
+
code: "unsupported_content",
|
|
448
|
+
param: "messages",
|
|
449
|
+
message: `The model '${model.id}' does not accept image input.`,
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
if (
|
|
453
|
+
request.outputFormat?.type === "json_schema" &&
|
|
454
|
+
!model.capabilities.structuredOutput.runnable
|
|
455
|
+
) {
|
|
456
|
+
throw new ModelCallError({
|
|
457
|
+
status: 400,
|
|
458
|
+
type: "invalid_request_error",
|
|
459
|
+
code: "unsupported_parameter",
|
|
460
|
+
param: "response_format",
|
|
461
|
+
message: `The model '${model.id}' does not support structured output.`,
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** A requested effort clamps to the model's nearest supported effort, or is dropped. */
|
|
467
|
+
function reasoningEffortFor(
|
|
468
|
+
model: ConfiguredModel,
|
|
469
|
+
requested: ModelCallInput["request"]["reasoningEffort"],
|
|
470
|
+
): Pick<ModelCallInput["request"], "reasoningEffort"> {
|
|
471
|
+
if (!requested || !model.capabilities.reasoning.runnable) return {};
|
|
472
|
+
if (model.capabilities.reasoning.efforts.length === 0) return {};
|
|
473
|
+
return { reasoningEffort: clampReasoningEffortForConfiguredModel(model, requested, requested) };
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* SuperGrok runs only on the shared subscription core, whose single-call
|
|
478
|
+
* `completion` operation stays Codex-only (design 5.3): this API neither
|
|
479
|
+
* lists nor serves a SuperGrok subscription model, so a request for one is
|
|
480
|
+
* `model_not_found` before admission, never a misleading capacity error.
|
|
481
|
+
*/
|
|
482
|
+
export function servedBySingleModelCalls(selection: WorkspaceModelSelection): boolean {
|
|
483
|
+
const source = selection.model.credentialSource;
|
|
484
|
+
return !(source.kind === "connected_subscription" && source.provider === "xai");
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Whether the account still has included plan usage. A single call never
|
|
489
|
+
* spends a ChatGPT account's paid extra credits: an exhausted or unverifiable
|
|
490
|
+
* account is skipped before anything reaches the provider.
|
|
491
|
+
*/
|
|
492
|
+
export function codexIncludedUsageAvailable(usage: CodexUsagePayload, now = Date.now()): boolean {
|
|
493
|
+
if (usage.status !== "ok" || usage.limitReached) return false;
|
|
494
|
+
const windows = [usage.fiveHour, usage.weekly].filter((window) => window !== null);
|
|
495
|
+
if (windows.length === 0) return false;
|
|
496
|
+
return windows.every(
|
|
497
|
+
(window) =>
|
|
498
|
+
Number.isFinite(window.percent) &&
|
|
499
|
+
(window.percent < 100 || (window.resetAt !== null && Date.parse(window.resetAt) <= now)),
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* A Codex single call is a sessionless operation on the shared subscription
|
|
505
|
+
* core, like transcription: it holds its own operation lease on a shared
|
|
506
|
+
* organization- or workspace-scoped connection, and every physical request is
|
|
507
|
+
* reserved and settled against that lease. Accounts are tried in allocation
|
|
508
|
+
* order only before dispatch; a dispatched request is never replayed.
|
|
509
|
+
*/
|
|
510
|
+
async function withCodexOperation<T>(
|
|
511
|
+
deps: ModelCallServiceDeps,
|
|
512
|
+
settings: Settings,
|
|
513
|
+
input: ModelCallInput,
|
|
514
|
+
model: ConfiguredModel,
|
|
515
|
+
run: () => Promise<T>,
|
|
516
|
+
): Promise<T> {
|
|
517
|
+
const disposition = await readCodexCutoverDisposition(
|
|
518
|
+
deps.db,
|
|
519
|
+
input.accountId,
|
|
520
|
+
input.workspaceId,
|
|
521
|
+
);
|
|
522
|
+
if (disposition !== "core") throw subscriptionCapacityUnavailable("Codex");
|
|
523
|
+
const scope: SubscriptionCoreCodexOperationScope = {
|
|
524
|
+
kind: "workspace",
|
|
525
|
+
accountId: input.accountId,
|
|
526
|
+
workspaceId: input.workspaceId,
|
|
527
|
+
subjectId: input.subjectId,
|
|
528
|
+
};
|
|
529
|
+
const candidates = (await listSubscriptionCoreCodexOperationCandidates(deps.db, scope)).filter(
|
|
530
|
+
(candidate) => connectionModelAllowed(candidate.allowedModelIds, model.id),
|
|
531
|
+
);
|
|
532
|
+
if (candidates.length === 0) throw subscriptionCapacityUnavailable("Codex");
|
|
533
|
+
const operationId = crypto.randomUUID();
|
|
534
|
+
const attemptId = crypto.randomUUID();
|
|
535
|
+
const resolveModel = buildModelResolver(codexUpstreamModelSlugs(settings));
|
|
536
|
+
for (const candidate of candidates) {
|
|
537
|
+
const ref: SubscriptionCoreCodexOperationLeaseRef = {
|
|
538
|
+
operationId,
|
|
539
|
+
attemptId,
|
|
540
|
+
operationKind: "completion",
|
|
541
|
+
connectionId: candidate.connectionId,
|
|
542
|
+
holderId: `completion:${input.requestId}`.slice(0, 256),
|
|
543
|
+
generation: 1,
|
|
544
|
+
};
|
|
545
|
+
const lease = await acquireSubscriptionCoreCodexOperationLease(deps.db, scope, ref);
|
|
546
|
+
if (lease.kind !== "acquired") continue;
|
|
547
|
+
try {
|
|
548
|
+
const { usage } = await fetchSubscriptionCoreCodexUsage(
|
|
549
|
+
deps.db,
|
|
550
|
+
deps.settings,
|
|
551
|
+
scope,
|
|
552
|
+
candidate.connectionId,
|
|
553
|
+
deps.codexFetch,
|
|
554
|
+
);
|
|
555
|
+
if (!codexIncludedUsageAvailable(usage)) continue;
|
|
556
|
+
const resolver = buildSubscriptionCoreCodexConnectionTokenResolver(
|
|
557
|
+
deps.db,
|
|
558
|
+
deps.settings,
|
|
559
|
+
scope,
|
|
560
|
+
candidate.connectionId,
|
|
561
|
+
ref,
|
|
562
|
+
);
|
|
563
|
+
let pending: { operationId: string } | null = null;
|
|
564
|
+
let sequence = 0;
|
|
565
|
+
const context: CodexRequestContext = {
|
|
566
|
+
clientVersion: CODEX_CLIENT_VERSION,
|
|
567
|
+
getToken: () => resolver.getToken(),
|
|
568
|
+
refresh: () => resolver.refresh(),
|
|
569
|
+
resolveModel,
|
|
570
|
+
beforeProviderDispatch: async (request) => {
|
|
571
|
+
if (!(await renewSubscriptionCoreCodexOperationLease(deps.db, scope, ref))) {
|
|
572
|
+
throw subscriptionCapacityUnavailable("Codex");
|
|
573
|
+
}
|
|
574
|
+
if (request) {
|
|
575
|
+
pending = await reserveSubscriptionCoreCodexOperationRequest(
|
|
576
|
+
deps.db,
|
|
577
|
+
scope,
|
|
578
|
+
ref,
|
|
579
|
+
candidate.connectionId,
|
|
580
|
+
request,
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
onProviderRequestSettled: async ({ outcome }) => {
|
|
585
|
+
const reserved = pending;
|
|
586
|
+
pending = null;
|
|
587
|
+
if (!reserved) return;
|
|
588
|
+
await settleSubscriptionCoreCodexOperationRequest(deps.db, scope, {
|
|
589
|
+
operationId: reserved.operationId,
|
|
590
|
+
outcome,
|
|
591
|
+
});
|
|
592
|
+
},
|
|
593
|
+
nextRequestId: () => `completion:${input.requestId}:${++sequence}`,
|
|
594
|
+
};
|
|
595
|
+
return await codexRequestStorage.run(context, run);
|
|
596
|
+
} finally {
|
|
597
|
+
await releaseSubscriptionCoreCodexOperationLease(deps.db, scope, ref).catch(() => false);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
throw new ModelCallError({
|
|
601
|
+
status: 429,
|
|
602
|
+
type: "rate_limit_error",
|
|
603
|
+
code: "subscription_usage_exhausted",
|
|
604
|
+
message: "No Codex subscription account has included usage available right now.",
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function subscriptionCapacityUnavailable(provider: string): ModelCallError {
|
|
609
|
+
return new ModelCallError({
|
|
610
|
+
status: 503,
|
|
611
|
+
type: "service_unavailable",
|
|
612
|
+
code: "subscription_unavailable",
|
|
613
|
+
message: `No ${provider} subscription account is available for this call.`,
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
function subscriptionReconnectRequired(provider: string): ModelCallError {
|
|
618
|
+
return new ModelCallError({
|
|
619
|
+
status: 503,
|
|
620
|
+
type: "service_unavailable",
|
|
621
|
+
code: "subscription_reconnect_required",
|
|
622
|
+
message: `Reconnect the ${provider} subscription to use this model.`,
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
export function isModelCallAbort(error: unknown): boolean {
|
|
627
|
+
return (
|
|
628
|
+
error instanceof Error && (error.name === "AbortError" || error.name === "APIUserAbortError")
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function providerMessage(error: unknown): string {
|
|
633
|
+
const message = error instanceof Error ? error.message.trim() : "";
|
|
634
|
+
return message.length > PROVIDER_MESSAGE_MAX_LENGTH
|
|
635
|
+
? `${message.slice(0, PROVIDER_MESSAGE_MAX_LENGTH)}…`
|
|
636
|
+
: message;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/** Map a provider or runtime failure to a public error; aborts pass through. */
|
|
640
|
+
export function publicModelCallError(error: unknown): unknown {
|
|
641
|
+
if (error instanceof ModelCallError || isModelCallAbort(error)) return error;
|
|
642
|
+
if (error instanceof SingleModelCallUnsupportedError) {
|
|
643
|
+
return new ModelCallError({
|
|
644
|
+
status: 400,
|
|
645
|
+
type: "invalid_request_error",
|
|
646
|
+
code: "unsupported_parameter",
|
|
647
|
+
param: error.parameter,
|
|
648
|
+
message: error.message,
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
if (error instanceof CodexReloginRequired) return subscriptionReconnectRequired("Codex");
|
|
652
|
+
if (error instanceof XaiSubscriptionReloginRequired) {
|
|
653
|
+
return subscriptionReconnectRequired("SuperGrok");
|
|
654
|
+
}
|
|
655
|
+
if (error instanceof ClaudeSubscriptionReconnectRequired) {
|
|
656
|
+
return subscriptionReconnectRequired("Claude");
|
|
657
|
+
}
|
|
658
|
+
if (error instanceof SingleModelCallProviderError) {
|
|
659
|
+
return new ModelCallError({
|
|
660
|
+
status: 502,
|
|
661
|
+
type: "api_error",
|
|
662
|
+
code: "provider_error",
|
|
663
|
+
message: providerMessage(error) || "The model request failed.",
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
const status = providerStatus(error);
|
|
667
|
+
if (status === 429) {
|
|
668
|
+
return new ModelCallError({
|
|
669
|
+
status: 429,
|
|
670
|
+
type: "rate_limit_error",
|
|
671
|
+
code: "provider_rate_limited",
|
|
672
|
+
message: "The model provider is rate limiting requests. Retry later.",
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
if (status === 400 || status === 404 || status === 413 || status === 422) {
|
|
676
|
+
return new ModelCallError({
|
|
677
|
+
status: 400,
|
|
678
|
+
type: "invalid_request_error",
|
|
679
|
+
code: "provider_rejected_request",
|
|
680
|
+
message: providerMessage(error) || "The model provider rejected the request.",
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
return new ModelCallError({
|
|
684
|
+
status: 502,
|
|
685
|
+
type: "api_error",
|
|
686
|
+
code: "provider_error",
|
|
687
|
+
message: "The model request failed.",
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
function providerStatus(error: unknown): number | null {
|
|
692
|
+
const status = (error as { status?: unknown } | null)?.status;
|
|
693
|
+
return typeof status === "number" ? status : null;
|
|
694
|
+
}
|