@vertesia/common 1.6.0-dev.20260918.090710Z → 1.6.0-dev.20260923.085325Z

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 (133) hide show
  1. package/lib/api-contract/components.generated.json +3562 -2515
  2. package/lib/api-schemas/account.d.ts +5 -0
  3. package/lib/api-schemas/account.d.ts.map +1 -1
  4. package/lib/api-schemas/account.js +7 -0
  5. package/lib/api-schemas/account.js.map +1 -1
  6. package/lib/api-schemas/agent-runs.d.ts +930 -300
  7. package/lib/api-schemas/agent-runs.d.ts.map +1 -1
  8. package/lib/api-schemas/app-lifecycle.d.ts +4 -0
  9. package/lib/api-schemas/app-lifecycle.d.ts.map +1 -1
  10. package/lib/api-schemas/app-lifecycle.js +10 -0
  11. package/lib/api-schemas/app-lifecycle.js.map +1 -1
  12. package/lib/api-schemas/app-runtime.d.ts +1360 -420
  13. package/lib/api-schemas/app-runtime.d.ts.map +1 -1
  14. package/lib/api-schemas/app-runtime.js +14 -0
  15. package/lib/api-schemas/app-runtime.js.map +1 -1
  16. package/lib/api-schemas/apps.d.ts +5 -0
  17. package/lib/api-schemas/apps.d.ts.map +1 -1
  18. package/lib/api-schemas/apps.js +6 -3
  19. package/lib/api-schemas/apps.js.map +1 -1
  20. package/lib/api-schemas/content.d.ts +465 -150
  21. package/lib/api-schemas/content.d.ts.map +1 -1
  22. package/lib/api-schemas/document-processing.d.ts +279 -90
  23. package/lib/api-schemas/document-processing.d.ts.map +1 -1
  24. package/lib/api-schemas/embeddings.d.ts +250 -0
  25. package/lib/api-schemas/embeddings.d.ts.map +1 -1
  26. package/lib/api-schemas/embeddings.js +163 -0
  27. package/lib/api-schemas/embeddings.js.map +1 -1
  28. package/lib/api-schemas/environment.d.ts +2 -2
  29. package/lib/api-schemas/events.d.ts +837 -270
  30. package/lib/api-schemas/events.d.ts.map +1 -1
  31. package/lib/api-schemas/files.d.ts +1 -0
  32. package/lib/api-schemas/files.d.ts.map +1 -1
  33. package/lib/api-schemas/files.js +1 -0
  34. package/lib/api-schemas/files.js.map +1 -1
  35. package/lib/api-schemas/interaction.d.ts +4260 -1290
  36. package/lib/api-schemas/interaction.d.ts.map +1 -1
  37. package/lib/api-schemas/interaction.js +1 -0
  38. package/lib/api-schemas/interaction.js.map +1 -1
  39. package/lib/api-schemas/oauth-server.d.ts +27 -0
  40. package/lib/api-schemas/oauth-server.d.ts.map +1 -1
  41. package/lib/api-schemas/oauth-server.js +32 -0
  42. package/lib/api-schemas/oauth-server.js.map +1 -1
  43. package/lib/api-schemas/process.d.ts +186 -60
  44. package/lib/api-schemas/process.d.ts.map +1 -1
  45. package/lib/api-schemas/project-configuration.d.ts +937 -300
  46. package/lib/api-schemas/project-configuration.d.ts.map +1 -1
  47. package/lib/api-schemas/project-configuration.js +6 -0
  48. package/lib/api-schemas/project-configuration.js.map +1 -1
  49. package/lib/api-schemas/project.d.ts +1416 -450
  50. package/lib/api-schemas/project.d.ts.map +1 -1
  51. package/lib/api-schemas/prompt.d.ts +1 -0
  52. package/lib/api-schemas/prompt.d.ts.map +1 -1
  53. package/lib/api-schemas/prompt.js +1 -0
  54. package/lib/api-schemas/prompt.js.map +1 -1
  55. package/lib/api-schemas/registry.d.ts +12314 -30352
  56. package/lib/api-schemas/registry.d.ts.map +1 -1
  57. package/lib/api-schemas/registry.js +62 -34
  58. package/lib/api-schemas/registry.js.map +1 -1
  59. package/lib/api-schemas/store.d.ts +4650 -1500
  60. package/lib/api-schemas/store.d.ts.map +1 -1
  61. package/lib/api-schemas/sts.d.ts +10 -0
  62. package/lib/api-schemas/sts.d.ts.map +1 -1
  63. package/lib/api-schemas/sts.js +14 -0
  64. package/lib/api-schemas/sts.js.map +1 -1
  65. package/lib/api-schemas/user.d.ts +28 -12
  66. package/lib/api-schemas/user.d.ts.map +1 -1
  67. package/lib/api-schemas/user.js +23 -17
  68. package/lib/api-schemas/user.js.map +1 -1
  69. package/lib/api-schemas/workflow-runs.d.ts +186 -60
  70. package/lib/api-schemas/workflow-runs.d.ts.map +1 -1
  71. package/lib/apps.d.ts +2 -1
  72. package/lib/apps.d.ts.map +1 -1
  73. package/lib/apps.js.map +1 -1
  74. package/lib/embeddings.d.ts +18 -1
  75. package/lib/embeddings.d.ts.map +1 -1
  76. package/lib/index.d.ts +3 -2
  77. package/lib/index.d.ts.map +1 -1
  78. package/lib/index.js +1 -0
  79. package/lib/index.js.map +1 -1
  80. package/lib/oauth-server.d.ts +5 -1
  81. package/lib/oauth-server.d.ts.map +1 -1
  82. package/lib/principal-context.d.ts +21 -12
  83. package/lib/principal-context.d.ts.map +1 -1
  84. package/lib/project.d.ts.map +1 -1
  85. package/lib/project.js +10 -0
  86. package/lib/project.js.map +1 -1
  87. package/lib/store/intake-policy-schema.generated.d.ts.map +1 -1
  88. package/lib/store/intake-policy-schema.generated.js +166 -32
  89. package/lib/store/intake-policy-schema.generated.js.map +1 -1
  90. package/lib/store/rendering.d.ts +1 -0
  91. package/lib/store/rendering.d.ts.map +1 -1
  92. package/lib/store/rendering.js +4 -0
  93. package/lib/store/rendering.js.map +1 -1
  94. package/lib/sts-token-types.d.ts +3 -1
  95. package/lib/sts-token-types.d.ts.map +1 -1
  96. package/lib/user.d.ts +2 -1
  97. package/lib/user.d.ts.map +1 -1
  98. package/lib/user.js.map +1 -1
  99. package/lib/vertesia-common.js +2 -2
  100. package/lib/vertesia-common.js.map +1 -1
  101. package/package.json +6 -6
  102. package/src/api-contract/components.generated.json +3562 -2515
  103. package/src/api-schemas/account.ts +8 -0
  104. package/src/api-schemas/app-lifecycle.ts +11 -0
  105. package/src/api-schemas/app-runtime.ts +15 -0
  106. package/src/api-schemas/apps.ts +6 -3
  107. package/src/api-schemas/embeddings.ts +184 -0
  108. package/src/api-schemas/files.ts +1 -0
  109. package/src/api-schemas/indexing.contract.test.ts +40 -1
  110. package/src/api-schemas/interaction.ts +1 -0
  111. package/src/api-schemas/llumiverse.contract.test.ts +70 -40
  112. package/src/api-schemas/mcp-api-key.contract.test.ts +39 -0
  113. package/src/api-schemas/oauth-server.ts +36 -0
  114. package/src/api-schemas/project-configuration.ts +6 -0
  115. package/src/api-schemas/project.contract.test.ts +15 -0
  116. package/src/api-schemas/prompt.ts +1 -0
  117. package/src/api-schemas/registry-groups.test.ts +9 -1
  118. package/src/api-schemas/registry.ts +136 -32
  119. package/src/api-schemas/store.contract.test.ts +6 -6
  120. package/src/api-schemas/sts.ts +16 -0
  121. package/src/api-schemas/user.contract.test.ts +24 -18
  122. package/src/api-schemas/user.ts +24 -18
  123. package/src/api-schemas/views.contract.test.ts +3 -10
  124. package/src/apps.ts +3 -0
  125. package/src/embeddings.ts +34 -0
  126. package/src/index.ts +10 -2
  127. package/src/oauth-server.ts +11 -0
  128. package/src/principal-context.ts +22 -12
  129. package/src/project.ts +10 -0
  130. package/src/store/intake-policy-schema.generated.ts +166 -32
  131. package/src/store/rendering.ts +9 -0
  132. package/src/sts-token-types.ts +5 -0
  133. package/src/user.ts +8 -1
