@vertesia/common 1.6.0-dev.20260918.115658Z → 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 (107) hide show
  1. package/lib/api-contract/components.generated.json +3085 -2649
  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 +1342 -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/content.d.ts +465 -150
  17. package/lib/api-schemas/content.d.ts.map +1 -1
  18. package/lib/api-schemas/document-processing.d.ts +279 -90
  19. package/lib/api-schemas/document-processing.d.ts.map +1 -1
  20. package/lib/api-schemas/environment.d.ts +2 -2
  21. package/lib/api-schemas/events.d.ts +837 -270
  22. package/lib/api-schemas/events.d.ts.map +1 -1
  23. package/lib/api-schemas/interaction.d.ts +4260 -1290
  24. package/lib/api-schemas/interaction.d.ts.map +1 -1
  25. package/lib/api-schemas/interaction.js +1 -0
  26. package/lib/api-schemas/interaction.js.map +1 -1
  27. package/lib/api-schemas/oauth-server.d.ts +27 -0
  28. package/lib/api-schemas/oauth-server.d.ts.map +1 -1
  29. package/lib/api-schemas/oauth-server.js +32 -0
  30. package/lib/api-schemas/oauth-server.js.map +1 -1
  31. package/lib/api-schemas/process.d.ts +186 -60
  32. package/lib/api-schemas/process.d.ts.map +1 -1
  33. package/lib/api-schemas/project-configuration.d.ts +937 -300
  34. package/lib/api-schemas/project-configuration.d.ts.map +1 -1
  35. package/lib/api-schemas/project-configuration.js +6 -0
  36. package/lib/api-schemas/project-configuration.js.map +1 -1
  37. package/lib/api-schemas/project.d.ts +1416 -450
  38. package/lib/api-schemas/project.d.ts.map +1 -1
  39. package/lib/api-schemas/prompt.d.ts +1 -0
  40. package/lib/api-schemas/prompt.d.ts.map +1 -1
  41. package/lib/api-schemas/prompt.js +1 -0
  42. package/lib/api-schemas/prompt.js.map +1 -1
  43. package/lib/api-schemas/registry.d.ts +12043 -30352
  44. package/lib/api-schemas/registry.d.ts.map +1 -1
  45. package/lib/api-schemas/registry.js +42 -33
  46. package/lib/api-schemas/registry.js.map +1 -1
  47. package/lib/api-schemas/store.d.ts +4650 -1500
  48. package/lib/api-schemas/store.d.ts.map +1 -1
  49. package/lib/api-schemas/sts.d.ts +10 -0
  50. package/lib/api-schemas/sts.d.ts.map +1 -1
  51. package/lib/api-schemas/sts.js +14 -0
  52. package/lib/api-schemas/sts.js.map +1 -1
  53. package/lib/api-schemas/user.d.ts +28 -12
  54. package/lib/api-schemas/user.d.ts.map +1 -1
  55. package/lib/api-schemas/user.js +23 -17
  56. package/lib/api-schemas/user.js.map +1 -1
  57. package/lib/api-schemas/workflow-runs.d.ts +186 -60
  58. package/lib/api-schemas/workflow-runs.d.ts.map +1 -1
  59. package/lib/apps.d.ts +2 -1
  60. package/lib/apps.d.ts.map +1 -1
  61. package/lib/apps.js.map +1 -1
  62. package/lib/index.d.ts +2 -2
  63. package/lib/index.d.ts.map +1 -1
  64. package/lib/index.js.map +1 -1
  65. package/lib/oauth-server.d.ts +5 -1
  66. package/lib/oauth-server.d.ts.map +1 -1
  67. package/lib/principal-context.d.ts +21 -12
  68. package/lib/principal-context.d.ts.map +1 -1
  69. package/lib/project.d.ts.map +1 -1
  70. package/lib/project.js +10 -0
  71. package/lib/project.js.map +1 -1
  72. package/lib/store/intake-policy-schema.generated.d.ts.map +1 -1
  73. package/lib/store/intake-policy-schema.generated.js +166 -32
  74. package/lib/store/intake-policy-schema.generated.js.map +1 -1
  75. package/lib/sts-token-types.d.ts +3 -1
  76. package/lib/sts-token-types.d.ts.map +1 -1
  77. package/lib/user.d.ts +2 -1
  78. package/lib/user.d.ts.map +1 -1
  79. package/lib/user.js.map +1 -1
  80. package/lib/vertesia-common.js +2 -2
  81. package/lib/vertesia-common.js.map +1 -1
  82. package/package.json +6 -6
  83. package/src/api-contract/components.generated.json +3085 -2649
  84. package/src/api-schemas/account.ts +8 -0
  85. package/src/api-schemas/app-lifecycle.ts +11 -0
  86. package/src/api-schemas/app-runtime.ts +15 -0
  87. package/src/api-schemas/interaction.ts +1 -0
  88. package/src/api-schemas/llumiverse.contract.test.ts +70 -40
  89. package/src/api-schemas/oauth-server.ts +36 -0
  90. package/src/api-schemas/project-configuration.ts +6 -0
  91. package/src/api-schemas/project.contract.test.ts +15 -0
  92. package/src/api-schemas/prompt.ts +1 -0
  93. package/src/api-schemas/registry-groups.test.ts +9 -1
  94. package/src/api-schemas/registry.ts +100 -32
  95. package/src/api-schemas/store.contract.test.ts +6 -6
  96. package/src/api-schemas/sts.ts +16 -0
  97. package/src/api-schemas/user.contract.test.ts +24 -18
  98. package/src/api-schemas/user.ts +24 -18
  99. package/src/api-schemas/views.contract.test.ts +3 -10
  100. package/src/apps.ts +3 -0
  101. package/src/index.ts +9 -2
  102. package/src/oauth-server.ts +11 -0
  103. package/src/principal-context.ts +22 -12
  104. package/src/project.ts +10 -0
  105. package/src/store/intake-policy-schema.generated.ts +166 -32
  106. package/src/sts-token-types.ts +5 -0
  107. 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)
