@opengeni/api-router 0.30.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-grant-rls.d.ts +3 -0
- package/dist/admission-trace.d.ts +8 -0
- package/dist/api-websocket.d.ts +18 -0
- package/dist/app.d.ts +50 -2
- package/dist/app.js +12 -1
- package/dist/artifact-catalog-cursor.d.ts +27 -0
- package/dist/auth/managed-auth-attempt-context.d.ts +10 -0
- package/dist/auth/managed-auth-rate-limits.d.ts +167 -0
- package/dist/auth/managed-auth-session-adapter.d.ts +6 -0
- package/dist/auth/managed-auth.d.ts +102 -3
- package/dist/auth/managed-email.d.ts +29 -0
- package/dist/auth/managed-sign-in-notifications.d.ts +4 -0
- package/dist/auth/new-signups-gate.d.ts +23 -0
- package/dist/auth/organization-user-setup.d.ts +80 -0
- package/dist/auth/signup-funnel-metrics.d.ts +44 -0
- package/dist/browser-controller-authority.d.ts +1 -61
- package/dist/browser-ephemeral.d.ts +5 -0
- package/dist/browser-state-authority.d.ts +1 -27
- package/dist/chunk-6TZ5LG3O.js +123948 -0
- package/dist/chunk-6TZ5LG3O.js.map +1 -0
- package/dist/chunk-OGQDXVXY.js +18 -0
- package/dist/chunk-OGQDXVXY.js.map +1 -0
- package/dist/claude-subscription-account-conflicts.d.ts +1 -0
- package/dist/claude-subscription-account-usage.d.ts +39 -0
- package/dist/claude-subscription-oauth.d.ts +25 -0
- package/dist/claude-subscription-profile.d.ts +9 -0
- package/dist/claude-subscription-usage.d.ts +44 -0
- package/dist/claude-workspace-connection.d.ts +15 -0
- package/dist/codemode.d.ts +32 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-ownership.d.ts +54 -0
- package/dist/controller-data-plane.d.ts +32 -0
- package/dist/editable-artifact-source-session.d.ts +3 -0
- package/dist/editable-artifact-websocket.d.ts +10 -18
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/fatal-process-boundary.d.ts +25 -0
- package/dist/github-access.d.ts +31 -2
- package/dist/http/acting-person.d.ts +24 -0
- package/dist/http/api-contract-compat.d.ts +19 -0
- package/dist/http/api-error.d.ts +27 -1
- package/dist/http/cors.d.ts +17 -0
- package/dist/http/deprecation.d.ts +42 -0
- package/dist/http/interaction-control-error.d.ts +13 -0
- package/dist/http/keyed-admission.d.ts +12 -0
- package/dist/http/local-browser-boundary.d.ts +72 -0
- package/dist/http/metrics-listener.d.ts +22 -0
- package/dist/http/path-identifier.d.ts +17 -0
- package/dist/http/registered-route-label.d.ts +16 -0
- package/dist/http/request-body.d.ts +27 -0
- package/dist/http/request-source.d.ts +52 -0
- package/dist/http/sse.d.ts +17 -6
- package/dist/http/unmatched-route.d.ts +18 -0
- package/dist/http/user-content.d.ts +36 -0
- package/dist/http/websocket-upgrade-dispatch.d.ts +18 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +1091 -162
- package/dist/index.js.map +1 -1
- package/dist/integration-endpoint-test.d.ts +20 -0
- package/dist/integrations/api-integrations.d.ts +2 -2
- package/dist/integrations/atlassian.d.ts +29 -3
- package/dist/integrations/connect-authority.d.ts +1 -0
- package/dist/integrations/connect-callback-return.d.ts +6 -0
- package/dist/integrations/fiken.d.ts +16 -2
- package/dist/integrations/github-app-connect.d.ts +47 -0
- package/dist/integrations/github-installation-proof.d.ts +3 -0
- package/dist/integrations/github-lens-connect.d.ts +116 -0
- package/dist/integrations/github-skill-source.d.ts +1 -5
- package/dist/integrations/google-drive.d.ts +24 -0
- package/dist/integrations/integration-commit-authority.d.ts +13 -0
- package/dist/integrations/marketplace-plugin.d.ts +2691 -0
- package/dist/integrations/oauth-client.d.ts +178 -18
- package/dist/integrations/oauth-profiles.d.ts +222 -0
- package/dist/integrations/oauth-return-path.d.ts +1 -0
- package/dist/integrations/personal-github-repositories.d.ts +84 -0
- package/dist/integrations/personal-github.d.ts +42 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +19 -1
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +367 -12
- package/dist/integrations/slack-file-upload-flow.d.ts +62 -0
- package/dist/integrations/slack-install.d.ts +20 -0
- package/dist/integrations/slack-interactions.d.ts +107 -9
- package/dist/integrations/slack-mrkdwn.d.ts +41 -0
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/slack-session-defaults.d.ts +58 -0
- package/dist/integrations/slack-task-file-upload.d.ts +36 -0
- package/dist/integrations/social-oauth.d.ts +7 -0
- package/dist/interaction-agent-access.d.ts +15 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/interaction-metrics.d.ts +2 -0
- package/dist/mcp/action-catalog-types.d.ts +9 -0
- package/dist/mcp/action-catalog.gen.d.ts +2 -0
- package/dist/mcp/capability-account-readiness.d.ts +7 -0
- package/dist/mcp/child-read-evidence.d.ts +9 -0
- package/dist/mcp/command-read.d.ts +24 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/contract-input.d.ts +11 -0
- package/dist/mcp/documents.d.ts +7 -5
- package/dist/mcp/files.d.ts +2 -2
- package/dist/mcp/first-party-tool-permissions.d.ts +650 -0
- package/dist/mcp/knowledge-entries.d.ts +5 -0
- package/dist/mcp/orchestration-failure-diagnostic.d.ts +43 -0
- package/dist/mcp/receipts.d.ts +9 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-input.d.ts +1189 -0
- package/dist/mcp/scheduled-task-view.d.ts +22 -4
- package/dist/mcp/server.d.ts +255 -3
- package/dist/mcp/session-event-view.d.ts +94 -0
- package/dist/mcp/session-view.d.ts +66 -2
- package/dist/mcp/session-wait.d.ts +174 -0
- package/dist/mcp-oauth.d.ts +52 -0
- package/dist/model-catalog.d.ts +11 -31
- package/dist/observability.d.ts +3 -1
- package/dist/organization-mcp.d.ts +52 -0
- package/dist/organization-recovery-notifications.d.ts +41 -0
- package/dist/routes/analytics-consent.d.ts +26 -0
- package/dist/routes/api-integrations.d.ts +25 -0
- package/dist/routes/api-keys.d.ts +17 -0
- package/dist/routes/artifact-catalog.d.ts +6 -0
- package/dist/routes/automations.d.ts +19 -0
- package/dist/routes/billing.d.ts +49 -0
- package/dist/routes/browser-sessions.d.ts +59 -2
- package/dist/routes/claude-subscription-accounts.d.ts +3 -0
- package/dist/routes/claude-subscription-oauth.d.ts +3 -0
- package/dist/routes/client-errors.d.ts +146 -0
- package/dist/routes/codex.d.ts +76 -2
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/computer-sessions.d.ts +14 -0
- package/dist/routes/connect.d.ts +5 -0
- package/dist/routes/editable-artifacts.d.ts +2 -0
- package/dist/routes/external-identity-links.d.ts +6 -0
- package/dist/routes/feedback.d.ts +3 -0
- package/dist/routes/github-browser-pages.d.ts +12 -0
- package/dist/routes/github.d.ts +2 -0
- package/dist/routes/insights-response-cache.d.ts +10 -0
- package/dist/routes/insights-usage.d.ts +12 -0
- package/dist/routes/insights.d.ts +30 -1
- package/dist/routes/knowledge.d.ts +3 -0
- package/dist/routes/managed-auth-session-sets.d.ts +26 -0
- package/dist/routes/managed-onboarding.d.ts +29 -0
- package/dist/routes/managed-sign-in-methods.d.ts +6 -0
- package/dist/routes/model-connection-access.d.ts +3 -0
- package/dist/routes/organization-integration-policy.d.ts +3 -0
- package/dist/routes/organization-integrations.d.ts +6 -0
- package/dist/routes/organization-mcp-connections.d.ts +3 -0
- package/dist/routes/organization-model-providers.d.ts +3 -0
- package/dist/routes/organization-recovery.d.ts +19 -0
- package/dist/routes/organization-service-accounts.d.ts +3 -0
- package/dist/routes/organization-sessions.d.ts +26 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/session-artifact-associations.d.ts +4 -0
- package/dist/routes/session-history-imports.d.ts +9 -0
- package/dist/routes/sessions.d.ts +44 -6
- package/dist/routes/skill-content.d.ts +4 -0
- package/dist/routes/skill-install-authority.d.ts +6 -0
- package/dist/routes/subscription-account-pools.d.ts +34 -0
- package/dist/routes/subscription-pool-access.d.ts +16 -0
- package/dist/routes/supergrok.d.ts +6 -1
- package/dist/routes/usage-allowances.d.ts +12 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-artifacts.d.ts +2 -1
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-integrations.d.ts +35 -0
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspace-model-providers.d.ts +4 -0
- package/dist/routes/workspaces.d.ts +29 -0
- package/dist/sandbox/auth-callout.d.ts +8 -0
- package/dist/sandbox/channel-a.d.ts +19 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +9 -1
- package/dist/sandbox/machines.d.ts +5 -2
- package/dist/sandbox/metrics-ingestion.d.ts +28 -20
- package/dist/sandbox/rematerialize.d.ts +2 -0
- package/dist/sandbox/session-attach-variable-sets.d.ts +30 -0
- package/dist/sandbox/viewer.d.ts +26 -1
- package/dist/sandbox-file-artifacts.d.ts +50 -0
- package/dist/scheduled-task-deletion.d.ts +13 -0
- package/dist/session-create-observability.d.ts +5 -0
- package/dist/session-event-view-MPS2OZD3.js +292 -0
- package/dist/session-event-view-MPS2OZD3.js.map +1 -0
- package/dist/site-session-origin.d.ts +13 -0
- package/dist/site-uploads.d.ts +41 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/dist/temporal-schedule-sync.d.ts +26 -0
- package/dist/transcription/providers/xai-subscription.d.ts +1 -0
- package/dist/transcription/service.d.ts +2 -1
- package/dist/work-discovery-observability.d.ts +33 -0
- package/dist/workspace-artifact-content.d.ts +28 -0
- package/dist/workspace-artifact-provenance.d.ts +7 -0
- package/dist/workspace-delete-observability.d.ts +10 -0
- package/dist/workspace-deletion.d.ts +6 -0
- package/dist/workspace-state-projection.d.ts +3 -5
- package/dist/workspace-tool-gateway-observability.d.ts +17 -0
- package/dist/workspace-tool-gateway.d.ts +123 -0
- package/dist/workspace-webhook-dispatch.d.ts +26 -0
- package/package.json +23 -19
- package/src/access-grant-rls.ts +75 -0
- package/src/admission-trace.ts +14 -0
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +1967 -252
- package/src/artifact-catalog-cursor.ts +60 -0
- package/src/auth/managed-auth-attempt-context.ts +70 -0
- package/src/auth/managed-auth-rate-limits.ts +252 -0
- package/src/auth/managed-auth-session-adapter.ts +222 -0
- package/src/auth/managed-auth.ts +536 -60
- package/src/auth/managed-email.ts +174 -0
- package/src/auth/managed-sign-in-notifications.ts +81 -0
- package/src/auth/new-signups-gate.ts +49 -0
- package/src/auth/organization-user-setup.ts +307 -0
- package/src/auth/signup-funnel-metrics.ts +164 -0
- package/src/browser-controller-authority.ts +1 -186
- package/src/browser-ephemeral.ts +39 -0
- package/src/browser-state-authority.ts +1 -236
- package/src/claude-subscription-account-conflicts.ts +12 -0
- package/src/claude-subscription-account-usage.ts +48 -0
- package/src/claude-subscription-oauth.ts +362 -0
- package/src/claude-subscription-profile.ts +73 -0
- package/src/claude-subscription-usage.ts +97 -0
- package/src/claude-workspace-connection.ts +82 -0
- package/src/codemode.ts +194 -30
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-ownership.ts +199 -0
- package/src/controller-data-plane.ts +81 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +28 -3
- package/src/editable-artifact-production.ts +23 -7
- package/src/editable-artifact-source-session.ts +123 -0
- package/src/editable-artifact-websocket.ts +27 -21
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/fatal-process-boundary.ts +246 -0
- package/src/gateway-realtime.ts +1 -1
- package/src/github-access.ts +147 -5
- package/src/http/acting-person.ts +71 -0
- package/src/http/api-contract-compat.ts +49 -0
- package/src/http/api-error.ts +115 -1
- package/src/http/auth.ts +48 -0
- package/src/http/cors.ts +67 -0
- package/src/http/deprecation.ts +118 -0
- package/src/http/interaction-control-error.ts +164 -0
- package/src/http/keyed-admission.ts +29 -0
- package/src/http/local-browser-boundary.ts +343 -0
- package/src/http/metrics-listener.ts +57 -0
- package/src/http/path-identifier.ts +54 -0
- package/src/http/registered-route-label.ts +34 -0
- package/src/http/request-body.ts +127 -0
- package/src/http/request-source.ts +178 -0
- package/src/http/sse.ts +486 -132
- package/src/http/unmatched-route.ts +60 -0
- package/src/http/user-content.ts +158 -0
- package/src/http/websocket-upgrade-dispatch.ts +29 -0
- package/src/index.ts +157 -52
- package/src/integration-endpoint-test.ts +291 -0
- package/src/integrations/api-integrations.ts +98 -11
- package/src/integrations/atlassian.ts +474 -136
- package/src/integrations/connect-authority.ts +2 -0
- package/src/integrations/connect-callback-return.ts +86 -0
- package/src/integrations/fiken.ts +354 -64
- package/src/integrations/github-app-connect.ts +435 -0
- package/src/integrations/github-installation-proof.ts +60 -0
- package/src/integrations/github-lens-connect.ts +76 -0
- package/src/integrations/github-skill-source.ts +2 -142
- package/src/integrations/google-drive.ts +717 -225
- package/src/integrations/integration-commit-authority.ts +69 -0
- package/src/integrations/marketplace-plugin.ts +48 -0
- package/src/integrations/oauth-client.ts +1356 -459
- package/src/integrations/oauth-profiles.ts +537 -0
- package/src/integrations/oauth-return-path.ts +18 -0
- package/src/integrations/personal-github-repositories.ts +674 -0
- package/src/integrations/personal-github.ts +825 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +250 -22
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +963 -239
- package/src/integrations/slack-file-upload-flow.ts +147 -0
- package/src/integrations/slack-install.ts +83 -0
- package/src/integrations/slack-interactions.ts +3167 -474
- package/src/integrations/slack-mrkdwn.ts +193 -0
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/slack-session-defaults.ts +224 -0
- package/src/integrations/slack-task-file-upload.ts +323 -0
- package/src/integrations/social-oauth.ts +213 -15
- package/src/interaction-agent-access.ts +48 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/interaction-metrics.ts +30 -0
- package/src/mcp/action-catalog-types.ts +9 -0
- package/src/mcp/action-catalog.gen.ts +6696 -0
- package/src/mcp/capability-account-readiness.ts +17 -0
- package/src/mcp/child-read-evidence.ts +19 -0
- package/src/mcp/command-read.ts +109 -0
- package/src/mcp/company-profile-agent-admin.ts +198 -0
- package/src/mcp/contract-input.ts +141 -0
- package/src/mcp/documents.ts +65 -377
- package/src/mcp/editable-artifacts.ts +12 -6
- package/src/mcp/files.ts +80 -43
- package/src/mcp/first-party-tool-permissions.ts +305 -0
- package/src/mcp/knowledge-entries.ts +322 -0
- package/src/mcp/orchestration-failure-diagnostic.ts +43 -0
- package/src/mcp/receipts.ts +34 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-input.ts +76 -0
- package/src/mcp/scheduled-task-view.ts +44 -3
- package/src/mcp/server.ts +3030 -1267
- package/src/mcp/session-event-view.ts +383 -0
- package/src/mcp/session-view.ts +84 -3
- package/src/mcp/session-wait.ts +665 -0
- package/src/mcp-oauth.ts +1123 -0
- package/src/model-catalog.ts +91 -333
- package/src/observability.ts +15 -1
- package/src/organization-mcp.ts +397 -0
- package/src/organization-recovery-notifications.ts +103 -0
- package/src/routes/analytics-consent.ts +123 -0
- package/src/routes/api-integrations.ts +364 -74
- package/src/routes/api-keys.ts +336 -10
- package/src/routes/artifact-catalog.ts +279 -0
- package/src/routes/automations.ts +768 -0
- package/src/routes/billing.ts +461 -46
- package/src/routes/browser-sessions.ts +780 -112
- package/src/routes/canonical-human-identities.ts +90 -14
- package/src/routes/capabilities.ts +107 -6
- package/src/routes/channels.ts +20 -3
- package/src/routes/claude-subscription-accounts.ts +334 -0
- package/src/routes/claude-subscription-oauth.ts +142 -0
- package/src/routes/client-errors.ts +362 -0
- package/src/routes/codex.ts +833 -116
- package/src/routes/company-brain.ts +322 -0
- package/src/routes/company-profile.ts +65 -1
- package/src/routes/computer-sessions.ts +557 -106
- package/src/routes/connect.ts +1938 -0
- package/src/routes/connections.ts +1039 -349
- package/src/routes/documents.ts +488 -287
- package/src/routes/editable-artifacts.ts +79 -9
- package/src/routes/enrollments.ts +135 -39
- package/src/routes/environments.ts +154 -58
- package/src/routes/external-identity-links.ts +201 -0
- package/src/routes/feedback.ts +113 -0
- package/src/routes/files.ts +267 -33
- package/src/routes/github-browser-pages.ts +162 -0
- package/src/routes/github.ts +446 -144
- package/src/routes/insights-response-cache.ts +83 -0
- package/src/routes/insights-usage.ts +345 -0
- package/src/routes/insights.ts +153 -19
- package/src/routes/install.ts +133 -38
- package/src/routes/integration-facets.ts +107 -33
- package/src/routes/interaction-resources.ts +30 -3
- package/src/routes/knowledge.ts +488 -0
- package/src/routes/machines.ts +313 -15
- package/src/routes/managed-auth-session-sets.ts +1218 -0
- package/src/routes/managed-onboarding.ts +337 -0
- package/src/routes/managed-sign-in-methods.ts +433 -0
- package/src/routes/memory-slack-publications.ts +3 -2
- package/src/routes/model-connection-access.ts +208 -0
- package/src/routes/organization-integration-policy.ts +116 -0
- package/src/routes/organization-integrations.ts +326 -0
- package/src/routes/organization-mcp-connections.ts +178 -0
- package/src/routes/organization-memberships.ts +1019 -27
- package/src/routes/organization-model-providers.ts +293 -0
- package/src/routes/organization-recovery.ts +325 -0
- package/src/routes/organization-service-accounts.ts +128 -0
- package/src/routes/organization-sessions.ts +350 -0
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +370 -0
- package/src/routes/plugins.ts +251 -22
- package/src/routes/pr-review-github.ts +881 -0
- package/src/routes/pr-review.ts +622 -0
- package/src/routes/preference-registry.ts +12 -93
- package/src/routes/rigs.ts +167 -50
- package/src/routes/scheduled-tasks.ts +346 -41
- package/src/routes/session-artifact-associations.ts +87 -0
- package/src/routes/session-history-imports.ts +280 -0
- package/src/routes/sessions.ts +2306 -264
- package/src/routes/skill-content.ts +297 -0
- package/src/routes/skill-install-authority.ts +64 -0
- package/src/routes/skills.ts +62 -9
- package/src/routes/social.ts +46 -18
- package/src/routes/subscription-account-pools.ts +436 -0
- package/src/routes/subscription-pool-access.ts +126 -0
- package/src/routes/supergrok.ts +219 -303
- package/src/routes/transcription-recordings.ts +38 -3
- package/src/routes/transcriptions.ts +4 -0
- package/src/routes/usage-allowances.ts +378 -0
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/video-generation.ts +14 -10
- package/src/routes/workspace-artifacts.ts +275 -69
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-integrations.ts +576 -0
- package/src/routes/workspace-learning.ts +159 -0
- package/src/routes/workspace-model-providers.ts +148 -0
- package/src/routes/workspace-state.ts +38 -25
- package/src/routes/workspaces.ts +1004 -127
- package/src/sandbox/auth-callout.ts +96 -19
- package/src/sandbox/channel-a.ts +323 -24
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +81 -6
- package/src/sandbox/machines.ts +218 -76
- package/src/sandbox/metrics-ingestion.ts +411 -62
- package/src/sandbox/rematerialize.ts +121 -19
- package/src/sandbox/session-attach-variable-sets.ts +131 -0
- package/src/sandbox/viewer.ts +280 -25
- package/src/sandbox-file-artifacts.ts +413 -0
- package/src/scheduled-task-deletion.ts +138 -0
- package/src/session-create-observability.ts +46 -0
- package/src/session-realtime-context.ts +6 -3
- package/src/site-session-origin.ts +48 -0
- package/src/site-uploads.ts +224 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/src/temporal-schedule-sync.ts +74 -0
- package/src/transcription/providers/codex-subscription.ts +2 -0
- package/src/transcription/providers/openai.ts +1 -0
- package/src/transcription/providers/xai-subscription.ts +49 -3
- package/src/transcription/segmenter.ts +8 -2
- package/src/transcription/service.ts +43 -6
- package/src/work-discovery-observability.ts +121 -0
- package/src/workspace-artifact-content.ts +144 -0
- package/src/workspace-artifact-provenance.ts +104 -0
- package/src/workspace-delete-observability.ts +75 -0
- package/src/workspace-deletion.ts +73 -0
- package/src/workspace-state-projection.ts +18 -148
- package/src/workspace-tool-gateway-observability.ts +100 -0
- package/src/workspace-tool-gateway.ts +870 -0
- package/src/workspace-webhook-dispatch.ts +190 -0
- package/src/xai-subscription-auth.ts +9 -2
- package/dist/chunk-WCXHI3FF.js +0 -49920
- package/dist/chunk-WCXHI3FF.js.map +0 -1
- package/dist/routes/packs.d.ts +0 -3
- package/src/routes/packs.ts +0 -729
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentInstructionSaveRequest,
|
|
3
|
+
WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
|
|
4
|
+
WorkspaceInstructionPolicyTarget,
|
|
5
|
+
KnowledgeEntryListRequest,
|
|
6
|
+
KnowledgeSavePreparationRequest,
|
|
7
|
+
KnowledgeEntrySaveRequest,
|
|
8
|
+
KnowledgeTaskNotePromotionRequest,
|
|
9
|
+
type AccessGrant,
|
|
10
|
+
} from "@opengeni/contracts";
|
|
11
|
+
import {
|
|
12
|
+
prepareKnowledgeFile,
|
|
13
|
+
prepareKnowledgeSave,
|
|
14
|
+
retainKnowledgeMessage,
|
|
15
|
+
searchKnowledgeEntries,
|
|
16
|
+
requireLiveAgentAttemptAuthorization,
|
|
17
|
+
type ApiRouteDeps,
|
|
18
|
+
} from "@opengeni/core";
|
|
19
|
+
import {
|
|
20
|
+
archiveKnowledgeEntry,
|
|
21
|
+
confirmLegacyKnowledge,
|
|
22
|
+
confirmLegacyInstruction,
|
|
23
|
+
getKnowledgeEntry,
|
|
24
|
+
listKnowledgeEntries,
|
|
25
|
+
nestedPostgresSqlState,
|
|
26
|
+
saveKnowledgeEntry,
|
|
27
|
+
saveAgentInstruction,
|
|
28
|
+
getAgentInstruction,
|
|
29
|
+
promoteTaskNoteToKnowledge,
|
|
30
|
+
withSessionRlsActorContext,
|
|
31
|
+
type KnowledgeContext,
|
|
32
|
+
KnowledgeEntryIdRequiredError,
|
|
33
|
+
KnowledgeEntryIdTakenError,
|
|
34
|
+
} from "@opengeni/db";
|
|
35
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
36
|
+
import { z } from "zod";
|
|
37
|
+
|
|
38
|
+
/** One structured write and retrieval path, independent of the legacy Memory toggle. */
|
|
39
|
+
export function registerKnowledgeEntryTools(
|
|
40
|
+
server: McpServer,
|
|
41
|
+
deps: ApiRouteDeps,
|
|
42
|
+
grant: AccessGrant,
|
|
43
|
+
sessionId: string,
|
|
44
|
+
) {
|
|
45
|
+
if (grant.principalKind !== "agent_attempt") return;
|
|
46
|
+
async function run(
|
|
47
|
+
fn: (context: KnowledgeContext) => Promise<unknown>,
|
|
48
|
+
surface: "knowledge" | "instruction" = "knowledge",
|
|
49
|
+
) {
|
|
50
|
+
try {
|
|
51
|
+
const attempt = await requireLiveAgentAttemptAuthorization(deps.db, grant, sessionId);
|
|
52
|
+
const context: KnowledgeContext = {
|
|
53
|
+
accountId: grant.accountId,
|
|
54
|
+
workspaceId: grant.workspaceId,
|
|
55
|
+
actor: {
|
|
56
|
+
kind: "agent",
|
|
57
|
+
sessionId: attempt.callerSessionId,
|
|
58
|
+
turnId: attempt.turnId,
|
|
59
|
+
attemptId: attempt.attemptId,
|
|
60
|
+
executionGeneration: attempt.executionGeneration,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
const result = await withSessionRlsActorContext(
|
|
64
|
+
{
|
|
65
|
+
subjectId: attempt.subjectId,
|
|
66
|
+
initiatingHumanSubjectId: attempt.initiatingHumanSubjectId,
|
|
67
|
+
},
|
|
68
|
+
() => fn(context),
|
|
69
|
+
);
|
|
70
|
+
return { content: [{ type: "text" as const, text: JSON.stringify(result) }] };
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (
|
|
73
|
+
error instanceof KnowledgeEntryIdTakenError ||
|
|
74
|
+
error instanceof KnowledgeEntryIdRequiredError
|
|
75
|
+
) {
|
|
76
|
+
return {
|
|
77
|
+
isError: true,
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: "text" as const,
|
|
81
|
+
text: JSON.stringify({ error: { code: error.code, message: error.message } }),
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const state = nestedPostgresSqlState(error);
|
|
87
|
+
const message =
|
|
88
|
+
surface === "instruction"
|
|
89
|
+
? state === "40001"
|
|
90
|
+
? "This instruction changed. Read its current content and baseline, then retry the same intended edit against that exact state."
|
|
91
|
+
: state === "23505"
|
|
92
|
+
? "This instruction operation ID was already used with different input. Reuse it only for an exact retry."
|
|
93
|
+
: state === "42501"
|
|
94
|
+
? "The instruction change is unavailable in this task's scope or Agent learning policy. Off disables authoring, not the task. Do not ask for approval to continue."
|
|
95
|
+
: state === "22023" || state === "23514"
|
|
96
|
+
? `Invalid instruction change. Read the current instruction, use append for a new rule, or edit with one localized exact oldText match to update or remove text. Agents cannot replace the complete instruction. Each supplied text and the resulting instruction must stay within ${WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters, the same limit as the human editor.`
|
|
97
|
+
: "Workspace instructions are temporarily unavailable. Retry the same operation ID only if the prior change may have succeeded."
|
|
98
|
+
: state === "40001"
|
|
99
|
+
? "This entry changed. Read its current revision and retry your correction with the current version."
|
|
100
|
+
: state === "23505"
|
|
101
|
+
? "This operation ID was already used with different input. Reuse it only for an exact retry."
|
|
102
|
+
: state === "42501"
|
|
103
|
+
? "The entry, reference, or write is unavailable in this task's scope and Agent learning policy. Off disables saving, not your task. Do not ask for an approval to continue."
|
|
104
|
+
: state === "22023" || state === "23514"
|
|
105
|
+
? "Invalid Knowledge entry or relationship. Check the referenced IDs and revision before retrying."
|
|
106
|
+
: "Knowledge is temporarily unavailable. Your task can continue; retry the same operation ID if saving may have succeeded.";
|
|
107
|
+
return {
|
|
108
|
+
isError: true,
|
|
109
|
+
content: [
|
|
110
|
+
{
|
|
111
|
+
type: "text" as const,
|
|
112
|
+
text: JSON.stringify({ error: { code: state ?? "knowledge_unavailable", message } }),
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Compatibility recovery for tool selections persisted before the cutover.
|
|
119
|
+
// This name is absent from new defaults. No legacy proposal writer is registered.
|
|
120
|
+
server.registerTool(
|
|
121
|
+
"remember_confirm",
|
|
122
|
+
{
|
|
123
|
+
description:
|
|
124
|
+
"Finish an existing pre-migration remember confirmation after its exact human answered Save. Knowledge publishes the migrated entry; instruction proposals retain their original authority. This tool never creates new proposals.",
|
|
125
|
+
inputSchema: {
|
|
126
|
+
operationId: z.uuid(),
|
|
127
|
+
claimId: z.uuid().optional(),
|
|
128
|
+
proposalId: z.uuid().optional(),
|
|
129
|
+
decisionReceiptId: z.uuid().optional(),
|
|
130
|
+
humanInputRequestId: z.uuid(),
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
(input) =>
|
|
134
|
+
run(async (context) => {
|
|
135
|
+
if (input.claimId && !input.proposalId && !input.decisionReceiptId) {
|
|
136
|
+
return confirmLegacyKnowledge(deps.db, context, {
|
|
137
|
+
operationId: input.operationId,
|
|
138
|
+
claimId: input.claimId,
|
|
139
|
+
humanInputRequestId: input.humanInputRequestId,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (input.proposalId && input.decisionReceiptId && !input.claimId) {
|
|
143
|
+
return confirmLegacyInstruction(deps.db, context, {
|
|
144
|
+
operationId: input.operationId,
|
|
145
|
+
proposalId: input.proposalId,
|
|
146
|
+
decisionReceiptId: input.decisionReceiptId,
|
|
147
|
+
humanInputRequestId: input.humanInputRequestId,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
throw new Error("Pass exactly one existing confirmation target");
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
153
|
+
server.registerTool(
|
|
154
|
+
"knowledge_prepare_save",
|
|
155
|
+
{
|
|
156
|
+
description:
|
|
157
|
+
"Before saving useful lasting Knowledge, find related published entries and unapproved proposals, and fetch the full authorized collection map with descriptions and parent IDs in one read-only call. First choose the destination: future behavior belongs in instruction_policy_save for short always-on workspace rules or skill_save for applicable procedures and preferences, not Knowledge. Supply a concise subject and the proposed fact, decision, requirement or incident. Search spans all authorized collections. Reuse an existing entry when unchanged; read its current content before a correction, preserve evidence, or create only when distinct. Pending matches are unapproved. Choose collections from this map in your writable scope. A collection may have both published and pending versions. If collections.complete is false, continue with collectionCursors=collections.nextCursors; never mistake a partial catalog for the whole map. Long descriptions explicitly report truncation and can be read with knowledge_get. This call saves and approves nothing.",
|
|
158
|
+
inputSchema: KnowledgeSavePreparationRequest.shape,
|
|
159
|
+
},
|
|
160
|
+
(input) =>
|
|
161
|
+
run((context) =>
|
|
162
|
+
prepareKnowledgeSave(
|
|
163
|
+
deps.db,
|
|
164
|
+
context,
|
|
165
|
+
input,
|
|
166
|
+
() => deps.getDocumentServices().embedder,
|
|
167
|
+
undefined,
|
|
168
|
+
deps.settings,
|
|
169
|
+
),
|
|
170
|
+
),
|
|
171
|
+
);
|
|
172
|
+
server.registerTool(
|
|
173
|
+
"knowledge_search",
|
|
174
|
+
{
|
|
175
|
+
description:
|
|
176
|
+
"Find Knowledge from useful findings and explicitly retained reference sources. Supporting chat/file evidence is excluded from ordinary published discovery; set includeEvidence=true only when searching that evidence deliberately. Use a concise subject or entity name first (for example Acme); omit scope to search all authorized scopes. If a query returns no entries, retry the key name alone in the same scope or browse groups before concluding the information is absent. Default view=published is accepted knowledge. Also search view=needs_review before creating or updating entries, to reuse pending findings and collections from earlier tasks. Pending revisions are unapproved proposals, not accepted facts or instructions; preserve that status when discussing them. Reading a proposal never approves it. Personal tasks search the verified user's personal and authorized shared Knowledge; shared tasks search shared Knowledge.",
|
|
177
|
+
inputSchema: KnowledgeEntryListRequest.omit({
|
|
178
|
+
view: true,
|
|
179
|
+
sessionId: true,
|
|
180
|
+
reviewBatchId: true,
|
|
181
|
+
rootOnly: true,
|
|
182
|
+
}).extend({ view: z.enum(["published", "needs_review"]).default("published") }).shape,
|
|
183
|
+
},
|
|
184
|
+
(input) =>
|
|
185
|
+
run((context) =>
|
|
186
|
+
searchKnowledgeEntries(
|
|
187
|
+
deps.db,
|
|
188
|
+
context,
|
|
189
|
+
input,
|
|
190
|
+
() => deps.getDocumentServices().embedder,
|
|
191
|
+
deps.settings,
|
|
192
|
+
),
|
|
193
|
+
),
|
|
194
|
+
);
|
|
195
|
+
server.registerTool(
|
|
196
|
+
"knowledge_browse",
|
|
197
|
+
{
|
|
198
|
+
description:
|
|
199
|
+
"Browse Knowledge groups or the entries in a group. A group collects references to the same entries across sources and can contain nested groups. Pass its groupId to list direct members. Membership never grants access or duplicates content.",
|
|
200
|
+
inputSchema: {
|
|
201
|
+
groupId: z.uuid().optional(),
|
|
202
|
+
view: z.enum(["published", "needs_review"]).default("published"),
|
|
203
|
+
cursor: z.string().optional(),
|
|
204
|
+
limit: z.number().int().positive().max(50).optional(),
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
(input) =>
|
|
208
|
+
run((context) =>
|
|
209
|
+
listKnowledgeEntries(deps.db, context, {
|
|
210
|
+
...input,
|
|
211
|
+
...(input.groupId ? {} : { kind: "group" as const }),
|
|
212
|
+
}),
|
|
213
|
+
),
|
|
214
|
+
);
|
|
215
|
+
server.registerTool(
|
|
216
|
+
"knowledge_get",
|
|
217
|
+
{
|
|
218
|
+
description:
|
|
219
|
+
"Read a Knowledge entry, its exact revision, evidence and collections. Default view=published reads accepted information. Use view=needs_review to inspect a pending proposal before improving it; revision.outcome=pending means unapproved. Pending information must not be presented as accepted or used to activate instructions. Source text is paginated. Use returned IDs and current version when citing, relating or correcting an entry.",
|
|
220
|
+
inputSchema: {
|
|
221
|
+
entryId: z.uuid(),
|
|
222
|
+
revisionId: z.uuid().optional(),
|
|
223
|
+
view: z.enum(["published", "needs_review"]).default("published"),
|
|
224
|
+
offset: z.number().int().nonnegative().default(0),
|
|
225
|
+
maxChars: z.number().int().positive().max(16_000).default(8_000),
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
(input) =>
|
|
229
|
+
run(async (context) => {
|
|
230
|
+
const record = await getKnowledgeEntry(deps.db, context, input.entryId, {
|
|
231
|
+
revisionId: input.revisionId,
|
|
232
|
+
view: input.view,
|
|
233
|
+
});
|
|
234
|
+
if (!record) return { found: false };
|
|
235
|
+
const content = record.revision.entry.content;
|
|
236
|
+
const end = Math.min(content.length, input.offset + input.maxChars);
|
|
237
|
+
return {
|
|
238
|
+
found: true,
|
|
239
|
+
...record,
|
|
240
|
+
revision: {
|
|
241
|
+
...record.revision,
|
|
242
|
+
entry: { ...record.revision.entry, content: content.slice(input.offset, end) },
|
|
243
|
+
},
|
|
244
|
+
contentRange: {
|
|
245
|
+
start: input.offset,
|
|
246
|
+
end,
|
|
247
|
+
total: content.length,
|
|
248
|
+
nextOffset: end < content.length ? end : null,
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
}),
|
|
252
|
+
);
|
|
253
|
+
server.registerTool(
|
|
254
|
+
"knowledge_retain_file",
|
|
255
|
+
{
|
|
256
|
+
description:
|
|
257
|
+
"Retain source text from an existing uploaded file only when it supports useful lasting Knowledge, or the user wants the file kept as a reusable reference. Ordinary chat attachments are not automatically added to Knowledge. Use purpose=evidence (default) for supporting material, or purpose=reference for a deliberately retained searchable reference. The original stays in Files. Read the image itself before drawing visual conclusions; OCR text is only evidence. Repeated calls reuse the same source and do not change its purpose, duplicate review requests or revive rejected/archived sources. To make previously retained evidence a searchable reference, read its current revision with knowledge_get and use knowledge_save to set source.purpose=reference while preserving content and links. Selected findings are optional separate knowledge_save entries with evidence pointing to the returned revision. A pending receipt never pauses the task.",
|
|
258
|
+
inputSchema: {
|
|
259
|
+
fileId: z.uuid(),
|
|
260
|
+
purpose: z.enum(["evidence", "reference"]).default("evidence"),
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
({ fileId, purpose }) => run((context) => prepareKnowledgeFile(deps, context, fileId, purpose)),
|
|
264
|
+
);
|
|
265
|
+
server.registerTool(
|
|
266
|
+
"knowledge_retain_message",
|
|
267
|
+
{
|
|
268
|
+
description:
|
|
269
|
+
"Retain the exact text of a user message as supporting evidence only after identifying useful lasting Knowledge to save. Do not retain routine approvals, acknowledgments, task instructions or status chatter merely because they occurred. The source stays out of ordinary Knowledge discovery and can be read through its evidence link. Use when a user supplies or confirms a durable fact, before saving a finding based on it. Omit messageId for the user message that triggered this turn, or pass an earlier user message event ID from this same conversation. The server copies the actual message, preserves its identity and follows this task's learning policy. Repeated calls reuse the source. Cite the returned entryId/revisionId as evidence in knowledge_save, with location.messageIds=[messageId]. Retaining a message does not prove every statement in it or approve a pending finding.",
|
|
270
|
+
inputSchema: { messageId: z.uuid().optional() },
|
|
271
|
+
},
|
|
272
|
+
({ messageId }) => run((context) => retainKnowledgeMessage(deps.db, context, messageId)),
|
|
273
|
+
);
|
|
274
|
+
server.registerTool(
|
|
275
|
+
"knowledge_save",
|
|
276
|
+
{
|
|
277
|
+
description:
|
|
278
|
+
"Retain retrieval-only facts, decisions, requirements, incidents or notes, or deliberately selected reference sources, not a behavioral preference or instruction for future sessions. Use instruction_policy_save for short always-on workspace rules and skill_save for applicable procedures and behavioral preferences; do not store them here as facts such as 'the user prefers concise replies', even if those destinations are unavailable or require review. First use knowledge_prepare_save when available (otherwise search published and needs_review Knowledge and browse collections). Skip unchanged duplicates; improve an existing entry when the subject is the same. Do not save routine approvals, acknowledgments, temporary instructions, screenshots or OCR merely because they occurred. State the reusable finding with enough context for a future task, preserve uncertainty and evidence, and place it in the relevant existing collections. Do this autonomously when useful for future work. Choose kind by content: source for retained original text; fact for a specific claim (the label is not verification); decision for a choice made and its reasoning; requirement for a need or constraint; incident for a problem with cause, fix and outcome when known; note for other useful context. Choose the closest kind without asking the user to classify it. A group is a collection about a customer, product, system or subject, not a finding type. Search published and needs_review views for an existing entry and relevant group before creating one, use groupIds to link entries across sources, and reuse an entry in multiple groups instead of copying it. Nest collections by setting a group entry's groupIds to its parent collections; keep the hierarchy shallow and useful, and never create circular membership. To create, omit entryId and pass expectedVersion 0; the returned entryId identifies the new entry. To correct or reorganize, pass an existing entryId and its current version. Source text and selected facts are independent entries, not mandatory duplicate stages. Evidence pins another entry's exact revision. When a user supplies or confirms a fact, retain the actual message with knowledge_retain_message and cite the returned revision; do not leave its provenance only in prose. Preserve existing evidence and relationships on corrections unless they are specifically no longer applicable; a contradictory original remains useful evidence of what changed. Use the same operationId only for an exact retry. Agent learning decides publication: published is available immediately; pending is saved for review and your task continues without an approval prompt. Do not turn Knowledge into instructions or Skills.",
|
|
279
|
+
inputSchema: KnowledgeEntrySaveRequest.omit({ scope: true }).shape,
|
|
280
|
+
},
|
|
281
|
+
(input) => run((context) => saveKnowledgeEntry(deps.db, context, input)),
|
|
282
|
+
);
|
|
283
|
+
server.registerTool(
|
|
284
|
+
"knowledge_archive",
|
|
285
|
+
{
|
|
286
|
+
description:
|
|
287
|
+
"Archive obsolete Knowledge while preserving its history. Prefer a correction when an entry still has useful information. Requires the current entry version and follows this task's Agent learning policy.",
|
|
288
|
+
inputSchema: {
|
|
289
|
+
operationId: z.uuid(),
|
|
290
|
+
entryId: z.uuid(),
|
|
291
|
+
expectedVersion: z.number().int().positive(),
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
(input) => run((context) => archiveKnowledgeEntry(deps.db, context, input)),
|
|
295
|
+
);
|
|
296
|
+
server.registerTool(
|
|
297
|
+
"instruction_policy_get",
|
|
298
|
+
{
|
|
299
|
+
description:
|
|
300
|
+
"Read the current standing instruction and exact baseline for one target before every change. Preserve unrelated rules exactly. Reading remains available when agent authoring is Off.",
|
|
301
|
+
inputSchema: { target: WorkspaceInstructionPolicyTarget },
|
|
302
|
+
},
|
|
303
|
+
(input) => run((context) => getAgentInstruction(deps.db, context, input.target), "instruction"),
|
|
304
|
+
);
|
|
305
|
+
server.registerTool(
|
|
306
|
+
"instruction_policy_save",
|
|
307
|
+
{
|
|
308
|
+
description: `Change a concise standing workspace instruction through this task's Agent learning policy. Use for short always-on behavior such as 'Keep replies concise; expand when asked', within the intended workspace scope; active instructions enter applicable prompts without Knowledge retrieval. Read the current policy first and submit its exact baseline. Use editMode=append by default for a new rule; it preserves the current content and adds one blank-line separator. Use edit with a localized oldText that occurs exactly once and newText to update or remove only that passage. Agents cannot replace the complete instruction; direct the user to the manual workspace-instruction editor for a whole-policy rewrite. Each supplied text and the resulting instruction are limited to ${WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters, the same limit as the human editor. Facts and incidents belong in knowledge_save and reusable procedures or context-specific preferences in skill_save. Preserve personal scope rather than creating a workspace-wide rule. Review first saves an inactive revision and returns pending; continue the task without an approval question. Report the actual receipt; Knowledge is not a workaround for Off, pending review, unavailable scope or size limits.`,
|
|
309
|
+
inputSchema: AgentInstructionSaveRequest.shape,
|
|
310
|
+
},
|
|
311
|
+
(input) => run((context) => saveAgentInstruction(deps.db, context, input), "instruction"),
|
|
312
|
+
);
|
|
313
|
+
server.registerTool(
|
|
314
|
+
"task_note_promote_knowledge",
|
|
315
|
+
{
|
|
316
|
+
description:
|
|
317
|
+
"Retain one active task note as durable Knowledge with its exact text and origin, only for retrieval-only information. Do not promote behavior rules or preferences to Knowledge; use instruction_policy_save for short always-on workspace rules or skill_save for applicable procedures and preferences, under their own scope and learning policy. Omit entryId; the returned entryId identifies the new entry. The note stays temporary and unchanged; this creates one Knowledge entry in this task's scope, governed by the same learning policy. Pending review never pauses the task. Use knowledge_save for a selected or rewritten finding instead.",
|
|
318
|
+
inputSchema: KnowledgeTaskNotePromotionRequest.shape,
|
|
319
|
+
},
|
|
320
|
+
(input) => run((context) => promoteTaskNoteToKnowledge(deps.db, context, input)),
|
|
321
|
+
);
|
|
322
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ApiRouteDeps } from "@opengeni/core";
|
|
2
|
+
import { failureDiagnostic, type FailureDiagnosticInput } from "@opengeni/observability";
|
|
3
|
+
|
|
4
|
+
type OrchestrationTool = "session_create" | "session_send_message" | "session_steer";
|
|
5
|
+
type CallerAttempt = {
|
|
6
|
+
sessionId: string;
|
|
7
|
+
turnId: string;
|
|
8
|
+
attemptId: string;
|
|
9
|
+
executionGeneration: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/** Caller identity comes only from the signed grant, never tool arguments. */
|
|
13
|
+
export function orchestrationFailureDiagnostic(
|
|
14
|
+
deps: Pick<ApiRouteDeps, "settings" | "observability">,
|
|
15
|
+
tool: OrchestrationTool,
|
|
16
|
+
error: unknown,
|
|
17
|
+
caller: CallerAttempt | null,
|
|
18
|
+
) {
|
|
19
|
+
const input: FailureDiagnosticInput = {
|
|
20
|
+
code: "mcp_orchestration_failed",
|
|
21
|
+
stage: `mcp.${tool}`,
|
|
22
|
+
retryDecision: "unknown",
|
|
23
|
+
error,
|
|
24
|
+
...(caller ?? {}),
|
|
25
|
+
};
|
|
26
|
+
const diagnostic = failureDiagnostic(input, deps.settings.deploymentRevision);
|
|
27
|
+
let diagnosticExport: "disabled" | "queued" | "unavailable" = "disabled";
|
|
28
|
+
if (deps.settings.observabilityDiagnosticsEndpoint) {
|
|
29
|
+
diagnosticExport = "unavailable";
|
|
30
|
+
try {
|
|
31
|
+
const id = deps.observability?.recordFailureDiagnostic({
|
|
32
|
+
...input,
|
|
33
|
+
diagnosticId: diagnostic.diagnosticId,
|
|
34
|
+
});
|
|
35
|
+
if (id === diagnostic.diagnosticId) diagnosticExport = "queued";
|
|
36
|
+
} catch {
|
|
37
|
+
// Evidence export cannot change the original error or replay the operation.
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Self-contained safe facts survive the ordinary failed-tool receipt even when
|
|
41
|
+
// the optional protected sink is disabled. Queued is not proof of delivery.
|
|
42
|
+
return { diagnostic, diagnosticExport };
|
|
43
|
+
}
|
package/src/mcp/receipts.ts
CHANGED
|
@@ -26,6 +26,40 @@ export function mcpMutationReceipt(input: McpMutationReceiptInput): McpMutationR
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export function sessionControlMutationReceipt(input: {
|
|
30
|
+
operation: "session_pause" | "session_resume";
|
|
31
|
+
sessionId: string;
|
|
32
|
+
state: string;
|
|
33
|
+
receiptId: string;
|
|
34
|
+
timestamp: string;
|
|
35
|
+
outcome: "changed" | "unchanged" | "replayed";
|
|
36
|
+
interruptionCount: number;
|
|
37
|
+
}): McpMutationReceiptType {
|
|
38
|
+
return mcpMutationReceipt({
|
|
39
|
+
operation: input.operation,
|
|
40
|
+
committed: true,
|
|
41
|
+
outcome:
|
|
42
|
+
input.outcome === "changed"
|
|
43
|
+
? "updated"
|
|
44
|
+
: input.outcome === "unchanged"
|
|
45
|
+
? "unchanged"
|
|
46
|
+
: "replayed",
|
|
47
|
+
changed: input.outcome === "changed",
|
|
48
|
+
resource: {
|
|
49
|
+
type: "session",
|
|
50
|
+
id: input.sessionId,
|
|
51
|
+
state: input.state,
|
|
52
|
+
},
|
|
53
|
+
relatedResources: [{ type: "session_command_receipt", id: input.receiptId }],
|
|
54
|
+
timestamp: input.timestamp,
|
|
55
|
+
idempotency: {
|
|
56
|
+
status: input.outcome === "replayed" ? "replayed" : "applied",
|
|
57
|
+
},
|
|
58
|
+
facts: { interruptionCount: input.interruptionCount },
|
|
59
|
+
nextAction: { tool: "session_get", arguments: { sessionId: input.sessionId } },
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
29
63
|
export type SessionCreateReceiptResult = {
|
|
30
64
|
session: {
|
|
31
65
|
id: string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Serve one first-party MCP POST and bind the tool handlers' `extra.signal` to
|
|
5
|
+
* the HTTP client's connection.
|
|
6
|
+
*
|
|
7
|
+
* The API builds a fresh transport plus `McpServer` per POST, so an MCP
|
|
8
|
+
* `notifications/cancelled` from the worker would land on a different Protocol
|
|
9
|
+
* instance and never reach the handler. The only cancellation evidence this
|
|
10
|
+
* process can observe is the HTTP request's own abort (`Request.signal`, which
|
|
11
|
+
* Bun fires when the client disconnects). Closing the transport runs the SDK
|
|
12
|
+
* `Protocol._onclose`, which aborts every in-flight request handler's
|
|
13
|
+
* controller, so a blocking tool such as `session_wait` stops promptly when the
|
|
14
|
+
* worker drops the call (Steer, Pause, turn interruption).
|
|
15
|
+
*
|
|
16
|
+
* In JSON-response mode the SDK's `handleRequest` promise never settles once
|
|
17
|
+
* its stream mapping is cleared, so the race resolves a client-gone response
|
|
18
|
+
* instead of leaving the route handler pending.
|
|
19
|
+
*/
|
|
20
|
+
export async function handleMcpRequestWithClientAbort(
|
|
21
|
+
transport: Pick<WebStandardStreamableHTTPServerTransport, "handleRequest" | "close">,
|
|
22
|
+
request: Request,
|
|
23
|
+
clientSignal: AbortSignal | undefined,
|
|
24
|
+
): Promise<Response> {
|
|
25
|
+
if (!clientSignal) return await transport.handleRequest(request);
|
|
26
|
+
const clientGone = () => new Response(null, { status: 499 });
|
|
27
|
+
if (clientSignal.aborted) {
|
|
28
|
+
await transport.close().catch(() => undefined);
|
|
29
|
+
return clientGone();
|
|
30
|
+
}
|
|
31
|
+
let onAbort: (() => void) | null = null;
|
|
32
|
+
const aborted = new Promise<Response>((resolve) => {
|
|
33
|
+
onAbort = () => {
|
|
34
|
+
void transport.close().catch(() => undefined);
|
|
35
|
+
resolve(clientGone());
|
|
36
|
+
};
|
|
37
|
+
clientSignal.addEventListener("abort", onAbort, { once: true });
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
return await Promise.race([transport.handleRequest(request), aborted]);
|
|
41
|
+
} finally {
|
|
42
|
+
if (onAbort) clientSignal.removeEventListener("abort", onAbort);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CreateScheduledTaskRequest,
|
|
3
|
+
ScheduledTaskAgentConfigInput,
|
|
4
|
+
ScheduledTaskRunMode,
|
|
5
|
+
} from "@opengeni/contracts";
|
|
6
|
+
import { z } from "zod/v4";
|
|
7
|
+
|
|
8
|
+
/** The calling session is supplied by the signed grant, never by model text. */
|
|
9
|
+
export function resolveScheduledTaskCreateInput(
|
|
10
|
+
input: Record<string, unknown>,
|
|
11
|
+
sessionId: string | null,
|
|
12
|
+
) {
|
|
13
|
+
const runMode =
|
|
14
|
+
input.runMode ?? (input.targetSessionId || sessionId ? "existing_session" : undefined);
|
|
15
|
+
const targetSessionId =
|
|
16
|
+
input.targetSessionId ?? (runMode === "existing_session" ? sessionId : undefined);
|
|
17
|
+
if (!runMode)
|
|
18
|
+
throw new Error(
|
|
19
|
+
"Choose an existing chat or explicitly select reusable_session or new_session_per_run for a separate agent",
|
|
20
|
+
);
|
|
21
|
+
if (runMode === "existing_session" && !targetSessionId)
|
|
22
|
+
throw new Error("Choose the chat that should receive scheduled messages");
|
|
23
|
+
return CreateScheduledTaskRequest.parse({
|
|
24
|
+
...input,
|
|
25
|
+
runMode,
|
|
26
|
+
...(targetSessionId ? { targetSessionId } : {}),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function scheduledTaskCreateToolInput() {
|
|
31
|
+
return z
|
|
32
|
+
.object({
|
|
33
|
+
...CreateScheduledTaskRequest.options[1].out.shape,
|
|
34
|
+
runMode: ScheduledTaskRunMode.optional().describe(
|
|
35
|
+
"Omit to schedule a message in this chat. Choose reusable_session or new_session_per_run only when the user requests a separate agent.",
|
|
36
|
+
),
|
|
37
|
+
targetSessionId: z
|
|
38
|
+
.string()
|
|
39
|
+
.uuid()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("Destination chat. Omitted existing-session destinations use the calling chat."),
|
|
42
|
+
prompt: ScheduledTaskAgentConfigInput.shape.prompt
|
|
43
|
+
.optional()
|
|
44
|
+
.describe(
|
|
45
|
+
"Message to send to an existing chat at each occurrence. The chat supplies its model, tools and machine.",
|
|
46
|
+
),
|
|
47
|
+
agentConfig: z
|
|
48
|
+
.object(ScheduledTaskAgentConfigInput.shape)
|
|
49
|
+
.omit({ slackBotChannelId: true })
|
|
50
|
+
.strict()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe(
|
|
53
|
+
"Creation settings for a separate scheduled agent. For an existing chat, supply prompt instead.",
|
|
54
|
+
),
|
|
55
|
+
})
|
|
56
|
+
.omit({ agentLearning: true, connectionAuthorities: true })
|
|
57
|
+
.strict();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Validate the original call, before projection defaults can add fields from
|
|
61
|
+
// the separate-agent branch to the existing-chat message branch.
|
|
62
|
+
export function scheduledTaskCreateToolValidation(sessionId: string | null) {
|
|
63
|
+
return z.record(z.string(), z.unknown()).superRefine((input, context) => {
|
|
64
|
+
try {
|
|
65
|
+
resolveScheduledTaskCreateInput(input, sessionId);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error instanceof z.ZodError)
|
|
68
|
+
for (const issue of error.issues) context.addIssue({ ...issue });
|
|
69
|
+
else
|
|
70
|
+
context.addIssue({
|
|
71
|
+
code: "custom",
|
|
72
|
+
message: error instanceof Error ? error.message : "Invalid schedule destination",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
@@ -301,6 +301,7 @@ function toolIdentity(
|
|
|
301
301
|
kind: tool.kind,
|
|
302
302
|
id: id.value,
|
|
303
303
|
...(tool.optional !== undefined ? { optional: tool.optional } : {}),
|
|
304
|
+
...(tool.eager !== undefined ? { eager: tool.eager } : {}),
|
|
304
305
|
},
|
|
305
306
|
truncatedFieldCount: Number(id.truncated),
|
|
306
307
|
};
|
|
@@ -308,6 +309,9 @@ function toolIdentity(
|
|
|
308
309
|
|
|
309
310
|
export function scheduledTaskMcpSummary(task: ScheduledTask) {
|
|
310
311
|
const action = task.action ?? ({ kind: "agent_turn" } as const);
|
|
312
|
+
const inheritsSessionSettings =
|
|
313
|
+
task.runMode === "existing_session" ||
|
|
314
|
+
(task.runMode === "reusable_session" && Boolean(task.reusableSessionId));
|
|
311
315
|
const name = projectScheduledTaskUtf8(task.name, SCHEDULED_TASK_NAME_MAX_BYTES);
|
|
312
316
|
const schedule = projectScheduledTaskSchedule(task.schedule);
|
|
313
317
|
const model = task.agentConfig.model
|
|
@@ -318,6 +322,7 @@ export function scheduledTaskMcpSummary(task: ScheduledTask) {
|
|
|
318
322
|
const result = {
|
|
319
323
|
id: task.id,
|
|
320
324
|
name: name.value,
|
|
325
|
+
executionDigest: task.executionDigest,
|
|
321
326
|
status: task.status,
|
|
322
327
|
schedule: schedule.schedule,
|
|
323
328
|
runMode: task.runMode,
|
|
@@ -349,9 +354,10 @@ export function scheduledTaskMcpSummary(task: ScheduledTask) {
|
|
|
349
354
|
createdAt: createdAt.value,
|
|
350
355
|
updatedAt: updatedAt.value,
|
|
351
356
|
configuration: {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
357
|
+
source: inheritsSessionSettings ? "target_session" : "task_defaults",
|
|
358
|
+
model: inheritsSessionSettings ? null : (model?.value ?? null),
|
|
359
|
+
reasoningEffort: inheritsSessionSettings ? null : (task.agentConfig.reasoningEffort ?? null),
|
|
360
|
+
sandboxBackend: inheritsSessionSettings ? null : (task.agentConfig.sandboxBackend ?? null),
|
|
355
361
|
hasGoal: task.agentConfig.goal !== undefined,
|
|
356
362
|
promptBytes: Buffer.byteLength(task.agentConfig.prompt, "utf8"),
|
|
357
363
|
resourceCount: task.agentConfig.resources.length,
|
|
@@ -380,6 +386,41 @@ export function scheduledTaskMcpSummary(task: ScheduledTask) {
|
|
|
380
386
|
return result;
|
|
381
387
|
}
|
|
382
388
|
|
|
389
|
+
/** Exact bounded text; JSON escapes preserve even legacy lone UTF-16 units. */
|
|
390
|
+
export function scheduledTaskPromptPage(
|
|
391
|
+
task: ScheduledTask,
|
|
392
|
+
offset: number,
|
|
393
|
+
expectedExecutionDigest?: string,
|
|
394
|
+
) {
|
|
395
|
+
if (offset > 0 && !expectedExecutionDigest)
|
|
396
|
+
throw new Error("Continue with the executionDigest from the first prompt page");
|
|
397
|
+
if (expectedExecutionDigest !== undefined && expectedExecutionDigest !== task.executionDigest)
|
|
398
|
+
throw new Error("Scheduled task changed. Restart the prompt read at offset 0.");
|
|
399
|
+
const text = task.agentConfig.prompt;
|
|
400
|
+
if (!Number.isInteger(offset) || offset < 0 || offset > text.length)
|
|
401
|
+
throw new Error("Invalid prompt offset");
|
|
402
|
+
const splitsPair = (at: number) =>
|
|
403
|
+
at > 0 &&
|
|
404
|
+
at < text.length &&
|
|
405
|
+
/[\uD800-\uDBFF]/.test(text[at - 1]!) &&
|
|
406
|
+
/[\uDC00-\uDFFF]/.test(text[at]!);
|
|
407
|
+
if (splitsPair(offset))
|
|
408
|
+
throw new Error("Prompt offset splits a surrogate pair; use nextOffset from the previous page");
|
|
409
|
+
let end = Math.min(text.length, offset + 2048);
|
|
410
|
+
if (splitsPair(end)) end -= 1;
|
|
411
|
+
return {
|
|
412
|
+
id: task.id,
|
|
413
|
+
executionDigest: task.executionDigest,
|
|
414
|
+
prompt: {
|
|
415
|
+
text: text.slice(offset, end),
|
|
416
|
+
offset,
|
|
417
|
+
nextOffset: end < text.length ? end : null,
|
|
418
|
+
totalLength: text.length,
|
|
419
|
+
unit: "utf16" as const,
|
|
420
|
+
},
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
|
|
383
424
|
function buildScheduledTaskDetailMcp(
|
|
384
425
|
task: ScheduledTask,
|
|
385
426
|
budget: DetailBudget,
|