@vertesia/common 1.6.0-dev.20260923.085325Z → 1.6.0-dev.20261008.064737Z
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/access-control-values.d.ts +2 -2
- package/lib/access-control-values.d.ts.map +1 -1
- package/lib/access-control-values.js +2 -2
- package/lib/access-control-values.js.map +1 -1
- package/lib/access-control.d.ts +7 -8
- package/lib/access-control.d.ts.map +1 -1
- package/lib/access-control.js +5 -0
- package/lib/access-control.js.map +1 -1
- package/lib/analytics.d.ts +6 -7
- package/lib/analytics.d.ts.map +1 -1
- package/lib/api-contract/components.generated.json +2553 -1046
- package/lib/api-contract/engine.d.ts +65 -0
- package/lib/api-contract/engine.d.ts.map +1 -0
- package/lib/api-contract/engine.js +569 -0
- package/lib/api-contract/engine.js.map +1 -0
- package/lib/api-contract/index.d.ts +21 -182
- package/lib/api-contract/index.d.ts.map +1 -1
- package/lib/api-contract/index.js +13 -551
- package/lib/api-contract/index.js.map +1 -1
- package/lib/api-schemas/access-control.d.ts +33 -10
- package/lib/api-schemas/access-control.d.ts.map +1 -1
- package/lib/api-schemas/access-control.js +7 -6
- package/lib/api-schemas/access-control.js.map +1 -1
- package/lib/api-schemas/account.d.ts +5 -9
- package/lib/api-schemas/account.d.ts.map +1 -1
- package/lib/api-schemas/account.js +0 -7
- package/lib/api-schemas/account.js.map +1 -1
- package/lib/api-schemas/agent-budget.d.ts +15 -0
- package/lib/api-schemas/agent-budget.d.ts.map +1 -0
- package/lib/api-schemas/agent-budget.js +55 -0
- package/lib/api-schemas/agent-budget.js.map +1 -0
- package/lib/api-schemas/agent-runs.d.ts +1525 -100
- package/lib/api-schemas/agent-runs.d.ts.map +1 -1
- package/lib/api-schemas/agent-runs.js +60 -28
- package/lib/api-schemas/agent-runs.js.map +1 -1
- package/lib/api-schemas/apikey.d.ts +11 -10
- package/lib/api-schemas/apikey.d.ts.map +1 -1
- package/lib/api-schemas/apikey.js.map +1 -1
- package/lib/api-schemas/app-lifecycle.d.ts +13 -0
- package/lib/api-schemas/app-lifecycle.d.ts.map +1 -1
- package/lib/api-schemas/app-lifecycle.js +4 -0
- package/lib/api-schemas/app-lifecycle.js.map +1 -1
- package/lib/api-schemas/app-runtime.d.ts +1821 -108
- package/lib/api-schemas/app-runtime.d.ts.map +1 -1
- package/lib/api-schemas/audit-trail.d.ts +275 -0
- package/lib/api-schemas/audit-trail.d.ts.map +1 -1
- package/lib/api-schemas/audit-trail.js +156 -1
- package/lib/api-schemas/audit-trail.js.map +1 -1
- package/lib/api-schemas/content.d.ts +665 -30
- package/lib/api-schemas/content.d.ts.map +1 -1
- package/lib/api-schemas/content.js +47 -0
- package/lib/api-schemas/content.js.map +1 -1
- package/lib/api-schemas/cost-analytics.d.ts +19 -0
- package/lib/api-schemas/cost-analytics.d.ts.map +1 -1
- package/lib/api-schemas/cost-analytics.js +38 -2
- package/lib/api-schemas/cost-analytics.js.map +1 -1
- package/lib/api-schemas/document-processing.d.ts +381 -18
- package/lib/api-schemas/document-processing.d.ts.map +1 -1
- package/lib/api-schemas/environment.d.ts +0 -5
- package/lib/api-schemas/environment.d.ts.map +1 -1
- package/lib/api-schemas/environment.js +0 -1
- package/lib/api-schemas/environment.js.map +1 -1
- package/lib/api-schemas/events.d.ts +1143 -54
- package/lib/api-schemas/events.d.ts.map +1 -1
- package/lib/api-schemas/group.d.ts +2 -1
- package/lib/api-schemas/group.d.ts.map +1 -1
- package/lib/api-schemas/group.js.map +1 -1
- package/lib/api-schemas/index.d.ts +2 -0
- package/lib/api-schemas/index.d.ts.map +1 -1
- package/lib/api-schemas/index.js +2 -0
- package/lib/api-schemas/index.js.map +1 -1
- package/lib/api-schemas/inference-profile.d.ts +5017 -0
- package/lib/api-schemas/inference-profile.d.ts.map +1 -0
- package/lib/api-schemas/inference-profile.js +135 -0
- package/lib/api-schemas/inference-profile.js.map +1 -0
- package/lib/api-schemas/integrations.d.ts +6 -6
- package/lib/api-schemas/interaction.d.ts +34391 -703
- package/lib/api-schemas/interaction.d.ts.map +1 -1
- package/lib/api-schemas/interaction.js +34 -1
- package/lib/api-schemas/interaction.js.map +1 -1
- package/lib/api-schemas/invites.d.ts +10 -9
- package/lib/api-schemas/invites.d.ts.map +1 -1
- package/lib/api-schemas/invites.js.map +1 -1
- package/lib/api-schemas/process.d.ts +653 -34
- package/lib/api-schemas/process.d.ts.map +1 -1
- package/lib/api-schemas/process.js +66 -0
- package/lib/api-schemas/process.js.map +1 -1
- package/lib/api-schemas/project-configuration.d.ts +1323 -62
- package/lib/api-schemas/project-configuration.d.ts.map +1 -1
- package/lib/api-schemas/project-configuration.js +15 -1
- package/lib/api-schemas/project-configuration.js.map +1 -1
- package/lib/api-schemas/project.d.ts +2031 -116
- package/lib/api-schemas/project.d.ts.map +1 -1
- package/lib/api-schemas/project.js +9 -1
- package/lib/api-schemas/project.js.map +1 -1
- package/lib/api-schemas/quota.d.ts +7 -6
- package/lib/api-schemas/quota.d.ts.map +1 -1
- package/lib/api-schemas/quota.js.map +1 -1
- package/lib/api-schemas/registry.d.ts +28171 -36096
- package/lib/api-schemas/registry.d.ts.map +1 -1
- package/lib/api-schemas/registry.js +77 -30
- package/lib/api-schemas/registry.js.map +1 -1
- package/lib/api-schemas/run-budget.d.ts +16 -0
- package/lib/api-schemas/run-budget.d.ts.map +1 -0
- package/lib/api-schemas/run-budget.js +22 -0
- package/lib/api-schemas/run-budget.js.map +1 -0
- package/lib/api-schemas/secrets.d.ts +0 -71
- package/lib/api-schemas/secrets.d.ts.map +1 -1
- package/lib/api-schemas/secrets.js +0 -73
- package/lib/api-schemas/secrets.js.map +1 -1
- package/lib/api-schemas/store.d.ts +6388 -338
- package/lib/api-schemas/store.d.ts.map +1 -1
- package/lib/api-schemas/store.js +11 -0
- package/lib/api-schemas/store.js.map +1 -1
- package/lib/api-schemas/user.d.ts +9 -8
- package/lib/api-schemas/user.d.ts.map +1 -1
- package/lib/api-schemas/user.js.map +1 -1
- package/lib/api-schemas/view-execution.d.ts +8 -0
- package/lib/api-schemas/view-execution.d.ts.map +1 -1
- package/lib/api-schemas/views.d.ts +14 -0
- package/lib/api-schemas/views.d.ts.map +1 -1
- package/lib/api-schemas/workflow-runs.d.ts +335 -12
- package/lib/api-schemas/workflow-runs.d.ts.map +1 -1
- package/lib/api-schemas/workflow-runs.js +2 -0
- package/lib/api-schemas/workflow-runs.js.map +1 -1
- package/lib/apikey.d.ts +30 -25
- package/lib/apikey.d.ts.map +1 -1
- package/lib/apikey.js.map +1 -1
- package/lib/apps.d.ts +116 -121
- package/lib/apps.d.ts.map +1 -1
- package/lib/apps.js.map +1 -1
- package/lib/audit-trail.d.ts +30 -19
- package/lib/audit-trail.d.ts.map +1 -1
- package/lib/audit-trail.js +6 -0
- package/lib/audit-trail.js.map +1 -1
- package/lib/browser-credentials.d.ts +11 -12
- package/lib/browser-credentials.d.ts.map +1 -1
- package/lib/common.d.ts +17 -24
- package/lib/common.d.ts.map +1 -1
- package/lib/content-query.d.ts +3 -4
- package/lib/content-query.d.ts.map +1 -1
- package/lib/cost-analytics.d.ts +13 -21
- package/lib/cost-analytics.d.ts.map +1 -1
- package/lib/cost-analytics.js +0 -7
- package/lib/cost-analytics.js.map +1 -1
- package/lib/data-platform.d.ts +79 -88
- package/lib/data-platform.d.ts.map +1 -1
- package/lib/data-platform.js.map +1 -1
- package/lib/delegation.d.ts +4 -5
- package/lib/delegation.d.ts.map +1 -1
- package/lib/email.d.ts +15 -17
- package/lib/email.d.ts.map +1 -1
- package/lib/email.js.map +1 -1
- package/lib/embeddings.d.ts +25 -26
- package/lib/embeddings.d.ts.map +1 -1
- package/lib/environment.d.ts +16 -17
- package/lib/environment.d.ts.map +1 -1
- package/lib/environment.js.map +1 -1
- package/lib/facets.d.ts +3 -4
- package/lib/facets.d.ts.map +1 -1
- package/lib/group.d.ts +6 -7
- package/lib/group.d.ts.map +1 -1
- package/lib/group.js.map +1 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/inference-profile.d.ts +17 -0
- package/lib/inference-profile.d.ts.map +1 -0
- package/lib/inference-profile.js +2 -0
- package/lib/inference-profile.js.map +1 -0
- package/lib/integrations.d.ts +19 -20
- package/lib/integrations.d.ts.map +1 -1
- package/lib/integrations.js.map +1 -1
- package/lib/interaction.d.ts +68 -73
- package/lib/interaction.d.ts.map +1 -1
- package/lib/interaction.js.map +1 -1
- package/lib/meters.d.ts +4 -5
- package/lib/meters.d.ts.map +1 -1
- package/lib/oauth-server.d.ts +40 -41
- package/lib/oauth-server.d.ts.map +1 -1
- package/lib/oauth.d.ts +9 -10
- package/lib/oauth.d.ts.map +1 -1
- package/lib/payload.d.ts +11 -14
- package/lib/payload.d.ts.map +1 -1
- package/lib/pending-asks.d.ts +8 -13
- package/lib/pending-asks.d.ts.map +1 -1
- package/lib/pending-asks.js +0 -4
- package/lib/pending-asks.js.map +1 -1
- package/lib/platform-event.d.ts +48 -71
- package/lib/platform-event.d.ts.map +1 -1
- package/lib/platform-event.js.map +1 -1
- package/lib/principal-context.d.ts +3 -3
- package/lib/principal-context.d.ts.map +1 -1
- package/lib/project.d.ts +42 -43
- package/lib/project.d.ts.map +1 -1
- package/lib/project.js.map +1 -1
- package/lib/prompt.d.ts +14 -16
- package/lib/prompt.d.ts.map +1 -1
- package/lib/prompt.js.map +1 -1
- package/lib/query.d.ts +10 -13
- package/lib/query.d.ts.map +1 -1
- package/lib/rate-limiter.d.ts +7 -11
- package/lib/rate-limiter.d.ts.map +1 -1
- package/lib/refs.d.ts +2 -3
- package/lib/refs.d.ts.map +1 -1
- package/lib/refs.js.map +1 -1
- package/lib/roles/types.d.ts +5 -6
- package/lib/roles/types.d.ts.map +1 -1
- package/lib/roles/types.js.map +1 -1
- package/lib/run-budget.d.ts +4 -0
- package/lib/run-budget.d.ts.map +1 -0
- package/lib/run-budget.js +2 -0
- package/lib/run-budget.js.map +1 -0
- package/lib/runs.d.ts +9 -10
- package/lib/runs.d.ts.map +1 -1
- package/lib/secrets.d.ts +10 -21
- package/lib/secrets.d.ts.map +1 -1
- package/lib/store/agent-approval.d.ts +4 -5
- package/lib/store/agent-approval.d.ts.map +1 -1
- package/lib/store/agent-approval.js.map +1 -1
- package/lib/store/agent-run.d.ts +50 -52
- package/lib/store/agent-run.d.ts.map +1 -1
- package/lib/store/agent-run.js.map +1 -1
- package/lib/store/collections.d.ts +11 -12
- package/lib/store/collections.d.ts.map +1 -1
- package/lib/store/collections.js.map +1 -1
- package/lib/store/conversation-state.d.ts +14 -8
- package/lib/store/conversation-state.d.ts.map +1 -1
- package/lib/store/doc-analyzer.d.ts +7 -8
- package/lib/store/doc-analyzer.d.ts.map +1 -1
- package/lib/store/dsl-workflow.d.ts +10 -12
- package/lib/store/dsl-workflow.d.ts.map +1 -1
- package/lib/store/dsl-workflow.js.map +1 -1
- package/lib/store/duration.d.ts +12 -0
- package/lib/store/duration.d.ts.map +1 -0
- package/lib/store/duration.js +2 -0
- package/lib/store/duration.js.map +1 -0
- package/lib/store/grounded-extraction.d.ts +6 -7
- package/lib/store/grounded-extraction.d.ts.map +1 -1
- package/lib/store/intake-policy-schema.generated.d.ts.map +1 -1
- package/lib/store/intake-policy-schema.generated.js +143 -2
- package/lib/store/intake-policy-schema.generated.js.map +1 -1
- package/lib/store/process.d.ts +70 -69
- package/lib/store/process.d.ts.map +1 -1
- package/lib/store/process.js.map +1 -1
- package/lib/store/rendering.d.ts +6 -12
- package/lib/store/rendering.d.ts.map +1 -1
- package/lib/store/rendering.js +0 -5
- package/lib/store/rendering.js.map +1 -1
- package/lib/store/signals.d.ts +43 -0
- package/lib/store/signals.d.ts.map +1 -1
- package/lib/store/signals.js +6 -1
- package/lib/store/signals.js.map +1 -1
- package/lib/store/store.d.ts +92 -91
- package/lib/store/store.d.ts.map +1 -1
- package/lib/store/store.js.map +1 -1
- package/lib/store/task.d.ts +10 -14
- package/lib/store/task.d.ts.map +1 -1
- package/lib/store/workflow.d.ts +35 -41
- package/lib/store/workflow.d.ts.map +1 -1
- package/lib/store/workflow.js.map +1 -1
- package/lib/sts-token-types.d.ts +14 -19
- package/lib/sts-token-types.d.ts.map +1 -1
- package/lib/tools.d.ts +12 -13
- package/lib/tools.d.ts.map +1 -1
- package/lib/transient-tokens.d.ts +3 -3
- package/lib/transient-tokens.d.ts.map +1 -1
- package/lib/user.d.ts +16 -20
- package/lib/user.d.ts.map +1 -1
- package/lib/user.js.map +1 -1
- package/lib/vertesia-common.js +2 -2
- package/lib/vertesia-common.js.map +1 -1
- package/lib/views.d.ts +61 -64
- package/lib/views.d.ts.map +1 -1
- package/lib/views.js.map +1 -1
- package/lib/wire-types.generated.d.ts +11227 -0
- package/lib/wire-types.generated.d.ts.map +1 -0
- package/lib/wire-types.generated.js +4 -0
- package/lib/wire-types.generated.js.map +1 -0
- package/lib/workflow-analytics.d.ts +21 -19
- package/lib/workflow-analytics.d.ts.map +1 -1
- package/lib/workflow-analytics.js +2 -2
- package/lib/workflow-analytics.js.map +1 -1
- package/package.json +16 -11
- package/src/access-control-values.ts +2 -2
- package/src/access-control.ts +7 -15
- package/src/analytics.ts +6 -13
- package/src/api-contract/components.generated.json +2553 -1046
- package/src/api-contract/engine.ts +641 -0
- package/src/api-contract/index.ts +30 -661
- package/src/api-schemas/access-control.ts +18 -16
- package/src/api-schemas/account.ts +5 -12
- package/src/api-schemas/agent-budget.ts +60 -0
- package/src/api-schemas/agent-runs.ts +63 -27
- package/src/api-schemas/apikey.ts +11 -10
- package/src/api-schemas/app-lifecycle.ts +5 -0
- package/src/api-schemas/audit-trail.ts +175 -1
- package/src/api-schemas/content.ts +55 -0
- package/src/api-schemas/cost-analytics.ts +42 -2
- package/src/api-schemas/environment.ts +0 -1
- package/src/api-schemas/group.ts +2 -1
- package/src/api-schemas/index.ts +2 -0
- package/src/api-schemas/inference-profile.ts +151 -0
- package/src/api-schemas/interaction.ts +40 -1
- package/src/api-schemas/invites.ts +10 -9
- package/src/api-schemas/process.ts +78 -2
- package/src/api-schemas/project-configuration.ts +19 -1
- package/src/api-schemas/project.ts +19 -10
- package/src/api-schemas/quota.ts +7 -6
- package/src/api-schemas/registry.ts +164 -62
- package/src/api-schemas/run-budget.ts +23 -0
- package/src/api-schemas/secrets.ts +0 -84
- package/src/api-schemas/store.ts +12 -0
- package/src/api-schemas/user.ts +9 -8
- package/src/api-schemas/workflow-runs.ts +2 -0
- package/src/apikey.ts +30 -39
- package/src/apps.ts +116 -239
- package/src/audit-trail.ts +37 -35
- package/src/browser-credentials.ts +11 -23
- package/src/common.ts +17 -37
- package/src/content-query.ts +3 -4
- package/src/cost-analytics.ts +13 -35
- package/src/data-platform.ts +79 -168
- package/src/delegation.ts +4 -9
- package/src/email.ts +15 -29
- package/src/embeddings.ts +25 -51
- package/src/environment.ts +16 -33
- package/src/facets.ts +3 -4
- package/src/group.ts +6 -13
- package/src/index.ts +23 -0
- package/src/inference-profile.ts +20 -0
- package/src/integrations.ts +21 -41
- package/src/interaction.ts +68 -137
- package/src/meters.ts +4 -9
- package/src/oauth-server.ts +40 -81
- package/src/oauth.ts +9 -19
- package/src/payload.ts +11 -25
- package/src/pending-asks.ts +8 -22
- package/src/platform-event.ts +48 -122
- package/src/principal-context.ts +3 -3
- package/src/project.ts +43 -86
- package/src/prompt.ts +14 -31
- package/src/query.ts +10 -20
- package/src/rate-limiter.ts +7 -19
- package/src/refs.ts +2 -3
- package/src/roles/types.ts +5 -11
- package/src/run-budget.ts +4 -0
- package/src/runs.ts +9 -19
- package/src/secrets.ts +10 -42
- package/src/store/agent-approval.ts +4 -9
- package/src/store/agent-run.ts +53 -99
- package/src/store/collections.ts +11 -23
- package/src/store/conversation-state.ts +15 -15
- package/src/store/doc-analyzer.ts +7 -15
- package/src/store/dsl-workflow.ts +10 -23
- package/src/store/duration.ts +45 -0
- package/src/store/grounded-extraction.ts +6 -13
- package/src/store/intake-policy-schema.generated.ts +148 -2
- package/src/store/process.ts +70 -140
- package/src/store/rendering.ts +6 -19
- package/src/store/signals.ts +48 -0
- package/src/store/store.ts +92 -181
- package/src/store/task.ts +10 -24
- package/src/store/workflow.ts +35 -71
- package/src/sts-token-types.ts +14 -33
- package/src/tools.ts +12 -25
- package/src/transient-tokens.ts +3 -3
- package/src/user.ts +16 -40
- package/src/views.ts +61 -125
- package/src/wire-types.generated.ts +11888 -0
- package/src/workflow-analytics.ts +21 -19
- package/src/agent-resources.test.ts +0 -89
- package/src/api-contract/components.contract.test.ts +0 -99
- package/src/api-schemas/access-control.contract.test.ts +0 -209
- package/src/api-schemas/account-apikey.test.ts +0 -60
- package/src/api-schemas/account.contract.test.ts +0 -319
- package/src/api-schemas/adapter-edge-cases.test.ts +0 -499
- package/src/api-schemas/agent-communication.contract.test.ts +0 -90
- package/src/api-schemas/agent-history.contract.test.ts +0 -42
- package/src/api-schemas/agent-runs.contract.test.ts +0 -240
- package/src/api-schemas/api-discriminators.test.ts +0 -185
- package/src/api-schemas/apikey.contract.test.ts +0 -270
- package/src/api-schemas/app-delete-summary.contract.test.ts +0 -67
- package/src/api-schemas/bulk-operation.contract.test.ts +0 -39
- package/src/api-schemas/bundle-isolation.test.ts +0 -44
- package/src/api-schemas/commands.contract.test.ts +0 -51
- package/src/api-schemas/cost-analytics.contract.test.ts +0 -64
- package/src/api-schemas/dashboard.contract.test.ts +0 -138
- package/src/api-schemas/data-store.contract.test.ts +0 -97
- package/src/api-schemas/document-processing.contract.test.ts +0 -76
- package/src/api-schemas/emit-json-schema.test.ts +0 -36
- package/src/api-schemas/environment.contract.test.ts +0 -202
- package/src/api-schemas/group.contract.test.ts +0 -205
- package/src/api-schemas/indexing.contract.test.ts +0 -122
- package/src/api-schemas/interaction.contract.test.ts +0 -307
- package/src/api-schemas/invites.contract.test.ts +0 -268
- package/src/api-schemas/llumiverse.contract.test.ts +0 -179
- package/src/api-schemas/mcp-api-key.contract.test.ts +0 -125
- package/src/api-schemas/oauth.contract.test.ts +0 -181
- package/src/api-schemas/parameters.test.ts +0 -402
- package/src/api-schemas/process.contract.test.ts +0 -115
- package/src/api-schemas/project.contract.test.ts +0 -472
- package/src/api-schemas/pruning-limits.test.ts +0 -189
- package/src/api-schemas/quota.contract.test.ts +0 -147
- package/src/api-schemas/registry-groups.test.ts +0 -99
- package/src/api-schemas/response-pruning.test.ts +0 -260
- package/src/api-schemas/store.contract.test.ts +0 -378
- package/src/api-schemas/sts.contract.test.ts +0 -112
- package/src/api-schemas/user.contract.test.ts +0 -197
- package/src/api-schemas/views.contract.test.ts +0 -112
- package/src/api-schemas/zeno-response-contracts.test.ts +0 -380
- package/src/apps.test.ts +0 -89
- package/src/oauth-scopes.test.ts +0 -15
- package/src/roles.test.ts +0 -33
- package/src/schema-for-extraction.test.ts +0 -191
- package/src/store/agent-approval.test.ts +0 -18
- package/src/store/content-type-editing.test.ts +0 -17
- package/src/store/ms.d.ts +0 -42
- package/src/store/schedule.test.ts +0 -59
- package/src/store/workflow.test.ts +0 -640
- package/src/versions.test.ts +0 -13
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { Ajv2020 } from 'ajv/dist/2020.js';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import type { CreateUserGroupPayload, UpdateUserGroupPayload, UserGroup } from '../group.js';
|
|
4
|
-
import type { User, UserRef } from '../user.js';
|
|
5
|
-
import type { JsonObject } from './adapter.js';
|
|
6
|
-
import type { UserGroupArrayFromSchema } from './group.js';
|
|
7
|
-
import { ApiSchemaComponents, apiComponentRef, validateApiRequest, validateApiResponse } from './registry.js';
|
|
8
|
-
import type { UserRefArrayFromSchema } from './user.js';
|
|
9
|
-
|
|
10
|
-
/** Exact type identity — `extends` in both directions is too weak (any/unknown slip through). */
|
|
11
|
-
type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
12
|
-
function assertType<T extends true>(_ok: T): void {}
|
|
13
|
-
|
|
14
|
-
function compile(name: string, components: Readonly<Record<string, JsonObject>> = ApiSchemaComponents) {
|
|
15
|
-
const ajv = new Ajv2020({ strictSchema: false, allErrors: true });
|
|
16
|
-
ajv.addSchema({ $id: 'vertesia://openapi', components: { schemas: components } });
|
|
17
|
-
return ajv.compile({ $ref: `vertesia://openapi${apiComponentRef(name as never)}` });
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const VALID_GROUP = {
|
|
21
|
-
id: 'g1',
|
|
22
|
-
account: 'a1',
|
|
23
|
-
name: 'Engineering',
|
|
24
|
-
tags: ['eng'],
|
|
25
|
-
created_at: '2026-07-30T10:00:00.000Z',
|
|
26
|
-
updated_at: '2026-07-30T10:00:00.000Z',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const VALID_REF = { id: 'u1', name: 'Someone', email: 'someone@acme.com' };
|
|
30
|
-
|
|
31
|
-
describe('gate 1 — the schema is the single source of truth for the public group types', () => {
|
|
32
|
-
it('publishes the exact schema-derived type, not a hand-written twin', () => {
|
|
33
|
-
assertType<Equals<UserGroupArrayFromSchema, UserGroup[]>>(true);
|
|
34
|
-
assertType<Equals<UserRefArrayFromSchema, UserRef[]>>(true);
|
|
35
|
-
expect(true).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('types the timestamps as the strings a client actually receives', () => {
|
|
39
|
-
// They were `Date` on the public type while the document published `format: date-time`
|
|
40
|
-
// strings. JSON has no date type, so the old declaration described the Mongoose document
|
|
41
|
-
// rather than the response — this is the correction, and the reason it is a compile-time
|
|
42
|
-
// break for anyone who was calling `.getTime()` on one.
|
|
43
|
-
assertType<Equals<UserGroup['created_at'], string>>(true);
|
|
44
|
-
assertType<Equals<UserGroup['updated_at'], string>>(true);
|
|
45
|
-
assertType<Equals<UserGroup['tags'], string[]>>(true);
|
|
46
|
-
assertType<Equals<UserGroup['allowed_projects'], string[] | undefined>>(true);
|
|
47
|
-
expect(true).toBe(true);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('derives UserRef from User rather than restating four fields', () => {
|
|
51
|
-
// `.pick()` on UserSchema, so a change to how `User` declares one of these follows through
|
|
52
|
-
// instead of leaving a twin behind. The requiredness comes with it: `email` is required on
|
|
53
|
-
// both, which is why the members listing has to map rather than serialize.
|
|
54
|
-
assertType<Equals<UserRef['id'], User['id']>>(true);
|
|
55
|
-
assertType<Equals<UserRef['name'], User['name']>>(true);
|
|
56
|
-
assertType<Equals<UserRef['email'], User['email']>>(true);
|
|
57
|
-
assertType<Equals<UserRef['picture'], User['picture']>>(true);
|
|
58
|
-
// And nothing else came across.
|
|
59
|
-
assertType<Equals<keyof UserRef, 'id' | 'name' | 'email' | 'picture'>>(true);
|
|
60
|
-
expect(true).toBe(true);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('derives both payloads from the group rather than restating its fields', () => {
|
|
64
|
-
// Same reasoning as UserRef, applied to the write side: each payload is a subset of the
|
|
65
|
-
// group, so the field types follow the response. Only requiredness differs, and only where
|
|
66
|
-
// it should — `tags` is required on a group the server always populates and optional in a
|
|
67
|
-
// payload the caller need not send.
|
|
68
|
-
assertType<Equals<CreateUserGroupPayload['name'], UserGroup['name']>>(true);
|
|
69
|
-
assertType<Equals<CreateUserGroupPayload['description'], UserGroup['description']>>(true);
|
|
70
|
-
assertType<Equals<CreateUserGroupPayload['tags'], string[] | undefined>>(true);
|
|
71
|
-
assertType<Equals<keyof CreateUserGroupPayload, 'name' | 'description' | 'tags' | 'allowed_projects'>>(true);
|
|
72
|
-
assertType<Equals<UpdateUserGroupPayload['properties'], UserGroup['properties']>>(true);
|
|
73
|
-
assertType<Equals<UpdateUserGroupPayload['clearance'], UserGroup['clearance']>>(true);
|
|
74
|
-
assertType<Equals<UpdateUserGroupPayload['compartments'], UserGroup['compartments']>>(true);
|
|
75
|
-
// The whitelist is what the pick leaves out: nothing server-owned is writable.
|
|
76
|
-
assertType<
|
|
77
|
-
Equals<
|
|
78
|
-
keyof UpdateUserGroupPayload,
|
|
79
|
-
'name' | 'description' | 'tags' | 'properties' | 'clearance' | 'compartments' | 'allowed_projects'
|
|
80
|
-
>
|
|
81
|
-
>(true);
|
|
82
|
-
expect(true).toBe(true);
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
describe('gate 2 — the published components match the closure the types come from', () => {
|
|
87
|
-
it('does not declare members on the group component', () => {
|
|
88
|
-
// Three handlers were shipping `members` — two by populating a `select: false` path, one by
|
|
89
|
-
// returning the in-memory document — while the component is closed and has never declared
|
|
90
|
-
// it. Members are published by their own route as UserRef[].
|
|
91
|
-
expect(Object.keys(ApiSchemaComponents.UserGroup.properties as JsonObject)).not.toContain('members');
|
|
92
|
-
expect(ApiSchemaComponents.UserGroup.additionalProperties).toBe(false);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('publishes UserRef as its own component, not a $ref back to User', () => {
|
|
96
|
-
// `.pick()` drops the `id: 'User'` metadata, which is what keeps the projection a separate
|
|
97
|
-
// component. If it carried the id across, every UserRef slot would suddenly promise a whole
|
|
98
|
-
// User to generated clients.
|
|
99
|
-
expect(JSON.stringify(ApiSchemaComponents.UserRef)).not.toContain('$ref');
|
|
100
|
-
expect(ApiSchemaComponents.UserRef.required).toEqual(['id', 'name', 'email']);
|
|
101
|
-
expect(ApiSchemaComponents.UserRefArray).toEqual({
|
|
102
|
-
type: 'array',
|
|
103
|
-
items: { $ref: '#/components/schemas/UserRef' },
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('keeps the timestamps enforceable rather than merely documented', () => {
|
|
108
|
-
const props = ApiSchemaComponents.UserGroup.properties as Record<string, JsonObject>;
|
|
109
|
-
expect(props.created_at).toEqual({ type: 'string', format: 'date-time' });
|
|
110
|
-
expect(ApiSchemaComponents.UserGroup.required).toEqual([
|
|
111
|
-
'id',
|
|
112
|
-
'account',
|
|
113
|
-
'name',
|
|
114
|
-
'tags',
|
|
115
|
-
'created_at',
|
|
116
|
-
'updated_at',
|
|
117
|
-
]);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe('gate 3 — AJV validates the same canonical objects that are published', () => {
|
|
122
|
-
it('accepts a minimal group and rejects a missing required field', () => {
|
|
123
|
-
const validate = compile('UserGroup');
|
|
124
|
-
expect(validate(VALID_GROUP)).toBe(true);
|
|
125
|
-
const { tags: _dropped, ...incomplete } = VALID_GROUP;
|
|
126
|
-
expect(validate(incomplete)).toBe(false);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('rejects the internal fields a serialized document would have leaked', () => {
|
|
130
|
-
const validate = compile('UserGroup');
|
|
131
|
-
expect(validate({ ...VALID_GROUP, members: ['u1'] })).toBe(false);
|
|
132
|
-
expect(validate({ ...VALID_GROUP, _id: 'deadbeef' })).toBe(false);
|
|
133
|
-
expect(validate({ ...VALID_GROUP, __v: 0 })).toBe(false);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('requires a name on the update payload, which both handlers checked by hand', () => {
|
|
137
|
-
const validate = compile('UpdateUserGroupPayload');
|
|
138
|
-
expect(validate({ name: 'Renamed' })).toBe(true);
|
|
139
|
-
expect(validate({})).toBe(false);
|
|
140
|
-
expect(validate({ name: 'Renamed', rogue_field: 1 })).toBe(false);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('accepts a create payload with only a name', () => {
|
|
144
|
-
const validate = compile('CreateUserGroupPayload');
|
|
145
|
-
expect(validate({ name: 'Engineering' })).toBe(true);
|
|
146
|
-
expect(validate({ name: 'Engineering', allowed_projects: [] })).toBe(true);
|
|
147
|
-
// `properties` and `clearance` are updatable but not settable at creation, and never were.
|
|
148
|
-
expect(validate({ name: 'Engineering', clearance: 3 })).toBe(false);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('documents allowed_projects for the request rather than inheriting the response text', () => {
|
|
152
|
-
// The one field where picking is not enough: the response explains what an empty list MEANS,
|
|
153
|
-
// the request explains what sending one DOES. Overriding the picked field is how a payload
|
|
154
|
-
// keeps request-specific documentation — and the same mechanism a field with genuinely
|
|
155
|
-
// different request semantics would need.
|
|
156
|
-
const create = (ApiSchemaComponents.CreateUserGroupPayload.properties as Record<string, JsonObject>)
|
|
157
|
-
.allowed_projects;
|
|
158
|
-
const group = (ApiSchemaComponents.UserGroup.properties as Record<string, JsonObject>).allowed_projects;
|
|
159
|
-
expect(create.description).toBe('Restrict the new group to the given projects (empty/absent = org-wide).');
|
|
160
|
-
expect(create.description).not.toBe(group.description);
|
|
161
|
-
// Everything except the description still comes from the group.
|
|
162
|
-
expect({ ...create, description: undefined }).toEqual({ ...group, description: undefined });
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
describe('gate 4 — runtime enforcement uses the published components', () => {
|
|
167
|
-
it('enforces the date-time format the timestamps claim', () => {
|
|
168
|
-
// Through the registry rather than the local `compile` helper: the production validator
|
|
169
|
-
// registers ajv-formats, and a bare Ajv2020 ignores `format` entirely.
|
|
170
|
-
expect(validateApiResponse('UserGroup', { ...VALID_GROUP, created_at: 'yesterday' }).valid).toBe(false);
|
|
171
|
-
expect(validateApiResponse('UserGroup', VALID_GROUP).valid).toBe(true);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it('rejects an undeclared update field without removing it', () => {
|
|
175
|
-
const payload: Record<string, unknown> = { name: 'Acme', rogue_field: 42 };
|
|
176
|
-
const result = validateApiRequest('UpdateUserGroupPayload', payload);
|
|
177
|
-
expect(result.valid).toBe(false);
|
|
178
|
-
expect(payload.rogue_field).toBe(42);
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
it('checks every member of the group listing against the same UserGroup component', () => {
|
|
182
|
-
expect(validateApiResponse('UserGroupArray', [VALID_GROUP, VALID_GROUP]).valid).toBe(true);
|
|
183
|
-
expect(validateApiResponse('UserGroupArray', []).valid).toBe(true);
|
|
184
|
-
// One group still carrying its members is what the unmapped listing would have produced.
|
|
185
|
-
expect(validateApiResponse('UserGroupArray', [VALID_GROUP, { ...VALID_GROUP, members: [] }]).valid).toBe(false);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it('checks every member of the members listing against UserRef', () => {
|
|
189
|
-
expect(validateApiResponse('UserRefArray', [VALID_REF]).valid).toBe(true);
|
|
190
|
-
// A user Mongo holds with no email — required on the wire, which is why the handler maps.
|
|
191
|
-
const { email: _dropped, ...withoutEmail } = VALID_REF;
|
|
192
|
-
expect(validateApiResponse('UserRefArray', [withoutEmail]).valid).toBe(false);
|
|
193
|
-
expect(validateApiResponse('UserRefArray', [{ ...VALID_REF, email: '' }]).valid).toBe(true);
|
|
194
|
-
// And the whole user document, which is what serializing the populated doc would send.
|
|
195
|
-
expect(validateApiResponse('UserRefArray', [{ ...VALID_REF, clearance: 3 }]).valid).toBe(false);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('hands back the component type on the valid branch', () => {
|
|
199
|
-
const result = validateApiResponse('UserGroup', VALID_GROUP);
|
|
200
|
-
expect(result.valid).toBe(true);
|
|
201
|
-
if (result.valid) {
|
|
202
|
-
assertType<Equals<typeof result.data, UserGroup>>(true);
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
});
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import type { GenericCommandResponse } from '../common.js';
|
|
3
|
-
import type { RecalculateEmbeddingsQuery } from '../embeddings.js';
|
|
4
|
-
import type {
|
|
5
|
-
DriftAnalysisStatusResponse,
|
|
6
|
-
EmbeddingsStatusResponse,
|
|
7
|
-
IndexingStatusResponse,
|
|
8
|
-
ProjectConfigurationEmbeddingEnablePayload,
|
|
9
|
-
ReindexAgentRunsPayload,
|
|
10
|
-
ReindexAgentRunsResponse,
|
|
11
|
-
StartProjectReindexPayload,
|
|
12
|
-
} from '../project.js';
|
|
13
|
-
import { WorkflowExecutionStatus } from '../store/workflow.js';
|
|
14
|
-
import type { GenericCommandResponseSchema } from './commands.js';
|
|
15
|
-
import type {
|
|
16
|
-
EmbeddingsStatusResponseSchema,
|
|
17
|
-
ProjectConfigurationEmbeddingEnablePayloadSchema,
|
|
18
|
-
RecalculateEmbeddingsQuerySchema,
|
|
19
|
-
} from './embeddings.js';
|
|
20
|
-
import type {
|
|
21
|
-
DriftAnalysisStatusResponseSchema,
|
|
22
|
-
IndexingStatusResponseSchema,
|
|
23
|
-
ReindexAgentRunsPayloadSchema,
|
|
24
|
-
ReindexAgentRunsResponseSchema,
|
|
25
|
-
StartProjectReindexPayloadSchema,
|
|
26
|
-
} from './indexing.js';
|
|
27
|
-
import { validateApiRequest, validateApiResponse } from './registry.js';
|
|
28
|
-
|
|
29
|
-
type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
30
|
-
function assertType<T extends true>(_value: T): void {}
|
|
31
|
-
|
|
32
|
-
describe('indexing and embedding API contracts', () => {
|
|
33
|
-
it('derives every public type from its domain schema', () => {
|
|
34
|
-
assertType<Equals<GenericCommandResponse, typeof GenericCommandResponseSchema._output>>(true);
|
|
35
|
-
assertType<Equals<EmbeddingsStatusResponse, typeof EmbeddingsStatusResponseSchema._output>>(true);
|
|
36
|
-
assertType<Equals<RecalculateEmbeddingsQuery, typeof RecalculateEmbeddingsQuerySchema._output>>(true);
|
|
37
|
-
assertType<Equals<IndexingStatusResponse, typeof IndexingStatusResponseSchema._output>>(true);
|
|
38
|
-
assertType<Equals<DriftAnalysisStatusResponse, typeof DriftAnalysisStatusResponseSchema._output>>(true);
|
|
39
|
-
assertType<
|
|
40
|
-
Equals<
|
|
41
|
-
ProjectConfigurationEmbeddingEnablePayload,
|
|
42
|
-
typeof ProjectConfigurationEmbeddingEnablePayloadSchema._output
|
|
43
|
-
>
|
|
44
|
-
>(true);
|
|
45
|
-
assertType<Equals<StartProjectReindexPayload, typeof StartProjectReindexPayloadSchema._output>>(true);
|
|
46
|
-
assertType<Equals<ReindexAgentRunsPayload, typeof ReindexAgentRunsPayloadSchema._output>>(true);
|
|
47
|
-
assertType<Equals<ReindexAgentRunsResponse, typeof ReindexAgentRunsResponseSchema._output>>(true);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('rejects undeclared request fields while allowing both optional reindex bodies', () => {
|
|
51
|
-
expect(validateApiRequest('StartProjectReindexPayload', undefined).valid).toBe(false);
|
|
52
|
-
expect(validateApiRequest('StartProjectReindexPayload', {}).valid).toBe(true);
|
|
53
|
-
expect(validateApiRequest('StartProjectReindexPayload', { unexpected: true }).valid).toBe(false);
|
|
54
|
-
expect(validateApiRequest('ReindexAgentRunsPayload', {}).valid).toBe(true);
|
|
55
|
-
expect(validateApiRequest('ReindexAgentRunsPayload', { recreate_index: true, unexpected: true }).valid).toBe(
|
|
56
|
-
false,
|
|
57
|
-
);
|
|
58
|
-
});
|
|
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
|
-
|
|
93
|
-
it('keeps drift workflow status numeric and nullable identifiers explicit', () => {
|
|
94
|
-
expect(
|
|
95
|
-
validateApiResponse('DriftAnalysisStatusResponse', {
|
|
96
|
-
workflow_id: null,
|
|
97
|
-
workflow_run_id: null,
|
|
98
|
-
status: WorkflowExecutionStatus.UNKNOWN,
|
|
99
|
-
}).valid,
|
|
100
|
-
).toBe(true);
|
|
101
|
-
expect(
|
|
102
|
-
validateApiResponse('DriftAnalysisStatusResponse', {
|
|
103
|
-
workflow_id: null,
|
|
104
|
-
workflow_run_id: null,
|
|
105
|
-
status: 'NOT_FOUND',
|
|
106
|
-
}).valid,
|
|
107
|
-
).toBe(false);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('validates command and embedding responses against the published components', () => {
|
|
111
|
-
expect(validateApiResponse('GenericCommandResponse', { status: 'ok', message: 'done' }).valid).toBe(true);
|
|
112
|
-
expect(
|
|
113
|
-
validateApiResponse('GenericCommandResponse', { status: 'ok', message: 'done', extra: true }).valid,
|
|
114
|
-
).toBe(false);
|
|
115
|
-
expect(
|
|
116
|
-
validateApiResponse('EmbeddingsStatusResponse', {
|
|
117
|
-
status: 'success',
|
|
118
|
-
vectorIndex: { status: 'READY' },
|
|
119
|
-
}).valid,
|
|
120
|
-
).toBe(true);
|
|
121
|
-
});
|
|
122
|
-
});
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import type { AsyncConversationExecutionPayload } from '../interaction.js';
|
|
3
|
-
import {
|
|
4
|
-
AsyncConversationExecutionPayloadSchema,
|
|
5
|
-
ComputeRunFacetPayloadSchema,
|
|
6
|
-
ComputeRunFacetsResponseSchema,
|
|
7
|
-
ConversationStateSchema,
|
|
8
|
-
ExecutionRunRefSchema,
|
|
9
|
-
FindRunResultSchema,
|
|
10
|
-
InCodeInteractionSchema,
|
|
11
|
-
InteractionCreatePayloadSchema,
|
|
12
|
-
InteractionPromptSegmentInputSchema,
|
|
13
|
-
InteractionSchema,
|
|
14
|
-
InteractionUpdatePayloadSchema,
|
|
15
|
-
PromptSegmentDefSchema,
|
|
16
|
-
ResolvedCatalogInteractionSchema,
|
|
17
|
-
RunClonePayloadSchema,
|
|
18
|
-
} from './interaction.js';
|
|
19
|
-
import { validateApiRequest } from './registry.js';
|
|
20
|
-
|
|
21
|
-
describe('conversation state contract', () => {
|
|
22
|
-
it('publishes the tool catalog storage scope used to resolve tool references', () => {
|
|
23
|
-
expect(ConversationStateSchema.shape.tool_catalog_storage_id.safeParse('process-run-1').success).toBe(true);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe('in-code interaction contract', () => {
|
|
28
|
-
it('retains prompt schemas when resolving a catalog interaction', () => {
|
|
29
|
-
const interaction = InCodeInteractionSchema.parse({
|
|
30
|
-
type: 'sys',
|
|
31
|
-
id: 'sys:GeneralAgent',
|
|
32
|
-
name: 'GeneralAgent',
|
|
33
|
-
title: 'General Agent',
|
|
34
|
-
tags: ['agent'],
|
|
35
|
-
agent_runner_options: { is_agent: true, request_template: '{{user_prompt}}' },
|
|
36
|
-
prompts: [
|
|
37
|
-
{
|
|
38
|
-
role: 'user',
|
|
39
|
-
content: '{{user_prompt}}',
|
|
40
|
-
content_type: 'handlebars',
|
|
41
|
-
schema: {
|
|
42
|
-
type: 'object',
|
|
43
|
-
properties: { user_prompt: { type: 'string', editor: 'textarea' } },
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
expect(interaction.prompts[0]?.schema).toMatchObject({
|
|
50
|
-
properties: { user_prompt: { type: 'string' } },
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('requires normalized title and tags only on the resolved response', () => {
|
|
55
|
-
const authoringShape = {
|
|
56
|
-
type: 'sys',
|
|
57
|
-
id: 'sys:Untitled',
|
|
58
|
-
name: 'Untitled',
|
|
59
|
-
prompts: [],
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
expect(InCodeInteractionSchema.safeParse(authoringShape).success).toBe(true);
|
|
63
|
-
expect(ResolvedCatalogInteractionSchema.safeParse(authoringShape).success).toBe(false);
|
|
64
|
-
expect(
|
|
65
|
-
ResolvedCatalogInteractionSchema.safeParse({ ...authoringShape, title: 'Untitled', tags: [] }).success,
|
|
66
|
-
).toBe(true);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('AsyncConversationExecutionPayload contract', () => {
|
|
71
|
-
it('accepts caller-provided metadata and enrichment controls', () => {
|
|
72
|
-
const payload: AsyncConversationExecutionPayload = {
|
|
73
|
-
type: 'conversation',
|
|
74
|
-
interaction: 'sys:AppTester',
|
|
75
|
-
title: 'Manual title',
|
|
76
|
-
topic: 'Manual topic',
|
|
77
|
-
generate_topic: false,
|
|
78
|
-
generate_lessons: false,
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
expect(AsyncConversationExecutionPayloadSchema.parse(payload)).toMatchObject(payload);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('retains an immutable app-version execution target', () => {
|
|
85
|
-
const payload: AsyncConversationExecutionPayload = {
|
|
86
|
-
type: 'conversation',
|
|
87
|
-
interaction: 'sys:AppTester',
|
|
88
|
-
app_version: '20260804T022611971Z',
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
expect(AsyncConversationExecutionPayloadSchema.parse(payload)).toMatchObject({
|
|
92
|
-
app_version: '20260804T022611971Z',
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('accepts Process-authored agent execution policy', () => {
|
|
97
|
-
const payload: AsyncConversationExecutionPayload = {
|
|
98
|
-
type: 'conversation',
|
|
99
|
-
interaction: 'sys:AppDeveloper',
|
|
100
|
-
agent_policy: {
|
|
101
|
-
phases: [
|
|
102
|
-
{
|
|
103
|
-
id: 'saved',
|
|
104
|
-
tools: ['app_workspace_save'],
|
|
105
|
-
tool_input_contains: [{ field: 'mode', contains: 'commit' }],
|
|
106
|
-
recovery_prompt: 'Save before finishing.',
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
phase_resets: [{ tools: ['app_workspace_edit'], to_phase: 'saved' }],
|
|
110
|
-
action_phase_count: 1,
|
|
111
|
-
action_phase_max_tokens: 4_096,
|
|
112
|
-
completion_prompt: 'Return the structured result now.',
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
expect(AsyncConversationExecutionPayloadSchema.parse(payload)).toMatchObject(payload);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('rejects a non-string app-version target', () => {
|
|
120
|
-
expect(() =>
|
|
121
|
-
AsyncConversationExecutionPayloadSchema.parse({
|
|
122
|
-
type: 'conversation',
|
|
123
|
-
interaction: 'sys:AppTester',
|
|
124
|
-
app_version: 42,
|
|
125
|
-
}),
|
|
126
|
-
).toThrow();
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
describe('run facet contracts', () => {
|
|
131
|
-
const facets = [
|
|
132
|
-
{ name: 'environments', field: 'environment' },
|
|
133
|
-
{ name: 'interactions', field: 'interaction' },
|
|
134
|
-
{ name: 'models', field: 'modelId' },
|
|
135
|
-
{ name: 'statuses', field: 'status' },
|
|
136
|
-
{ name: 'finish_reason', field: 'finish_reason' },
|
|
137
|
-
];
|
|
138
|
-
|
|
139
|
-
it('accepts exactly the supported run facet pairs', () => {
|
|
140
|
-
expect(ComputeRunFacetPayloadSchema.parse({ facets })).toEqual({ facets });
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it.each(['tags', 'created_by', 'start', 'end'])('rejects the removed %s facet', (field) => {
|
|
144
|
-
expect(ComputeRunFacetPayloadSchema.safeParse({ facets: [{ name: field, field }] }).success).toBe(false);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('rejects mismatched and additional facet names', () => {
|
|
148
|
-
expect(ComputeRunFacetPayloadSchema.safeParse({ facets: [{ name: 'models', field: 'status' }] }).success).toBe(
|
|
149
|
-
false,
|
|
150
|
-
);
|
|
151
|
-
expect(ComputeRunFacetPayloadSchema.safeParse({ facets: [{ name: 'custom', field: 'modelId' }] }).success).toBe(
|
|
152
|
-
false,
|
|
153
|
-
);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('keeps removed facet fields available as query filters', () => {
|
|
157
|
-
const query = {
|
|
158
|
-
tags: ['visible'],
|
|
159
|
-
created_by: 'user:123',
|
|
160
|
-
start: '2026-08-01T00:00:00.000Z',
|
|
161
|
-
end: '2026-08-02T00:00:00.000Z',
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
expect(ComputeRunFacetPayloadSchema.parse({ facets: [], query })).toEqual({ facets: [], query });
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('rejects removed and custom response facets', () => {
|
|
168
|
-
expect(ComputeRunFacetsResponseSchema.safeParse({ tags: [] }).success).toBe(false);
|
|
169
|
-
expect(ComputeRunFacetsResponseSchema.safeParse({ custom: [] }).success).toBe(false);
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
describe('run response contracts', () => {
|
|
174
|
-
it('retains an environment ID when a run references a deleted environment', () => {
|
|
175
|
-
expect(ExecutionRunRefSchema.shape.environment.parse('env-deleted')).toBe('env-deleted');
|
|
176
|
-
expect(ExecutionRunRefSchema.shape.environment.parse(null)).toBeNull();
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('models the arbitrary stored-field projection returned by /runs/find', () => {
|
|
180
|
-
expect(
|
|
181
|
-
FindRunResultSchema.parse({
|
|
182
|
-
id: 'run-1',
|
|
183
|
-
environment: 'env-1',
|
|
184
|
-
account: 'account-1',
|
|
185
|
-
project: 'project-1',
|
|
186
|
-
interaction: 'interaction-1',
|
|
187
|
-
result: [],
|
|
188
|
-
parameters: { query: 'test' },
|
|
189
|
-
}),
|
|
190
|
-
).toMatchObject({ environment: 'env-1', account: 'account-1', project: 'project-1' });
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('does not publish run persistence-only fields', () => {
|
|
194
|
-
expect(() => FindRunResultSchema.parse({ interaction_code: 'sys:Example' })).toThrow();
|
|
195
|
-
expect(() => FindRunResultSchema.parse({ tmp_prompt: [] })).toThrow();
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('models enriched supported run facet buckets', () => {
|
|
199
|
-
expect(
|
|
200
|
-
ComputeRunFacetsResponseSchema.parse({
|
|
201
|
-
environments: [{ _id: 'env-1', count: 2, name: 'Default' }],
|
|
202
|
-
interactions: [{ _id: 'interaction-1', count: 1, name: 'Example', status: 'published', version: 3 }],
|
|
203
|
-
models: [{ _id: 'gpt', count: 2 }],
|
|
204
|
-
total: 2,
|
|
205
|
-
}),
|
|
206
|
-
).toMatchObject({ total: 2 });
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
describe('interaction contracts', () => {
|
|
211
|
-
const populatedPrompt = {
|
|
212
|
-
role: 'user',
|
|
213
|
-
content: 'Hello',
|
|
214
|
-
content_type: 'text',
|
|
215
|
-
id: 'prompt-1',
|
|
216
|
-
name: 'Greeting',
|
|
217
|
-
status: 'draft',
|
|
218
|
-
version: 1,
|
|
219
|
-
project: 'project-1',
|
|
220
|
-
created_by: 'user-1',
|
|
221
|
-
updated_by: 'user-1',
|
|
222
|
-
created_at: '2026-08-20T00:00:00.000Z',
|
|
223
|
-
updated_at: '2026-08-20T00:00:00.000Z',
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
it('accepts the media-result storage setting on interaction payloads and responses', () => {
|
|
227
|
-
expect(InteractionSchema.shape.store_media_results.parse(true)).toBe(true);
|
|
228
|
-
expect(InteractionCreatePayloadSchema.shape.store_media_results.parse(false)).toBe(false);
|
|
229
|
-
expect(InteractionUpdatePayloadSchema.shape.store_media_results.parse(true)).toBe(true);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('keeps legacy populated prompts valid in interaction write payloads', () => {
|
|
233
|
-
const segment = { type: 'template', template: populatedPrompt };
|
|
234
|
-
|
|
235
|
-
expect(InteractionPromptSegmentInputSchema.safeParse(segment).success).toBe(true);
|
|
236
|
-
expect(
|
|
237
|
-
InteractionPromptSegmentInputSchema.safeParse({
|
|
238
|
-
...segment,
|
|
239
|
-
template: { ...populatedPrompt, edit_revision: 3 },
|
|
240
|
-
}).success,
|
|
241
|
-
).toBe(true);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it('still requires edit revisions on populated prompts returned by the API', () => {
|
|
245
|
-
const segment = { type: 'template', template: populatedPrompt };
|
|
246
|
-
|
|
247
|
-
expect(PromptSegmentDefSchema.safeParse(segment).success).toBe(false);
|
|
248
|
-
expect(
|
|
249
|
-
PromptSegmentDefSchema.safeParse({
|
|
250
|
-
...segment,
|
|
251
|
-
template: { ...populatedPrompt, edit_revision: 3 },
|
|
252
|
-
}).success,
|
|
253
|
-
).toBe(true);
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
describe('user message payload contract', () => {
|
|
258
|
-
const base = {
|
|
259
|
-
run: { id: 'run-1', account: 'acc-1', project: 'proj-1' },
|
|
260
|
-
environment: 'env-1',
|
|
261
|
-
options: { model: 'model-1' },
|
|
262
|
-
tools: [],
|
|
263
|
-
message: 'Search the other collection instead.',
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
it('accepts tool results owed to the model alongside the message', () => {
|
|
267
|
-
// A stop or an approval denial can leave results undelivered. They have to travel with
|
|
268
|
-
// the message that resumes the conversation: the payload is strict, so before `results`
|
|
269
|
-
// existed here the server rejected them and the work was silently dropped.
|
|
270
|
-
const result = validateApiRequest('UserMessagePayload', {
|
|
271
|
-
...base,
|
|
272
|
-
results: [{ tool_use_id: 'search-1', content: 'found 3 docs', is_error: false }],
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
expect(result.valid).toBe(true);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it('still accepts a message with no owed results', () => {
|
|
279
|
-
expect(validateApiRequest('UserMessagePayload', base).valid).toBe(true);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it('stays closed to undeclared fields', () => {
|
|
283
|
-
expect(validateApiRequest('UserMessagePayload', { ...base, unsupported: true }).valid).toBe(false);
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
describe('inference workflow attribution', () => {
|
|
288
|
-
it('keeps required clone workflow identifiers free of execution deprecation metadata', () => {
|
|
289
|
-
const workflow = RunClonePayloadSchema.shape.workflow.shape;
|
|
290
|
-
expect(workflow.run_id.meta()?.deprecated).toBeUndefined();
|
|
291
|
-
expect(workflow.workflow_id.meta()?.deprecated).toBeUndefined();
|
|
292
|
-
});
|
|
293
|
-
it('accepts root agent attribution on execution and clone requests', () => {
|
|
294
|
-
const workflow = { run_id: 'child-run', workflow_id: 'workstream:parent:child', agent_run_id: 'root-agent' };
|
|
295
|
-
expect(validateApiRequest('ExecutionRunWorkflow', workflow).valid).toBe(true);
|
|
296
|
-
expect(validateApiRequest('RunClonePayload', { source_run_id: 'source', workflow }).valid).toBe(true);
|
|
297
|
-
expect(
|
|
298
|
-
validateApiRequest('ExecutionRunWorkflow', { run_id: 'legacy', workflow_id: 'AgentRun:legacy' }).valid,
|
|
299
|
-
).toBe(true);
|
|
300
|
-
});
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
describe('background inference telemetry contract', () => {
|
|
304
|
-
it('accepts the background call type in the generated runtime contract', () => {
|
|
305
|
-
expect(validateApiRequest('LlmCallType', 'background').valid).toBe(true);
|
|
306
|
-
});
|
|
307
|
-
});
|