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