@vertesia/common 1.6.0-dev.20260923.085325Z → 1.6.0-dev.20261004.085740Z
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 +1389 -45
- 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 -4
- package/lib/api-schemas/account.d.ts.map +1 -1
- 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 +20 -0
- package/lib/api-schemas/audit-trail.d.ts.map +1 -1
- package/lib/api-schemas/audit-trail.js +7 -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 +18 -0
- package/lib/api-schemas/cost-analytics.d.ts.map +1 -1
- package/lib/api-schemas/cost-analytics.js +31 -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 +1 -0
- package/lib/api-schemas/index.d.ts.map +1 -1
- package/lib/api-schemas/index.js +1 -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 +27820 -35892
- package/lib/api-schemas/registry.d.ts.map +1 -1
- package/lib/api-schemas/registry.js +55 -5
- package/lib/api-schemas/registry.js.map +1 -1
- package/lib/api-schemas/run-budget.d.ts +52 -0
- package/lib/api-schemas/run-budget.d.ts.map +1 -0
- package/lib/api-schemas/run-budget.js +55 -0
- package/lib/api-schemas/run-budget.js.map +1 -0
- 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 +17 -18
- package/lib/audit-trail.d.ts.map +1 -1
- package/lib/audit-trail.js +2 -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 -51
- 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 +8 -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 +20 -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 +17 -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 +11231 -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 +15 -10
- 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 +1389 -45
- package/src/api-schemas/access-control.ts +18 -16
- package/src/api-schemas/account.ts +5 -4
- 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 +7 -1
- package/src/api-schemas/content.ts +55 -0
- package/src/api-schemas/cost-analytics.ts +34 -2
- package/src/api-schemas/environment.ts +0 -1
- package/src/api-schemas/group.ts +2 -1
- package/src/api-schemas/index.ts +1 -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 +131 -33
- package/src/api-schemas/run-budget.ts +60 -0
- 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 +18 -33
- 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 +27 -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 -97
- 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 +8 -0
- package/src/runs.ts +9 -19
- package/src/secrets.ts +20 -41
- 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 +17 -39
- package/src/views.ts +61 -125
- package/src/wire-types.generated.ts +11889 -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,115 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { ProcessRunConfigSchema, RecordProcessRunPayloadSchema } from './process.js';
|
|
3
|
-
import { ProcessAgentExecutionPolicySchema } from './process-agent-policy.js';
|
|
4
|
-
|
|
5
|
-
describe('ProcessRunConfigSchema', () => {
|
|
6
|
-
it('accepts validated LLM execution configuration and retains a strict Process boundary', () => {
|
|
7
|
-
expect(
|
|
8
|
-
ProcessRunConfigSchema.parse({
|
|
9
|
-
environment: 'openrouter-environment',
|
|
10
|
-
model: 'openai/gpt-5.6-sol',
|
|
11
|
-
model_options: { _option_id: 'openrouter-text', service_tier: 'flex' },
|
|
12
|
-
}),
|
|
13
|
-
).toEqual({
|
|
14
|
-
environment: 'openrouter-environment',
|
|
15
|
-
model: 'openai/gpt-5.6-sol',
|
|
16
|
-
model_options: { _option_id: 'openrouter-text', service_tier: 'flex' },
|
|
17
|
-
});
|
|
18
|
-
expect(() =>
|
|
19
|
-
ProcessRunConfigSchema.parse({ environment: 'openrouter-environment', unexpected: true }),
|
|
20
|
-
).toThrow();
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe('RecordProcessRunPayloadSchema', () => {
|
|
25
|
-
it('accepts schedule metadata for workflow-owned process runs', () => {
|
|
26
|
-
expect(
|
|
27
|
-
RecordProcessRunPayloadSchema.parse({
|
|
28
|
-
workflow_id: 'ProcessRun:scheduled',
|
|
29
|
-
first_workflow_run_id: 'temporal-run',
|
|
30
|
-
run_kind: 'process',
|
|
31
|
-
process_id: '68c01a23456789abcdef0123',
|
|
32
|
-
schedule_id: 'schedule-1',
|
|
33
|
-
type: 'schedule',
|
|
34
|
-
}),
|
|
35
|
-
).toMatchObject({ schedule_id: 'schedule-1', type: 'schedule' });
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe('ProcessAgentExecutionPolicySchema', () => {
|
|
40
|
-
it('accepts cache-stable phase tool enforcement and retains a strict boundary', () => {
|
|
41
|
-
expect(
|
|
42
|
-
ProcessAgentExecutionPolicySchema.parse({
|
|
43
|
-
phases: [
|
|
44
|
-
{
|
|
45
|
-
id: 'inspect',
|
|
46
|
-
tools: ['app_workspace_typecheck'],
|
|
47
|
-
continuation_tools: ['app_workspace_read'],
|
|
48
|
-
recovery_tools: ['app_workspace_read', 'app_workspace_edit'],
|
|
49
|
-
tool_input_contains: [
|
|
50
|
-
{
|
|
51
|
-
field: 'command',
|
|
52
|
-
contains: 'pnpm run test:unit',
|
|
53
|
-
not_contains: ['|'],
|
|
54
|
-
min_length: 18,
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
max_tokens: 12_288,
|
|
58
|
-
recovery_prompt: 'Inspect source.',
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
restrict_to_phase_tools: true,
|
|
62
|
-
max_failed_tool_iterations: 3,
|
|
63
|
-
max_failed_tool_iterations_per_phase: 2,
|
|
64
|
-
max_repeated_tool_failure_iterations: 1,
|
|
65
|
-
}),
|
|
66
|
-
).toMatchObject({
|
|
67
|
-
phases: [
|
|
68
|
-
{
|
|
69
|
-
tools: ['app_workspace_typecheck'],
|
|
70
|
-
continuation_tools: ['app_workspace_read'],
|
|
71
|
-
recovery_tools: ['app_workspace_read', 'app_workspace_edit'],
|
|
72
|
-
tool_input_contains: [
|
|
73
|
-
{
|
|
74
|
-
field: 'command',
|
|
75
|
-
contains: 'pnpm run test:unit',
|
|
76
|
-
not_contains: ['|'],
|
|
77
|
-
min_length: 18,
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
max_tokens: 12_288,
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
restrict_to_phase_tools: true,
|
|
84
|
-
max_failed_tool_iterations: 3,
|
|
85
|
-
max_failed_tool_iterations_per_phase: 2,
|
|
86
|
-
max_repeated_tool_failure_iterations: 1,
|
|
87
|
-
});
|
|
88
|
-
expect(() =>
|
|
89
|
-
ProcessAgentExecutionPolicySchema.parse({
|
|
90
|
-
phases: [{ id: 'inspect', tools: ['app_workspace_read'], recovery_prompt: 'Inspect source.' }],
|
|
91
|
-
restrict_to_phase_tools: true,
|
|
92
|
-
unexpected: true,
|
|
93
|
-
}),
|
|
94
|
-
).toThrow();
|
|
95
|
-
expect(() =>
|
|
96
|
-
ProcessAgentExecutionPolicySchema.parse({
|
|
97
|
-
phases: [
|
|
98
|
-
{
|
|
99
|
-
id: 'inspect',
|
|
100
|
-
tools: ['app_workspace_read'],
|
|
101
|
-
tool_input_contains: [{ field: 'path', contains: 'src/', not_contains: [], min_length: -1 }],
|
|
102
|
-
recovery_prompt: 'Inspect source.',
|
|
103
|
-
},
|
|
104
|
-
],
|
|
105
|
-
}),
|
|
106
|
-
).toThrow();
|
|
107
|
-
expect(() =>
|
|
108
|
-
ProcessAgentExecutionPolicySchema.parse({
|
|
109
|
-
phases: [{ id: 'inspect', tools: ['app_workspace_read'], recovery_prompt: 'Inspect source.' }],
|
|
110
|
-
max_failed_tool_iterations_per_phase: 0,
|
|
111
|
-
max_repeated_tool_failure_iterations: 0,
|
|
112
|
-
}),
|
|
113
|
-
).toThrow();
|
|
114
|
-
});
|
|
115
|
-
});
|
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
import { Ajv2020 } from 'ajv/dist/2020.js';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import type { ProjectToolInfo, RenderingTemplateDefinitionRef } from '../apps.js';
|
|
4
|
-
import {
|
|
5
|
-
type AskUserWebhookConfigurationInput,
|
|
6
|
-
type AwsConfiguration,
|
|
7
|
-
type ExaConfigurationInput,
|
|
8
|
-
type GithubConfigurationInput,
|
|
9
|
-
type GladiaConfigurationInput,
|
|
10
|
-
type LinkupConfigurationInput,
|
|
11
|
-
type MagicPdfConfiguration,
|
|
12
|
-
type ResendConfigurationInput,
|
|
13
|
-
type SerperConfigurationInput,
|
|
14
|
-
SupportedIntegrations,
|
|
15
|
-
} from '../integrations.js';
|
|
16
|
-
import {
|
|
17
|
-
type ICreateProjectPayload,
|
|
18
|
-
type ModelDefault,
|
|
19
|
-
type Project,
|
|
20
|
-
type ProjectPluginsUpdatePayload,
|
|
21
|
-
SYSTEM_INTERACTION_CATEGORIES,
|
|
22
|
-
type SystemDefaults,
|
|
23
|
-
SystemInteractionCategory,
|
|
24
|
-
} from '../project.js';
|
|
25
|
-
import type { JsonObject } from './adapter.js';
|
|
26
|
-
import type { CreateProjectPayloadFromSchema, ProjectToolInfoArrayFromSchema } from './project.js';
|
|
27
|
-
import { ApiSchemaComponents, apiComponentRef, validateApiRequest, validateApiResponse } from './registry.js';
|
|
28
|
-
|
|
29
|
-
/** Exact type identity — `extends` in both directions is too weak (any/unknown slip through). */
|
|
30
|
-
type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
31
|
-
function assertType<T extends true>(_ok: T): void {}
|
|
32
|
-
|
|
33
|
-
function compile(name: string) {
|
|
34
|
-
const ajv = new Ajv2020({ strictSchema: false, allErrors: true });
|
|
35
|
-
ajv.addSchema({ $id: 'vertesia://openapi', components: { schemas: ApiSchemaComponents } });
|
|
36
|
-
return ajv.compile({ $ref: `vertesia://openapi${apiComponentRef(name as never)}` });
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const VALID_TOOL = {
|
|
40
|
-
tool_name: 'web_search',
|
|
41
|
-
app_name: 'Search',
|
|
42
|
-
app_install_id: '68b1779130afe5403a1589bc',
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
describe('gate 1 — the schema is the single source of truth for the converted Projects types', () => {
|
|
46
|
-
it('publishes the exact schema-derived type, not a hand-written twin', () => {
|
|
47
|
-
assertType<Equals<ICreateProjectPayload, CreateProjectPayloadFromSchema>>(true);
|
|
48
|
-
assertType<Equals<ProjectToolInfoArrayFromSchema, ProjectToolInfo[]>>(true);
|
|
49
|
-
expect(true).toBe(true);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('types the plugin list as strings, which is what the collection has always held', () => {
|
|
53
|
-
// The wire type always said `string[]`; `IProject` in @dglabs/server-common said
|
|
54
|
-
// `Types.ObjectId[]`, and the Mongoose schema says `{ type: [String] }`. Validating the
|
|
55
|
-
// payload is what forced the three to agree.
|
|
56
|
-
assertType<Equals<ProjectPluginsUpdatePayload['plugins'], string[]>>(true);
|
|
57
|
-
expect(true).toBe(true);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('preserves enum-member discriminator types in inferred integration configurations', () => {
|
|
61
|
-
assertType<Equals<AskUserWebhookConfigurationInput['integration'], SupportedIntegrations.ask_user_webhook>>(
|
|
62
|
-
true,
|
|
63
|
-
);
|
|
64
|
-
assertType<Equals<AwsConfiguration['integration'], SupportedIntegrations.aws>>(true);
|
|
65
|
-
assertType<Equals<ExaConfigurationInput['integration'], SupportedIntegrations.exa>>(true);
|
|
66
|
-
assertType<Equals<GithubConfigurationInput['integration'], SupportedIntegrations.github>>(true);
|
|
67
|
-
assertType<Equals<GladiaConfigurationInput['integration'], SupportedIntegrations.gladia>>(true);
|
|
68
|
-
assertType<Equals<LinkupConfigurationInput['integration'], SupportedIntegrations.linkup>>(true);
|
|
69
|
-
assertType<Equals<MagicPdfConfiguration['integration'], SupportedIntegrations.magic_pdf>>(true);
|
|
70
|
-
assertType<Equals<ResendConfigurationInput['integration'], SupportedIntegrations.resend>>(true);
|
|
71
|
-
assertType<Equals<SerperConfigurationInput['integration'], SupportedIntegrations.serper>>(true);
|
|
72
|
-
expect(true).toBe(true);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('accepts an AWS integration that is declared but not configured', () => {
|
|
76
|
-
// `getIntegrationConfig` reads `integrations?.[integrationId] ?? {}`, so a project that has
|
|
77
|
-
// never set up AWS answers with the discriminator and `enabled` alone. `s3_role_arn` was
|
|
78
|
-
// required, which made that answer fail its own response contract on every call.
|
|
79
|
-
expect(
|
|
80
|
-
validateApiResponse('ProjectIntegrationConfigResponse', {
|
|
81
|
-
integration: SupportedIntegrations.aws,
|
|
82
|
-
enabled: false,
|
|
83
|
-
}).valid,
|
|
84
|
-
).toBe(true);
|
|
85
|
-
expect(
|
|
86
|
-
validateApiResponse('ProjectIntegrationConfigResponse', {
|
|
87
|
-
integration: SupportedIntegrations.aws,
|
|
88
|
-
enabled: true,
|
|
89
|
-
s3_role_arn: 'arn:aws:iam::123456789012:role/vertesia',
|
|
90
|
-
}).valid,
|
|
91
|
-
).toBe(true);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('accepts an ask_user_webhook integration that is declared but not configured', () => {
|
|
95
|
-
// Same defect as the AWS case above: `webhook_url` was required on the response, so an
|
|
96
|
-
// unconfigured project failed its own contract on every GET of this integration.
|
|
97
|
-
expect(
|
|
98
|
-
validateApiResponse('ProjectIntegrationConfigResponse', {
|
|
99
|
-
integration: SupportedIntegrations.ask_user_webhook,
|
|
100
|
-
enabled: false,
|
|
101
|
-
webhook_secret: null,
|
|
102
|
-
}).valid,
|
|
103
|
-
).toBe(true);
|
|
104
|
-
expect(
|
|
105
|
-
validateApiResponse('ProjectIntegrationConfigResponse', {
|
|
106
|
-
integration: SupportedIntegrations.ask_user_webhook,
|
|
107
|
-
enabled: true,
|
|
108
|
-
webhook_url: 'https://example.test/hooks/ask-user',
|
|
109
|
-
webhook_secret: null,
|
|
110
|
-
}).valid,
|
|
111
|
-
).toBe(true);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('still requires webhook_url when the integration is being configured', () => {
|
|
115
|
-
// The request schema must not follow the response into optionality — you cannot set this
|
|
116
|
-
// integration up without a URL.
|
|
117
|
-
expect(
|
|
118
|
-
validateApiRequest('ProjectIntegrationConfigRequest', {
|
|
119
|
-
integration: SupportedIntegrations.ask_user_webhook,
|
|
120
|
-
enabled: true,
|
|
121
|
-
}).valid,
|
|
122
|
-
).toBe(false);
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* The batch is deliberately partial, and these two tests pin WHY — so the boundary is a checked fact
|
|
128
|
-
* rather than a claim in a comment that quietly stops being true.
|
|
129
|
-
*/
|
|
130
|
-
describe('gate 2 — the closure is closed, bottom-up', () => {
|
|
131
|
-
it('converts Project only after everything it reaches', () => {
|
|
132
|
-
// The order was forced, not chosen. `ProjectConfiguration` reaches
|
|
133
|
-
// `InteractionExecutionConfiguration.model_options`, which is `ModelOptions` — the union of
|
|
134
|
-
// every llumiverse driver's options — and a canonical component may not `$ref` a
|
|
135
|
-
// TypeScript-derived one. So `ModelOptions` converted first, then the intake policy tree,
|
|
136
|
-
// The registry owns the whole reference closure. Asserting the chain prevents a schema
|
|
137
|
-
// group edit from leaving a published `$ref` without its component.
|
|
138
|
-
for (const name of [
|
|
139
|
-
'ModelOptions',
|
|
140
|
-
'InteractionExecutionConfiguration',
|
|
141
|
-
'ContentTypeIntakePolicy',
|
|
142
|
-
'ProjectIntakeConfiguration',
|
|
143
|
-
'ProjectConfiguration',
|
|
144
|
-
'Project',
|
|
145
|
-
]) {
|
|
146
|
-
expect(Object.keys(ApiSchemaComponents), name).toContain(name);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('publishes dedicated, optional update projections', () => {
|
|
151
|
-
for (const name of ['UpdateProjectPayload', 'UpdateProjectConfigurationPayload']) {
|
|
152
|
-
expect(Object.keys(ApiSchemaComponents), name).toContain(name);
|
|
153
|
-
}
|
|
154
|
-
// `.partial()` of the root, not a restatement: same properties, none required.
|
|
155
|
-
const project = ApiSchemaComponents.Project as JsonObject;
|
|
156
|
-
const partial = ApiSchemaComponents.UpdateProjectPayload as JsonObject;
|
|
157
|
-
expect(Object.keys(partial.properties as JsonObject)).toEqual(Object.keys(project.properties as JsonObject));
|
|
158
|
-
expect(partial.required).toBeUndefined();
|
|
159
|
-
expect(partial.additionalProperties).toBe(false);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('says what JSON can carry, which the TypeScript declaration did not', () => {
|
|
163
|
-
// `integrations` was `Map<string, unknown>` and the timestamps `Date`. No HTTP response has
|
|
164
|
-
// ever contained either — Mongoose flattens maps in `toJSON` and `JSON.stringify` turns a
|
|
165
|
-
// Date into a string — so a caller writing `.get(id)` or `.getTime()` got a TypeError. The
|
|
166
|
-
// published document is unchanged; only the TypeScript was wrong.
|
|
167
|
-
assertType<Equals<Project['integrations'], Record<string, unknown> | undefined>>(true);
|
|
168
|
-
assertType<Equals<Project['created_at'], string>>(true);
|
|
169
|
-
|
|
170
|
-
const properties = (ApiSchemaComponents.Project as JsonObject).properties as Record<string, JsonObject>;
|
|
171
|
-
// Still `format: date-time`, which is what makes the generated clients emit
|
|
172
|
-
// `OffsetDateTime` / `time.Time` rather than a bare string. A plain `z.string()` here would
|
|
173
|
-
// have dropped it silently.
|
|
174
|
-
expect(properties.created_at).toEqual({ type: 'string', format: 'date-time' });
|
|
175
|
-
expect(properties.updated_at).toEqual({ type: 'string', format: 'date-time' });
|
|
176
|
-
// The same open-map emission as Account.feature_flags and User.properties, normalized to the
|
|
177
|
-
// spelling the document has always used — `z.record`'s `{}` and `propertyNames` say the same
|
|
178
|
-
// thing but generate a different Go map type. `tenant_id` is absent, as it always was — the
|
|
179
|
-
// model computes it and the handler used to ship it anyway, which is what the response mapper
|
|
180
|
-
// now stops.
|
|
181
|
-
expect(properties.integrations).toEqual({ type: 'object', additionalProperties: true });
|
|
182
|
-
expect(properties).not.toHaveProperty('tenant_id');
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('converts the vision-profile map, because a canonical alias cannot be a mapped-type key', () => {
|
|
186
|
-
// `vision_profiles` was `Partial<Record<IntakeVisionDetail, …>>`. Once `IntakeVisionDetail`
|
|
187
|
-
// became a canonical alias the schema generator could no longer enumerate the mapped type's
|
|
188
|
-
// keys — it failed with `Unexpected key type "def-canonical-alias-IntakeVisionDetail"`, and
|
|
189
|
-
// `Project` then fell back to a source-text inference that silently dropped `configuration`
|
|
190
|
-
// and `integrations` from the published document. Converting the map is what removed the
|
|
191
|
-
// mapped type; this asserts the components it produces still exist under their old names.
|
|
192
|
-
expect(Object.keys(ApiSchemaComponents)).toContain('ProjectIntakeConfiguration');
|
|
193
|
-
const intake = ApiSchemaComponents.ProjectIntakeConfiguration as JsonObject;
|
|
194
|
-
const properties = intake.properties as Record<string, JsonObject>;
|
|
195
|
-
expect(properties.vision_profiles.$ref).toBe(apiComponentRef('IntakeVisionProfileSettingsMap' as never));
|
|
196
|
-
const map = ApiSchemaComponents.IntakeVisionProfileSettingsMap as JsonObject;
|
|
197
|
-
// The three keys are restated in the schema rather than derived from the enum, so this is
|
|
198
|
-
// what fails if a detail name is added to `IntakeVisionDetail` and not to the map.
|
|
199
|
-
expect(Object.keys(map.properties as JsonObject).sort()).toEqual(['high', 'low', 'standard']);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('converts every configuration leaf that depends on nothing outside this module', () => {
|
|
203
|
-
// Sixteen components, none of them named by an endpoint — they are hoisted by
|
|
204
|
-
// `ProjectConfiguration`, which is still derived. Converting them changes no slot; it makes
|
|
205
|
-
// the `$ref`s that the two remaining configuration components have to satisfy canonical, so
|
|
206
|
-
// the closure rule stops applying to them one level at a time.
|
|
207
|
-
for (const name of [
|
|
208
|
-
'ModelDefault',
|
|
209
|
-
'ModalityDefaults',
|
|
210
|
-
'SystemDefaults',
|
|
211
|
-
'ProjectModelDefaults',
|
|
212
|
-
'ResourceVisibility',
|
|
213
|
-
'ProjectSearchTier',
|
|
214
|
-
'ElasticsearchBackend',
|
|
215
|
-
'ProjectSearchPropertyType',
|
|
216
|
-
'ProjectSearchPropertyMapping',
|
|
217
|
-
'ProjectSearchPropertyMappingMap',
|
|
218
|
-
'ProjectIndexingConfiguration',
|
|
219
|
-
'ProjectConfigurationEmbedding',
|
|
220
|
-
'BrowserUseRiskPolicy',
|
|
221
|
-
'BrowserUseScreenshotCapture',
|
|
222
|
-
'BrowserUseProjectConfiguration',
|
|
223
|
-
'ProjectIntakeSniffConfiguration',
|
|
224
|
-
]) {
|
|
225
|
-
expect(Object.keys(ApiSchemaComponents), name).toContain(name);
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('keeps SystemDefaults covering every system interaction category', () => {
|
|
230
|
-
// The interface was `{ [K in SystemInteractionCategory]?: ModelDefault }`, so a new category
|
|
231
|
-
// widened it for free. A Zod object cannot map over an enum and still infer useful keys, so
|
|
232
|
-
// the categories are written out — and this is what makes forgetting one a compile error
|
|
233
|
-
// rather than a silently unpublishable default. The template literal turns the enum's member
|
|
234
|
-
// union into its string values, which is what the schema's keys are.
|
|
235
|
-
assertType<Equals<keyof SystemDefaults, `${SystemInteractionCategory}`>>(true);
|
|
236
|
-
assertType<Equals<SystemDefaults['intake'], ModelDefault | undefined>>(true);
|
|
237
|
-
expect(true).toBe(true);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
it('uses the analysis model default for both content query planning and reranking', () => {
|
|
241
|
-
expect(SYSTEM_INTERACTION_CATEGORIES.ContentSearchAgent).toBe(SystemInteractionCategory.analysis);
|
|
242
|
-
expect(SYSTEM_INTERACTION_CATEGORIES.ContentSearchReranker).toBe(SystemInteractionCategory.analysis);
|
|
243
|
-
});
|
|
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
|
-
|
|
260
|
-
it('publishes the property-mapping map without the propertyNames z.record adds', () => {
|
|
261
|
-
// `Record<string, ProjectSearchPropertyMapping>` is inline in the interface and has no
|
|
262
|
-
// TypeScript name, so it never becomes a canonical alias — it stays canonical AND derived,
|
|
263
|
-
// and the two have to agree forever. `z.record` emits a `propertyNames: {type: 'string'}`
|
|
264
|
-
// that the scanner never did, which is why the schema is a catchall-only object instead.
|
|
265
|
-
expect(ApiSchemaComponents.ProjectSearchPropertyMappingMap).toEqual({
|
|
266
|
-
type: 'object',
|
|
267
|
-
additionalProperties: { $ref: '#/components/schemas/ProjectSearchPropertyMapping' },
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it('accepts explicit nested paths through the project configuration contract', () => {
|
|
272
|
-
expect(ApiSchemaComponents.ProjectSearchPropertyType.enum).toContain('nested');
|
|
273
|
-
expect(
|
|
274
|
-
validateApiRequest('UpdateProjectConfigurationPayload', {
|
|
275
|
-
indexing: {
|
|
276
|
-
property_mappings: {
|
|
277
|
-
line_items: { type: 'nested' },
|
|
278
|
-
'line_items.sku': { type: 'keyword' },
|
|
279
|
-
'line_items.quantity': { type: 'long' },
|
|
280
|
-
},
|
|
281
|
-
},
|
|
282
|
-
}).valid,
|
|
283
|
-
).toBe(true);
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('publishes geo_point as an explicit project property mapping type', () => {
|
|
287
|
-
expect(ApiSchemaComponents.ProjectSearchPropertyType.enum).toContain('geo_point');
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
it('enforces the browser-use configuration the deleted AJV schema only described', () => {
|
|
291
|
-
// A `JSONSchemaType<BrowserUseProjectConfiguration>` used to sit beside the interface with
|
|
292
|
-
// descriptions that had already drifted from the TSDoc, and nothing compiled it. This is the
|
|
293
|
-
// same shape, and it is enforced.
|
|
294
|
-
expect(validateApiRequest('BrowserUseProjectConfiguration', { max_policy: 'low_write' }).valid).toBe(true);
|
|
295
|
-
expect(validateApiRequest('BrowserUseProjectConfiguration', { max_policy: 'god_mode' }).valid).toBe(false);
|
|
296
|
-
expect(validateApiRequest('BrowserUseProjectConfiguration', { capture_screenshots: 'always' }).valid).toBe(
|
|
297
|
-
false,
|
|
298
|
-
);
|
|
299
|
-
expect(validateApiRequest('BrowserUseProjectConfiguration', { unknown_switch: true }).valid).toBe(false);
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('converts the rendering templates ahead of the AppManifest that embeds them', () => {
|
|
303
|
-
// This pair was previously held back because the Ref is an `Omit<>`, which the scanner emits
|
|
304
|
-
// with `additionalProperties` before `properties` — an ordering Zod cannot reproduce. The
|
|
305
|
-
// canonical/derived comparison is no longer spelling-sensitive: `schemasAgree` compares
|
|
306
|
-
// objects key-order-insensitively and arrays index-by-index, so only the `required` ARRAY
|
|
307
|
-
// order still has to match, and the schema declares its fields to produce it.
|
|
308
|
-
expect(Object.keys(ApiSchemaComponents)).toContain('RenderingTemplateDefinition');
|
|
309
|
-
expect(Object.keys(ApiSchemaComponents)).toContain('RenderingTemplateDefinitionRef');
|
|
310
|
-
expect(ApiSchemaComponents.RenderingTemplateDefinitionRef.required).toEqual([
|
|
311
|
-
'assets',
|
|
312
|
-
'description',
|
|
313
|
-
'id',
|
|
314
|
-
'name',
|
|
315
|
-
'path',
|
|
316
|
-
'type',
|
|
317
|
-
]);
|
|
318
|
-
// `AppManifestData.templates` stays derived and now `$ref`s the canonical Ref — the closure
|
|
319
|
-
// rule only forbids the other direction.
|
|
320
|
-
expect(Object.keys(ApiSchemaComponents)).toContain('AppManifest');
|
|
321
|
-
const ref: RenderingTemplateDefinitionRef = {
|
|
322
|
-
path: '/api/v1/projects/p/apps/templates/deck',
|
|
323
|
-
id: 'acme:deck',
|
|
324
|
-
name: 'deck',
|
|
325
|
-
description: 'A deck',
|
|
326
|
-
type: 'presentation',
|
|
327
|
-
assets: [],
|
|
328
|
-
};
|
|
329
|
-
expect(validateApiResponse('RenderingTemplateDefinitionRef', ref).valid).toBe(true);
|
|
330
|
-
// The instructions body belongs to the full definition, not the listing entry.
|
|
331
|
-
expect(validateApiResponse('RenderingTemplateDefinitionRef', { ...ref, instructions: '# Deck' }).valid).toBe(
|
|
332
|
-
false,
|
|
333
|
-
);
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
describe('gate 3 — the published components match the closure the types come from', () => {
|
|
338
|
-
it('keeps SupportedIntegrations as the shared enum component it already was', () => {
|
|
339
|
-
const props = ApiSchemaComponents.ProjectIntegrationListEntry.properties as Record<string, JsonObject>;
|
|
340
|
-
expect(props.id).toEqual({ $ref: '#/components/schemas/SupportedIntegrations' });
|
|
341
|
-
// Still referenced by the unconverted integration-config union, which is only safe because
|
|
342
|
-
// the emitted enum is byte-identical to what the scanner derives.
|
|
343
|
-
expect(ApiSchemaComponents.SupportedIntegrations.enum).toEqual(Object.values(SupportedIntegrations));
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
it('publishes the tool settings as the open map the earlier batches established', () => {
|
|
347
|
-
const props = ApiSchemaComponents.ProjectToolInfo.properties as Record<string, JsonObject>;
|
|
348
|
-
expect(props.settings).toEqual({
|
|
349
|
-
type: 'object',
|
|
350
|
-
additionalProperties: true,
|
|
351
|
-
description: expect.stringContaining('may contain API keys'),
|
|
352
|
-
});
|
|
353
|
-
// Same emission as Account.feature_flags and User.properties, which have shipped since the
|
|
354
|
-
// first two batches. `z.record` writes this as `{}` plus a `propertyNames` that constrains
|
|
355
|
-
// nothing; both are normalized away so the document keeps one spelling for an open map.
|
|
356
|
-
expect((ApiSchemaComponents.Account.properties as Record<string, JsonObject>).feature_flags).toMatchObject({
|
|
357
|
-
additionalProperties: true,
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
it('closes every component in the batch', () => {
|
|
362
|
-
for (const name of [
|
|
363
|
-
'ListProjectsQuery',
|
|
364
|
-
'ProjectTagQuery',
|
|
365
|
-
'ICreateProjectPayload',
|
|
366
|
-
'ProjectPluginsUpdatePayload',
|
|
367
|
-
'CountResult',
|
|
368
|
-
'ProjectIntegrationListResponse',
|
|
369
|
-
'ProjectIntegrationListEntry',
|
|
370
|
-
'ProjectToolInfo',
|
|
371
|
-
] as const) {
|
|
372
|
-
expect([name, ApiSchemaComponents[name].additionalProperties]).toEqual([name, false]);
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
describe('gate 4 — AJV validates the same canonical objects that are published', () => {
|
|
378
|
-
it('requires name and namespace on a create payload and rejects anything else', () => {
|
|
379
|
-
const validate = compile('ICreateProjectPayload');
|
|
380
|
-
expect(validate({ name: 'Acme', namespace: 'acme' })).toBe(true);
|
|
381
|
-
expect(validate({ name: 'Acme', namespace: 'acme', description: 'x', auto_config: true })).toBe(true);
|
|
382
|
-
// The two hand-written presence checks the handler used to run, now enforced before it does.
|
|
383
|
-
expect(validate({ name: 'Acme' })).toBe(false);
|
|
384
|
-
expect(validate({ namespace: 'acme' })).toBe(false);
|
|
385
|
-
expect(validate({ name: 'Acme', namespace: 'acme', rogue_field: 1 })).toBe(false);
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
it('rejects a plugin list that is not an array of strings', () => {
|
|
389
|
-
const validate = compile('ProjectPluginsUpdatePayload');
|
|
390
|
-
expect(validate({ plugins: [] })).toBe(true);
|
|
391
|
-
expect(validate({ plugins: ['data-platform'] })).toBe(true);
|
|
392
|
-
// All three were accepted by `payload.plugins || []` off an `any` and written to the document.
|
|
393
|
-
expect(validate({ plugins: 'data-platform' })).toBe(false);
|
|
394
|
-
expect(validate({ plugins: [1, 2] })).toBe(false);
|
|
395
|
-
expect(validate({})).toBe(false);
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
it('validates the two query components the scanner expands into parameters', () => {
|
|
399
|
-
expect(compile('ListProjectsQuery')({})).toBe(true);
|
|
400
|
-
expect(compile('ListProjectsQuery')({ account: '68b1779130afe5403a1589ba' })).toBe(true);
|
|
401
|
-
// A repeated `?account=` reaches Koa as an array; the handler used to cast it to string.
|
|
402
|
-
expect(compile('ListProjectsQuery')({ account: ['a', 'b'] })).toBe(false);
|
|
403
|
-
expect(compile('ProjectTagQuery')({ tag: 'release' })).toBe(true);
|
|
404
|
-
expect(compile('ProjectTagQuery')({})).toBe(true);
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
it('accepts a minimal tool and rejects a missing required field', () => {
|
|
408
|
-
const validate = compile('ProjectToolInfo');
|
|
409
|
-
expect(validate(VALID_TOOL)).toBe(true);
|
|
410
|
-
expect(validate({ ...VALID_TOOL, tool_description: 'Searches the web' })).toBe(true);
|
|
411
|
-
expect(validate({ ...VALID_TOOL, settings: { api_key: 'sk-x', nested: { a: [1] } } })).toBe(true);
|
|
412
|
-
const { app_install_id: _dropped, ...incomplete } = VALID_TOOL;
|
|
413
|
-
expect(validate(incomplete)).toBe(false);
|
|
414
|
-
expect(validate({ ...VALID_TOOL, rogue_field: 1 })).toBe(false);
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
it('constrains the integration id to the supported catalog', () => {
|
|
418
|
-
const validate = compile('ProjectIntegrationListResponse');
|
|
419
|
-
expect(validate({ integrations: [{ id: SupportedIntegrations.github, enabled: true }] })).toBe(true);
|
|
420
|
-
expect(validate({ integrations: [] })).toBe(true);
|
|
421
|
-
expect(validate({ integrations: [{ id: 'dropbox', enabled: true }] })).toBe(false);
|
|
422
|
-
// An envelope, not a bare array — which is what the document already published.
|
|
423
|
-
expect(validate([{ id: SupportedIntegrations.github, enabled: true }])).toBe(false);
|
|
424
|
-
});
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
describe('gate 5 — runtime enforcement uses the published components', () => {
|
|
428
|
-
it('accepts decrypted integration credentials only on the response contract', () => {
|
|
429
|
-
expect(
|
|
430
|
-
validateApiResponse('ProjectIntegrationConfigResponse', {
|
|
431
|
-
integration: SupportedIntegrations.exa,
|
|
432
|
-
enabled: true,
|
|
433
|
-
api_key: 'agent-runtime-secret',
|
|
434
|
-
}).valid,
|
|
435
|
-
).toBe(true);
|
|
436
|
-
expect(
|
|
437
|
-
validateApiResponse('ProjectIntegrationConfigResponse', {
|
|
438
|
-
integration: SupportedIntegrations.ask_user_webhook,
|
|
439
|
-
enabled: true,
|
|
440
|
-
webhook_secret: 'agent-runtime-secret',
|
|
441
|
-
}).valid,
|
|
442
|
-
).toBe(true);
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
it('checks the shared count response the same way for every service that returns it', () => {
|
|
446
|
-
// Four slots across three resources and two servers, so this component had to move as a unit.
|
|
447
|
-
expect(validateApiResponse('CountResult', { count: 0 }).valid).toBe(true);
|
|
448
|
-
expect(validateApiResponse('CountResult', { count: 3, ids: ['a'] }).valid).toBe(false);
|
|
449
|
-
expect(validateApiResponse('CountResult', {}).valid).toBe(false);
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
it('checks every member of the tool listing against the same component', () => {
|
|
453
|
-
expect(validateApiResponse('ProjectToolInfoArray', [VALID_TOOL, VALID_TOOL]).valid).toBe(true);
|
|
454
|
-
expect(validateApiResponse('ProjectToolInfoArray', []).valid).toBe(true);
|
|
455
|
-
expect(validateApiResponse('ProjectToolInfoArray', [VALID_TOOL, { tool_name: 'x' }]).valid).toBe(false);
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
it('rejects an undeclared create field without removing it', () => {
|
|
459
|
-
const payload: Record<string, unknown> = { name: 'Acme', namespace: 'acme', rogue_field: 42 };
|
|
460
|
-
const result = validateApiRequest('ICreateProjectPayload', payload);
|
|
461
|
-
expect(result.valid).toBe(false);
|
|
462
|
-
expect(payload.rogue_field).toBe(42);
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
it('hands back the component type on the valid branch', () => {
|
|
466
|
-
const result = validateApiResponse('ProjectToolInfo', VALID_TOOL);
|
|
467
|
-
expect(result.valid).toBe(true);
|
|
468
|
-
if (result.valid) {
|
|
469
|
-
assertType<Equals<typeof result.data, ProjectToolInfo>>(true);
|
|
470
|
-
}
|
|
471
|
-
});
|
|
472
|
-
});
|