@@ -2,6 +2,7 @@ import { z } from 'zod';
2
2
  // From the values module, never from `user.ts`: `user.ts` derives its public types from the schemas
3
3
  // below, so importing it here would invert the dependency and make the source of truth circular.
4
4
  import { ACCOUNT_APP_ACCESS_MESSAGE_MAX_LENGTH, AccountType, BillingMethod, QuotaTier } from '../account-values.js';
5
+ import { ApiVersions } from '../versions.js';
5
6
 
6
7
  /**
7
8
  * Runtime API schemas for the Accounts endpoints.
@@ -144,3 +145,10 @@ export type AccountBillingFromSchema = z.infer<typeof AccountBillingSchema>;
144
145
  export type AccountFromSchema = z.infer<typeof AccountSchema>;
145
146
  export type UpdateAccountPayloadFromSchema = z.infer<typeof UpdateAccountPayloadSchema>;
146
147
  export type StripeBillingStatusResponseFromSchema = z.infer<typeof StripeBillingStatusResponseSchema>;
148
+
149
+ /** Account-wide defaults for request API version negotiation. */
150
+ export const AccountApiVersionPolicySchema = z
151
+ .strictObject({
152
+ default_api_version: z.enum(ApiVersions).optional(),
153
+ })
154
+ .meta({ id: 'AccountApiVersionPolicy' });
@@ -40,6 +40,13 @@ export const UpdateAppInstallationToolAllowlistPayloadSchema = z
40
40
  })
41
41
  .meta({ id: 'UpdateAppInstallationToolAllowlistPayload' });
42
42
 
43
+ export const UpdateAppInstallationOAuthApprovalPayloadSchema = z
44
+ .strictObject({ approved_scopes: z.array(z.string().min(1)).max(200) })
45
+ .meta({
46
+ id: 'UpdateAppInstallationOAuthApprovalPayload',
47
+ description: 'Approve OAuth scopes for this project installation. An empty list revokes project approval.',
48
+ });
49
+
43
50
  export const ValidateUrlResponseSchema = z
