@opengeni/contracts 0.40.0 → 0.44.1

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.
Files changed (125) hide show
  1. package/dist/atlassian.d.ts +278 -0
  2. package/dist/atlassian.js +55 -0
  3. package/dist/atlassian.js.map +1 -0
  4. package/dist/chunk-52SGB2QO.js +688 -0
  5. package/dist/chunk-52SGB2QO.js.map +1 -0
  6. package/dist/{chunk-7JZMI22I.js → chunk-5UDNP7AO.js} +34 -2
  7. package/dist/chunk-5UDNP7AO.js.map +1 -0
  8. package/dist/chunk-BVGIYW7D.js +11 -0
  9. package/dist/chunk-BVGIYW7D.js.map +1 -0
  10. package/dist/chunk-CADSX6UN.js +1145 -0
  11. package/dist/chunk-CADSX6UN.js.map +1 -0
  12. package/dist/chunk-D2HKF2EF.js +1460 -0
  13. package/dist/chunk-D2HKF2EF.js.map +1 -0
  14. package/dist/chunk-FJBG5E4O.js +194 -0
  15. package/dist/chunk-FJBG5E4O.js.map +1 -0
  16. package/dist/chunk-H5BVCZKF.js +382 -0
  17. package/dist/chunk-H5BVCZKF.js.map +1 -0
  18. package/dist/chunk-LSB7GRLG.js +779 -0
  19. package/dist/chunk-LSB7GRLG.js.map +1 -0
  20. package/dist/chunk-MYBZRDTY.js +340 -0
  21. package/dist/chunk-MYBZRDTY.js.map +1 -0
  22. package/dist/chunk-RIY7GYQS.js +1204 -0
  23. package/dist/chunk-RIY7GYQS.js.map +1 -0
  24. package/dist/chunk-TZ6YEYN4.js +386 -0
  25. package/dist/chunk-TZ6YEYN4.js.map +1 -0
  26. package/dist/chunk-VA22KRHS.js +15177 -0
  27. package/dist/chunk-VA22KRHS.js.map +1 -0
  28. package/dist/chunk-Y3MLSLB4.js +392 -0
  29. package/dist/chunk-Y3MLSLB4.js.map +1 -0
  30. package/dist/chunk-YRKRZ6OF.js +134 -0
  31. package/dist/chunk-YRKRZ6OF.js.map +1 -0
  32. package/dist/company-profile.d.ts +629 -0
  33. package/dist/document-artifact-commands.d.ts +282 -0
  34. package/dist/document-artifact-commands.js +54 -0
  35. package/dist/document-artifact-commands.js.map +1 -0
  36. package/dist/document-artifact-query.d.ts +2 -0
  37. package/dist/document-artifact-query.js +54 -0
  38. package/dist/document-artifact-query.js.map +1 -0
  39. package/dist/editable-artifact-binary.d.ts +56 -0
  40. package/dist/editable-artifact-causal-frontier.d.ts +12 -0
  41. package/dist/editable-artifact-causal-frontier.js +18 -0
  42. package/dist/editable-artifact-causal-frontier.js.map +1 -0
  43. package/dist/editable-artifact-codec-registry.d.ts +48 -0
  44. package/dist/editable-artifact-codec-registry.js +20 -0
  45. package/dist/editable-artifact-codec-registry.js.map +1 -0
  46. package/dist/editable-artifact-committed-transaction.d.ts +35 -0
  47. package/dist/editable-artifact-committed-transaction.js +19 -0
  48. package/dist/editable-artifact-committed-transaction.js.map +1 -0
  49. package/dist/editable-artifact-live.d.ts +276 -0
  50. package/dist/editable-artifact-live.js +907 -0
  51. package/dist/editable-artifact-live.js.map +1 -0
  52. package/dist/editable-artifact-serialized-commit.d.ts +53 -0
  53. package/dist/editable-artifact-serialized-commit.js +26 -0
  54. package/dist/editable-artifact-serialized-commit.js.map +1 -0
  55. package/dist/editable-artifact-versions.d.ts +6 -0
  56. package/dist/editable-artifact-versions.js +11 -0
  57. package/dist/editable-artifact-versions.js.map +1 -0
  58. package/dist/editable-artifacts.d.ts +46 -0
  59. package/dist/editable-artifacts.js +236 -0
  60. package/dist/editable-artifacts.js.map +1 -0
  61. package/dist/event-preview.d.ts +1 -1
  62. package/dist/google-drive.d.ts +114 -2
  63. package/dist/google-drive.js +70 -14
  64. package/dist/google-drive.js.map +1 -1
  65. package/dist/image-generation.d.ts +70 -0
  66. package/dist/index.d.ts +4460 -155
  67. package/dist/index.js +1127 -30
  68. package/dist/interaction.d.ts +6895 -0
  69. package/dist/memory-slack-delivery.d.ts +397 -0
  70. package/dist/presentation-artifact-commands.d.ts +349 -0
  71. package/dist/presentation-artifact-commands.js +66 -0
  72. package/dist/presentation-artifact-commands.js.map +1 -0
  73. package/dist/presentation-artifact-query.d.ts +2 -0
  74. package/dist/presentation-artifact-query.js +66 -0
  75. package/dist/presentation-artifact-query.js.map +1 -0
  76. package/dist/retained-output.d.ts +24 -0
  77. package/dist/sandbox-snapshots.d.ts +9 -0
  78. package/dist/scoped-knowledge.d.ts +14 -13
  79. package/dist/slack-bot-scopes.d.ts +4 -0
  80. package/dist/slack-bot-scopes.js +3 -1
  81. package/dist/spreadsheet-artifact-commands.d.ts +101 -0
  82. package/dist/spreadsheet-artifact-commands.js +27 -0
  83. package/dist/spreadsheet-artifact-commands.js.map +1 -0
  84. package/dist/spreadsheet-artifact-date.d.ts +4 -0
  85. package/dist/spreadsheet-artifact-query.d.ts +120 -0
  86. package/dist/spreadsheet-artifact-query.js +48 -0
  87. package/dist/spreadsheet-artifact-query.js.map +1 -0
  88. package/dist/tool-catalog.d.ts +576 -0
  89. package/dist/video-generation.d.ts +532 -0
  90. package/dist/video-generation.js +51 -0
  91. package/dist/video-generation.js.map +1 -0
  92. package/dist/workspace-learning-policy.d.ts +208 -0
  93. package/package.json +61 -1
  94. package/src/atlassian.ts +160 -0
  95. package/src/company-profile.ts +306 -0
  96. package/src/document-artifact-commands.ts +1709 -0
  97. package/src/document-artifact-query.ts +2 -0
  98. package/src/editable-artifact-binary.ts +396 -0
  99. package/src/editable-artifact-causal-frontier.ts +154 -0
  100. package/src/editable-artifact-codec-registry.ts +261 -0
  101. package/src/editable-artifact-committed-transaction.ts +478 -0
  102. package/src/editable-artifact-live.ts +1379 -0
  103. package/src/editable-artifact-serialized-commit.ts +494 -0
  104. package/src/editable-artifact-versions.ts +8 -0
  105. package/src/editable-artifacts.ts +473 -0
  106. package/src/google-drive.ts +68 -15
  107. package/src/image-generation.ts +106 -0
  108. package/src/index.ts +2326 -325
  109. package/src/interaction.ts +2292 -0
  110. package/src/memory-slack-delivery.ts +183 -0
  111. package/src/presentation-artifact-commands.ts +2035 -0
  112. package/src/presentation-artifact-query.ts +2 -0
  113. package/src/retained-output.ts +149 -2
  114. package/src/sandbox-snapshots.ts +28 -1
  115. package/src/scoped-knowledge.ts +18 -4
  116. package/src/slack-bot-scopes.ts +34 -1
  117. package/src/spreadsheet-artifact-commands.ts +999 -0
  118. package/src/spreadsheet-artifact-date.ts +21 -0
  119. package/src/spreadsheet-artifact-query.ts +1411 -0
  120. package/src/tool-catalog.ts +334 -0
  121. package/src/video-generation.ts +394 -0
  122. package/src/workspace-learning-policy.ts +233 -0
  123. package/dist/chunk-5HR2GPSC.js +0 -11031
  124. package/dist/chunk-5HR2GPSC.js.map +0 -1
  125. package/dist/chunk-7JZMI22I.js.map +0 -1
package/src/index.ts CHANGED
@@ -1,15 +1,27 @@
1
1
  import { z } from "zod";
2
+ import { ScopedKnowledgeScope } from "./scoped-knowledge";
2
3
  import {
3
4
  boundSessionEventPayload,
4
5
  measureSessionEventJson,
5
6
  sessionEventJsonBytes,
6
7
  type SessionEventBoundarySurface,
7
8
  } from "./event-preview";
9
+ import { MemorySlackPublicationDistribution } from "./memory-slack-delivery";
8
10
  import { WorkspaceInstructionPolicyRoleKeyInput } from "./workspace-instruction-policies";
9
11
  import { ClientResumableVoiceInputConfig } from "./transcription-recordings";
12
+ import { MediaGenerationResult } from "./video-generation";
10
13
 
11
14
  export * from "./slack-bot-scopes";
15
+ export * from "./atlassian";
12
16
  export * from "./connector-destinations";
17
+ export * from "./memory-slack-delivery";
18
+ export * from "./image-generation";
19
+ export * from "./video-generation";
20
+ export * from "./editable-artifacts";
21
+ export * from "./editable-artifact-committed-transaction";
22
+ export * from "./editable-artifact-serialized-commit";
23
+ export * from "./tool-catalog";
24
+ export * from "./interaction";
13
25
 
