@opengeni/contracts 0.44.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-authored-durable-text.d.ts +70 -0
- package/dist/agent-config.d.ts +869 -0
- package/dist/agent-instruction-changes.d.ts +110 -0
- package/dist/agent-learning.d.ts +243 -0
- package/dist/agent-topology.d.ts +292 -0
- package/dist/allowance-refusal.d.ts +9 -0
- package/dist/allowance-refusal.js +50 -0
- package/dist/allowance-refusal.js.map +1 -0
- package/dist/analytics-consent-report.d.ts +19 -0
- package/dist/analytics-consent-report.js +10 -0
- package/dist/analytics-consent-report.js.map +1 -0
- package/dist/api-key-presets.d.ts +19 -0
- package/dist/artifact-catalog.d.ts +161 -0
- package/dist/artifacts.d.ts +135 -11
- package/dist/atlassian-native-retirement.d.ts +16 -0
- package/dist/atlassian-native-retirement.js +30 -0
- package/dist/atlassian-native-retirement.js.map +1 -0
- package/dist/atlassian.d.ts +2 -0
- package/dist/atlassian.js +27 -11
- package/dist/browser-storage.d.ts +5 -0
- package/dist/browser-storage.js +9 -0
- package/dist/browser-storage.js.map +1 -0
- package/dist/bundled-skills.d.ts +40 -0
- package/dist/canonical-human-identities.d.ts +157 -0
- package/dist/canonical-human-identities.js +23 -0
- package/dist/canonical-human-identities.js.map +1 -0
- package/dist/chunk-2ACYHZFB.js +292 -0
- package/dist/chunk-2ACYHZFB.js.map +1 -0
- package/dist/chunk-2VORLN2R.js +353 -0
- package/dist/chunk-2VORLN2R.js.map +1 -0
- package/dist/{chunk-Y3MLSLB4.js → chunk-3SIZGL3O.js} +42 -30
- package/dist/chunk-3SIZGL3O.js.map +1 -0
- package/dist/chunk-46KLD2UH.js +186 -0
- package/dist/chunk-46KLD2UH.js.map +1 -0
- package/dist/chunk-4JGHSSB7.js +11 -0
- package/dist/chunk-4JGHSSB7.js.map +1 -0
- package/dist/{chunk-52SGB2QO.js → chunk-5IXYF6XN.js} +50 -10
- package/dist/chunk-5IXYF6XN.js.map +1 -0
- package/dist/chunk-BCS7WHCK.js +139 -0
- package/dist/chunk-BCS7WHCK.js.map +1 -0
- package/dist/chunk-EK7NDGFR.js +128 -0
- package/dist/chunk-EK7NDGFR.js.map +1 -0
- package/dist/{chunk-5UDNP7AO.js → chunk-FZ6BXQHL.js} +78 -38
- package/dist/chunk-FZ6BXQHL.js.map +1 -0
- package/dist/chunk-GRG7PHWQ.js +25 -0
- package/dist/chunk-GRG7PHWQ.js.map +1 -0
- package/dist/chunk-JUFK3T4Q.js +80 -0
- package/dist/chunk-JUFK3T4Q.js.map +1 -0
- package/dist/chunk-KHHZTBP7.js +11 -0
- package/dist/chunk-KHHZTBP7.js.map +1 -0
- package/dist/chunk-KR2V42UZ.js +187 -0
- package/dist/chunk-KR2V42UZ.js.map +1 -0
- package/dist/chunk-MZLBPKFE.js +168 -0
- package/dist/chunk-MZLBPKFE.js.map +1 -0
- package/dist/{chunk-H5BVCZKF.js → chunk-NRMCVHAU.js} +6 -5
- package/dist/chunk-NRMCVHAU.js.map +1 -0
- package/dist/{chunk-TZ6YEYN4.js → chunk-NVJMJWLL.js} +3 -1
- package/dist/chunk-NVJMJWLL.js.map +1 -0
- package/dist/chunk-O77VSFYZ.js +70 -0
- package/dist/chunk-O77VSFYZ.js.map +1 -0
- package/dist/chunk-PX3VCKAU.js +29 -0
- package/dist/chunk-PX3VCKAU.js.map +1 -0
- package/dist/chunk-QR5D2IQC.js +61 -0
- package/dist/chunk-QR5D2IQC.js.map +1 -0
- package/dist/chunk-RJ76DRPO.js +117 -0
- package/dist/chunk-RJ76DRPO.js.map +1 -0
- package/dist/chunk-RKX3NQYS.js +28 -0
- package/dist/chunk-RKX3NQYS.js.map +1 -0
- package/dist/{chunk-FJBG5E4O.js → chunk-SIOU2K4U.js} +45 -22
- package/dist/chunk-SIOU2K4U.js.map +1 -0
- package/dist/chunk-TSCDAGET.js +75 -0
- package/dist/chunk-TSCDAGET.js.map +1 -0
- package/dist/{chunk-LSB7GRLG.js → chunk-TXTQIYCV.js} +15 -11
- package/dist/chunk-TXTQIYCV.js.map +1 -0
- package/dist/chunk-X7ETVO4P.js +26544 -0
- package/dist/chunk-X7ETVO4P.js.map +1 -0
- package/dist/{chunk-CADSX6UN.js → chunk-Y3KNXVTD.js} +2 -2
- package/dist/chunk-YBW5JSA3.js +251 -0
- package/dist/chunk-YBW5JSA3.js.map +1 -0
- package/dist/chunk-YRXAWWCU.js +45 -0
- package/dist/chunk-YRXAWWCU.js.map +1 -0
- package/dist/claude-provider-account-authority.d.ts +18 -0
- package/dist/claude-subscription-oauth.d.ts +42 -0
- package/dist/claude-subscription-usage.d.ts +159 -0
- package/dist/client-error-report.d.ts +109 -0
- package/dist/client-error-report.js +87 -0
- package/dist/client-error-report.js.map +1 -0
- package/dist/code-search.d.ts +52 -0
- package/dist/code-search.js +40 -0
- package/dist/code-search.js.map +1 -0
- package/dist/codex-provider-account-authority.d.ts +23 -0
- package/dist/codex-provider-account-authority.js +23 -0
- package/dist/codex-provider-account-authority.js.map +1 -0
- package/dist/company-brain-governed-writes.d.ts +475 -0
- package/dist/company-brain.d.ts +336 -0
- package/dist/company-profile.d.ts +566 -0
- package/dist/connect.d.ts +325 -0
- package/dist/connect.js +191 -0
- package/dist/connect.js.map +1 -0
- package/dist/connection-account-label.d.ts +2 -0
- package/dist/connection-account-label.js +35 -0
- package/dist/connection-account-label.js.map +1 -0
- package/dist/connection-authority.d.ts +193 -0
- package/dist/connection-authority.js +50 -0
- package/dist/connection-authority.js.map +1 -0
- package/dist/connector-attachments.d.ts +95 -0
- package/dist/connector-attachments.js +51 -0
- package/dist/connector-attachments.js.map +1 -0
- package/dist/connector-tool-permissions.d.ts +73 -0
- package/dist/direct-model-provider.d.ts +36 -0
- package/dist/editable-artifact-codec-registry.d.ts +16 -7
- package/dist/editable-artifact-codec-registry.js +19 -9
- package/dist/editable-artifact-committed-transaction.d.ts +2 -2
- package/dist/editable-artifact-committed-transaction.js +2 -2
- package/dist/editable-artifact-live.d.ts +11 -12
- package/dist/editable-artifact-live.js +110 -45
- package/dist/editable-artifact-live.js.map +1 -1
- package/dist/editable-artifact-serialized-commit.d.ts +2 -1
- package/dist/editable-artifact-serialized-commit.js +8 -7
- package/dist/editable-artifact-versions.d.ts +20 -5
- package/dist/editable-artifact-versions.js +23 -5
- package/dist/editable-artifacts.d.ts +2 -0
- package/dist/editable-artifacts.js +48 -36
- package/dist/external-identities.d.ts +784 -0
- package/dist/external-identities.js +44 -0
- package/dist/external-identities.js.map +1 -0
- package/dist/feedback.d.ts +51 -0
- package/dist/github-repository-contracts.d.ts +36 -0
- package/dist/github-repository-contracts.js +59 -0
- package/dist/github-repository-contracts.js.map +1 -0
- package/dist/github-repository.d.ts +14 -0
- package/dist/github-repository.js +36 -0
- package/dist/github-repository.js.map +1 -0
- package/dist/google-drive.d.ts +90 -1
- package/dist/google-drive.js +91 -15
- package/dist/google-drive.js.map +1 -1
- package/dist/governed-learning-activation.d.ts +154 -0
- package/dist/governed-learning-evaluator.d.ts +152 -0
- package/dist/host-mcp-bindings.d.ts +326 -0
- package/dist/host-mcp-bindings.js +252 -0
- package/dist/host-mcp-bindings.js.map +1 -0
- package/dist/image-generation.d.ts +1 -0
- package/dist/index.d.ts +27574 -5374
- package/dist/index.js +2531 -177
- package/dist/insights-usage.d.ts +877 -0
- package/dist/insights-usage.js +509 -0
- package/dist/insights-usage.js.map +1 -0
- package/dist/interaction.d.ts +1752 -13
- package/dist/knowledge-entries.d.ts +982 -0
- package/dist/knowledge-preparation.d.ts +237 -0
- package/dist/knowledge.d.ts +740 -0
- package/dist/managed-auth-session-sets.d.ts +241 -0
- package/dist/managed-auth-session-sets.js +191 -0
- package/dist/managed-auth-session-sets.js.map +1 -0
- package/dist/managed-sign-in-methods.d.ts +56 -0
- package/dist/managed-sign-in-methods.js +46 -0
- package/dist/managed-sign-in-methods.js.map +1 -0
- package/dist/mcp-catalog-limits.d.ts +2 -0
- package/dist/mcp-endpoint.d.ts +7 -0
- package/dist/mcp-endpoint.js +9 -0
- package/dist/mcp-endpoint.js.map +1 -0
- package/dist/mcp-oauth.d.ts +71 -0
- package/dist/modal-native-proof-v2.d.ts +587 -0
- package/dist/modal-native-proof-v2.js +37 -0
- package/dist/modal-native-proof-v2.js.map +1 -0
- package/dist/model-availability.d.ts +15 -0
- package/dist/model-connection-access.d.ts +24 -0
- package/dist/model-context-inspector.d.ts +329 -0
- package/dist/model-display.d.ts +38 -0
- package/dist/model-display.js +134 -0
- package/dist/model-display.js.map +1 -0
- package/dist/model-picker-order.d.ts +25 -0
- package/dist/model-picker-order.js +42 -0
- package/dist/model-picker-order.js.map +1 -0
- package/dist/organization-access.d.ts +231 -0
- package/dist/organization-access.js +34 -0
- package/dist/organization-access.js.map +1 -0
- package/dist/organization-integration-policy.d.ts +27 -0
- package/dist/organization-membership-lifecycle.d.ts +1022 -0
- package/dist/organization-model-usage.d.ts +146 -0
- package/dist/organization-model-usage.js +67 -0
- package/dist/organization-model-usage.js.map +1 -0
- package/dist/organization-recovery.d.ts +337 -0
- package/dist/organization-recovery.js +37 -0
- package/dist/organization-recovery.js.map +1 -0
- package/dist/organization-usage.d.ts +138 -0
- package/dist/permissions.d.ts +54 -0
- package/dist/personal-github.d.ts +320 -0
- package/dist/personal-github.js +222 -0
- package/dist/personal-github.js.map +1 -0
- package/dist/plugin-discovery.d.ts +35 -0
- package/dist/plugin-discovery.js +7 -0
- package/dist/plugin-discovery.js.map +1 -0
- package/dist/preference-registry.d.ts +44 -1
- package/dist/product-analytics.d.ts +113 -0
- package/dist/product-lifecycle-facts.d.ts +73 -0
- package/dist/remember.d.ts +350 -0
- package/dist/retained-output.d.ts +8 -0
- package/dist/sandbox-file-artifacts.d.ts +57 -0
- package/dist/sandbox-provider-command.d.ts +113 -0
- package/dist/sandbox-recovery.d.ts +146 -0
- package/dist/sandbox-snapshots.d.ts +39 -0
- package/dist/session-final-reply.d.ts +6 -0
- package/dist/session-final-reply.js +9 -0
- package/dist/session-final-reply.js.map +1 -0
- package/dist/session-goal-reports.d.ts +21 -0
- package/dist/session-history-import.d.ts +947 -0
- package/dist/session-list-entries.d.ts +4 -0
- package/dist/session-list-entries.js +51 -0
- package/dist/session-list-entries.js.map +1 -0
- package/dist/session-mcp-projections.d.ts +215 -0
- package/dist/session-message-search.d.ts +68 -0
- package/dist/session-titles.d.ts +68 -0
- package/dist/session-titles.js +25 -0
- package/dist/session-titles.js.map +1 -0
- package/dist/session-topology-primitives.d.ts +22 -0
- package/dist/signup-attribution.d.ts +39 -0
- package/dist/site-request-headers.test.d.ts +1 -0
- package/dist/site-session-http.d.ts +11 -0
- package/dist/site-session-http.js +11 -0
- package/dist/site-session-http.js.map +1 -0
- package/dist/skill-catalog-context.d.ts +7 -0
- package/dist/skill-files.d.ts +12 -0
- package/dist/skill-metadata.d.ts +9 -0
- package/dist/skill-use.d.ts +61 -0
- package/dist/skills.d.ts +185 -0
- package/dist/slack-bot-scopes.d.ts +46 -21
- package/dist/slack-bot-scopes.js +14 -3
- package/dist/slack-rest-mcp.d.ts +31 -0
- package/dist/slack-rest-mcp.js +19 -0
- package/dist/slack-rest-mcp.js.map +1 -0
- package/dist/slack-task-policy.d.ts +294 -0
- package/dist/spreadsheet-artifact-commands.d.ts +2 -3
- package/dist/spreadsheet-artifact-commands.js +4 -2
- package/dist/spreadsheet-artifact-query.js +3 -2
- package/dist/subscription-account-pools.d.ts +292 -0
- package/dist/task-notes.d.ts +169 -0
- package/dist/tool-catalog.d.ts +286 -0
- package/dist/tool-result-spill.d.ts +16 -0
- package/dist/usage-allowances.d.ts +285 -0
- package/dist/usage-allowances.js +49 -0
- package/dist/usage-allowances.js.map +1 -0
- package/dist/video-generation.d.ts +51 -0
- package/dist/video-generation.js +9 -1
- package/dist/work-claims.d.ts +411 -0
- package/dist/workspace-instruction-policies.d.ts +94 -0
- package/dist/workspace-integration-wire.d.ts +36 -0
- package/dist/workspace-integration-wire.js +23 -0
- package/dist/workspace-integration-wire.js.map +1 -0
- package/dist/workspace-integrations.d.ts +948 -0
- package/dist/workspace-learning-administration.d.ts +289 -0
- package/dist/workspace-learning-policy.d.ts +1 -1
- package/dist/workspace-state.d.ts +85 -416
- package/dist/xai-provider-account-authority.d.ts +26 -0
- package/dist/xai-provider-account-authority.js +9 -0
- package/dist/xai-provider-account-authority.js.map +1 -0
- package/package.json +146 -1
- package/src/agent-authored-durable-text.ts +116 -0
- package/src/agent-config.ts +1527 -0
- package/src/agent-instruction-changes.ts +98 -0
- package/src/agent-learning.ts +161 -0
- package/src/agent-topology.ts +69 -0
- package/src/allowance-refusal.ts +81 -0
- package/src/analytics-consent-report.ts +20 -0
- package/src/api-key-presets.ts +25 -0
- package/src/artifact-catalog.ts +60 -0
- package/src/artifacts.ts +146 -18
- package/src/atlassian-native-retirement.ts +33 -0
- package/src/browser-storage.ts +10 -0
- package/src/bundled-skills.ts +73 -0
- package/src/canonical-human-identities.ts +93 -0
- package/src/claude-provider-account-authority.ts +12 -0
- package/src/claude-subscription-oauth.ts +62 -0
- package/src/claude-subscription-usage.ts +59 -0
- package/src/client-error-report.ts +184 -0
- package/src/code-search.ts +105 -0
- package/src/codex-provider-account-authority.ts +37 -0
- package/src/company-brain-governed-writes.ts +356 -0
- package/src/company-brain.ts +201 -0
- package/src/company-profile.ts +167 -1
- package/src/connect.ts +202 -0
- package/src/connection-account-label.ts +46 -0
- package/src/connection-authority.ts +213 -0
- package/src/connector-attachments.ts +327 -0
- package/src/connector-tool-permissions.ts +60 -0
- package/src/direct-model-provider.ts +98 -0
- package/src/editable-artifact-codec-registry.ts +55 -17
- package/src/editable-artifact-committed-transaction.ts +44 -31
- package/src/editable-artifact-live.ts +123 -57
- package/src/editable-artifact-serialized-commit.ts +2 -1
- package/src/editable-artifact-versions.ts +26 -5
- package/src/editable-artifacts.ts +2 -0
- package/src/external-identities.ts +285 -0
- package/src/feedback.ts +39 -0
- package/src/github-repository-contracts.ts +85 -0
- package/src/github-repository.ts +59 -0
- package/src/google-drive.ts +76 -4
- package/src/governed-learning-activation.ts +191 -0
- package/src/governed-learning-evaluator.ts +176 -0
- package/src/host-mcp-bindings.ts +298 -0
- package/src/image-generation.ts +8 -2
- package/src/index.ts +8019 -1799
- package/src/insights-usage.ts +679 -0
- package/src/interaction.ts +1102 -6
- package/src/knowledge-entries.ts +375 -0
- package/src/knowledge-preparation.ts +50 -0
- package/src/knowledge.ts +335 -0
- package/src/managed-auth-session-sets.ts +253 -0
- package/src/managed-sign-in-methods.ts +37 -0
- package/src/mcp-catalog-limits.ts +2 -0
- package/src/mcp-endpoint.ts +30 -0
- package/src/mcp-oauth.ts +66 -0
- package/src/modal-native-proof-v2.ts +398 -0
- package/src/model-availability.ts +22 -0
- package/src/model-connection-access.ts +17 -0
- package/src/model-context-inspector.ts +139 -0
- package/src/model-display.ts +195 -0
- package/src/model-picker-order.ts +97 -0
- package/src/organization-access.ts +176 -0
- package/src/organization-integration-policy.ts +54 -0
- package/src/organization-membership-lifecycle.ts +559 -0
- package/src/organization-model-usage.ts +72 -0
- package/src/organization-recovery.ts +186 -0
- package/src/organization-usage.ts +79 -0
- package/src/permissions.ts +58 -0
- package/src/personal-github.ts +267 -0
- package/src/plugin-discovery.ts +33 -0
- package/src/preference-registry.ts +20 -1
- package/src/product-analytics.ts +253 -0
- package/src/product-lifecycle-facts.ts +121 -0
- package/src/remember.ts +243 -0
- package/src/retained-output.ts +20 -3
- package/src/sandbox-file-artifacts.ts +73 -0
- package/src/sandbox-provider-command.ts +82 -0
- package/src/sandbox-recovery.ts +116 -0
- package/src/sandbox-snapshots.ts +142 -0
- package/src/session-final-reply.ts +16 -0
- package/src/session-goal-reports.ts +55 -0
- package/src/session-history-import.ts +159 -0
- package/src/session-list-entries.ts +91 -0
- package/src/session-mcp-projections.ts +273 -0
- package/src/session-message-search.ts +54 -0
- package/src/session-titles.ts +467 -0
- package/src/session-topology-primitives.ts +21 -0
- package/src/signup-attribution.ts +81 -0
- package/src/site-request-headers.test.ts +28 -0
- package/src/site-session-http.ts +63 -0
- package/src/skill-catalog-context.ts +50 -0
- package/src/skill-files.ts +52 -0
- package/src/skill-metadata.ts +40 -0
- package/src/skill-use.ts +77 -0
- package/src/skills.ts +136 -0
- package/src/slack-bot-scopes.ts +106 -42
- package/src/slack-rest-mcp.ts +194 -0
- package/src/slack-task-policy.ts +215 -0
- package/src/spreadsheet-artifact-commands.ts +12 -13
- package/src/subscription-account-pools.ts +44 -0
- package/src/task-notes.ts +105 -0
- package/src/tool-catalog.ts +155 -0
- package/src/tool-result-spill.ts +35 -0
- package/src/usage-allowances.ts +187 -0
- package/src/video-generation.ts +43 -6
- package/src/work-claims.ts +266 -0
- package/src/workspace-instruction-policies.ts +31 -0
- package/src/workspace-integration-wire.ts +99 -0
- package/src/workspace-integrations.ts +640 -0
- package/src/workspace-learning-administration.ts +88 -0
- package/src/workspace-learning-policy.ts +4 -3
- package/src/workspace-state.ts +16 -126
- package/src/xai-provider-account-authority.ts +38 -0
- package/dist/chunk-52SGB2QO.js.map +0 -1
- package/dist/chunk-5UDNP7AO.js.map +0 -1
- package/dist/chunk-BVGIYW7D.js +0 -11
- package/dist/chunk-BVGIYW7D.js.map +0 -1
- package/dist/chunk-FJBG5E4O.js.map +0 -1
- package/dist/chunk-H5BVCZKF.js.map +0 -1
- package/dist/chunk-LSB7GRLG.js.map +0 -1
- package/dist/chunk-TZ6YEYN4.js.map +0 -1
- package/dist/chunk-VA22KRHS.js +0 -15177
- package/dist/chunk-VA22KRHS.js.map +0 -1
- package/dist/chunk-Y3MLSLB4.js.map +0 -1
- /package/dist/{chunk-CADSX6UN.js.map → chunk-Y3KNXVTD.js.map} +0 -0
|
@@ -0,0 +1,1527 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent configuration: one `agent` object that describes what an OpenGeni
|
|
3
|
+
* agent is (identity), how it answers (renderer, instructions alias) and what
|
|
4
|
+
* it can do (capabilities). Capabilities are product words; this module owns
|
|
5
|
+
* the single registry that maps every first-party tool to exactly one of them
|
|
6
|
+
* and the pure resolution shared by every session creator (API, MCP child,
|
|
7
|
+
* Slack, scheduled tasks, automations) and the mid-session update.
|
|
8
|
+
*
|
|
9
|
+
* Invariants:
|
|
10
|
+
* - `"all"` reproduces the creator's legacy tool values exactly: capability
|
|
11
|
+
* filtering only removes tools of capabilities that are OFF, and every
|
|
12
|
+
* capability is ON under `"all"` (deployment-disabled capabilities are
|
|
13
|
+
* reported but never rewrite the stored selection; the runtime enforces them).
|
|
14
|
+
* - A session with no configuration (`null`) keeps byte-identical legacy
|
|
15
|
+
* behavior; nothing here runs for it.
|
|
16
|
+
* - Children and agent callers may only narrow.
|
|
17
|
+
*
|
|
18
|
+
* This module must not import runtime values from `./index` (the index
|
|
19
|
+
* re-exports it); only types cross that edge.
|
|
20
|
+
*/
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import type { FirstPartyMcpToolName, SessionToolPolicy, ToolRef } from "./index";
|
|
23
|
+
|
|
24
|
+
export const AGENT_CAPABILITY_IDS = [
|
|
25
|
+
"webSearch",
|
|
26
|
+
"humanInput",
|
|
27
|
+
"skills",
|
|
28
|
+
"goals",
|
|
29
|
+
"subagents",
|
|
30
|
+
"knowledge",
|
|
31
|
+
"schedules",
|
|
32
|
+
"artifacts",
|
|
33
|
+
"browser",
|
|
34
|
+
"media",
|
|
35
|
+
"workspaceFiles",
|
|
36
|
+
"workspaceConnectors",
|
|
37
|
+
"workspaceAdmin",
|
|
38
|
+
] as const;
|
|
39
|
+
export const AgentCapabilityId = z.enum(AGENT_CAPABILITY_IDS);
|
|
40
|
+
export type AgentCapabilityId = z.infer<typeof AgentCapabilityId>;
|
|
41
|
+
|
|
42
|
+
/** Boolean capabilities: every capability except the three-state `skills`. */
|
|
43
|
+
export type AgentBooleanCapabilityId = Exclude<AgentCapabilityId, "skills">;
|
|
44
|
+
export const AGENT_BOOLEAN_CAPABILITY_IDS = AGENT_CAPABILITY_IDS.filter(
|
|
45
|
+
(id): id is AgentBooleanCapabilityId => id !== "skills",
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
/** `read` reads installed Skills; `manage` also saves/installs/publishes/removes. */
|
|
49
|
+
export const AgentSkillsCapability = z.union([
|
|
50
|
+
z.literal("read"),
|
|
51
|
+
z.literal("manage"),
|
|
52
|
+
z.literal(false),
|
|
53
|
+
]);
|
|
54
|
+
export type AgentSkillsCapability = z.infer<typeof AgentSkillsCapability>;
|
|
55
|
+
|
|
56
|
+
export const AgentCapabilityStartingPoint = z.enum(["all", "none"]);
|
|
57
|
+
export type AgentCapabilityStartingPoint = z.infer<typeof AgentCapabilityStartingPoint>;
|
|
58
|
+
|
|
59
|
+
export const AgentCapabilityToggles = z
|
|
60
|
+
.object({
|
|
61
|
+
webSearch: z.boolean().optional(),
|
|
62
|
+
humanInput: z.boolean().optional(),
|
|
63
|
+
skills: AgentSkillsCapability.optional(),
|
|
64
|
+
goals: z.boolean().optional(),
|
|
65
|
+
subagents: z.boolean().optional(),
|
|
66
|
+
knowledge: z.boolean().optional(),
|
|
67
|
+
schedules: z.boolean().optional(),
|
|
68
|
+
artifacts: z.boolean().optional(),
|
|
69
|
+
browser: z.boolean().optional(),
|
|
70
|
+
media: z.boolean().optional(),
|
|
71
|
+
workspaceFiles: z.boolean().optional(),
|
|
72
|
+
workspaceConnectors: z.boolean().optional(),
|
|
73
|
+
workspaceAdmin: z.boolean().optional(),
|
|
74
|
+
})
|
|
75
|
+
.strict();
|
|
76
|
+
export type AgentCapabilityToggles = z.infer<typeof AgentCapabilityToggles>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* `"all"`: everything this workspace offers (today's behavior). `"none"`: the
|
|
80
|
+
* session's own tools plus essentials (human input and reading Skills). An
|
|
81
|
+
* object starts from one of them and switches individual capabilities.
|
|
82
|
+
*/
|
|
83
|
+
export const AgentCapabilities = z.union([
|
|
84
|
+
z.literal("all"),
|
|
85
|
+
z.literal("none"),
|
|
86
|
+
AgentCapabilityToggles.extend({ from: AgentCapabilityStartingPoint }).strict(),
|
|
87
|
+
]);
|
|
88
|
+
export type AgentCapabilities = z.infer<typeof AgentCapabilities>;
|
|
89
|
+
|
|
90
|
+
/** `opengeni` emits `sandbox:`/`artifact:` links and inline visuals; `markdown` does not. */
|
|
91
|
+
export const AgentRenderer = z.enum(["opengeni", "markdown"]);
|
|
92
|
+
export type AgentRenderer = z.infer<typeof AgentRenderer>;
|
|
93
|
+
|
|
94
|
+
export const AGENT_IDENTITY_MAX_CHARACTERS = 8_000;
|
|
95
|
+
/** Same bound as `SESSION_INSTRUCTIONS_MAX_CHARACTERS` (asserted by test). */
|
|
96
|
+
export const AGENT_INSTRUCTIONS_MAX_CHARACTERS = 65_536;
|
|
97
|
+
|
|
98
|
+
export const AgentIdentity = z.string().trim().min(1).max(AGENT_IDENTITY_MAX_CHARACTERS);
|
|
99
|
+
|
|
100
|
+
/** The request-side agent object. Every field is optional. */
|
|
101
|
+
export const AgentConfigRequest = z
|
|
102
|
+
.object({
|
|
103
|
+
capabilities: AgentCapabilities.optional(),
|
|
104
|
+
/** Replaces only OpenGeni's identity lines; null selects the default identity. */
|
|
105
|
+
identity: AgentIdentity.nullable().optional(),
|
|
106
|
+
/** Alias of the session `instructions` field (same column, same bound). */
|
|
107
|
+
instructions: z.string().trim().min(1).max(AGENT_INSTRUCTIONS_MAX_CHARACTERS).optional(),
|
|
108
|
+
renderer: AgentRenderer.optional(),
|
|
109
|
+
})
|
|
110
|
+
.strict();
|
|
111
|
+
export type AgentConfigRequest = z.infer<typeof AgentConfigRequest>;
|
|
112
|
+
|
|
113
|
+
/** Workspace "Defaults for new sessions" agent part (no instructions alias). */
|
|
114
|
+
export const WorkspaceAgentDefaults = z
|
|
115
|
+
.object({
|
|
116
|
+
capabilities: AgentCapabilities.optional(),
|
|
117
|
+
identity: AgentIdentity.nullable().optional(),
|
|
118
|
+
renderer: AgentRenderer.optional(),
|
|
119
|
+
})
|
|
120
|
+
.strict();
|
|
121
|
+
export type WorkspaceAgentDefaults = z.infer<typeof WorkspaceAgentDefaults>;
|
|
122
|
+
|
|
123
|
+
export const ResolvedAgentCapabilities = z
|
|
124
|
+
.object({
|
|
125
|
+
webSearch: z.boolean(),
|
|
126
|
+
humanInput: z.boolean(),
|
|
127
|
+
skills: AgentSkillsCapability,
|
|
128
|
+
goals: z.boolean(),
|
|
129
|
+
subagents: z.boolean(),
|
|
130
|
+
knowledge: z.boolean(),
|
|
131
|
+
schedules: z.boolean(),
|
|
132
|
+
artifacts: z.boolean(),
|
|
133
|
+
browser: z.boolean(),
|
|
134
|
+
media: z.boolean(),
|
|
135
|
+
workspaceFiles: z.boolean(),
|
|
136
|
+
workspaceConnectors: z.boolean(),
|
|
137
|
+
workspaceAdmin: z.boolean(),
|
|
138
|
+
})
|
|
139
|
+
.strict();
|
|
140
|
+
export type ResolvedAgentCapabilities = z.infer<typeof ResolvedAgentCapabilities>;
|
|
141
|
+
|
|
142
|
+
export const ResolvedAgentConfigSource = z.enum([
|
|
143
|
+
"request",
|
|
144
|
+
"workspace_default",
|
|
145
|
+
"deployment_default",
|
|
146
|
+
"inherited",
|
|
147
|
+
"legacy_conversion",
|
|
148
|
+
]);
|
|
149
|
+
export type ResolvedAgentConfigSource = z.infer<typeof ResolvedAgentConfigSource>;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The frozen per-session configuration (`sessions.agent_config`). `capabilities`
|
|
153
|
+
* is the effective map; `unavailable` names capabilities the configuration
|
|
154
|
+
* wanted on but this deployment does not offer (reported off, never widened
|
|
155
|
+
* later without a new resolution).
|
|
156
|
+
*/
|
|
157
|
+
export const ResolvedAgentConfig = z
|
|
158
|
+
.object({
|
|
159
|
+
version: z.literal(1),
|
|
160
|
+
from: AgentCapabilityStartingPoint,
|
|
161
|
+
capabilities: ResolvedAgentCapabilities,
|
|
162
|
+
unavailable: z.array(AgentCapabilityId).max(AGENT_CAPABILITY_IDS.length).default([]),
|
|
163
|
+
identity: AgentIdentity.nullable(),
|
|
164
|
+
renderer: AgentRenderer,
|
|
165
|
+
source: ResolvedAgentConfigSource,
|
|
166
|
+
})
|
|
167
|
+
.strict();
|
|
168
|
+
export type ResolvedAgentConfig = z.infer<typeof ResolvedAgentConfig>;
|
|
169
|
+
|
|
170
|
+
/** `PUT /v1/workspaces/:workspaceId/sessions/:sessionId/agent`. Omitted fields keep current values. */
|
|
171
|
+
export const UpdateSessionAgentRequest = z
|
|
172
|
+
.object({
|
|
173
|
+
agent: AgentConfigRequest,
|
|
174
|
+
expectedVersion: z.number().int().positive(),
|
|
175
|
+
})
|
|
176
|
+
.strict();
|
|
177
|
+
export type UpdateSessionAgentRequest = z.infer<typeof UpdateSessionAgentRequest>;
|
|
178
|
+
|
|
179
|
+
/** Client-safe agent-configuration projection. */
|
|
180
|
+
export const ClientAgentConfig = z
|
|
181
|
+
.object({
|
|
182
|
+
/** @deprecated Agent configuration is always on; servers always report `true`. */
|
|
183
|
+
enabled: z.boolean(),
|
|
184
|
+
/** @deprecated Omitted `agent` always resolves `{ capabilities: "all" }`; always `true`. */
|
|
185
|
+
defaultForNewSessions: z.boolean(),
|
|
186
|
+
capabilities: z.array(
|
|
187
|
+
z
|
|
188
|
+
.object({
|
|
189
|
+
id: AgentCapabilityId,
|
|
190
|
+
available: z.boolean(),
|
|
191
|
+
reason: z.string().max(200).optional(),
|
|
192
|
+
})
|
|
193
|
+
.strict(),
|
|
194
|
+
),
|
|
195
|
+
})
|
|
196
|
+
.strict();
|
|
197
|
+
export type ClientAgentConfig = z.infer<typeof ClientAgentConfig>;
|
|
198
|
+
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
// Capability registry
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
|
|
203
|
+
/** A first-party tool's owner: a capability, or pure runtime mechanics. */
|
|
204
|
+
export type AgentToolCapability = AgentCapabilityId | "runtime";
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Exhaustive map from every `FIRST_PARTY_MCP_TOOL_NAMES` entry to exactly one
|
|
208
|
+
* owner. The `Record` type makes an unmapped new name a compile error, and
|
|
209
|
+
* `agent-config-registry.test.ts` asserts it at runtime too.
|
|
210
|
+
*
|
|
211
|
+
* `runtime` tools are mechanics every agent needs regardless of what it may do:
|
|
212
|
+
* - `wait_for_input`: ends the turn and waits for the next input.
|
|
213
|
+
* - `command_read` / `command_wait`: read/await the session's own background
|
|
214
|
+
* sandbox commands (the shell already exists whenever a sandbox is attached).
|
|
215
|
+
* - `set_session_title`: session titling.
|
|
216
|
+
*/
|
|
217
|
+
export const FIRST_PARTY_MCP_TOOL_CAPABILITIES = {
|
|
218
|
+
set_session_title: "runtime",
|
|
219
|
+
wait_for_input: "runtime",
|
|
220
|
+
command_wait: "runtime",
|
|
221
|
+
command_read: "runtime",
|
|
222
|
+
|
|
223
|
+
goal_set: "goals",
|
|
224
|
+
goal_update: "goals",
|
|
225
|
+
goal_progress: "goals",
|
|
226
|
+
goal_complete: "goals",
|
|
227
|
+
goal_pause: "goals",
|
|
228
|
+
goal_resume: "goals",
|
|
229
|
+
|
|
230
|
+
knowledge_search: "knowledge",
|
|
231
|
+
knowledge_prepare_save: "knowledge",
|
|
232
|
+
knowledge_get: "knowledge",
|
|
233
|
+
knowledge_browse: "knowledge",
|
|
234
|
+
knowledge_save: "knowledge",
|
|
235
|
+
knowledge_retain_file: "knowledge",
|
|
236
|
+
knowledge_retain_message: "knowledge",
|
|
237
|
+
knowledge_archive: "knowledge",
|
|
238
|
+
instruction_policy_save: "knowledge",
|
|
239
|
+
instruction_policy_get: "knowledge",
|
|
240
|
+
memory_search: "knowledge",
|
|
241
|
+
memory_save: "knowledge",
|
|
242
|
+
memory_correct: "knowledge",
|
|
243
|
+
preference_registry_summary: "knowledge",
|
|
244
|
+
preference_registry_get: "knowledge",
|
|
245
|
+
task_notes_list: "knowledge",
|
|
246
|
+
task_note_save: "knowledge",
|
|
247
|
+
task_note_archive: "knowledge",
|
|
248
|
+
task_note_replace: "knowledge",
|
|
249
|
+
work_claim_upsert: "knowledge",
|
|
250
|
+
work_claim_release: "knowledge",
|
|
251
|
+
knowledge_propose: "knowledge",
|
|
252
|
+
knowledge_correct: "knowledge",
|
|
253
|
+
task_note_promote_knowledge: "knowledge",
|
|
254
|
+
task_note_promote_instruction_policy: "knowledge",
|
|
255
|
+
task_note_promote_preference: "knowledge",
|
|
256
|
+
instruction_policy_propose: "knowledge",
|
|
257
|
+
preference_propose: "knowledge",
|
|
258
|
+
remember: "knowledge",
|
|
259
|
+
remember_confirm: "knowledge",
|
|
260
|
+
company_profile_propose: "knowledge",
|
|
261
|
+
company_profile_confirm: "knowledge",
|
|
262
|
+
|
|
263
|
+
sandboxes_list: "workspaceAdmin",
|
|
264
|
+
sandbox_attach: "workspaceAdmin",
|
|
265
|
+
sandbox_swap: "workspaceAdmin",
|
|
266
|
+
run_on: "workspaceAdmin",
|
|
267
|
+
sandbox_provision: "workspaceAdmin",
|
|
268
|
+
connected_machine_remove: "workspaceAdmin",
|
|
269
|
+
connected_machine_enroll_token: "workspaceAdmin",
|
|
270
|
+
project_list: "workspaceAdmin",
|
|
271
|
+
project_get: "workspaceAdmin",
|
|
272
|
+
project_create: "workspaceAdmin",
|
|
273
|
+
project_update: "workspaceAdmin",
|
|
274
|
+
project_reorder: "workspaceAdmin",
|
|
275
|
+
project_delete: "workspaceAdmin",
|
|
276
|
+
session_set_project: "workspaceAdmin",
|
|
277
|
+
rig_list: "workspaceAdmin",
|
|
278
|
+
rig_get: "workspaceAdmin",
|
|
279
|
+
rig_propose_change: "workspaceAdmin",
|
|
280
|
+
rig_verify: "workspaceAdmin",
|
|
281
|
+
rig_promote: "workspaceAdmin",
|
|
282
|
+
variable_set_list: "workspaceAdmin",
|
|
283
|
+
environment_list: "workspaceAdmin",
|
|
284
|
+
variable_set_get_variable: "workspaceAdmin",
|
|
285
|
+
variable_set_set_variable: "workspaceAdmin",
|
|
286
|
+
environment_set_variable: "workspaceAdmin",
|
|
287
|
+
capability_catalog_search: "workspaceAdmin",
|
|
288
|
+
capability_authorization_request: "workspaceAdmin",
|
|
289
|
+
custom_mcp_setup_request: "workspaceAdmin",
|
|
290
|
+
|
|
291
|
+
sessions_list: "subagents",
|
|
292
|
+
session_get: "subagents",
|
|
293
|
+
session_events: "subagents",
|
|
294
|
+
session_wait: "subagents",
|
|
295
|
+
session_create: "subagents",
|
|
296
|
+
session_send_message: "subagents",
|
|
297
|
+
session_pause: "subagents",
|
|
298
|
+
session_resume: "subagents",
|
|
299
|
+
session_steer: "subagents",
|
|
300
|
+
session_human_input_respond: "subagents",
|
|
301
|
+
set_other_session_title: "subagents",
|
|
302
|
+
session_set_model: "subagents",
|
|
303
|
+
|
|
304
|
+
interaction_discover: "browser",
|
|
305
|
+
browser_open: "browser",
|
|
306
|
+
browser_tabs: "browser",
|
|
307
|
+
browser_observe: "browser",
|
|
308
|
+
browser_read: "browser",
|
|
309
|
+
browser_screenshot: "browser",
|
|
310
|
+
browser_act: "browser",
|
|
311
|
+
browser_clipboard: "browser",
|
|
312
|
+
browser_debug: "browser",
|
|
313
|
+
browser_downloads: "browser",
|
|
314
|
+
browser_download_save: "browser",
|
|
315
|
+
browser_auth: "browser",
|
|
316
|
+
interaction_request_human: "browser",
|
|
317
|
+
browser_identity: "browser",
|
|
318
|
+
browser_publish: "browser",
|
|
319
|
+
browser_lifecycle: "browser",
|
|
320
|
+
computer_open: "browser",
|
|
321
|
+
computer_targets: "browser",
|
|
322
|
+
computer_observe: "browser",
|
|
323
|
+
computer_clipboard: "browser",
|
|
324
|
+
computer_act: "browser",
|
|
325
|
+
computer_lifecycle: "browser",
|
|
326
|
+
|
|
327
|
+
github_connect_link: "workspaceConnectors",
|
|
328
|
+
github_repositories_list: "workspaceConnectors",
|
|
329
|
+
social_connections_list: "workspaceConnectors",
|
|
330
|
+
social_posts_recent: "workspaceConnectors",
|
|
331
|
+
social_daily_analysis_context: "workspaceConnectors",
|
|
332
|
+
social_search_live: "workspaceConnectors",
|
|
333
|
+
social_mentions_live: "workspaceConnectors",
|
|
334
|
+
social_thread_fetch: "workspaceConnectors",
|
|
335
|
+
social_posts_sync: "workspaceConnectors",
|
|
336
|
+
social_post_reply: "workspaceConnectors",
|
|
337
|
+
x_accounts_list: "workspaceConnectors",
|
|
338
|
+
x_search_live: "workspaceConnectors",
|
|
339
|
+
x_mentions_live: "workspaceConnectors",
|
|
340
|
+
x_thread_fetch: "workspaceConnectors",
|
|
341
|
+
x_posts_sync: "workspaceConnectors",
|
|
342
|
+
x_post_reply: "workspaceConnectors",
|
|
343
|
+
reddit_accounts_list: "workspaceConnectors",
|
|
344
|
+
reddit_search_live: "workspaceConnectors",
|
|
345
|
+
reddit_mentions_live: "workspaceConnectors",
|
|
346
|
+
reddit_thread_fetch: "workspaceConnectors",
|
|
347
|
+
reddit_posts_sync: "workspaceConnectors",
|
|
348
|
+
reddit_post_reply: "workspaceConnectors",
|
|
349
|
+
slack_bot_list_channels: "workspaceConnectors",
|
|
350
|
+
slack_bot_search: "workspaceConnectors",
|
|
351
|
+
slack_bot_channel_history: "workspaceConnectors",
|
|
352
|
+
slack_bot_thread_replies: "workspaceConnectors",
|
|
353
|
+
slack_bot_list_users: "workspaceConnectors",
|
|
354
|
+
slack_bot_list_files: "workspaceConnectors",
|
|
355
|
+
slack_bot_file_info: "workspaceConnectors",
|
|
356
|
+
slack_bot_file_content: "workspaceConnectors",
|
|
357
|
+
slack_bot_upload_file: "workspaceConnectors",
|
|
358
|
+
slack_bot_post_message: "workspaceConnectors",
|
|
359
|
+
slack_bot_delete_message: "workspaceConnectors",
|
|
360
|
+
slack_bot_prepare_message: "workspaceConnectors",
|
|
361
|
+
slack_bot_send_prepared_message: "workspaceConnectors",
|
|
362
|
+
fiken_companies_list: "workspaceConnectors",
|
|
363
|
+
fiken_contacts_list: "workspaceConnectors",
|
|
364
|
+
fiken_contact_create: "workspaceConnectors",
|
|
365
|
+
fiken_products_list: "workspaceConnectors",
|
|
366
|
+
fiken_invoices_list: "workspaceConnectors",
|
|
367
|
+
fiken_invoice_get: "workspaceConnectors",
|
|
368
|
+
fiken_invoice_draft_create: "workspaceConnectors",
|
|
369
|
+
fiken_bank_accounts_list: "workspaceConnectors",
|
|
370
|
+
fiken_purchases_list: "workspaceConnectors",
|
|
371
|
+
fiken_sales_list: "workspaceConnectors",
|
|
372
|
+
atlassian_sources_list: "workspaceConnectors",
|
|
373
|
+
atlassian_search: "workspaceConnectors",
|
|
374
|
+
atlassian_get: "workspaceConnectors",
|
|
375
|
+
|
|
376
|
+
scheduled_tasks_list: "schedules",
|
|
377
|
+
scheduled_tasks_get: "schedules",
|
|
378
|
+
scheduled_tasks_create: "schedules",
|
|
379
|
+
scheduled_tasks_update: "schedules",
|
|
380
|
+
scheduled_tasks_pause: "schedules",
|
|
381
|
+
scheduled_tasks_resume: "schedules",
|
|
382
|
+
scheduled_tasks_trigger: "schedules",
|
|
383
|
+
scheduled_tasks_delete: "schedules",
|
|
384
|
+
scheduled_task_runs_list: "schedules",
|
|
385
|
+
|
|
386
|
+
artifacts_list: "artifacts",
|
|
387
|
+
artifacts_get_source: "artifacts",
|
|
388
|
+
artifacts_prepare_upload: "artifacts",
|
|
389
|
+
artifacts_create: "artifacts",
|
|
390
|
+
artifacts_publish: "artifacts",
|
|
391
|
+
artifacts_rollback: "artifacts",
|
|
392
|
+
artifacts_archive: "artifacts",
|
|
393
|
+
artifacts_restore: "artifacts",
|
|
394
|
+
sandbox_file_publish: "artifacts",
|
|
395
|
+
editable_artifact_list: "artifacts",
|
|
396
|
+
editable_artifact_create: "artifacts",
|
|
397
|
+
editable_artifact_import: "artifacts",
|
|
398
|
+
editable_artifact_get: "artifacts",
|
|
399
|
+
editable_artifact_inspect: "artifacts",
|
|
400
|
+
editable_artifact_apply: "artifacts",
|
|
401
|
+
editable_artifact_export: "artifacts",
|
|
402
|
+
editable_artifact_export_status: "artifacts",
|
|
403
|
+
} as const satisfies Record<FirstPartyMcpToolName, AgentToolCapability>;
|
|
404
|
+
|
|
405
|
+
/** Owner of a non-MCP tool: a capability, runtime mechanics, or the sandbox. */
|
|
406
|
+
export type AgentFunctionToolClass = AgentCapabilityId | "runtime" | "sandbox";
|
|
407
|
+
|
|
408
|
+
/** Tools served outside the first-party MCP catalog, by the name the model sees. */
|
|
409
|
+
export const AGENT_FUNCTION_TOOL_CAPABILITIES = {
|
|
410
|
+
// Hosted provider tools.
|
|
411
|
+
web_search: "webSearch",
|
|
412
|
+
x_search: "webSearch",
|
|
413
|
+
image_generation: "media",
|
|
414
|
+
// Runtime function tools.
|
|
415
|
+
request_human_input: "humanInput",
|
|
416
|
+
list_models: "subagents",
|
|
417
|
+
generate_image: "media",
|
|
418
|
+
generate_video: "media",
|
|
419
|
+
get_video_generation_capabilities: "media",
|
|
420
|
+
skill_read: "skills",
|
|
421
|
+
skill_search: "skills",
|
|
422
|
+
skill_checkout: "skills",
|
|
423
|
+
skill_save: "skills",
|
|
424
|
+
skill_install: "skills",
|
|
425
|
+
skill_publish: "skills",
|
|
426
|
+
skill_remove: "skills",
|
|
427
|
+
// Derived from an attached sandbox, never toggled.
|
|
428
|
+
exec_command: "sandbox",
|
|
429
|
+
write_stdin: "sandbox",
|
|
430
|
+
apply_patch: "sandbox",
|
|
431
|
+
view_image: "sandbox",
|
|
432
|
+
repository_skill_read: "sandbox",
|
|
433
|
+
code_search: "sandbox",
|
|
434
|
+
// Derived runtime mechanics: search router, operation recovery, credential
|
|
435
|
+
// renewal, and a scheduled task's own bound knowledge source.
|
|
436
|
+
tool_search: "runtime",
|
|
437
|
+
tool_list: "runtime",
|
|
438
|
+
tool_invoke: "runtime",
|
|
439
|
+
operation_read: "runtime",
|
|
440
|
+
refresh_credentials: "runtime",
|
|
441
|
+
knowledge_source_fetch: "runtime",
|
|
442
|
+
knowledge_source_read: "runtime",
|
|
443
|
+
} as const satisfies Record<string, AgentFunctionToolClass>;
|
|
444
|
+
export type AgentFunctionToolName = keyof typeof AGENT_FUNCTION_TOOL_CAPABILITIES;
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Value-free snapshot of the adapters actually selected for one runtime build.
|
|
448
|
+
* Undefined means attachment has not been resolved, not that media is absent.
|
|
449
|
+
* Subscription pool readiness is not evidence for either adapter.
|
|
450
|
+
*/
|
|
451
|
+
export type AgentMediaAttachment = {
|
|
452
|
+
image: "native_hosted" | "provider_adapter" | null;
|
|
453
|
+
video: boolean;
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
export function resolveAgentMediaToolSurface(
|
|
457
|
+
config: ResolvedAgentConfig | null | undefined,
|
|
458
|
+
attachment?: AgentMediaAttachment,
|
|
459
|
+
): { toolsKnown: boolean; hosted: AgentFunctionToolName[]; runtime: AgentFunctionToolName[] } {
|
|
460
|
+
if (!resolveAgentToolFamilies(config).media) {
|
|
461
|
+
return { toolsKnown: true, hosted: [], runtime: [] };
|
|
462
|
+
}
|
|
463
|
+
if (!attachment) return { toolsKnown: false, hosted: [], runtime: [] };
|
|
464
|
+
return {
|
|
465
|
+
toolsKnown: true,
|
|
466
|
+
hosted: attachment.image === "native_hosted" ? ["image_generation"] : [],
|
|
467
|
+
runtime: [
|
|
468
|
+
...(attachment.image === "provider_adapter" ? ["generate_image" as const] : []),
|
|
469
|
+
...(attachment.video
|
|
470
|
+
? ["get_video_generation_capabilities" as const, "generate_video" as const]
|
|
471
|
+
: []),
|
|
472
|
+
],
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/** Skill tools that only read installed Skills (`skills: "read"`). */
|
|
477
|
+
export const AGENT_SKILL_READ_TOOL_NAMES = ["skill_read"] as const;
|
|
478
|
+
/** Skill tools that change Skills (`skills: "manage"` only). */
|
|
479
|
+
export const AGENT_SKILL_MANAGE_TOOL_NAMES = [
|
|
480
|
+
"skill_search",
|
|
481
|
+
"skill_checkout",
|
|
482
|
+
"skill_save",
|
|
483
|
+
"skill_install",
|
|
484
|
+
"skill_publish",
|
|
485
|
+
"skill_remove",
|
|
486
|
+
] as const;
|
|
487
|
+
|
|
488
|
+
/** Built-in MCP servers that belong to a capability rather than the product. */
|
|
489
|
+
export const AGENT_BUILTIN_MCP_SERVER_CAPABILITIES = {
|
|
490
|
+
opengeni: "runtime",
|
|
491
|
+
files: "workspaceFiles",
|
|
492
|
+
docs: "knowledge",
|
|
493
|
+
"google-drive-publishing": "workspaceConnectors",
|
|
494
|
+
} as const satisfies Record<string, AgentToolCapability>;
|
|
495
|
+
|
|
496
|
+
export function firstPartyMcpToolCapability(tool: FirstPartyMcpToolName): AgentToolCapability {
|
|
497
|
+
return FIRST_PARTY_MCP_TOOL_CAPABILITIES[tool];
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/** Availability narrows configuration; it never grants a disabled capability. */
|
|
501
|
+
export type AgentToolEnvironment = {
|
|
502
|
+
/** Explicit product MCPs are independent of ambient workspace connectors. */
|
|
503
|
+
productServerIds?: ReadonlySet<string>;
|
|
504
|
+
unavailable?: readonly AgentCapabilityId[];
|
|
505
|
+
hasSkills?: boolean;
|
|
506
|
+
webSearch?: boolean;
|
|
507
|
+
humanInput?: boolean;
|
|
508
|
+
media?: boolean | undefined;
|
|
509
|
+
hasDeferredTools?: boolean;
|
|
510
|
+
routerInHistory?: boolean;
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
export const AGENT_RUNTIME_MECHANIC_TOOL_NAMES = [
|
|
514
|
+
"wait_for_input",
|
|
515
|
+
"command_read",
|
|
516
|
+
"command_wait",
|
|
517
|
+
] as const satisfies readonly FirstPartyMcpToolName[];
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* The one turn-time capability gate. Null means the historical attachment
|
|
521
|
+
* rules, including unconditional Skill tools and router. Resource-derived
|
|
522
|
+
* sandbox tools, product MCPs and runtime mechanics are never toggled.
|
|
523
|
+
*/
|
|
524
|
+
export function resolveAgentToolFamilies(
|
|
525
|
+
config: ResolvedAgentConfig | null | undefined,
|
|
526
|
+
environment: AgentToolEnvironment = {},
|
|
527
|
+
) {
|
|
528
|
+
const enabled = (id: AgentCapabilityId): boolean =>
|
|
529
|
+
!config ||
|
|
530
|
+
(agentCapabilityEnabled(config.capabilities, id) &&
|
|
531
|
+
!config.unavailable.includes(id) &&
|
|
532
|
+
!environment.unavailable?.includes(id));
|
|
533
|
+
const webSearch = enabled("webSearch") && environment.webSearch !== false;
|
|
534
|
+
const humanInput = enabled("humanInput") && environment.humanInput !== false;
|
|
535
|
+
const media = enabled("media") && environment.media !== false;
|
|
536
|
+
const skills = !config ? "manage" : enabled("skills") ? config.capabilities.skills : false;
|
|
537
|
+
const allowsFirstPartyTool = (name: FirstPartyMcpToolName): boolean => {
|
|
538
|
+
const owner = FIRST_PARTY_MCP_TOOL_CAPABILITIES[name];
|
|
539
|
+
return owner === "runtime" || enabled(owner);
|
|
540
|
+
};
|
|
541
|
+
return {
|
|
542
|
+
webSearch,
|
|
543
|
+
humanInput,
|
|
544
|
+
media,
|
|
545
|
+
subagents: enabled("subagents"),
|
|
546
|
+
skills,
|
|
547
|
+
router:
|
|
548
|
+
!config || environment.hasDeferredTools === true || environment.routerInHistory === true,
|
|
549
|
+
allowsFirstPartyTool,
|
|
550
|
+
firstPartyTools(names: readonly FirstPartyMcpToolName[]): FirstPartyMcpToolName[] {
|
|
551
|
+
return !config
|
|
552
|
+
? [...names]
|
|
553
|
+
: [
|
|
554
|
+
...new Set([
|
|
555
|
+
...names.filter(allowsFirstPartyTool),
|
|
556
|
+
...AGENT_RUNTIME_MECHANIC_TOOL_NAMES,
|
|
557
|
+
]),
|
|
558
|
+
];
|
|
559
|
+
},
|
|
560
|
+
allowsFunctionTool(name: string): boolean {
|
|
561
|
+
if (!config) return true;
|
|
562
|
+
const owner = (AGENT_FUNCTION_TOOL_CAPABILITIES as Record<string, AgentFunctionToolClass>)[
|
|
563
|
+
name
|
|
564
|
+
];
|
|
565
|
+
if (!owner || owner === "sandbox" || owner === "runtime") return true;
|
|
566
|
+
if (owner === "webSearch") return webSearch;
|
|
567
|
+
if (owner === "humanInput") return humanInput;
|
|
568
|
+
if (owner === "media") return media;
|
|
569
|
+
if (owner === "skills") {
|
|
570
|
+
return (
|
|
571
|
+
skills === "manage" ||
|
|
572
|
+
(skills === "read" && name === "skill_read" && environment.hasSkills === true)
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
return enabled(owner);
|
|
576
|
+
},
|
|
577
|
+
allowsMcpServer(id: string): boolean {
|
|
578
|
+
if (!config) return true;
|
|
579
|
+
const owner = (AGENT_BUILTIN_MCP_SERVER_CAPABILITIES as Record<string, AgentToolCapability>)[
|
|
580
|
+
id
|
|
581
|
+
];
|
|
582
|
+
return owner
|
|
583
|
+
? owner === "runtime" || enabled(owner)
|
|
584
|
+
: environment.productServerIds?.has(id) === true || enabled("workspaceConnectors");
|
|
585
|
+
},
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
export function firstPartyMcpToolsForCapability(
|
|
590
|
+
capability: AgentCapabilityId,
|
|
591
|
+
): FirstPartyMcpToolName[] {
|
|
592
|
+
return (Object.keys(FIRST_PARTY_MCP_TOOL_CAPABILITIES) as FirstPartyMcpToolName[]).filter(
|
|
593
|
+
(tool) => FIRST_PARTY_MCP_TOOL_CAPABILITIES[tool] === capability,
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/** Product words for UI and docs. Meaning is fixed by the ids. */
|
|
598
|
+
export const AGENT_CAPABILITY_DESCRIPTIONS: Readonly<
|
|
599
|
+
Record<AgentCapabilityId, { label: string; description: string }>
|
|
600
|
+
> = {
|
|
601
|
+
webSearch: { label: "Web search", description: "Search the public web for current information." },
|
|
602
|
+
humanInput: {
|
|
603
|
+
label: "Ask questions",
|
|
604
|
+
description: "Pause and ask the person for a decision or missing detail.",
|
|
605
|
+
},
|
|
606
|
+
skills: {
|
|
607
|
+
label: "Skills",
|
|
608
|
+
description: "Read installed Skills; with manage, also save, install, and publish them.",
|
|
609
|
+
},
|
|
610
|
+
goals: { label: "Goals", description: "Work toward a goal across many turns until it is done." },
|
|
611
|
+
subagents: {
|
|
612
|
+
label: "Subagents",
|
|
613
|
+
description: "Start, message, and follow other sessions; see available models.",
|
|
614
|
+
},
|
|
615
|
+
knowledge: {
|
|
616
|
+
label: "Knowledge",
|
|
617
|
+
description: "Search and save workspace knowledge, task notes, and instructions.",
|
|
618
|
+
},
|
|
619
|
+
schedules: { label: "Schedules", description: "Create and manage scheduled tasks." },
|
|
620
|
+
artifacts: {
|
|
621
|
+
label: "Artifacts and Sites",
|
|
622
|
+
description: "Publish files, documents, and Sites people can open.",
|
|
623
|
+
},
|
|
624
|
+
browser: { label: "Browser and computer", description: "Use a browser or desktop computer." },
|
|
625
|
+
media: { label: "Images and video", description: "Generate images and videos." },
|
|
626
|
+
workspaceFiles: {
|
|
627
|
+
label: "Workspace files",
|
|
628
|
+
description: "Read files uploaded to the workspace.",
|
|
629
|
+
},
|
|
630
|
+
workspaceConnectors: {
|
|
631
|
+
label: "Workspace connectors",
|
|
632
|
+
description: "Use the workspace's connected apps and integrations.",
|
|
633
|
+
},
|
|
634
|
+
workspaceAdmin: {
|
|
635
|
+
label: "Workspace admin",
|
|
636
|
+
description: "Manage variable sets, projects, rigs, machines, and connector setup.",
|
|
637
|
+
},
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
// ---------------------------------------------------------------------------
|
|
641
|
+
// Prompt modules
|
|
642
|
+
// ---------------------------------------------------------------------------
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Sections of the modular operational contract (sessions with an agent
|
|
646
|
+
* configuration). The order is the composition order. `base_behavior` and
|
|
647
|
+
* `runtime_mechanics` are always present; every other module is included only
|
|
648
|
+
* when its capability or resource is present. The model-context inspector
|
|
649
|
+
* reports them as metadata on the `operational_contract` layer.
|
|
650
|
+
*/
|
|
651
|
+
export const AGENT_PROMPT_MODULE_IDS = [
|
|
652
|
+
"base_behavior",
|
|
653
|
+
"runtime_mechanics",
|
|
654
|
+
"renderer_markdown",
|
|
655
|
+
"sandbox",
|
|
656
|
+
"connected_machine",
|
|
657
|
+
"repositories",
|
|
658
|
+
"workspace_environment",
|
|
659
|
+
"rig",
|
|
660
|
+
"artifacts",
|
|
661
|
+
"media",
|
|
662
|
+
"goals",
|
|
663
|
+
"subagents",
|
|
664
|
+
"knowledge",
|
|
665
|
+
"skills",
|
|
666
|
+
"admin",
|
|
667
|
+
"attachments",
|
|
668
|
+
] as const;
|
|
669
|
+
export const AgentPromptModuleId = z.enum(AGENT_PROMPT_MODULE_IDS);
|
|
670
|
+
export type AgentPromptModuleId = z.infer<typeof AgentPromptModuleId>;
|
|
671
|
+
|
|
672
|
+
export const AGENT_PROMPT_MODULE_TITLES: Readonly<Record<AgentPromptModuleId, string>> = {
|
|
673
|
+
base_behavior: "Base behavior",
|
|
674
|
+
runtime_mechanics: "Runtime mechanics",
|
|
675
|
+
renderer_markdown: "Markdown rendering",
|
|
676
|
+
sandbox: "Sandbox",
|
|
677
|
+
connected_machine: "Connected Machine",
|
|
678
|
+
repositories: "Repositories and Git",
|
|
679
|
+
workspace_environment: "Workspace environment",
|
|
680
|
+
rig: "Sandbox environment",
|
|
681
|
+
artifacts: "Documents, files, and visuals",
|
|
682
|
+
media: "Images and video",
|
|
683
|
+
goals: "Goals",
|
|
684
|
+
subagents: "Session coordination",
|
|
685
|
+
knowledge: "Knowledge",
|
|
686
|
+
skills: "Skills",
|
|
687
|
+
admin: "Integration setup",
|
|
688
|
+
attachments: "Attached files",
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
/** The prompt module each capability owns; capabilities absent here own none. */
|
|
692
|
+
export const AGENT_CAPABILITY_PROMPT_MODULES: Readonly<
|
|
693
|
+
Partial<Record<AgentCapabilityId, readonly AgentPromptModuleId[]>>
|
|
694
|
+
> = {
|
|
695
|
+
artifacts: ["artifacts"],
|
|
696
|
+
media: ["media"],
|
|
697
|
+
goals: ["goals"],
|
|
698
|
+
subagents: ["subagents"],
|
|
699
|
+
knowledge: ["knowledge"],
|
|
700
|
+
skills: ["skills"],
|
|
701
|
+
workspaceAdmin: ["admin"],
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
// ---------------------------------------------------------------------------
|
|
705
|
+
// Resolution
|
|
706
|
+
// ---------------------------------------------------------------------------
|
|
707
|
+
|
|
708
|
+
export const AgentConfigErrorCode = z.enum([
|
|
709
|
+
"agent_capability_unavailable",
|
|
710
|
+
"agent_config_conflict",
|
|
711
|
+
"agent_config_widening",
|
|
712
|
+
]);
|
|
713
|
+
export type AgentConfigErrorCode = z.infer<typeof AgentConfigErrorCode>;
|
|
714
|
+
|
|
715
|
+
/** Typed resolution failure. Transports render it as 422 with `details.code`. */
|
|
716
|
+
export class AgentConfigError extends Error {
|
|
717
|
+
readonly code: AgentConfigErrorCode;
|
|
718
|
+
readonly capability: AgentCapabilityId | undefined;
|
|
719
|
+
|
|
720
|
+
constructor(code: AgentConfigErrorCode, message: string, capability?: AgentCapabilityId) {
|
|
721
|
+
super(message);
|
|
722
|
+
this.name = "AgentConfigError";
|
|
723
|
+
this.code = code;
|
|
724
|
+
this.capability = capability;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
export function isAgentConfigError(error: unknown): error is AgentConfigError {
|
|
729
|
+
return error instanceof AgentConfigError;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const SKILLS_RANK: Record<string, number> = { false: 0, read: 1, manage: 2 };
|
|
733
|
+
function skillsRank(value: AgentSkillsCapability): number {
|
|
734
|
+
return SKILLS_RANK[String(value)] ?? 0;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
export function allAgentCapabilities(): ResolvedAgentCapabilities {
|
|
738
|
+
return {
|
|
739
|
+
webSearch: true,
|
|
740
|
+
humanInput: true,
|
|
741
|
+
skills: "manage",
|
|
742
|
+
goals: true,
|
|
743
|
+
subagents: true,
|
|
744
|
+
knowledge: true,
|
|
745
|
+
schedules: true,
|
|
746
|
+
artifacts: true,
|
|
747
|
+
browser: true,
|
|
748
|
+
media: true,
|
|
749
|
+
workspaceFiles: true,
|
|
750
|
+
workspaceConnectors: true,
|
|
751
|
+
workspaceAdmin: true,
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/** `"none"`: the session's own tools plus the essentials. */
|
|
756
|
+
export function noneAgentCapabilities(): ResolvedAgentCapabilities {
|
|
757
|
+
return {
|
|
758
|
+
webSearch: false,
|
|
759
|
+
humanInput: true,
|
|
760
|
+
skills: "read",
|
|
761
|
+
goals: false,
|
|
762
|
+
subagents: false,
|
|
763
|
+
knowledge: false,
|
|
764
|
+
schedules: false,
|
|
765
|
+
artifacts: false,
|
|
766
|
+
browser: false,
|
|
767
|
+
media: false,
|
|
768
|
+
workspaceFiles: false,
|
|
769
|
+
workspaceConnectors: false,
|
|
770
|
+
workspaceAdmin: false,
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
export function agentCapabilityEnabled(
|
|
775
|
+
capabilities: ResolvedAgentCapabilities,
|
|
776
|
+
id: AgentCapabilityId,
|
|
777
|
+
): boolean {
|
|
778
|
+
return id === "skills" ? capabilities.skills !== false : capabilities[id] === true;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/** Clamp `value` to `ceiling` (children and agent callers never widen). */
|
|
782
|
+
export function intersectAgentCapabilities(
|
|
783
|
+
value: ResolvedAgentCapabilities,
|
|
784
|
+
ceiling: ResolvedAgentCapabilities,
|
|
785
|
+
): ResolvedAgentCapabilities {
|
|
786
|
+
const next = { ...value };
|
|
787
|
+
for (const id of AGENT_BOOLEAN_CAPABILITY_IDS) {
|
|
788
|
+
next[id] = value[id] && ceiling[id];
|
|
789
|
+
}
|
|
790
|
+
next.skills =
|
|
791
|
+
skillsRank(value.skills) <= skillsRank(ceiling.skills) ? value.skills : ceiling.skills;
|
|
792
|
+
return next;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/** First capability `value` enables beyond `ceiling`, or null. */
|
|
796
|
+
export function agentCapabilityWidening(
|
|
797
|
+
value: ResolvedAgentCapabilities,
|
|
798
|
+
ceiling: ResolvedAgentCapabilities,
|
|
799
|
+
): AgentCapabilityId | null {
|
|
800
|
+
for (const id of AGENT_CAPABILITY_IDS) {
|
|
801
|
+
if (id === "skills") {
|
|
802
|
+
if (skillsRank(value.skills) > skillsRank(ceiling.skills)) return id;
|
|
803
|
+
} else if (value[id] && !ceiling[id]) {
|
|
804
|
+
return id;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
function normalizeCapabilities(capabilities: AgentCapabilities): {
|
|
811
|
+
from: AgentCapabilityStartingPoint;
|
|
812
|
+
toggles: AgentCapabilityToggles;
|
|
813
|
+
} {
|
|
814
|
+
if (capabilities === "all" || capabilities === "none") return { from: capabilities, toggles: {} };
|
|
815
|
+
const { from, ...toggles } = capabilities;
|
|
816
|
+
return { from, toggles };
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
function applyToggles(
|
|
820
|
+
base: ResolvedAgentCapabilities,
|
|
821
|
+
toggles: AgentCapabilityToggles,
|
|
822
|
+
): ResolvedAgentCapabilities {
|
|
823
|
+
const next = { ...base };
|
|
824
|
+
for (const id of AGENT_CAPABILITY_IDS) {
|
|
825
|
+
const value = toggles[id];
|
|
826
|
+
if (value === undefined) continue;
|
|
827
|
+
if (id === "skills") next.skills = value as AgentSkillsCapability;
|
|
828
|
+
else next[id] = value as boolean;
|
|
829
|
+
}
|
|
830
|
+
return next;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/** Hard limits: capabilities this deployment does not offer, with a reason. */
|
|
834
|
+
export type AgentConfigDeploymentLimits = {
|
|
835
|
+
unavailable: Partial<Record<AgentCapabilityId, string>>;
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
export type AgentConfigCreator =
|
|
839
|
+
| "api"
|
|
840
|
+
| "slack"
|
|
841
|
+
| "scheduled"
|
|
842
|
+
| "automation"
|
|
843
|
+
| "site_auth_maintenance";
|
|
844
|
+
|
|
845
|
+
/** What the workspace offers when a configuration is being created. */
|
|
846
|
+
export type AgentConfigWorkspaceContext = {
|
|
847
|
+
/** Explicit `settings.sessionAgentDefaults`, honored only with admission enabled. */
|
|
848
|
+
defaults: WorkspaceAgentDefaults | null;
|
|
849
|
+
/** Legacy `settings.agentHumanInputEnabled`; false maps to `humanInput: false`. */
|
|
850
|
+
humanInputEnabled: boolean;
|
|
851
|
+
};
|
|
852
|
+
|
|
853
|
+
export type AgentConfigParent =
|
|
854
|
+
| { kind: "configured"; config: ResolvedAgentConfig }
|
|
855
|
+
/** A null-config parent: its current effective capabilities are the ceiling. */
|
|
856
|
+
| { kind: "legacy"; ceiling: ResolvedAgentCapabilities };
|
|
857
|
+
|
|
858
|
+
export type ResolveAgentConfigInput = {
|
|
859
|
+
creator: AgentConfigCreator;
|
|
860
|
+
/** The request `agent` object; undefined when omitted. */
|
|
861
|
+
request?: AgentConfigRequest | undefined;
|
|
862
|
+
/** The legacy session `instructions` field (alias target). */
|
|
863
|
+
instructions?: string | undefined;
|
|
864
|
+
workspace: AgentConfigWorkspaceContext;
|
|
865
|
+
deployment: AgentConfigDeploymentLimits;
|
|
866
|
+
/** Undefined for a top-level session. */
|
|
867
|
+
parent?: AgentConfigParent | undefined;
|
|
868
|
+
/** Whether the new session carries a goal. */
|
|
869
|
+
goal: boolean;
|
|
870
|
+
};
|
|
871
|
+
|
|
872
|
+
export type ResolveAgentConfigResult = {
|
|
873
|
+
config: ResolvedAgentConfig | null;
|
|
874
|
+
/** The effective session instructions after the alias rule. */
|
|
875
|
+
instructions: string | undefined;
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
function defaultRenderer(creator: AgentConfigCreator): AgentRenderer {
|
|
879
|
+
return creator === "slack" ? "markdown" : "opengeni";
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
function agentConfigFromCapabilities(input: {
|
|
883
|
+
from: AgentCapabilityStartingPoint;
|
|
884
|
+
wanted: ResolvedAgentCapabilities;
|
|
885
|
+
explicitOn: ReadonlySet<AgentCapabilityId>;
|
|
886
|
+
deployment: AgentConfigDeploymentLimits;
|
|
887
|
+
identity: string | null;
|
|
888
|
+
renderer: AgentRenderer;
|
|
889
|
+
source: ResolvedAgentConfigSource;
|
|
890
|
+
inheritedUnavailable?: readonly AgentCapabilityId[] | undefined;
|
|
891
|
+
}): ResolvedAgentConfig {
|
|
892
|
+
const capabilities = { ...input.wanted };
|
|
893
|
+
const unavailable = new Set<AgentCapabilityId>(input.inheritedUnavailable ?? []);
|
|
894
|
+
for (const id of AGENT_CAPABILITY_IDS) {
|
|
895
|
+
const reason = input.deployment.unavailable[id];
|
|
896
|
+
if (reason === undefined || !agentCapabilityEnabled(capabilities, id)) continue;
|
|
897
|
+
if (input.explicitOn.has(id)) {
|
|
898
|
+
throw new AgentConfigError(
|
|
899
|
+
"agent_capability_unavailable",
|
|
900
|
+
`agent capability ${id} is not available on this deployment: ${reason}`,
|
|
901
|
+
id,
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
unavailable.add(id);
|
|
905
|
+
if (id === "skills") capabilities.skills = false;
|
|
906
|
+
else capabilities[id] = false;
|
|
907
|
+
}
|
|
908
|
+
for (const id of unavailable) {
|
|
909
|
+
if (id === "skills") capabilities.skills = false;
|
|
910
|
+
else capabilities[id] = false;
|
|
911
|
+
}
|
|
912
|
+
return {
|
|
913
|
+
version: 1,
|
|
914
|
+
from: input.from,
|
|
915
|
+
capabilities,
|
|
916
|
+
unavailable: AGENT_CAPABILITY_IDS.filter((id) => unavailable.has(id)),
|
|
917
|
+
identity: input.identity,
|
|
918
|
+
renderer: input.renderer,
|
|
919
|
+
source: input.source,
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
function explicitOnToggles(toggles: AgentCapabilityToggles): Set<AgentCapabilityId> {
|
|
924
|
+
const on = new Set<AgentCapabilityId>();
|
|
925
|
+
for (const id of AGENT_CAPABILITY_IDS) {
|
|
926
|
+
const value = toggles[id];
|
|
927
|
+
if (value !== undefined && value !== false) on.add(id);
|
|
928
|
+
}
|
|
929
|
+
return on;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
function resolveInstructionsAlias(
|
|
933
|
+
request: AgentConfigRequest | undefined,
|
|
934
|
+
instructions: string | undefined,
|
|
935
|
+
): string | undefined {
|
|
936
|
+
const aliased = request?.instructions;
|
|
937
|
+
if (
|
|
938
|
+
aliased !== undefined &&
|
|
939
|
+
instructions !== undefined &&
|
|
940
|
+
aliased.trim() !== instructions.trim()
|
|
941
|
+
) {
|
|
942
|
+
throw new AgentConfigError(
|
|
943
|
+
"agent_config_conflict",
|
|
944
|
+
"agent.instructions and instructions are both set and differ; send only one",
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
return instructions ?? aliased;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* Resolve the frozen agent configuration for a new session.
|
|
952
|
+
*
|
|
953
|
+
* Order: deployment limits, then the workspace default, then the request, then
|
|
954
|
+
* the parent (children only narrow). An omitted `agent` on a top-level
|
|
955
|
+
* session resolves the workspace default, else `{ capabilities: "all" }`.
|
|
956
|
+
* Returns `config: null` (exact legacy) only under a legacy parent, which
|
|
957
|
+
* keeps its tree legacy, and for site-auth maintenance sessions.
|
|
958
|
+
*/
|
|
959
|
+
export function resolveAgentConfig(input: ResolveAgentConfigInput): ResolveAgentConfigResult {
|
|
960
|
+
const { request } = input;
|
|
961
|
+
const instructions = resolveInstructionsAlias(request, input.instructions);
|
|
962
|
+
const requestConfigFields =
|
|
963
|
+
request !== undefined &&
|
|
964
|
+
(request.capabilities !== undefined ||
|
|
965
|
+
request.identity !== undefined ||
|
|
966
|
+
request.renderer !== undefined ||
|
|
967
|
+
request.instructions !== undefined);
|
|
968
|
+
|
|
969
|
+
const parent = input.parent;
|
|
970
|
+
const workspaceDefaults = input.workspace.defaults;
|
|
971
|
+
|
|
972
|
+
// --- Omitted agent ---------------------------------------------------------
|
|
973
|
+
if (!requestConfigFields) {
|
|
974
|
+
if (parent?.kind === "configured") {
|
|
975
|
+
return {
|
|
976
|
+
config: withGoalImplication(
|
|
977
|
+
{ ...parent.config, source: "inherited" },
|
|
978
|
+
input.goal,
|
|
979
|
+
false,
|
|
980
|
+
parent.config.capabilities,
|
|
981
|
+
),
|
|
982
|
+
instructions,
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
if (parent?.kind === "legacy") return { config: null, instructions };
|
|
986
|
+
if (input.creator === "site_auth_maintenance") return { config: null, instructions };
|
|
987
|
+
if (workspaceDefaults) {
|
|
988
|
+
const config = resolveTopLevel(input, workspaceDefaults, "workspace_default");
|
|
989
|
+
return { config, instructions };
|
|
990
|
+
}
|
|
991
|
+
const config = resolveTopLevel(input, { capabilities: "all" }, "deployment_default");
|
|
992
|
+
return { config, instructions };
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// --- Explicit agent ---------------------------------------------------------
|
|
996
|
+
if (!parent) {
|
|
997
|
+
const merged: WorkspaceAgentDefaults = {
|
|
998
|
+
capabilities: request.capabilities ?? workspaceDefaults?.capabilities ?? "all",
|
|
999
|
+
...(request.identity !== undefined
|
|
1000
|
+
? { identity: request.identity }
|
|
1001
|
+
: workspaceDefaults?.identity !== undefined
|
|
1002
|
+
? { identity: workspaceDefaults.identity }
|
|
1003
|
+
: {}),
|
|
1004
|
+
...((request.renderer ?? workspaceDefaults?.renderer)
|
|
1005
|
+
? { renderer: request.renderer ?? workspaceDefaults?.renderer }
|
|
1006
|
+
: {}),
|
|
1007
|
+
};
|
|
1008
|
+
return {
|
|
1009
|
+
config: resolveTopLevel(input, merged, "request", request.capabilities === undefined),
|
|
1010
|
+
instructions,
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
const ceiling = parent.kind === "configured" ? parent.config.capabilities : parent.ceiling;
|
|
1015
|
+
const parentConfig = parent.kind === "configured" ? parent.config : null;
|
|
1016
|
+
const requested = request.capabilities
|
|
1017
|
+
? normalizeCapabilities(request.capabilities)
|
|
1018
|
+
: { from: (parentConfig?.from ?? "all") as AgentCapabilityStartingPoint, toggles: {} };
|
|
1019
|
+
// `"all"` for a child means the parent's set; `"none"` means the essentials
|
|
1020
|
+
// the parent also has. Only explicit toggles can widen, and that is refused.
|
|
1021
|
+
const base =
|
|
1022
|
+
requested.from === "all"
|
|
1023
|
+
? { ...ceiling }
|
|
1024
|
+
: intersectAgentCapabilities(noneAgentCapabilities(), ceiling);
|
|
1025
|
+
const wanted = applyToggles(base, requested.toggles);
|
|
1026
|
+
const widened = agentCapabilityWidening(wanted, ceiling);
|
|
1027
|
+
if (widened) {
|
|
1028
|
+
throw new AgentConfigError(
|
|
1029
|
+
"agent_config_widening",
|
|
1030
|
+
`a child session may only narrow its parent's agent capabilities: ${widened}`,
|
|
1031
|
+
widened,
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
const config = agentConfigFromCapabilities({
|
|
1035
|
+
from: requested.from,
|
|
1036
|
+
wanted,
|
|
1037
|
+
explicitOn: explicitOnToggles(requested.toggles),
|
|
1038
|
+
deployment: input.deployment,
|
|
1039
|
+
identity: request.identity !== undefined ? request.identity : (parentConfig?.identity ?? null),
|
|
1040
|
+
renderer: request.renderer ?? parentConfig?.renderer ?? defaultRenderer(input.creator),
|
|
1041
|
+
source: "request",
|
|
1042
|
+
inheritedUnavailable: parentConfig?.unavailable,
|
|
1043
|
+
});
|
|
1044
|
+
return {
|
|
1045
|
+
config: withGoalImplication(config, input.goal, requested.toggles.goals === false, ceiling),
|
|
1046
|
+
instructions,
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
function resolveTopLevel(
|
|
1051
|
+
input: ResolveAgentConfigInput,
|
|
1052
|
+
source: WorkspaceAgentDefaults,
|
|
1053
|
+
sourceKind: ResolvedAgentConfigSource,
|
|
1054
|
+
capabilitiesFromWorkspace = false,
|
|
1055
|
+
): ResolvedAgentConfig {
|
|
1056
|
+
const { from, toggles } = normalizeCapabilities(source.capabilities ?? "all");
|
|
1057
|
+
const base = from === "all" ? allAgentCapabilities() : noneAgentCapabilities();
|
|
1058
|
+
// "Everything this workspace offers": a workspace that turned structured
|
|
1059
|
+
// human input off keeps it off unless a toggle explicitly asks for it.
|
|
1060
|
+
if (!input.workspace.humanInputEnabled) base.humanInput = false;
|
|
1061
|
+
const wanted = applyToggles(base, toggles);
|
|
1062
|
+
const explicitGoalsOff = !capabilitiesFromWorkspace && toggles.goals === false;
|
|
1063
|
+
const config = agentConfigFromCapabilities({
|
|
1064
|
+
from,
|
|
1065
|
+
wanted,
|
|
1066
|
+
// A workspace default never fails a create: unavailable capabilities it
|
|
1067
|
+
// names are reported off instead. Only the request's own toggles are strict.
|
|
1068
|
+
explicitOn:
|
|
1069
|
+
sourceKind === "request" && !capabilitiesFromWorkspace
|
|
1070
|
+
? explicitOnToggles(toggles)
|
|
1071
|
+
: new Set(),
|
|
1072
|
+
deployment: input.deployment,
|
|
1073
|
+
identity: source.identity ?? null,
|
|
1074
|
+
renderer: source.renderer ?? defaultRenderer(input.creator),
|
|
1075
|
+
source: sourceKind,
|
|
1076
|
+
});
|
|
1077
|
+
return withGoalImplication(config, input.goal, explicitGoalsOff, allAgentCapabilities());
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/** Setting a goal implies `goals`; an explicit `goals: false` with a goal is a conflict. */
|
|
1081
|
+
function withGoalImplication(
|
|
1082
|
+
config: ResolvedAgentConfig,
|
|
1083
|
+
goal: boolean,
|
|
1084
|
+
explicitGoalsOff: boolean,
|
|
1085
|
+
ceiling: ResolvedAgentCapabilities,
|
|
1086
|
+
): ResolvedAgentConfig {
|
|
1087
|
+
if (!goal || config.capabilities.goals) return config;
|
|
1088
|
+
if (explicitGoalsOff) {
|
|
1089
|
+
throw new AgentConfigError(
|
|
1090
|
+
"agent_config_conflict",
|
|
1091
|
+
"a session with a goal needs the goals capability; remove goals: false or the goal",
|
|
1092
|
+
"goals",
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
if (config.unavailable.includes("goals")) return config;
|
|
1096
|
+
if (!ceiling.goals) {
|
|
1097
|
+
throw new AgentConfigError(
|
|
1098
|
+
"agent_config_widening",
|
|
1099
|
+
"a child session with a goal needs the goals capability its parent does not have",
|
|
1100
|
+
"goals",
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
return { ...config, capabilities: { ...config.capabilities, goals: true } };
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Resolve a mid-session update. Omitted fields keep the current values; a
|
|
1108
|
+
* legacy (null) session converts from `legacyCeiling` (its current effective
|
|
1109
|
+
* state). Agent callers may only narrow.
|
|
1110
|
+
*/
|
|
1111
|
+
export function resolveAgentConfigUpdate(input: {
|
|
1112
|
+
current: ResolvedAgentConfig | null;
|
|
1113
|
+
legacyCeiling: ResolvedAgentCapabilities;
|
|
1114
|
+
request: AgentConfigRequest;
|
|
1115
|
+
deployment: AgentConfigDeploymentLimits;
|
|
1116
|
+
onlyNarrow: boolean;
|
|
1117
|
+
/** A parent's configuration or legacy ceiling; children never widen past it. */
|
|
1118
|
+
parentCeiling?: ResolvedAgentCapabilities | undefined;
|
|
1119
|
+
goal: boolean;
|
|
1120
|
+
}): ResolvedAgentConfig {
|
|
1121
|
+
const current: ResolvedAgentConfig = input.current ?? {
|
|
1122
|
+
version: 1,
|
|
1123
|
+
from: "all",
|
|
1124
|
+
capabilities: { ...input.legacyCeiling },
|
|
1125
|
+
unavailable: [],
|
|
1126
|
+
identity: null,
|
|
1127
|
+
renderer: "opengeni",
|
|
1128
|
+
source: "legacy_conversion",
|
|
1129
|
+
};
|
|
1130
|
+
let wanted = { ...current.capabilities };
|
|
1131
|
+
let from = current.from;
|
|
1132
|
+
let explicitOn = new Set<AgentCapabilityId>();
|
|
1133
|
+
let explicitGoalsOff = false;
|
|
1134
|
+
if (input.request.capabilities !== undefined) {
|
|
1135
|
+
const normalized = normalizeCapabilities(input.request.capabilities);
|
|
1136
|
+
from = normalized.from;
|
|
1137
|
+
const base = normalized.from === "all" ? allAgentCapabilities() : noneAgentCapabilities();
|
|
1138
|
+
wanted = applyToggles(base, normalized.toggles);
|
|
1139
|
+
explicitOn = explicitOnToggles(normalized.toggles);
|
|
1140
|
+
explicitGoalsOff = normalized.toggles.goals === false;
|
|
1141
|
+
// Starting points are clamped silently to what this session may hold;
|
|
1142
|
+
// explicit toggles beyond it are refused below.
|
|
1143
|
+
const implicitCeiling = input.onlyNarrow ? current.capabilities : input.parentCeiling;
|
|
1144
|
+
if (implicitCeiling) {
|
|
1145
|
+
const clamped = intersectAgentCapabilities(wanted, implicitCeiling);
|
|
1146
|
+
for (const id of AGENT_CAPABILITY_IDS) {
|
|
1147
|
+
if (!explicitOn.has(id)) {
|
|
1148
|
+
if (id === "skills") wanted.skills = clamped.skills;
|
|
1149
|
+
else wanted[id] = clamped[id];
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
for (const [ceiling, who] of [
|
|
1155
|
+
[input.onlyNarrow ? current.capabilities : undefined, "an agent may only narrow its session"],
|
|
1156
|
+
[input.parentCeiling, "a child session may only narrow its parent's agent capabilities"],
|
|
1157
|
+
] as const) {
|
|
1158
|
+
if (!ceiling) continue;
|
|
1159
|
+
const widened = agentCapabilityWidening(wanted, ceiling);
|
|
1160
|
+
if (widened) {
|
|
1161
|
+
throw new AgentConfigError("agent_config_widening", `${who}: ${widened}`, widened);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
const config = agentConfigFromCapabilities({
|
|
1165
|
+
from,
|
|
1166
|
+
wanted,
|
|
1167
|
+
explicitOn,
|
|
1168
|
+
deployment: input.deployment,
|
|
1169
|
+
identity: input.request.identity !== undefined ? input.request.identity : current.identity,
|
|
1170
|
+
renderer: input.request.renderer ?? current.renderer,
|
|
1171
|
+
source: input.current ? "request" : "legacy_conversion",
|
|
1172
|
+
// Capabilities a human re-enables are re-checked against the deployment.
|
|
1173
|
+
inheritedUnavailable: current.unavailable.filter(
|
|
1174
|
+
(id) => input.deployment.unavailable[id] !== undefined,
|
|
1175
|
+
),
|
|
1176
|
+
});
|
|
1177
|
+
return withGoalImplication(
|
|
1178
|
+
config,
|
|
1179
|
+
input.goal,
|
|
1180
|
+
explicitGoalsOff,
|
|
1181
|
+
input.parentCeiling ?? (input.onlyNarrow ? current.capabilities : allAgentCapabilities()),
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
// ---------------------------------------------------------------------------
|
|
1186
|
+
// Write-through to the legacy session columns
|
|
1187
|
+
// ---------------------------------------------------------------------------
|
|
1188
|
+
|
|
1189
|
+
/** A capability is filtered out of legacy columns only when the config turns it off itself. */
|
|
1190
|
+
function capabilityFilteredOut(config: ResolvedAgentConfig, id: AgentCapabilityId): boolean {
|
|
1191
|
+
return !agentCapabilityEnabled(config.capabilities, id) && !config.unavailable.includes(id);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
/**
|
|
1195
|
+
* Narrow a creator's first-party selection (its exact legacy value) to the
|
|
1196
|
+
* enabled capabilities. `"all"` returns `baseline` unchanged. `explicit`, when
|
|
1197
|
+
* the request listed `firstPartyMcpTools` itself, must not name a tool of a
|
|
1198
|
+
* capability the configuration turns off.
|
|
1199
|
+
*/
|
|
1200
|
+
export function agentConfigFirstPartyMcpTools(
|
|
1201
|
+
config: ResolvedAgentConfig,
|
|
1202
|
+
baseline: readonly FirstPartyMcpToolName[],
|
|
1203
|
+
explicit?: readonly FirstPartyMcpToolName[],
|
|
1204
|
+
): FirstPartyMcpToolName[] {
|
|
1205
|
+
for (const tool of explicit ?? []) {
|
|
1206
|
+
const owner = FIRST_PARTY_MCP_TOOL_CAPABILITIES[tool];
|
|
1207
|
+
if (owner !== "runtime" && capabilityFilteredOut(config, owner)) {
|
|
1208
|
+
throw new AgentConfigError(
|
|
1209
|
+
"agent_config_conflict",
|
|
1210
|
+
`firstPartyMcpTools lists ${tool}, but agent capability ${owner} is off`,
|
|
1211
|
+
owner,
|
|
1212
|
+
);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
return baseline.filter((tool) => {
|
|
1216
|
+
const owner = FIRST_PARTY_MCP_TOOL_CAPABILITIES[tool];
|
|
1217
|
+
return owner === "runtime" || !capabilityFilteredOut(config, owner);
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
/**
|
|
1222
|
+
* First-party tools a capability change adds on top of the current selection:
|
|
1223
|
+
* the default-selection tools of every capability that `next` enables and
|
|
1224
|
+
* `previous` did not. Unchanged capabilities keep their exact current tools.
|
|
1225
|
+
*/
|
|
1226
|
+
export function agentConfigAddedFirstPartyMcpTools(
|
|
1227
|
+
previous: ResolvedAgentCapabilities,
|
|
1228
|
+
next: ResolvedAgentConfig,
|
|
1229
|
+
defaults: readonly FirstPartyMcpToolName[],
|
|
1230
|
+
): FirstPartyMcpToolName[] {
|
|
1231
|
+
return defaults.filter((tool) => {
|
|
1232
|
+
const owner = FIRST_PARTY_MCP_TOOL_CAPABILITIES[tool];
|
|
1233
|
+
return (
|
|
1234
|
+
owner !== "runtime" &&
|
|
1235
|
+
!agentCapabilityEnabled(previous, owner) &&
|
|
1236
|
+
agentCapabilityEnabled(next.capabilities, owner)
|
|
1237
|
+
);
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
export type AgentConfigToolRefsInput = {
|
|
1242
|
+
config: ResolvedAgentConfig;
|
|
1243
|
+
tools: readonly ToolRef[];
|
|
1244
|
+
toolPolicy: SessionToolPolicy;
|
|
1245
|
+
/** Product servers: attached to this session or named explicitly by the request. */
|
|
1246
|
+
productServerIds: ReadonlySet<string>;
|
|
1247
|
+
/** Server ids the request's explicit `tools` named (strict conflict check). */
|
|
1248
|
+
explicitServerIds?: ReadonlySet<string>;
|
|
1249
|
+
};
|
|
1250
|
+
|
|
1251
|
+
/**
|
|
1252
|
+
* Apply `workspaceFiles`, `knowledge` (the `docs` server) and
|
|
1253
|
+
* `workspaceConnectors` to the stored tool refs and policy. A workspace-default
|
|
1254
|
+
* policy keeps tracking defaults with `files`/`docs` excluded when their
|
|
1255
|
+
* capability is off; with connectors off it becomes an explicit policy holding
|
|
1256
|
+
* only product refs (plus enabled built-ins), so no workspace default connector
|
|
1257
|
+
* ever reaches the session. `"all"` returns the input unchanged.
|
|
1258
|
+
*/
|
|
1259
|
+
export function agentConfigToolRefs(input: AgentConfigToolRefsInput): {
|
|
1260
|
+
tools: ToolRef[];
|
|
1261
|
+
toolPolicy: SessionToolPolicy;
|
|
1262
|
+
} {
|
|
1263
|
+
const { config } = input;
|
|
1264
|
+
const filesOff = capabilityFilteredOut(config, "workspaceFiles");
|
|
1265
|
+
const docsOff = capabilityFilteredOut(config, "knowledge");
|
|
1266
|
+
const connectorsOff = capabilityFilteredOut(config, "workspaceConnectors");
|
|
1267
|
+
for (const id of input.explicitServerIds ?? []) {
|
|
1268
|
+
const owner: AgentCapabilityId | null =
|
|
1269
|
+
id === "files" ? "workspaceFiles" : id === "docs" ? "knowledge" : null;
|
|
1270
|
+
if (owner && capabilityFilteredOut(config, owner)) {
|
|
1271
|
+
throw new AgentConfigError(
|
|
1272
|
+
"agent_config_conflict",
|
|
1273
|
+
`tools lists the ${id} server, but agent capability ${owner} is off`,
|
|
1274
|
+
owner,
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
const builtinOff = (id: string) => (id === "files" && filesOff) || (id === "docs" && docsOff);
|
|
1279
|
+
const isWorkspaceConnector = (id: string) =>
|
|
1280
|
+
id !== "opengeni" && id !== "files" && id !== "docs" && !input.productServerIds.has(id);
|
|
1281
|
+
let tools = input.tools
|
|
1282
|
+
.filter((tool) => !builtinOff(tool.id))
|
|
1283
|
+
.map((tool) =>
|
|
1284
|
+
config.from === "none" && input.productServerIds.has(tool.id) && tool.eager === undefined
|
|
1285
|
+
? { ...tool, eager: true }
|
|
1286
|
+
: tool,
|
|
1287
|
+
);
|
|
1288
|
+
let toolPolicy: SessionToolPolicy = { ...input.toolPolicy };
|
|
1289
|
+
if (connectorsOff) {
|
|
1290
|
+
tools = tools.filter((tool) => !isWorkspaceConnector(tool.id));
|
|
1291
|
+
if (toolPolicy.mode === "workspace_default") {
|
|
1292
|
+
toolPolicy = { mode: "explicit", inheritedFromSessionId: toolPolicy.inheritedFromSessionId };
|
|
1293
|
+
}
|
|
1294
|
+
} else if (toolPolicy.mode === "workspace_default" && (filesOff || docsOff)) {
|
|
1295
|
+
const excluded = new Set(toolPolicy.excludedMcpServerIds ?? []);
|
|
1296
|
+
if (filesOff) excluded.add("files");
|
|
1297
|
+
if (docsOff) excluded.add("docs");
|
|
1298
|
+
toolPolicy = { ...toolPolicy, excludedMcpServerIds: [...excluded].sort() };
|
|
1299
|
+
}
|
|
1300
|
+
if (
|
|
1301
|
+
tools.length === input.tools.length &&
|
|
1302
|
+
tools.every((tool, index) => tool === input.tools[index]) &&
|
|
1303
|
+
JSON.stringify(toolPolicy) === JSON.stringify(input.toolPolicy)
|
|
1304
|
+
) {
|
|
1305
|
+
return { tools: [...input.tools], toolPolicy: input.toolPolicy };
|
|
1306
|
+
}
|
|
1307
|
+
return { tools, toolPolicy };
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* The effective capabilities of a null-config (legacy) session, used as the
|
|
1312
|
+
* ceiling when a child asks for an explicit configuration and when a legacy
|
|
1313
|
+
* session converts on its first update. Legacy sessions always carry web
|
|
1314
|
+
* search, media, list_models and every Skill tool, so those are on.
|
|
1315
|
+
*/
|
|
1316
|
+
export function legacyEffectiveAgentCapabilities(input: {
|
|
1317
|
+
firstPartyMcpTools: readonly FirstPartyMcpToolName[];
|
|
1318
|
+
tools: readonly ToolRef[];
|
|
1319
|
+
toolPolicy: SessionToolPolicy;
|
|
1320
|
+
humanInputEnabled: boolean;
|
|
1321
|
+
/**
|
|
1322
|
+
* The workspace's current omitted-tools default server ids, when known. A
|
|
1323
|
+
* workspace-default session only has `files`/`docs`/connectors that are
|
|
1324
|
+
* actually defaults; without this the ceiling assumes they are.
|
|
1325
|
+
*/
|
|
1326
|
+
defaultServerIds?: Iterable<string> | undefined;
|
|
1327
|
+
}): ResolvedAgentCapabilities {
|
|
1328
|
+
const selected = new Set<AgentToolCapability>(
|
|
1329
|
+
input.firstPartyMcpTools.map((tool) => FIRST_PARTY_MCP_TOOL_CAPABILITIES[tool]),
|
|
1330
|
+
);
|
|
1331
|
+
const ids = new Set(input.tools.map((tool) => tool.id));
|
|
1332
|
+
const tracksDefaults = input.toolPolicy.mode === "workspace_default";
|
|
1333
|
+
const excluded = new Set(input.toolPolicy.excludedMcpServerIds ?? []);
|
|
1334
|
+
const defaults = input.defaultServerIds ? new Set(input.defaultServerIds) : null;
|
|
1335
|
+
const isDefault = (id: string) => defaults === null || defaults.has(id);
|
|
1336
|
+
const serverOn = (id: string) =>
|
|
1337
|
+
ids.has(id) || (tracksDefaults && !excluded.has(id) && isDefault(id));
|
|
1338
|
+
const defaultConnector =
|
|
1339
|
+
tracksDefaults &&
|
|
1340
|
+
(defaults === null ||
|
|
1341
|
+
[...defaults].some(
|
|
1342
|
+
(id) => id !== "opengeni" && id !== "files" && id !== "docs" && !excluded.has(id),
|
|
1343
|
+
));
|
|
1344
|
+
return {
|
|
1345
|
+
webSearch: true,
|
|
1346
|
+
humanInput: input.humanInputEnabled,
|
|
1347
|
+
skills: "manage",
|
|
1348
|
+
goals: selected.has("goals"),
|
|
1349
|
+
subagents: true,
|
|
1350
|
+
knowledge: selected.has("knowledge") || serverOn("docs"),
|
|
1351
|
+
schedules: selected.has("schedules"),
|
|
1352
|
+
artifacts: selected.has("artifacts"),
|
|
1353
|
+
browser: selected.has("browser"),
|
|
1354
|
+
media: true,
|
|
1355
|
+
workspaceFiles: serverOn("files"),
|
|
1356
|
+
workspaceConnectors:
|
|
1357
|
+
selected.has("workspaceConnectors") ||
|
|
1358
|
+
defaultConnector ||
|
|
1359
|
+
[...ids].some((id) => id !== "opengeni" && id !== "files" && id !== "docs"),
|
|
1360
|
+
workspaceAdmin: selected.has("workspaceAdmin"),
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
/**
|
|
1365
|
+
* Deployment limits derivable from the deployment's first-party ceiling: a
|
|
1366
|
+
* capability whose every first-party tool is outside the allowlist is not
|
|
1367
|
+
* offered. Callers add feature flags (for example hosted web search).
|
|
1368
|
+
*/
|
|
1369
|
+
export function agentConfigDeploymentLimitsFromAllowlist(
|
|
1370
|
+
allowed: readonly FirstPartyMcpToolName[],
|
|
1371
|
+
extra: Partial<Record<AgentCapabilityId, string>> = {},
|
|
1372
|
+
): AgentConfigDeploymentLimits {
|
|
1373
|
+
const allowedSet = new Set(allowed);
|
|
1374
|
+
const unavailable: Partial<Record<AgentCapabilityId, string>> = {};
|
|
1375
|
+
for (const id of AGENT_CAPABILITY_IDS) {
|
|
1376
|
+
const tools = firstPartyMcpToolsForCapability(id);
|
|
1377
|
+
if (tools.length > 0 && !tools.some((tool) => allowedSet.has(tool))) {
|
|
1378
|
+
unavailable[id] = "its tools are not allowed on this server";
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
return { unavailable: { ...unavailable, ...extra } };
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
export type AgentEffectiveToolEntry = {
|
|
1385
|
+
name: string;
|
|
1386
|
+
capability: AgentCapabilityId | "runtime" | "sandbox" | "product";
|
|
1387
|
+
source: "first_party" | "runtime" | "hosted" | "sandbox" | "mcp";
|
|
1388
|
+
visibility?: "upfront" | "search";
|
|
1389
|
+
};
|
|
1390
|
+
|
|
1391
|
+
export type AgentEffectiveMcpServerEntry = {
|
|
1392
|
+
id: string;
|
|
1393
|
+
capability: AgentCapabilityId | "runtime" | "product";
|
|
1394
|
+
toolsKnown: boolean;
|
|
1395
|
+
};
|
|
1396
|
+
|
|
1397
|
+
export const AgentEffectiveTools = z
|
|
1398
|
+
.object({
|
|
1399
|
+
capabilities: ResolvedAgentCapabilities,
|
|
1400
|
+
unavailable: z.array(AgentCapabilityId),
|
|
1401
|
+
/** False means media adapters await exact turn/credential attachment; tools does not guess them. */
|
|
1402
|
+
mediaToolsKnown: z.boolean().optional(),
|
|
1403
|
+
tools: z
|
|
1404
|
+
.array(
|
|
1405
|
+
z
|
|
1406
|
+
.object({
|
|
1407
|
+
name: z.string().min(1).max(512),
|
|
1408
|
+
capability: z.union([
|
|
1409
|
+
AgentCapabilityId,
|
|
1410
|
+
z.literal("runtime"),
|
|
1411
|
+
z.literal("sandbox"),
|
|
1412
|
+
z.literal("product"),
|
|
1413
|
+
]),
|
|
1414
|
+
source: z.enum(["first_party", "runtime", "hosted", "sandbox", "mcp"]),
|
|
1415
|
+
visibility: z.enum(["upfront", "search"]).optional(),
|
|
1416
|
+
})
|
|
1417
|
+
.strict(),
|
|
1418
|
+
)
|
|
1419
|
+
.max(512),
|
|
1420
|
+
mcpServers: z
|
|
1421
|
+
.array(
|
|
1422
|
+
z
|
|
1423
|
+
.object({
|
|
1424
|
+
id: z.string().min(1).max(200),
|
|
1425
|
+
capability: z.union([AgentCapabilityId, z.literal("runtime"), z.literal("product")]),
|
|
1426
|
+
toolsKnown: z.boolean(),
|
|
1427
|
+
})
|
|
1428
|
+
.strict(),
|
|
1429
|
+
)
|
|
1430
|
+
.max(256),
|
|
1431
|
+
})
|
|
1432
|
+
.strict();
|
|
1433
|
+
export type AgentEffectiveTools = z.infer<typeof AgentEffectiveTools>;
|
|
1434
|
+
|
|
1435
|
+
/**
|
|
1436
|
+
* Project known model tools through the same turn-time gates. External MCP
|
|
1437
|
+
* schemas are never guessed: their server stays toolsKnown:false until listed.
|
|
1438
|
+
*/
|
|
1439
|
+
export function projectAgentEffectiveTools(input: {
|
|
1440
|
+
config: ResolvedAgentConfig;
|
|
1441
|
+
firstPartyMcpTools: readonly FirstPartyMcpToolName[];
|
|
1442
|
+
mcpServerIds: readonly string[];
|
|
1443
|
+
/** Servers attached to the session itself; other non-built-in ids are workspace connectors. */
|
|
1444
|
+
productServerIds: ReadonlySet<string>;
|
|
1445
|
+
environment?: AgentToolEnvironment;
|
|
1446
|
+
runtimeToolNames?: readonly AgentFunctionToolName[];
|
|
1447
|
+
hostedToolNames?: readonly AgentFunctionToolName[];
|
|
1448
|
+
sandboxToolNames?: readonly AgentFunctionToolName[];
|
|
1449
|
+
routerToolNames?: readonly AgentFunctionToolName[];
|
|
1450
|
+
/** Raw first-party names; other entries use model-facing names. */
|
|
1451
|
+
upfrontToolNames?: ReadonlySet<string>;
|
|
1452
|
+
firstPartyModelNames?: ReadonlyMap<FirstPartyMcpToolName, string>;
|
|
1453
|
+
mediaAttachment?: AgentMediaAttachment | undefined;
|
|
1454
|
+
}): AgentEffectiveTools {
|
|
1455
|
+
const { capabilities } = input.config;
|
|
1456
|
+
const media = resolveAgentMediaToolSurface(input.config, input.mediaAttachment);
|
|
1457
|
+
const mediaNames = new Set<string>([...media.hosted, ...media.runtime]);
|
|
1458
|
+
const families = resolveAgentToolFamilies(input.config, {
|
|
1459
|
+
...input.environment,
|
|
1460
|
+
media: media.toolsKnown ? mediaNames.size > 0 : undefined,
|
|
1461
|
+
productServerIds: input.productServerIds,
|
|
1462
|
+
});
|
|
1463
|
+
const tools: AgentEffectiveToolEntry[] = input.firstPartyMcpTools
|
|
1464
|
+
.filter(families.allowsFirstPartyTool)
|
|
1465
|
+
.map((tool) => ({
|
|
1466
|
+
name: input.firstPartyModelNames?.get(tool) ?? `opengeni__${tool}`,
|
|
1467
|
+
capability: FIRST_PARTY_MCP_TOOL_CAPABILITIES[tool],
|
|
1468
|
+
source: "first_party",
|
|
1469
|
+
visibility: input.upfrontToolNames?.has(tool) ? "upfront" : "search",
|
|
1470
|
+
}));
|
|
1471
|
+
const functionTool = (name: AgentFunctionToolName, source: AgentEffectiveToolEntry["source"]) => {
|
|
1472
|
+
const owner = AGENT_FUNCTION_TOOL_CAPABILITIES[name];
|
|
1473
|
+
if (owner === "media" && !mediaNames.has(name)) return;
|
|
1474
|
+
if (!families.allowsFunctionTool(name)) return;
|
|
1475
|
+
if (tools.some((tool) => tool.name === name)) return;
|
|
1476
|
+
tools.push({
|
|
1477
|
+
name,
|
|
1478
|
+
capability: owner,
|
|
1479
|
+
source,
|
|
1480
|
+
visibility:
|
|
1481
|
+
input.upfrontToolNames?.has(name) || source === "sandbox" || source === "hosted"
|
|
1482
|
+
? "upfront"
|
|
1483
|
+
: "search",
|
|
1484
|
+
});
|
|
1485
|
+
};
|
|
1486
|
+
for (const name of input.hostedToolNames ?? []) functionTool(name, "hosted");
|
|
1487
|
+
for (const name of input.runtimeToolNames ?? []) functionTool(name, "runtime");
|
|
1488
|
+
for (const name of media.hosted) functionTool(name, "hosted");
|
|
1489
|
+
for (const name of media.runtime) functionTool(name, "runtime");
|
|
1490
|
+
for (const name of input.sandboxToolNames ?? []) functionTool(name, "sandbox");
|
|
1491
|
+
if (families.router)
|
|
1492
|
+
for (const name of input.routerToolNames ?? []) functionTool(name, "runtime");
|
|
1493
|
+
const builtin = AGENT_BUILTIN_MCP_SERVER_CAPABILITIES as Record<string, AgentToolCapability>;
|
|
1494
|
+
const mcpServers: AgentEffectiveMcpServerEntry[] = [...new Set(input.mcpServerIds)]
|
|
1495
|
+
.filter(families.allowsMcpServer)
|
|
1496
|
+
.sort()
|
|
1497
|
+
.map((id) => ({
|
|
1498
|
+
id,
|
|
1499
|
+
capability:
|
|
1500
|
+
builtin[id] ?? (input.productServerIds.has(id) ? "product" : "workspaceConnectors"),
|
|
1501
|
+
toolsKnown: id === "opengeni",
|
|
1502
|
+
}));
|
|
1503
|
+
return {
|
|
1504
|
+
capabilities: {
|
|
1505
|
+
...capabilities,
|
|
1506
|
+
webSearch: families.webSearch,
|
|
1507
|
+
humanInput: families.humanInput,
|
|
1508
|
+
media: families.media,
|
|
1509
|
+
},
|
|
1510
|
+
mediaToolsKnown: media.toolsKnown,
|
|
1511
|
+
unavailable: [
|
|
1512
|
+
...new Set([
|
|
1513
|
+
...input.config.unavailable,
|
|
1514
|
+
...AGENT_CAPABILITY_IDS.filter(
|
|
1515
|
+
(id) =>
|
|
1516
|
+
agentCapabilityEnabled(capabilities, id) &&
|
|
1517
|
+
(input.environment?.unavailable?.includes(id) ||
|
|
1518
|
+
(id === "webSearch" && !families.webSearch) ||
|
|
1519
|
+
(id === "humanInput" && !families.humanInput) ||
|
|
1520
|
+
(id === "media" && !families.media)),
|
|
1521
|
+
),
|
|
1522
|
+
]),
|
|
1523
|
+
],
|
|
1524
|
+
tools,
|
|
1525
|
+
mcpServers,
|
|
1526
|
+
};
|
|
1527
|
+
}
|