@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
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InsightsCallsResponse,
|
|
3
|
+
InsightsUsageResponse,
|
|
4
|
+
OrganizationInsightsCallsQuery,
|
|
5
|
+
OrganizationInsightsUsageQuery,
|
|
6
|
+
WorkspaceInsightsCallsQuery,
|
|
7
|
+
WorkspaceInsightsUsageQuery,
|
|
8
|
+
} from "@opengeni/contracts/insights-usage";
|
|
9
|
+
import type { AccessContext } from "@opengeni/contracts";
|
|
10
|
+
import {
|
|
11
|
+
accountScopedApiKeyWorkspaceAuthority,
|
|
12
|
+
getInsightsUsage,
|
|
13
|
+
hasPermission,
|
|
14
|
+
listInsightsCalls,
|
|
15
|
+
requireAccessContext,
|
|
16
|
+
requireAccessGrant,
|
|
17
|
+
type ApiRouteDeps,
|
|
18
|
+
type InsightsQueryScope,
|
|
19
|
+
} from "@opengeni/core";
|
|
20
|
+
import {
|
|
21
|
+
currentSessionRlsActorIdentityKey,
|
|
22
|
+
InvalidInsightsCallsCursorError,
|
|
23
|
+
readInsightsResponseCacheFence,
|
|
24
|
+
} from "@opengeni/db";
|
|
25
|
+
import type { Context, Hono } from "hono";
|
|
26
|
+
import { createHash } from "node:crypto";
|
|
27
|
+
import { HTTPException } from "hono/http-exception";
|
|
28
|
+
import { requireSelectedAccount, withBillingUsageActor } from "./billing";
|
|
29
|
+
import { createInFlightCoalescer } from "./insights";
|
|
30
|
+
import {
|
|
31
|
+
createInsightsCredentialPartition,
|
|
32
|
+
createInsightsResponseCache,
|
|
33
|
+
insightsWithFriendlyTimeout,
|
|
34
|
+
} from "./insights-response-cache";
|
|
35
|
+
|
|
36
|
+
/** Keep repeated filters, but reject repeated scalar options in the strict schema. */
|
|
37
|
+
export function insightsQueryParameters(
|
|
38
|
+
query: Record<string, string[]>,
|
|
39
|
+
): Record<string, string | string[]> {
|
|
40
|
+
return Object.fromEntries(
|
|
41
|
+
Object.entries(query).map(([key, values]) => [key, values.length === 1 ? values[0]! : values]),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Frozen interim capabilities: a newer additive contract must not silently widen a raw query. */
|
|
46
|
+
export function insightsRawQuerySupported(
|
|
47
|
+
query: Record<string, unknown>,
|
|
48
|
+
organization: boolean,
|
|
49
|
+
calls: boolean,
|
|
50
|
+
): boolean {
|
|
51
|
+
const keys = new Set([
|
|
52
|
+
"range",
|
|
53
|
+
"provider",
|
|
54
|
+
"model",
|
|
55
|
+
"payer",
|
|
56
|
+
"projectId",
|
|
57
|
+
"person",
|
|
58
|
+
"rootSessionId",
|
|
59
|
+
"scheduleId",
|
|
60
|
+
"limit",
|
|
61
|
+
...(organization ? ["workspaceId"] : []),
|
|
62
|
+
...(calls ? ["cursor"] : ["groupBy", "seriesGroups"]),
|
|
63
|
+
]);
|
|
64
|
+
if (Object.keys(query).some((key) => !keys.has(key))) return false;
|
|
65
|
+
if (
|
|
66
|
+
query.range !== undefined &&
|
|
67
|
+
!new Set(["today", "week", "month", "30d", "90d", "ytd"]).has(String(query.range))
|
|
68
|
+
)
|
|
69
|
+
return false;
|
|
70
|
+
return (
|
|
71
|
+
query.groupBy === undefined ||
|
|
72
|
+
new Set([
|
|
73
|
+
"model",
|
|
74
|
+
"provider",
|
|
75
|
+
"payer",
|
|
76
|
+
"project",
|
|
77
|
+
"rootSession",
|
|
78
|
+
"person",
|
|
79
|
+
"schedule",
|
|
80
|
+
...(organization ? ["workspace"] : []),
|
|
81
|
+
]).has(String(query.groupBy))
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function organizationCacheAuthority(context: AccessContext, accountId: string) {
|
|
86
|
+
const key = accountScopedApiKeyWorkspaceAuthority(context);
|
|
87
|
+
return [
|
|
88
|
+
context.subjectId,
|
|
89
|
+
context.accountGrants
|
|
90
|
+
.filter((g) => g.accountId === accountId)
|
|
91
|
+
.map((g) => [g.subjectId, g.role, [...g.permissions].sort()]),
|
|
92
|
+
context.workspaceGrants
|
|
93
|
+
.filter((g) => g.accountId === accountId)
|
|
94
|
+
.map((g) => [g.workspaceId, g.subjectId, g.permissionMode, [...g.permissions].sort()])
|
|
95
|
+
.sort(),
|
|
96
|
+
key
|
|
97
|
+
? [key.accountId, key.permissionMode, [...key.permissions].sort(), key.workspaceScope]
|
|
98
|
+
: null,
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function rawUsageResponse(response: Awaited<ReturnType<typeof getInsightsUsage>>) {
|
|
103
|
+
const parsed = InsightsUsageResponse.parse(response);
|
|
104
|
+
// A newer contract can supply an additive default. Absence is a capability
|
|
105
|
+
// signal, so this raw implementation must not manufacture source support.
|
|
106
|
+
if (!Object.hasOwn(response.facets, "sources")) Reflect.deleteProperty(parsed.facets, "sources");
|
|
107
|
+
return parsed;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** The actor and its canonical detail authority are part of every sharing key. */
|
|
111
|
+
export function insightsUsageCoalesceKey(
|
|
112
|
+
scope: InsightsQueryScope,
|
|
113
|
+
query: unknown,
|
|
114
|
+
actor: string | null,
|
|
115
|
+
): string {
|
|
116
|
+
return JSON.stringify([
|
|
117
|
+
scope.accountId,
|
|
118
|
+
scope.workspaceId,
|
|
119
|
+
[...(scope.detailsWorkspaceIds ?? [])].sort(),
|
|
120
|
+
scope.detailsSharedWorkspaces === true,
|
|
121
|
+
query,
|
|
122
|
+
actor,
|
|
123
|
+
]);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Reuse canonical read grants, never infer session access from billing authority. */
|
|
127
|
+
export function organizationInsightsScope(
|
|
128
|
+
context: AccessContext,
|
|
129
|
+
accountId: string,
|
|
130
|
+
): InsightsQueryScope {
|
|
131
|
+
const authority = accountScopedApiKeyWorkspaceAuthority(context);
|
|
132
|
+
if (authority?.accountId === accountId) {
|
|
133
|
+
const readable = hasPermission(
|
|
134
|
+
authority.permissions,
|
|
135
|
+
"sessions:read",
|
|
136
|
+
authority.permissionMode,
|
|
137
|
+
);
|
|
138
|
+
return {
|
|
139
|
+
accountId,
|
|
140
|
+
workspaceId: null,
|
|
141
|
+
detailsWorkspaceIds:
|
|
142
|
+
readable && authority.workspaceScope.kind === "selected"
|
|
143
|
+
? [...authority.workspaceScope.workspaceIds].sort()
|
|
144
|
+
: [],
|
|
145
|
+
detailsSharedWorkspaces: readable && authority.workspaceScope.kind === "all",
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
accountId,
|
|
150
|
+
workspaceId: null,
|
|
151
|
+
detailsWorkspaceIds: [
|
|
152
|
+
...new Set(
|
|
153
|
+
context.workspaceGrants
|
|
154
|
+
.filter(
|
|
155
|
+
(grant) =>
|
|
156
|
+
grant.accountId === accountId &&
|
|
157
|
+
grant.subjectId === context.subjectId &&
|
|
158
|
+
hasPermission(grant.permissions, "sessions:read", grant.permissionMode),
|
|
159
|
+
)
|
|
160
|
+
.map((grant) => grant.workspaceId),
|
|
161
|
+
),
|
|
162
|
+
].sort(),
|
|
163
|
+
detailsSharedWorkspaces: false,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function callsWithValidation(
|
|
168
|
+
read: () => Promise<Awaited<ReturnType<typeof listInsightsCalls>>>,
|
|
169
|
+
) {
|
|
170
|
+
try {
|
|
171
|
+
return await read();
|
|
172
|
+
} catch (error) {
|
|
173
|
+
if (error instanceof InvalidInsightsCallsCursorError)
|
|
174
|
+
throw new HTTPException(400, { message: "invalid Insights calls cursor" });
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function registerInsightsUsageRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
180
|
+
const usage = createInFlightCoalescer<InsightsUsageResponse>();
|
|
181
|
+
const calls = createInFlightCoalescer<InsightsCallsResponse>();
|
|
182
|
+
const cache = createInsightsResponseCache();
|
|
183
|
+
const credentialPartition = createInsightsCredentialPartition();
|
|
184
|
+
async function cached<T>(
|
|
185
|
+
c: Context,
|
|
186
|
+
kind: "usage" | "calls",
|
|
187
|
+
scope: InsightsQueryScope,
|
|
188
|
+
query: object,
|
|
189
|
+
authority: unknown,
|
|
190
|
+
coalescer: { run(key: string, work: () => Promise<T>): Promise<T> },
|
|
191
|
+
read: () => Promise<T>,
|
|
192
|
+
): Promise<T> {
|
|
193
|
+
// This runs only after this request's normal authentication and scope checks.
|
|
194
|
+
const normalized = Object.fromEntries(
|
|
195
|
+
Object.entries(query)
|
|
196
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
197
|
+
.map(([key, value]) => [key, Array.isArray(value) ? [...new Set(value)].sort() : value]),
|
|
198
|
+
);
|
|
199
|
+
const key = createHash("sha256")
|
|
200
|
+
.update(
|
|
201
|
+
JSON.stringify([
|
|
202
|
+
kind,
|
|
203
|
+
authority,
|
|
204
|
+
insightsUsageCoalesceKey(scope, normalized, currentSessionRlsActorIdentityKey()),
|
|
205
|
+
credentialPartition(c.req.header("authorization"), c.req.header("cookie")),
|
|
206
|
+
new Date().toISOString().slice(0, 10),
|
|
207
|
+
]),
|
|
208
|
+
)
|
|
209
|
+
.digest("hex");
|
|
210
|
+
const fence = await readInsightsResponseCacheFence(deps.db, scope);
|
|
211
|
+
if (fence !== null) {
|
|
212
|
+
const hit = cache.get<T>(key, fence);
|
|
213
|
+
if (hit !== null) return hit;
|
|
214
|
+
}
|
|
215
|
+
return await coalescer.run(`${key}:${fence ?? "uncached"}`, async () => {
|
|
216
|
+
const response = await insightsWithFriendlyTimeout(read);
|
|
217
|
+
// Store validated successes only, and only if metadata remained stable.
|
|
218
|
+
if (fence !== null && fence === (await readInsightsResponseCacheFence(deps.db, scope)))
|
|
219
|
+
cache.put(key, fence, response);
|
|
220
|
+
return response;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
app.get("/v1/workspaces/:workspaceId/insights/usage", async (c) => {
|
|
225
|
+
const workspaceId = c.req.param("workspaceId");
|
|
226
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
227
|
+
const query = insightsQueryParameters(c.req.queries());
|
|
228
|
+
if (!insightsRawQuerySupported(query, false, false))
|
|
229
|
+
throw new HTTPException(400, { message: "unsupported interim Insights query" });
|
|
230
|
+
const parsed = WorkspaceInsightsUsageQuery.safeParse(query);
|
|
231
|
+
if (!parsed.success) throw new HTTPException(400, { message: "invalid Insights usage query" });
|
|
232
|
+
const scope = {
|
|
233
|
+
accountId: grant.accountId,
|
|
234
|
+
workspaceId,
|
|
235
|
+
detailsWorkspaceIds: hasPermission(grant.permissions, "sessions:read", grant.permissionMode)
|
|
236
|
+
? [workspaceId]
|
|
237
|
+
: [],
|
|
238
|
+
};
|
|
239
|
+
// The API's workspace middleware already binds/revalidates this grant's RLS actor.
|
|
240
|
+
const response = await cached(
|
|
241
|
+
c,
|
|
242
|
+
"usage",
|
|
243
|
+
scope,
|
|
244
|
+
parsed.data,
|
|
245
|
+
[grant.subjectId, grant.permissionMode, [...grant.permissions].sort()],
|
|
246
|
+
usage,
|
|
247
|
+
async () =>
|
|
248
|
+
rawUsageResponse(await getInsightsUsage(deps.db, { ...scope, query: parsed.data })),
|
|
249
|
+
);
|
|
250
|
+
c.header("cache-control", "private, no-store");
|
|
251
|
+
c.header("x-opengeni-insights-max-staleness-seconds", "60");
|
|
252
|
+
return c.json(response);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
app.get("/v1/workspaces/:workspaceId/insights/calls", async (c) => {
|
|
256
|
+
const workspaceId = c.req.param("workspaceId");
|
|
257
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
258
|
+
const query = insightsQueryParameters(c.req.queries());
|
|
259
|
+
if (!insightsRawQuerySupported(query, false, true))
|
|
260
|
+
throw new HTTPException(400, { message: "unsupported interim Insights query" });
|
|
261
|
+
const parsed = WorkspaceInsightsCallsQuery.safeParse(query);
|
|
262
|
+
if (!parsed.success) throw new HTTPException(400, { message: "invalid Insights calls query" });
|
|
263
|
+
const scope = {
|
|
264
|
+
accountId: grant.accountId,
|
|
265
|
+
workspaceId,
|
|
266
|
+
detailsWorkspaceIds: hasPermission(grant.permissions, "sessions:read", grant.permissionMode)
|
|
267
|
+
? [workspaceId]
|
|
268
|
+
: [],
|
|
269
|
+
};
|
|
270
|
+
const response = await cached(
|
|
271
|
+
c,
|
|
272
|
+
"calls",
|
|
273
|
+
scope,
|
|
274
|
+
parsed.data,
|
|
275
|
+
[grant.subjectId, grant.permissionMode, [...grant.permissions].sort()],
|
|
276
|
+
calls,
|
|
277
|
+
async () =>
|
|
278
|
+
InsightsCallsResponse.parse(
|
|
279
|
+
await callsWithValidation(() =>
|
|
280
|
+
listInsightsCalls(deps.db, { ...scope, query: parsed.data }),
|
|
281
|
+
),
|
|
282
|
+
),
|
|
283
|
+
);
|
|
284
|
+
c.header("cache-control", "private, no-store");
|
|
285
|
+
c.header("x-opengeni-insights-max-staleness-seconds", "60");
|
|
286
|
+
return c.json(response);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
app.get("/v1/organizations/:accountId/insights/usage", async (c) => {
|
|
290
|
+
const context = await requireAccessContext(c, deps);
|
|
291
|
+
const accountId = requireSelectedAccount(context, c.req.param("accountId"), "billing:read");
|
|
292
|
+
const query = insightsQueryParameters(c.req.queries());
|
|
293
|
+
if (!insightsRawQuerySupported(query, true, false))
|
|
294
|
+
throw new HTTPException(400, { message: "unsupported interim Insights query" });
|
|
295
|
+
const parsed = OrganizationInsightsUsageQuery.safeParse(query);
|
|
296
|
+
if (!parsed.success) throw new HTTPException(400, { message: "invalid Insights usage query" });
|
|
297
|
+
const scope = organizationInsightsScope(context, accountId);
|
|
298
|
+
const response = await withBillingUsageActor(deps, context, accountId, () =>
|
|
299
|
+
cached(
|
|
300
|
+
c,
|
|
301
|
+
"usage",
|
|
302
|
+
scope,
|
|
303
|
+
parsed.data,
|
|
304
|
+
organizationCacheAuthority(context, accountId),
|
|
305
|
+
usage,
|
|
306
|
+
async () =>
|
|
307
|
+
rawUsageResponse(await getInsightsUsage(deps.db, { ...scope, query: parsed.data })),
|
|
308
|
+
),
|
|
309
|
+
);
|
|
310
|
+
c.header("cache-control", "private, no-store");
|
|
311
|
+
c.header("x-opengeni-insights-max-staleness-seconds", "60");
|
|
312
|
+
return c.json(response);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
app.get("/v1/organizations/:accountId/insights/calls", async (c) => {
|
|
316
|
+
const context = await requireAccessContext(c, deps);
|
|
317
|
+
const accountId = requireSelectedAccount(context, c.req.param("accountId"), "billing:read");
|
|
318
|
+
const query = insightsQueryParameters(c.req.queries());
|
|
319
|
+
if (!insightsRawQuerySupported(query, true, true))
|
|
320
|
+
throw new HTTPException(400, { message: "unsupported interim Insights query" });
|
|
321
|
+
const parsed = OrganizationInsightsCallsQuery.safeParse(query);
|
|
322
|
+
if (!parsed.success) throw new HTTPException(400, { message: "invalid Insights calls query" });
|
|
323
|
+
const scope = organizationInsightsScope(context, accountId);
|
|
324
|
+
// Call readers intersect these canonical grants with current actor visibility.
|
|
325
|
+
const response = await withBillingUsageActor(deps, context, accountId, () =>
|
|
326
|
+
cached(
|
|
327
|
+
c,
|
|
328
|
+
"calls",
|
|
329
|
+
scope,
|
|
330
|
+
parsed.data,
|
|
331
|
+
organizationCacheAuthority(context, accountId),
|
|
332
|
+
calls,
|
|
333
|
+
async () =>
|
|
334
|
+
InsightsCallsResponse.parse(
|
|
335
|
+
await callsWithValidation(() =>
|
|
336
|
+
listInsightsCalls(deps.db, { ...scope, query: parsed.data }),
|
|
337
|
+
),
|
|
338
|
+
),
|
|
339
|
+
),
|
|
340
|
+
);
|
|
341
|
+
c.header("cache-control", "private, no-store");
|
|
342
|
+
c.header("x-opengeni-insights-max-staleness-seconds", "60");
|
|
343
|
+
return c.json(response);
|
|
344
|
+
});
|
|
345
|
+
}
|
package/src/routes/insights.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { InsightsRange, WorkspaceInsightsResponse } from "@opengeni/contracts";
|
|
2
2
|
import {
|
|
3
3
|
getWorkspaceInsights,
|
|
4
|
+
measureInsightsPhase,
|
|
5
|
+
workspaceInsightsPhaseMetricObserver,
|
|
4
6
|
normalizeWorkspaceInsightsFilter,
|
|
7
|
+
normalizeWorkspaceInsightsSessionScope,
|
|
5
8
|
requireAccessGrant,
|
|
9
|
+
scheduledTaskViewerForGrant,
|
|
6
10
|
WorkspaceInsightsFilterValidationError,
|
|
7
11
|
type ApiRouteDeps,
|
|
8
12
|
type WorkspaceInsightsFilterField,
|
|
9
13
|
} from "@opengeni/core";
|
|
14
|
+
import { currentSessionRlsActorIdentityKey } from "@opengeni/db";
|
|
10
15
|
import { workspaceInsightsMetricObserver } from "@opengeni/observability";
|
|
11
16
|
import type { Hono } from "hono";
|
|
12
17
|
import { HTTPException } from "hono/http-exception";
|
|
@@ -16,7 +21,9 @@ export function normalizeWorkspaceInsightsQueryFilter(
|
|
|
16
21
|
field: WorkspaceInsightsFilterField,
|
|
17
22
|
): string | null {
|
|
18
23
|
try {
|
|
19
|
-
return
|
|
24
|
+
return field === "rootSessionId" || field === "sessionId"
|
|
25
|
+
? normalizeWorkspaceInsightsSessionScope(value, field)
|
|
26
|
+
: normalizeWorkspaceInsightsFilter(value, field);
|
|
20
27
|
} catch (error) {
|
|
21
28
|
if (error instanceof WorkspaceInsightsFilterValidationError) {
|
|
22
29
|
throw new HTTPException(400, { message: error.message });
|
|
@@ -25,20 +32,82 @@ export function normalizeWorkspaceInsightsQueryFilter(
|
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Share one in-flight computation between identical concurrent callers.
|
|
37
|
+
*
|
|
38
|
+
* A reload, a second tab, or a retried fetch joins the rollup already running
|
|
39
|
+
* instead of starting another multi-second aggregate on the database.
|
|
40
|
+
* Authorization and filter validation still run per request before a caller
|
|
41
|
+
* may join; the map only ever holds running work. The caller supplies the
|
|
42
|
+
* complete sharing key, which must identify everything the result depends on.
|
|
43
|
+
*/
|
|
44
|
+
export function createInFlightCoalescer<T>(): {
|
|
45
|
+
run: (key: string, work: () => Promise<T>) => Promise<T>;
|
|
46
|
+
readonly size: number;
|
|
47
|
+
} {
|
|
48
|
+
const inFlight = new Map<string, Promise<T>>();
|
|
49
|
+
return {
|
|
50
|
+
run(key, work) {
|
|
51
|
+
const pending = inFlight.get(key);
|
|
52
|
+
if (pending) return pending;
|
|
53
|
+
const started: Promise<T> = work().finally(() => {
|
|
54
|
+
if (inFlight.get(key) === started) inFlight.delete(key);
|
|
55
|
+
});
|
|
56
|
+
inFlight.set(key, started);
|
|
57
|
+
return started;
|
|
58
|
+
},
|
|
59
|
+
get size() {
|
|
60
|
+
return inFlight.size;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Insights rows are filtered by the database RLS actor (private sessions are
|
|
67
|
+
* visible only to their owner), so two administrators of one workspace can
|
|
68
|
+
* legitimately receive different responses. The actor identity is part of
|
|
69
|
+
* the key; requests share work only when every visibility input is equal.
|
|
70
|
+
*/
|
|
71
|
+
export function workspaceInsightsCoalesceKey(input: {
|
|
72
|
+
workspaceId: string;
|
|
73
|
+
range: string;
|
|
74
|
+
provider: string | null;
|
|
75
|
+
model: string | null;
|
|
76
|
+
rootSessionId?: string | null;
|
|
77
|
+
sessionId?: string | null;
|
|
78
|
+
rlsActor: string | null;
|
|
79
|
+
}): string {
|
|
80
|
+
return JSON.stringify([
|
|
81
|
+
input.workspaceId,
|
|
82
|
+
input.range,
|
|
83
|
+
input.provider,
|
|
84
|
+
input.model,
|
|
85
|
+
input.rootSessionId ?? null,
|
|
86
|
+
input.sessionId ?? null,
|
|
87
|
+
input.rlsActor,
|
|
88
|
+
]);
|
|
89
|
+
}
|
|
90
|
+
|
|
28
91
|
export function registerInsightsRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
29
92
|
const observeRequest = workspaceInsightsMetricObserver(deps.observability);
|
|
93
|
+
const observePhase = workspaceInsightsPhaseMetricObserver(deps.observability);
|
|
94
|
+
const coalesce = createInFlightCoalescer<Awaited<ReturnType<typeof getWorkspaceInsights>>>();
|
|
30
95
|
app.get("/v1/workspaces/:workspaceId/insights", async (c) => {
|
|
31
96
|
const startedAtMs = performance.now();
|
|
32
97
|
const rangeRaw = c.req.query("range") ?? "week";
|
|
33
98
|
const providerRaw = c.req.query("provider");
|
|
34
99
|
const modelRaw = c.req.query("model");
|
|
100
|
+
const rootSessionIdRaw = c.req.query("rootSessionId");
|
|
101
|
+
const sessionIdRaw = c.req.query("sessionId");
|
|
35
102
|
let provider: string | null = null;
|
|
36
103
|
let model: string | null = null;
|
|
37
104
|
let outcome = "failed";
|
|
38
105
|
|
|
39
106
|
try {
|
|
40
107
|
const workspaceId = c.req.param("workspaceId");
|
|
41
|
-
await
|
|
108
|
+
const grant = await measureInsightsPhase(observePhase, "auth", () =>
|
|
109
|
+
requireAccessGrant(c, deps, workspaceId, "workspace:admin"),
|
|
110
|
+
);
|
|
42
111
|
|
|
43
112
|
const rangeParsed = InsightsRange.safeParse(rangeRaw);
|
|
44
113
|
if (!rangeParsed.success) {
|
|
@@ -48,13 +117,39 @@ export function registerInsightsRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
48
117
|
}
|
|
49
118
|
provider = normalizeWorkspaceInsightsQueryFilter(providerRaw, "provider");
|
|
50
119
|
model = normalizeWorkspaceInsightsQueryFilter(modelRaw, "model");
|
|
120
|
+
const rootSessionId = normalizeWorkspaceInsightsQueryFilter(
|
|
121
|
+
rootSessionIdRaw,
|
|
122
|
+
"rootSessionId",
|
|
123
|
+
);
|
|
124
|
+
const sessionId = normalizeWorkspaceInsightsQueryFilter(sessionIdRaw, "sessionId");
|
|
51
125
|
|
|
52
|
-
const response = await
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
126
|
+
const response = await coalesce.run(
|
|
127
|
+
workspaceInsightsCoalesceKey({
|
|
128
|
+
workspaceId,
|
|
129
|
+
range: rangeParsed.data,
|
|
130
|
+
provider,
|
|
131
|
+
model,
|
|
132
|
+
rootSessionId,
|
|
133
|
+
sessionId,
|
|
134
|
+
rlsActor: currentSessionRlsActorIdentityKey(),
|
|
135
|
+
}),
|
|
136
|
+
() =>
|
|
137
|
+
getWorkspaceInsights(
|
|
138
|
+
deps.db,
|
|
139
|
+
deps.settings,
|
|
140
|
+
{
|
|
141
|
+
workspaceId,
|
|
142
|
+
range: rangeParsed.data,
|
|
143
|
+
provider,
|
|
144
|
+
model,
|
|
145
|
+
rootSessionId,
|
|
146
|
+
sessionId,
|
|
147
|
+
viewerSubjectId: async () =>
|
|
148
|
+
(await scheduledTaskViewerForGrant(deps.db, grant, deps.settings)).subjectId,
|
|
149
|
+
},
|
|
150
|
+
observePhase,
|
|
151
|
+
),
|
|
152
|
+
);
|
|
58
153
|
c.header("cache-control", "private, no-store");
|
|
59
154
|
const result = c.json(WorkspaceInsightsResponse.parse(response));
|
|
60
155
|
outcome = "completed";
|
package/src/routes/install.ts
CHANGED
|
@@ -158,18 +158,53 @@ function bakedContentType(asset: string): string {
|
|
|
158
158
|
// BAKED_DIR is a fixed sibling, so the resolved path cannot escape the dir.
|
|
159
159
|
async function readBaked(asset: string): Promise<ArrayBuffer | null> {
|
|
160
160
|
const url = new URL(asset, BAKED_DIR);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
const runtime =
|
|
162
|
+
/^(?:opengeni-agent-browser|opengeni-computer-native|opengeni-browserd|opengeni-agent)-(.+?)(?:\.(?:sha256|minisig))?$/.exec(
|
|
163
|
+
asset,
|
|
164
|
+
);
|
|
165
|
+
if (runtime) {
|
|
166
|
+
const target = runtime[1]!;
|
|
167
|
+
const cohort = [
|
|
168
|
+
"opengeni-agent",
|
|
169
|
+
"opengeni-browserd",
|
|
170
|
+
"opengeni-agent-browser",
|
|
171
|
+
"opengeni-computer-native",
|
|
172
|
+
].flatMap((component) =>
|
|
173
|
+
["", ".sha256", ".minisig"].map((suffix) => `${component}-${target}${suffix}`),
|
|
174
|
+
);
|
|
175
|
+
const members = await Promise.all(
|
|
176
|
+
cohort.map(async (name) => {
|
|
177
|
+
try {
|
|
178
|
+
const info = await stat(new URL(name, BAKED_DIR));
|
|
179
|
+
return info.isFile() && info.size > 0 ? "complete" : "invalid";
|
|
180
|
+
} catch (error) {
|
|
181
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return "absent";
|
|
182
|
+
throw new HTTPException(503, { message: "baked interaction runtime is unavailable" });
|
|
183
|
+
}
|
|
184
|
+
}),
|
|
185
|
+
);
|
|
186
|
+
// A target is either wholly absent or wholly baked. A partial image cannot
|
|
187
|
+
// combine its agent with helpers or verification sidecars from an archive.
|
|
188
|
+
if (members.every((member) => member === "absent")) return null;
|
|
189
|
+
if (members.some((member) => member !== "complete")) {
|
|
190
|
+
throw new HTTPException(503, { message: "baked interaction runtime is incomplete" });
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
try {
|
|
194
|
+
const info = await stat(url);
|
|
195
|
+
if (!info.isFile()) return null;
|
|
196
|
+
} catch {
|
|
164
197
|
return null;
|
|
165
198
|
}
|
|
166
|
-
} catch {
|
|
167
|
-
return null;
|
|
168
199
|
}
|
|
169
200
|
// Return a standalone ArrayBuffer (a valid Response BodyInit). `readFile`'s
|
|
170
201
|
// Buffer may be a view into a larger pooled allocation, so copy out the exact
|
|
171
202
|
// byte range with `.slice` rather than handing over the backing store.
|
|
172
|
-
const buf = await readFile(url)
|
|
203
|
+
const buf = await readFile(url).catch(() => {
|
|
204
|
+
// Never redirect after selecting a baked cohort, even if a file becomes
|
|
205
|
+
// unreadable between the completeness check and the byte read.
|
|
206
|
+
throw new HTTPException(503, { message: "baked interaction runtime is unavailable" });
|
|
207
|
+
});
|
|
173
208
|
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
174
209
|
}
|
|
175
210
|
|
|
@@ -205,7 +240,11 @@ export function registerInstallRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
205
240
|
// otherwise 302 to the GitHub Release at `redirectUrl` (mac/windows + any
|
|
206
241
|
// un-baked asset). The baked path makes the agent the API enrolls against
|
|
207
242
|
// identical to the API that serves it — no version skew, no extra hop.
|
|
208
|
-
async function serveAsset(
|
|
243
|
+
async function serveAsset(
|
|
244
|
+
asset: string,
|
|
245
|
+
redirectUrl: string,
|
|
246
|
+
allowBaked: boolean,
|
|
247
|
+
): Promise<Response> {
|
|
209
248
|
const committed = COMMITTED_BINARY_ASSETS[asset];
|
|
210
249
|
if (committed) {
|
|
211
250
|
const buf = await readFile(new URL(committed.file, INSTALL_DIR));
|
|
@@ -218,7 +257,7 @@ export function registerInstallRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
218
257
|
},
|
|
219
258
|
});
|
|
220
259
|
}
|
|
221
|
-
const baked = await readBaked(asset);
|
|
260
|
+
const baked = allowBaked ? await readBaked(asset) : null;
|
|
222
261
|
if (baked !== null) {
|
|
223
262
|
return new Response(baked, {
|
|
224
263
|
status: 200,
|
|
@@ -251,7 +290,7 @@ export function registerInstallRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
251
290
|
if (!ASSET_NAME.test(asset)) {
|
|
252
291
|
throw new HTTPException(400, { message: "invalid asset name" });
|
|
253
292
|
}
|
|
254
|
-
return serveAsset(asset, `${releasesBase}/download/${stableAgentTag}/${asset}
|
|
293
|
+
return serveAsset(asset, `${releasesBase}/download/${stableAgentTag}/${asset}`, true);
|
|
255
294
|
});
|
|
256
295
|
|
|
257
296
|
// Signed self-update channel manifests. Each deployment exposes its own
|
|
@@ -296,7 +335,9 @@ export function registerInstallRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
|
296
335
|
message: "invalid version or asset name",
|
|
297
336
|
});
|
|
298
337
|
}
|
|
299
|
-
|
|
338
|
+
// A pinned release must never be substituted with this deployment's baked
|
|
339
|
+
// canary, even when its semver happens to match. The archive owns its bytes.
|
|
340
|
+
return serveAsset(asset, `${releasesBase}/download/agent-${versionSeg}/${asset}`, false);
|
|
300
341
|
});
|
|
301
342
|
}
|
|
302
343
|
|