@opengeni/api-router 0.30.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-grant-rls.d.ts +3 -0
- package/dist/admission-trace.d.ts +8 -0
- package/dist/api-websocket.d.ts +18 -0
- package/dist/app.d.ts +50 -2
- package/dist/app.js +12 -1
- package/dist/artifact-catalog-cursor.d.ts +27 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
- package/dist/auth/managed-auth.d.ts +102 -3
- package/dist/auth/managed-email.d.ts +29 -0
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/organization-user-setup.d.ts +80 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/chunk-6TZ5LG3O.js +123948 -0
- package/dist/chunk-6TZ5LG3O.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-subscription-account-conflicts.d.ts +1 -0
- package/dist/claude-subscription-account-usage.d.ts +39 -0
- package/dist/claude-subscription-oauth.d.ts +25 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +44 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +32 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-ownership.d.ts +54 -0
- package/dist/controller-data-plane.d.ts +32 -0
- package/dist/editable-artifact-office-import.d.ts +7 -4
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +10 -18
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/fatal-process-boundary.d.ts +25 -0
- package/dist/github-access.d.ts +31 -2
- package/dist/http/acting-person.d.ts +24 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +27 -1
- package/dist/http/cors.d.ts +17 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/interaction-control-error.d.ts +13 -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/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +52 -0
- package/dist/http/sse.d.ts +17 -6
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +1129 -166
- package/dist/index.js.map +1 -1
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +29 -3
- package/dist/integrations/connect-authority.d.ts +1 -0
- package/dist/integrations/connect-callback-return.d.ts +6 -0
- package/dist/integrations/fiken.d.ts +16 -2
- package/dist/integrations/github-app-connect.d.ts +47 -0
- package/dist/integrations/github-installation-proof.d.ts +3 -0
- package/dist/integrations/github-lens-connect.d.ts +116 -0
- package/dist/integrations/github-skill-source.d.ts +1 -5
- package/dist/integrations/google-drive.d.ts +25 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +2691 -0
- package/dist/integrations/oauth-client.d.ts +178 -18
- package/dist/integrations/oauth-profiles.d.ts +222 -0
- package/dist/integrations/oauth-return-path.d.ts +1 -0
- package/dist/integrations/personal-github-repositories.d.ts +84 -0
- package/dist/integrations/personal-github.d.ts +42 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +19 -1
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +367 -12
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-install.d.ts +20 -0
- package/dist/integrations/slack-interactions.d.ts +113 -10
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/social-oauth.d.ts +7 -0
- package/dist/interaction-agent-access.d.ts +15 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/interaction-metrics.d.ts +2 -0
- package/dist/mcp/action-catalog-types.d.ts +9 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/command-read.d.ts +24 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/contract-input.d.ts +11 -0
- package/dist/mcp/documents.d.ts +7 -5
- package/dist/mcp/files.d.ts +2 -2
- package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
- package/dist/mcp/knowledge-entries.d.ts +5 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/receipts.d.ts +9 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-input.d.ts +1189 -0
- package/dist/mcp/scheduled-task-view.d.ts +22 -4
- package/dist/mcp/server.d.ts +255 -3
- package/dist/mcp/session-event-view.d.ts +94 -0
- package/dist/mcp/session-view.d.ts +66 -2
- package/dist/mcp/session-wait.d.ts +174 -0
- package/dist/mcp-oauth.d.ts +52 -0
- package/dist/model-catalog.d.ts +11 -31
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +52 -0
- package/dist/organization-recovery-notifications.d.ts +41 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +25 -0
- package/dist/routes/api-keys.d.ts +17 -0
- package/dist/routes/artifact-catalog.d.ts +6 -0
- package/dist/routes/automations.d.ts +19 -0
- package/dist/routes/billing.d.ts +49 -0
- package/dist/routes/browser-sessions.d.ts +71 -3
- 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 +146 -0
- package/dist/routes/codex.d.ts +76 -2
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/computer-sessions.d.ts +14 -0
- package/dist/routes/connect.d.ts +5 -0
- package/dist/routes/editable-artifacts.d.ts +2 -0
- package/dist/routes/external-identity-links.d.ts +6 -0
- package/dist/routes/feedback.d.ts +3 -0
- package/dist/routes/files.d.ts +4 -0
- package/dist/routes/github-browser-pages.d.ts +12 -0
- package/dist/routes/github.d.ts +2 -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 +30 -1
- package/dist/routes/knowledge.d.ts +3 -0
- package/dist/routes/managed-auth-session-sets.d.ts +26 -0
- package/dist/routes/managed-onboarding.d.ts +29 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-connection-access.d.ts +3 -0
- package/dist/routes/organization-integration-policy.d.ts +3 -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-providers.d.ts +3 -0
- package/dist/routes/organization-recovery.d.ts +19 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/organization-sessions.d.ts +26 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +9 -0
- package/dist/routes/sessions.d.ts +44 -6
- package/dist/routes/skill-content.d.ts +4 -0
- package/dist/routes/skill-install-authority.d.ts +6 -0
- package/dist/routes/subscription-account-pools.d.ts +34 -0
- package/dist/routes/subscription-pool-access.d.ts +16 -0
- package/dist/routes/supergrok.d.ts +6 -1
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-artifacts.d.ts +2 -1
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +29 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +19 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +9 -1
- package/dist/sandbox/machines.d.ts +5 -2
- package/dist/sandbox/metrics-ingestion.d.ts +28 -20
- package/dist/sandbox/rematerialize.d.ts +2 -0
- package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
- package/dist/sandbox/viewer.d.ts +26 -1
- package/dist/sandbox-file-artifacts.d.ts +50 -0
- package/dist/scheduled-task-deletion.d.ts +13 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-MPS2OZD3.js +292 -0
- package/dist/session-event-view-MPS2OZD3.js.map +1 -0
- package/dist/site-session-origin.d.ts +13 -0
- package/dist/site-uploads.d.ts +41 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/providers/xai-subscription.d.ts +1 -0
- package/dist/transcription/service.d.ts +2 -1
- package/dist/work-discovery-observability.d.ts +33 -0
- package/dist/workspace-artifact-content.d.ts +28 -0
- package/dist/workspace-artifact-provenance.d.ts +7 -0
- package/dist/workspace-delete-observability.d.ts +10 -0
- package/dist/workspace-deletion.d.ts +6 -0
- package/dist/workspace-state-projection.d.ts +3 -5
- package/dist/workspace-tool-gateway-observability.d.ts +17 -0
- package/dist/workspace-tool-gateway.d.ts +123 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/package.json +23 -19
- package/src/access-grant-rls.ts +75 -0
- package/src/admission-trace.ts +14 -0
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +1974 -256
- package/src/artifact-catalog-cursor.ts +60 -0
- package/src/auth/managed-auth-attempt-context.ts +70 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +222 -0
- package/src/auth/managed-auth.ts +536 -60
- package/src/auth/managed-email.ts +174 -0
- 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 +307 -0
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-subscription-account-conflicts.ts +12 -0
- package/src/claude-subscription-account-usage.ts +48 -0
- package/src/claude-subscription-oauth.ts +362 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +97 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +194 -30
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-ownership.ts +199 -0
- package/src/controller-data-plane.ts +81 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +77 -9
- package/src/editable-artifact-production.ts +23 -7
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +27 -21
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/fatal-process-boundary.ts +246 -0
- package/src/gateway-realtime.ts +1 -1
- package/src/github-access.ts +147 -5
- package/src/http/acting-person.ts +71 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +115 -1
- package/src/http/auth.ts +48 -0
- package/src/http/cors.ts +67 -0
- package/src/http/deprecation.ts +118 -0
- package/src/http/interaction-control-error.ts +164 -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/request-body.ts +127 -0
- package/src/http/request-source.ts +178 -0
- package/src/http/sse.ts +486 -132
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +157 -52
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +98 -11
- package/src/integrations/atlassian.ts +474 -136
- package/src/integrations/connect-authority.ts +2 -0
- package/src/integrations/connect-callback-return.ts +86 -0
- package/src/integrations/fiken.ts +354 -64
- package/src/integrations/github-app-connect.ts +435 -0
- package/src/integrations/github-installation-proof.ts +60 -0
- package/src/integrations/github-lens-connect.ts +76 -0
- package/src/integrations/github-skill-source.ts +2 -142
- package/src/integrations/google-drive.ts +820 -222
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +48 -0
- package/src/integrations/oauth-client.ts +1356 -459
- package/src/integrations/oauth-profiles.ts +537 -0
- package/src/integrations/oauth-return-path.ts +18 -0
- package/src/integrations/personal-github-repositories.ts +674 -0
- package/src/integrations/personal-github.ts +825 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +250 -22
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +963 -239
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +83 -0
- package/src/integrations/slack-interactions.ts +3170 -474
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/social-oauth.ts +213 -15
- package/src/interaction-agent-access.ts +48 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/interaction-metrics.ts +30 -0
- package/src/mcp/action-catalog-types.ts +9 -0
- package/src/mcp/action-catalog.gen.ts +6696 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/command-read.ts +109 -0
- package/src/mcp/company-profile-agent-admin.ts +198 -0
- package/src/mcp/contract-input.ts +141 -0
- package/src/mcp/documents.ts +65 -377
- package/src/mcp/editable-artifacts.ts +12 -6
- package/src/mcp/files.ts +80 -38
- package/src/mcp/first-party-tool-permissions.ts +305 -0
- package/src/mcp/knowledge-entries.ts +322 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/receipts.ts +34 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-input.ts +76 -0
- package/src/mcp/scheduled-task-view.ts +44 -3
- package/src/mcp/server.ts +3030 -1267
- package/src/mcp/session-event-view.ts +383 -0
- package/src/mcp/session-view.ts +84 -3
- package/src/mcp/session-wait.ts +665 -0
- package/src/mcp-oauth.ts +1123 -0
- package/src/model-catalog.ts +91 -333
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +397 -0
- package/src/organization-recovery-notifications.ts +103 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +364 -74
- package/src/routes/api-keys.ts +336 -10
- package/src/routes/artifact-catalog.ts +279 -0
- package/src/routes/automations.ts +768 -0
- package/src/routes/billing.ts +461 -46
- package/src/routes/browser-sessions.ts +839 -131
- package/src/routes/canonical-human-identities.ts +90 -14
- package/src/routes/capabilities.ts +107 -6
- package/src/routes/channels.ts +20 -3
- package/src/routes/claude-subscription-accounts.ts +334 -0
- package/src/routes/claude-subscription-oauth.ts +142 -0
- package/src/routes/client-errors.ts +362 -0
- package/src/routes/codex.ts +833 -116
- package/src/routes/company-brain.ts +322 -0
- package/src/routes/company-profile.ts +65 -1
- package/src/routes/computer-sessions.ts +557 -106
- package/src/routes/connect.ts +1938 -0
- package/src/routes/connections.ts +1040 -349
- package/src/routes/documents.ts +488 -287
- package/src/routes/editable-artifacts.ts +79 -9
- package/src/routes/enrollments.ts +135 -39
- package/src/routes/environments.ts +154 -58
- package/src/routes/external-identity-links.ts +201 -0
- package/src/routes/feedback.ts +113 -0
- package/src/routes/files.ts +337 -39
- package/src/routes/github-browser-pages.ts +162 -0
- package/src/routes/github.ts +446 -144
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +153 -19
- package/src/routes/install.ts +133 -38
- package/src/routes/integration-facets.ts +107 -33
- package/src/routes/interaction-resources.ts +30 -3
- package/src/routes/knowledge.ts +488 -0
- package/src/routes/machines.ts +313 -15
- package/src/routes/managed-auth-session-sets.ts +1218 -0
- package/src/routes/managed-onboarding.ts +337 -0
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-connection-access.ts +208 -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 +178 -0
- package/src/routes/organization-memberships.ts +1019 -27
- package/src/routes/organization-model-providers.ts +293 -0
- package/src/routes/organization-recovery.ts +325 -0
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +350 -0
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +370 -0
- package/src/routes/plugins.ts +251 -22
- package/src/routes/pr-review-github.ts +881 -0
- package/src/routes/pr-review.ts +622 -0
- package/src/routes/preference-registry.ts +12 -93
- package/src/routes/rigs.ts +167 -50
- package/src/routes/scheduled-tasks.ts +346 -41
- package/src/routes/session-artifact-associations.ts +87 -0
- package/src/routes/session-history-imports.ts +280 -0
- package/src/routes/sessions.ts +2306 -264
- package/src/routes/skill-content.ts +297 -0
- package/src/routes/skill-install-authority.ts +64 -0
- package/src/routes/skills.ts +62 -9
- package/src/routes/social.ts +46 -18
- package/src/routes/subscription-account-pools.ts +436 -0
- package/src/routes/subscription-pool-access.ts +126 -0
- package/src/routes/supergrok.ts +219 -303
- package/src/routes/transcription-recordings.ts +38 -3
- package/src/routes/transcriptions.ts +4 -0
- package/src/routes/usage-allowances.ts +378 -0
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/video-generation.ts +14 -10
- package/src/routes/workspace-artifacts.ts +275 -69
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-learning.ts +159 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +38 -25
- package/src/routes/workspaces.ts +1004 -127
- package/src/sandbox/auth-callout.ts +96 -19
- package/src/sandbox/channel-a.ts +323 -24
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +81 -6
- package/src/sandbox/machines.ts +218 -76
- package/src/sandbox/metrics-ingestion.ts +411 -62
- package/src/sandbox/rematerialize.ts +121 -19
- package/src/sandbox/session-attach-variable-sets.ts +131 -0
- package/src/sandbox/viewer.ts +280 -25
- package/src/sandbox-file-artifacts.ts +413 -0
- package/src/scheduled-task-deletion.ts +138 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +6 -3
- package/src/site-session-origin.ts +48 -0
- package/src/site-uploads.ts +224 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/providers/codex-subscription.ts +2 -0
- package/src/transcription/providers/openai.ts +1 -0
- package/src/transcription/providers/xai-subscription.ts +49 -3
- package/src/transcription/segmenter.ts +8 -2
- package/src/transcription/service.ts +43 -6
- package/src/work-discovery-observability.ts +121 -0
- package/src/workspace-artifact-content.ts +144 -0
- package/src/workspace-artifact-provenance.ts +104 -0
- package/src/workspace-delete-observability.ts +75 -0
- package/src/workspace-deletion.ts +73 -0
- package/src/workspace-state-projection.ts +18 -148
- package/src/workspace-tool-gateway-observability.ts +100 -0
- package/src/workspace-tool-gateway.ts +870 -0
- package/src/workspace-webhook-dispatch.ts +190 -0
- package/src/xai-subscription-auth.ts +9 -2
- package/dist/chunk-2PQMSRCB.js +0 -49759
- package/dist/chunk-2PQMSRCB.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
package/src/sandbox/channel-a.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
hasGitCredentialRepositorySelection,
|
|
23
23
|
hasGitHubRepositorySelection,
|
|
24
24
|
sandboxLifecycleTransitionWaitMs,
|
|
25
|
+
sandboxWarmRateMicrosPerSecond,
|
|
25
26
|
stableSandboxEnvironmentForRun,
|
|
26
27
|
type Settings,
|
|
27
28
|
} from "@opengeni/config";
|
|
@@ -30,25 +31,33 @@ import type { Session } from "@opengeni/contracts";
|
|
|
30
31
|
import {
|
|
31
32
|
acquireLease,
|
|
32
33
|
getSandboxSessionEnvelope,
|
|
33
|
-
|
|
34
|
+
getLiveEnrollmentConnection,
|
|
34
35
|
getSandbox,
|
|
35
|
-
|
|
36
|
+
touchLeaseHolder,
|
|
36
37
|
markWarmLeaseInstanceLost,
|
|
37
38
|
readActiveSandbox,
|
|
38
39
|
readLease,
|
|
39
40
|
releaseLeaseHolder,
|
|
41
|
+
SandboxImageConflictError,
|
|
40
42
|
SandboxProviderReadLockUnavailableError,
|
|
43
|
+
SandboxRigConflictError,
|
|
44
|
+
SandboxPaidComputeAdmissionError,
|
|
41
45
|
withSandboxProviderReadLock,
|
|
42
46
|
type Database,
|
|
43
47
|
type LeaseSnapshot,
|
|
44
48
|
} from "@opengeni/db";
|
|
45
49
|
import { appendAndPublishEvents, type EventBus } from "@opengeni/events";
|
|
46
50
|
import {
|
|
51
|
+
recordTenancyCompatibilityLaneUse,
|
|
47
52
|
sandboxLeaseTelemetryKey,
|
|
48
53
|
sandboxOperationMetricObserver,
|
|
54
|
+
sandboxCaptureWaitMetricObserver,
|
|
49
55
|
type Observability,
|
|
50
56
|
} from "@opengeni/observability";
|
|
51
57
|
import { HTTPException } from "hono/http-exception";
|
|
58
|
+
import { ApiHttpError } from "../http/api-error";
|
|
59
|
+
import { loadSessionAttachVariableSetValues } from "./session-attach-variable-sets";
|
|
60
|
+
import type { ObjectStorage } from "@opengeni/storage";
|
|
52
61
|
|
|
53
62
|
import {
|
|
54
63
|
buildSelfhostedBackendSession,
|
|
@@ -59,27 +68,43 @@ import {
|
|
|
59
68
|
NatsOpStreamTransport,
|
|
60
69
|
SandboxResumeIdentityMismatchError,
|
|
61
70
|
SandboxResumeIdentityUnavailableError,
|
|
71
|
+
RoutingActiveRouteChangedError,
|
|
72
|
+
RoutingWorkspaceRootChangedError,
|
|
73
|
+
SelfhostedWorkspaceRootChangedError,
|
|
62
74
|
ChannelAConflictError,
|
|
75
|
+
ChannelAFileSystemRouteChangedError,
|
|
63
76
|
ChannelANotFoundError,
|
|
64
77
|
ChannelAUnsupportedError,
|
|
65
78
|
ChannelAUnavailableError,
|
|
66
79
|
ChannelAValidationError,
|
|
67
80
|
BrowserControlRequestError,
|
|
68
81
|
BrowserControlTransportError,
|
|
82
|
+
SelfhostedControlError,
|
|
83
|
+
agentErrorToControlError,
|
|
69
84
|
codemodeTokenFileFromEnvironment,
|
|
85
|
+
offlineAgentError,
|
|
86
|
+
resolveConnectedMachineWorkspaceRoot,
|
|
70
87
|
withCodemodeTokenSession,
|
|
71
88
|
withRunCredentialsSession,
|
|
72
89
|
type ChannelASession,
|
|
73
90
|
type EstablishedSandboxSession,
|
|
74
91
|
type RoutingSandboxSession,
|
|
75
92
|
} from "@opengeni/runtime/sandbox";
|
|
76
|
-
import {
|
|
93
|
+
import {
|
|
94
|
+
managedSessionGroupBackend,
|
|
95
|
+
managedSessionGroupOs,
|
|
96
|
+
providerSettingsForSessionSandboxRuntime,
|
|
97
|
+
relayConfigFromSettings,
|
|
98
|
+
resolveSessionSandboxRuntime,
|
|
99
|
+
wrapChannelABoxWithRouting,
|
|
100
|
+
} from "@opengeni/core";
|
|
77
101
|
import { establishApiSandboxSpawner } from "./rematerialize";
|
|
78
102
|
|
|
79
103
|
export type ChannelAServices = {
|
|
80
104
|
db: Database;
|
|
81
105
|
settings: Settings;
|
|
82
106
|
bus: EventBus;
|
|
107
|
+
objectStorage?: ObjectStorage | null;
|
|
83
108
|
observability?: Observability | undefined;
|
|
84
109
|
};
|
|
85
110
|
|
|
@@ -87,6 +112,7 @@ export type ChannelAOperation =
|
|
|
87
112
|
| "fs.list"
|
|
88
113
|
| "fs.list-batch"
|
|
89
114
|
| "fs.read"
|
|
115
|
+
| "artifact.publish"
|
|
90
116
|
| "fs.write"
|
|
91
117
|
| "fs.delete"
|
|
92
118
|
| "fs.move"
|
|
@@ -132,6 +158,10 @@ export type ChannelAContext = {
|
|
|
132
158
|
* provider handle and replay the request. Tab/lifecycle mutations that lack
|
|
133
159
|
* a controller operation id must never opt into this recovery. */
|
|
134
160
|
retryControllerTransport?: boolean | undefined;
|
|
161
|
+
/** Ephemeral browser callbacks must never replay after an ambiguous result. */
|
|
162
|
+
allowOperationReplay?: boolean | undefined;
|
|
163
|
+
/** Exact existing interaction provider; may not spawn/rotate on image drift. */
|
|
164
|
+
retainedInstanceId?: string | undefined;
|
|
135
165
|
};
|
|
136
166
|
|
|
137
167
|
export type ChannelAOperationFailureReason =
|
|
@@ -379,6 +409,8 @@ type ChannelAReadRecoveryOptions = {
|
|
|
379
409
|
/** Modal may expose one more stale command-router route after the first
|
|
380
410
|
* successful handle rebuild. Keep this closed and statically bounded. */
|
|
381
411
|
maxFreshHandleRetries?: 1 | 2;
|
|
412
|
+
/** Explicit opt-out overrides every transport/provider retry classification. */
|
|
413
|
+
allowOperationReplay?: boolean | undefined;
|
|
382
414
|
/** Never start another provider attempt after the originating request ends. */
|
|
383
415
|
waitSignal?: AbortSignal | undefined;
|
|
384
416
|
/** Additional callback-specific failure that is safe to replay. */
|
|
@@ -405,7 +437,11 @@ export async function runChannelAReadWithFreshHandleRetry<T>(
|
|
|
405
437
|
} catch (error) {
|
|
406
438
|
const retryable =
|
|
407
439
|
error instanceof ChannelAUnavailableError || options.retryableError?.(error) === true;
|
|
408
|
-
if (
|
|
440
|
+
if (
|
|
441
|
+
options.allowOperationReplay === false ||
|
|
442
|
+
!retryable ||
|
|
443
|
+
retries >= maxFreshHandleRetries
|
|
444
|
+
) {
|
|
409
445
|
throw error;
|
|
410
446
|
}
|
|
411
447
|
options.waitSignal?.throwIfAborted();
|
|
@@ -507,6 +543,9 @@ async function withChannelAOperation<T>(
|
|
|
507
543
|
const onSandboxOperation = services.observability
|
|
508
544
|
? sandboxOperationMetricObserver(services.observability)
|
|
509
545
|
: undefined;
|
|
546
|
+
const onSandboxCaptureWait = services.observability
|
|
547
|
+
? sandboxCaptureWaitMetricObserver(services.observability)
|
|
548
|
+
: undefined;
|
|
510
549
|
const { accountId, workspaceId, session } = ctx;
|
|
511
550
|
|
|
512
551
|
if (session.sandboxBackend === "none") {
|
|
@@ -522,19 +561,19 @@ async function withChannelAOperation<T>(
|
|
|
522
561
|
|
|
523
562
|
// The STABLE run-environment used by both a cloud home and a machine home.
|
|
524
563
|
// It also carries the per-session Codemode pointer selected below.
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
settings,
|
|
564
|
+
const workspaceEnvironmentValues = await loadSessionAttachVariableSetValues(db, settings, {
|
|
565
|
+
accountId,
|
|
528
566
|
workspaceId,
|
|
529
|
-
session
|
|
530
|
-
|
|
567
|
+
session,
|
|
568
|
+
subjectId: ctx.subjectId,
|
|
569
|
+
});
|
|
531
570
|
const settingsForSession =
|
|
532
571
|
session.sandboxBackend !== settings.sandboxBackend
|
|
533
572
|
? { ...settings, sandboxBackend: session.sandboxBackend }
|
|
534
573
|
: settings;
|
|
535
574
|
const environment = stableSandboxEnvironmentForRun(
|
|
536
575
|
settingsForSession,
|
|
537
|
-
|
|
576
|
+
workspaceEnvironmentValues,
|
|
538
577
|
{ workspaceId },
|
|
539
578
|
);
|
|
540
579
|
if (hasGitCredentialRepositorySelection(session.resources)) {
|
|
@@ -566,12 +605,27 @@ async function withChannelAOperation<T>(
|
|
|
566
605
|
codemodeTokenFileFromEnvironment(environment, session.id),
|
|
567
606
|
)
|
|
568
607
|
: credentialSession;
|
|
608
|
+
const fileSystemAuthority = await routingSession.fileSystemAuthority();
|
|
609
|
+
const fileSystemEpoch =
|
|
610
|
+
fileSystemAuthority.backendKind === "selfhosted"
|
|
611
|
+
? fileSystemAuthority.activeEpoch
|
|
612
|
+
: (lease?.leaseEpoch ?? fileSystemAuthority.activeEpoch);
|
|
569
613
|
const service = new SandboxChannelAService({
|
|
570
614
|
session: scopedSession as ChannelASession,
|
|
571
|
-
|
|
615
|
+
workspaceRoot: fileSystemAuthority.root,
|
|
616
|
+
leaseEpoch: fileSystemEpoch,
|
|
617
|
+
...(fileSystemAuthority.backendKind === "selfhosted"
|
|
618
|
+
? { providerPathMode: "workspace-relative" as const, fileReadScope: "machine" as const }
|
|
619
|
+
: {}),
|
|
572
620
|
emit,
|
|
573
621
|
});
|
|
574
|
-
const result = await fn({
|
|
622
|
+
const result = await fn({
|
|
623
|
+
service,
|
|
624
|
+
lease,
|
|
625
|
+
homeSession,
|
|
626
|
+
routingSession,
|
|
627
|
+
requestId,
|
|
628
|
+
});
|
|
575
629
|
// The direct request has accepted the result in memory. Finalize every
|
|
576
630
|
// Connected Machine backend the routing proxy reached so a mid-request
|
|
577
631
|
// route transition cannot leave completed output retained until TTL.
|
|
@@ -588,27 +642,81 @@ async function withChannelAOperation<T>(
|
|
|
588
642
|
ctx.waitSignal?.throwIfAborted();
|
|
589
643
|
const pointer = await readActiveSandbox(db, workspaceId, session.id);
|
|
590
644
|
if (!pointer?.activeSandboxId) {
|
|
645
|
+
// A machine-home session with no selected machine uses the deployment's
|
|
646
|
+
// managed group box, exactly like the worker turn path. Keep the durable
|
|
647
|
+
// home label honest; only this request's effective backend changes.
|
|
648
|
+
const groupBackend = managedSessionGroupBackend(
|
|
649
|
+
settings.sandboxBackend,
|
|
650
|
+
session.sandboxBackend,
|
|
651
|
+
);
|
|
652
|
+
if (groupBackend) {
|
|
653
|
+
return await withChannelAOperation(
|
|
654
|
+
services,
|
|
655
|
+
{
|
|
656
|
+
...ctx,
|
|
657
|
+
session: {
|
|
658
|
+
...session,
|
|
659
|
+
sandboxBackend: groupBackend,
|
|
660
|
+
sandboxOs: managedSessionGroupOs(session.sandboxBackend, session.sandboxOs),
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
readOnly,
|
|
664
|
+
fn,
|
|
665
|
+
);
|
|
666
|
+
}
|
|
591
667
|
throw new HTTPException(409, {
|
|
592
|
-
message: "machine-home session has no active Connected Machine",
|
|
668
|
+
message: "machine-home session has no active Connected Machine or managed sandbox",
|
|
593
669
|
});
|
|
594
670
|
}
|
|
595
|
-
const sandbox = await getSandbox(
|
|
671
|
+
const sandbox = await getSandbox(
|
|
672
|
+
db,
|
|
673
|
+
{ accountId: ctx.accountId, workspaceId, subjectId: ctx.subjectId },
|
|
674
|
+
pointer.activeSandboxId,
|
|
675
|
+
);
|
|
596
676
|
if (sandbox?.kind !== "selfhosted" || !sandbox.enrollmentId) {
|
|
597
677
|
throw new HTTPException(409, {
|
|
598
678
|
message: "machine-home session points to an unavailable Connected Machine",
|
|
599
679
|
});
|
|
600
680
|
}
|
|
601
|
-
const
|
|
681
|
+
const originWorkspaceId = sandbox.workspaceId;
|
|
682
|
+
const enrollment = await getLiveEnrollmentConnection(
|
|
683
|
+
db,
|
|
684
|
+
{ accountId, workspaceId, subjectId: ctx.subjectId },
|
|
685
|
+
sandbox.enrollmentId,
|
|
686
|
+
);
|
|
687
|
+
if (!enrollment?.connectionInstanceId) {
|
|
688
|
+
// Preserve causal machine liveness through Channel-A. Generic callers
|
|
689
|
+
// retain the established 409 mapping below; Browser/Computer callers can
|
|
690
|
+
// project the same bounded `agent_offline` contract as control RPC.
|
|
691
|
+
throw agentErrorToControlError(
|
|
692
|
+
offlineAgentError("Connected Machine has no live runner connection", true),
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
if (!enrollment.workspaceRoot) {
|
|
696
|
+
throw new HTTPException(409, {
|
|
697
|
+
message:
|
|
698
|
+
"Connected Machine has not reported an absolute workspace root; reconnect it with a current agent",
|
|
699
|
+
});
|
|
700
|
+
}
|
|
602
701
|
const built = await buildSelfhostedBackendSession({
|
|
603
|
-
workspaceId,
|
|
702
|
+
workspaceId: originWorkspaceId,
|
|
604
703
|
agentId: sandbox.enrollmentId,
|
|
704
|
+
connectionInstanceId: enrollment.connectionInstanceId,
|
|
705
|
+
workspaceRoot: resolveConnectedMachineWorkspaceRoot(
|
|
706
|
+
enrollment.workspaceRoot,
|
|
707
|
+
pointer.workingDir,
|
|
708
|
+
),
|
|
605
709
|
relay: relayConfigFromSettings(settings),
|
|
606
710
|
controlRpcFactory: () => new NatsControlRpc(async () => bus.getRequestConnection()),
|
|
607
711
|
epoch: pointer.activeEpoch,
|
|
608
712
|
environment,
|
|
609
|
-
workingDir: pointer.workingDir,
|
|
610
713
|
timeoutMs: settings.sandboxSelfhostedControlTimeoutMs,
|
|
611
714
|
execTimeoutMs: settings.sandboxSelfhostedExecTimeoutMs,
|
|
715
|
+
operationResourcePolicy: enrollment.operationPolicy,
|
|
716
|
+
operationResourcePolicySupported:
|
|
717
|
+
enrollment.agentCapabilities.operationResourcePolicy === true,
|
|
718
|
+
operationCpuQuotaSupported: enrollment.agentCapabilities.operationCpuQuota === true,
|
|
719
|
+
transactionalFsWriteSupported: enrollment.agentCapabilities.transactionalFsWrite === true,
|
|
612
720
|
...(settings.agentOpStreamEnabled === true &&
|
|
613
721
|
enrollment?.opStream === true &&
|
|
614
722
|
bus.getOpStreamConnection
|
|
@@ -634,12 +742,14 @@ async function withChannelAOperation<T>(
|
|
|
634
742
|
settings,
|
|
635
743
|
bus,
|
|
636
744
|
...(onSandboxOperation ? { onSandboxOperation } : {}),
|
|
745
|
+
...(onSandboxCaptureWait ? { onSandboxCaptureWait } : {}),
|
|
637
746
|
...(ctx.waitSignal ? { waitSignal: ctx.waitSignal } : {}),
|
|
638
747
|
},
|
|
639
748
|
{
|
|
640
749
|
accountId,
|
|
641
750
|
workspaceId,
|
|
642
751
|
sessionId: session.id,
|
|
752
|
+
resourceSubjectId: ctx.subjectId,
|
|
643
753
|
pinnedSelfhosted: {
|
|
644
754
|
sandboxId: sandbox.id,
|
|
645
755
|
epoch: pointer.activeEpoch,
|
|
@@ -665,6 +775,12 @@ async function withChannelAOperation<T>(
|
|
|
665
775
|
}
|
|
666
776
|
}
|
|
667
777
|
|
|
778
|
+
// One session has one logical runtime across turns and every API-direct
|
|
779
|
+
// surface. Without this, Terminal/Files/Browser/Computer/viewers could rearm
|
|
780
|
+
|
|
781
|
+
// deployment image for the same durable sandbox group.
|
|
782
|
+
const sandboxRuntime = await resolveSessionSandboxRuntime(db, settings, session);
|
|
783
|
+
|
|
668
784
|
const release = async (): Promise<void> => {
|
|
669
785
|
await releaseLeaseHolder(db, {
|
|
670
786
|
accountId,
|
|
@@ -692,7 +808,15 @@ async function withChannelAOperation<T>(
|
|
|
692
808
|
holderId,
|
|
693
809
|
subjectId: session.id,
|
|
694
810
|
backend: session.sandboxBackend,
|
|
811
|
+
warmBilling: {
|
|
812
|
+
mode: settings.sandboxWarmBillingMode,
|
|
813
|
+
rateMicrosPerSecond: sandboxWarmRateMicrosPerSecond(settings, session.sandboxBackend),
|
|
814
|
+
},
|
|
695
815
|
os: session.sandboxOs,
|
|
816
|
+
image: sandboxRuntime.image,
|
|
817
|
+
imagePolicy: "new_creates_only",
|
|
818
|
+
...(ctx.retainedInstanceId ? { retainedInstanceId: ctx.retainedInstanceId } : {}),
|
|
819
|
+
rigVersionId: session.rigVersionId,
|
|
696
820
|
leaseTtlMs,
|
|
697
821
|
warmingLeaseTtlMs: settings.sandboxWarmingTimeoutMs,
|
|
698
822
|
captureWaitMs: sandboxLifecycleTransitionWaitMs(settings),
|
|
@@ -716,6 +840,56 @@ async function withChannelAOperation<T>(
|
|
|
716
840
|
});
|
|
717
841
|
}
|
|
718
842
|
} catch (error) {
|
|
843
|
+
let mappedError: unknown = error;
|
|
844
|
+
if (error instanceof SandboxImageConflictError) {
|
|
845
|
+
// A durable Browser/Computer holder can outlive its provider container.
|
|
846
|
+
// Runtime drift is checked before a new direct holder is admitted, so a
|
|
847
|
+
// dead old container would otherwise strand the lease behind a permanent
|
|
848
|
+
// conflict. Probe the exact old identity without replacement; only an
|
|
849
|
+
// authoritative provider-missing result may retire it and unblock the
|
|
850
|
+
// next request's cold successor election.
|
|
851
|
+
const live = await readLease(db, workspaceId, sandboxGroupId).catch(() => null);
|
|
852
|
+
if (live?.liveness === "warm" && live.instanceId !== null && live.resumeState !== null) {
|
|
853
|
+
let probe: EstablishedSandboxSession | undefined;
|
|
854
|
+
try {
|
|
855
|
+
probe = await establishSandboxSessionFromEnvelope(
|
|
856
|
+
sandboxRuntime.settings,
|
|
857
|
+
live.resumeState,
|
|
858
|
+
{
|
|
859
|
+
sessionId: session.id,
|
|
860
|
+
recovery: "resume-only",
|
|
861
|
+
backendOverride: session.sandboxBackend,
|
|
862
|
+
environment,
|
|
863
|
+
},
|
|
864
|
+
);
|
|
865
|
+
} catch (probeError) {
|
|
866
|
+
if (isProviderSandboxNotFoundError(session.sandboxBackend, probeError)) {
|
|
867
|
+
const marked = await markWarmLeaseInstanceLost(db, {
|
|
868
|
+
accountId,
|
|
869
|
+
workspaceId,
|
|
870
|
+
sandboxGroupId,
|
|
871
|
+
expectedEpoch: live.leaseEpoch,
|
|
872
|
+
expectedInstanceId: live.instanceId,
|
|
873
|
+
}).catch(() => null);
|
|
874
|
+
if (marked?.status === "marked") {
|
|
875
|
+
await appendAndPublishEvents(db, bus, workspaceId, session.id, [
|
|
876
|
+
{
|
|
877
|
+
type: "sandbox.box.lost",
|
|
878
|
+
payload: { sandboxId: live.instanceId },
|
|
879
|
+
},
|
|
880
|
+
]).catch(() => undefined);
|
|
881
|
+
mappedError = new ApiHttpError(409, {
|
|
882
|
+
code: "conflict",
|
|
883
|
+
message: "sandbox instance was lost; retry to restore it",
|
|
884
|
+
retryable: true,
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
} finally {
|
|
889
|
+
await dropEstablishedHandle(probe);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
719
893
|
// Release is idempotent. If acquisition committed before the request was
|
|
720
894
|
// cancelled, this removes that exact direct holder; a transient DB failure
|
|
721
895
|
// must not overwrite the original structural error (holder TTL is the final
|
|
@@ -727,12 +901,28 @@ async function withChannelAOperation<T>(
|
|
|
727
901
|
backend: session.sandboxBackend,
|
|
728
902
|
operation,
|
|
729
903
|
durationMs: performance.now() - operationStartedAt,
|
|
730
|
-
error,
|
|
904
|
+
error: mappedError,
|
|
731
905
|
waitSignal: ctx.waitSignal,
|
|
732
906
|
});
|
|
733
|
-
throw mapChannelAError(
|
|
907
|
+
throw mapChannelAError(mappedError, ctx.waitSignal);
|
|
734
908
|
}
|
|
735
909
|
|
|
910
|
+
// Keep the exact direct-request owner visible for the full operation. A
|
|
911
|
+
// yielded command is also tracked by a non-TTL process holder, but the
|
|
912
|
+
// retained-process reconciler must not poll that provider session while this
|
|
913
|
+
// request is still its active owner. Stale direct holders remain crash-
|
|
914
|
+
// recoverable through the ordinary holder TTL reaper.
|
|
915
|
+
const directHolderHeartbeat = setInterval(() => {
|
|
916
|
+
void touchLeaseHolder(db, {
|
|
917
|
+
accountId,
|
|
918
|
+
workspaceId,
|
|
919
|
+
sandboxGroupId,
|
|
920
|
+
kind: "direct",
|
|
921
|
+
holderId,
|
|
922
|
+
}).catch(() => undefined);
|
|
923
|
+
}, 10_000);
|
|
924
|
+
directHolderHeartbeat.unref?.();
|
|
925
|
+
|
|
736
926
|
let established: EstablishedSandboxSession | undefined;
|
|
737
927
|
let leaseSnapshot: LeaseSnapshot = acquired.lease;
|
|
738
928
|
let establishedCacheKey: string | null = null;
|
|
@@ -747,7 +937,7 @@ async function withChannelAOperation<T>(
|
|
|
747
937
|
): Promise<{ established: EstablishedSandboxSession; cacheKey: string }> => {
|
|
748
938
|
const cacheKey = establishedHandleCacheKey(workspaceId, session.id, live);
|
|
749
939
|
const establish = () =>
|
|
750
|
-
establishSandboxSessionFromEnvelope(settings, live.resumeState, {
|
|
940
|
+
establishSandboxSessionFromEnvelope(sandboxRuntime.settings, live.resumeState, {
|
|
751
941
|
sessionId: session.id,
|
|
752
942
|
recovery: "resume-only",
|
|
753
943
|
backendOverride: session.sandboxBackend,
|
|
@@ -781,8 +971,10 @@ async function withChannelAOperation<T>(
|
|
|
781
971
|
},
|
|
782
972
|
]);
|
|
783
973
|
}
|
|
784
|
-
throw new
|
|
974
|
+
throw new ApiHttpError(409, {
|
|
975
|
+
code: "conflict",
|
|
785
976
|
message: `sandbox instance was lost; retry to restore it`,
|
|
977
|
+
retryable: true,
|
|
786
978
|
});
|
|
787
979
|
}
|
|
788
980
|
};
|
|
@@ -802,9 +994,13 @@ async function withChannelAOperation<T>(
|
|
|
802
994
|
// resume_state is the lease's authoritative box descriptor; the session
|
|
803
995
|
// `_sandbox` envelope is only the per-session fallback.
|
|
804
996
|
try {
|
|
997
|
+
const providerSettings = await providerSettingsForSessionSandboxRuntime(
|
|
998
|
+
sandboxRuntime,
|
|
999
|
+
session.sandboxBackend,
|
|
1000
|
+
);
|
|
805
1001
|
const result = await establishApiSandboxSpawner({
|
|
806
1002
|
db,
|
|
807
|
-
settings,
|
|
1003
|
+
settings: providerSettings,
|
|
808
1004
|
accountId,
|
|
809
1005
|
workspaceId,
|
|
810
1006
|
sandboxGroupId,
|
|
@@ -815,6 +1011,9 @@ async function withChannelAOperation<T>(
|
|
|
815
1011
|
acquiredLease: acquired.lease,
|
|
816
1012
|
fallbackEnvelope: envelope,
|
|
817
1013
|
dataPlaneUrl: acquired.lease.dataPlaneUrl,
|
|
1014
|
+
...(services.objectStorage !== undefined
|
|
1015
|
+
? { objectStorage: services.objectStorage }
|
|
1016
|
+
: {}),
|
|
818
1017
|
});
|
|
819
1018
|
established = result.established;
|
|
820
1019
|
leaseSnapshot = result.lease;
|
|
@@ -857,12 +1056,14 @@ async function withChannelAOperation<T>(
|
|
|
857
1056
|
settings,
|
|
858
1057
|
bus,
|
|
859
1058
|
...(onSandboxOperation ? { onSandboxOperation } : {}),
|
|
1059
|
+
...(onSandboxCaptureWait ? { onSandboxCaptureWait } : {}),
|
|
860
1060
|
...(ctx.waitSignal ? { waitSignal: ctx.waitSignal } : {}),
|
|
861
1061
|
},
|
|
862
1062
|
{
|
|
863
1063
|
accountId,
|
|
864
1064
|
workspaceId,
|
|
865
1065
|
sessionId: session.id,
|
|
1066
|
+
resourceSubjectId: ctx.subjectId,
|
|
866
1067
|
homeLease: {
|
|
867
1068
|
sandboxGroupId,
|
|
868
1069
|
leaseEpoch: leaseSnapshot.leaseEpoch,
|
|
@@ -964,6 +1165,7 @@ async function withChannelAOperation<T>(
|
|
|
964
1165
|
},
|
|
965
1166
|
{
|
|
966
1167
|
maxFreshHandleRetries: session.sandboxBackend === "modal" ? 2 : 1,
|
|
1168
|
+
allowOperationReplay: ctx.allowOperationReplay,
|
|
967
1169
|
...(ctx.waitSignal ? { waitSignal: ctx.waitSignal } : {}),
|
|
968
1170
|
...(ctx.retryControllerTransport
|
|
969
1171
|
? { retryableError: isRetryableControllerTransport }
|
|
@@ -990,6 +1192,7 @@ async function withChannelAOperation<T>(
|
|
|
990
1192
|
});
|
|
991
1193
|
throw mapChannelAError(error, ctx.waitSignal);
|
|
992
1194
|
} finally {
|
|
1195
|
+
clearInterval(directHolderHeartbeat);
|
|
993
1196
|
await release();
|
|
994
1197
|
await dropEstablishedHandle(established);
|
|
995
1198
|
}
|
|
@@ -999,6 +1202,8 @@ async function withChannelAOperation<T>(
|
|
|
999
1202
|
* already-HTTPException unchanged. */
|
|
1000
1203
|
export function mapChannelAError(error: unknown, waitSignal?: AbortSignal): unknown {
|
|
1001
1204
|
if (error instanceof HTTPException) return error;
|
|
1205
|
+
if (error instanceof SandboxPaidComputeAdmissionError)
|
|
1206
|
+
return new HTTPException(402, { message: error.message, cause: error });
|
|
1002
1207
|
if (isChannelARequestCancellation(error, waitSignal))
|
|
1003
1208
|
return new HTTPException(499 as never, {
|
|
1004
1209
|
message: "request cancelled",
|
|
@@ -1009,8 +1214,44 @@ export function mapChannelAError(error: unknown, waitSignal?: AbortSignal): unkn
|
|
|
1009
1214
|
error instanceof SandboxResumeIdentityUnavailableError
|
|
1010
1215
|
)
|
|
1011
1216
|
return new HTTPException(409, { message: error.message });
|
|
1217
|
+
if (
|
|
1218
|
+
error instanceof RoutingActiveRouteChangedError ||
|
|
1219
|
+
error instanceof RoutingWorkspaceRootChangedError ||
|
|
1220
|
+
error instanceof SelfhostedWorkspaceRootChangedError ||
|
|
1221
|
+
error instanceof ChannelAFileSystemRouteChangedError
|
|
1222
|
+
)
|
|
1223
|
+
return new ApiHttpError(409, {
|
|
1224
|
+
code: "conflict",
|
|
1225
|
+
message: error.message,
|
|
1226
|
+
retryable: true,
|
|
1227
|
+
});
|
|
1012
1228
|
if (error instanceof SandboxProviderReadLockUnavailableError)
|
|
1013
1229
|
return new HTTPException(503, { message: error.message });
|
|
1230
|
+
if (error instanceof SandboxImageConflictError || error instanceof SandboxRigConflictError)
|
|
1231
|
+
return new ApiHttpError(409, {
|
|
1232
|
+
code: "conflict",
|
|
1233
|
+
message: "sandbox runtime changed while this session still has active operations; retry",
|
|
1234
|
+
retryable: true,
|
|
1235
|
+
});
|
|
1236
|
+
if (error instanceof SelfhostedControlError && error.agentOffline)
|
|
1237
|
+
return new HTTPException(409, { message: error.message, cause: error });
|
|
1238
|
+
if (error instanceof SelfhostedControlError && error.payloadTooLarge) {
|
|
1239
|
+
const outbound = error.detail.direction === "request";
|
|
1240
|
+
// Project only the bounded direction. Native free-form diagnostics can
|
|
1241
|
+
// contain file contents or private paths. A large reply is not evidence
|
|
1242
|
+
// that the operation failed before execution, and must not invite replay.
|
|
1243
|
+
return new ApiHttpError(outbound ? 413 : 502, {
|
|
1244
|
+
code: "limit_exceeded",
|
|
1245
|
+
message: outbound
|
|
1246
|
+
? "The request exceeds the connected machine's per-message size limit. Large file content requires a machine that supports bounded file transfers."
|
|
1247
|
+
: "The connected machine's reply exceeds its per-message size limit. The operation may have completed; inspect its result before repeating it. Read large files in bounded ranges.",
|
|
1248
|
+
retryable: false,
|
|
1249
|
+
details: {
|
|
1250
|
+
code: "machine_transport_payload_too_large",
|
|
1251
|
+
direction: outbound ? "request" : "response",
|
|
1252
|
+
},
|
|
1253
|
+
});
|
|
1254
|
+
}
|
|
1014
1255
|
if (error instanceof ChannelAUnavailableError)
|
|
1015
1256
|
return new HTTPException(503, { message: error.message });
|
|
1016
1257
|
if (error instanceof ChannelAValidationError)
|
|
@@ -1021,9 +1262,31 @@ export function mapChannelAError(error: unknown, waitSignal?: AbortSignal): unkn
|
|
|
1021
1262
|
return new HTTPException(409, { message: error.message });
|
|
1022
1263
|
if (error instanceof ChannelAUnsupportedError)
|
|
1023
1264
|
return new HTTPException(409, { message: error.message });
|
|
1265
|
+
const authorityFence = workspaceMutationAuthorityFenceCode(error);
|
|
1266
|
+
// A revoked grant is an authorization outcome, not a server fault; an
|
|
1267
|
+
// unattributed pre-0277 writer is a conflict the caller resolves by starting
|
|
1268
|
+
// fresh work. Both must be visible instead of surfacing as a 500.
|
|
1269
|
+
if (authorityFence === "authority_revoked")
|
|
1270
|
+
return new HTTPException(403, { message: (error as Error).message });
|
|
1271
|
+
if (authorityFence === "authority_unattributed")
|
|
1272
|
+
return new HTTPException(409, { message: (error as Error).message });
|
|
1024
1273
|
return error;
|
|
1025
1274
|
}
|
|
1026
1275
|
|
|
1276
|
+
/** Structural check: the fence type lives in `@opengeni/db` and is raised deep
|
|
1277
|
+
* inside admission, so match it the same way the worker does. */
|
|
1278
|
+
function workspaceMutationAuthorityFenceCode(error: unknown): string | null {
|
|
1279
|
+
if (
|
|
1280
|
+
!(error instanceof Error) ||
|
|
1281
|
+
(error.name !== "SandboxWorkspaceMutationFencedError" &&
|
|
1282
|
+
error.name !== "SandboxRetainedProcessPromotionFencedError")
|
|
1283
|
+
) {
|
|
1284
|
+
return null;
|
|
1285
|
+
}
|
|
1286
|
+
const code = (error as Error & { code?: unknown }).code;
|
|
1287
|
+
return typeof code === "string" ? code : null;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1027
1290
|
export function isChannelARequestCancellation(error: unknown, waitSignal?: AbortSignal): boolean {
|
|
1028
1291
|
if (waitSignal?.aborted !== true) return false;
|
|
1029
1292
|
const isSignalReason = waitSignal.reason !== undefined && error === waitSignal.reason;
|
|
@@ -1053,7 +1316,21 @@ export function channelAOperationFailureDiagnostic(
|
|
|
1053
1316
|
errorCode: "sandbox_channel_a_provider_busy",
|
|
1054
1317
|
};
|
|
1055
1318
|
}
|
|
1056
|
-
if (error instanceof
|
|
1319
|
+
if (error instanceof SelfhostedControlError && error.payloadTooLarge) {
|
|
1320
|
+
return {
|
|
1321
|
+
reason: error.detail.direction === "request" ? "request_rejected" : "provider_unavailable",
|
|
1322
|
+
status: error.detail.direction === "request" ? 413 : 502,
|
|
1323
|
+
errorCode: "sandbox_channel_a_operation_failed",
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
if (error instanceof SandboxImageConflictError || error instanceof SandboxRigConflictError) {
|
|
1327
|
+
return {
|
|
1328
|
+
reason: "lifecycle_conflict",
|
|
1329
|
+
status: 409,
|
|
1330
|
+
errorCode: "sandbox_channel_a_lifecycle_conflict",
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
if (error instanceof ChannelAUnavailableError || error instanceof BrowserControlTransportError) {
|
|
1057
1334
|
return {
|
|
1058
1335
|
reason: "provider_unavailable",
|
|
1059
1336
|
status: 503,
|
|
@@ -1063,6 +1340,10 @@ export function channelAOperationFailureDiagnostic(
|
|
|
1063
1340
|
if (
|
|
1064
1341
|
error instanceof SandboxResumeIdentityMismatchError ||
|
|
1065
1342
|
error instanceof SandboxResumeIdentityUnavailableError ||
|
|
1343
|
+
error instanceof RoutingActiveRouteChangedError ||
|
|
1344
|
+
error instanceof RoutingWorkspaceRootChangedError ||
|
|
1345
|
+
error instanceof SelfhostedWorkspaceRootChangedError ||
|
|
1346
|
+
error instanceof ChannelAFileSystemRouteChangedError ||
|
|
1066
1347
|
(error instanceof HTTPException && error.status === 409)
|
|
1067
1348
|
) {
|
|
1068
1349
|
return {
|
|
@@ -1091,6 +1372,16 @@ export function channelAOperationFailureDiagnostic(
|
|
|
1091
1372
|
errorCode: "sandbox_channel_a_operation_failed",
|
|
1092
1373
|
};
|
|
1093
1374
|
}
|
|
1375
|
+
// An authority fence is a deliberate rejection, not a fault: keep it out of
|
|
1376
|
+
// the unexpected-failure signal that operators page on.
|
|
1377
|
+
const authorityFence = workspaceMutationAuthorityFenceCode(error);
|
|
1378
|
+
if (authorityFence === "authority_revoked" || authorityFence === "authority_unattributed") {
|
|
1379
|
+
return {
|
|
1380
|
+
reason: "request_rejected",
|
|
1381
|
+
status: authorityFence === "authority_revoked" ? 403 : 409,
|
|
1382
|
+
errorCode: "sandbox_channel_a_operation_failed",
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1094
1385
|
return {
|
|
1095
1386
|
reason: "unexpected",
|
|
1096
1387
|
status: 500,
|
|
@@ -1098,7 +1389,8 @@ export function channelAOperationFailureDiagnostic(
|
|
|
1098
1389
|
};
|
|
1099
1390
|
}
|
|
1100
1391
|
|
|
1101
|
-
|
|
1392
|
+
/** Exported for the telemetry contract tests; not a route surface. */
|
|
1393
|
+
export function observeChannelAOperationFailure(
|
|
1102
1394
|
services: ChannelAServices,
|
|
1103
1395
|
input: {
|
|
1104
1396
|
workspaceId: string;
|
|
@@ -1111,6 +1403,13 @@ function observeChannelAOperationFailure(
|
|
|
1111
1403
|
},
|
|
1112
1404
|
): void {
|
|
1113
1405
|
if (!services.observability) return;
|
|
1406
|
+
// A writer with no recorded authority is a compatibility lane, not a fault:
|
|
1407
|
+
// count the lane itself so an operator can see whether it is still live,
|
|
1408
|
+
// separately from the structural failure signal operators page on below.
|
|
1409
|
+
// Lane name only - never the workspace, sandbox group, backend, or operation.
|
|
1410
|
+
if (workspaceMutationAuthorityFenceCode(input.error) === "authority_unattributed") {
|
|
1411
|
+
recordTenancyCompatibilityLaneUse(services.observability, "workspace_writer_unattributed");
|
|
1412
|
+
}
|
|
1114
1413
|
const diagnostic = channelAOperationFailureDiagnostic(input.error, input.waitSignal);
|
|
1115
1414
|
const attributes = {
|
|
1116
1415
|
sandboxLeaseKey: sandboxLeaseTelemetryKey(input.workspaceId, input.sandboxGroupId),
|