14
26
  export {
15
27
  CreateWorkspaceArtifactRequest,
@@ -71,6 +83,8 @@ export {
71
83
  COMPUTER_SCREENSHOT_MAX_PIXELS,
72
84
  COMPUTER_SCREENSHOT_RETENTION_MS,
73
85
  COMPUTER_SCREENSHOT_WORKSPACE_QUOTA_BYTES,
86
+ GENERATED_IMAGE_MAX_BYTES,
87
+ GENERATED_VIDEO_MAX_BYTES,
74
88
  RETAINED_OUTPUT_DEFAULT_PAGE_BYTES,
75
89
  RETAINED_OUTPUT_MAX_PAGE_BYTES,
76
90
  RETAINED_OUTPUT_RECEIPT_MAX_BYTES,
@@ -81,6 +95,8 @@ export {
81
95
  RetainedOutputKind,
82
96
  RetainedOutputUnavailableReason,
83
97
  retainedArtifactReferenceFromFile,
98
+ retainedGeneratedImageReferenceFromFile,
99
+ retainedGeneratedVideoReferenceFromFile,
84
100
  retainedScreenshotReferenceFromFile,
85
101
  retainedOutputUnavailable,
86
102
  resolveRetainedOutputRange,
@@ -88,6 +104,8 @@ export {
88
104
  type RetainedArtifactFileInput,
89
105
  type RetainedArtifactMetadata,
90
106
  type RetainedArtifactReference,
107
+ type RetainedGeneratedImageArtifactInput,
108
+ type RetainedGeneratedVideoArtifactInput,
91
109
  type RetainedScreenshotArtifactInput,
92
110
  type RetainedArtifactUnavailable,
93
111
  type RetainedOutputAvailableEvidence,
@@ -101,6 +119,7 @@ export {
101
119
  WORKSPACE_ARCHIVE_DESCRIPTOR_VERSION,
102
120
  backendForNativeSnapshotProvider,
103
121
  decodeNativeSnapshotRef,
122
+ encodeNativeSnapshotRef,
104
123
  parseWorkspaceArchiveDescriptor,
105
124
  type NativeSnapshotDescriptor,
106
125
  type NativeSnapshotProvider,
@@ -147,6 +166,54 @@ export const SandboxBackend = z.enum([
147
166
  ]);
148
167
  export type SandboxBackend = z.infer<typeof SandboxBackend>;
149
168
 
169
+ // OpenGeni-owned identity carried beside the provider's opaque SDK envelope.
170
+ // Provider serializers intentionally use different keys (`sandboxId`,
171
+ // `devboxId`, `sandboxName`, ...); durable lease logic must not need to learn a
172
+ // new provider's private state shape. Existing envelopes remain readable via
173
+ // the legacy keys below, while every newly-serialized envelope carries this
174
+ // stable field.
175
+ export const OPENGENI_SANDBOX_PROVIDER_INSTANCE_ID_FIELD = "opengeniProviderInstanceId" as const;
176
+ export const SANDBOX_PROVIDER_INSTANCE_ID_FIELDS_BY_BACKEND = {
177
+ docker: ["containerId"],
178
+ modal: ["sandboxId"],
179
+ local: ["workspaceRootPath"],
180
+ none: [],
181
+ daytona: ["sandboxId"],
182
+ runloop: ["devboxId"],
183
+ e2b: ["sandboxId"],
184
+ // A Blaxel name is reusable after deletion. The SDK persists a canonical
185
+ // metadata identity (name + creation timestamp + workspace) specifically to
186
+ // distinguish a later sandbox created under the same name.
187
+ blaxel: ["sandboxIdentity"],
188
+ cloudflare: ["sandboxId"],
189
+ vercel: ["sandboxId"],
190
+ selfhosted: ["agentId"],
191
+ } as const satisfies Record<SandboxBackend, readonly string[]>;
192
+ export const LEGACY_SANDBOX_PROVIDER_INSTANCE_ID_FIELDS = [
193
+ "sandboxId",
194
+ "devboxId",
195
+ "sandboxName",
196
+ "sandboxIdentity",
197
+ "containerId",
198
+ "workspaceRootPath",
199
+ "agentId",
200
+ ] as const;
201
+
202
+ /**
203
+ * Durable proof that a provider may replace an execution wrapper without
204
+ * replacing the workspace OpenGeni owns. This is intentionally narrower than
205
+ * generic provider resume: only a provider adapter that can prove the same
206
+ * continuity key may consume it, and only a cold->warming owner or teardown
207
+ * claimant may authorize that replacement.
208
+ */
209
+ export type SandboxProviderContinuityRecovery = {
210
+ version: 1;
211
+ backend: SandboxBackend;
212
+ kind: "docker_workspace";
213
+ sourceInstanceId: string;
214
+ continuityKey: string;
215
+ };
216
+
150
217
  // OS axis. Only "linux" is reachable in v1; macos/windows are seam placeholders.
151
218
  export const SandboxOs = z.enum(["linux", "macos", "windows"]);
152
219
  export type SandboxOs = z.infer<typeof SandboxOs>;
@@ -217,6 +284,7 @@ export const DESKTOP_STREAM_PORT = 6080;
217
284
  // ttyd's default; the box bakes ttyd and launches it on this port. The pty-ws
218
285
  // Terminal cell's `url` is the tunnel address resolved against this port.
219
286
  export const TERMINAL_STREAM_PORT = 7681;
287
+ export const BROWSER_CONTROL_PORT = 7682;
220
288
 
221
289
  // The provider capability matrix (sandbox contract PART D + module 03-providers). One row per
222
290
  // backend (10 rows). v1 reachable cells are all Linux; macos/windows are seam
@@ -664,7 +732,7 @@ export const Permission = z.enum([
664
732
  // Programmatic sandbox -> tool access through the first-party MCP gate. This is
665
733
  // intentionally narrow and is never part of first-party MCP defaults; callers
666
734
  // must receive it through an explicit delegated `ogd_` mint carrying sessionId.
667
- "toolspace:call",
735
+ "codemode:call",
668
736
  "goals:manage",
669
737
  // Bring-your-own-compute (M5). enrollments:read lists a workspace's machines;
670
738
  // enrollments:manage approves a device-flow enrollment (the LOUD whole-machine
@@ -697,6 +765,7 @@ export type Permission = z.infer<typeof Permission>;
697
765
  */
698
766
  export const DEFAULT_FIRST_PARTY_MCP_PERMISSIONS = [
699
767
  "workspace:read",
768
+ "files:upload",
700
769
  "files:read",
701
770
  "documents:search",
702
771
  "scheduled_tasks:manage",
@@ -756,11 +825,27 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
756
825
  "session_resume",
757
826
  "session_steer",
758
827
  "set_other_session_title",
828
+ "interaction_discover",
829
+ "browser_open",
830
+ "browser_tabs",
831
+ "browser_observe",
832
+ "browser_act",
833
+ "browser_debug",
834
+ "browser_identity",
835
+ "browser_publish",
836
+ "browser_lifecycle",
837
+ "computer_open",
838
+ "computer_targets",
839
+ "computer_observe",
840
+ "computer_act",
841
+ "computer_lifecycle",
759
842
  "variable_set_list",
760
843
  "environment_list",
761
844
  "variable_set_get_variable",
762
845
  "variable_set_set_variable",
763
846
  "environment_set_variable",
847
+ "capability_catalog_search",
848
+ "capability_authorization_request",
764
849
  "github_connect_link",
765
850
  "github_repositories_list",
766
851
  "social_connections_list",
@@ -771,6 +856,18 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
771
856
  "social_thread_fetch",
772
857
  "social_posts_sync",
773
858
  "social_post_reply",
859
+ "x_accounts_list",
860
+ "x_search_live",
861
+ "x_mentions_live",
862
+ "x_thread_fetch",
863
+ "x_posts_sync",
864
+ "x_post_reply",
865
+ "reddit_accounts_list",
866
+ "reddit_search_live",
867
+ "reddit_mentions_live",
868
+ "reddit_thread_fetch",
869
+ "reddit_posts_sync",
870
+ "reddit_post_reply",
774
871
  "scheduled_tasks_list",
775
872
  "scheduled_tasks_get",
776
873
  "scheduled_tasks_create",
@@ -789,22 +886,81 @@ export const FIRST_PARTY_MCP_TOOL_NAMES = [
789
886
  "slack_bot_file_content",
790
887
  "slack_bot_post_message",
791
888
  "slack_bot_delete_message",
889
+ "atlassian_sources_list",
890
+ "atlassian_search",
891
+ "atlassian_get",
792
892
  "artifacts_list",
793
893
  "artifacts_get_source",
794
894
  "artifacts_create",
795
895
  "artifacts_publish",
796
896
  "artifacts_rollback",
897
+ "editable_artifact_list",
898
+ "editable_artifact_create",
899
+ "editable_artifact_import",
900
+ "editable_artifact_get",
901
+ "editable_artifact_inspect",
902
+ "editable_artifact_apply",
903
+ "editable_artifact_export",
904
+ "editable_artifact_export_status",
797
905
  ] as const;
798
906
  export const FirstPartyMcpToolName = z.enum(FIRST_PARTY_MCP_TOOL_NAMES);
799
907
  export type FirstPartyMcpToolName = z.infer<typeof FirstPartyMcpToolName>;
800
908
 
909
+ /**
910
+ * First-party interaction tools executed inside the frozen attempt rather than
911
+ * registered on the remote `opengeni` MCP server. They still belong to the
912
+ * same user-selectable first-party catalog and use the same attempt executor.
913
+ */
914
+ export const FIRST_PARTY_IN_PROCESS_TOOL_NAMES = [
915
+ "interaction_discover",
916
+ "browser_open",
917
+ "browser_tabs",
918
+ "browser_observe",
919
+ "browser_act",
920
+ "browser_debug",
921
+ "browser_identity",
922
+ "browser_publish",
923
+ "browser_lifecycle",
924
+ "computer_open",
925
+ "computer_targets",
926
+ "computer_observe",
927
+ "computer_act",
928
+ "computer_lifecycle",
929
+ ] as const satisfies readonly FirstPartyMcpToolName[];
930
+
931
+ const FIRST_PARTY_IN_PROCESS_TOOL_NAME_SET = new Set<FirstPartyMcpToolName>(
932
+ FIRST_PARTY_IN_PROCESS_TOOL_NAMES,
933
+ );
934
+
935
+ /** Exact catalog registered by the remote first-party `opengeni` MCP server. */
936
+ export const FIRST_PARTY_REMOTE_MCP_TOOL_NAMES = FIRST_PARTY_MCP_TOOL_NAMES.filter(
937
+ (name) => !FIRST_PARTY_IN_PROCESS_TOOL_NAME_SET.has(name),
938
+ ) satisfies readonly FirstPartyMcpToolName[];
939
+
940
+ /** Authored CodeMode paths for the canonical collaborative artifact surface. */
941
+ export const EDITABLE_ARTIFACT_MCP_CODEMODE_PATHS = {
942
+ editable_artifact_list: ["artifacts", "list"],
943
+ editable_artifact_create: ["artifacts", "create"],
944
+ editable_artifact_import: ["artifacts", "import"],
945
+ editable_artifact_get: ["artifacts", "get"],
946
+ editable_artifact_inspect: ["artifacts", "inspect"],
947
+ editable_artifact_apply: ["artifacts", "apply"],
948
+ editable_artifact_export: ["artifacts", "export"],
949
+ editable_artifact_export_status: ["artifacts", "exportStatus"],
950
+ } as const satisfies Partial<Record<FirstPartyMcpToolName, readonly [string, string]>>;
951
+
801
952
  /**
802
953
  * Connector-wide tools are explicit-only. Ordinary session omission selects
803
954
  * the non-connector catalog, while an explicit session policy may still select
804
955
  * any catalogued connector tool and remains independently permission-gated.
805
956
  */
806
957
  export const DEFAULT_FIRST_PARTY_MCP_TOOLS = FIRST_PARTY_MCP_TOOL_NAMES.filter(
807
- (name) => !name.startsWith("social_") && !name.startsWith("slack_bot_"),
958
+ (name) =>
959
+ !name.startsWith("social_") &&
960
+ !name.startsWith("x_") &&
961
+ !name.startsWith("reddit_") &&
962
+ !name.startsWith("slack_bot_") &&
963
+ !name.startsWith("atlassian_"),
808
964
  ) satisfies readonly FirstPartyMcpToolName[];
809
965
 
810
966
  export function prefixedMcpToolName(registryId: string, toolName: string): string {
@@ -1220,12 +1376,7 @@ export * from "./transcription-recordings";
1220
1376
  export const CodexCompactionMode = z.enum(["remote_v2", "portable"]);
1221
1377
  export type CodexCompactionMode = z.infer<typeof CodexCompactionMode>;
1222
1378
 
1223
- export const SlackReactionEmojiName = z
1224
- .string()
1225
- .trim()
1226
- .min(1)
1227
- .max(64)
1228
- .regex(/^[a-z0-9_+-]+$/, "use the exact Slack emoji name without surrounding colons");
1379
+ export const SlackReactionEmojiName = z.literal("genie");
1229
1380
  export type SlackReactionEmojiName = z.infer<typeof SlackReactionEmojiName>;
1230
1381
 
1231
1382
  export const WorkspaceSlackReactionChannelPolicy = z.discriminatedUnion("mode", [
@@ -2086,6 +2237,61 @@ export const UpdateWorkspaceMemberRequest = z.object({
2086
2237
  });
2087
2238
  export type UpdateWorkspaceMemberRequest = z.infer<typeof UpdateWorkspaceMemberRequest>;
2088
2239
 
2240
+ export const SlackUserLinkAccessRequestStatus = z.enum([
2241
+ "prepared",
2242
+ "pending",
2243
+ "completed",
2244
+ "denied",
2245
+ "cancelled",
2246
+ "expired",
2247
+ ]);
2248
+ export type SlackUserLinkAccessRequestStatus = z.infer<typeof SlackUserLinkAccessRequestStatus>;
2249
+
2250
+ /**
2251
+ * Durable, token-free projection of one signed Slack identity-link intent.
2252
+ * The original bearer and its digest are deliberately absent from every
2253
+ * public response.
2254
+ */
2255
+ export const SlackUserLinkAccessRequest = z.object({
2256
+ id: z.string().uuid(),
2257
+ workspaceId: z.string().uuid(),
2258
+ workspaceDisplayName: z.string().min(1).max(256).nullable(),
2259
+ subjectLabel: z.string().min(1).max(512).nullable(),
2260
+ status: SlackUserLinkAccessRequestStatus,
2261
+ version: z.number().int().positive(),
2262
+ expiresAt: z.string().datetime({ offset: true }),
2263
+ requestedAt: z.string().datetime({ offset: true }).nullable(),
2264
+ decidedAt: z.string().datetime({ offset: true }).nullable(),
2265
+ completedAt: z.string().datetime({ offset: true }).nullable(),
2266
+ createdAt: z.string().datetime({ offset: true }),
2267
+ updatedAt: z.string().datetime({ offset: true }),
2268
+ });
2269
+ export type SlackUserLinkAccessRequest = z.infer<typeof SlackUserLinkAccessRequest>;
2270
+
2271
+ export const PrepareSlackUserLinkAccessRequest = z.object({
2272
+ linkToken: z.string().min(1).max(2_048),
2273
+ });
2274
+ export type PrepareSlackUserLinkAccessRequest = z.infer<typeof PrepareSlackUserLinkAccessRequest>;
2275
+
2276
+ export const SlackUserLinkAccessMutationRequest = z.object({
2277
+ expectedVersion: z.number().int().positive(),
2278
+ idempotencyKey: z.string().trim().min(1).max(200),
2279
+ });
2280
+ export type SlackUserLinkAccessMutationRequest = z.infer<typeof SlackUserLinkAccessMutationRequest>;
2281
+
2282
+ export const ApproveSlackUserLinkAccessRequest = SlackUserLinkAccessMutationRequest.extend({
2283
+ role: z.string().trim().min(1).max(128).optional(),
2284
+ permissions: z.array(Permission).min(1),
2285
+ });
2286
+ export type ApproveSlackUserLinkAccessRequest = z.infer<typeof ApproveSlackUserLinkAccessRequest>;
2287
+
2288
+ export const ListSlackUserLinkAccessRequestsResponse = z.object({
2289
+ requests: z.array(SlackUserLinkAccessRequest),
2290
+ });
2291
+ export type ListSlackUserLinkAccessRequestsResponse = z.infer<
2292
+ typeof ListSlackUserLinkAccessRequestsResponse
2293
+ >;
2294
+
2089
2295
  export const UsageEventType = z.enum([
2090
2296
  "agent_run.created",
2091
2297
  "agent_run.completed",
@@ -2095,6 +2301,10 @@ export const UsageEventType = z.enum([
2095
2301
  "file.deleted",
2096
2302
  "document.indexed",
2097
2303
  "scheduled_task.fired",
2304
+ "knowledge_source_sync.fired",
2305
+ "knowledge_source_sync.completed",
2306
+ "knowledge_source_sync.items",
2307
+ "knowledge_source_sync.bytes",
2098
2308
  "api_key.request",
2099
2309
  // --- sandbox warm-time metering (P2.1) ---
2100
2310
  // Wall-clock seconds a box was warm — the billable warm-time meter. Accrued on
@@ -2133,6 +2343,9 @@ export type InsightsRange = z.infer<typeof InsightsRange>;
2133
2343
  export const InsightsBillingPath = z.enum(["opengeni_credits", "external"]);
2134
2344
  export type InsightsBillingPath = z.infer<typeof InsightsBillingPath>;
2135
2345
 
2346
+ export const InsightsPricingSource = z.enum(["configured_list_price", "gateway_reported"]);
2347
+ export type InsightsPricingSource = z.infer<typeof InsightsPricingSource>;
2348
+
2136
2349
  export const InsightsModelUsageRow = z.object({
2137
2350
  id: z.string().min(1),
2138
2351
  model: z.string().min(1),
@@ -2142,10 +2355,17 @@ export const InsightsModelUsageRow = z.object({
2142
2355
  inputTokens: z.number().nonnegative(),
2143
2356
  outputTokens: z.number().nonnegative(),
2144
2357
  cachedTokens: z.number().nonnegative(),
2358
+ cacheInputTokens: z.number().nonnegative(),
2145
2359
  cacheWriteTokens: z.number().nonnegative(),
2146
2360
  reasoningTokens: z.number().nonnegative(),
2361
+ totalTokens: z.number().nonnegative(),
2362
+ tokenKnownCalls: z.number().int().nonnegative(),
2363
+ cacheKnownCalls: z.number().int().nonnegative(),
2147
2364
  /** Priced OpenGeni credit $ for this model×provider (from model_call_facts). */
2148
2365
  creditUsd: z.number().nonnegative(),
2366
+ /** Hypothetical provider-rate USD; never an OpenGeni charge. */
2367
+ estimatedProviderUsd: z.number().nonnegative(),
2368
+ estimatedProviderCostKnownCalls: z.number().int().nonnegative(),
2149
2369
  });
2150
2370
  export type InsightsModelUsageRow = z.infer<typeof InsightsModelUsageRow>;
2151
2371
 
@@ -2153,9 +2373,19 @@ export const InsightsSeriesPoint = z.object({
2153
2373
  label: z.string().min(1),
2154
2374
  /** Day-bucketed sum of usage_events.model.cost (workspace-wide) or filtered facts when provider/model set. */
2155
2375
  modelCostUsd: z.number().nonnegative(),
2376
+ /** Day-bucketed hypothetical provider-rate USD for calls with captured pricing. */
2377
+ estimatedProviderUsd: z.number().nonnegative(),
2378
+ estimatedProviderCostKnownCalls: z.number().int().nonnegative(),
2156
2379
  warmSeconds: z.number().nonnegative(),
2157
2380
  inputTokens: z.number().nonnegative(),
2381
+ outputTokens: z.number().nonnegative(),
2158
2382
  cachedTokens: z.number().nonnegative(),
2383
+ cacheInputTokens: z.number().nonnegative(),
2384
+ cacheWriteTokens: z.number().nonnegative(),
2385
+ reasoningTokens: z.number().nonnegative(),
2386
+ totalTokens: z.number().nonnegative(),
2387
+ tokenKnownCalls: z.number().int().nonnegative(),
2388
+ cacheKnownCalls: z.number().int().nonnegative(),
2159
2389
  cacheHitPct: z.number().int().min(0).max(100),
2160
2390
  calls: z.number().int().nonnegative(),
2161
2391
  });
@@ -2178,9 +2408,12 @@ export const InsightsSpendDriver = z.object({
2178
2408
  groupBy: z.enum(["root_session", "schedule"]),
2179
2409
  label: z.string().min(1),
2180
2410
  creditUsd: z.number().nonnegative(),
2411
+ estimatedProviderUsd: z.number().nonnegative(),
2412
+ estimatedProviderCostKnownCalls: z.number().int().nonnegative(),
2181
2413
  tokens: z.number().nonnegative(),
2182
2414
  cacheHitPct: z.number().int().min(0).max(100),
2183
2415
  pctOfCreditUsd: z.number().int().min(0).max(100),
2416
+ pctOfTokens: z.number().int().min(0).max(100),
2184
2417
  deltaUsdVsPrior: z.number(),
2185
2418
  });
2186
2419
  export type InsightsSpendDriver = z.infer<typeof InsightsSpendDriver>;
@@ -2227,18 +2460,48 @@ export const InsightsScheduleRow = z.object({
2227
2460
  fires: z.number().int().nonnegative(),
2228
2461
  /** Null when no facts carry scheduled_task_id for this window. */
2229
2462
  creditUsd: z.number().nonnegative().nullable(),
2463
+ estimatedProviderUsd: z.number().nonnegative().nullable(),
2464
+ estimatedProviderCostKnownCalls: z.number().int().nonnegative().nullable(),
2230
2465
  tokens: z.number().nonnegative().nullable(),
2231
2466
  cacheHitPct: z.number().int().min(0).max(100).nullable(),
2232
2467
  billing: InsightsBillingPath.nullable(),
2233
2468
  });
2234
2469
  export type InsightsScheduleRow = z.infer<typeof InsightsScheduleRow>;
2235
2470
 
2471
+ export const InsightsModelCallRow = z.object({
2472
+ id: z.string().uuid(),
2473
+ occurredAt: z.string().datetime(),
2474
+ recordedAt: z.string().datetime(),
2475
+ sessionId: z.string().uuid(),
2476
+ sessionTitle: z.string(),
2477
+ turnId: z.string().uuid(),
2478
+ provider: z.string().min(1),
2479
+ providerApi: z.string().min(1),
2480
+ model: z.string().min(1),
2481
+ billing: InsightsBillingPath,
2482
+ inputTokens: z.number().nonnegative().nullable(),
2483
+ outputTokens: z.number().nonnegative().nullable(),
2484
+ cachedTokens: z.number().nonnegative().nullable(),
2485
+ cacheWriteTokens: z.number().nonnegative().nullable(),
2486
+ reasoningTokens: z.number().nonnegative().nullable(),
2487
+ totalTokens: z.number().nonnegative().nullable(),
2488
+ /** OpenGeni credit price for this call. External calls are always zero. */
2489
+ creditUsd: z.number().nonnegative(),
2490
+ /** Hypothetical provider-rate USD; null when historical pricing is unavailable. */
2491
+ estimatedProviderUsd: z.number().nonnegative().nullable(),
2492
+ pricingSource: InsightsPricingSource.nullable(),
2493
+ });
2494
+ export type InsightsModelCallRow = z.infer<typeof InsightsModelCallRow>;
2495
+
2236
2496
  export const WorkspaceInsightsSnapshot = z.object({
2237
2497
  range: InsightsRange,
2238
2498
  rangeLabel: z.string().min(1),
2239
2499
  priorLabel: z.string().min(1),
2240
2500
  seriesLabel: z.string().min(1),
2241
2501
  cacheSeriesLabel: z.string().min(1),
2502
+ windowStart: z.string().datetime(),
2503
+ windowEnd: z.string().datetime(),
2504
+ generatedAt: z.string().datetime(),
2242
2505
  /** All ranges/series are UTC. */
2243
2506
  timezone: z.literal("UTC"),
2244
2507
  models: z.array(InsightsModelUsageRow),
@@ -2248,6 +2511,7 @@ export const WorkspaceInsightsSnapshot = z.object({
2248
2511
  depth: z.array(InsightsDepthBucket),
2249
2512
  drivers: z.array(InsightsSpendDriver),
2250
2513
  schedules: z.array(InsightsScheduleRow),
2514
+ recentCalls: z.array(InsightsModelCallRow),
2251
2515
  warmSeconds: z.number().nonnegative(),
2252
2516
  priorWarmSeconds: z.number().nonnegative(),
2253
2517
  warmGroups: z.array(InsightsWarmGroupRow),
@@ -2261,7 +2525,14 @@ export const WorkspaceInsightsSnapshot = z.object({
2261
2525
  /** Model-filterable credit $ from facts (equals workspace when unfiltered, ignoring late-reject drift). */
2262
2526
  creditUsd: z.number().nonnegative(),
2263
2527
  priorCreditUsd: z.number().nonnegative(),
2528
+ /** Hypothetical provider-rate USD for calls whose historical price was captured. */
2529
+ estimatedProviderUsd: z.number().nonnegative(),
2530
+ priorEstimatedProviderUsd: z.number().nonnegative(),
2531
+ estimatedProviderCostKnownCalls: z.number().int().nonnegative(),
2532
+ priorEstimatedProviderCostKnownCalls: z.number().int().nonnegative(),
2533
+ modelCalls: z.number().int().nonnegative(),
2264
2534
  priorInputTokens: z.number().nonnegative(),
2535
+ priorTotalTokens: z.number().nonnegative(),
2265
2536
  priorCacheHitPct: z.number().int().min(0).max(100),
2266
2537
  priorCalls: z.number().int().nonnegative(),
2267
2538
  /** Lifetime workspace topology (not scoped to the selected Insights range). */
@@ -2408,7 +2679,7 @@ export type GitCredentialRepositoryRef = z.infer<typeof GitCredentialRepositoryR
2408
2679
  // `loadVariableSetForRun` (today decrypted with
2409
2680
  // `environmentsEncryptionKeyBytes(settings)`).
2410
2681
  // - MCP credentials: request-time transport headers for connection-backed
2411
- // servers, shared by normal model tools and Toolspace/Code Mode.
2682
+ // servers, shared by normal model tools and Codemode/Code Mode.
2412
2683
  //
2413
2684
  // In embedded/separate topologies the HOST owns these external connections
2414
2685
  // (its GitHub App, its secret vault + encryption key). When a host binds this
@@ -2691,7 +2962,7 @@ export const McpPersonalConnectionDelegation = z
2691
2962
  ownerSubjectId: z.string().min(1).max(512),
2692
2963
  providerDomain: z.string().min(1).max(2048),
2693
2964
  kind: z.enum(["oauth2", "api_key", "app_install", "delegated"]).optional(),
2694
- connectionType: z.enum(["mcp", "social"]).optional(),
2965
+ connectionType: z.enum(["mcp", "social", "atlassian"]).optional(),
2695
2966
  })
2696
2967
  .strict();
2697
2968
  export type McpPersonalConnectionDelegation = z.infer<typeof McpPersonalConnectionDelegation>;
@@ -2727,7 +2998,7 @@ export type McpPersonalConnectionSummary = z.infer<typeof McpPersonalConnectionS
2727
2998
  export type McpCredentialsRequest = {
2728
2999
  accountId: string;
2729
3000
  workspaceId: string;
2730
- /** Immediate session whose model or Toolspace call needs the credential. */
3001
+ /** Immediate session whose model or Codemode call needs the credential. */
2731
3002
  sessionId: string;
2732
3003
  /** Workspace-scoped lineage root for host authorization and binding lookup. */
2733
3004
  rootSessionId: string;
@@ -2740,9 +3011,16 @@ export type McpCredentialsRequest = {
2740
3011
  initiatorContext: TurnInitiatorContext;
2741
3012
  /** Immediate technical caller, retained only as non-authoritative audit context. */
2742
3013
  callerSubjectId?: string;
2743
- surface: "model" | "toolspace";
3014
+ surface: "model" | "codemode";
2744
3015
  /** Canonical MCP destination that will receive the resolved headers. */
2745
3016
  destinationUrl: string;
3017
+ /**
3018
+ * Credential transport requested by the caller. Omitted means the existing
3019
+ * header-only MCP transport. The additive `http_api` target allows embedding
3020
+ * hosts to return query/cookie API-key placements for local API integrations
3021
+ * without making those placements eligible for a remote MCP request.
3022
+ */
3023
+ credentialTarget?: "mcp" | "http_api";
2746
3024
  serverId: string;
2747
3025
  toolName?: string;
2748
3026
  connectionRef: McpServerConnectionRef;
@@ -2755,6 +3033,13 @@ export type McpCredentialAuthNeededReason =
2755
3033
  | "unsupported_auth"
2756
3034
  | "resource_scope_unavailable";
2757
3035
 
3036
+ export type ConnectionCredentialPlacement = {
3037
+ carrier: "header" | "query" | "cookie";
3038
+ name: string;
3039
+ value: string;
3040
+ prefix?: string;
3041
+ };
3042
+
2758
3043
  export type McpCredentialResolution =
2759
3044
  | {
2760
3045
  status: "ok";
@@ -2763,6 +3048,12 @@ export type McpCredentialResolution =
2763
3048
  workspaceId: string;
2764
3049
  sessionId: string;
2765
3050
  headers: Record<string, string>;
3051
+ /**
3052
+ * Optional normalized HTTP credential placements. When present, header
3053
+ * placements must exactly match `headers`. Query/cookie placements are
3054
+ * accepted only for a request whose credentialTarget is `http_api`.
3055
+ */
3056
+ placements?: ConnectionCredentialPlacement[];
2766
3057
  connectionId: string;
2767
3058
  providerDomain: string;
2768
3059
  provider?: string;
@@ -2803,7 +3094,7 @@ export type ConnectionCredentialsPort = {
2803
3094
  * Resolve rotating MCP transport credentials at request time. Embedded hosts
2804
3095
  * use this to keep their provider connection as the sole credential source;
2805
3096
  * OpenGeni never requires a duplicate connection record. The same resolver is
2806
- * used by model-visible MCP tools and the additive Toolspace/Code Mode proxy.
3097
+ * used by model-visible MCP tools and the exact-attempt Codemode projection.
2807
3098
  */
2808
3099
  mcpCredentials?(input: McpCredentialsRequest): Promise<McpCredentialResolution>;
2809
3100
  };
@@ -3098,6 +3389,12 @@ export type FileResourceRef = z.infer<typeof FileResourceRef>;
3098
3389
  * reconstruct the same typed attachment input after a model switch or retry.
3099
3390
  */
3100
3391
  export const MODEL_ATTACHMENT_REFS_FIELD = "opengeni_attachment_refs" as const;
3392
+ /**
3393
+ * Structured timeline annotations retained beside the deterministic user-text
3394
+ * projection in canonical history. Provider adapters remove this OpenGeni
3395
+ * extension field; the numbered projection in `content` remains model-visible.
3396
+ */
3397
+ export const MODEL_TIMELINE_ANNOTATIONS_FIELD = "opengeni_timeline_annotations" as const;
3101
3398
 
3102
3399
  export const ResourceRef = z.discriminatedUnion("kind", [RepositoryResourceRef, FileResourceRef]);
3103
3400
  export type ResourceRef = z.infer<typeof ResourceRef>;
@@ -3408,6 +3705,56 @@ export const DocumentSearchResponse = z.object({
3408
3705
  });
3409
3706
  export type DocumentSearchResponse = z.infer<typeof DocumentSearchResponse>;
3410
3707
 
3708
+ export const IndexedDocumentSource = z.object({
3709
+ kind: KnowledgeSourceKind,
3710
+ uri: z.string().nullable(),
3711
+ externalId: z.string().nullable(),
3712
+ title: z.string().nullable(),
3713
+ author: z.string().nullable(),
3714
+ createdAt: z.string().nullable(),
3715
+ updatedAt: z.string().nullable(),
3716
+ version: z.string().nullable(),
3717
+ });
3718
+ export type IndexedDocumentSource = z.infer<typeof IndexedDocumentSource>;
3719
+
3720
+ export const IndexedDocumentProvenance = z.object({
3721
+ ingestionWorkspaceId: z.string().uuid(),
3722
+ baseId: z.string().uuid(),
3723
+ fileId: z.string().uuid(),
3724
+ authorityKind: DocumentAuthorityKind,
3725
+ authorityWorkspaceId: z.string().uuid().nullable(),
3726
+ authoritySubjectId: z.string().nullable(),
3727
+ createdBy: z.string().nullable(),
3728
+ createdAt: z.string(),
3729
+ });
3730
+ export type IndexedDocumentProvenance = z.infer<typeof IndexedDocumentProvenance>;
3731
+
3732
+ export const IndexedDocumentSummary = z.object({
3733
+ id: z.string().uuid(),
3734
+ title: z.string(),
3735
+ parser: z.string(),
3736
+ chunkCount: z.number().int().nonnegative(),
3737
+ indexedAt: z.string(),
3738
+ summary: z.string().nullable(),
3739
+ topics: z.array(z.string()),
3740
+ source: IndexedDocumentSource,
3741
+ provenance: IndexedDocumentProvenance,
3742
+ });
3743
+ export type IndexedDocumentSummary = z.infer<typeof IndexedDocumentSummary>;
3744
+
3745
+ export const ListIndexedDocumentsRequest = z.object({
3746
+ checkpoint: z.string().min(1).max(1_024).optional(),
3747
+ limit: z.number().int().positive().max(100).default(50),
3748
+ });
3749
+ export type ListIndexedDocumentsRequest = z.infer<typeof ListIndexedDocumentsRequest>;
3750
+
3751
+ export const ListIndexedDocumentsResponse = z.object({
3752
+ documents: z.array(IndexedDocumentSummary),
3753
+ nextCheckpoint: z.string().min(1).max(1_024),
3754
+ hasMore: z.boolean(),
3755
+ });
3756
+ export type ListIndexedDocumentsResponse = z.infer<typeof ListIndexedDocumentsResponse>;
3757
+
3411
3758
  export const CreateDocumentBaseRequest = z.object({
3412
3759
  name: z.string().min(1),
3413
3760
  description: z.string().optional(),
@@ -3547,6 +3894,7 @@ export const CreateKnowledgeMemoryRequest = z.object({
3547
3894
  createdBySessionId: z.string().uuid().optional(),
3548
3895
  pinned: z.boolean().optional(),
3549
3896
  replacesId: z.string().min(1).optional(),
3897
+ slackPublication: MemorySlackPublicationDistribution.optional(),
3550
3898
  });
3551
3899
  export type CreateKnowledgeMemoryRequest = z.infer<typeof CreateKnowledgeMemoryRequest>;
3552
3900
 
@@ -4161,7 +4509,7 @@ export const SessionAuthorizationSurface = z.enum([
4161
4509
  "core",
4162
4510
  "stream",
4163
4511
  "first_party_mcp",
4164
- "toolspace",
4512
+ "codemode",
4165
4513
  ]);
4166
4514
  export type SessionAuthorizationSurface = z.infer<typeof SessionAuthorizationSurface>;
4167
4515
 
@@ -4450,7 +4798,7 @@ export const SessionAuthorizationOperation = z.enum([
4450
4798
  "session.viewer.control",
4451
4799
  "session.first_party_mcp.call",
4452
4800
  "session.secret.read",
4453
- "session.toolspace.call",
4801
+ "session.codemode.call",
4454
4802
  "session.pin.write",
4455
4803
  "session.codex_account.write",
4456
4804
  "session.realtime.start",
@@ -4486,6 +4834,8 @@ export const SessionAuthorizationActor = z.discriminatedUnion("kind", [
4486
4834
  /** Frozen authority that admitted the calling turn. */
4487
4835
  initiator: TurnInitiator,
4488
4836
  initiatorContext: TurnInitiatorContext,
4837
+ /** Durable causal human for delegated/service work; null for pure service work. */
4838
+ initiatingHumanSubjectId: z.string().min(1).max(1024).nullable(),
4489
4839
  }),
4490
4840
  ]);
4491
4841
  export type SessionAuthorizationActor = z.infer<typeof SessionAuthorizationActor>;
@@ -4564,44 +4914,276 @@ export type SessionAuthorizationPort = {
4564
4914
  ): Promise<SessionAuthorizationListScope>;
4565
4915
  };
4566
4916
 
4567
- export const SessionTurn = z.object({
4568
- id: z.string().uuid(),
4569
- workspaceId: z.string().uuid(),
4570
- sessionId: z.string().uuid(),
4571
- triggerEventId: z.string().uuid(),
4572
- temporalWorkflowId: z.string(),
4573
- status: SessionTurnStatus,
4574
- source: SessionTurnSource,
4575
- position: z.number().int(),
4576
- prompt: z.string().min(1),
4577
- resources: z.array(ResourceRef),
4578
- tools: z.array(ToolRef),
4579
- // Omitted/default discovery and explicit `tools: []` are distinct. False
4580
- // inherits the durable session policy; true replaces it for this turn after
4581
- // admission proves the selection is a subset.
4582
- toolsProvided: z.boolean().optional(),
4583
- model: z.string().min(1),
4584
- reasoningEffort: ReasoningEffort,
4585
- latencyMode: LatencyMode.default("standard"),
4586
- sandboxBackend: SandboxBackend,
4587
- // Per-turn OS override. NULL = inherit the session's sandboxOs.
4588
- sandboxOs: SandboxOs.nullable(),
4589
- metadata: z.record(z.string(), z.unknown()),
4590
- version: z.number().int().positive(),
4591
- executionGeneration: z.number().int().nonnegative(),
4592
- activeAttemptId: z.string().uuid().nullable(),
4593
- lineage: z.record(z.string(), z.unknown()),
4594
- initiator: TurnInitiator,
4595
- initiatorContext: TurnInitiatorContext,
4596
- /** Secret-safe projection of the exact personal authority frozen on this turn. */
4597
- personalConnections: z.array(McpPersonalConnectionSummary).default([]),
4598
- cancelledBy: z.string().nullable(),
4599
- cancelReason: z.string().nullable(),
4600
- startedAt: z.string().nullable(),
4601
- finishedAt: z.string().nullable(),
4602
- createdAt: z.string(),
4603
- updatedAt: z.string(),
4604
- });
4917
+ export const TIMELINE_ANNOTATION_MAX_COUNT = 12;
4918
+ export const TIMELINE_ANNOTATION_QUOTE_MAX_BYTES = 16 * 1024;
4919
+ export const TIMELINE_ANNOTATION_NOTE_MAX_BYTES = 2 * 1024;
4920
+ export const TIMELINE_ANNOTATION_CONTEXT_MAX_BYTES = 512;
4921
+ export const TIMELINE_ANNOTATION_LABEL_MAX_BYTES = 256;
4922
+ export const TIMELINE_ANNOTATIONS_MAX_BYTES = 64 * 1024;
4923
+
4924
+ export const TimelineAnnotationSourceKind = z.enum([
4925
+ "user_message",
4926
+ "assistant_message",
4927
+ "tool_output",
4928
+ ]);
4929
+ export type TimelineAnnotationSourceKind = z.infer<typeof TimelineAnnotationSourceKind>;
4930
+
4931
+ export const TimelineAnnotationSourceEventType = z.enum([
4932
+ "user.message",
4933
+ "agent.message.completed",
4934
+ "agent.toolCall.output",
4935
+ ]);
4936
+ export type TimelineAnnotationSourceEventType = z.infer<typeof TimelineAnnotationSourceEventType>;
4937
+
4938
+ function timelineAnnotationUtf8Bytes(value: string): number {
4939
+ return new TextEncoder().encode(value).byteLength;
4940
+ }
4941
+
4942
+ function timelineAnnotationBoundedText(maxBytes: number, label: string) {
4943
+ return z.string().superRefine((value, ctx) => {
4944
+ if (timelineAnnotationUtf8Bytes(value) > maxBytes) {
4945
+ ctx.addIssue({
4946
+ code: z.ZodIssueCode.custom,
4947
+ message: `${label} must be at most ${maxBytes} UTF-8 bytes`,
4948
+ });
4949
+ }
4950
+ });
4951
+ }
4952
+
4953
+ export const TimelineAnnotationSource = z
4954
+ .object({
4955
+ kind: TimelineAnnotationSourceKind,
4956
+ eventId: z.string().uuid(),
4957
+ eventType: TimelineAnnotationSourceEventType,
4958
+ sequence: z.number().int().positive(),
4959
+ turnId: z.string().uuid().nullable(),
4960
+ startOffset: z.number().int().nonnegative(),
4961
+ endOffset: z.number().int().nonnegative(),
4962
+ contextBefore: timelineAnnotationBoundedText(
4963
+ TIMELINE_ANNOTATION_CONTEXT_MAX_BYTES,
4964
+ "annotation source contextBefore",
4965
+ ),
4966
+ contextAfter: timelineAnnotationBoundedText(
4967
+ TIMELINE_ANNOTATION_CONTEXT_MAX_BYTES,
4968
+ "annotation source contextAfter",
4969
+ ),
4970
+ label: timelineAnnotationBoundedText(
4971
+ TIMELINE_ANNOTATION_LABEL_MAX_BYTES,
4972
+ "annotation source label",
4973
+ ).optional(),
4974
+ })
4975
+ .strict()
4976
+ .superRefine((source, ctx) => {
4977
+ if (source.endOffset < source.startOffset) {
4978
+ ctx.addIssue({
4979
+ code: z.ZodIssueCode.custom,
4980
+ path: ["endOffset"],
4981
+ message: "annotation source endOffset must not precede startOffset",
4982
+ });
4983
+ }
4984
+ const expectedKind =
4985
+ source.eventType === "user.message"
4986
+ ? "user_message"
4987
+ : source.eventType === "agent.message.completed"
4988
+ ? "assistant_message"
4989
+ : "tool_output";
4990
+ if (source.kind !== expectedKind) {
4991
+ ctx.addIssue({
4992
+ code: z.ZodIssueCode.custom,
4993
+ path: ["kind"],
4994
+ message: "annotation source kind does not match eventType",
4995
+ });
4996
+ }
4997
+ });
4998
+ export type TimelineAnnotationSource = z.infer<typeof TimelineAnnotationSource>;
4999
+
5000
+ export const DraftTimelineAnnotation = z
5001
+ .object({
5002
+ id: z.string().uuid(),
5003
+ source: TimelineAnnotationSource,
5004
+ quote: timelineAnnotationBoundedText(TIMELINE_ANNOTATION_QUOTE_MAX_BYTES, "annotation quote"),
5005
+ note: timelineAnnotationBoundedText(TIMELINE_ANNOTATION_NOTE_MAX_BYTES, "annotation note"),
5006
+ })
5007
+ .strict()
5008
+ .superRefine((annotation, ctx) => {
5009
+ if (!annotation.quote.trim()) {
5010
+ ctx.addIssue({
5011
+ code: z.ZodIssueCode.custom,
5012
+ path: ["quote"],
5013
+ message: "annotation quote must contain non-whitespace text",
5014
+ });
5015
+ }
5016
+ });
5017
+ export type DraftTimelineAnnotation = z.infer<typeof DraftTimelineAnnotation>;
5018
+
5019
+ export const SubmittedTimelineAnnotation = DraftTimelineAnnotation.superRefine(
5020
+ (annotation, ctx) => {
5021
+ if (!annotation.note.trim()) {
5022
+ ctx.addIssue({
5023
+ code: z.ZodIssueCode.custom,
5024
+ path: ["note"],
5025
+ message: "annotation note must contain non-whitespace text",
5026
+ });
5027
+ }
5028
+ },
5029
+ );
5030
+ export type SubmittedTimelineAnnotation = z.infer<typeof SubmittedTimelineAnnotation>;
5031
+
5032
+ export const TimelineAnnotation = z
5033
+ .object({
5034
+ id: z.string().uuid(),
5035
+ source: TimelineAnnotationSource,
5036
+ quote: timelineAnnotationBoundedText(TIMELINE_ANNOTATION_QUOTE_MAX_BYTES, "annotation quote"),
5037
+ note: timelineAnnotationBoundedText(
5038
+ TIMELINE_ANNOTATION_NOTE_MAX_BYTES,
5039
+ "annotation note",
5040
+ ).refine((value) => value.trim().length > 0, {
5041
+ message: "annotation note must contain non-whitespace text",
5042
+ }),
5043
+ ordinal: z.number().int().positive(),
5044
+ })
5045
+ .strict();
5046
+ export type TimelineAnnotation = z.infer<typeof TimelineAnnotation>;
5047
+
5048
+ function timelineAnnotationArray<T extends z.ZodTypeAny>(item: T) {
5049
+ return z
5050
+ .array(item)
5051
+ .max(TIMELINE_ANNOTATION_MAX_COUNT)
5052
+ .superRefine((annotations, ctx) => {
5053
+ const ids = new Set<string>();
5054
+ for (let index = 0; index < annotations.length; index += 1) {
5055
+ const id = (annotations[index] as { id?: unknown }).id;
5056
+ if (typeof id === "string" && ids.has(id)) {
5057
+ ctx.addIssue({
5058
+ code: z.ZodIssueCode.custom,
5059
+ path: [index, "id"],
5060
+ message: "annotation ids must be unique",
5061
+ });
5062
+ }
5063
+ if (typeof id === "string") ids.add(id);
5064
+ }
5065
+ if (
5066
+ timelineAnnotationUtf8Bytes(JSON.stringify(annotations)) > TIMELINE_ANNOTATIONS_MAX_BYTES
5067
+ ) {
5068
+ ctx.addIssue({
5069
+ code: z.ZodIssueCode.custom,
5070
+ message: `annotations must be at most ${TIMELINE_ANNOTATIONS_MAX_BYTES} UTF-8 bytes`,
5071
+ });
5072
+ }
5073
+ });
5074
+ }
5075
+
5076
+ export const DraftTimelineAnnotations = timelineAnnotationArray(DraftTimelineAnnotation);
5077
+ export type DraftTimelineAnnotations = z.infer<typeof DraftTimelineAnnotations>;
5078
+
5079
+ export const SubmittedTimelineAnnotations = timelineAnnotationArray(SubmittedTimelineAnnotation);
5080
+ export type SubmittedTimelineAnnotations = z.infer<typeof SubmittedTimelineAnnotations>;
5081
+
5082
+ export const TimelineAnnotations = timelineAnnotationArray(TimelineAnnotation).superRefine(
5083
+ (annotations, ctx) => {
5084
+ for (let index = 0; index < annotations.length; index += 1) {
5085
+ if (annotations[index]!.ordinal !== index + 1) {
5086
+ ctx.addIssue({
5087
+ code: z.ZodIssueCode.custom,
5088
+ path: [index, "ordinal"],
5089
+ message: "annotation ordinals must be contiguous and match array order",
5090
+ });
5091
+ }
5092
+ }
5093
+ },
5094
+ );
5095
+ export type TimelineAnnotations = z.infer<typeof TimelineAnnotations>;
5096
+
5097
+ export function numberTimelineAnnotations(
5098
+ annotations: readonly SubmittedTimelineAnnotation[],
5099
+ ): TimelineAnnotation[] {
5100
+ return annotations.map((annotation, index) => ({
5101
+ ...annotation,
5102
+ source: { ...annotation.source },
5103
+ ordinal: index + 1,
5104
+ }));
5105
+ }
5106
+
5107
+ export function renderTimelineAnnotationsForModel(
5108
+ text: string,
5109
+ annotations: readonly TimelineAnnotation[],
5110
+ ): string {
5111
+ if (annotations.length === 0) return text;
5112
+ const sections = annotations.flatMap((annotation) => [
5113
+ `Annotation ${annotation.ordinal}`,
5114
+ `Source: ${JSON.stringify({
5115
+ kind: annotation.source.kind,
5116
+ eventId: annotation.source.eventId,
5117
+ eventType: annotation.source.eventType,
5118
+ sequence: annotation.source.sequence,
5119
+ turnId: annotation.source.turnId,
5120
+ startOffset: annotation.source.startOffset,
5121
+ endOffset: annotation.source.endOffset,
5122
+ contextBefore: annotation.source.contextBefore,
5123
+ contextAfter: annotation.source.contextAfter,
5124
+ ...(annotation.source.label ? { label: annotation.source.label } : {}),
5125
+ })}`,
5126
+ `Exact quote: ${JSON.stringify(annotation.quote)}`,
5127
+ `User note: ${JSON.stringify(annotation.note)}`,
5128
+ ]);
5129
+ return [
5130
+ ...(text.length > 0 ? [text, ""] : []),
5131
+ "[OpenGeni timeline annotations]",
5132
+ ...sections.flatMap((line, index) =>
5133
+ index > 0 && line.startsWith("Annotation ") ? ["", line] : [line],
5134
+ ),
5135
+ ].join("\n");
5136
+ }
5137
+
5138
+ export const SessionTurn = z
5139
+ .object({
5140
+ id: z.string().uuid(),
5141
+ workspaceId: z.string().uuid(),
5142
+ sessionId: z.string().uuid(),
5143
+ triggerEventId: z.string().uuid(),
5144
+ temporalWorkflowId: z.string(),
5145
+ status: SessionTurnStatus,
5146
+ source: SessionTurnSource,
5147
+ position: z.number().int(),
5148
+ prompt: z.string(),
5149
+ annotations: TimelineAnnotations.default([]),
5150
+ resources: z.array(ResourceRef),
5151
+ tools: z.array(ToolRef),
5152
+ // Omitted/default discovery and explicit `tools: []` are distinct. False
5153
+ // inherits the durable session policy; true replaces it for this turn after
5154
+ // admission proves the selection is a subset.
5155
+ toolsProvided: z.boolean().optional(),
5156
+ model: z.string().min(1),
5157
+ reasoningEffort: ReasoningEffort,
5158
+ latencyMode: LatencyMode.default("standard"),
5159
+ sandboxBackend: SandboxBackend,
5160
+ // Per-turn OS override. NULL = inherit the session's sandboxOs.
5161
+ sandboxOs: SandboxOs.nullable(),
5162
+ metadata: z.record(z.string(), z.unknown()),
5163
+ version: z.number().int().positive(),
5164
+ executionGeneration: z.number().int().nonnegative(),
5165
+ activeAttemptId: z.string().uuid().nullable(),
5166
+ lineage: z.record(z.string(), z.unknown()),
5167
+ initiator: TurnInitiator,
5168
+ initiatorContext: TurnInitiatorContext,
5169
+ /** Secret-safe projection of the exact personal authority frozen on this turn. */
5170
+ personalConnections: z.array(McpPersonalConnectionSummary).default([]),
5171
+ cancelledBy: z.string().nullable(),
5172
+ cancelReason: z.string().nullable(),
5173
+ startedAt: z.string().nullable(),
5174
+ finishedAt: z.string().nullable(),
5175
+ createdAt: z.string(),
5176
+ updatedAt: z.string(),
5177
+ })
5178
+ .superRefine((turn, ctx) => {
5179
+ if (turn.prompt.length === 0 && turn.annotations.length === 0) {
5180
+ ctx.addIssue({
5181
+ code: z.ZodIssueCode.custom,
5182
+ path: ["prompt"],
5183
+ message: "turn prompt or annotations are required",
5184
+ });
5185
+ }
5186
+ });
4605
5187
  export type SessionTurn = z.infer<typeof SessionTurn>;
4606
5188
 
4607
5189
  export const EffectiveControlBlocker = z.object({
@@ -4670,6 +5252,7 @@ export type SessionCommandReceipt = z.infer<typeof SessionCommandReceipt>;
4670
5252
  export const ComposerDraft = z.object({
4671
5253
  revision: z.number().int().nonnegative(),
4672
5254
  text: z.string(),
5255
+ annotations: DraftTimelineAnnotations.default([]),
4673
5256
  resources: z.array(ResourceRef),
4674
5257
  model: z.string().min(1),
4675
5258
  reasoningEffort: ReasoningEffort,
@@ -4711,6 +5294,7 @@ export type DeleteSessionQueueItemRequest = z.infer<typeof DeleteSessionQueueIte
4711
5294
 
4712
5295
  export const SaveComposerDraftRequest = ComposerDraft.pick({
4713
5296
  text: true,
5297
+ annotations: true,
4714
5298
  resources: true,
4715
5299
  model: true,
4716
5300
  reasoningEffort: true,
@@ -4984,6 +5568,7 @@ export const SessionSystemUpdateKind = z.enum([
4984
5568
  "agent_message",
4985
5569
  "agent_steer_instruction",
4986
5570
  "child_terminal_result",
5571
+ "media_generation_result",
4987
5572
  ]);
4988
5573
  export type SessionSystemUpdateKind = z.infer<typeof SessionSystemUpdateKind>;
4989
5574
 
@@ -5028,6 +5613,7 @@ export const SessionSystemUpdatePayload = z.discriminatedUnion("type", [
5028
5613
  status: z.enum(["idle", "failed", "cancelled"]),
5029
5614
  })
5030
5615
  .passthrough(),
5616
+ MediaGenerationResult,
5031
5617
  ]);
5032
5618
  export type SessionSystemUpdatePayload = z.infer<typeof SessionSystemUpdatePayload>;
5033
5619
 
@@ -5259,59 +5845,182 @@ export const RigCheck = z.object({
5259
5845
  });
5260
5846
  export type RigCheck = z.infer<typeof RigCheck>;
5261
5847
 
5262
- export const RigVersion = z.object({
5263
- id: z.string().uuid(),
5264
- rigId: z.string().uuid(),
5265
- version: z.number().int().positive(),
5266
- image: z.string().nullable(),
5267
- setupScript: z.string().nullable(),
5268
- checks: z.array(RigCheck),
5269
- credentialHooks: z.array(z.string()),
5270
- defaultVariableSetIds: z.array(z.string().uuid()),
5271
- changelog: z.string().nullable(),
5272
- // Attribution: 'user:<subject>' | 'session:<id>' | 'system'.
5273
- createdBy: z.string().nullable(),
5274
- active: z.boolean(),
5275
- createdAt: z.string(),
5276
- });
5277
- export type RigVersion = z.infer<typeof RigVersion>;
5278
-
5279
- export const RigVerificationHealth = z.object({
5280
- checkHealth: z.enum(["passing", "failing", "unknown"]),
5281
- lastVerifiedAt: z.string().nullable(),
5282
- });
5283
- export type RigVerificationHealth = z.infer<typeof RigVerificationHealth>;
5284
-
5285
- export const Rig = z.object({
5286
- id: z.string().uuid(),
5287
- accountId: z.string().uuid(),
5288
- workspaceId: z.string().uuid(),
5289
- name: z.string(),
5290
- description: z.string().nullable(),
5291
- createdBy: z.string().nullable(),
5292
- // The rig's currently-active version (present after create; nullable so a
5293
- // partial/list read can omit it without a schema change).
5294
- activeVersion: RigVersion.nullable(),
5295
- // Summary for the currently active version. null only when there is no active
5296
- // version; otherwise "unknown" means the active version has no verification.
5297
- activeVersionHealth: RigVerificationHealth.nullable(),
5298
- versionCount: z.number().int().nonnegative(),
5299
- createdAt: z.string(),
5300
- updatedAt: z.string(),
5301
- });
5302
- export type Rig = z.infer<typeof Rig>;
5303
-
5304
- export const RigChangeKind = z.enum(["setup_append", "definition_edit"]);
5305
- export type RigChangeKind = z.infer<typeof RigChangeKind>;
5306
-
5307
- export const RigChangeStatus = z.enum(["proposed", "verifying", "merged", "rejected", "failed"]);
5308
- export type RigChangeStatus = z.infer<typeof RigChangeStatus>;
5848
+ export const RigProviderImageBuildStatus = z.enum(["building", "ready", "failed", "unsupported"]);
5849
+ export type RigProviderImageBuildStatus = z.infer<typeof RigProviderImageBuildStatus>;
5309
5850
 
5310
- // A single check's outcome inside a verification run (populated in M4).
5311
- export const RigCheckResult = z.object({
5312
- name: z.string(),
5313
- command: z.string(),
5314
- exitCode: z.number().int().nullable(),
5851
+ export const RigProviderImage = z
5852
+ .object({
5853
+ backend: SandboxBackend,
5854
+ provider: z.string().min(1).max(64),
5855
+ status: RigProviderImageBuildStatus,
5856
+ // Exact immutable rig-definition/setup identity used to reject stale image
5857
+ // reuse when a version or its effective base image changes.
5858
+ contentHash: z.string().regex(/^sha256:[0-9a-f]{64}$/u),
5859
+ setupHash: z.string().regex(/^sha256:[0-9a-f]{64}$/u),
5860
+ sourceImage: z.string().max(2048).nullable(),
5861
+ buildRequestId: z.string().uuid(),
5862
+ imageId: z.string().min(1).max(512).nullable(),
5863
+ imageDigest: z.string().min(1).max(512).nullable(),
5864
+ artifactId: z.string().uuid().nullable(),
5865
+ providerBindingKeyHash: z
5866
+ .string()
5867
+ .regex(/^sha256:[0-9a-f]{64}$/u)
5868
+ .nullable(),
5869
+ // Added after provider-image v1 shipped. Absence is retained for rolling
5870
+ // compatibility but means runtime must use logical-image + setup fallback
5871
+ // until an explicit verification cold-boots this exact image.
5872
+ coldBootValidation: z
5873
+ .object({
5874
+ version: z.literal(1),
5875
+ checkedAt: z.string().datetime(),
5876
+ })
5877
+ .optional(),
5878
+ provenance: z.object({
5879
+ kind: z.literal("rig_verification"),
5880
+ targetKind: z.enum(["change", "version"]),
5881
+ targetId: z.string().uuid(),
5882
+ }),
5883
+ startedAt: z.string().datetime(),
5884
+ finishedAt: z.string().datetime().nullable(),
5885
+ error: z
5886
+ .object({
5887
+ code: z.string().min(1).max(120),
5888
+ message: z.string().min(1).max(2000),
5889
+ retryable: z.boolean(),
5890
+ })
5891
+ .nullable(),
5892
+ })
5893
+ .superRefine((value, ctx) => {
5894
+ if (value.status === "ready" && !value.imageId && !value.imageDigest) {
5895
+ ctx.addIssue({
5896
+ code: "custom",
5897
+ path: ["imageId"],
5898
+ message: "ready provider images require an immutable image id or digest",
5899
+ });
5900
+ }
5901
+ if (
5902
+ value.status === "ready" &&
5903
+ value.backend === "modal" &&
5904
+ (value.artifactId === null || value.providerBindingKeyHash === null)
5905
+ ) {
5906
+ ctx.addIssue({
5907
+ code: "custom",
5908
+ path: [value.artifactId === null ? "artifactId" : "providerBindingKeyHash"],
5909
+ message: "ready Modal provider images require durable artifact ownership and binding",
5910
+ });
5911
+ }
5912
+ if (value.status !== "ready" && value.artifactId !== null) {
5913
+ ctx.addIssue({
5914
+ code: "custom",
5915
+ path: ["artifactId"],
5916
+ message: "only ready provider images may retain a durable artifact",
5917
+ });
5918
+ }
5919
+ if (value.status === "building") {
5920
+ if (value.finishedAt !== null) {
5921
+ ctx.addIssue({
5922
+ code: "custom",
5923
+ path: ["finishedAt"],
5924
+ message: "building provider images cannot be finished",
5925
+ });
5926
+ }
5927
+ if (value.error !== null) {
5928
+ ctx.addIssue({
5929
+ code: "custom",
5930
+ path: ["error"],
5931
+ message: "building provider images cannot have a terminal error",
5932
+ });
5933
+ }
5934
+ } else if (value.finishedAt === null) {
5935
+ ctx.addIssue({
5936
+ code: "custom",
5937
+ path: ["finishedAt"],
5938
+ message: "terminal provider images require a finish timestamp",
5939
+ });
5940
+ }
5941
+ if ((value.status === "failed" || value.status === "unsupported") && value.error === null) {
5942
+ ctx.addIssue({
5943
+ code: "custom",
5944
+ path: ["error"],
5945
+ message: `${value.status} provider images require failure truth`,
5946
+ });
5947
+ }
5948
+ if (value.status === "ready" && value.error !== null) {
5949
+ ctx.addIssue({
5950
+ code: "custom",
5951
+ path: ["error"],
5952
+ message: "ready provider images cannot retain an error",
5953
+ });
5954
+ }
5955
+ if (value.status !== "ready" && value.coldBootValidation !== undefined) {
5956
+ ctx.addIssue({
5957
+ code: "custom",
5958
+ path: ["coldBootValidation"],
5959
+ message: "only ready provider images may retain cold-boot validation",
5960
+ });
5961
+ }
5962
+ });
5963
+ export type RigProviderImage = z.infer<typeof RigProviderImage>;
5964
+
5965
+ export const RigProviderImages = z.partialRecord(SandboxBackend, RigProviderImage);
5966
+ export type RigProviderImages = z.infer<typeof RigProviderImages>;
5967
+
5968
+ export const RigVersion = z.object({
5969
+ id: z.string().uuid(),
5970
+ rigId: z.string().uuid(),
5971
+ version: z.number().int().positive(),
5972
+ image: z.string().nullable(),
5973
+ setupScript: z.string().nullable(),
5974
+ checks: z.array(RigCheck),
5975
+ credentialHooks: z.array(z.string()),
5976
+ defaultVariableSetIds: z.array(z.string().uuid()),
5977
+ changelog: z.string().nullable(),
5978
+ // Operational build metadata is version-bound but not part of the immutable
5979
+ // rig definition. Each backend records its own truthful build state.
5980
+ providerImages: RigProviderImages.default({}),
5981
+ // Attribution: 'user:<subject>' | 'session:<id>' | 'system'.
5982
+ createdBy: z.string().nullable(),
5983
+ active: z.boolean(),
5984
+ createdAt: z.string(),
5985
+ });
5986
+ export type RigVersion = z.infer<typeof RigVersion>;
5987
+
5988
+ export const RigVerificationHealth = z.object({
5989
+ checkHealth: z.enum(["passing", "failing", "unknown"]),
5990
+ lastVerifiedAt: z.string().nullable(),
5991
+ });
5992
+ export type RigVerificationHealth = z.infer<typeof RigVerificationHealth>;
5993
+
5994
+ export const Rig = z.object({
5995
+ id: z.string().uuid(),
5996
+ accountId: z.string().uuid(),
5997
+ workspaceId: z.string().uuid(),
5998
+ name: z.string(),
5999
+ description: z.string().nullable(),
6000
+ createdBy: z.string().nullable(),
6001
+ // The rig's currently-active version (present after create; nullable so a
6002
+ // partial/list read can omit it without a schema change).
6003
+ activeVersion: RigVersion.nullable(),
6004
+ // Summary for the currently active version. null only when there is no active
6005
+ // version; otherwise "unknown" means the active version has no verification.
6006
+ activeVersionHealth: RigVerificationHealth.nullable(),
6007
+ versionCount: z.number().int().nonnegative(),
6008
+ createdAt: z.string(),
6009
+ updatedAt: z.string(),
6010
+ });
6011
+ export type Rig = z.infer<typeof Rig>;
6012
+
6013
+ export const RigChangeKind = z.enum(["setup_append", "definition_edit"]);
6014
+ export type RigChangeKind = z.infer<typeof RigChangeKind>;
6015
+
6016
+ export const RigChangeStatus = z.enum(["proposed", "verifying", "merged", "rejected", "failed"]);
6017
+ export type RigChangeStatus = z.infer<typeof RigChangeStatus>;
6018
+
6019
+ // A single check's outcome inside a verification run (populated in M4).
6020
+ export const RigCheckResult = z.object({
6021
+ name: z.string(),
6022
+ command: z.string(),
6023
+ exitCode: z.number().int().nullable(),
5315
6024
  output: z.string().optional(),
5316
6025
  });
5317
6026
  export type RigCheckResult = z.infer<typeof RigCheckResult>;
@@ -5389,26 +6098,112 @@ export const ProposeRigChangeRequest = z.discriminatedUnion("kind", [
5389
6098
  ]);
5390
6099
  export type ProposeRigChangeRequest = z.infer<typeof ProposeRigChangeRequest>;
5391
6100
 
5392
- export const ScheduledTaskStatus = z.enum(["active", "paused"]);
6101
+ export const ScheduledTaskStatus = /* @__PURE__ */ z.enum(["active", "paused"]);
5393
6102
  export type ScheduledTaskStatus = z.infer<typeof ScheduledTaskStatus>;
5394
6103
 
5395
- export const ScheduledTaskRunStatus = z.enum(["queued", "dispatched", "failed"]);
6104
+ export const ScheduledTaskRunStatus = /* @__PURE__ */ z.enum([
6105
+ "queued",
6106
+ "dispatched",
6107
+ "succeeded",
6108
+ "skipped",
6109
+ "failed",
6110
+ ]);
5396
6111
  export type ScheduledTaskRunStatus = z.infer<typeof ScheduledTaskRunStatus>;
5397
6112
 
5398
- export const ScheduledTaskRunMode = z.enum([
6113
+ export const ScheduledTaskRunMode = /* @__PURE__ */ z.enum([
5399
6114
  "new_session_per_run",
5400
6115
  "reusable_session",
5401
6116
  "existing_session",
5402
6117
  ]);
5403
6118
  export type ScheduledTaskRunMode = z.infer<typeof ScheduledTaskRunMode>;
5404
6119
 
5405
- export const ScheduledTaskOverlapPolicy = z.enum(["allow_concurrent", "skip", "buffer_one"]);
6120
+ export const ScheduledTaskOverlapPolicy = /* @__PURE__ */ z.enum([
6121
+ "allow_concurrent",
6122
+ "skip",
6123
+ "buffer_one",
6124
+ ]);
5406
6125
  export type ScheduledTaskOverlapPolicy = z.infer<typeof ScheduledTaskOverlapPolicy>;
5407
6126
 
5408
- export const ScheduledTaskTriggerType = z.enum(["scheduled", "manual"]);
6127
+ export const ScheduledTaskTriggerType = /* @__PURE__ */ z.enum([
6128
+ "scheduled",
6129
+ "manual",
6130
+ "initial",
6131
+ "provider_event",
6132
+ "retry",
6133
+ "repair",
6134
+ ]);
5409
6135
  export type ScheduledTaskTriggerType = z.infer<typeof ScheduledTaskTriggerType>;
5410
6136
 
5411
- export const ScheduledTaskScheduleSpec = z.discriminatedUnion("type", [
6137
+ export const ScheduledTaskActionKind = /* @__PURE__ */ z.enum([
6138
+ "agent_turn",
6139
+ "knowledge_source_sync",
6140
+ ]);
6141
+ export type ScheduledTaskActionKind = z.infer<typeof ScheduledTaskActionKind>;
6142
+
6143
+ const KnowledgeSourceSyncPositiveInteger = z.number().int().positive();
6144
+ const KnowledgeSourceSyncNonnegativeInteger = z.number().int().nonnegative();
6145
+ const KnowledgeSourceSyncZeroInteger = KnowledgeSourceSyncNonnegativeInteger.default(0);
6146
+ const KnowledgeSourceSyncUuid = z.string().uuid();
6147
+ const KnowledgeSourceSyncSubject = z.string().min(1).max(1024);
6148
+ const KnowledgeSourceSyncEnabled = z.boolean().default(true);
6149
+ const KnowledgeSourceSyncDisabled = z.boolean().default(false);
6150
+
6151
+ export const KnowledgeSourceSyncLimits = /* @__PURE__ */ z.object({
6152
+ maxItems: KnowledgeSourceSyncPositiveInteger.max(10_000).default(500),
6153
+ maxBytes: KnowledgeSourceSyncPositiveInteger.max(5_000_000_000).default(500_000_000),
6154
+ maxFileBytes: KnowledgeSourceSyncPositiveInteger.max(5_000_000_000).default(100_000_000),
6155
+ maxProviderRequests: KnowledgeSourceSyncPositiveInteger.max(10_000).default(1_000),
6156
+ maxElapsedSeconds: KnowledgeSourceSyncPositiveInteger.max(3_600).default(300),
6157
+ maxConcurrency: KnowledgeSourceSyncPositiveInteger.max(32).default(4),
6158
+ maxFailureDetails: KnowledgeSourceSyncPositiveInteger.max(100).default(25),
6159
+ });
6160
+ export type KnowledgeSourceSyncLimits = z.infer<typeof KnowledgeSourceSyncLimits>;
6161
+
6162
+ export const KnowledgeSourceSyncConnectionAuthority = /* @__PURE__ */ z.object({
6163
+ connectionId: KnowledgeSourceSyncUuid,
6164
+ connectionVersion: KnowledgeSourceSyncPositiveInteger,
6165
+ providerDomain: z.string().min(1).max(2048),
6166
+ kind: z.enum(["oauth2", "api_key", "app_install", "delegated"]),
6167
+ ownerSubjectId: KnowledgeSourceSyncSubject,
6168
+ });
6169
+ export type KnowledgeSourceSyncConnectionAuthority = z.infer<
6170
+ typeof KnowledgeSourceSyncConnectionAuthority
6171
+ >;
6172
+
6173
+ export const KnowledgeSourceSyncAction = /* @__PURE__ */ z
6174
+ .object({
6175
+ kind: z.literal("knowledge_source_sync"),
6176
+ sourceId: KnowledgeSourceSyncUuid,
6177
+ sourceGeneration: KnowledgeSourceSyncNonnegativeInteger,
6178
+ sourceLifecycleGeneration: KnowledgeSourceSyncPositiveInteger,
6179
+ sourceConfigGeneration: KnowledgeSourceSyncPositiveInteger,
6180
+ controlWorkspaceId: KnowledgeSourceSyncUuid,
6181
+ providerCoordinationKey: z.string().trim().min(1).max(1024),
6182
+ connection: KnowledgeSourceSyncConnectionAuthority,
6183
+ destination: ScopedKnowledgeScope,
6184
+ initiatingSubjectId: KnowledgeSourceSyncSubject,
6185
+ allDescendants: KnowledgeSourceSyncEnabled,
6186
+ limits: KnowledgeSourceSyncLimits.prefault({}),
6187
+ })
6188
+ .strict();
6189
+ export type KnowledgeSourceSyncAction = z.infer<typeof KnowledgeSourceSyncAction>;
6190
+
6191
+ export const KnowledgeSourceSyncScheduleControl = /* @__PURE__ */ z
6192
+ .object({
6193
+ sourceEnabled: KnowledgeSourceSyncEnabled,
6194
+ connectionPaused: KnowledgeSourceSyncDisabled,
6195
+ })
6196
+ .strict();
6197
+ export type KnowledgeSourceSyncScheduleControl = z.infer<typeof KnowledgeSourceSyncScheduleControl>;
6198
+
6199
+ export const ScheduledTaskAction = /* @__PURE__ */ z.discriminatedUnion("kind", [
6200
+ z.object({ kind: z.literal("agent_turn") }).strict(),
6201
+ KnowledgeSourceSyncAction,
6202
+ ]);
6203
+ export type ScheduledTaskAction = z.infer<typeof ScheduledTaskAction>;
6204
+
6205
+ export const ScheduledTaskScheduleSpec = /* @__PURE__ */ z.discriminatedUnion("type", [
6206
+ z.object({ type: z.literal("manual") }).strict(),
5412
6207
  z.object({
5413
6208
  type: z.literal("once"),
5414
6209
  runAt: z.string().datetime({ offset: true }),
@@ -5433,7 +6228,7 @@ export const ScheduledTaskScheduleSpec = z.discriminatedUnion("type", [
5433
6228
  ]);
5434
6229
  export type ScheduledTaskScheduleSpec = z.infer<typeof ScheduledTaskScheduleSpec>;
5435
6230
 
5436
- export const ScheduledTaskAgentConfig = z.object({
6231
+ export const ScheduledTaskAgentConfig = /* @__PURE__ */ z.object({
5437
6232
  prompt: z.string().min(1),
5438
6233
  resources: z.array(ResourceRef).default([]),
5439
6234
  tools: z.array(ToolRef).default([]),
@@ -5452,7 +6247,7 @@ export const ScheduledTaskAgentConfig = z.object({
5452
6247
  });
5453
6248
  export type ScheduledTaskAgentConfig = z.infer<typeof ScheduledTaskAgentConfig>;
5454
6249
 
5455
- export const ScheduledTask = z.object({
6250
+ export const ScheduledTask = /* @__PURE__ */ z.object({
5456
6251
  id: z.string().uuid(),
5457
6252
  accountId: z.string().uuid(),
5458
6253
  workspaceId: z.string().uuid(),
@@ -5462,6 +6257,7 @@ export const ScheduledTask = z.object({
5462
6257
  temporalScheduleId: z.string(),
5463
6258
  runMode: ScheduledTaskRunMode,
5464
6259
  overlapPolicy: ScheduledTaskOverlapPolicy,
6260
+ action: ScheduledTaskAction.default({ kind: "agent_turn" }),
5465
6261
  agentConfig: ScheduledTaskAgentConfig,
5466
6262
  createdBy: TurnInitiator.default({
5467
6263
  kind: "service",
@@ -5484,7 +6280,52 @@ export const ScheduledTask = z.object({
5484
6280
  });
5485
6281
  export type ScheduledTask = z.infer<typeof ScheduledTask>;
5486
6282
 
5487
- export const ScheduledTaskRun = z.object({
6283
+ export const KnowledgeSourceSyncFailure = /* @__PURE__ */ z.object({
6284
+ externalObjectId: KnowledgeSourceSyncSubject,
6285
+ code: z.enum([
6286
+ "authority_changed",
6287
+ "connection_reconnect_required",
6288
+ "provider_unavailable",
6289
+ "provider_rejected",
6290
+ "provider_payload_invalid",
6291
+ "content_unsupported",
6292
+ "content_too_large",
6293
+ "resource_limit",
6294
+ "item_processing_failed",
6295
+ "indexing_failed",
6296
+ "internal_failure",
6297
+ ]),
6298
+ retryable: z.boolean(),
6299
+ message: z.string().min(1).max(1000),
6300
+ });
6301
+ export type KnowledgeSourceSyncFailure = z.infer<typeof KnowledgeSourceSyncFailure>;
6302
+
6303
+ export const KnowledgeSourceSyncRunSummary = /* @__PURE__ */ z.object({
6304
+ phase: z
6305
+ .enum(["queued", "inventory", "transfer", "index", "checkpoint", "completed", "failed"])
6306
+ .default("queued"),
6307
+ scanned: KnowledgeSourceSyncZeroInteger,
6308
+ imported: KnowledgeSourceSyncZeroInteger,
6309
+ unchanged: KnowledgeSourceSyncZeroInteger,
6310
+ skipped: KnowledgeSourceSyncZeroInteger,
6311
+ failed: KnowledgeSourceSyncZeroInteger,
6312
+ bytes: KnowledgeSourceSyncZeroInteger,
6313
+ providerRequests: KnowledgeSourceSyncZeroInteger,
6314
+ elapsedMs: KnowledgeSourceSyncZeroInteger,
6315
+ indexed: KnowledgeSourceSyncZeroInteger,
6316
+ aclPending: KnowledgeSourceSyncZeroInteger,
6317
+ retryable: KnowledgeSourceSyncDisabled,
6318
+ limitReached: z
6319
+ .enum(["items", "bytes", "file_bytes", "provider_requests", "elapsed_time"])
6320
+ .nullable()
6321
+ .default(null),
6322
+ checkpointed: KnowledgeSourceSyncDisabled,
6323
+ reconnectRequired: KnowledgeSourceSyncDisabled,
6324
+ failures: z.array(KnowledgeSourceSyncFailure).max(100).default([]),
6325
+ });
6326
+ export type KnowledgeSourceSyncRunSummary = z.infer<typeof KnowledgeSourceSyncRunSummary>;
6327
+
6328
+ export const ScheduledTaskRun = /* @__PURE__ */ z.object({
5488
6329
  id: z.string().uuid(),
5489
6330
  accountId: z.string().uuid(),
5490
6331
  workspaceId: z.string().uuid(),
@@ -5495,15 +6336,23 @@ export const ScheduledTaskRun = z.object({
5495
6336
  firedAt: z.string(),
5496
6337
  sessionId: z.string().uuid().nullable(),
5497
6338
  triggerEventId: z.string().uuid().nullable(),
6339
+ actionKind: ScheduledTaskActionKind.default("agent_turn"),
6340
+ knowledgeSyncRunId: KnowledgeSourceSyncUuid.nullable().default(null),
6341
+ knowledgeSummary: KnowledgeSourceSyncRunSummary.nullable().default(null),
6342
+ completedAt: z.string().nullable().default(null),
5498
6343
  error: z.string().nullable(),
5499
6344
  createdAt: z.string(),
5500
6345
  updatedAt: z.string(),
5501
6346
  });
5502
6347
  export type ScheduledTaskRun = z.infer<typeof ScheduledTaskRun>;
5503
6348
 
5504
- export const CreateScheduledTaskRequest = withVariableSetIdAlias({
6349
+ const CreateAgentScheduledTaskRequest = /* @__PURE__ */ withVariableSetIdAlias({
5505
6350
  name: z.string().min(1),
5506
6351
  schedule: ScheduledTaskScheduleSpec,
6352
+ action: z
6353
+ .object({ kind: z.literal("agent_turn") })
6354
+ .strict()
6355
+ .default({ kind: "agent_turn" }),
5507
6356
  runMode: ScheduledTaskRunMode.default("new_session_per_run"),
5508
6357
  overlapPolicy: ScheduledTaskOverlapPolicy.default("allow_concurrent"),
5509
6358
  targetSessionId: z.string().uuid().nullable().optional(),
@@ -5537,13 +6386,44 @@ export const CreateScheduledTaskRequest = withVariableSetIdAlias({
5537
6386
  });
5538
6387
  }
5539
6388
  });
6389
+
6390
+ const CreateKnowledgeSourceSyncScheduledTaskRequest = /* @__PURE__ */ z
6391
+ .object({
6392
+ name: z.string().min(1),
6393
+ schedule: ScheduledTaskScheduleSpec,
6394
+ action: KnowledgeSourceSyncAction,
6395
+ overlapPolicy: z.enum(["skip", "buffer_one"]).default("buffer_one"),
6396
+ status: ScheduledTaskStatus.default("active"),
6397
+ metadata: z.record(z.string(), z.unknown()).default({}),
6398
+ })
6399
+ .strict()
6400
+ .transform((value) => ({
6401
+ ...value,
6402
+ runMode: "new_session_per_run" as const,
6403
+ targetSessionId: null,
6404
+ agentConfig: {
6405
+ prompt: "Knowledge source synchronization",
6406
+ resources: [],
6407
+ tools: [],
6408
+ metadata: {},
6409
+ },
6410
+ variableSetId: null,
6411
+ environmentId: null,
6412
+ rigId: null,
6413
+ }));
6414
+
6415
+ export const CreateScheduledTaskRequest = /* @__PURE__ */ z.union([
6416
+ CreateKnowledgeSourceSyncScheduledTaskRequest,
6417
+ CreateAgentScheduledTaskRequest,
6418
+ ]);
5540
6419
  export type CreateScheduledTaskRequest = z.infer<typeof CreateScheduledTaskRequest>;
5541
6420
 
5542
- export const UpdateScheduledTaskRequest = withVariableSetIdAlias({
6421
+ export const UpdateScheduledTaskRequest = /* @__PURE__ */ withVariableSetIdAlias({
5543
6422
  name: z.string().min(1).optional(),
5544
6423
  schedule: ScheduledTaskScheduleSpec.optional(),
5545
6424
  runMode: ScheduledTaskRunMode.optional(),
5546
6425
  overlapPolicy: ScheduledTaskOverlapPolicy.optional(),
6426
+ action: ScheduledTaskAction.optional(),
5547
6427
  targetSessionId: z.string().uuid().nullable().optional(),
5548
6428
  agentConfig: ScheduledTaskAgentConfig.optional(),
5549
6429
  status: ScheduledTaskStatus.optional(),
@@ -5729,11 +6609,86 @@ function isSafePackSkillRelativePath(path: string): boolean {
5729
6609
  .every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
5730
6610
  }
5731
6611
 
5732
- const CapabilityPackVariableSet = z.object({
5733
- description: z.string().min(1),
5734
- requiredVariables: z.array(VariableSetVariableName).default([]),
5735
- required: z.boolean().default(false),
5736
- });
6612
+ const CapabilityPackVariableSet = z
6613
+ .object({
6614
+ description: z.string().min(1).max(2048),
6615
+ requiredVariables: z.array(VariableSetVariableName).max(256).default([]),
6616
+ required: z.boolean().default(false),
6617
+ })
6618
+ .strict();
6619
+
6620
+ const CapabilityPackComponentKey = z
6621
+ .string()
6622
+ .min(1)
6623
+ .max(128)
6624
+ .regex(/^[a-z0-9](?:[a-z0-9._/-]*[a-z0-9])?$/);
6625
+
6626
+ const CapabilityPackInstanceKey = z
6627
+ .string()
6628
+ .min(1)
6629
+ .max(128)
6630
+ .regex(/^[a-z0-9](?:[a-z0-9._/-]*[a-z0-9])?$/);
6631
+
6632
+ /**
6633
+ * Immutable requirements adopted by a Pack installation. The manifest names
6634
+ * portable identities; installation resolves them to exact workspace-local
6635
+ * component rows and records Pack ownership in the shared component ledger.
6636
+ */
6637
+ export const CapabilityPackComponentReference = z.discriminatedUnion("kind", [
6638
+ z
6639
+ .object({
6640
+ key: CapabilityPackComponentKey,
6641
+ kind: z.literal("plugin"),
6642
+ pluginKey: z.string().min(1).max(200),
6643
+ version: z.string().min(1).max(128),
6644
+ manifestDigest: z.string().regex(/^[0-9a-f]{64}$/),
6645
+ required: z.boolean().default(true),
6646
+ })
6647
+ .strict(),
6648
+ z
6649
+ .object({
6650
+ key: CapabilityPackComponentKey,
6651
+ kind: z.literal("skill"),
6652
+ capabilityId: z.string().min(1).max(512),
6653
+ contentSha256: z.string().regex(/^[0-9a-f]{64}$/),
6654
+ required: z.boolean().default(true),
6655
+ })
6656
+ .strict(),
6657
+ z
6658
+ .object({
6659
+ key: CapabilityPackComponentKey,
6660
+ kind: z.literal("integration"),
6661
+ capabilityId: z.string().min(1).max(512),
6662
+ instanceKey: CapabilityPackInstanceKey,
6663
+ revisionId: z.string().min(1).max(512),
6664
+ contentSha256: z.string().regex(/^[0-9a-f]{64}$/),
6665
+ required: z.boolean().default(true),
6666
+ })
6667
+ .strict(),
6668
+ z
6669
+ .object({
6670
+ key: CapabilityPackComponentKey,
6671
+ kind: z.literal("feature"),
6672
+ capabilityId: z.string().min(1).max(512),
6673
+ instanceKey: CapabilityPackInstanceKey,
6674
+ featureKey: z.string().min(1).max(200),
6675
+ bindingKey: CapabilityPackInstanceKey,
6676
+ configDigest: z.string().regex(/^[0-9a-f]{64}$/),
6677
+ required: z.boolean().default(true),
6678
+ })
6679
+ .strict(),
6680
+ ]);
6681
+ export type CapabilityPackComponentReference = z.infer<typeof CapabilityPackComponentReference>;
6682
+
6683
+ export const CapabilityPackRigRequirement = z
6684
+ .object({
6685
+ description: z.string().min(1).max(2048).optional(),
6686
+ required: z.boolean().default(true),
6687
+ rigId: z.string().uuid().optional(),
6688
+ requireVerified: z.boolean().default(false),
6689
+ })
6690
+ .strict();
6691
+ export type CapabilityPackRigRequirement = z.infer<typeof CapabilityPackRigRequirement>;
5737
6692
 
5738
6693
  export const CapabilityPack = z.preprocess(
5739
6694
  (input) => {
@@ -5763,15 +6718,19 @@ export const CapabilityPack = z.preprocess(
5763
6718
  },
5764
6719
  z
5765
6720
  .object({
5766
- id: z.string().min(1),
5767
- name: z.string().min(1),
5768
- description: z.string().min(1),
5769
- role: z.string().min(1),
5770
- category: z.string().min(1),
5771
- version: z.string().min(1),
5772
- // Container image ref (digest-pinned recommended) the pack's sessions run
5773
- // in. At most one enabled pack per workspace may declare one; with none,
5774
- // sessions use the deployment-wide image settings.
6721
+ id: z
6722
+ .string()
6723
+ .min(1)
6724
+ .max(100)
6725
+ .regex(/^[a-z0-9](?:[a-z0-9._/-]*[a-z0-9])?$/),
6726
+ name: z.string().min(1).max(200),
6727
+ description: z.string().min(1).max(4096),
6728
+ role: z.string().min(1).max(128),
6729
+ category: z.string().min(1).max(128),
6730
+ version: z.string().min(1).max(128),
6731
+ // Legacy manifest compatibility. V2 installation resolves this image to
6732
+ // an explicit Rig requirement; the Pack no longer changes workspace
6733
+ // runtime settings directly.
5775
6734
  sandboxImage: z.string().trim().min(1).max(512).optional(),
5776
6735
  // Optional provider-native immutable identities for the exact logical
5777
6736
  // sandboxImage above. These avoid re-importing a private registry image on
@@ -5791,7 +6750,8 @@ export const CapabilityPack = z.preprocess(
5791
6750
  })
5792
6751
  .strict()
5793
6752
  .optional(),
5794
- // Skills delivered into the sandbox skill index when the pack is enabled.
6753
+ // Legacy inline Skills are migrated into immutable Skill components by
6754
+ // the V2 Pack installer. They are not loaded directly by V2 runtime.
5795
6755
  skills: z
5796
6756
  .array(CapabilityPackSkill)
5797
6757
  .max(32)
@@ -5810,6 +6770,8 @@ export const CapabilityPack = z.preprocess(
5810
6770
  });
5811
6771
  })
5812
6772
  .default([]),
6773
+ components: z.array(CapabilityPackComponentReference).max(128).default([]),
6774
+ rig: CapabilityPackRigRequirement.optional(),
5813
6775
  tools: z.array(ToolRef).default([]),
5814
6776
  connectors: z.array(CapabilityPackConnector).default([]),
5815
6777
  knowledge: z.array(CapabilityPackKnowledge).default([]),
@@ -5818,6 +6780,28 @@ export const CapabilityPack = z.preprocess(
5818
6780
  metadata: z.record(z.string(), z.unknown()).default({}),
5819
6781
  })
5820
6782
  .superRefine((pack, ctx) => {
6783
+ const componentKeys = new Set<string>();
6784
+ pack.components.forEach((component, index) => {
6785
+ if (componentKeys.has(component.key)) {
6786
+ ctx.addIssue({
6787
+ code: "custom",
6788
+ message: `duplicate Pack component key: ${component.key}`,
6789
+ path: ["components", index, "key"],
6790
+ });
6791
+ }
6792
+ componentKeys.add(component.key);
6793
+ });
6794
+ pack.skills.forEach((skill, index) => {
6795
+ const key = `inline-skill/${skill.name.toLowerCase()}`;
6796
+ if (componentKeys.has(key)) {
6797
+ ctx.addIssue({
6798
+ code: "custom",
6799
+ message: `Pack component key conflicts with inline Skill ${skill.name}: ${key}`,
6800
+ path: ["skills", index, "name"],
6801
+ });
6802
+ }
6803
+ componentKeys.add(key);
6804
+ });
5821
6805
  if (!pack.sandboxProviderImages?.modal) {
5822
6806
  return;
5823
6807
  }
@@ -5855,7 +6839,12 @@ export const WorkspaceRegisteredPack = z.object({
5855
6839
  });
5856
6840
  export type WorkspaceRegisteredPack = z.infer<typeof WorkspaceRegisteredPack>;
5857
6841
 
5858
- export const PackInstallationStatus = z.enum(["active", "disabled"]);
6842
+ export const PackInstallationStatus = z.enum([
6843
+ "installing",
6844
+ "active",
6845
+ "needs_attention",
6846
+ "disabled",
6847
+ ]);
5859
6848
  export type PackInstallationStatus = z.infer<typeof PackInstallationStatus>;
5860
6849
 
5861
6850
  export const PackInstallation = z.object({
@@ -5864,6 +6853,14 @@ export const PackInstallation = z.object({
5864
6853
  workspaceId: z.string().uuid(),
5865
6854
  packId: z.string().min(1),
5866
6855
  status: PackInstallationStatus,
6856
+ version: z.number().int().positive(),
6857
+ manifestSnapshot: CapabilityPack.nullable(),
6858
+ manifestDigest: z
6859
+ .string()
6860
+ .regex(/^[0-9a-f]{64}$/)
6861
+ .nullable(),
6862
+ selectedRigId: z.string().uuid().nullable(),
6863
+ installedBySubjectId: z.string().min(1).max(1024).nullable(),
5867
6864
  metadata: z.record(z.string(), z.unknown()),
5868
6865
  enabledAt: z.string(),
5869
6866
  updatedAt: z.string(),
@@ -5877,6 +6874,116 @@ export const EnablePackRequest = withVariableSetIdAlias({
5877
6874
  });
5878
6875
  export type EnablePackRequest = z.infer<typeof EnablePackRequest>;
5879
6876
 
6877
+ export const PackComponentResolutionStatus = z.enum(["ready", "missing", "mismatch"]);
6878
+ export type PackComponentResolutionStatus = z.infer<typeof PackComponentResolutionStatus>;
6879
+
6880
+ export const PackComponentResolution = z
6881
+ .object({
6882
+ key: CapabilityPackComponentKey,
6883
+ kind: z.enum(["plugin", "skill", "integration", "feature", "inline_skill"]),
6884
+ capabilityId: z.string().min(1).max(512),
6885
+ required: z.boolean(),
6886
+ status: PackComponentResolutionStatus,
6887
+ expectedDigest: z.string().regex(/^[0-9a-f]{64}$/),
6888
+ actualDigest: z
6889
+ .string()
6890
+ .regex(/^[0-9a-f]{64}$/)
6891
+ .nullable(),
6892
+ resolvedId: z.string().min(1).max(512).nullable(),
6893
+ label: z.string().min(1).max(200),
6894
+ })
6895
+ .strict();
6896
+ export type PackComponentResolution = z.infer<typeof PackComponentResolution>;
6897
+
6898
+ export const PackRigResolution = z
6899
+ .object({
6900
+ required: z.boolean(),
6901
+ status: z.enum(["not_required", "ready", "missing", "mismatch", "unverified"]),
6902
+ requestedRigId: z.string().uuid().nullable(),
6903
+ rigId: z.string().uuid().nullable(),
6904
+ rigVersionId: z.string().uuid().nullable(),
6905
+ name: z.string().min(1).max(200).nullable(),
6906
+ image: z.string().min(1).max(512).nullable(),
6907
+ })
6908
+ .strict();
6909
+ export type PackRigResolution = z.infer<typeof PackRigResolution>;
6910
+
6911
+ export const PreviewPackInstallationRequest = z
6912
+ .object({
6913
+ rigId: z.string().uuid().optional(),
6914
+ variableSetId: z.string().uuid().optional(),
6915
+ })
6916
+ .strict();
6917
+ export type PreviewPackInstallationRequest = z.infer<typeof PreviewPackInstallationRequest>;
6918
+
6919
+ export const PackInstallationPreview = z
6920
+ .object({
6921
+ packId: z.string().min(1),
6922
+ packVersion: z.string().min(1),
6923
+ manifestDigest: z.string().regex(/^[0-9a-f]{64}$/),
6924
+ installationVersion: z.number().int().positive().nullable(),
6925
+ action: z.enum(["install", "update", "repair"]),
6926
+ ready: z.boolean(),
6927
+ blockers: z.array(z.string().min(1).max(500)).max(256),
6928
+ components: z.array(PackComponentResolution).max(160),
6929
+ rig: PackRigResolution,
6930
+ variableSetId: z.string().uuid().nullable(),
6931
+ legacyInlineSkillCount: z.number().int().nonnegative().max(32),
6932
+ legacySandboxImage: z.string().min(1).max(512).nullable(),
6933
+ })
6934
+ .strict();
6935
+ export type PackInstallationPreview = z.infer<typeof PackInstallationPreview>;
6936
+
6937
+ export const InstallPackRequest = z
6938
+ .object({
6939
+ expectedManifestDigest: z.string().regex(/^[0-9a-f]{64}$/),
6940
+ expectedInstallationVersion: z.number().int().positive().optional(),
6941
+ rigId: z.string().uuid().optional(),
6942
+ variableSetId: z.string().uuid().optional(),
6943
+ idempotencyKey: z.string().uuid(),
6944
+ metadata: z.record(z.string(), z.unknown()).default({}),
6945
+ })
6946
+ .strict();
6947
+ export type InstallPackRequest = z.infer<typeof InstallPackRequest>;
6948
+
6949
+ export const PackUninstallPreview = z
6950
+ .object({
6951
+ packId: z.string().min(1),
6952
+ installed: z.boolean(),
6953
+ installationVersion: z.number().int().positive().nullable(),
6954
+ components: z
6955
+ .array(
6956
+ z
6957
+ .object({
6958
+ key: CapabilityPackComponentKey,
6959
+ kind: z.enum(["plugin", "skill", "integration", "feature", "inline_skill"]),
6960
+ capabilityId: z.string().min(1).max(512),
6961
+ retainedByOtherOwners: z.boolean(),
6962
+ })
6963
+ .strict(),
6964
+ )
6965
+ .max(160),
6966
+ })
6967
+ .strict();
6968
+ export type PackUninstallPreview = z.infer<typeof PackUninstallPreview>;
6969
+
6970
+ export const UninstallPackRequest = z
6971
+ .object({
6972
+ expectedInstallationVersion: z.number().int().positive(),
6973
+ idempotencyKey: z.string().uuid(),
6974
+ })
6975
+ .strict();
6976
+ export type UninstallPackRequest = z.infer<typeof UninstallPackRequest>;
6977
+
6978
+ export const UninstallPackResult = z
6979
+ .object({
6980
+ packId: z.string().min(1),
6981
+ status: z.enum(["not_installed", "uninstalled"]),
6982
+ retainedComponents: z.array(z.string().min(1).max(512)).max(160),
6983
+ })
6984
+ .strict();
6985
+ export type UninstallPackResult = z.infer<typeof UninstallPackResult>;
6986
+
5880
6987
  export const SocialProvider = z.enum([
5881
6988
  "x",
5882
6989
  "reddit",
@@ -6110,6 +7217,38 @@ export const OpenGeniSlackBotInstallStart = z.object({
6110
7217
  });
6111
7218
  export type OpenGeniSlackBotInstallStart = z.infer<typeof OpenGeniSlackBotInstallStart>;
6112
7219
 
7220
+ export const SlackInstallationBindingState = z.enum(["active", "quarantined"]);
7221
+ export type SlackInstallationBindingState = z.infer<typeof SlackInstallationBindingState>;
7222
+
7223
+ export const SlackInstallationBinding = z.object({
7224
+ id: z.string().uuid(),
7225
+ accountId: z.string().uuid(),
7226
+ accountName: z.string().min(1),
7227
+ workspaceId: z.string().uuid(),
7228
+ workspaceName: z.string().min(1),
7229
+ connectionId: z.string().uuid(),
7230
+ connectionStatus: ConnectionStatus,
7231
+ connectionVersion: z.number().int().positive(),
7232
+ slackTeamId: z.string().min(1).max(64),
7233
+ slackTeamName: z.string().min(1).max(256),
7234
+ botId: z.string().min(1).max(64),
7235
+ botUserId: z.string().min(1).max(64),
7236
+ botDisplayName: z.literal("OpenGeni"),
7237
+ state: SlackInstallationBindingState,
7238
+ quarantineReason: z.string().min(1).nullable(),
7239
+ version: z.number().int().positive(),
7240
+ createdAt: z.string(),
7241
+ updatedAt: z.string(),
7242
+ });
7243
+ export type SlackInstallationBinding = z.infer<typeof SlackInstallationBinding>;
7244
+
7245
+ export const ListSlackInstallationBindingsResponse = z.object({
7246
+ bindings: z.array(SlackInstallationBinding),
7247
+ });
7248
+ export type ListSlackInstallationBindingsResponse = z.infer<
7249
+ typeof ListSlackInstallationBindingsResponse
7250
+ >;
7251
+
6113
7252
  export const UpdateConnectionRequest = z.object({
6114
7253
  providerDomain: z.string().min(1).optional(),
6115
7254
  subjectId: z.string().min(1).nullable().optional(),
@@ -6201,176 +7340,914 @@ export const CapabilitySource = z.enum([
6201
7340
  ]);
6202
7341
  export type CapabilitySource = z.infer<typeof CapabilitySource>;
6203
7342
 
6204
- export const CapabilityInstallationStatus = z.enum(["active", "disabled"]);
6205
- export type CapabilityInstallationStatus = z.infer<typeof CapabilityInstallationStatus>;
7343
+ export const CapabilityInstallationStatus = z.enum(["active", "disabled"]);
7344
+ export type CapabilityInstallationStatus = z.infer<typeof CapabilityInstallationStatus>;
7345
+
7346
+ export const CapabilityCatalogAuthKind = z.enum(["oauth2", "api_key", "none", "unknown"]);
7347
+ export type CapabilityCatalogAuthKind = z.infer<typeof CapabilityCatalogAuthKind>;
7348
+
7349
+ export const CapabilityCatalogTier = z.enum(["verified", "community"]);
7350
+ export type CapabilityCatalogTier = z.infer<typeof CapabilityCatalogTier>;
7351
+
7352
+ /**
7353
+ * User-facing lifecycle truth for the Capabilities control center. This is a
7354
+ * read-model projection only: each action is still executed by the owning
7355
+ * Plugin, Integration, Connection, Skill, or Pack domain.
7356
+ */
7357
+ export const CapabilityLifecycleStatus = z.enum([
7358
+ "available",
7359
+ "installed",
7360
+ "connected",
7361
+ "ready",
7362
+ "needs_attention",
7363
+ "unavailable",
7364
+ "managed",
7365
+ ]);
7366
+ export type CapabilityLifecycleStatus = z.infer<typeof CapabilityLifecycleStatus>;
7367
+
7368
+ export const CapabilityReadiness = z.enum(["ready", "setup_required", "attention", "unavailable"]);
7369
+ export type CapabilityReadiness = z.infer<typeof CapabilityReadiness>;
7370
+
7371
+ export const CapabilityAction = z.enum([
7372
+ "install",
7373
+ "connect",
7374
+ "configure",
7375
+ "update",
7376
+ "repair",
7377
+ "disconnect",
7378
+ "uninstall",
7379
+ "inspect",
7380
+ ]);
7381
+ export type CapabilityAction = z.infer<typeof CapabilityAction>;
7382
+
7383
+ export const CapabilityLifecycle = z.object({
7384
+ status: CapabilityLifecycleStatus,
7385
+ readiness: CapabilityReadiness,
7386
+ detail: z.string().nullable().default(null),
7387
+ managedBy: z.enum(["deployment", "platform", "workspace"]).nullable().default(null),
7388
+ });
7389
+ export type CapabilityLifecycle = z.infer<typeof CapabilityLifecycle>;
7390
+
7391
+ export const CapabilityRuntime = z.object({
7392
+ available: z.boolean().default(false),
7393
+ mcpServerId: z.string().min(1).optional(),
7394
+ transport: z.string().min(1).optional(),
7395
+ notes: z.string().nullable().default(null),
7396
+ // Registry exposure provenance is server-derived and contains no endpoint or
7397
+ // credential material.
7398
+ catalogTrust: z
7399
+ .object({
7400
+ state: z.enum(["trusted", "legacy_active", "unverified"]),
7401
+ reason: z.enum([
7402
+ "trusted_source",
7403
+ "verified_probe",
7404
+ "active_installation_compatibility",
7405
+ "missing_verification",
7406
+ ]),
7407
+ })
7408
+ .optional(),
7409
+ });
7410
+ export type CapabilityRuntime = z.infer<typeof CapabilityRuntime>;
7411
+
7412
+ export const CapabilityCatalogItem = z.object({
7413
+ id: z.string().min(1),
7414
+ accountId: z.string().uuid().optional(),
7415
+ workspaceId: z.string().uuid().optional(),
7416
+ kind: CapabilityKind,
7417
+ source: CapabilitySource,
7418
+ name: z.string().min(1),
7419
+ description: z.string().nullable().default(null),
7420
+ category: z.string().min(1).default("custom"),
7421
+ tags: z.array(z.string().min(1)).default([]),
7422
+ homepageUrl: z.string().url().nullable().default(null),
7423
+ endpointUrl: z.string().url().nullable().default(null),
7424
+ installUrl: z.string().url().nullable().default(null),
7425
+ authModel: z.string().min(1).nullable().default(null),
7426
+ providerDomain: z.string().min(1).nullable().default(null),
7427
+ surfaceType: z.string().min(1).nullable().default(null),
7428
+ transport: z.string().min(1).nullable().default(null),
7429
+ mcpUrl: z.string().url().nullable().default(null),
7430
+ authKind: CapabilityCatalogAuthKind.nullable().default(null),
7431
+ credentialFacts: z.array(z.record(z.string(), z.unknown())).default([]),
7432
+ tier: CapabilityCatalogTier.nullable().default(null),
7433
+ provenance: z.string().min(1).nullable().default(null),
7434
+ logoAssetPath: z.string().min(1).nullable().default(null),
7435
+ importBatchId: z.string().uuid().nullable().default(null),
7436
+ stale: z.boolean().default(false),
7437
+ staleAt: z.string().nullable().default(null),
7438
+ tools: z.array(ToolRef).default([]),
7439
+ runtime: CapabilityRuntime.default({ available: false, notes: null }),
7440
+ lifecycle: CapabilityLifecycle.default({
7441
+ status: "available",
7442
+ readiness: "setup_required",
7443
+ detail: null,
7444
+ managedBy: null,
7445
+ }),
7446
+ actions: z.array(CapabilityAction).default([]),
7447
+ /**
7448
+ * @deprecated Compatibility projection for existing clients. New surfaces
7449
+ * must use lifecycle and actions rather than treating every type as an
7450
+ * enable/disable toggle.
7451
+ */
7452
+ enabled: z.boolean().default(false),
7453
+ /** @deprecated Compatibility explanation paired with enabled. */
7454
+ enabledReason: z.string().nullable().default(null),
7455
+ // The non-secret connection binding stored with an enabled installation.
7456
+ // Workspace refs retain an exact row id. Subject refs deliberately omit it:
7457
+ // each caller resolves their own visible row by provider/kind at runtime.
7458
+ connectionRef: z
7459
+ .object({
7460
+ connectionId: z.string().min(1).optional(),
7461
+ providerDomain: z.string().min(1),
7462
+ kind: z.string().min(1),
7463
+ subjectScope: z.enum(["workspace", "subject"]).optional(),
7464
+ })
7465
+ .nullable()
7466
+ .default(null),
7467
+ metadata: z.record(z.string(), z.unknown()).default({}),
7468
+ createdAt: z.string().optional(),
7469
+ updatedAt: z.string().optional(),
7470
+ });
7471
+ export type CapabilityCatalogItem = z.infer<typeof CapabilityCatalogItem>;
7472
+
7473
+ /**
7474
+ * Shared trust gate for catalog visibility and runtime selection. Registry rows
7475
+ * remain durable for provenance and audit, but only a reviewed real-MCP probe
7476
+ * with known authentication is exposable. API-key rows additionally need a
7477
+ * machine-actionable header contract; prose credential instructions are not a
7478
+ * runtime contract and must fail closed.
7479
+ */
7480
+ export function capabilityCatalogItemIsTrustedForExposure(
7481
+ item: Pick<CapabilityCatalogItem, "source" | "stale" | "authKind" | "metadata">,
7482
+ ): boolean {
7483
+ if (item.stale) return false;
7484
+ if (item.source !== "registry") return true;
7485
+ const probe = item.metadata.mcpProbe;
7486
+ if (!probe || typeof probe !== "object" || Array.isArray(probe)) return false;
7487
+ if ((probe as Record<string, unknown>).status !== "real") return false;
7488
+ if (item.authKind === null || item.authKind === "unknown") return false;
7489
+ if (item.authKind !== "api_key") return true;
7490
+ const contract = item.metadata.authContract;
7491
+ if (!contract || typeof contract !== "object" || Array.isArray(contract)) return false;
7492
+ const record = contract as Record<string, unknown>;
7493
+ return (
7494
+ typeof record.headerName === "string" &&
7495
+ /^[A-Za-z0-9!#$%&'*+.^_`|~-]+$/.test(record.headerName) &&
7496
+ typeof record.scheme === "string" &&
7497
+ record.scheme.trim().length > 0
7498
+ );
7499
+ }
7500
+
7501
+ export const CapabilityInstallation = z.object({
7502
+ id: z.string().uuid(),
7503
+ accountId: z.string().uuid(),
7504
+ workspaceId: z.string().uuid(),
7505
+ capabilityId: z.string().min(1),
7506
+ kind: CapabilityKind,
7507
+ status: CapabilityInstallationStatus,
7508
+ config: z.record(z.string(), z.unknown()),
7509
+ metadata: z.record(z.string(), z.unknown()),
7510
+ enabledAt: z.string(),
7511
+ updatedAt: z.string(),
7512
+ });
7513
+ export type CapabilityInstallation = z.infer<typeof CapabilityInstallation>;
7514
+
7515
+ export const CreateCapabilityCatalogItemRequest = z.object({
7516
+ id: z.string().min(1).optional(),
7517
+ kind: CapabilityKind.exclude(["pack"]),
7518
+ source: CapabilitySource.default("manual"),
7519
+ name: z.string().min(1),
7520
+ description: z.string().min(1).optional(),
7521
+ category: z.string().min(1).default("custom"),
7522
+ tags: z.array(z.string().min(1)).default([]),
7523
+ homepageUrl: z.string().url().optional(),
7524
+ endpointUrl: z.string().url().optional(),
7525
+ installUrl: z.string().url().optional(),
7526
+ authModel: z.string().min(1).optional(),
7527
+ metadata: z.record(z.string(), z.unknown()).default({}),
7528
+ });
7529
+ export type CreateCapabilityCatalogItemRequest = z.infer<typeof CreateCapabilityCatalogItemRequest>;
7530
+
7531
+ export const EnableCapabilityRequest = withVariableSetIdAlias({
7532
+ config: z.record(z.string(), z.unknown()).default({}),
7533
+ metadata: z.record(z.string(), z.unknown()).default({}),
7534
+ connectionRef: McpServerConnectionRef.optional(),
7535
+ /**
7536
+ * Credential headers for remote MCP capabilities (for example an
7537
+ * Authorization bearer token). Values are encrypted at rest with the
7538
+ * workspace-variable-sets key, injected only into the runtime MCP client,
7539
+ * and never returned by the API — responses expose header names only.
7540
+ */
7541
+ headers: z.record(z.string(), z.string()).default({}),
7542
+ /**
7543
+ * Initial variableSet attachment for kind=pack capabilities. Mirrors the
7544
+ * dedicated POST /packs/:id/enable body: required to enable an
7545
+ * variableSet.required pack through the unified capability-enable path,
7546
+ * optional otherwise. Ignored by non-pack capabilities.
7547
+ */
7548
+ variableSetId: z.string().uuid().optional(),
7549
+ environmentId: z.string().uuid().optional(),
7550
+ });
7551
+ export type EnableCapabilityRequest = z.infer<typeof EnableCapabilityRequest>;
7552
+
7553
+ export const CapabilityCatalogResponse = z.object({
7554
+ items: z.array(CapabilityCatalogItem),
7555
+ installations: z.array(CapabilityInstallation),
7556
+ });
7557
+ export type CapabilityCatalogResponse = z.infer<typeof CapabilityCatalogResponse>;
7558
+
7559
+ export const DiscoverMcpCapabilitiesResponse = z.object({
7560
+ items: z.array(CapabilityCatalogItem),
7561
+ source: z.literal("official_mcp_registry"),
7562
+ sourceUrl: z.string().url(),
7563
+ });
7564
+ export type DiscoverMcpCapabilitiesResponse = z.infer<typeof DiscoverMcpCapabilitiesResponse>;
7565
+
7566
+ export const SkillImportSource = z.enum(["github", "skills_sh"]);
7567
+ export type SkillImportSource = z.infer<typeof SkillImportSource>;
7568
+
7569
+ export const PreviewSkillImportRequest = z.object({
7570
+ url: z.string().url().max(2048),
7571
+ });
7572
+ export type PreviewSkillImportRequest = z.infer<typeof PreviewSkillImportRequest>;
7573
+
7574
+ export const SkillImportFileSummary = z.object({
7575
+ path: z.string().min(1).max(1024),
7576
+ byteSize: z.number().int().nonnegative().max(262144),
7577
+ contentSha256: z.string().regex(/^[0-9a-f]{64}$/),
7578
+ });
7579
+ export type SkillImportFileSummary = z.infer<typeof SkillImportFileSummary>;
7580
+
7581
+ export const SkillImportPreview = z.object({
7582
+ source: SkillImportSource,
7583
+ sourceUrl: z.string().url(),
7584
+ repositoryUrl: z.string().url(),
7585
+ owner: z.string().min(1).max(100),
7586
+ repository: z.string().min(1).max(100),
7587
+ sourcePath: z.string().min(1).max(1024),
7588
+ sourceCommit: z.string().regex(/^[0-9a-f]{40,64}$/),
7589
+ name: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/),
7590
+ description: z.string().min(1).max(2048),
7591
+ contentSha256: z.string().regex(/^[0-9a-f]{64}$/),
7592
+ totalBytes: z.number().int().positive().max(1048576),
7593
+ files: z.array(SkillImportFileSummary).min(1).max(128),
7594
+ warnings: z.array(z.string().min(1).max(500)).max(32).default([]),
7595
+ installed: z.boolean().default(false),
7596
+ installationVersion: z.number().int().positive().nullable().default(null),
7597
+ });
7598
+ export type SkillImportPreview = z.infer<typeof SkillImportPreview>;
7599
+
7600
+ export const InstallSkillRequest = z.object({
7601
+ url: z.string().url().max(2048),
7602
+ expectedSourceCommit: z.string().regex(/^[0-9a-f]{40,64}$/),
7603
+ expectedContentSha256: z.string().regex(/^[0-9a-f]{64}$/),
7604
+ expectedInstallationVersion: z.number().int().positive().optional(),
7605
+ });
7606
+ export type InstallSkillRequest = z.infer<typeof InstallSkillRequest>;
7607
+
7608
+ export const InstalledSkill = z.object({
7609
+ capabilityId: z.string().min(1),
7610
+ pluginId: z.string().uuid(),
7611
+ pluginVersionId: z.string().uuid(),
7612
+ facetId: z.string().uuid(),
7613
+ pluginInstallationId: z.string().uuid(),
7614
+ facetInstallationId: z.string().uuid(),
7615
+ installationVersion: z.number().int().positive(),
7616
+ source: SkillImportSource,
7617
+ sourceUrl: z.string().url(),
7618
+ sourceCommit: z.string().regex(/^[0-9a-f]{40,64}$/),
7619
+ contentSha256: z.string().regex(/^[0-9a-f]{64}$/),
7620
+ name: z.string(),
7621
+ status: z.literal("installed"),
7622
+ });
7623
+ export type InstalledSkill = z.infer<typeof InstalledSkill>;
7624
+
7625
+ export const CapabilityComponentOwner = z.object({
7626
+ kind: z.enum(["direct", "plugin", "pack", "migration"]),
7627
+ id: z.string().min(1).max(512),
7628
+ removable: z.boolean(),
7629
+ });
7630
+ export type CapabilityComponentOwner = z.infer<typeof CapabilityComponentOwner>;
7631
+
7632
+ export const SkillUninstallPreview = z.object({
7633
+ capabilityId: z.string().min(1),
7634
+ installed: z.boolean(),
7635
+ installationVersion: z.number().int().positive().nullable(),
7636
+ directOwner: CapabilityComponentOwner.nullable(),
7637
+ remainingOwners: z.array(CapabilityComponentOwner),
7638
+ removesRuntimeSkill: z.boolean(),
7639
+ });
7640
+ export type SkillUninstallPreview = z.infer<typeof SkillUninstallPreview>;
7641
+
7642
+ export const UninstallSkillRequest = z.object({
7643
+ expectedInstallationVersion: z.number().int().positive(),
7644
+ });
7645
+ export type UninstallSkillRequest = z.infer<typeof UninstallSkillRequest>;
7646
+
7647
+ export const UninstallSkillResult = z.object({
7648
+ capabilityId: z.string().min(1),
7649
+ status: z.enum(["not_installed", "uninstalled", "retained_by_other_owners"]),
7650
+ remainingOwners: z.array(CapabilityComponentOwner),
7651
+ });
7652
+ export type UninstallSkillResult = z.infer<typeof UninstallSkillResult>;
7653
+
7654
+ export const ApiIntegrationProtocol = z.enum(["openapi", "graphql"]);
7655
+ export type ApiIntegrationProtocol = z.infer<typeof ApiIntegrationProtocol>;
7656
+
7657
+ export const IntegrationFeatureKey = z
7658
+ .string()
7659
+ .min(1)
7660
+ .max(200)
7661
+ .regex(/^[a-z0-9](?:[a-z0-9._/-]*[a-z0-9])?$/);
7662
+ export type IntegrationFeatureKey = z.infer<typeof IntegrationFeatureKey>;
7663
+
7664
+ export const IntegrationFeatureKind = z.enum([
7665
+ "tools",
7666
+ "knowledge_source",
7667
+ "inbound_trigger",
7668
+ "delivery_destination",
7669
+ "identity_link",
7670
+ ]);
7671
+ export type IntegrationFeatureKind = z.infer<typeof IntegrationFeatureKind>;
7672
+
7673
+ export const IntegrationFeatureStatus = z.enum(["active", "paused", "needs_attention", "disabled"]);
7674
+ export type IntegrationFeatureStatus = z.infer<typeof IntegrationFeatureStatus>;
7675
+
7676
+ const IntegrationFeatureJsonObject = z.record(z.string(), z.unknown()).superRefine((value, ctx) => {
7677
+ let serialized: string;
7678
+ try {
7679
+ serialized = JSON.stringify(value);
7680
+ } catch {
7681
+ ctx.addIssue({ code: "custom", message: "must be JSON serializable" });
7682
+ return;
7683
+ }
7684
+ if (new TextEncoder().encode(serialized).byteLength > 131_072) {
7685
+ ctx.addIssue({ code: "custom", message: "must not exceed 131072 UTF-8 bytes" });
7686
+ }
7687
+ });
7688
+
7689
+ export const IntegrationFeatureDefinitionSummary = z
7690
+ .object({
7691
+ featureKey: IntegrationFeatureKey,
7692
+ kind: IntegrationFeatureKind.exclude(["tools"]),
7693
+ configSchema: IntegrationFeatureJsonObject,
7694
+ capabilities: IntegrationFeatureJsonObject,
7695
+ })
7696
+ .strict();
7697
+ export type IntegrationFeatureDefinitionSummary = z.infer<
7698
+ typeof IntegrationFeatureDefinitionSummary
7699
+ >;
7700
+
7701
+ export const ApiIntegrationPresetSummary = z
7702
+ .object({
7703
+ id: z.string().min(1).max(128),
7704
+ name: z.string().min(1).max(200),
7705
+ summary: z.string().min(1).max(1000),
7706
+ family: z.enum(["google", "microsoft"]),
7707
+ protocol: z.literal("openapi"),
7708
+ providerDomain: z.string().min(1).max(253),
7709
+ scopes: z.array(z.string().min(1).max(1024)).max(256),
7710
+ features: z.array(IntegrationFeatureDefinitionSummary).max(128),
7711
+ })
7712
+ .strict();
7713
+ export type ApiIntegrationPresetSummary = z.infer<typeof ApiIntegrationPresetSummary>;
7714
+
7715
+ export const ListApiIntegrationPresetsResponse = z
7716
+ .object({ presets: z.array(ApiIntegrationPresetSummary).max(128) })
7717
+ .strict();
7718
+ export type ListApiIntegrationPresetsResponse = z.infer<typeof ListApiIntegrationPresetsResponse>;
7719
+
7720
+ export const IntegrationInstanceKey = z
7721
+ .string()
7722
+ .min(1)
7723
+ .max(128)
7724
+ .regex(/^[a-z0-9](?:[a-z0-9._/-]*[a-z0-9])?$/);
7725
+ export type IntegrationInstanceKey = z.infer<typeof IntegrationInstanceKey>;
7726
+
7727
+ export const IntegrationFeatureBindingSummary = z
7728
+ .object({
7729
+ id: z.string().uuid(),
7730
+ featureKey: IntegrationFeatureKey,
7731
+ kind: IntegrationFeatureKind.exclude(["tools"]),
7732
+ bindingKey: IntegrationInstanceKey,
7733
+ displayName: z.string().min(1).max(200),
7734
+ connectionId: z.string().uuid().nullable(),
7735
+ status: IntegrationFeatureStatus,
7736
+ config: IntegrationFeatureJsonObject,
7737
+ version: z.number().int().positive(),
7738
+ hasCursor: z.boolean(),
7739
+ lastSuccessAt: z.string().datetime({ offset: true }).nullable(),
7740
+ lastErrorCode: z.string().min(1).max(120).nullable(),
7741
+ createdAt: z.string().datetime({ offset: true }),
7742
+ updatedAt: z.string().datetime({ offset: true }),
7743
+ })
7744
+ .strict();
7745
+ export type IntegrationFeatureBindingSummary = z.infer<typeof IntegrationFeatureBindingSummary>;
7746
+
7747
+ export const IntegrationInstanceFeaturesResponse = z
7748
+ .object({
7749
+ capabilityId: z.string().min(1).max(512),
7750
+ instanceKey: IntegrationInstanceKey,
7751
+ providerDomain: z.string().min(1).max(253),
7752
+ connectionId: z.string().uuid().nullable(),
7753
+ features: z
7754
+ .array(
7755
+ z
7756
+ .object({
7757
+ definition: IntegrationFeatureDefinitionSummary,
7758
+ binding: IntegrationFeatureBindingSummary.nullable(),
7759
+ })
7760
+ .strict(),
7761
+ )
7762
+ .max(128),
7763
+ })
7764
+ .strict();
7765
+ export type IntegrationInstanceFeaturesResponse = z.infer<
7766
+ typeof IntegrationInstanceFeaturesResponse
7767
+ >;
7768
+
7769
+ export const UpsertIntegrationFeatureRequest = z
7770
+ .object({
7771
+ displayName: z.string().min(1).max(200),
7772
+ config: IntegrationFeatureJsonObject.default({}),
7773
+ expectedVersion: z.number().int().positive().optional(),
7774
+ idempotencyKey: z.string().uuid(),
7775
+ })
7776
+ .strict();
7777
+ export type UpsertIntegrationFeatureRequest = z.infer<typeof UpsertIntegrationFeatureRequest>;
7778
+
7779
+ export const MutateIntegrationFeatureRequest = z
7780
+ .object({
7781
+ expectedVersion: z.number().int().positive(),
7782
+ idempotencyKey: z.string().uuid(),
7783
+ })
7784
+ .strict();
7785
+ export type MutateIntegrationFeatureRequest = z.infer<typeof MutateIntegrationFeatureRequest>;
7786
+
7787
+ export const IntegrationFeatureMutationResult = z
7788
+ .object({
7789
+ capabilityId: z.string().min(1).max(512),
7790
+ instanceKey: IntegrationInstanceKey,
7791
+ featureKey: IntegrationFeatureKey,
7792
+ status: z.enum(["configured", "paused", "active"]),
7793
+ binding: IntegrationFeatureBindingSummary,
7794
+ })
7795
+ .strict();
7796
+ export type IntegrationFeatureMutationResult = z.infer<typeof IntegrationFeatureMutationResult>;
7797
+
7798
+ export const IntegrationFeatureRemovalResult = z
7799
+ .object({
7800
+ capabilityId: z.string().min(1).max(512),
7801
+ instanceKey: IntegrationInstanceKey,
7802
+ featureKey: IntegrationFeatureKey,
7803
+ status: z.enum(["not_configured", "removed", "retained_by_other_owners"]),
7804
+ binding: IntegrationFeatureBindingSummary.nullable(),
7805
+ remainingOwners: z.array(CapabilityComponentOwner),
7806
+ })
7807
+ .strict();
7808
+ export type IntegrationFeatureRemovalResult = z.infer<typeof IntegrationFeatureRemovalResult>;
7809
+
7810
+ export const ApiIntegrationSource = z.discriminatedUnion("kind", [
7811
+ z.object({ kind: z.literal("preset"), presetId: z.string().min(1).max(128) }).strict(),
7812
+ z
7813
+ .object({
7814
+ kind: z.literal("openapi"),
7815
+ url: z.string().url().max(2048),
7816
+ baseUrl: z.string().url().max(2048).optional(),
7817
+ })
7818
+ .strict(),
7819
+ z
7820
+ .object({
7821
+ kind: z.literal("graphql"),
7822
+ endpoint: z.string().url().max(2048),
7823
+ name: z.string().min(1).max(200).optional(),
7824
+ })
7825
+ .strict(),
7826
+ z
7827
+ .object({
7828
+ kind: z.literal("auto"),
7829
+ url: z.string().url().max(2048),
7830
+ baseUrl: z.string().url().max(2048).optional(),
7831
+ })
7832
+ .strict(),
7833
+ ]);
7834
+ export type ApiIntegrationSource = z.infer<typeof ApiIntegrationSource>;
7835
+
7836
+ export const PreviewApiIntegrationRequest = z
7837
+ .object({
7838
+ source: ApiIntegrationSource,
7839
+ connectionId: z.string().uuid().optional(),
7840
+ ownership: ConnectionOwnership.optional(),
7841
+ })
7842
+ .strict();
7843
+ export type PreviewApiIntegrationRequest = z.infer<typeof PreviewApiIntegrationRequest>;
7844
+
7845
+ export const ApiIntegrationOAuthStartRequest = z
7846
+ .object({
7847
+ presetId: z.string().min(1).max(128),
7848
+ ownership: ConnectionOwnership.optional(),
7849
+ connectionId: z.string().uuid().optional(),
7850
+ returnPath: z.string().min(1).max(2048).optional(),
7851
+ })
7852
+ .strict();
7853
+ export type ApiIntegrationOAuthStartRequest = z.infer<typeof ApiIntegrationOAuthStartRequest>;
7854
+
7855
+ export const API_INTEGRATION_OAUTH_CREDENTIAL_ROLE = "api_integration_oauth" as const;
7856
+
7857
+ export const ApiIntegrationOAuthConnectionMetadata = z
7858
+ .object({
7859
+ credentialRole: z.literal(API_INTEGRATION_OAUTH_CREDENTIAL_ROLE),
7860
+ providerFamily: z.enum(["google", "microsoft"]),
7861
+ providerPrincipalId: z.string().min(1).max(512),
7862
+ providerEmail: z.string().min(1).max(512).nullable(),
7863
+ providerDisplayName: z.string().min(1).max(512).nullable(),
7864
+ authorizedPresetIds: z.array(z.string().min(1).max(128)).min(1).max(32),
7865
+ verifiedAt: z.string().datetime({ offset: true }),
7866
+ })
7867
+ .passthrough();
7868
+ export type ApiIntegrationOAuthConnectionMetadata = z.infer<
7869
+ typeof ApiIntegrationOAuthConnectionMetadata
7870
+ >;
7871
+
7872
+ export const ApiIntegrationAuthPreview = z.discriminatedUnion("kind", [
7873
+ z.object({ kind: z.literal("none") }).strict(),
7874
+ z
7875
+ .object({
7876
+ kind: z.literal("oauth2"),
7877
+ providerDomain: z.string().min(1).max(253),
7878
+ scopes: z.array(z.string().min(1).max(1024)).max(256),
7879
+ })
7880
+ .strict(),
7881
+ z
7882
+ .object({
7883
+ kind: z.literal("api_key"),
7884
+ providerDomain: z.string().min(1).max(253),
7885
+ carrier: z.enum(["header", "query", "cookie"]),
7886
+ name: z.string().min(1).max(256),
7887
+ })
7888
+ .strict(),
7889
+ z
7890
+ .object({
7891
+ kind: z.literal("http"),
7892
+ providerDomain: z.string().min(1).max(253),
7893
+ scheme: z.string().min(1).max(64),
7894
+ })
7895
+ .strict(),
7896
+ ]);
7897
+ export type ApiIntegrationAuthPreview = z.infer<typeof ApiIntegrationAuthPreview>;
7898
+
7899
+ export const ApiIntegrationToolPreview = z
7900
+ .object({
7901
+ id: z.string().min(1).max(200),
7902
+ operationKey: z.string().min(1).max(512),
7903
+ name: z.string().min(1).max(200),
7904
+ description: z.string().max(4000),
7905
+ safety: z.enum(["read", "write", "destructive"]),
7906
+ approvalMode: z.enum(["never", "ask"]),
7907
+ deprecated: z.boolean(),
7908
+ })
7909
+ .strict();
7910
+ export type ApiIntegrationToolPreview = z.infer<typeof ApiIntegrationToolPreview>;
7911
+
7912
+ export const ApiIntegrationPreview = z
7913
+ .object({
7914
+ source: ApiIntegrationSource,
7915
+ presetId: z.string().min(1).max(128).nullable(),
7916
+ protocol: ApiIntegrationProtocol,
7917
+ integrationId: z.string().min(1).max(200),
7918
+ capabilityId: z.string().min(1).max(512),
7919
+ pluginKey: z.string().min(1).max(200),
7920
+ serverId: SessionMcpServerId,
7921
+ name: z.string().min(1).max(200),
7922
+ description: z.string().max(4000).nullable(),
7923
+ provider: z.string().min(1).max(128).nullable(),
7924
+ providerDomain: z.string().min(1).max(253),
7925
+ baseUrl: z.string().url().max(2048),
7926
+ sourceUrl: z.string().url().max(2048).nullable(),
7927
+ revisionId: z.string().min(1).max(96),
7928
+ contentSha256: z.string().regex(/^[0-9a-f]{64}$/),
7929
+ auth: ApiIntegrationAuthPreview,
7930
+ connectionId: z.string().uuid().nullable(),
7931
+ connectionOwnership: ConnectionOwnership.nullable(),
7932
+ tools: z.array(ApiIntegrationToolPreview).min(1).max(2000),
7933
+ warnings: z.array(z.string().min(1).max(500)).max(32).default([]),
7934
+ })
7935
+ .strict();
7936
+ export type ApiIntegrationPreview = z.infer<typeof ApiIntegrationPreview>;
7937
+
7938
+ export const InstallApiIntegrationRequest = z
7939
+ .object({
7940
+ source: ApiIntegrationSource,
7941
+ expectedRevisionId: z.string().min(1).max(96),
7942
+ expectedContentSha256: z.string().regex(/^[0-9a-f]{64}$/),
7943
+ connectionId: z.string().uuid().optional(),
7944
+ ownership: ConnectionOwnership.optional(),
7945
+ instanceKey: IntegrationInstanceKey.optional(),
7946
+ displayName: z.string().min(1).max(200).optional(),
7947
+ expectedInstanceVersion: z.number().int().positive().optional(),
7948
+ allowedTools: z.array(z.string().min(1).max(200)).max(2000).optional(),
7949
+ })
7950
+ .strict();
7951
+ export type InstallApiIntegrationRequest = z.infer<typeof InstallApiIntegrationRequest>;
7952
+
7953
+ export const InstalledApiIntegration = z
7954
+ .object({
7955
+ capabilityId: z.string().min(1),
7956
+ pluginId: z.string().uuid(),
7957
+ pluginVersionId: z.string().uuid(),
7958
+ integrationFacetId: z.string().uuid(),
7959
+ apiFacetId: z.string().uuid(),
7960
+ pluginInstallationId: z.string().uuid(),
7961
+ integrationFacetInstallationId: z.string().uuid(),
7962
+ apiFacetInstallationId: z.string().uuid(),
7963
+ installationVersion: z.number().int().positive(),
7964
+ instanceId: z.string().uuid(),
7965
+ instanceKey: IntegrationInstanceKey,
7966
+ displayName: z.string().min(1).max(200),
7967
+ instanceVersion: z.number().int().positive(),
7968
+ revisionId: z.string().min(1),
7969
+ serverId: SessionMcpServerId,
7970
+ status: z.literal("installed"),
7971
+ })
7972
+ .strict();
7973
+ export type InstalledApiIntegration = z.infer<typeof InstalledApiIntegration>;
7974
+
7975
+ export const ApiIntegrationInstallationSummary = z
7976
+ .object({
7977
+ capabilityId: z.string().min(1),
7978
+ pluginKey: z.string().min(1),
7979
+ installationVersion: z.number().int().positive(),
7980
+ instanceId: z.string().uuid(),
7981
+ instanceKey: IntegrationInstanceKey,
7982
+ displayName: z.string().min(1).max(200),
7983
+ instanceVersion: z.number().int().positive(),
7984
+ serverId: SessionMcpServerId,
7985
+ name: z.string().min(1),
7986
+ description: z.string().nullable(),
7987
+ protocol: ApiIntegrationProtocol,
7988
+ presetId: z.string().min(1).max(128).nullable(),
7989
+ providerDomain: z.string().min(1),
7990
+ baseUrl: z.string().url(),
7991
+ sourceUrl: z.string().url().nullable(),
7992
+ connected: z.boolean(),
7993
+ requiresConnection: z.boolean(),
7994
+ connectionId: z.string().uuid().nullable(),
7995
+ ownership: z.enum(["workspace", "personal", "none"]),
7996
+ allowedTools: z.array(z.string().min(1).max(200)).max(2000),
7997
+ toolCount: z.number().int().nonnegative(),
7998
+ approvalRequiredToolCount: z.number().int().nonnegative(),
7999
+ revisionId: z.string().min(1),
8000
+ contentSha256: z.string().regex(/^[0-9a-f]{64}$/),
8001
+ })
8002
+ .strict();
8003
+ export type ApiIntegrationInstallationSummary = z.infer<typeof ApiIntegrationInstallationSummary>;
8004
+
8005
+ export const ListApiIntegrationsResponse = z
8006
+ .object({ integrations: z.array(ApiIntegrationInstallationSummary) })
8007
+ .strict();
8008
+ export type ListApiIntegrationsResponse = z.infer<typeof ListApiIntegrationsResponse>;
8009
+
8010
+ export const ApiIntegrationUninstallPreview = z
8011
+ .object({
8012
+ capabilityId: z.string().min(1),
8013
+ instanceKey: IntegrationInstanceKey,
8014
+ displayName: z.string().min(1).max(200).nullable(),
8015
+ installed: z.boolean(),
8016
+ installationVersion: z.number().int().positive().nullable(),
8017
+ instanceVersion: z.number().int().positive().nullable(),
8018
+ directOwner: CapabilityComponentOwner.nullable(),
8019
+ remainingOwners: z.array(CapabilityComponentOwner),
8020
+ removesRuntimeIntegration: z.boolean(),
8021
+ removesDefinition: z.boolean(),
8022
+ })
8023
+ .strict();
8024
+ export type ApiIntegrationUninstallPreview = z.infer<typeof ApiIntegrationUninstallPreview>;
8025
+
8026
+ export const UninstallApiIntegrationRequest = z
8027
+ .object({
8028
+ expectedInstallationVersion: z.number().int().positive(),
8029
+ expectedInstanceVersion: z.number().int().positive(),
8030
+ })
8031
+ .strict();
8032
+ export type UninstallApiIntegrationRequest = z.infer<typeof UninstallApiIntegrationRequest>;
8033
+
8034
+ export const UninstallApiIntegrationResult = z
8035
+ .object({
8036
+ capabilityId: z.string().min(1),
8037
+ instanceKey: IntegrationInstanceKey,
8038
+ status: z.enum(["not_installed", "uninstalled", "retained_by_other_owners"]),
8039
+ remainingOwners: z.array(CapabilityComponentOwner),
8040
+ definitionStatus: z.enum(["retained", "disabled"]),
8041
+ })
8042
+ .strict();
8043
+ export type UninstallApiIntegrationResult = z.infer<typeof UninstallApiIntegrationResult>;
8044
+
8045
+ const PluginComponentKey = z
8046
+ .string()
8047
+ .min(1)
8048
+ .max(128)
8049
+ .regex(/^[a-z0-9](?:[a-z0-9._/-]*[a-z0-9])?$/);
8050
+
8051
+ export const PluginManifest = z
8052
+ .object({
8053
+ schemaVersion: z.literal(1),
8054
+ pluginKey: z
8055
+ .string()
8056
+ .min(1)
8057
+ .max(200)
8058
+ .regex(/^[a-z0-9](?:[a-z0-9._/-]*[a-z0-9])?$/),
8059
+ version: z.string().min(1).max(128),
8060
+ name: z.string().min(1).max(200),
8061
+ description: z.string().max(4000).default(""),
8062
+ category: z.string().min(1).max(100).default("plugins"),
8063
+ tags: z.array(z.string().min(1).max(100)).max(64).default([]),
8064
+ components: z
8065
+ .array(
8066
+ z.discriminatedUnion("kind", [
8067
+ z
8068
+ .object({ key: PluginComponentKey, kind: z.literal("skill"), url: z.string().url() })
8069
+ .strict(),
8070
+ z
8071
+ .object({
8072
+ key: PluginComponentKey,
8073
+ kind: z.literal("integration"),
8074
+ source: ApiIntegrationSource,
8075
+ })
8076
+ .strict(),
8077
+ z
8078
+ .object({
8079
+ key: PluginComponentKey,
8080
+ kind: z.literal("mcp"),
8081
+ serverId: SessionMcpServerId,
8082
+ })
8083
+ .strict(),
8084
+ ]),
8085
+ )
8086
+ .min(1)
8087
+ .max(64),
8088
+ })
8089
+ .strict()
8090
+ .superRefine((manifest, context) => {
8091
+ const seen = new Set<string>();
8092
+ for (const [index, component] of manifest.components.entries()) {
8093
+ if (seen.has(component.key)) {
8094
+ context.addIssue({
8095
+ code: "custom",
8096
+ message: "Plugin component keys must be unique",
8097
+ path: ["components", index, "key"],
8098
+ });
8099
+ }
8100
+ seen.add(component.key);
8101
+ }
8102
+ });
8103
+ export type PluginManifest = z.infer<typeof PluginManifest>;
8104
+
8105
+ export const PluginComponentBinding = z
8106
+ .object({
8107
+ connectionId: z.string().uuid().optional(),
8108
+ instanceKey: IntegrationInstanceKey.optional(),
8109
+ displayName: z.string().min(1).max(200).optional(),
8110
+ })
8111
+ .strict();
8112
+ export type PluginComponentBinding = z.infer<typeof PluginComponentBinding>;
8113
+
8114
+ export const PreviewPluginRequest = z
8115
+ .object({
8116
+ url: z.string().url().max(2048),
8117
+ bindings: z.record(PluginComponentKey, PluginComponentBinding).default({}),
8118
+ })
8119
+ .strict();
8120
+ export type PreviewPluginRequest = z.infer<typeof PreviewPluginRequest>;
6206
8121
 
6207
- export const CapabilityCatalogAuthKind = z.enum(["oauth2", "api_key", "none", "unknown"]);
6208
- export type CapabilityCatalogAuthKind = z.infer<typeof CapabilityCatalogAuthKind>;
8122
+ export const PluginComponentPreview = z
8123
+ .object({
8124
+ key: PluginComponentKey,
8125
+ kind: z.enum(["skill", "integration", "mcp"]),
8126
+ name: z.string().min(1).max(200),
8127
+ capabilityId: z.string().min(1).max(512),
8128
+ digest: z.string().regex(/^[0-9a-f]{64}$/),
8129
+ connectionRequired: z.boolean(),
8130
+ connectionId: z.string().uuid().nullable(),
8131
+ instanceKey: IntegrationInstanceKey.nullable(),
8132
+ displayName: z.string().min(1).max(200).nullable(),
8133
+ facts: z.record(z.string(), z.unknown()),
8134
+ })
8135
+ .strict();
8136
+ export type PluginComponentPreview = z.infer<typeof PluginComponentPreview>;
6209
8137
 
6210
- export const CapabilityCatalogTier = z.enum(["verified", "community"]);
6211
- export type CapabilityCatalogTier = z.infer<typeof CapabilityCatalogTier>;
8138
+ export const PluginUpdateDiff = z
8139
+ .object({
8140
+ fromVersion: z.string().nullable(),
8141
+ toVersion: z.string().min(1),
8142
+ added: z.array(PluginComponentKey),
8143
+ removed: z.array(PluginComponentKey),
8144
+ changed: z.array(PluginComponentKey),
8145
+ unchanged: z.array(PluginComponentKey),
8146
+ })
8147
+ .strict();
8148
+ export type PluginUpdateDiff = z.infer<typeof PluginUpdateDiff>;
6212
8149
 
6213
- export const CapabilityRuntime = z.object({
6214
- available: z.boolean().default(false),
6215
- mcpServerId: z.string().min(1).optional(),
6216
- transport: z.string().min(1).optional(),
6217
- notes: z.string().nullable().default(null),
6218
- // Registry exposure provenance is server-derived and contains no endpoint or
6219
- // credential material.
6220
- catalogTrust: z
6221
- .object({
6222
- state: z.enum(["trusted", "legacy_active", "unverified"]),
6223
- reason: z.enum([
6224
- "trusted_source",
6225
- "verified_probe",
6226
- "active_installation_compatibility",
6227
- "missing_verification",
6228
- ]),
6229
- })
6230
- .optional(),
6231
- });
6232
- export type CapabilityRuntime = z.infer<typeof CapabilityRuntime>;
8150
+ export const PluginPreview = z
8151
+ .object({
8152
+ sourceUrl: z.string().url(),
8153
+ manifest: PluginManifest,
8154
+ manifestDigest: z.string().regex(/^[0-9a-f]{64}$/),
8155
+ installed: z.boolean(),
8156
+ installationVersion: z.number().int().positive().nullable(),
8157
+ components: z.array(PluginComponentPreview).min(1).max(64),
8158
+ diff: PluginUpdateDiff,
8159
+ })
8160
+ .strict();
8161
+ export type PluginPreview = z.infer<typeof PluginPreview>;
6233
8162
 
6234
- export const CapabilityCatalogItem = z.object({
6235
- id: z.string().min(1),
6236
- accountId: z.string().uuid().optional(),
6237
- workspaceId: z.string().uuid().optional(),
6238
- kind: CapabilityKind,
6239
- source: CapabilitySource,
6240
- name: z.string().min(1),
6241
- description: z.string().nullable().default(null),
6242
- category: z.string().min(1).default("custom"),
6243
- tags: z.array(z.string().min(1)).default([]),
6244
- homepageUrl: z.string().url().nullable().default(null),
6245
- endpointUrl: z.string().url().nullable().default(null),
6246
- installUrl: z.string().url().nullable().default(null),
6247
- authModel: z.string().min(1).nullable().default(null),
6248
- providerDomain: z.string().min(1).nullable().default(null),
6249
- surfaceType: z.string().min(1).nullable().default(null),
6250
- transport: z.string().min(1).nullable().default(null),
6251
- mcpUrl: z.string().url().nullable().default(null),
6252
- authKind: CapabilityCatalogAuthKind.nullable().default(null),
6253
- credentialFacts: z.array(z.record(z.string(), z.unknown())).default([]),
6254
- tier: CapabilityCatalogTier.nullable().default(null),
6255
- provenance: z.string().min(1).nullable().default(null),
6256
- logoAssetPath: z.string().min(1).nullable().default(null),
6257
- importBatchId: z.string().uuid().nullable().default(null),
6258
- stale: z.boolean().default(false),
6259
- staleAt: z.string().nullable().default(null),
6260
- tools: z.array(ToolRef).default([]),
6261
- runtime: CapabilityRuntime.default({ available: false, notes: null }),
6262
- enabled: z.boolean().default(false),
6263
- enabledReason: z.string().nullable().default(null),
6264
- // The non-secret connection binding stored with an enabled installation.
6265
- // Workspace refs retain an exact row id. Subject refs deliberately omit it:
6266
- // each caller resolves their own visible row by provider/kind at runtime.
6267
- connectionRef: z
6268
- .object({
6269
- connectionId: z.string().min(1).optional(),
6270
- providerDomain: z.string().min(1),
6271
- kind: z.string().min(1),
6272
- subjectScope: z.enum(["workspace", "subject"]).optional(),
6273
- })
6274
- .nullable()
6275
- .default(null),
6276
- metadata: z.record(z.string(), z.unknown()).default({}),
6277
- createdAt: z.string().optional(),
6278
- updatedAt: z.string().optional(),
6279
- });
6280
- export type CapabilityCatalogItem = z.infer<typeof CapabilityCatalogItem>;
8163
+ export const InstallPluginRequest = z
8164
+ .object({
8165
+ url: z.string().url().max(2048),
8166
+ expectedManifestDigest: z.string().regex(/^[0-9a-f]{64}$/),
8167
+ expectedComponents: z
8168
+ .array(
8169
+ z.object({ key: PluginComponentKey, digest: z.string().regex(/^[0-9a-f]{64}$/) }).strict(),
8170
+ )
8171
+ .min(1)
8172
+ .max(64),
8173
+ bindings: z.record(PluginComponentKey, PluginComponentBinding).default({}),
8174
+ idempotencyKey: z.string().uuid(),
8175
+ expectedInstallationVersion: z.number().int().positive().optional(),
8176
+ })
8177
+ .strict();
8178
+ export type InstallPluginRequest = z.infer<typeof InstallPluginRequest>;
6281
8179
 
6282
- /**
6283
- * Shared trust gate for catalog visibility and runtime selection. Registry rows
6284
- * remain durable for provenance and audit, but only a reviewed real-MCP probe
6285
- * with known authentication is exposable. API-key rows additionally need a
6286
- * machine-actionable header contract; prose credential instructions are not a
6287
- * runtime contract and must fail closed.
6288
- */
6289
- export function capabilityCatalogItemIsTrustedForExposure(
6290
- item: Pick<CapabilityCatalogItem, "source" | "stale" | "authKind" | "metadata">,
6291
- ): boolean {
6292
- if (item.stale) return false;
6293
- if (item.source !== "registry") return true;
6294
- const probe = item.metadata.mcpProbe;
6295
- if (!probe || typeof probe !== "object" || Array.isArray(probe)) return false;
6296
- if ((probe as Record<string, unknown>).status !== "real") return false;
6297
- if (item.authKind === null || item.authKind === "unknown") return false;
6298
- if (item.authKind !== "api_key") return true;
6299
- const contract = item.metadata.authContract;
6300
- if (!contract || typeof contract !== "object" || Array.isArray(contract)) return false;
6301
- const record = contract as Record<string, unknown>;
6302
- return (
6303
- typeof record.headerName === "string" &&
6304
- /^[A-Za-z0-9!#$%&'*+.^_`|~-]+$/.test(record.headerName) &&
6305
- typeof record.scheme === "string" &&
6306
- record.scheme.trim().length > 0
6307
- );
6308
- }
8180
+ export const InstalledPlugin = z
8181
+ .object({
8182
+ pluginKey: z.string().min(1),
8183
+ version: z.string().min(1),
8184
+ pluginId: z.string().uuid(),
8185
+ pluginVersionId: z.string().uuid(),
8186
+ pluginInstallationId: z.string().uuid(),
8187
+ installationVersion: z.number().int().positive(),
8188
+ componentCount: z.number().int().positive(),
8189
+ status: z.literal("installed"),
8190
+ })
8191
+ .strict();
8192
+ export type InstalledPlugin = z.infer<typeof InstalledPlugin>;
6309
8193
 
6310
- export const CapabilityInstallation = z.object({
6311
- id: z.string().uuid(),
6312
- accountId: z.string().uuid(),
6313
- workspaceId: z.string().uuid(),
6314
- capabilityId: z.string().min(1),
6315
- kind: CapabilityKind,
6316
- status: CapabilityInstallationStatus,
6317
- config: z.record(z.string(), z.unknown()),
6318
- metadata: z.record(z.string(), z.unknown()),
6319
- enabledAt: z.string(),
6320
- updatedAt: z.string(),
6321
- });
6322
- export type CapabilityInstallation = z.infer<typeof CapabilityInstallation>;
8194
+ export const PluginInstallationSummary = z
8195
+ .object({
8196
+ pluginKey: z.string().min(1).max(200),
8197
+ version: z.string().min(1).max(128),
8198
+ name: z.string().min(1).max(200),
8199
+ description: z.string().max(4000),
8200
+ category: z.string().min(1).max(100),
8201
+ tags: z.array(z.string().min(1).max(100)).max(64),
8202
+ sourceUrl: z.string().url().max(2048).nullable(),
8203
+ manifestDigest: z.string().regex(/^[0-9a-f]{64}$/),
8204
+ installationVersion: z.number().int().positive(),
8205
+ componentCount: z.number().int().nonnegative().max(64),
8206
+ status: z.enum(["active", "needs_attention"]),
8207
+ installedAt: z.string().datetime({ offset: true }),
8208
+ updatedAt: z.string().datetime({ offset: true }),
8209
+ })
8210
+ .strict();
8211
+ export type PluginInstallationSummary = z.infer<typeof PluginInstallationSummary>;
6323
8212
 
6324
- export const CreateCapabilityCatalogItemRequest = z.object({
6325
- id: z.string().min(1).optional(),
6326
- kind: CapabilityKind.exclude(["pack"]),
6327
- source: CapabilitySource.default("manual"),
6328
- name: z.string().min(1),
6329
- description: z.string().min(1).optional(),
6330
- category: z.string().min(1).default("custom"),
6331
- tags: z.array(z.string().min(1)).default([]),
6332
- homepageUrl: z.string().url().optional(),
6333
- endpointUrl: z.string().url().optional(),
6334
- installUrl: z.string().url().optional(),
6335
- authModel: z.string().min(1).optional(),
6336
- metadata: z.record(z.string(), z.unknown()).default({}),
6337
- });
6338
- export type CreateCapabilityCatalogItemRequest = z.infer<typeof CreateCapabilityCatalogItemRequest>;
8213
+ export const ListInstalledPluginsResponse = z
8214
+ .object({ plugins: z.array(PluginInstallationSummary).max(1000) })
8215
+ .strict();
8216
+ export type ListInstalledPluginsResponse = z.infer<typeof ListInstalledPluginsResponse>;
6339
8217
 
6340
- export const EnableCapabilityRequest = withVariableSetIdAlias({
6341
- config: z.record(z.string(), z.unknown()).default({}),
6342
- metadata: z.record(z.string(), z.unknown()).default({}),
6343
- connectionRef: McpServerConnectionRef.optional(),
6344
- /**
6345
- * Credential headers for remote MCP capabilities (for example an
6346
- * Authorization bearer token). Values are encrypted at rest with the
6347
- * workspace-variable-sets key, injected only into the runtime MCP client,
6348
- * and never returned by the API — responses expose header names only.
6349
- */
6350
- headers: z.record(z.string(), z.string()).default({}),
6351
- /**
6352
- * Initial variableSet attachment for kind=pack capabilities. Mirrors the
6353
- * dedicated POST /packs/:id/enable body: required to enable an
6354
- * variableSet.required pack through the unified capability-enable path,
6355
- * optional otherwise. Ignored by non-pack capabilities.
6356
- */
6357
- variableSetId: z.string().uuid().optional(),
6358
- environmentId: z.string().uuid().optional(),
6359
- });
6360
- export type EnableCapabilityRequest = z.infer<typeof EnableCapabilityRequest>;
8218
+ export const PluginUninstallPreview = z
8219
+ .object({
8220
+ pluginKey: z.string().min(1),
8221
+ installed: z.boolean(),
8222
+ version: z.string().nullable(),
8223
+ installationVersion: z.number().int().positive().nullable(),
8224
+ components: z.array(
8225
+ z.object({
8226
+ capabilityId: z.string().min(1),
8227
+ kind: z.enum(["skill", "integration", "mcp"]),
8228
+ retainedByOtherOwners: z.boolean(),
8229
+ }),
8230
+ ),
8231
+ })
8232
+ .strict();
8233
+ export type PluginUninstallPreview = z.infer<typeof PluginUninstallPreview>;
6361
8234
 
6362
- export const CapabilityCatalogResponse = z.object({
6363
- items: z.array(CapabilityCatalogItem),
6364
- installations: z.array(CapabilityInstallation),
6365
- });
6366
- export type CapabilityCatalogResponse = z.infer<typeof CapabilityCatalogResponse>;
8235
+ export const UninstallPluginRequest = z
8236
+ .object({
8237
+ expectedInstallationVersion: z.number().int().positive(),
8238
+ idempotencyKey: z.string().uuid(),
8239
+ })
8240
+ .strict();
8241
+ export type UninstallPluginRequest = z.infer<typeof UninstallPluginRequest>;
6367
8242
 
6368
- export const DiscoverMcpCapabilitiesResponse = z.object({
6369
- items: z.array(CapabilityCatalogItem),
6370
- source: z.literal("official_mcp_registry"),
6371
- sourceUrl: z.string().url(),
6372
- });
6373
- export type DiscoverMcpCapabilitiesResponse = z.infer<typeof DiscoverMcpCapabilitiesResponse>;
8243
+ export const UninstallPluginResult = z
8244
+ .object({
8245
+ pluginKey: z.string().min(1),
8246
+ status: z.enum(["not_installed", "uninstalled"]),
8247
+ retainedComponents: z.array(z.string().min(1)),
8248
+ })
8249
+ .strict();
8250
+ export type UninstallPluginResult = z.infer<typeof UninstallPluginResult>;
6374
8251
 
6375
8252
  export const Session = z.object({
6376
8253
  id: z.string().uuid(),
@@ -6535,6 +8412,57 @@ export const SessionListResponse = z.object({
6535
8412
  });
6536
8413
  export type SessionListResponse = z.infer<typeof SessionListResponse>;
6537
8414
 
8415
+ /** Compact, bounded session projection for workspace agent-topology browsers. */
8416
+ export const AgentTopologySession = z.object({
8417
+ id: z.string().uuid(),
8418
+ title: z.string().nullable(),
8419
+ titleTruncated: z.boolean(),
8420
+ parentSessionId: z.string().uuid().nullable(),
8421
+ rootSessionId: z.string().uuid(),
8422
+ nestedAgentDepth: NestedAgentDepthValue,
8423
+ ancestorPath: z.array(
8424
+ z.object({
8425
+ id: z.string().uuid(),
8426
+ title: z.string().nullable(),
8427
+ titleTruncated: z.boolean(),
8428
+ }),
8429
+ ),
8430
+ status: SessionStatus,
8431
+ pause: z.object({
8432
+ state: z.enum(["active", "paused"]),
8433
+ additionalBlockerCount: z.number().int().nonnegative(),
8434
+ source: z
8435
+ .object({
8436
+ kind: z.enum(["session", "workspace"]),
8437
+ sessionId: z.string().uuid().optional(),
8438
+ displayName: z.string(),
8439
+ displayNameTruncated: z.boolean(),
8440
+ })
8441
+ .nullable(),
8442
+ }),
8443
+ children: z.object({
8444
+ directChildren: z.number().int().nonnegative(),
8445
+ totalDescendants: z.number().int().nonnegative(),
8446
+ runningDescendants: z.number().int().nonnegative(),
8447
+ queuedDescendants: z.number().int().nonnegative(),
8448
+ attentionDescendants: z.number().int().nonnegative(),
8449
+ pausedDescendants: z.number().int().nonnegative(),
8450
+ failedDescendants: z.number().int().nonnegative(),
8451
+ truncated: z.boolean(),
8452
+ }),
8453
+ createdAt: z.string(),
8454
+ updatedAt: z.string(),
8455
+ });
8456
+ export type AgentTopologySession = z.infer<typeof AgentTopologySession>;
8457
+
8458
+ export const AgentTopologyPageResponse = z.object({
8459
+ sessions: z.array(AgentTopologySession),
8460
+ total: z.number().int().nonnegative(),
8461
+ hasMore: z.boolean(),
8462
+ nextCursor: z.string().nullable(),
8463
+ });
8464
+ export type AgentTopologyPageResponse = z.infer<typeof AgentTopologyPageResponse>;
8465
+
6538
8466
  // Recursive: the TS type is declared first so the schema annotation can carry
6539
8467
  // the FULL recursive shape (a shallow annotation loses type information for
6540
8468
  // contracts consumers after one level of nesting).
@@ -6953,6 +8881,21 @@ export const ToolAuthNeededPayload = z.object({
6953
8881
  selectedResources: McpConnectionResourceScopes.optional(),
6954
8882
  authorizationUrl: z.string().url().optional(),
6955
8883
  subjectId: z.string().min(1).nullable().optional(),
8884
+ // A catalog recommendation is still a tool-level authorization condition:
8885
+ // the agent may describe and request it, but only the authenticated host UI
8886
+ // can start setup. Keeping this nested and optional preserves the established
8887
+ // auth-needed event for ordinary failed MCP calls.
8888
+ capability: z
8889
+ .object({
8890
+ id: z.string().min(1).max(512),
8891
+ name: z.string().min(1).max(256),
8892
+ kind: CapabilityKind,
8893
+ source: CapabilitySource,
8894
+ action: z.enum(["connect", "add_credentials", "enable"]),
8895
+ rationale: z.string().min(1).max(2000),
8896
+ requiredVariables: z.array(VariableSetVariableName).max(64).default([]),
8897
+ })
8898
+ .optional(),
6956
8899
  });
6957
8900
  export type ToolAuthNeededPayload = z.infer<typeof ToolAuthNeededPayload>;
6958
8901
 
@@ -7307,6 +9250,9 @@ export type GitStatusRequest = z.infer<typeof GitStatusRequest>;
7307
9250
  export const GitStatusResponse = z.object({
7308
9251
  isRepo: z.boolean(),
7309
9252
  head: z.string().nullable(), // branch name
9253
+ // Exact commit object identity. null for unborn/non-repositories; optional
9254
+ // only so older adapters and serialized captures remain readable.
9255
+ headOid: z.string().nullable().optional(),
7310
9256
  detached: z.boolean().default(false),
7311
9257
  upstream: z.string().nullable(),
7312
9258
  ahead: z.number().int().nonnegative().default(0),
@@ -7432,6 +9378,9 @@ export type WorkspaceCaptureFile = z.infer<typeof WorkspaceCaptureFile>;
7432
9378
  export const WorkspaceCaptureRepo = z.object({
7433
9379
  root: z.string(),
7434
9380
  head: z.string().nullable(),
9381
+ // Exact HEAD commit object identity. null for unborn repositories; optional
9382
+ // for workspace captures written before commit identity was retained.
9383
+ headOid: z.string().nullable().optional(),
7435
9384
  detached: z.boolean().default(false),
7436
9385
  upstream: z.string().nullable(),
7437
9386
  ahead: z.number().int().nonnegative().default(0),
@@ -9003,27 +10952,45 @@ export function approvalIdentifier(value: unknown): string | null {
9003
10952
  return String(candidate);
9004
10953
  }
9005
10954
 
10955
+ function requireMessageTextOrAnnotations(
10956
+ value: { text: string; annotations: readonly unknown[] },
10957
+ ctx: z.RefinementCtx,
10958
+ ): void {
10959
+ if (value.text.length === 0 && value.annotations.length === 0) {
10960
+ ctx.addIssue({
10961
+ code: z.ZodIssueCode.custom,
10962
+ path: ["text"],
10963
+ message: "message text or annotations are required",
10964
+ });
10965
+ }
10966
+ }
10967
+
10968
+ export const SessionUserMessagePayload = z
10969
+ .object({
10970
+ text: z.string().default(""),
10971
+ annotations: SubmittedTimelineAnnotations.default([]),
10972
+ // System-level host context for this exact turn only. Persisted on the
10973
+ // turn for retry/recovery, never copied into the visible user message.
10974
+ turnInstructions: z.string().trim().min(1).max(32768).optional(),
10975
+ resources: z.array(ResourceRef).default([]),
10976
+ model: z.string().min(1).optional(),
10977
+ reasoningEffort: ReasoningEffort.optional(),
10978
+ latencyMode: LatencyMode.optional(),
10979
+ controlEtag: z.string().min(1).optional(),
10980
+ expectedDraftRevision: z.number().int().nonnegative().optional(),
10981
+ // Header-value rotation only. URL/name/tool settings are immutable after
10982
+ // session create; persisted events expose metadata, never header values.
10983
+ mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
10984
+ })
10985
+ .strict()
10986
+ .superRefine(requireMessageTextOrAnnotations);
10987
+ export type SessionUserMessagePayload = z.infer<typeof SessionUserMessagePayload>;
10988
+
9006
10989
  export const ClientSessionEvent = z.discriminatedUnion("type", [
9007
10990
  z.object({
9008
10991
  type: z.literal("user.message"),
9009
10992
  clientEventId: SessionOperationKey.optional(),
9010
- payload: z
9011
- .object({
9012
- text: z.string().min(1),
9013
- // System-level host context for this exact turn only. Persisted on the
9014
- // turn for retry/recovery, never copied into the visible user message.
9015
- turnInstructions: z.string().trim().min(1).max(32768).optional(),
9016
- resources: z.array(ResourceRef).default([]),
9017
- model: z.string().min(1).optional(),
9018
- reasoningEffort: ReasoningEffort.optional(),
9019
- latencyMode: LatencyMode.optional(),
9020
- controlEtag: z.string().min(1).optional(),
9021
- expectedDraftRevision: z.number().int().nonnegative().optional(),
9022
- // Header-value rotation only. URL/name/tool settings are immutable after
9023
- // session create; persisted events expose metadata, never header values.
9024
- mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
9025
- })
9026
- .strict(),
10993
+ payload: SessionUserMessagePayload,
9027
10994
  }),
9028
10995
  z.object({
9029
10996
  type: z.literal("user.approvalDecision"),
@@ -9047,7 +11014,8 @@ export type ClientSessionEvent = z.infer<typeof ClientSessionEvent>;
9047
11014
 
9048
11015
  export const SteerSessionMessageRequest = z
9049
11016
  .object({
9050
- text: z.string().min(1),
11017
+ text: z.string().default(""),
11018
+ annotations: SubmittedTimelineAnnotations.default([]),
9051
11019
  // Same per-turn system-level context as a queued user.message.
9052
11020
  turnInstructions: z.string().trim().min(1).max(32768).optional(),
9053
11021
  resources: z.array(ResourceRef).default([]),
@@ -9059,7 +11027,8 @@ export const SteerSessionMessageRequest = z
9059
11027
  expectedDraftRevision: z.number().int().nonnegative().optional(),
9060
11028
  mcpCredentialUpdates: z.array(SessionMcpCredentialUpdateInput).optional(),
9061
11029
  })
9062
- .strict();
11030
+ .strict()
11031
+ .superRefine(requireMessageTextOrAnnotations);
9063
11032
  export type SteerSessionMessageRequest = z.infer<typeof SteerSessionMessageRequest>;
9064
11033
 
9065
11034
  export const SteerSessionMessageResponse = z.object({
@@ -9278,19 +11247,21 @@ export type SessionCapabilities = z.infer<typeof SessionCapabilities>;
9278
11247
  // POST .../viewers — acquire a viewer holder. An omitted viewerId mints a fresh
9279
11248
  // one (returned in the response, to carry through heartbeats + detach).
9280
11249
  //
9281
- // `desktop` declares intent to attach the UN-REDACTED pixel plane (noVNC). ONLY
9282
- // that plane carries the consent gate (the un-redacted/shared acknowledgment). A
9283
- // terminal-only warm attach (`desktop:false`, the default) needs NO consent — a
9284
- // shell is interactive by nature and the gate is the scoped tunnel URL + stream
9285
- // token so it warms the box and mints the pty-ws terminal cell WITHOUT a 409.
9286
- // Omitted defaults to `false` so a terminal-only client never trips the gate.
9287
- export const AttachViewerRequest = z.object({
11250
+ // Each optional plane flag declares exactly which live capability is being
11251
+ // acquired. The holder itself is shared liveness; credentials are minted only
11252
+ // for explicitly requested planes. `desktop` alone carries the un-redacted pixel
11253
+ // consent gate, `terminal` carries terminal:attach, and `files` carries
11254
+ // files:write. For compatibility, an entirely omitted plane set retains the old
11255
+ // terminal-only meaning; new clients always send all three flags explicitly.
11256
+ export const AttachViewerRequest = /* @__PURE__ */ z.object({
9288
11257
  viewerId: z.string().uuid().optional(),
9289
11258
  desktop: z.boolean().optional(),
11259
+ terminal: z.boolean().optional(),
11260
+ files: z.boolean().optional(),
9290
11261
  });
9291
11262
  export type AttachViewerRequest = z.infer<typeof AttachViewerRequest>;
9292
11263
 
9293
- export const ViewerHolder = z.object({
11264
+ export const ViewerHolder = /* @__PURE__ */ z.object({
9294
11265
  viewerId: z.string().uuid(),
9295
11266
  sandboxGroupId: z.string().uuid(),
9296
11267
  liveness: z.enum(["cold", "warming", "warm", "draining"]),
@@ -9306,6 +11277,21 @@ export const ViewerHolder = z.object({
9306
11277
  });
9307
11278
  export type ViewerHolder = z.infer<typeof ViewerHolder>;
9308
11279
 
11280
+ /** Exact POST /viewers response. Keep the credential cells in the contracts
11281
+ * package so API and zero-runtime SDK mirrors cannot silently drift. */
11282
+ export const AttachViewerResponse = /* @__PURE__ */ ViewerHolder.extend({
11283
+ streamToken: z.string().nullable(),
11284
+ streamExpiresAt: z.string().nullable(),
11285
+ resolution: z.tuple([z.number().int().positive(), z.number().int().positive()]).nullable(),
11286
+ transport: z.enum(["vnc-ws", "relay-frames"]).nullable(),
11287
+ client: z.enum(["novnc", "frames"]).nullable(),
11288
+ terminalUrl: z.string().nullable(),
11289
+ terminalToken: z.string().nullable(),
11290
+ terminalExpiresAt: z.string().nullable(),
11291
+ terminalTransport: z.literal("pty-ws").nullable(),
11292
+ });
11293
+ export type AttachViewerResponse = z.infer<typeof AttachViewerResponse>;
11294
+
9309
11295
  // POST .../stream-capabilities/acknowledge — record the calling principal's
9310
11296
  // acknowledgment of the un-redacted pixel plane. Reuses the acknowledgment
9311
11297
  // machinery — no new endpoint
@@ -9315,7 +11301,7 @@ export type ViewerHolder = z.infer<typeof ViewerHolder>;
9315
11301
  // session): the un-redacted desktop path returns 409 shared_acknowledgment_required
9316
11302
  // until a shared box is acknowledged WITH the shared-exposure consent. For a
9317
11303
  // solo box `acknowledgeShared` is irrelevant (the un-redacted ack alone gates).
9318
- export const AcknowledgeStreamRequest = z.object({
11304
+ export const AcknowledgeStreamRequest = /* @__PURE__ */ z.object({
9319
11305
  // The principal accepts that the desktop pixel plane is un-redacted (can show
9320
11306
  // cloud creds the agent cat's into a terminal). Always true to record consent;
9321
11307
  // present for self-documentation + a future explicit withdraw.
@@ -9326,7 +11312,7 @@ export const AcknowledgeStreamRequest = z.object({
9326
11312
  });
9327
11313
  export type AcknowledgeStreamRequest = z.infer<typeof AcknowledgeStreamRequest>;
9328
11314
 
9329
- export const AcknowledgeStreamResponse = z.object({
11315
+ export const AcknowledgeStreamResponse = /* @__PURE__ */ z.object({
9330
11316
  acknowledged: z.boolean(),
9331
11317
  acknowledgedShared: z.boolean(),
9332
11318
  });
@@ -9334,12 +11320,12 @@ export type AcknowledgeStreamResponse = z.infer<typeof AcknowledgeStreamResponse
9334
11320
 
9335
11321
  // POST .../viewers/:viewerId/heartbeat — refresh the holder TTL. Epoch-fenced:
9336
11322
  // a stale-epoch beat (a box re-established under a newer epoch) is rejected.
9337
- export const ViewerHeartbeatRequest = z.object({
11323
+ export const ViewerHeartbeatRequest = /* @__PURE__ */ z.object({
9338
11324
  leaseEpoch: z.number().int().nonnegative(),
9339
11325
  });
9340
11326
  export type ViewerHeartbeatRequest = z.infer<typeof ViewerHeartbeatRequest>;
9341
11327
 
9342
- export const ViewerHeartbeatResponse = z.object({
11328
+ export const ViewerHeartbeatResponse = /* @__PURE__ */ z.object({
9343
11329
  // false ⇒ the holder was reaped or the epoch is stale; the client re-attaches.
9344
11330
  alive: z.boolean(),
9345
11331
  });
@@ -9508,10 +11494,23 @@ export const RevokeEnrollmentResponse = z.object({
9508
11494
  lastSeenAt: z.string().datetime({ offset: true }).nullable(),
9509
11495
  revokedAt: z.string().datetime({ offset: true }).nullable(),
9510
11496
  code: z
9511
- .enum(["active_route", "active_commands", "active_lease", "recovery_pending", "not_selfhosted"])
11497
+ .enum([
11498
+ "active_route",
11499
+ "active_commands",
11500
+ "machine_home",
11501
+ "active_lease",
11502
+ "recovery_pending",
11503
+ "not_selfhosted",
11504
+ ])
9512
11505
  .nullable(),
9513
11506
  message: z.string(),
9514
11507
  action: z.string(),
11508
+ dependentSessions: z.array(
11509
+ z.object({
11510
+ id: z.string().uuid(),
11511
+ title: z.string().nullable(),
11512
+ }),
11513
+ ),
9515
11514
  });
9516
11515
  export type RevokeEnrollmentResponse = z.infer<typeof RevokeEnrollmentResponse>;
9517
11516
 
@@ -10173,7 +12172,7 @@ export type WorkspaceModelCatalogResponse = z.infer<typeof WorkspaceModelCatalog
10173
12172
  * that rollout boundary. Mutating clients send this value in
10174
12173
  * `x-opengeni-api-contract`; the API rejects any other value before routing.
10175
12174
  */
10176
- export const OPENGENI_API_CONTRACT_REVISION = "2026-07-workspace-artifacts-v1" as const;
12175
+ export const OPENGENI_API_CONTRACT_REVISION = "2026-08-social-provider-tools-v1" as const;
10177
12176
  export const OPENGENI_API_CONTRACT_HEADER = "x-opengeni-api-contract" as const;
10178
12177
  /** Bounded request/response identifier shared by browser, ingress, and API diagnostics. */
10179
12178
  export const OPENGENI_CORRELATION_HEADER = "x-opengeni-correlation-id" as const;
@@ -10336,6 +12335,8 @@ export function evaluateWorkspaceModelPolicy(
10336
12335
 
10337
12336
  export * from "./codex-fleet-policy";
10338
12337
  export * from "./workspace-instruction-policies";
12338
+ export * from "./company-profile";
12339
+ export * from "./workspace-learning-policy";
10339
12340
  export * from "./workspace-state";
10340
12341
  export * from "./preference-registry";
10341
12342
  export * from "./scoped-knowledge";