@@ -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',
@@ -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
  }),
@@ -242,6 +242,21 @@ describe('gate 2 — the closure is closed, bottom-up', () => {
242
242
  expect(SYSTEM_INTERACTION_CATEGORIES.ContentSearchReranker).toBe(SystemInteractionCategory.analysis);
243
243
  });
244
244
 
245
+ it('uses the agent model default for every app development agent', () => {
246
+ // Each is launched in-code without an environment or model of its own, so an uncategorised
247
+ // one silently resolves to the project BASE default instead of the agent default.
248
+ for (const endpoint of [
249
+ 'AppDevelopmentOrchestrator',
250
+ 'AppSolutionArchitect',
251
+ 'AppDesigner',
252
+ 'AppDeveloper',
253
+ 'AppReviewer',
254
+ 'AppTester',
255
+ ]) {
256
+ expect(SYSTEM_INTERACTION_CATEGORIES[endpoint]).toBe(SystemInteractionCategory.agent);
257
+ }
258
+ });
259
+
245
260
  it('publishes the property-mapping map without the propertyNames z.record adds', () => {
246
261
  // `Record<string, ProjectSearchPropertyMapping>` is inline in the interface and has no
247
262
  // TypeScript name, so it never becomes a canonical alias — it stays canonical AND derived,
@@ -34,6 +34,7 @@ export const PromptTemplateInteractionVersionSchema = z
34
34
 
35
35
  export const PromptTemplateForkPayloadSchema = z
36
36
  .strictObject({
37
+ newName: z.string().optional(),
37
38
  keepTags: z.boolean().optional(),
38
39
  targetProject: z.string().optional(),
39
40
  })
@@ -1,5 +1,6 @@
1
- import { describe, expect, it } from 'vitest';
1
+ import { describe, expect, expectTypeOf, it } from 'vitest';
2
2
  import { z } from 'zod';
3
+ import type { NamedInteractionExecutionPayloadSchema } from './interaction.js';
3
4
  import { type ApiComponentName, type ApiComponentType, ApiSchemaComponents, mergeComponentGroups } from './registry.js';
4
5
 
5
6
  /**
@@ -30,6 +31,13 @@ type ResolvedName<N extends ApiComponentName> = [ApiComponentType<N>] extends [n
30
31
  * merge actually refuses, which no import of a correct registry can show.
31
32
  */
32
33
  describe('mergeComponentGroups', () => {
34
+ it('preserves execution payload types and rejects unregistered component names', () => {
35
+ expectTypeOf<ApiComponentType<'NamedInteractionExecutionPayload'>>().toEqualTypeOf<
36
+ z.infer<typeof NamedInteractionExecutionPayloadSchema>
37
+ >();
38
+ expectTypeOf<'UnregisteredExecutionComponent'>().not.toMatchTypeOf<ApiComponentName>();
39
+ });
40
+
33
41
  const A = z.strictObject({ a: z.string() });
34
42
  const B = z.strictObject({ b: z.number() });
35
43
 
@@ -77,7 +77,12 @@ import {
77
77
  RoleDefinitionArraySchema,
78
78
  SystemRoleDefinitionArraySchema,
79
79
  } from './access-control.js';
80
- import { AccountSchema, StripeBillingStatusResponseSchema, UpdateAccountPayloadSchema } from './account.js';
80
+ import {
81
+ AccountApiVersionPolicySchema,
82
+ AccountSchema,
83
+ StripeBillingStatusResponseSchema,
84
+ UpdateAccountPayloadSchema,
85
+ } from './account.js';
81
86
  import { type JsonObject, toOpenApiComponents } from './adapter.js';
82
87
  import * as AgentCommunicationSchemas from './agent-communication.js';
83
88
  import * as AgentRunSchemas from './agent-runs.js';
@@ -175,6 +180,7 @@ import {
175
180
  StartAppScaffoldResponseSchema,
176
181
  StoredTypeRefSchema,
177
182
  SystemPackageQuerySchema,
183
+ UpdateAppInstallationOAuthApprovalPayloadSchema,
178
184
  UpdateAppInstallationToolAllowlistPayloadSchema,
179
185
  UpsertAppVersionRequestSchema,
180
186
  ValidateUrlRequestSchema,
@@ -630,6 +636,7 @@ import {
630
636
  CreateOAuthClientPayloadSchema,
631
637
  ListOAuthGrantsQuerySchema,
632
638
  OAuthAuthorizationDecisionResponseSchema,
639
+ OAuthAuthorizationRequestGeneratedAppSchema,
633
640
  OAuthAuthorizationRequestSchema,
634
641
  OAuthAuthorizationRequestStatusSchema,
635
642
  OAuthAuthorizationServerMetadataSchema,
@@ -652,6 +659,9 @@ import {
652
659
  OAuthGrantSortOrderSchema,
653
660
  OAuthGrantStatusSchema,
654
661
  OAuthGrantTypeSchema,
662
+ OAuthLoginDecisionResponseSchema,
663
+ OAuthLoginPayloadSchema,
664
+ OAuthLoginUserNotFoundResponseSchema,
655
665
  OAuthProjectBindingModeSchema,
656
666
  OAuthRegistrationSourceSchema,
657
667
  OAuthResponseTypeSchema,
@@ -833,6 +843,7 @@ import * as WorkflowRunSchemas from './workflow-runs.js';
833
843
  * group approaches the proven-safe size.
834
844
  */
835
845
  const IAM_AND_ACCOUNT_SCHEMAS = {
846
+ AccountApiVersionPolicy: AccountApiVersionPolicySchema,
836
847
  Account: AccountSchema,
837
848
  UpdateAccountPayload: UpdateAccountPayloadSchema,
838
849
  StripeBillingStatusResponse: StripeBillingStatusResponseSchema,
@@ -975,6 +986,10 @@ const OAUTH_SCHEMAS = {
975
986
  OAuthAuthorizeQuery: OAuthAuthorizeQuerySchema,
976
987
  CreateOAuthAuthorizationRequestPayload: CreateOAuthAuthorizationRequestPayloadSchema,
977
988
  OAuthAuthorizationRequest: OAuthAuthorizationRequestSchema,
989
+ OAuthAuthorizationRequestGeneratedApp: OAuthAuthorizationRequestGeneratedAppSchema,
990
+ OAuthLoginPayload: OAuthLoginPayloadSchema,
991
+ OAuthLoginUserNotFoundResponse: OAuthLoginUserNotFoundResponseSchema,
992
+ OAuthLoginDecisionResponse: OAuthLoginDecisionResponseSchema,
978
993
  ApproveOAuthAuthorizationRequestPayload: ApproveOAuthAuthorizationRequestPayloadSchema,
979
994
  OAuthGrantableScopesResponse: OAuthGrantableScopesResponseSchema,
980
995
  OAuthAuthorizationDecisionResponse: OAuthAuthorizationDecisionResponseSchema,
@@ -1216,7 +1231,55 @@ const AGENT_CONVERSATION_SCHEMAS = {
1216
1231
  ConversationState: ConversationStateSchema,
1217
1232
  } as const satisfies Record<string, z.ZodType>;
1218
1233
 
1219
- const EXECUTION_RUN_SCHEMAS = {
1234
+ // Reference schema types by name to keep declaration output bounded without erasing payload types.
1235
+ type ExecutionRunSchemaMap = {
1236
+ ExecutionRunStatus: typeof ExecutionRunStatusSchema;
1237
+ RunSourceTypes: typeof RunSourceTypesSchema;
1238
+ RunSource: typeof RunSourceSchema;
1239
+ ExecutionRunDocRef: typeof ExecutionRunDocRefSchema;
1240
+ ExecutionRunWorkflow: typeof ExecutionRunWorkflowSchema;
1241
+ ExecutionRunInteraction: typeof ExecutionRunInteractionSchema;
1242
+ ExecutionRun: typeof ExecutionRunSchema;
1243
+ ExecutionRunRef: typeof ExecutionRunRefSchema;
1244
+ ExecutionRunRefArray: typeof ExecutionRunRefArraySchema;
1245
+ UpdateExecutionRunPayload: typeof UpdateExecutionRunPayloadSchema;
1246
+ RunCreatePayload: typeof RunCreatePayloadSchema;
1247
+ SortOrder: typeof SortOrderSchema;
1248
+ SortOption: typeof SortOptionSchema;
1249
+ RunSearchQuery: typeof RunSearchQuerySchema;
1250
+ RunListQuery: typeof RunListQuerySchema;
1251
+ RunSearchPayload: typeof RunSearchPayloadSchema;
1252
+ InteractionExecutionPayload: typeof InteractionExecutionPayloadSchema;
1253
+ NamedInteractionExecutionPayload: typeof NamedInteractionExecutionPayloadSchema;
1254
+ InteractionExecutionResult: typeof InteractionExecutionResultSchema;
1255
+ FindRunResult: typeof FindRunResultSchema;
1256
+ FindRunResultArray: typeof FindRunResultArraySchema;
1257
+ PopulatedExecutionRunResult: typeof PopulatedExecutionRunResultSchema;
1258
+ LegacyExecutionRunResult: typeof LegacyExecutionRunResultSchema;
1259
+ LegacyPopulatedExecutionRunResult: typeof LegacyPopulatedExecutionRunResultSchema;
1260
+ InteractionExecutionConfiguration: typeof InteractionExecutionConfigurationSchema;
1261
+ InteractionExecutionError: typeof InteractionExecutionErrorSchema;
1262
+ ResultStorageOptions: typeof ResultStorageOptionsSchema;
1263
+ ExecuteInteractionByEndpointQuery: typeof ExecuteInteractionByEndpointQuerySchema;
1264
+ ExecuteInteractionByEndpointHeaders: typeof ExecuteInteractionByEndpointHeadersSchema;
1265
+ AsyncCompletionMode: typeof AsyncCompletionModeSchema;
1266
+ AsyncCompletionOptions: typeof AsyncCompletionOptionsSchema;
1267
+ AsyncExecutionPayload: typeof AsyncExecutionPayloadSchema;
1268
+ AsyncInteractionExecutionPayload: typeof AsyncInteractionExecutionPayloadSchema;
1269
+ AsyncConversationExecutionPayload: typeof AsyncConversationExecutionPayloadSchema;
1270
+ AsyncExecutionResult: typeof AsyncExecutionResultSchema;
1271
+ RateLimitRequestPayload: typeof RateLimitRequestPayloadSchema;
1272
+ RateLimitRequestResponse: typeof RateLimitRequestResponseSchema;
1273
+ ComputeRunFacetPayload: typeof ComputeRunFacetPayloadSchema;
1274
+ ComputeRunFacetsResponse: typeof ComputeRunFacetsResponseSchema;
1275
+ RunSearchMetaResponse: typeof RunSearchMetaResponseSchema;
1276
+ ToolResultsPayload: typeof ToolResultsPayloadSchema;
1277
+ UserMessagePayload: typeof UserMessagePayloadSchema;
1278
+ ExecutionResponse: typeof ExecutionResponseSchema;
1279
+ RunClonePayload: typeof RunClonePayloadSchema;
1280
+ };
1281
+
1282
+ const EXECUTION_RUN_SCHEMAS: ExecutionRunSchemaMap = {
1220
1283
  // A run: what was executed, by whom, and how it ended.
1221
1284
  ExecutionRunStatus: ExecutionRunStatusSchema,
1222
1285
  RunSourceTypes: RunSourceTypesSchema,
@@ -2083,6 +2146,7 @@ const VIEW_EXPERIENCE_SCHEMAS = {
2083
2146
  const APP_LIFECYCLE_SCHEMAS = {
2084
2147
  // What an app does once it exists: versions, builds, scaffolds, git repositories,
2085
2148
  // development tasks, installations and inspection.
2149
+ UpdateAppInstallationOAuthApprovalPayload: UpdateAppInstallationOAuthApprovalPayloadSchema,
2086
2150
  UpdateAppInstallationToolAllowlistPayload: UpdateAppInstallationToolAllowlistPayloadSchema,
2087
2151
  ValidateUrlResponse: ValidateUrlResponseSchema,
2088
2152
  ValidateUrlRequest: ValidateUrlRequestSchema,
@@ -2280,6 +2344,8 @@ const STS_SCHEMAS = {
2280
2344
  EnvironmentTokenRequest: StsSchemas.EnvironmentTokenRequestSchema,
2281
2345
  AgentTokenRequest: StsSchemas.AgentTokenRequestSchema,
2282
2346
  ServiceAccountTokenRequest: StsSchemas.ServiceAccountTokenRequestSchema,
2347
+ AppSessionTokenRequest: StsSchemas.AppSessionTokenRequestSchema,
2348
+ AppSessionTokenResponse: StsSchemas.AppSessionTokenResponseSchema,
2283
2349
  IssueTokenRequest: StsSchemas.IssueTokenRequestSchema,
2284
2350
  IssueTokenResponse: StsSchemas.IssueTokenResponseSchema,
2285
2351
  IssueTokenForbiddenResponse: StsSchemas.IssueTokenForbiddenResponseSchema,
@@ -2500,6 +2566,8 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
2500
2566
  'EnvironmentTokenRequest',
2501
2567
  'AgentTokenRequest',
2502
2568
  'ServiceAccountTokenRequest',
2569
+ 'AppSessionTokenRequest',
2570
+ 'AppSessionTokenResponse',
2503
2571
  'IssueTokenResponse',
2504
2572
  'IssueTokenForbiddenResponse',
2505
2573
  'IssueTokenUnavailableResponse',
@@ -2515,7 +2583,7 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
2515
2583
  'QuotaStandingWindow',
2516
2584
  'QuotaStandingAdmissionClass',
2517
2585
  'QuotaTierResponse',
2518
- // The IAM closure. PrincipalContext is composed into PrincipalIdentity rather than hoisted,
2586
+ // The IAM closure. AbacPrincipalContext is composed into PrincipalIdentity rather than hoisted,
2519
2587
  // so it has no component of its own to list.
2520
2588
  'User',
2521
2589
  'UpdateUserPayload',
@@ -2638,34 +2706,12 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
2638
2706
  //
2639
2707
  // `JSONSchema` is deliberately absent: it is OPEN by design and by long-standing publication —
2640
2708
  // a JSON Schema carries keywords the type never enumerated. `JSONSchemaProperties` is a map.
2641
- 'TextFallbackOptions',
2642
- 'AzureFoundryChatOptions',
2643
- 'ImagenOptions',
2644
- 'VertexAIClaudeOptions',
2645
- 'VertexAIGeminiOptions',
2646
- 'VertexAIGeminiOmniVideoOptions',
2647
- 'VertexAIGrokOptions',
2648
- 'NovaCanvasOptions',
2649
- 'BedrockConverseOptions',
2650
- 'BedrockNovaOptions',
2651
- 'BedrockMistralOptions',
2652
- 'BedrockAI21Options',
2653
- 'BedrockCohereCommandOptions',
2654
- 'BedrockClaudeOptions',
2655
- 'BedrockPalmyraOptions',
2656
- 'BedrockGptOssOptions',
2657
- 'TwelvelabsPegasusOptions',
2658
- 'BedrockMantleResponsesOptions',
2659
- 'BedrockMantleChatCompletionsOptions',
2660
- 'BedrockMantleClaudeOptions',
2661
- 'OpenAiThinkingOptions',
2662
- 'OpenAiTextOptions',
2663
- 'OpenRouterTextOptions',
2664
- 'OpenAiDalleOptions',
2665
- 'OpenAiGptImageOptions',
2666
- 'XAIGrokImageOptions',
2667
- 'GroqOptions',
2668
- 'MistralTextOptions',
2709
+ // Derive membership so new provider schemas inherit this enforcement check automatically.
2710
+ ...ModelOptionsSchema.options.map((schema) => {
2711
+ const id = schema.meta()?.id;
2712
+ if (!id) throw new Error('Model option schemas must declare a component id');
2713
+ return id;
2714
+ }),
2669
2715
  // The app-manifest leaves. Every object among them is published closed today, the nested `git`
2670
2716
  // block included, and it is spelled `strictObject` so the emission carries it directly. The five
2671
2717
  // enums take no `additionalProperties` at all.
@@ -3076,6 +3122,10 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
3076
3122
  'OAuthAuthorizeQuery',
3077
3123
  'CreateOAuthAuthorizationRequestPayload',
3078
3124
  'OAuthAuthorizationRequest',
3125
+ 'OAuthAuthorizationRequestGeneratedApp',
3126
+ 'OAuthLoginPayload',
3127
+ 'OAuthLoginUserNotFoundResponse',
3128
+ 'OAuthLoginDecisionResponse',
3079
3129
  'ApproveOAuthAuthorizationRequestPayload',
3080
3130
  'OAuthGrantableScopesResponse',
3081
3131
  'OAuthAuthorizationDecisionResponse',
@@ -3316,6 +3366,7 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
3316
3366
  'AuditTrailQuery',
3317
3367
  'ViewExperienceListQuery',
3318
3368
  'UpdateAppInstallationToolAllowlistPayload',
3369
+ 'UpdateAppInstallationOAuthApprovalPayload',
3319
3370
  'ValidateUrlResponse',
3320
3371
  'ValidateUrlRequest',
3321
3372
  'AppVersionUrls',
@@ -3474,8 +3525,25 @@ const STRICT_COMPONENTS: ReadonlySet<string> = new Set<string>([
3474
3525
  * divergence. Note that `.refine()` is silently DROPPED rather than rejected, so refinements must
3475
3526
  * not be used to express contract rules — they would be invisible to both the spec and AJV.
3476
3527
  */
3528
+ function emitSchema(name: string, schema: z.ZodType): unknown {
3529
+ const emitted = emitJsonSchema(schema) as Record<string, unknown>;
3530
+ const rootRef = emitted.$ref;
3531
+ const defs = emitted.$defs;
3532
+ const expectedRef = `#/$defs/${name}`;
3533
+ if (rootRef !== expectedRef || !defs || typeof defs !== 'object' || Array.isArray(defs)) return emitted;
3534
+
3535
+ const root = (defs as Record<string, unknown>)[name];
3536
+ if (!root || typeof root !== 'object' || Array.isArray(root)) return emitted;
3537
+ const remainingDefs = Object.fromEntries(
3538
+ Object.entries(defs as Record<string, unknown>).filter(([id]) => id !== name),
3539
+ );
3540
+ return Object.keys(remainingDefs).length === 0
3541
+ ? root
3542
+ : { ...(root as Record<string, unknown>), $defs: remainingDefs };
3543
+ }
3544
+
3477
3545
  function emitRawSchemas(): Record<string, unknown> {
3478
- return Object.fromEntries(Object.entries(API_SCHEMAS).map(([name, schema]) => [name, emitJsonSchema(schema)]));
3546
+ return Object.fromEntries(Object.entries(API_SCHEMAS).map(([name, schema]) => [name, emitSchema(name, schema)]));
3479
3547
  }
3480
3548
 
3481
3549
  /**
@@ -263,8 +263,8 @@ describe('runtime tightenings — recorded as operation 25 of the 1.5 runbook',
263
263
 
264
264
  it('validates model_options against the union instead of accepting any object', () => {
265
265
  // Same class: `model_options` was `{type: object, additionalProperties: true}` in the
266
- // hand-written schema and `$ref: ModelOptions` in the published component. It now has to name
267
- // a driver through `_option_id`, which is the discriminator generated clients already use.
266
+ // hand-written schema and `$ref: ModelOptions` in the published component. The family hint
267
+ // is optional, but known field types and supplied IDs remain validated.
268
268
  expect(ApiSchemaComponents.ContentTypeIntakePolicy).toBeDefined();
269
269
  expect(
270
270
  validate({
@@ -272,11 +272,11 @@ describe('runtime tightenings — recorded as operation 25 of the 1.5 runbook',
272
272
  }),
273
273
  errors(),
274
274
  ).toBe(true);
275
- expect(validate({ extraction: { config: { model_options: { temperature: 0.5 } } } })).toBe(false);
275
+ expect(validate({ extraction: { config: { model_options: { temperature: 0.5 } } } })).toBe(true);
276
276
  expect(validate({ extraction: { config: { model_options: { _option_id: 'not-a-driver' } } } })).toBe(false);
277
- // The empty object is rejected for the same reason, which is why nothing may PUT it on the
278
- // wire — see `normalizeModelOptions`, which drops an options bag with no options in it.
279
- expect(validate({ extraction: { config: { model_options: {} } } })).toBe(false);
277
+ expect(validate({ extraction: { config: { model_options: {} } } })).toBe(true);
278
+ expect(validate({ extraction: { config: { model_options: { temperature: 'hot' } } } })).toBe(false);
279
+ expect(validate({ extraction: { config: { model_options: { unknown_option: true } } } })).toBe(false);
280
280
  });
281
281
 
282
282
  it('constrains the two config enums that were unconstrained strings', () => {