@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,194 @@
|
|
|
1
|
+
/** The catalog and OAuth identity stay stable while calls use the ordinary Web API. */
|
|
2
|
+
export const OFFICIAL_SLACK_MCP_URL = "https://mcp.slack.com/mcp";
|
|
3
|
+
export const SLACK_REST_API_BASE = "https://slack.com/api/";
|
|
4
|
+
|
|
5
|
+
export const OPENGENI_SLACK_REST_USER_SCOPES = [
|
|
6
|
+
"channels:read",
|
|
7
|
+
"groups:read",
|
|
8
|
+
"im:read",
|
|
9
|
+
"mpim:read",
|
|
10
|
+
"channels:history",
|
|
11
|
+
"groups:history",
|
|
12
|
+
"im:history",
|
|
13
|
+
"mpim:history",
|
|
14
|
+
"users:read",
|
|
15
|
+
"im:write",
|
|
16
|
+
"chat:write",
|
|
17
|
+
] as const;
|
|
18
|
+
|
|
19
|
+
/** Slack returns comma-delimited scopes, including in existing saved grants. */
|
|
20
|
+
export function normalizeSlackScopes(
|
|
21
|
+
scopes: readonly string[] | string | undefined | null,
|
|
22
|
+
): string[] {
|
|
23
|
+
return [
|
|
24
|
+
...new Set(
|
|
25
|
+
(typeof scopes === "string" ? [scopes] : (scopes ?? []))
|
|
26
|
+
.flatMap((entry) => entry.split(/[\s,]+/u))
|
|
27
|
+
.filter(Boolean),
|
|
28
|
+
),
|
|
29
|
+
].sort();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type SlackRestMcpTool = {
|
|
33
|
+
name: string;
|
|
34
|
+
description: string;
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: "object";
|
|
37
|
+
properties: Record<string, unknown>;
|
|
38
|
+
required: string[];
|
|
39
|
+
additionalProperties: false;
|
|
40
|
+
};
|
|
41
|
+
annotations: {
|
|
42
|
+
readOnlyHint: boolean;
|
|
43
|
+
destructiveHint: false;
|
|
44
|
+
idempotentHint: boolean;
|
|
45
|
+
openWorldHint: true;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const conversationScopes = ["channels:read", "groups:read", "im:read", "mpim:read"];
|
|
50
|
+
const historyScopes = ["channels:history", "groups:history", "im:history", "mpim:history"];
|
|
51
|
+
const channel = { type: "string", description: "Slack conversation ID, such as C123 or D123." };
|
|
52
|
+
const cursor = { type: "string", maxLength: 4096, description: "Cursor from the previous page." };
|
|
53
|
+
const directoryPage = { type: "integer", minimum: 1, maximum: 100, default: 100 };
|
|
54
|
+
const historyPage = { type: "integer", minimum: 1, maximum: 15, default: 15 };
|
|
55
|
+
const timestamp = { type: "string", pattern: "^[0-9]+\\.[0-9]+$" };
|
|
56
|
+
|
|
57
|
+
function tool(
|
|
58
|
+
name: string,
|
|
59
|
+
description: string,
|
|
60
|
+
properties: Record<string, unknown>,
|
|
61
|
+
required: string[] = [],
|
|
62
|
+
mutation = false,
|
|
63
|
+
): SlackRestMcpTool {
|
|
64
|
+
return {
|
|
65
|
+
name,
|
|
66
|
+
description,
|
|
67
|
+
inputSchema: { type: "object", properties, required, additionalProperties: false },
|
|
68
|
+
annotations: {
|
|
69
|
+
readOnlyHint: !mutation,
|
|
70
|
+
destructiveHint: false,
|
|
71
|
+
idempotentHint: !mutation,
|
|
72
|
+
openWorldHint: true,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Static reviewed pilot surface. Each call reads only one explicitly requested page. */
|
|
78
|
+
export const SLACK_REST_MCP_TOOLS: SlackRestMcpTool[] = [
|
|
79
|
+
tool(
|
|
80
|
+
"slack_list_channels",
|
|
81
|
+
"Lists one page of conversations visible to your connected Slack account. Conversation types without a granted read scope are omitted.",
|
|
82
|
+
{
|
|
83
|
+
types: {
|
|
84
|
+
type: "array",
|
|
85
|
+
items: { type: "string", enum: ["public_channel", "private_channel", "im", "mpim"] },
|
|
86
|
+
minItems: 1,
|
|
87
|
+
maxItems: 4,
|
|
88
|
+
},
|
|
89
|
+
cursor,
|
|
90
|
+
limit: directoryPage,
|
|
91
|
+
exclude_archived: { type: "boolean", default: true },
|
|
92
|
+
},
|
|
93
|
+
),
|
|
94
|
+
tool(
|
|
95
|
+
"slack_get_channel_info",
|
|
96
|
+
"Gets metadata for one conversation visible to your connected Slack account.",
|
|
97
|
+
{ channel },
|
|
98
|
+
["channel"],
|
|
99
|
+
),
|
|
100
|
+
tool(
|
|
101
|
+
"slack_list_channel_members",
|
|
102
|
+
"Lists one page of members in a visible channel or group conversation.",
|
|
103
|
+
{ channel, cursor, limit: directoryPage },
|
|
104
|
+
["channel"],
|
|
105
|
+
),
|
|
106
|
+
tool("slack_list_users", "Lists one page of users in the connected Slack workspace.", {
|
|
107
|
+
cursor,
|
|
108
|
+
limit: directoryPage,
|
|
109
|
+
}),
|
|
110
|
+
tool(
|
|
111
|
+
"slack_get_user_info",
|
|
112
|
+
"Gets a user's profile by their Slack user ID. Email is included only when Slack has granted that scope.",
|
|
113
|
+
{ user: { type: "string" } },
|
|
114
|
+
["user"],
|
|
115
|
+
),
|
|
116
|
+
tool(
|
|
117
|
+
"slack_read_channel",
|
|
118
|
+
"Reads one page of at most 15 messages from a selected conversation. Slack history limits are shared across the workspace. No automatic pagination or backfill.",
|
|
119
|
+
{
|
|
120
|
+
channel,
|
|
121
|
+
cursor,
|
|
122
|
+
limit: historyPage,
|
|
123
|
+
oldest: timestamp,
|
|
124
|
+
latest: timestamp,
|
|
125
|
+
inclusive: { type: "boolean", default: false },
|
|
126
|
+
},
|
|
127
|
+
["channel"],
|
|
128
|
+
),
|
|
129
|
+
tool(
|
|
130
|
+
"slack_read_thread",
|
|
131
|
+
"Reads one page of at most 15 messages in a selected thread. Slack thread limits are shared across the workspace. No automatic pagination or backfill.",
|
|
132
|
+
{
|
|
133
|
+
channel,
|
|
134
|
+
ts: { ...timestamp, description: "Thread root message timestamp." },
|
|
135
|
+
cursor,
|
|
136
|
+
limit: historyPage,
|
|
137
|
+
},
|
|
138
|
+
["channel", "ts"],
|
|
139
|
+
),
|
|
140
|
+
tool(
|
|
141
|
+
"slack_open_dm",
|
|
142
|
+
"Opens or resumes a direct message with one Slack user as your connected account.",
|
|
143
|
+
{ user: { type: "string" } },
|
|
144
|
+
["user"],
|
|
145
|
+
true,
|
|
146
|
+
),
|
|
147
|
+
tool(
|
|
148
|
+
"slack_send_message",
|
|
149
|
+
"Sends a message as your connected Slack account. Supply thread_ts to reply in a thread. Review the recipient and text before approving. An uncertain submission is never automatically retried.",
|
|
150
|
+
{
|
|
151
|
+
channel,
|
|
152
|
+
text: { type: "string", minLength: 1, maxLength: 40000 },
|
|
153
|
+
thread_ts: { ...timestamp, description: "Optional thread root timestamp for a reply." },
|
|
154
|
+
unfurl_links: { type: "boolean", default: false },
|
|
155
|
+
unfurl_media: { type: "boolean", default: false },
|
|
156
|
+
},
|
|
157
|
+
["channel", "text"],
|
|
158
|
+
true,
|
|
159
|
+
),
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
const REQUIRED_ANY_SCOPES: Readonly<Record<string, readonly string[]>> = {
|
|
163
|
+
slack_list_channels: conversationScopes,
|
|
164
|
+
slack_get_channel_info: conversationScopes,
|
|
165
|
+
slack_list_channel_members: ["channels:read", "groups:read", "mpim:read"],
|
|
166
|
+
slack_list_users: ["users:read"],
|
|
167
|
+
slack_get_user_info: ["users:read"],
|
|
168
|
+
slack_read_channel: historyScopes,
|
|
169
|
+
slack_read_thread: historyScopes,
|
|
170
|
+
slack_open_dm: ["im:write"],
|
|
171
|
+
slack_send_message: ["chat:write"],
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export function slackRestMcpToolsForScopes(scopes: readonly string[] | string): SlackRestMcpTool[] {
|
|
175
|
+
const granted = new Set(normalizeSlackScopes(scopes));
|
|
176
|
+
return SLACK_REST_MCP_TOOLS.filter((entry) =>
|
|
177
|
+
REQUIRED_ANY_SCOPES[entry.name]?.some((scope) => granted.has(scope)),
|
|
178
|
+
).map((entry) => ({
|
|
179
|
+
...entry,
|
|
180
|
+
inputSchema: {
|
|
181
|
+
...entry.inputSchema,
|
|
182
|
+
required: [...entry.inputSchema.required],
|
|
183
|
+
properties: { ...entry.inputSchema.properties },
|
|
184
|
+
},
|
|
185
|
+
annotations: { ...entry.annotations },
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export const SLACK_CONVERSATION_READ_SCOPE_BY_TYPE = {
|
|
190
|
+
public_channel: "channels:read",
|
|
191
|
+
private_channel: "groups:read",
|
|
192
|
+
im: "im:read",
|
|
193
|
+
mpim: "mpim:read",
|
|
194
|
+
} as const;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const SLACK_TASK_POLICY_ID_MAX_CHARS = 128;
|
|
4
|
+
export const SLACK_TASK_POLICY_REASON_MAX_CHARS = 4_096;
|
|
5
|
+
export const SLACK_TASK_POLICY_MAX_IDS = 256;
|
|
6
|
+
|
|
7
|
+
const SlackOpaqueId = z.string().min(1).max(SLACK_TASK_POLICY_ID_MAX_CHARS);
|
|
8
|
+
|
|
9
|
+
export const SlackSharedConversationMode = z.enum(["deny", "private_handoff"]);
|
|
10
|
+
export type SlackSharedConversationMode = z.infer<typeof SlackSharedConversationMode>;
|
|
11
|
+
|
|
12
|
+
export const SlackResultPublicationMode = z.enum(["never", "approval_required", "allow"]);
|
|
13
|
+
export type SlackResultPublicationMode = z.infer<typeof SlackResultPublicationMode>;
|
|
14
|
+
|
|
15
|
+
function uniqueSortedIds(values: string[]): string[] {
|
|
16
|
+
return [...new Set(values)].sort();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const SlackTaskPolicyContent = z
|
|
20
|
+
.object({
|
|
21
|
+
allowedTeamIds: z
|
|
22
|
+
.array(SlackOpaqueId)
|
|
23
|
+
.max(SLACK_TASK_POLICY_MAX_IDS)
|
|
24
|
+
.transform(uniqueSortedIds),
|
|
25
|
+
allowedConversationIds: z
|
|
26
|
+
.array(SlackOpaqueId)
|
|
27
|
+
.max(SLACK_TASK_POLICY_MAX_IDS)
|
|
28
|
+
.transform(uniqueSortedIds),
|
|
29
|
+
allowGuestInitiators: z.boolean(),
|
|
30
|
+
allowExternalInitiators: z.boolean(),
|
|
31
|
+
allowMpim: z.boolean(),
|
|
32
|
+
sharedConversationMode: SlackSharedConversationMode,
|
|
33
|
+
resultPublicationMode: SlackResultPublicationMode,
|
|
34
|
+
})
|
|
35
|
+
.strict();
|
|
36
|
+
export type SlackTaskPolicyContent = z.infer<typeof SlackTaskPolicyContent>;
|
|
37
|
+
|
|
38
|
+
export const DEFAULT_SLACK_TASK_POLICY: SlackTaskPolicyContent = Object.freeze({
|
|
39
|
+
allowedTeamIds: [],
|
|
40
|
+
allowedConversationIds: [],
|
|
41
|
+
allowGuestInitiators: false,
|
|
42
|
+
allowExternalInitiators: false,
|
|
43
|
+
allowMpim: false,
|
|
44
|
+
sharedConversationMode: "deny",
|
|
45
|
+
resultPublicationMode: "never",
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export function canonicalizeSlackTaskPolicy(value: SlackTaskPolicyContent): SlackTaskPolicyContent {
|
|
49
|
+
const parsed = SlackTaskPolicyContent.parse(value);
|
|
50
|
+
return {
|
|
51
|
+
allowedTeamIds: parsed.allowedTeamIds,
|
|
52
|
+
allowedConversationIds: parsed.allowedConversationIds,
|
|
53
|
+
allowGuestInitiators: parsed.allowGuestInitiators,
|
|
54
|
+
allowExternalInitiators: parsed.allowExternalInitiators,
|
|
55
|
+
allowMpim: parsed.allowMpim,
|
|
56
|
+
sharedConversationMode: parsed.sharedConversationMode,
|
|
57
|
+
resultPublicationMode: parsed.resultPublicationMode,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const SlackTaskPolicyRevisionIdentity = z.object({
|
|
62
|
+
id: z.string().uuid(),
|
|
63
|
+
revision: z.number().int().positive(),
|
|
64
|
+
policyHash: z.string().regex(/^[0-9a-f]{64}$/),
|
|
65
|
+
});
|
|
66
|
+
export type SlackTaskPolicyRevisionIdentity = z.infer<typeof SlackTaskPolicyRevisionIdentity>;
|
|
67
|
+
|
|
68
|
+
export const SlackTaskPolicyRevision = SlackTaskPolicyRevisionIdentity.extend({
|
|
69
|
+
operationId: z.string().uuid(),
|
|
70
|
+
accountId: z.string().uuid(),
|
|
71
|
+
workspaceId: z.string().uuid(),
|
|
72
|
+
policy: SlackTaskPolicyContent,
|
|
73
|
+
supersedesRevisionId: z.string().uuid().nullable(),
|
|
74
|
+
createdBySubjectId: z.string().min(1).max(1_024),
|
|
75
|
+
createdAt: z.string().datetime(),
|
|
76
|
+
});
|
|
77
|
+
export type SlackTaskPolicyRevision = z.infer<typeof SlackTaskPolicyRevision>;
|
|
78
|
+
|
|
79
|
+
export const SlackTaskPolicyHead = z.object({
|
|
80
|
+
accountId: z.string().uuid(),
|
|
81
|
+
workspaceId: z.string().uuid(),
|
|
82
|
+
revisionId: z.string().uuid(),
|
|
83
|
+
revision: z.number().int().positive(),
|
|
84
|
+
policyHash: z.string().regex(/^[0-9a-f]{64}$/),
|
|
85
|
+
activationVersion: z.number().int().positive(),
|
|
86
|
+
activatedAt: z.string().datetime(),
|
|
87
|
+
});
|
|
88
|
+
export type SlackTaskPolicyHead = z.infer<typeof SlackTaskPolicyHead>;
|
|
89
|
+
|
|
90
|
+
export const SlackTaskPolicyActivationEvent = z.object({
|
|
91
|
+
id: z.string().uuid(),
|
|
92
|
+
operationId: z.string().uuid(),
|
|
93
|
+
accountId: z.string().uuid(),
|
|
94
|
+
workspaceId: z.string().uuid(),
|
|
95
|
+
activationVersion: z.number().int().positive(),
|
|
96
|
+
oldRevision: SlackTaskPolicyRevisionIdentity.nullable(),
|
|
97
|
+
newRevision: SlackTaskPolicyRevisionIdentity,
|
|
98
|
+
actorSubjectId: z.string().min(1).max(1_024),
|
|
99
|
+
reason: z.string().min(1).max(SLACK_TASK_POLICY_REASON_MAX_CHARS),
|
|
100
|
+
createdAt: z.string().datetime(),
|
|
101
|
+
});
|
|
102
|
+
export type SlackTaskPolicyActivationEvent = z.infer<typeof SlackTaskPolicyActivationEvent>;
|
|
103
|
+
|
|
104
|
+
export const SlackTaskPolicyListResponse = z.object({
|
|
105
|
+
current: SlackTaskPolicyHead.nullable(),
|
|
106
|
+
activeRevision: SlackTaskPolicyRevision.nullable(),
|
|
107
|
+
revisions: z.array(SlackTaskPolicyRevision),
|
|
108
|
+
activationEvents: z.array(SlackTaskPolicyActivationEvent),
|
|
109
|
+
});
|
|
110
|
+
export type SlackTaskPolicyListResponse = z.infer<typeof SlackTaskPolicyListResponse>;
|
|
111
|
+
|
|
112
|
+
export const UpdateSlackTaskPolicyRequest = z.object({
|
|
113
|
+
operationId: z.string().uuid().optional(),
|
|
114
|
+
policy: SlackTaskPolicyContent,
|
|
115
|
+
expectedCurrentRevisionId: z.string().uuid().nullable(),
|
|
116
|
+
expectedActivationVersion: z.number().int().nonnegative(),
|
|
117
|
+
reason: z.string().trim().min(1).max(SLACK_TASK_POLICY_REASON_MAX_CHARS),
|
|
118
|
+
});
|
|
119
|
+
export type UpdateSlackTaskPolicyRequest = z.infer<typeof UpdateSlackTaskPolicyRequest>;
|
|
120
|
+
|
|
121
|
+
export const SlackTaskPolicyMutationResponse = z.object({
|
|
122
|
+
revision: SlackTaskPolicyRevision,
|
|
123
|
+
head: SlackTaskPolicyHead,
|
|
124
|
+
event: SlackTaskPolicyActivationEvent,
|
|
125
|
+
});
|
|
126
|
+
export type SlackTaskPolicyMutationResponse = z.infer<typeof SlackTaskPolicyMutationResponse>;
|
|
127
|
+
|
|
128
|
+
export type SlackTaskPolicyConversationFacts = Readonly<{
|
|
129
|
+
installationTeamId: string;
|
|
130
|
+
conversationId: string;
|
|
131
|
+
contextTeamId: string | null;
|
|
132
|
+
connectedTeamIds: readonly string[] | null;
|
|
133
|
+
sharedTeamIds: readonly string[] | null;
|
|
134
|
+
isShared: boolean;
|
|
135
|
+
isExternallyShared: boolean;
|
|
136
|
+
isOrgShared: boolean;
|
|
137
|
+
isPendingExternallyShared: boolean;
|
|
138
|
+
isMpim: boolean;
|
|
139
|
+
}>;
|
|
140
|
+
|
|
141
|
+
export type SlackTaskPolicyInitiatorFacts = Readonly<{
|
|
142
|
+
teamId: string | null;
|
|
143
|
+
isGuest: boolean | null;
|
|
144
|
+
isExternal: boolean | null;
|
|
145
|
+
}>;
|
|
146
|
+
|
|
147
|
+
export type SlackTaskPolicyDecision = Readonly<{
|
|
148
|
+
disposition: "ordinary" | "deny" | "private_handoff";
|
|
149
|
+
publication: SlackResultPublicationMode;
|
|
150
|
+
reason:
|
|
151
|
+
| "ordinary_conversation"
|
|
152
|
+
| "policy_missing"
|
|
153
|
+
| "conversation_not_allowed"
|
|
154
|
+
| "team_not_allowed"
|
|
155
|
+
| "ambiguous_shared_facts"
|
|
156
|
+
| "mpim_not_allowed"
|
|
157
|
+
| "guest_not_allowed"
|
|
158
|
+
| "external_not_allowed"
|
|
159
|
+
| "allowed";
|
|
160
|
+
}>;
|
|
161
|
+
|
|
162
|
+
export function evaluateSlackTaskPolicy(input: {
|
|
163
|
+
policy: SlackTaskPolicyContent | null;
|
|
164
|
+
conversation: SlackTaskPolicyConversationFacts;
|
|
165
|
+
initiator: SlackTaskPolicyInitiatorFacts;
|
|
166
|
+
}): SlackTaskPolicyDecision {
|
|
167
|
+
const { conversation, initiator } = input;
|
|
168
|
+
const governed =
|
|
169
|
+
conversation.isShared ||
|
|
170
|
+
conversation.isExternallyShared ||
|
|
171
|
+
conversation.isOrgShared ||
|
|
172
|
+
conversation.isPendingExternallyShared ||
|
|
173
|
+
conversation.isMpim;
|
|
174
|
+
if (!governed) {
|
|
175
|
+
return { disposition: "ordinary", publication: "allow", reason: "ordinary_conversation" };
|
|
176
|
+
}
|
|
177
|
+
if (!input.policy) return { disposition: "deny", publication: "never", reason: "policy_missing" };
|
|
178
|
+
const policy = canonicalizeSlackTaskPolicy(input.policy);
|
|
179
|
+
if (!policy.allowedConversationIds.includes(conversation.conversationId)) {
|
|
180
|
+
return { disposition: "deny", publication: "never", reason: "conversation_not_allowed" };
|
|
181
|
+
}
|
|
182
|
+
if (conversation.isMpim && !policy.allowMpim) {
|
|
183
|
+
return { disposition: "deny", publication: "never", reason: "mpim_not_allowed" };
|
|
184
|
+
}
|
|
185
|
+
if (initiator.isGuest === null || initiator.isExternal === null || initiator.teamId === null) {
|
|
186
|
+
return { disposition: "deny", publication: "never", reason: "ambiguous_shared_facts" };
|
|
187
|
+
}
|
|
188
|
+
if (initiator.isGuest && !policy.allowGuestInitiators) {
|
|
189
|
+
return { disposition: "deny", publication: "never", reason: "guest_not_allowed" };
|
|
190
|
+
}
|
|
191
|
+
if (initiator.isExternal && !policy.allowExternalInitiators) {
|
|
192
|
+
return { disposition: "deny", publication: "never", reason: "external_not_allowed" };
|
|
193
|
+
}
|
|
194
|
+
const teams = [
|
|
195
|
+
conversation.installationTeamId,
|
|
196
|
+
conversation.contextTeamId,
|
|
197
|
+
initiator.teamId,
|
|
198
|
+
...(conversation.connectedTeamIds ?? []),
|
|
199
|
+
...(conversation.sharedTeamIds ?? []),
|
|
200
|
+
];
|
|
201
|
+
if (conversation.connectedTeamIds === null || conversation.sharedTeamIds === null) {
|
|
202
|
+
return { disposition: "deny", publication: "never", reason: "ambiguous_shared_facts" };
|
|
203
|
+
}
|
|
204
|
+
if (teams.some((teamId) => teamId === null || !policy.allowedTeamIds.includes(teamId))) {
|
|
205
|
+
return { disposition: "deny", publication: "never", reason: "team_not_allowed" };
|
|
206
|
+
}
|
|
207
|
+
if (policy.sharedConversationMode === "deny") {
|
|
208
|
+
return { disposition: "deny", publication: "never", reason: "allowed" };
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
disposition: "private_handoff",
|
|
212
|
+
publication: policy.resultPublicationMode,
|
|
213
|
+
reason: "allowed",
|
|
214
|
+
};
|
|
215
|
+
}
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
canonicalSpreadsheetDateFromMilliseconds,
|
|
3
3
|
canonicalSpreadsheetDateMilliseconds,
|
|
4
4
|
} from "./spreadsheet-artifact-date";
|
|
5
|
+
import { SPREADSHEET_ARTIFACT_COMMAND_VERSION } from "./editable-artifact-versions";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Canonical, identity-free spreadsheet mutation commands nested inside
|
|
@@ -10,14 +11,14 @@ import {
|
|
|
10
11
|
* authority.
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
|
-
export
|
|
14
|
+
export { SPREADSHEET_ARTIFACT_COMMAND_VERSION } from "./editable-artifact-versions";
|
|
14
15
|
export const SPREADSHEET_ARTIFACT_COMMAND_MAX_BYTES = 4 * 1024 * 1024;
|
|
15
16
|
export const SPREADSHEET_ARTIFACT_COMMAND_MAX_COMMANDS = 4_096;
|
|
16
17
|
export const SPREADSHEET_ARTIFACT_COMMAND_MAX_CELLS = 1_000_000;
|
|
17
18
|
export const SPREADSHEET_ARTIFACT_COMMAND_MAX_STRING_BYTES = 1 * 1024 * 1024;
|
|
18
19
|
export const SPREADSHEET_ARTIFACT_SHEET_NAME_MAX_UTF16_UNITS = 31;
|
|
19
20
|
|
|
20
|
-
const MAGIC = new TextEncoder().encode("
|
|
21
|
+
const MAGIC = new TextEncoder().encode("OGASC002");
|
|
21
22
|
const HEADER_BYTES = 8 + 2 + 2 + 4 + 8;
|
|
22
23
|
const CHECKSUM_BYTES = 8;
|
|
23
24
|
const textEncoder = new TextEncoder();
|
|
@@ -78,7 +79,6 @@ export type SpreadsheetCellScalar =
|
|
|
78
79
|
| SpreadsheetFormulaError;
|
|
79
80
|
export type SpreadsheetFormulaCell = Readonly<{
|
|
80
81
|
formula: string;
|
|
81
|
-
cached: SpreadsheetCellScalar;
|
|
82
82
|
}>;
|
|
83
83
|
export type SpreadsheetCellInput = SpreadsheetCellScalar | SpreadsheetFormulaCell;
|
|
84
84
|
|
|
@@ -491,7 +491,7 @@ function batchRecord(input: unknown): SpreadsheetArtifactCommandBatch {
|
|
|
491
491
|
const batch = plainRecord(input, "spreadsheet command batch");
|
|
492
492
|
exactKeys(batch, ["commands", "version"], "spreadsheet command batch");
|
|
493
493
|
if (batch.version !== SPREADSHEET_ARTIFACT_COMMAND_VERSION) {
|
|
494
|
-
throw new TypeError("spreadsheet command batch version must be
|
|
494
|
+
throw new TypeError("spreadsheet command batch version must be 2");
|
|
495
495
|
}
|
|
496
496
|
if (!Array.isArray(batch.commands)) throw new TypeError("commands must be an array");
|
|
497
497
|
if (
|
|
@@ -770,13 +770,12 @@ class BinaryWriter {
|
|
|
770
770
|
cell(value: unknown): void {
|
|
771
771
|
if (isFormulaCell(value)) {
|
|
772
772
|
const cell = plainRecord(value, "formula cell");
|
|
773
|
-
exactKeys(cell, ["
|
|
773
|
+
exactKeys(cell, ["formula"], "formula cell");
|
|
774
774
|
if (typeof cell.formula !== "string" || cell.formula.length === 0) {
|
|
775
775
|
throw new TypeError("formula source must be a nonempty string");
|
|
776
776
|
}
|
|
777
777
|
this.u8(1);
|
|
778
778
|
this.string(cell.formula, SPREADSHEET_ARTIFACT_COMMAND_MAX_STRING_BYTES);
|
|
779
|
-
this.scalar(cell.cached);
|
|
780
779
|
return;
|
|
781
780
|
}
|
|
782
781
|
this.u8(0);
|
|
@@ -902,12 +901,12 @@ class BinaryReader {
|
|
|
902
901
|
cell(): SpreadsheetCellInput {
|
|
903
902
|
const formulaTag = this.u8();
|
|
904
903
|
if (formulaTag > 1) throw new TypeError("spreadsheet formula presence tag is invalid");
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
return
|
|
904
|
+
if (formulaTag === 1) {
|
|
905
|
+
return Object.freeze({
|
|
906
|
+
formula: this.nonemptyFormula(this.string(SPREADSHEET_ARTIFACT_COMMAND_MAX_STRING_BYTES)),
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
return this.scalar();
|
|
911
910
|
}
|
|
912
911
|
|
|
913
912
|
done(message: string): void {
|
|
@@ -981,7 +980,7 @@ function isFormulaError(value: unknown): value is SpreadsheetFormulaError {
|
|
|
981
980
|
typeof value === "object" &&
|
|
982
981
|
value !== null &&
|
|
983
982
|
!Array.isArray(value) &&
|
|
984
|
-
|
|
983
|
+
Object.hasOwn(value, "error")
|
|
985
984
|
);
|
|
986
985
|
}
|
|
987
986
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ClaudeSubscriptionUsage } from "./claude-subscription-usage";
|
|
3
|
+
|
|
4
|
+
/** Shared, secret-free account list contract for native subscription pools. */
|
|
5
|
+
export const SubscriptionAccountSummary = z.object({
|
|
6
|
+
id: z.string().uuid(),
|
|
7
|
+
scope: z.enum(["organization", "workspace", "user"]),
|
|
8
|
+
subject: z.string().min(1),
|
|
9
|
+
email: z.string().email().nullable(),
|
|
10
|
+
label: z.string().nullable(),
|
|
11
|
+
plan: z.string().nullable(),
|
|
12
|
+
status: z.enum(["active", "needs_relogin", "error", "disabled"]),
|
|
13
|
+
active: z.boolean(),
|
|
14
|
+
expiresAt: z.string().datetime().nullable(),
|
|
15
|
+
lastRefreshAt: z.string().datetime().nullable(),
|
|
16
|
+
lastError: z.string().nullable(),
|
|
17
|
+
allocatorEnabled: z.boolean(),
|
|
18
|
+
allocatorVersion: z.number().int().positive(),
|
|
19
|
+
allocatorUpdatedAt: z.string().datetime().nullable(),
|
|
20
|
+
});
|
|
21
|
+
export type SubscriptionAccountSummary = z.infer<typeof SubscriptionAccountSummary>;
|
|
22
|
+
export const SubscriptionPoolSettings = z
|
|
23
|
+
.object({
|
|
24
|
+
rotationEnabled: z.boolean(),
|
|
25
|
+
rotationStrategy: z.literal("sharded"),
|
|
26
|
+
activeCredentialId: z.string().uuid().nullable(),
|
|
27
|
+
})
|
|
28
|
+
.strict();
|
|
29
|
+
export type SubscriptionPoolSettings = z.infer<typeof SubscriptionPoolSettings>;
|
|
30
|
+
export const ClaudeSubscriptionAccount = SubscriptionAccountSummary.extend({
|
|
31
|
+
version: z.number().int().positive(),
|
|
32
|
+
usage: ClaudeSubscriptionUsage.optional(),
|
|
33
|
+
}).strict();
|
|
34
|
+
export type ClaudeSubscriptionAccount = z.infer<typeof ClaudeSubscriptionAccount>;
|
|
35
|
+
export const ClaudeSubscriptionAccountsResponse = z
|
|
36
|
+
.object({
|
|
37
|
+
accounts: z.array(ClaudeSubscriptionAccount),
|
|
38
|
+
activeAccountId: z.string().uuid().nullable(),
|
|
39
|
+
source: z.enum(["organization", "workspace", "user"]),
|
|
40
|
+
organizationId: z.string().uuid(),
|
|
41
|
+
settings: SubscriptionPoolSettings,
|
|
42
|
+
})
|
|
43
|
+
.strict();
|
|
44
|
+
export type ClaudeSubscriptionAccountsResponse = z.infer<typeof ClaudeSubscriptionAccountsResponse>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const TASK_NOTE_TEXT_MAX_BYTES = 4_096;
|
|
4
|
+
export const TASK_NOTE_REASON_MAX_BYTES = 2_048;
|
|
5
|
+
export const TASK_NOTE_MAX_LIFETIME_DAYS = 90;
|
|
6
|
+
export const TASK_NOTE_ACTIVE_RECORD_CAP = 500;
|
|
7
|
+
export const TASK_NOTE_LIST_DEFAULT_LIMIT = 10;
|
|
8
|
+
export const TASK_NOTE_LIST_MAX_LIMIT = 20;
|
|
9
|
+
export const TASK_NOTE_LIST_RESPONSE_MAX_BYTES = 96 * 1_024;
|
|
10
|
+
|
|
11
|
+
const utf8Bytes = (value: string): number => new TextEncoder().encode(value).byteLength;
|
|
12
|
+
|
|
13
|
+
export function boundedTaskNoteText(maxBytes: number, label: string) {
|
|
14
|
+
return z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1)
|
|
17
|
+
.superRefine((value, ctx) => {
|
|
18
|
+
if (value !== value.trim()) {
|
|
19
|
+
ctx.addIssue({
|
|
20
|
+
code: z.ZodIssueCode.custom,
|
|
21
|
+
message: `${label} must not have leading or trailing whitespace`,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (utf8Bytes(value) > maxBytes) {
|
|
25
|
+
ctx.addIssue({
|
|
26
|
+
code: z.ZodIssueCode.custom,
|
|
27
|
+
message: `${label} must be at most ${maxBytes} UTF-8 bytes`,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const TaskNoteText = boundedTaskNoteText(TASK_NOTE_TEXT_MAX_BYTES, "task note text");
|
|
34
|
+
export const TaskNoteReason = boundedTaskNoteText(
|
|
35
|
+
TASK_NOTE_REASON_MAX_BYTES,
|
|
36
|
+
"task note archive reason",
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export const TaskNoteKind = z.enum([
|
|
40
|
+
"finding",
|
|
41
|
+
"decision",
|
|
42
|
+
"blocker",
|
|
43
|
+
"ownership",
|
|
44
|
+
"artifact",
|
|
45
|
+
"handoff",
|
|
46
|
+
]);
|
|
47
|
+
export type TaskNoteKind = z.infer<typeof TaskNoteKind>;
|
|
48
|
+
|
|
49
|
+
export const TaskNoteStatus = z.enum(["active", "archived"]);
|
|
50
|
+
export type TaskNoteStatus = z.infer<typeof TaskNoteStatus>;
|
|
51
|
+
|
|
52
|
+
export const TaskNoteActorKind = z.enum(["human", "service"]);
|
|
53
|
+
export type TaskNoteActorKind = z.infer<typeof TaskNoteActorKind>;
|
|
54
|
+
|
|
55
|
+
export const TaskNote = z.object({
|
|
56
|
+
id: z.string().uuid(),
|
|
57
|
+
rootSessionId: z.string().uuid(),
|
|
58
|
+
kind: TaskNoteKind,
|
|
59
|
+
text: TaskNoteText,
|
|
60
|
+
status: TaskNoteStatus,
|
|
61
|
+
version: z.number().int().positive(),
|
|
62
|
+
expiresAt: z.string().datetime({ offset: true }),
|
|
63
|
+
createdAt: z.string().datetime({ offset: true }),
|
|
64
|
+
updatedAt: z.string().datetime({ offset: true }),
|
|
65
|
+
archivedAt: z.string().datetime({ offset: true }).nullable(),
|
|
66
|
+
provenance: z.object({
|
|
67
|
+
actorKind: TaskNoteActorKind,
|
|
68
|
+
sourceSessionId: z.string().uuid(),
|
|
69
|
+
sourceTurnId: z.string().uuid(),
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
72
|
+
export type TaskNote = z.infer<typeof TaskNote>;
|
|
73
|
+
|
|
74
|
+
export const TaskNoteMutationResult = z.object({
|
|
75
|
+
note: TaskNote,
|
|
76
|
+
replayed: z.boolean(),
|
|
77
|
+
});
|
|
78
|
+
export type TaskNoteMutationResult = z.infer<typeof TaskNoteMutationResult>;
|
|
79
|
+
|
|
80
|
+
/** Atomic correction lineage: archive one exact v1 note and create one v1 replacement. */
|
|
81
|
+
export const TaskNoteReplacementResult = z.object({
|
|
82
|
+
operationId: z.string().uuid(),
|
|
83
|
+
inputHash: z.string().regex(/^[0-9a-f]{64}$/),
|
|
84
|
+
replaces: z.object({
|
|
85
|
+
noteId: z.string().uuid(),
|
|
86
|
+
archivedVersion: z.literal(2),
|
|
87
|
+
}),
|
|
88
|
+
replacement: TaskNote,
|
|
89
|
+
replayed: z.boolean(),
|
|
90
|
+
});
|
|
91
|
+
export type TaskNoteReplacementResult = z.infer<typeof TaskNoteReplacementResult>;
|
|
92
|
+
|
|
93
|
+
export const TaskNoteListResponse = z
|
|
94
|
+
.object({
|
|
95
|
+
notes: z.array(TaskNote).max(TASK_NOTE_LIST_MAX_LIMIT),
|
|
96
|
+
})
|
|
97
|
+
.superRefine((value, ctx) => {
|
|
98
|
+
if (utf8Bytes(JSON.stringify(value)) > TASK_NOTE_LIST_RESPONSE_MAX_BYTES) {
|
|
99
|
+
ctx.addIssue({
|
|
100
|
+
code: z.ZodIssueCode.custom,
|
|
101
|
+
message: `task note list response must be at most ${TASK_NOTE_LIST_RESPONSE_MAX_BYTES} UTF-8 bytes`,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
export type TaskNoteListResponse = z.infer<typeof TaskNoteListResponse>;
|