44
51
  .strictObject({
45
52
  valid: z.boolean(),
@@ -405,6 +412,10 @@ export const StartAppScaffoldRequestSchema = z
405
412
  title: z.string().optional(),
406
413
  description: z.string().optional(),
407
414
  modules: z.array(AppScaffoldModuleSchema).optional(),
415
+ oauth_scopes: z
416
+ .array(z.string())
417
+ .optional()
418
+ .meta({ description: 'App permissions declared in generated source. Defaults to sign-in only.' }),
408
419
  appgen_package_spec: z
409
420
  .string()
410
421
  .regex(APPGEN_PACKAGE_SPEC_PATTERN)
@@ -256,11 +256,18 @@ export const InCodeProcessDefinitionSchema: z.ZodType<InCodeProcessDefinition> =
256
256
  })
257
257
  .meta({ id: 'InCodeProcessDefinition' });
258
258
 
259
+ const appOAuthApprovalSchema = z.strictObject({
260
+ scopes: z.array(z.string()),
261
+ approved_by: z.string(),
262
+ approved_at: z.string(),
263
+ });
264
+
259
265
  export const AppInstallationSchema = z
260
266
  .strictObject({
261
267
  id: z.string(),
262
268
  project: z.string(),
263
269
  manifest: z.string(),
270
+ oauth_approval: appOAuthApprovalSchema.optional(),
264
271
  settings: z.looseObject({}).optional(),
265
272
  tool_allowlist: z
266
273
  .array(z.string())
@@ -331,6 +338,7 @@ export const AppDashboardDefinitionSchema = z
331
338
 
332
339
  export const AppManifestDataSchema = z
333
340
  .strictObject({
341
+ oauth_scopes: z.array(z.string()).optional(),
334
342
  name: z.string().meta({
335
343
  description: 'The name of the app, used as the id in the system. Must be in kebab case (e.g. my-app).',
336
344
  }),
@@ -511,6 +519,7 @@ export const CompositeAppMessageOverridesSchema = z
511
519
 
512
520
  export const AppManifestSchema = z
513
521
  .strictObject({
522
+ oauth_scopes: z.array(z.string()).optional(),
514
523
  edit_revision: EditRevisionSchema,
515
524
  name: z.string().meta({
516
525
  description: 'The name of the app, used as the id in the system. Must be in kebab case (e.g. my-app).',
@@ -630,6 +639,7 @@ export const AppInstallationWithManifestSchema = z
630
639
  .strictObject({
631
640
  id: z.string(),
632
641
  project: z.string(),
642
+ oauth_approval: appOAuthApprovalSchema.optional(),
633
643
  settings: z.looseObject({}).optional(),
634
644
  tool_allowlist: z
635
645
  .array(z.string())
@@ -675,6 +685,7 @@ export const AppInstallationListEntrySchema = z
675
685
  .strictObject({
676
686
  id: z.string(),
677
687
  project: z.string(),
688
+ oauth_approval: appOAuthApprovalSchema.optional(),
678
689
  settings: z.looseObject({}).optional(),
679
690
  tool_allowlist: z
680
691
  .array(z.string())
@@ -911,6 +922,10 @@ export const AppEventSubscriptionDefinitionSchema = z
911
922
 
912
923
  export const AppPackageSchema = z
913
924
  .strictObject({
925
+ oauth_scopes: z
926
+ .array(z.string())
927
+ .meta({ description: 'OAuth scopes requested by the app. Users must consent to project permissions.' })
928
+ .optional(),
914
929
  ui: AppUIConfigSchema.meta({ description: 'The UI configuration of the app' }).optional(),
915
930
  tools: z
916
931
  .array(AgentToolDefinitionSchema)
@@ -113,12 +113,15 @@ export const AppUIConfigSchema = z
113
113
  })
114
114
  .meta({ id: 'AppUIConfig' });
115
115
 
116
- export const ToolCollectionAuthTypeSchema = z.enum(['oauth', 'api_key', 'other']).meta({
116
+ export const ToolCollectionAuthTypeSchema = z.enum(['none', 'oauth', 'api_key', 'other']).meta({
117
117
  id: 'ToolCollectionAuthType',
118
118
  description:
119
- "Authentication type for tool collections.\n- 'oauth': the runtime resolves a per-user or per-project " +
119
+ "Authentication type for tool collections.\n- 'none': connect directly without credentials for MCP collections; " +
120
+ 'does not disable authentication for Vertesia SDK collections\n' +
121
+ "- 'oauth': the runtime resolves a per-user or per-project " +
120
122
  "OAuth access token\n- 'api_key': a static key held in the project's secret store is sent as the RFC 6750 " +
121
- 'bearer token (`Authorization: Bearer <key>`)',
123
+ 'bearer token (`Authorization: Bearer <key>`)\n' +
124
+ "- 'other' or omitted: use the legacy provider connection-details flow for MCP collections",
122
125
  });
123
126
 
124
127
  export const MCPOAuthConfigSchema = z
@@ -102,10 +102,40 @@ export const EmbeddingsApiRequestSchema = z
102
102
  })
103
103
  .meta({ id: 'EmbeddingsApiRequest' });
104
104
 
105
+ export const EmbeddingBatchRunStateSchema = z.enum([
106
+ 'preparing',
107
+ 'submitted',
108
+ 'running',
109
+ 'applying',
110
+ 'completed',
111
+ 'completed_with_errors',
112
+ 'cancelled',
113
+ 'stale',
114
+ 'failed',
115
+ ]);
116
+
117
+ export const EmbeddingBatchRunSummarySchema = z
118
+ .strictObject({
119
+ id: z.string(),
120
+ state: EmbeddingBatchRunStateSchema,
121
+ model: z.string(),
122
+ created_at: z.string().meta({ format: 'date-time' }),
123
+ completed_at: z.string().meta({ format: 'date-time' }).optional(),
124
+ applied: z.number().int().nonnegative(),
125
+ skipped: z.number().int().nonnegative(),
126
+ failed: z.number().int().nonnegative(),
127
+ stale: z.number().int().nonnegative(),
128
+ })
129
+ .meta({
130
+ id: 'EmbeddingBatchRunSummary',
131
+ description: 'Latest batch run for this embedding type, without provider payloads or input content.',
132
+ });
133
+
105
134
  export const EmbeddingsStatusResponseSchema = z
106
135
  .strictObject({
107
136
  status: z.string(),
108
137
  embeddingRunsInProgress: z.number().optional(),
138
+ latestBatchRun: EmbeddingBatchRunSummarySchema.optional(),
109
139
  totalIndexableObjects: z.number().optional(),
110
140
  embeddingsModels: z.array(z.string()).optional(),
111
141
  objectsWithEmbeddings: z.number().optional(),
@@ -117,6 +147,25 @@ export const EmbeddingsStatusResponseSchema = z
117
147
  })
118
148
  .meta({ id: 'EmbeddingsStatusResponse' });
119
149
 
150
+ export const RecalculateEmbeddingsQuerySchema = z
151
+ .strictObject({
152
+ mode: z
153
+ .literal('sync')
154
+ .meta({
155
+ description:
156
+ 'Force synchronous per-object recalculation. When omitted, batch inference is used when supported.',
157
+ })
158
+ .optional(),
159
+ force: z
160
+ .boolean()
161
+ .meta({
162
+ description:
163
+ 'Recalculate all eligible objects, including current embeddings. Token limits still apply; existing renditions are reused.',
164
+ })
165
+ .optional(),
166
+ })
167
+ .meta({ id: 'RecalculateEmbeddingsQuery' });
168
+
120
169
  export const ProjectConfigurationEmbeddingEnablePayloadSchema = z
121
170
  .strictObject({
122
171
  environment: z.string(),
@@ -124,3 +173,138 @@ export const ProjectConfigurationEmbeddingEnablePayloadSchema = z
124
173
  model: z.string().optional(),
125
174
  })
126
175
  .meta({ id: 'ProjectConfigurationEmbeddingEnablePayload' });
176
+
177
+ export const EmbeddingBatchProviderStateSchema = z.enum([
178
+ 'pending',
179
+ 'running',
180
+ 'succeeded',
181
+ 'failed',
182
+ 'cancelled',
183
+ 'paused',
184
+ ]);
185
+
186
+ export const EmbeddingBatchCapabilityRequestSchema = z
187
+ .strictObject({ embedding_type: SupportedEmbeddingTypesSchema })
188
+ .meta({ id: 'EmbeddingBatchCapabilityRequest' });
189
+
190
+ export const EmbeddingBatchCapabilityResponseSchema = z
191
+ .strictObject({
192
+ eligible: z.boolean(),
193
+ reason: z.string().optional(),
194
+ environment: z.string().optional(),
195
+ provider: z.string().optional(),
196
+ model: z.string().optional(),
197
+ dimensions: z.number().int().positive().optional(),
198
+ max_tokens: z.number().int().positive().optional(),
199
+ location: z.string().optional(),
200
+ input_format: z.string().optional(),
201
+ max_rows: z.number().int().positive().optional(),
202
+ artifact_uri: z.string().optional(),
203
+ })
204
+ .meta({ id: 'EmbeddingBatchCapabilityResponse' });
205
+
206
+ export const EmbeddingBatchCreateRequestSchema = z
207
+ .strictObject({
208
+ embedding_type: SupportedEmbeddingTypesSchema,
209
+ model: z.string(),
210
+ dimensions: z.number().int().positive(),
211
+ display_name: z.string(),
212
+ input_uri: z.string(),
213
+ output_uri: z.string(),
214
+ })
215
+ .meta({ id: 'EmbeddingBatchCreateRequest' });
216
+
217
+ export const EmbeddingBatchJobRequestSchema = z
218
+ .strictObject({
219
+ embedding_type: SupportedEmbeddingTypesSchema,
220
+ model: z.string(),
221
+ name: z.string(),
222
+ include_output_artifacts: z.boolean().optional().meta({
223
+ description:
224
+ 'On get, resolve terminal result artifacts for application. Omit for lightweight status polling.',
225
+ }),
226
+ })
227
+ .meta({ id: 'EmbeddingBatchJobRequest' });
228
+
229
+ export const EmbeddingBatchJobResponseSchema = z
230
+ .strictObject({
231
+ name: z.string(),
232
+ display_name: z.string().optional(),
233
+ state: EmbeddingBatchProviderStateSchema,
234
+ model: z.string().optional(),
235
+ input_uri: z.string().optional(),
236
+ output_uri: z.string().optional(),
237
+ output_artifacts: z.array(z.string()).optional().meta({
238
+ description:
239
+ 'Terminal job result artifacts in application storage, including partial results. Never provider file IDs.',
240
+ }),
241
+ error_message: z.string().optional(),
242
+ })
243
+ .meta({ id: 'EmbeddingBatchJobResponse' });
244
+
245
+ export const EmbeddingBatchPrepareRequestSchema = z
246
+ .strictObject({
247
+ run_id: z.string(),
248
+ embedding_type: SupportedEmbeddingTypesSchema,
249
+ capability: EmbeddingBatchCapabilityResponseSchema,
250
+ })
251
+ .meta({ id: 'EmbeddingBatchPrepareRequest' });
252
+
253
+ export const EmbeddingBatchSubjobSchema = z.strictObject({
254
+ index: z.number().int().nonnegative(),
255
+ display_name: z.string(),
256
+ input_uri: z.string(),
257
+ output_uri: z.string(),
258
+ row_count: z.number().int().nonnegative(),
259
+ provider_name: z.string().optional(),
260
+ state: EmbeddingBatchProviderStateSchema.optional(),
261
+ });
262
+
263
+ export const EmbeddingBatchPrepareResponseSchema = z
264
+ .strictObject({
265
+ run_id: z.string(),
266
+ row_count: z.number().int().nonnegative(),
267
+ subjobs: z.array(EmbeddingBatchSubjobSchema),
268
+ })
269
+ .meta({ id: 'EmbeddingBatchPrepareResponse' });
270
+
271
+ export const EmbeddingBatchRenditionPageRequestSchema = z
272
+ .strictObject({ run_id: z.string() })
273
+ .meta({ id: 'EmbeddingBatchRenditionPageRequest' });
274
+
275
+ export const EmbeddingBatchRenditionPageResponseSchema = z
276
+ .strictObject({
277
+ status: z.enum(['running', 'page_completed', 'completed']),
278
+ page_index: z.number().int().nonnegative(),
279
+ page_scanned: z.number().int().nonnegative(),
280
+ page_ready: z.number().int().nonnegative(),
281
+ page_generated: z.number().int().nonnegative(),
282
+ page_failed: z.number().int().nonnegative(),
283
+ running: z.number().int().nonnegative(),
284
+ })
285
+ .meta({ id: 'EmbeddingBatchRenditionPageResponse' });
286
+
287
+ export const EmbeddingBatchUpdateRequestSchema = z
288
+ .strictObject({
289
+ run_id: z.string(),
290
+ state: EmbeddingBatchRunStateSchema,
291
+ subjobs: z.array(EmbeddingBatchSubjobSchema).optional(),
292
+ error_code: z.string().optional(),
293
+ error_message: z.string().optional(),
294
+ })
295
+ .meta({ id: 'EmbeddingBatchUpdateRequest' });
296
+
297
+ export const EmbeddingBatchApplyRequestSchema = z
298
+ .strictObject({ run_id: z.string() })
299
+ .meta({ id: 'EmbeddingBatchApplyRequest' });
300
+
301
+ export const EmbeddingBatchApplyResponseSchema = z
302
+ .strictObject({
303
+ state: EmbeddingBatchRunStateSchema,
304
+ succeeded: z.number().int().nonnegative(),
305
+ failed: z.number().int().nonnegative(),
306
+ stale: z.number().int().nonnegative(),
307
+ applied: z.number().int().nonnegative(),
308
+ failure_counts: z.record(z.string(), z.number().int().nonnegative()).optional(),
309
+ })
310
+ .meta({ id: 'EmbeddingBatchApplyResponse' });
@@ -74,6 +74,7 @@ export const BulkUploadUrlsPayloadSchema = z
74
74
  export const FileBucketResponseSchema = z
75
75
  .strictObject({
76
76
  bucket: z.string(),
77
+ location: z.string().optional(),
77
78
  })
78
79
  .meta({ id: 'FileBucketResponse' });
79
80
 
@@ -1,5 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
  import type { GenericCommandResponse } from '../common.js';
3
+ import type { RecalculateEmbeddingsQuery } from '../embeddings.js';
3
4
  import type {
4
5
  DriftAnalysisStatusResponse,
5
6
  EmbeddingsStatusResponse,
@@ -11,7 +12,11 @@ import type {
11
12
  } from '../project.js';
12
13
  import { WorkflowExecutionStatus } from '../store/workflow.js';
13
14
  import type { GenericCommandResponseSchema } from './commands.js';
14
- import type { EmbeddingsStatusResponseSchema, ProjectConfigurationEmbeddingEnablePayloadSchema } from './embeddings.js';
15
+ import type {
16
+ EmbeddingsStatusResponseSchema,
17
+ ProjectConfigurationEmbeddingEnablePayloadSchema,
18
+ RecalculateEmbeddingsQuerySchema,
19
+ } from './embeddings.js';
15
20
  import type {
16
21
  DriftAnalysisStatusResponseSchema,
17
22
  IndexingStatusResponseSchema,
@@ -28,6 +33,7 @@ describe('indexing and embedding API contracts', () => {
28
33
  it('derives every public type from its domain schema', () => {
29
34
  assertType<Equals<GenericCommandResponse, typeof GenericCommandResponseSchema._output>>(true);
30
35
  assertType<Equals<EmbeddingsStatusResponse, typeof EmbeddingsStatusResponseSchema._output>>(true);
36
+ assertType<Equals<RecalculateEmbeddingsQuery, typeof RecalculateEmbeddingsQuerySchema._output>>(true);
31
37
  assertType<Equals<IndexingStatusResponse, typeof IndexingStatusResponseSchema._output>>(true);
32
38
  assertType<Equals<DriftAnalysisStatusResponse, typeof DriftAnalysisStatusResponseSchema._output>>(true);
33
39
  assertType<
@@ -51,6 +57,39 @@ describe('indexing and embedding API contracts', () => {
51
57
  );
52
58
  });
53
59
 
60
+ it('allows only the explicit synchronous embedding recalculation override', () => {
61
+ expect(validateApiRequest('RecalculateEmbeddingsQuery', {}).valid).toBe(true);
62
+ expect(validateApiRequest('RecalculateEmbeddingsQuery', { mode: 'sync' }).valid).toBe(true);
63
+ expect(validateApiRequest('RecalculateEmbeddingsQuery', { force: true }).valid).toBe(true);
64
+ expect(validateApiRequest('RecalculateEmbeddingsQuery', { mode: 'sync', force: true }).valid).toBe(true);
65
+ expect(validateApiRequest('RecalculateEmbeddingsQuery', { force_renditions: true }).valid).toBe(false);
66
+ expect(validateApiRequest('RecalculateEmbeddingsQuery', { mode: 'batch' }).valid).toBe(false);
67
+ });
68
+
69
+ it('validates the optional batch summary without exposing stored run fields', () => {
70
+ const summary = {
71
+ id: 'run-1',
72
+ state: 'completed_with_errors',
73
+ model: 'model-1',
74
+ created_at: '2026-01-01T00:00:00Z',
75
+ applied: 110,
76
+ skipped: 17,
77
+ failed: 0,
78
+ stale: 0,
79
+ };
80
+ expect(
81
+ validateApiResponse('EmbeddingsStatusResponse', {
82
+ status: 'success',
83
+ vectorIndex: { status: 'READY' },
84
+ latestBatchRun: summary,
85
+ }).valid,
86
+ ).toBe(true);
87
+ expect(validateApiResponse('EmbeddingBatchRunSummary', { ...summary, applied: -1 }).valid).toBe(false);
88
+ expect(validateApiResponse('EmbeddingBatchRunSummary', { ...summary, prefix_uri: 'private' }).valid).toBe(
89
+ false,
90
+ );
91
+ });
92
+
54
93
  it('keeps drift workflow status numeric and nullable identifiers explicit', () => {
55
94
  expect(
56
95
  validateApiResponse('DriftAnalysisStatusResponse', {
@@ -488,6 +488,7 @@ export const InteractionPublishPayloadSchema = z
488
488
 
489
489
  export const InteractionForkPayloadSchema = z
490
490
  .strictObject({
491
+ newName: z.string().optional(),
491
492
  keepTags: z.boolean().optional(),
492
493
  forkPrompts: z.boolean().optional(),
493
494
  targetProject: z.string().optional(),
@@ -1,4 +1,5 @@
1
1
  import type { JSONSchema, ModelOptions } from '@llumiverse/common';
2
+ import { ModelOptionsSchema } from '@llumiverse/common/schemas';
2
3
  import { Ajv2020 } from 'ajv/dist/2020.js';
3
4
  import { describe, expect, it } from 'vitest';
4
5
  import type { JsonObject } from './adapter.js';
@@ -19,36 +20,12 @@ function compile(name: string) {
19
20
  return ajv.compile({ $ref: `vertesia://openapi${apiComponentRef(name as never)}` });
20
21
  }
21
22
 
22
- const UNION_MEMBERS = [
23
- 'TextFallbackOptions',
24
- 'AzureFoundryChatOptions',
25
- 'ImagenOptions',
26
- 'VertexAIClaudeOptions',
27
- 'VertexAIGeminiOptions',
28
- 'VertexAIGeminiOmniVideoOptions',
29
- 'VertexAIGrokOptions',
30
- 'NovaCanvasOptions',
31
- 'BedrockConverseOptions',
32
- 'BedrockNovaOptions',
33
- 'BedrockMistralOptions',
34
- 'BedrockAI21Options',
35
- 'BedrockCohereCommandOptions',
36
- 'BedrockClaudeOptions',
37
- 'BedrockPalmyraOptions',
38
- 'BedrockGptOssOptions',
39
- 'TwelvelabsPegasusOptions',
40
- 'BedrockMantleResponsesOptions',
41
- 'BedrockMantleChatCompletionsOptions',
42
- 'BedrockMantleClaudeOptions',
43
- 'OpenAiThinkingOptions',
44
- 'OpenAiTextOptions',
45
- 'OpenRouterTextOptions',
46
- 'OpenAiDalleOptions',
47
- 'OpenAiGptImageOptions',
48
- 'XAIGrokImageOptions',
49
- 'GroqOptions',
50
- 'MistralTextOptions',
51
- ];
23
+ // Follow the canonical union; do not maintain a second provider membership list here.
24
+ const UNION_MEMBERS = ModelOptionsSchema.options.map((schema) => {
25
+ const id = schema.meta()?.id;
26
+ if (!id) throw new Error('Model option schemas must declare a component id');
27
+ return id;
28
+ });
52
29
 
53
30
  describe('the ModelOptions closure is published whole and enforced closed', () => {
54
31
  it('hoists every union member and enum into its own component', () => {
@@ -60,18 +37,29 @@ describe('the ModelOptions closure is published whole and enforced closed', () =
60
37
  }
61
38
  });
62
39
 
63
- it('publishes a discriminator whose mapping covers every member', () => {
64
- const union = ApiSchemaComponents.ModelOptions as JsonObject & {
65
- oneOf: { $ref: string }[];
66
- discriminator: { propertyName: string; mapping: Record<string, string> };
67
- };
68
- expect(union.discriminator.propertyName).toBe('_option_id');
69
- expect(union.oneOf.map((member) => member.$ref)).toEqual(
40
+ it('publishes every optional-ID family as anyOf, without a required discriminator', () => {
41
+ const union = ApiSchemaComponents.ModelOptions as JsonObject & { anyOf: { $ref: string }[] };
42
+ expect(union.discriminator).toBeUndefined();
43
+ expect(union.oneOf).toBeUndefined();
44
+ expect(union.required ?? []).not.toContain('_option_id');
45
+ expect(union.anyOf.map((member) => member.$ref)).toEqual(
70
46
  UNION_MEMBERS.map((name) => `#/components/schemas/${name}`),
71
47
  );
72
- // A mapping short of the `oneOf` is the failure that matters: a generated Java or Go client
73
- // reads the mapping to pick the concrete subtype and falls back to a loose map without it.
74
- expect(new Set(Object.values(union.discriminator.mapping))).toEqual(new Set(union.oneOf.map((m) => m.$ref)));
48
+ for (const name of UNION_MEMBERS) {
49
+ expect((ApiSchemaComponents[name] as JsonObject).required ?? [], name).not.toContain('_option_id');
50
+ }
51
+ });
52
+
53
+ it.each([
54
+ {},
55
+ { temperature: 0.2, max_tokens: 1024 },
56
+ { cache_enabled: true, cache_ttl: '1h', thinking_budget_tokens: 1024 },
57
+ { extra_body: { provider_extension: true } },
58
+ ] satisfies ModelOptions[])('accepts untagged options through the run request contract: %j', (model_options) => {
59
+ const payload = { interaction: 'Chat', config: { model: 'claude-sonnet-4-6', model_options } };
60
+ expect(validateApiRequest('RunCreatePayload', payload).valid).toBe(true);
61
+ expect(payload.config.model_options).not.toHaveProperty('_option_id');
62
+ expect(compile('ModelOptions')(model_options)).toBe(true);
75
63
  });
76
64
 
77
65
  it('enforces the closure it documents — an undeclared option is rejected, not ignored', () => {
@@ -106,6 +94,48 @@ describe('the ModelOptions closure is published whole and enforced closed', () =
106
94
  expect(validate({ _option_id: 'openai-text', extra_body: ['not-an-object'] })).toBe(false);
107
95
  });
108
96
 
97
+ it('accepts Anthropic options through the run request contract', () => {
98
+ const payload = {
99
+ interaction: 'Chat',
100
+ config: {
101
+ model: 'claude-sonnet-4-6',
102
+ model_options: {
103
+ _option_id: 'anthropic-claude',
104
+ effort: 'high',
105
+ cache_enabled: true,
106
+ cache_ttl: '1h',
107
+ },
108
+ },
109
+ };
110
+ expect(validateApiRequest('RunCreatePayload', payload).valid).toBe(true);
111
+ expect(
112
+ validateApiRequest('RunCreatePayload', {
113
+ ...payload,
114
+ config: { ...payload.config, model_options: { ...payload.config.model_options, cache_ttl: '2h' } },
115
+ }).valid,
116
+ ).toBe(false);
117
+ });
118
+
119
+ it.each([
120
+ { _option_id: 'bedrock-nova', top_k: 12 },
121
+ { _option_id: 'bedrock-mistral', top_k: 12 },
122
+ { _option_id: 'bedrock-ai21', presence_penalty: 0.4, frequency_penalty: 0.2 },
123
+ { _option_id: 'bedrock-cohere-command', top_k: 12, presence_penalty: 0.4, frequency_penalty: 0.2 },
124
+ { _option_id: 'bedrock-mantle-responses', effort: 'max', reasoning_effort: 'max' },
125
+ { _option_id: 'vertexai-imagen', person_generation: 'allow_adult', mask_class: [0, 42] },
126
+ { _option_id: 'vertexai-imagen', person_generation: 'allow_adults' },
127
+ { _option_id: 'bedrock-nova-canvas', taskType: 'OUTPAINTING', outPaintingMode: 'DEFAULT' },
128
+ ] satisfies ModelOptions[])('accepts restored provider options: %j', (model_options) => {
129
+ const payload = { interaction: 'Chat', config: { model: 'model', model_options } };
130
+ expect(validateApiRequest('RunCreatePayload', payload).valid).toBe(true);
131
+ expect(
132
+ validateApiRequest('RunCreatePayload', {
133
+ ...payload,
134
+ config: { ...payload.config, model_options: { ...model_options, unknown_option: true } },
135
+ }).valid,
136
+ ).toBe(false);
137
+ });
138
+
109
139
  it('accepts Gemini Omni task and resolution options through the run request contract', () => {
110
140
  const result = validateApiRequest('RunCreatePayload', {
111
141
  interaction: 'GenerateVideo',
@@ -84,3 +84,42 @@ describe('McpApiKeyStatus', () => {
84
84
  );
85
85
  });
86
86
  });
87
+
88
+ describe('MCP anonymous authentication — emitted contract', () => {
89
+ const collection = {
90
+ type: 'mcp',
91
+ id: 'public',
92
+ name: 'Public tools',
93
+ description: 'Public tools',
94
+ namespace: 'public',
95
+ url: 'https://example.com/mcp',
96
+ };
97
+
98
+ it.each(['none', 'oauth', 'api_key', 'other', undefined])('accepts auth=%s', (auth) => {
99
+ expect(
100
+ validateApiRequest('AppManifestData', {
101
+ name: 'public-mcp',
102
+ title: 'Public MCP',
103
+ description: 'Public tools',
104
+ publisher: 'Vertesia',
105
+ status: 'beta',
106
+ visibility: 'private',
107
+ tool_collections: [{ ...collection, auth }],
108
+ }).valid,
109
+ ).toBe(true);
110
+ });
111
+
112
+ it('rejects unknown authentication modes', () => {
113
+ expect(
114
+ validateApiRequest('AppManifestData', {
115
+ name: 'public-mcp',
116
+ title: 'Public MCP',
117
+ description: 'Public tools',
118
+ publisher: 'Vertesia',
119
+ status: 'beta',
120
+ visibility: 'private',
121
+ tool_collections: [{ ...collection, auth: 'anonymous' }],
122
+ }).valid,
123
+ ).toBe(false);
124
+ });
125
+ });
@@ -83,6 +83,7 @@ const oauthAuthorizeQueryFields = {
83
83
  state: z.string().optional(),
84
84
  code_challenge: z.string(),
85
85
  code_challenge_method: z.literal('S256'),
86
+ account_id: z.string().optional(),
86
87
  project_id: z.string().optional(),
87
88
  };
88
89
 
@@ -92,9 +93,21 @@ export const CreateOAuthAuthorizationRequestPayloadSchema = z
92
93
  .strictObject(oauthAuthorizeQueryFields)
93
94
  .meta({ id: 'CreateOAuthAuthorizationRequestPayload' });
94
95
 
96
+ export const OAuthAuthorizationRequestGeneratedAppSchema = z
97
+ .strictObject({
98
+ tenant_id: z.string(),
99
+ app_name: z.string(),
100
+ version_id: z.string().optional(),
101
+ })
102
+ .meta({ id: 'OAuthAuthorizationRequestGeneratedApp' });
103
+
95
104
  export const OAuthAuthorizationRequestSchema = z
96
105
  .strictObject({
97
106
  request_id: z.string(),
107
+ user_code: z.string().optional().meta({
108
+ description:
109
+ 'User-visible device code to compare with the terminal before approving. Never the secret device_code.',
110
+ }),
98
111
  client_id: z.string(),
99
112
  client_name: z.string(),
100
113
  client_metadata: OAuthClientDisplayMetadataSchema.optional(),
@@ -104,7 +117,9 @@ export const OAuthAuthorizationRequestSchema = z
104
117
  resource: z.string().optional(),
105
118
  requested_scopes: z.array(z.string()),
106
119
  optional_scopes: z.array(z.string()).optional(),
120
+ requested_account_id: z.string().optional(),
107
121
  requested_project_id: z.string().optional(),
122
+ generated_app: OAuthAuthorizationRequestGeneratedAppSchema.optional(),
108
123
  project_binding_mode: OAuthProjectBindingModeSchema,
109
124
  fixed_project_id: z.string().optional(),
110
125
  restrict_to_owner_account: z.boolean().optional().meta({
@@ -370,3 +385,24 @@ export const OAuthGrantRevokeResponseSchema = z
370
385
  revoked_consents: z.number(),
371
386
  })
372
387
  .meta({ id: 'OAuthGrantRevokeResponse' });
388
+
389
+ export const OAuthLoginPayloadSchema = z
390
+ .strictObject({
391
+ id_token: z.string().min(1),
392
+ account_id: z.string().optional(),
393
+ project_id: z.string().optional(),
394
+ })
395
+ .meta({ id: 'OAuthLoginPayload' });
396
+ export const OAuthLoginDecisionResponseSchema = z
397
+ .strictObject({
398
+ redirect_url: z.string().optional(),
399
+ consent_url: z.string().optional(),
400
+ })
401
+ .meta({ id: 'OAuthLoginDecisionResponse' });
402
+
403
+ export const OAuthLoginUserNotFoundResponseSchema = z
404
+ .strictObject({
405
+ error: z.literal('user_not_found'),
406
+ ensure_user_url: z.string(),
407
+ })
408
+ .meta({ id: 'OAuthLoginUserNotFoundResponse' });
@@ -460,6 +460,12 @@ export const ProjectConfigurationSchema = z
460
460
  "'de'). Determines which Elasticsearch analyzer is used for the text field. Defaults to 'en' " +
461
461
  '(English/standard analyzer).\n\nChanging this value requires a full reindex to take effect.',
462
462
  }),
463
+ oauth_clients: z
464
+ .strictObject({
465
+ external_clients: z.enum(['allow_all', 'allowlist']).optional(),
466
+ allowed_origins: z.array(z.string()).optional(),
467
+ })
468
+ .optional(),
463
469
  browser_use: BrowserUseProjectConfigurationSchema.optional().meta({
464
470
  description: 'Project defaults and caps for browser_use agent workstreams.',
465
471
  }),