@adcp/sdk 14.0.0-rc.37 → 14.0.0-rc.39
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/bin/adcp-storyboard-summary.js +286 -0
- package/bin/adcp.js +221 -10
- package/dist/lib/conformance/schemaLoader.d.mts +1 -1
- package/dist/lib/conformance/schemaLoader.d.ts +1 -1
- package/dist/lib/core/AgentClient.d.mts +6 -1
- package/dist/lib/core/AgentClient.d.ts +6 -1
- package/dist/lib/core/AgentClient.js +9 -0
- package/dist/lib/core/AgentClient.mjs +9 -0
- package/dist/lib/core/ConversationTypes.d.mts +29 -0
- package/dist/lib/core/ConversationTypes.d.ts +29 -0
- package/dist/lib/core/SingleAgentClient.d.mts +3 -1
- package/dist/lib/core/SingleAgentClient.d.ts +3 -1
- package/dist/lib/core/SingleAgentClient.js +9 -1
- package/dist/lib/core/SingleAgentClient.mjs +9 -1
- package/dist/lib/core/TaskExecutor.d.mts +13 -1
- package/dist/lib/core/TaskExecutor.d.ts +13 -1
- package/dist/lib/core/TaskExecutor.js +216 -18
- package/dist/lib/core/TaskExecutor.mjs +216 -19
- package/dist/lib/index.d.mts +5 -2
- package/dist/lib/index.d.ts +5 -2
- package/dist/lib/index.js +10 -1
- package/dist/lib/index.mjs +10 -1
- package/dist/lib/media-buy/action-assessment.d.mts +77 -0
- package/dist/lib/media-buy/action-assessment.d.ts +77 -0
- package/dist/lib/media-buy/action-assessment.js +300 -0
- package/dist/lib/media-buy/action-assessment.mjs +284 -0
- package/dist/lib/media-buy/action-constraints.d.mts +9 -0
- package/dist/lib/media-buy/action-constraints.d.ts +9 -0
- package/dist/lib/media-buy/action-constraints.js +170 -0
- package/dist/lib/media-buy/action-constraints.mjs +146 -0
- package/dist/lib/media-buy/action-contracts.d.mts +40 -0
- package/dist/lib/media-buy/action-contracts.d.ts +40 -0
- package/dist/lib/media-buy/action-contracts.js +304 -0
- package/dist/lib/media-buy/action-contracts.mjs +267 -0
- package/dist/lib/media-buy/action-metadata.generated.d.mts +37 -0
- package/dist/lib/media-buy/action-metadata.generated.d.ts +37 -0
- package/dist/lib/media-buy/action-metadata.generated.js +128 -0
- package/dist/lib/media-buy/action-metadata.generated.mjs +101 -0
- package/dist/lib/media-buy/action-types.d.mts +106 -0
- package/dist/lib/media-buy/action-types.d.ts +106 -0
- package/dist/lib/{types/v3-1-beta/tools.generated.js → media-buy/action-types.js} +2 -2
- package/dist/lib/media-buy/actions.d.mts +6 -0
- package/dist/lib/media-buy/actions.d.ts +6 -0
- package/dist/lib/media-buy/actions.js +38 -0
- package/dist/lib/media-buy/actions.mjs +9 -0
- package/dist/lib/media-buy/available-actions.d.mts +2 -1
- package/dist/lib/media-buy/available-actions.d.ts +2 -1
- package/dist/lib/media-buy/available-actions.js +4 -3
- package/dist/lib/media-buy/available-actions.mjs +4 -3
- package/dist/lib/media-buy/compatibility.js +3 -0
- package/dist/lib/media-buy/compatibility.mjs +3 -0
- package/dist/lib/media-buy/index.d.mts +4 -0
- package/dist/lib/media-buy/index.d.ts +4 -0
- package/dist/lib/media-buy/index.js +3 -1
- package/dist/lib/media-buy/index.mjs +1 -0
- package/dist/lib/media-buy/legacy-action-ids.d.mts +1 -0
- package/dist/lib/media-buy/legacy-action-ids.d.ts +1 -0
- package/dist/lib/media-buy/legacy-action-ids.js +50 -0
- package/dist/lib/media-buy/legacy-action-ids.mjs +26 -0
- package/dist/lib/media-buy/mutations.d.mts +70 -0
- package/dist/lib/media-buy/mutations.d.ts +70 -0
- package/dist/lib/media-buy/mutations.js +525 -0
- package/dist/lib/media-buy/mutations.mjs +498 -0
- package/dist/lib/media-buy/preflight.d.mts +20 -69
- package/dist/lib/media-buy/preflight.d.ts +20 -69
- package/dist/lib/media-buy/preflight.js +100 -336
- package/dist/lib/media-buy/preflight.mjs +111 -333
- package/dist/lib/media-buy/targeting-input.d.mts +7 -4
- package/dist/lib/media-buy/targeting-input.d.ts +7 -4
- package/dist/lib/media-buy/types.d.mts +55 -7
- package/dist/lib/media-buy/types.d.ts +55 -7
- package/dist/lib/protocols/rawResponseCapture.d.mts +12 -0
- package/dist/lib/protocols/rawResponseCapture.d.ts +12 -0
- package/dist/lib/protocols/rawResponseCapture.js +33 -3
- package/dist/lib/protocols/rawResponseCapture.mjs +32 -3
- package/dist/lib/registry/types.generated.d.mts +377 -9
- package/dist/lib/registry/types.generated.d.ts +377 -9
- package/dist/lib/reporting/content-mismatch.d.mts +126 -0
- package/dist/lib/reporting/content-mismatch.d.ts +126 -0
- package/dist/lib/reporting/content-mismatch.js +90 -0
- package/dist/lib/reporting/content-mismatch.mjs +66 -0
- package/dist/lib/reporting/evidence.d.mts +1 -0
- package/dist/lib/reporting/evidence.d.ts +1 -0
- package/dist/lib/reporting/evidence.js +32 -3
- package/dist/lib/reporting/evidence.mjs +31 -3
- package/dist/lib/reporting/index.d.mts +3 -1
- package/dist/lib/reporting/index.d.ts +3 -1
- package/dist/lib/reporting/index.js +3 -0
- package/dist/lib/reporting/index.mjs +2 -0
- package/dist/lib/reporting/ledger/handler.d.mts +51 -1
- package/dist/lib/reporting/ledger/handler.d.ts +51 -1
- package/dist/lib/reporting/ledger/handler.js +306 -38
- package/dist/lib/reporting/ledger/handler.mjs +304 -37
- package/dist/lib/reporting/ledger/health.d.mts +12 -0
- package/dist/lib/reporting/ledger/health.d.ts +12 -0
- package/dist/lib/reporting/ledger/health.js +15 -2
- package/dist/lib/reporting/ledger/health.mjs +13 -1
- package/dist/lib/reporting/ledger/index.d.mts +3 -0
- package/dist/lib/reporting/ledger/index.d.ts +3 -0
- package/dist/lib/reporting/ledger/index.js +7 -1
- package/dist/lib/reporting/ledger/index.mjs +3 -0
- package/dist/lib/reporting/ledger/lifecycle.d.mts +31 -4
- package/dist/lib/reporting/ledger/lifecycle.d.ts +31 -4
- package/dist/lib/reporting/ledger/lifecycle.js +244 -37
- package/dist/lib/reporting/ledger/lifecycle.mjs +244 -37
- package/dist/lib/reporting/ledger/managed-postgres.d.mts +231 -0
- package/dist/lib/reporting/ledger/managed-postgres.d.ts +231 -0
- package/dist/lib/reporting/ledger/managed-postgres.js +1797 -0
- package/dist/lib/reporting/ledger/managed-postgres.mjs +1776 -0
- package/dist/lib/reporting/ledger/managed.d.mts +355 -0
- package/dist/lib/reporting/ledger/managed.d.ts +355 -0
- package/dist/lib/reporting/ledger/managed.js +661 -0
- package/dist/lib/reporting/ledger/managed.mjs +633 -0
- package/dist/lib/reporting/ledger/notification-activity.d.mts +222 -0
- package/dist/lib/reporting/ledger/notification-activity.d.ts +222 -0
- package/dist/lib/reporting/ledger/notification-activity.js +1139 -0
- package/dist/lib/reporting/ledger/notification-activity.mjs +1110 -0
- package/dist/lib/reporting/ledger/postgres.d.mts +161 -1
- package/dist/lib/reporting/ledger/postgres.d.ts +161 -1
- package/dist/lib/reporting/ledger/postgres.js +1153 -21
- package/dist/lib/reporting/ledger/postgres.mjs +1152 -21
- package/dist/lib/reporting/ledger/producer.d.mts +8 -0
- package/dist/lib/reporting/ledger/producer.d.ts +8 -0
- package/dist/lib/reporting/ledger/producer.js +146 -52
- package/dist/lib/reporting/ledger/producer.mjs +146 -51
- package/dist/lib/reporting/ledger/types.d.mts +358 -1
- package/dist/lib/reporting/ledger/types.d.ts +358 -1
- package/dist/lib/reporting/ledger/types.js +3 -0
- package/dist/lib/reporting/ledger/types.mjs +2 -0
- package/dist/lib/reporting/reconciliation.d.mts +362 -2
- package/dist/lib/reporting/reconciliation.d.ts +362 -2
- package/dist/lib/reporting/reconciliation.js +1051 -7
- package/dist/lib/reporting/reconciliation.mjs +1053 -7
- package/dist/lib/reporting/service/conformance.d.mts +35 -0
- package/dist/lib/reporting/service/conformance.d.ts +35 -0
- package/dist/lib/reporting/service/conformance.js +89 -0
- package/dist/lib/reporting/service/conformance.mjs +68 -0
- package/dist/lib/reporting/service/index.d.mts +182 -0
- package/dist/lib/reporting/service/index.d.ts +182 -0
- package/dist/lib/reporting/service/index.js +793 -0
- package/dist/lib/reporting/service/index.mjs +787 -0
- package/dist/lib/reporting/source/index.d.mts +2 -1
- package/dist/lib/reporting/source/index.d.ts +2 -1
- package/dist/lib/reporting/source/index.js +16 -3
- package/dist/lib/reporting/source/index.mjs +12 -1
- package/dist/lib/reporting/source/inline.d.mts +88 -1
- package/dist/lib/reporting/source/inline.d.ts +88 -1
- package/dist/lib/reporting/source/inline.js +1161 -163
- package/dist/lib/reporting/source/inline.mjs +1166 -163
- package/dist/lib/reporting/source/manifest.js +12 -7
- package/dist/lib/reporting/source/manifest.mjs +12 -7
- package/dist/lib/reporting/source/source.d.mts +26 -0
- package/dist/lib/reporting/source/source.d.ts +26 -0
- package/dist/lib/reporting/source/source.js +71 -2
- package/dist/lib/reporting/source/source.mjs +65 -1
- package/dist/lib/schemas/index.d.mts +22 -1
- package/dist/lib/schemas/index.d.ts +22 -1
- package/dist/lib/schemas/index.js +7 -0
- package/dist/lib/schemas/index.mjs +7 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +18 -0
- package/dist/lib/server/create-adcp-server.d.ts +18 -0
- package/dist/lib/server/create-adcp-server.js +52 -2
- package/dist/lib/server/create-adcp-server.mjs +52 -2
- package/dist/lib/server/decisioning/account.d.mts +1 -1
- package/dist/lib/server/decisioning/account.d.ts +1 -1
- package/dist/lib/server/decisioning/index.d.mts +1 -0
- package/dist/lib/server/decisioning/index.d.ts +1 -0
- package/dist/lib/server/decisioning/platform.d.mts +3 -0
- package/dist/lib/server/decisioning/platform.d.ts +3 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js +88 -10
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +88 -10
- package/dist/lib/server/decisioning/specialisms/reporting.d.mts +38 -0
- package/dist/lib/server/decisioning/specialisms/reporting.d.ts +38 -0
- package/dist/lib/{types/v3-1-beta/index.js → server/decisioning/specialisms/reporting.js} +2 -8
- package/dist/lib/server/decisioning/specialisms/reporting.mjs +0 -0
- package/dist/lib/server/index.d.mts +4 -2
- package/dist/lib/server/index.d.ts +4 -2
- package/dist/lib/server/index.js +5 -0
- package/dist/lib/server/index.mjs +4 -0
- package/dist/lib/server/media-buy-action-resolver.d.mts +63 -0
- package/dist/lib/server/media-buy-action-resolver.d.ts +63 -0
- package/dist/lib/server/media-buy-action-resolver.js +297 -0
- package/dist/lib/server/media-buy-action-resolver.mjs +285 -0
- package/dist/lib/server/media-buy-actions.d.mts +7 -8
- package/dist/lib/server/media-buy-actions.d.ts +7 -8
- package/dist/lib/server/media-buy-actions.js +57 -14
- package/dist/lib/server/media-buy-actions.mjs +63 -14
- package/dist/lib/server/notification-subscriptions/index.d.mts +2 -2
- package/dist/lib/server/notification-subscriptions/index.d.ts +2 -2
- package/dist/lib/server/notification-subscriptions/index.js +2 -0
- package/dist/lib/server/notification-subscriptions/index.mjs +2 -0
- package/dist/lib/server/notification-subscriptions/postgres-runtime.d.mts +3 -1
- package/dist/lib/server/notification-subscriptions/postgres-runtime.d.ts +3 -1
- package/dist/lib/server/notification-subscriptions/postgres-runtime.js +1 -0
- package/dist/lib/server/notification-subscriptions/postgres-runtime.mjs +1 -0
- package/dist/lib/server/notification-subscriptions/runtime.d.mts +12 -1
- package/dist/lib/server/notification-subscriptions/runtime.d.ts +12 -1
- package/dist/lib/server/notification-subscriptions/runtime.js +102 -16
- package/dist/lib/server/notification-subscriptions/runtime.mjs +101 -16
- package/dist/lib/server/notification-subscriptions/types.d.mts +104 -1
- package/dist/lib/server/notification-subscriptions/types.d.ts +104 -1
- package/dist/lib/server/webhook-emitter.d.mts +40 -5
- package/dist/lib/server/webhook-emitter.d.ts +40 -5
- package/dist/lib/server/webhook-emitter.js +23 -12
- package/dist/lib/server/webhook-emitter.mjs +23 -12
- package/dist/lib/storage/interfaces.d.mts +14 -2
- package/dist/lib/storage/interfaces.d.ts +14 -2
- package/dist/lib/testing/compliance/comply.d.mts +9 -3
- package/dist/lib/testing/compliance/comply.d.ts +9 -3
- package/dist/lib/testing/compliance/comply.js +158 -3
- package/dist/lib/testing/compliance/comply.mjs +159 -4
- package/dist/lib/testing/compliance/storyboard-tracks.js +7 -5
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +7 -5
- package/dist/lib/testing/compliance/summary.js +10 -1
- package/dist/lib/testing/compliance/summary.mjs +10 -1
- package/dist/lib/testing/index.d.mts +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.js +2 -0
- package/dist/lib/testing/index.mjs +3 -1
- package/dist/lib/testing/storyboard/agent-routing.d.mts +12 -43
- package/dist/lib/testing/storyboard/agent-routing.d.ts +12 -43
- package/dist/lib/testing/storyboard/agent-routing.js +75 -13
- package/dist/lib/testing/storyboard/agent-routing.mjs +70 -12
- package/dist/lib/testing/storyboard/index.d.mts +1 -0
- package/dist/lib/testing/storyboard/index.d.ts +1 -0
- package/dist/lib/testing/storyboard/index.js +3 -0
- package/dist/lib/testing/storyboard/index.mjs +2 -0
- package/dist/lib/testing/storyboard/junit.d.mts +1 -1
- package/dist/lib/testing/storyboard/junit.d.ts +1 -1
- package/dist/lib/testing/storyboard/junit.js +21 -2
- package/dist/lib/testing/storyboard/junit.mjs +21 -2
- package/dist/lib/testing/storyboard/probes.d.mts +130 -0
- package/dist/lib/testing/storyboard/probes.d.ts +130 -0
- package/dist/lib/testing/storyboard/probes.js +682 -10
- package/dist/lib/testing/storyboard/probes.mjs +683 -3
- package/dist/lib/testing/storyboard/request-signing/builder.d.mts +16 -5
- package/dist/lib/testing/storyboard/request-signing/builder.d.ts +16 -5
- package/dist/lib/testing/storyboard/request-signing/grader.d.mts +44 -1
- package/dist/lib/testing/storyboard/request-signing/grader.d.ts +44 -1
- package/dist/lib/testing/storyboard/request-signing/grader.js +46 -22
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +43 -21
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.mts +86 -11
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.ts +86 -11
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.js +119 -25
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +117 -26
- package/dist/lib/testing/storyboard/request-signing/synthesize.js +22 -2
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +22 -2
- package/dist/lib/testing/storyboard/runner.d.mts +103 -0
- package/dist/lib/testing/storyboard/runner.d.ts +103 -0
- package/dist/lib/testing/storyboard/runner.js +1090 -268
- package/dist/lib/testing/storyboard/runner.mjs +1096 -261
- package/dist/lib/testing/storyboard/seeding.d.mts +4 -1
- package/dist/lib/testing/storyboard/seeding.d.ts +4 -1
- package/dist/lib/testing/storyboard/seeding.js +55 -24
- package/dist/lib/testing/storyboard/seeding.mjs +55 -24
- package/dist/lib/testing/storyboard/test-kit.d.mts +37 -3
- package/dist/lib/testing/storyboard/test-kit.d.ts +37 -3
- package/dist/lib/testing/storyboard/test-kit.js +8 -2
- package/dist/lib/testing/storyboard/test-kit.mjs +7 -2
- package/dist/lib/testing/storyboard/types.d.mts +132 -10
- package/dist/lib/testing/storyboard/types.d.ts +132 -10
- package/dist/lib/testing/storyboard/types.js +17 -0
- package/dist/lib/testing/storyboard/types.mjs +16 -0
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/validations.js +16 -0
- package/dist/lib/testing/storyboard/validations.mjs +16 -0
- package/dist/lib/testing/test-controller.d.mts +1 -1
- package/dist/lib/testing/test-controller.d.ts +1 -1
- package/dist/lib/types/buy-products.d.ts +71 -6
- package/dist/lib/types/control-media-buy.d.ts +25 -11
- package/dist/lib/types/core.generated.d.mts +69 -10
- package/dist/lib/types/core.generated.d.ts +69 -10
- package/dist/lib/types/create-media-buy.d.ts +71 -6
- package/dist/lib/types/forward-compat-error-codes.d.mts +7 -6
- package/dist/lib/types/forward-compat-error-codes.d.ts +7 -6
- package/dist/lib/types/index.d.mts +2 -2
- package/dist/lib/types/index.d.ts +2 -2
- package/dist/lib/types/schemas.generated.d.ts +8040 -8116
- package/dist/lib/types/schemas.generated.js +1074 -309
- package/dist/lib/types/schemas.generated.mjs +1068 -309
- package/dist/lib/types/tools.generated.d.mts +65 -6
- package/dist/lib/types/tools.generated.d.ts +65 -6
- package/dist/lib/types/update-media-buy.d.ts +71 -6
- package/dist/lib/utils/redact-secrets.d.mts +1 -1
- package/dist/lib/utils/redact-secrets.d.ts +1 -1
- package/dist/lib/utils/redact-secrets.js +1 -1
- package/dist/lib/utils/redact-secrets.mjs +1 -1
- package/dist/lib/v2/projection/cache-versions.d.mts +0 -1
- package/dist/lib/v2/projection/cache-versions.d.ts +0 -1
- package/dist/lib/v2/projection/cache-versions.js +1 -15
- package/dist/lib/v2/projection/cache-versions.mjs +1 -14
- package/dist/lib/v2/projection/canonical-properties.js +2 -2
- package/dist/lib/v2/projection/canonical-properties.mjs +3 -3
- package/dist/lib/v2/projection/registry.d.mts +1 -1
- package/dist/lib/v2/projection/registry.d.ts +1 -1
- package/dist/lib/v2/projection/registry.js +2 -2
- package/dist/lib/v2/projection/registry.mjs +3 -3
- package/dist/lib/validation/schema-loader.d.mts +9 -1
- package/dist/lib/validation/schema-loader.d.ts +9 -1
- package/dist/lib/validation/schema-loader.js +65 -8
- package/dist/lib/validation/schema-loader.mjs +64 -8
- package/dist/lib/version.d.mts +5 -5
- package/dist/lib/version.d.ts +5 -5
- package/dist/lib/version.js +3 -8
- package/dist/lib/version.mjs +3 -8
- package/dist/lib/wholesale-feed-sync/index.d.mts +1 -0
- package/dist/lib/wholesale-feed-sync/index.d.ts +1 -0
- package/dist/lib/wholesale-feed-sync/protocol-types.d.mts +42 -0
- package/dist/lib/wholesale-feed-sync/protocol-types.d.ts +42 -0
- package/dist/lib/wholesale-feed-sync/protocol-types.js +16 -0
- package/dist/lib/wholesale-feed-sync/protocol-types.mjs +0 -0
- package/dist/lib/wholesale-feed-sync/sync.d.mts +6 -6
- package/dist/lib/wholesale-feed-sync/sync.d.ts +6 -6
- package/dist/lib/wholesale-feed-sync/sync.js +3 -1
- package/dist/lib/wholesale-feed-sync/sync.mjs +3 -1
- package/dist/lib/wholesale-feed-sync/types.d.mts +15 -14
- package/dist/lib/wholesale-feed-sync/types.d.ts +15 -14
- package/dist/lib/wholesale-feed-sync/webhook-notification.d.mts +7 -5
- package/dist/lib/wholesale-feed-sync/webhook-notification.d.ts +7 -5
- package/dist/lib/wholesale-feed-sync/webhook-notification.js +45 -0
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +44 -0
- package/docs/CLI.md +1 -1
- package/docs/TYPE-SUMMARY.md +118 -4
- package/docs/guides/ASYNC-API-REFERENCE.md +62 -1
- package/docs/guides/ASYNC-DEVELOPER-GUIDE.md +25 -0
- package/docs/guides/ASYNC-DOCUMENTATION-INDEX.md +3 -0
- package/docs/guides/BUYER-QUICKSTART-3.2.md +5 -0
- package/docs/guides/DURABLE-BUYER-WRITES.md +337 -0
- package/docs/guides/EXISTING-PLATFORM.md +80 -1
- package/docs/guides/MEDIA-BUY-3.2-COMPATIBILITY.md +57 -0
- package/docs/guides/MEDIA-BUY-ACTION-ASSESSMENT.md +300 -0
- package/docs/guides/REPORTING-LEDGER.md +654 -3
- package/docs/guides/REPORTING-RECONCILIATION.md +50 -0
- package/docs/guides/REPORTING-SOURCE-EXECUTOR.md +63 -1
- package/docs/guides/SELLER-QUICKSTART-3.2.md +2 -0
- package/docs/guides/VALIDATE-YOUR-AGENT.md +35 -0
- package/docs/guides/idempotency-crash-recovery.md +4 -0
- package/docs/llms.txt +4 -2
- package/docs/migration-14.x-rc-worksheet.md +60 -5
- package/docs/migration-7.9-to-7.10.md +7 -5
- package/examples/README.md +17 -0
- package/examples/durable-buyer-writes/caller.ts +745 -0
- package/examples/durable-buyer-writes/worker.ts +240 -0
- package/examples/reliable-reporting-service/README.md +100 -0
- package/examples/seller-3.2-starter.ts +7 -8
- package/examples/targeting-input-existing-platform.ts +153 -0
- package/package.json +41 -29
- package/skills/build-seller-agent/SKILL.md +2 -0
- package/skills/build-seller-agent/specialisms/signed-requests.md +11 -1
- package/skills/cross-cutting.md +28 -11
- package/compliance/cache/3.1.0-beta.7/domains/brand/index.yaml +0 -160
- package/compliance/cache/3.1.0-beta.7/domains/brand/scenarios/distributed_brand_resolution.yaml +0 -415
- package/compliance/cache/3.1.0-beta.7/domains/brand/scenarios/single_side_trust_extension.yaml +0 -454
- package/compliance/cache/3.1.0-beta.7/domains/creative/index.yaml +0 -339
- package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/billing_out_of_band.yaml +0 -153
- package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/creative_lifecycle_webhooks.yaml +0 -389
- package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/native_in_feed.yaml +0 -543
- package/compliance/cache/3.1.0-beta.7/domains/governance/index.yaml +0 -682
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/index.yaml +0 -781
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/audience_buy_flow.yaml +0 -380
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/available_actions.yaml +0 -565
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/billing_finality_delivery.yaml +0 -354
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/canonical_formats.yaml +0 -711
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/clicks_buy_flow.yaml +0 -264
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/completed_views_buy_flow.yaml +0 -344
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/create_media_buy_async.yaml +0 -234
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/creative_fate_after_cancellation.yaml +0 -419
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/creative_reception.yaml +0 -247
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/delivery_reporting.yaml +0 -357
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/dependency_impairment.yaml +0 -633
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/dependency_impairment_cardinality.yaml +0 -800
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/event_dedup_flow.yaml +0 -399
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/frequency_cap_enforcement.yaml +0 -309
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_approved.yaml +0 -214
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_conditions.yaml +0 -199
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_denied.yaml +0 -204
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_denied_recovery.yaml +0 -252
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/invalid_transitions.yaml +0 -289
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/inventory_list_no_match.yaml +0 -148
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/inventory_list_targeting.yaml +0 -276
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/measurement_accountability.yaml +0 -244
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/measurement_terms_rejected.yaml +0 -203
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/pending_creatives_to_start.yaml +0 -274
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/per_creative_conversion_attribution.yaml +0 -500
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/performance_buy_flow.yaml +0 -428
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/performance_buy_flow_roas.yaml +0 -470
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/product_signal_targeting.yaml +0 -373
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_finalize.yaml +0 -399
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_finalize_asap_timing.yaml +0 -264
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_not_found_errors.yaml +0 -257
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_audit_observation.yaml +0 -333
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_enforcement.yaml +0 -517
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_truth_of_claim.yaml +0 -294
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/reach_buy_flow.yaml +0 -823
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/refine_finalize_exclusivity.yaml +0 -360
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/refine_products.yaml +0 -148
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_accountability.yaml +0 -293
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +0 -307
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_optimization_flow.yaml +0 -576
- package/compliance/cache/3.1.0-beta.7/domains/media-buy/state-machine.yaml +0 -442
- package/compliance/cache/3.1.0-beta.7/domains/signals/index.yaml +0 -266
- package/compliance/cache/3.1.0-beta.7/domains/sponsored-intelligence/index.yaml +0 -256
- package/compliance/cache/3.1.0-beta.7/index.json +0 -356
- package/compliance/cache/3.1.0-beta.7/protocols/brand/index.yaml +0 -160
- package/compliance/cache/3.1.0-beta.7/protocols/brand/scenarios/distributed_brand_resolution.yaml +0 -415
- package/compliance/cache/3.1.0-beta.7/protocols/brand/scenarios/single_side_trust_extension.yaml +0 -454
- package/compliance/cache/3.1.0-beta.7/protocols/creative/index.yaml +0 -339
- package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/billing_out_of_band.yaml +0 -153
- package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/creative_lifecycle_webhooks.yaml +0 -389
- package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/native_in_feed.yaml +0 -543
- package/compliance/cache/3.1.0-beta.7/protocols/governance/index.yaml +0 -682
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/index.yaml +0 -781
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/audience_buy_flow.yaml +0 -380
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/available_actions.yaml +0 -565
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/billing_finality_delivery.yaml +0 -354
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/canonical_formats.yaml +0 -711
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/clicks_buy_flow.yaml +0 -264
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/completed_views_buy_flow.yaml +0 -344
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/create_media_buy_async.yaml +0 -234
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/creative_fate_after_cancellation.yaml +0 -419
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/creative_reception.yaml +0 -247
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/delivery_reporting.yaml +0 -357
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/dependency_impairment.yaml +0 -633
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/dependency_impairment_cardinality.yaml +0 -800
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/event_dedup_flow.yaml +0 -399
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/frequency_cap_enforcement.yaml +0 -309
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_approved.yaml +0 -214
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_conditions.yaml +0 -199
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_denied.yaml +0 -204
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_denied_recovery.yaml +0 -252
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/invalid_transitions.yaml +0 -289
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/inventory_list_no_match.yaml +0 -148
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/inventory_list_targeting.yaml +0 -276
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/measurement_accountability.yaml +0 -244
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/measurement_terms_rejected.yaml +0 -203
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/pending_creatives_to_start.yaml +0 -274
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/per_creative_conversion_attribution.yaml +0 -500
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/performance_buy_flow.yaml +0 -428
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/performance_buy_flow_roas.yaml +0 -470
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/product_signal_targeting.yaml +0 -373
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_finalize.yaml +0 -399
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_finalize_asap_timing.yaml +0 -264
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_not_found_errors.yaml +0 -257
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_audit_observation.yaml +0 -333
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_enforcement.yaml +0 -517
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_truth_of_claim.yaml +0 -294
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/reach_buy_flow.yaml +0 -823
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/refine_finalize_exclusivity.yaml +0 -360
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/refine_products.yaml +0 -148
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_accountability.yaml +0 -293
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +0 -307
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_optimization_flow.yaml +0 -576
- package/compliance/cache/3.1.0-beta.7/protocols/media-buy/state-machine.yaml +0 -442
- package/compliance/cache/3.1.0-beta.7/protocols/signals/index.yaml +0 -266
- package/compliance/cache/3.1.0-beta.7/protocols/sponsored-intelligence/index.yaml +0 -256
- package/compliance/cache/3.1.0-beta.7/specialisms/audience-sync/index.yaml +0 -313
- package/compliance/cache/3.1.0-beta.7/specialisms/brand-rights/index.yaml +0 -350
- package/compliance/cache/3.1.0-beta.7/specialisms/brand-rights/scenarios/governance_denied.yaml +0 -226
- package/compliance/cache/3.1.0-beta.7/specialisms/collection-lists/index.yaml +0 -359
- package/compliance/cache/3.1.0-beta.7/specialisms/content-standards/index.yaml +0 -572
- package/compliance/cache/3.1.0-beta.7/specialisms/creative-ad-server/index.yaml +0 -409
- package/compliance/cache/3.1.0-beta.7/specialisms/creative-generative/generative-seller.yaml +0 -807
- package/compliance/cache/3.1.0-beta.7/specialisms/creative-generative/index.yaml +0 -758
- package/compliance/cache/3.1.0-beta.7/specialisms/creative-template/index.yaml +0 -510
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-aware-seller/index.yaml +0 -143
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-aware-seller/scenarios/governance_multi_agent_rejected.yaml +0 -117
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-delivery-monitor/index.yaml +0 -441
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-spend-authority/denied.yaml +0 -221
- package/compliance/cache/3.1.0-beta.7/specialisms/governance-spend-authority/index.yaml +0 -330
- package/compliance/cache/3.1.0-beta.7/specialisms/property-lists/index.yaml +0 -482
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-broadcast-tv/index.yaml +0 -738
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-catalog-driven/index.yaml +0 -840
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-guaranteed/index.yaml +0 -601
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-non-guaranteed/index.yaml +0 -546
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-proposal-mode/index.yaml +0 -586
- package/compliance/cache/3.1.0-beta.7/specialisms/sales-social/index.yaml +0 -919
- package/compliance/cache/3.1.0-beta.7/specialisms/signal-marketplace/index.yaml +0 -424
- package/compliance/cache/3.1.0-beta.7/specialisms/signal-marketplace/scenarios/governance_denied.yaml +0 -211
- package/compliance/cache/3.1.0-beta.7/specialisms/signal-owned/index.yaml +0 -317
- package/compliance/cache/3.1.0-beta.7/specialisms/sponsored-intelligence/index.yaml +0 -59
- package/compliance/cache/3.1.0-beta.7/test-kits/acme-outdoor-live.yaml +0 -78
- package/compliance/cache/3.1.0-beta.7/test-kits/acme-outdoor.yaml +0 -223
- package/compliance/cache/3.1.0-beta.7/test-kits/billing-gate-runner.yaml +0 -115
- package/compliance/cache/3.1.0-beta.7/test-kits/bistro-oranje.yaml +0 -126
- package/compliance/cache/3.1.0-beta.7/test-kits/distributed-brand-runner.yaml +0 -281
- package/compliance/cache/3.1.0-beta.7/test-kits/nova-motors.yaml +0 -262
- package/compliance/cache/3.1.0-beta.7/test-kits/osei-natural.yaml +0 -126
- package/compliance/cache/3.1.0-beta.7/test-kits/parallel-dispatch-runner.yaml +0 -196
- package/compliance/cache/3.1.0-beta.7/test-kits/rate-limit-trip-runner.yaml +0 -172
- package/compliance/cache/3.1.0-beta.7/test-kits/signed-requests-runner.yaml +0 -155
- package/compliance/cache/3.1.0-beta.7/test-kits/single-side-trust-runner.yaml +0 -294
- package/compliance/cache/3.1.0-beta.7/test-kits/substitution-observer-runner.yaml +0 -688
- package/compliance/cache/3.1.0-beta.7/test-kits/summit-foods.yaml +0 -125
- package/compliance/cache/3.1.0-beta.7/test-kits/webhook-receiver-runner.yaml +0 -265
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/001-minimal-plan.json +0 -43
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/002-full-plan.json +0 -217
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/003-bookkeeping-stripped.json +0 -60
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/004a-human-review-omitted.json +0 -43
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/004b-human-review-explicit-null.json +0 -49
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/005a-policy-categories-order-1.json +0 -53
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/005b-policy-categories-order-2.json +0 -57
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/006a-ext-trace-v1.json +0 -49
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/006b-ext-trace-v2.json +0 -53
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/007-unicode-objectives.json +0 -43
- package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/008-numeric-canonicalization.json +0 -65
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/README.md +0 -220
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/canonicalization.json +0 -241
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/keys.json +0 -60
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/001-no-signature-header.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/002-wrong-tag.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/003-expired-signature.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/004-window-too-long.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/005-alg-not-allowed.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/006-missing-covered-component.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/007-missing-content-digest.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/008-unknown-keyid.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/009-key-ops-missing-verify.json +0 -27
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/010-content-digest-mismatch.json +0 -33
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/011-malformed-header.json +0 -27
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/012-missing-expires-param.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/013-expires-le-created.json +0 -27
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/014-missing-nonce-param.json +0 -27
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/015-signature-invalid.json +0 -28
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/016-replayed-nonce.json +0 -35
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/017-key-revoked.json +0 -38
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/018-digest-covered-when-forbidden.json +0 -28
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/019-signature-without-signature-input.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/020-rate-abuse.json +0 -34
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/021-duplicate-signature-input-label.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/022-multi-valued-content-type.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/023-multi-valued-content-digest.json +0 -32
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/024-unquoted-string-param.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/025-jwk-alg-crv-mismatch.json +0 -43
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/026-non-ascii-host.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/027-webhook-registration-authentication-unsigned.json +0 -25
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/028-unsigned-protocol-method-required.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/001-basic-post.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/002-post-with-content-digest.json +0 -31
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/003-es256-post.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/004-multiple-signature-labels.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/005-default-port-stripped.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/006-dot-segment-path.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/007-query-byte-preserved.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/008-percent-encoded-path.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/009-percent-encoded-unreserved-decoded.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/010-percent-encoded-slash-preserved.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/011-ipv6-authority.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/012-ipv6-authority-default-port-stripped.json +0 -30
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/README.md +0 -211
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/keys.json +0 -61
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/001-wrong-tag.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/002-expired-signature.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/003-window-too-long.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/004-alg-not-allowed.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/005-missing-authority-component.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/006-missing-content-digest.json +0 -25
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/007-unknown-keyid.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/008-wrong-adcp-use.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/009-content-digest-mismatch.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/010-malformed-signature-input.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/011-signature-without-input.json +0 -25
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/012-missing-expires-param.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/013-expires-le-created.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/014-missing-nonce-param.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/015-signature-invalid.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/016-replayed-nonce.json +0 -37
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/017-key-revoked.json +0 -32
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/018-rate-abuse.json +0 -33
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/019-revocation-stale.json +0 -32
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/020-key-ops-missing-verify.json +0 -41
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/021-base64-alphabet-mixing.json +0 -26
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/001-basic-post.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/002-es256-post.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/003-multiple-signature-labels.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/004-default-port-stripped.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/005-percent-encoded-path.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/006-query-byte-preserved.json +0 -24
- package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/007-body-without-idempotency-key.json +0 -25
- package/compliance/cache/3.1.0-beta.7/universal/billing-gate-dispatch.yaml +0 -450
- package/compliance/cache/3.1.0-beta.7/universal/canonical-format-validate-input.yaml +0 -640
- package/compliance/cache/3.1.0-beta.7/universal/capability-discovery.yaml +0 -125
- package/compliance/cache/3.1.0-beta.7/universal/collection-lists-pagination-integrity.yaml +0 -306
- package/compliance/cache/3.1.0-beta.7/universal/comply-controller-mode-gate.yaml +0 -141
- package/compliance/cache/3.1.0-beta.7/universal/content-standards-pagination-integrity.yaml +0 -326
- package/compliance/cache/3.1.0-beta.7/universal/deterministic-testing.yaml +0 -1430
- package/compliance/cache/3.1.0-beta.7/universal/error-compliance-signals.yaml +0 -377
- package/compliance/cache/3.1.0-beta.7/universal/error-compliance.yaml +0 -528
- package/compliance/cache/3.1.0-beta.7/universal/fictional-entities.yaml +0 -307
- package/compliance/cache/3.1.0-beta.7/universal/get-media-buys-pagination-integrity.yaml +0 -160
- package/compliance/cache/3.1.0-beta.7/universal/get-signals-pagination-integrity.yaml +0 -211
- package/compliance/cache/3.1.0-beta.7/universal/idempotency.yaml +0 -861
- package/compliance/cache/3.1.0-beta.7/universal/notification-config-event-scope.yaml +0 -119
- package/compliance/cache/3.1.0-beta.7/universal/notification-config-lifecycle.yaml +0 -337
- package/compliance/cache/3.1.0-beta.7/universal/notification-config-rejections.yaml +0 -107
- package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity-creative-formats.yaml +0 -265
- package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity-list-accounts.yaml +0 -245
- package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity.yaml +0 -263
- package/compliance/cache/3.1.0-beta.7/universal/property-lists-pagination-integrity.yaml +0 -307
- package/compliance/cache/3.1.0-beta.7/universal/read-tool-idempotency.yaml +0 -405
- package/compliance/cache/3.1.0-beta.7/universal/runner-output-contract.yaml +0 -1266
- package/compliance/cache/3.1.0-beta.7/universal/schema-validation-signals.yaml +0 -181
- package/compliance/cache/3.1.0-beta.7/universal/schema-validation.yaml +0 -548
- package/compliance/cache/3.1.0-beta.7/universal/security.yaml +0 -539
- package/compliance/cache/3.1.0-beta.7/universal/signed-requests.yaml +0 -217
- package/compliance/cache/3.1.0-beta.7/universal/stale-response-advisory.yaml +0 -295
- package/compliance/cache/3.1.0-beta.7/universal/storyboard-schema.yaml +0 -2136
- package/compliance/cache/3.1.0-beta.7/universal/v3-envelope-integrity.yaml +0 -117
- package/compliance/cache/3.1.0-beta.7/universal/version-negotiation.yaml +0 -130
- package/compliance/cache/3.1.0-beta.7/universal/webhook-emission.yaml +0 -411
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-bulk-webhooks.yaml +0 -82
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-product-webhooks.yaml +0 -83
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-products.yaml +0 -151
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-signal-webhooks.yaml +0 -83
- package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-signals.yaml +0 -149
- package/dist/lib/types/v3-1-beta/index.d.mts +0 -1
- package/dist/lib/types/v3-1-beta/index.d.ts +0 -1
- package/dist/lib/types/v3-1-beta/index.mjs +0 -1
- package/dist/lib/types/v3-1-beta/tools.generated.d.mts +0 -26788
- package/dist/lib/types/v3-1-beta/tools.generated.d.ts +0 -26788
- /package/dist/lib/{types/v3-1-beta/tools.generated.mjs → media-buy/action-types.mjs} +0 -0
|
@@ -20,7 +20,10 @@ var runner_exports = {};
|
|
|
20
20
|
__export(runner_exports, {
|
|
21
21
|
__defaultAuthHeadersForRawProbeForTest: () => __defaultAuthHeadersForRawProbeForTest,
|
|
22
22
|
__filterResponseHeadersForTest: () => __filterResponseHeadersForTest,
|
|
23
|
+
__protectedToolCandidatesForTest: () => __protectedToolCandidatesForTest,
|
|
23
24
|
__redactSecretsForTest: () => __redactSecretsForTest,
|
|
25
|
+
__selectProtectedToolTargetForTest: () => __selectProtectedToolTargetForTest,
|
|
26
|
+
__sessionControlCredentialsForTest: () => __sessionControlCredentialsForTest,
|
|
24
27
|
applyAdcpVersionRunOptions: () => applyAdcpVersionRunOptions,
|
|
25
28
|
applyBrandInvariant: () => applyBrandInvariant,
|
|
26
29
|
applyDisableSandboxHint: () => applyDisableSandboxHint,
|
|
@@ -34,6 +37,9 @@ __export(runner_exports, {
|
|
|
34
37
|
resolveCapabilityPath: () => resolveCapabilityPath,
|
|
35
38
|
runStoryboard: () => runStoryboard,
|
|
36
39
|
runStoryboardStep: () => runStoryboardStep,
|
|
40
|
+
signingCoverage: () => signingCoverage,
|
|
41
|
+
signingCoverageUnverified: () => signingCoverageUnverified,
|
|
42
|
+
storyboardCapabilityPredicates: () => storyboardCapabilityPredicates,
|
|
37
43
|
summarizeStrictValidation: () => summarizeStrictValidation
|
|
38
44
|
});
|
|
39
45
|
module.exports = __toCommonJS(runner_exports);
|
|
@@ -68,13 +74,18 @@ var import_probes = require('./probes.js');
|
|
|
68
74
|
var import_capabilities_types = require('../../signing/agent-resolver/capabilities-types.js');
|
|
69
75
|
var import_select_agent = require('../../signing/agent-resolver/select-agent.js');
|
|
70
76
|
var import_test_kit = require('./test-kit.js');
|
|
77
|
+
var import_idempotency2 = require('../../utils/idempotency.js');
|
|
78
|
+
var import_tool_request_schemas = require('../../utils/tool-request-schemas.js');
|
|
79
|
+
var import_capabilities = require('../../utils/capabilities.js');
|
|
71
80
|
var import_loader = require('./loader.js');
|
|
72
81
|
var import_phase_condition = require('./phase-condition.js');
|
|
73
82
|
var import_provenance = require('./provenance.js');
|
|
74
83
|
var import_probe_dispatch = require('./request-signing/probe-dispatch.js');
|
|
84
|
+
var import_synthesize = require('./request-signing/synthesize.js');
|
|
75
85
|
var import_webhook_receiver = require('./webhook-receiver.js');
|
|
76
86
|
var import_webhook_assertions = require('./webhook-assertions.js');
|
|
77
87
|
var import_seeding = require('./seeding.js');
|
|
88
|
+
var import_test_controller2 = require('../test-controller.js');
|
|
78
89
|
var import_fixture_resolution = require('./fixture-resolution.js');
|
|
79
90
|
var import_compliance = require('./compliance.js');
|
|
80
91
|
var import_client3 = require('../../signing/client.js');
|
|
@@ -115,7 +126,7 @@ function applyStoryboardVersionOptions(storyboard, options) {
|
|
|
115
126
|
function applyReusableProfileOptions(options) {
|
|
116
127
|
const profile = options.profile ?? options._profile;
|
|
117
128
|
if (!profile) return options;
|
|
118
|
-
const profileTools = options.agents === void 0 ? normalizeAgentToolNames(profile.tools) ?? [] : void 0;
|
|
129
|
+
const profileTools = options.agents === void 0 ? (0, import_agent_routing.normalizeAgentToolNames)(profile.tools) ?? [] : void 0;
|
|
119
130
|
return {
|
|
120
131
|
...options,
|
|
121
132
|
_profile: profile,
|
|
@@ -157,11 +168,26 @@ const DETAILED_SKIP_DETAILS = {
|
|
|
157
168
|
rate_abuse_opt_out: "Rate-abuse vector was excluded by request_signing.skipRateAbuse.",
|
|
158
169
|
capability_profile_mismatch: "Vector is outside the agent capability profile selected for this run.",
|
|
159
170
|
transport_ungradable: "Vector cannot be graded faithfully by the selected transport.",
|
|
171
|
+
signing_transport_unavailable: "Request-signing vectors have no shape this run's protocol can carry, so no verifier behavior was graded.",
|
|
160
172
|
rate_limit_not_triggered: "No RATE_LIMITED response was observed within the configured max_attempts."
|
|
161
173
|
};
|
|
162
174
|
const CANONICAL_SKIP_DETAILS = {
|
|
163
|
-
rate_limit_not_triggered: "rate_limit_not_triggered"
|
|
175
|
+
rate_limit_not_triggered: "rate_limit_not_triggered",
|
|
176
|
+
// Same shape as `rate_limit_not_triggered` above, which
|
|
177
|
+
// runner-output-contract.yaml registers under
|
|
178
|
+
// `canonical_detail_sub_reasons.not_applicable` with a test-kit
|
|
179
|
+
// `spec_source`: emit the sub-reason token *exactly* as `skip.detail`,
|
|
180
|
+
// with empty validations and no pass/fail counter movement. The
|
|
181
|
+
// operator-facing remedy travels on the probe result (`response.error`),
|
|
182
|
+
// which is where the renderers read it.
|
|
183
|
+
//
|
|
184
|
+
// Upstream ask, tracked as the remaining external blocker: register
|
|
185
|
+
// `not_applicable.signing_transport_unavailable` with
|
|
186
|
+
// `spec_source: test-kits/signed-requests-runner.yaml`. Emitting the
|
|
187
|
+
// registered *shape* now means that registration changes nothing here.
|
|
188
|
+
signing_transport_unavailable: "signing_transport_unavailable"
|
|
164
189
|
};
|
|
190
|
+
const MCP_SESSION_PROBE_REQUEST_TIMEOUT_MS = 5e3;
|
|
165
191
|
const REPLAY_WEBHOOK_VECTOR_TASK = "replay_webhook_vector";
|
|
166
192
|
const REPLAY_TRUSTED_MATCH_CONTEXT_VECTOR_TASK = "replay_trusted_match_context_vector";
|
|
167
193
|
const WEBHOOK_REPLAY_DEFAULT_TIMEOUT_MS = 1e4;
|
|
@@ -504,6 +530,42 @@ function resetClientSessions(clients) {
|
|
|
504
530
|
if (typeof reset === "function") reset.call(client);
|
|
505
531
|
}
|
|
506
532
|
}
|
|
533
|
+
async function resetControllerState(client, storyboard, options) {
|
|
534
|
+
const controller = options._controllerCapabilities;
|
|
535
|
+
if (controller?.detected !== true || !controller.scenarios.includes("reset_state")) return void 0;
|
|
536
|
+
const outcome = await (0, import_client.runStep)(
|
|
537
|
+
"Reset test-controller state",
|
|
538
|
+
"comply_test_controller",
|
|
539
|
+
() => (0, import_test_controller2.callControllerRaw)(
|
|
540
|
+
client,
|
|
541
|
+
{
|
|
542
|
+
scenario: "reset_state",
|
|
543
|
+
context: { correlation_id: `${storyboard.id}--__reset_state__` }
|
|
544
|
+
},
|
|
545
|
+
options
|
|
546
|
+
)
|
|
547
|
+
);
|
|
548
|
+
if (!outcome.step.passed) return outcome.step;
|
|
549
|
+
const raw = outcome.result;
|
|
550
|
+
const data = raw?.data;
|
|
551
|
+
if (raw?.success && data?.success === true) return void 0;
|
|
552
|
+
if (raw?.success && data?.success === false && data.error === "UNKNOWN_SCENARIO") return void 0;
|
|
553
|
+
return {
|
|
554
|
+
...outcome.step,
|
|
555
|
+
passed: false,
|
|
556
|
+
error: data?.error_detail ?? data?.error ?? raw?.error ?? "comply_test_controller reset_state failed"
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
async function resetControllerStates(targets, storyboard) {
|
|
560
|
+
const seen = /* @__PURE__ */ new Set();
|
|
561
|
+
for (const target of targets) {
|
|
562
|
+
if (seen.has(target.client)) continue;
|
|
563
|
+
seen.add(target.client);
|
|
564
|
+
const failure = await resetControllerState(target.client, storyboard, target.options);
|
|
565
|
+
if (failure) return failure;
|
|
566
|
+
}
|
|
567
|
+
return void 0;
|
|
568
|
+
}
|
|
507
569
|
function isPollEligibleEnvelope(data) {
|
|
508
570
|
if (data == null || typeof data !== "object") return false;
|
|
509
571
|
const obj = data;
|
|
@@ -623,6 +685,15 @@ function __redactSecretsForTest(value) {
|
|
|
623
685
|
function __filterResponseHeadersForTest(headers) {
|
|
624
686
|
return filterResponseHeaders(headers);
|
|
625
687
|
}
|
|
688
|
+
function __selectProtectedToolTargetForTest(tools) {
|
|
689
|
+
return selectProtectedToolTarget(tools);
|
|
690
|
+
}
|
|
691
|
+
function __protectedToolCandidatesForTest(tools) {
|
|
692
|
+
return protectedToolCandidates(tools);
|
|
693
|
+
}
|
|
694
|
+
function __sessionControlCredentialsForTest(mechanism, options, client, agentUrl) {
|
|
695
|
+
return sessionControlCredentials(mechanism, options, client, agentUrl);
|
|
696
|
+
}
|
|
626
697
|
function __defaultAuthHeadersForRawProbeForTest(options) {
|
|
627
698
|
return defaultAuthHeadersForRawProbe(options);
|
|
628
699
|
}
|
|
@@ -689,7 +760,7 @@ async function runStoryboardBody(agentUrlOrUrls, storyboard, options) {
|
|
|
689
760
|
);
|
|
690
761
|
}
|
|
691
762
|
const hasCapabilityGate = storyboardCapabilityPredicates(storyboard).length > 0;
|
|
692
|
-
const deferCapabilityAndRequires = hasCapabilityGate && options._profile === void 0;
|
|
763
|
+
const deferCapabilityAndRequires = options.agents !== void 0 || hasCapabilityGate && options._profile === void 0;
|
|
693
764
|
if (hasCapabilityGate && !deferCapabilityAndRequires) {
|
|
694
765
|
const unmetDetail = evaluateStoryboardCapabilityGates(
|
|
695
766
|
storyboard,
|
|
@@ -706,8 +777,25 @@ async function runStoryboardBody(agentUrlOrUrls, storyboard, options) {
|
|
|
706
777
|
}
|
|
707
778
|
}
|
|
708
779
|
const allRequires = resolveStoryboardRequires(storyboard, options);
|
|
709
|
-
|
|
710
|
-
|
|
780
|
+
const preflightDefersRequirement = (requirement) => {
|
|
781
|
+
switch (requirement) {
|
|
782
|
+
case "controller":
|
|
783
|
+
return options.agents !== void 0 || !options.agentTools;
|
|
784
|
+
case "request_signer":
|
|
785
|
+
return options.agents !== void 0 || !options._profile?.raw_capabilities;
|
|
786
|
+
default:
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
};
|
|
790
|
+
const firstDeferred = allRequires.findIndex(preflightDefersRequirement);
|
|
791
|
+
const earlyRequires = hasCapabilityGate ? [] : allRequires.slice(0, firstDeferred < 0 ? void 0 : firstDeferred);
|
|
792
|
+
if (earlyRequires.length && (!deferCapabilityAndRequires || options.agents && !hasCapabilityGate)) {
|
|
793
|
+
const requirementCheck = await checkRequires(
|
|
794
|
+
earlyRequires,
|
|
795
|
+
storyboard,
|
|
796
|
+
options,
|
|
797
|
+
options.agents ? void 0 : options._profile
|
|
798
|
+
);
|
|
711
799
|
if ("requirement" in requirementCheck) {
|
|
712
800
|
const resultAgentUrls = options.agents ? Object.values(options.agents).map((e) => e.url) : agentUrls;
|
|
713
801
|
return {
|
|
@@ -976,20 +1064,7 @@ function buildRequiredAnyOfToolsMissingResult(agentUrls, storyboard, detail) {
|
|
|
976
1064
|
notices: []
|
|
977
1065
|
};
|
|
978
1066
|
}
|
|
979
|
-
function
|
|
980
|
-
if (!Array.isArray(tools)) return void 0;
|
|
981
|
-
const names = [];
|
|
982
|
-
for (const tool of tools) {
|
|
983
|
-
if (typeof tool === "string") {
|
|
984
|
-
names.push(tool);
|
|
985
|
-
} else if (tool && typeof tool === "object") {
|
|
986
|
-
const name = tool.name;
|
|
987
|
-
if (typeof name === "string") names.push(name);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
return names.length > 0 ? names : void 0;
|
|
991
|
-
}
|
|
992
|
-
async function checkRequires(requires, storyboard, options, profile) {
|
|
1067
|
+
async function checkRequires(requires, storyboard, options, profile, precomputed) {
|
|
993
1068
|
let preparedPublisherAuthProbes = getPreparedTrustedMatchPublisherAuth(options);
|
|
994
1069
|
for (const requirement of requires) {
|
|
995
1070
|
if (!isKnownRequirement(requirement)) {
|
|
@@ -998,6 +1073,13 @@ async function checkRequires(requires, storyboard, options, profile) {
|
|
|
998
1073
|
detail: `Storyboard requires unknown runtime requirement '${requirement}'. This SDK does not know how to satisfy it, so the requirement is treated as unmet for forward compatibility.`
|
|
999
1074
|
};
|
|
1000
1075
|
}
|
|
1076
|
+
const established = precomputed?.get(requirement);
|
|
1077
|
+
if (established) {
|
|
1078
|
+
if (established.status === "unmet") {
|
|
1079
|
+
return { requirement: established.requirement, detail: established.detail };
|
|
1080
|
+
}
|
|
1081
|
+
continue;
|
|
1082
|
+
}
|
|
1001
1083
|
switch (requirement) {
|
|
1002
1084
|
case "controller": {
|
|
1003
1085
|
if (!options.agentTools) continue;
|
|
@@ -1159,6 +1241,28 @@ function detectImplicitRequires(storyboard, options = {}) {
|
|
|
1159
1241
|
if (needsSigner) requires.push("request_signer");
|
|
1160
1242
|
return requires;
|
|
1161
1243
|
}
|
|
1244
|
+
function probeResponseStatus(response) {
|
|
1245
|
+
if (response === null || typeof response !== "object") return 0;
|
|
1246
|
+
const status = response.status;
|
|
1247
|
+
return typeof status === "number" ? status : 0;
|
|
1248
|
+
}
|
|
1249
|
+
function signingCoverage(steps) {
|
|
1250
|
+
const probes = steps.filter((step) => step.task === import_synthesize.REQUEST_SIGNING_PROBE_TASK);
|
|
1251
|
+
if (probes.length === 0) return "not_probed";
|
|
1252
|
+
if (probes.some((step) => step.skipped !== true && probeResponseStatus(step.response) > 0 && !isProbeFault(step.response)))
|
|
1253
|
+
return "graded";
|
|
1254
|
+
if (probes.some((step) => isProbeFault(step.response))) return "probe_errored";
|
|
1255
|
+
if (probes.some((step) => step.skip_reason === "signing_transport_unavailable")) return "transport_unverified";
|
|
1256
|
+
if (probes.every((step) => step.skipped === true)) return "scope_excluded";
|
|
1257
|
+
return "self_check_only";
|
|
1258
|
+
}
|
|
1259
|
+
function isProbeFault(response) {
|
|
1260
|
+
return response !== null && typeof response === "object" && response.probe_error === true;
|
|
1261
|
+
}
|
|
1262
|
+
function signingCoverageUnverified(steps) {
|
|
1263
|
+
const coverage = signingCoverage(steps);
|
|
1264
|
+
return coverage !== "not_probed" && coverage !== "graded";
|
|
1265
|
+
}
|
|
1162
1266
|
function buildDiscoveryFailedResult(agentUrls, storyboard, discoveryStep) {
|
|
1163
1267
|
const detail = discoveryStep.error ?? "Discovery failed (no agent tools advertised).";
|
|
1164
1268
|
const syntheticStep = {
|
|
@@ -1378,7 +1482,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1378
1482
|
try {
|
|
1379
1483
|
routingContext = await (0, import_agent_routing.buildRoutingContext)(storyboard, options);
|
|
1380
1484
|
} catch (err) {
|
|
1381
|
-
const detail = err?.message ?? String(err);
|
|
1485
|
+
const detail = (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(err?.message ?? String(err));
|
|
1382
1486
|
const failedStep = {
|
|
1383
1487
|
step: err instanceof import_agent_routing.DiscoveryFailure ? `Discover agent capabilities (${err.agentKey})` : "Build agent routing index",
|
|
1384
1488
|
passed: false,
|
|
@@ -1393,13 +1497,9 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1393
1497
|
profile = [...routingContext.profiles.values()][0];
|
|
1394
1498
|
const unionedTools = /* @__PURE__ */ new Set();
|
|
1395
1499
|
for (const p of routingContext.profiles.values()) {
|
|
1396
|
-
for (const t of normalizeAgentToolNames(p.tools) ?? []) unionedTools.add(t);
|
|
1397
|
-
}
|
|
1398
|
-
if (!options.agentTools) {
|
|
1399
|
-
options = { ...options, agentTools: [...unionedTools], _profile: profile };
|
|
1400
|
-
} else if (profile && !options._profile) {
|
|
1401
|
-
options = { ...options, _profile: profile };
|
|
1500
|
+
for (const t of (0, import_agent_routing.normalizeAgentToolNames)(p.tools) ?? []) unionedTools.add(t);
|
|
1402
1501
|
}
|
|
1502
|
+
options = { ...options, agentTools: [...unionedTools], _profile: profile };
|
|
1403
1503
|
} else {
|
|
1404
1504
|
const clientResolutions = agentUrls.map((url) => (0, import_client.getOrCreateClientResolution)(url, options));
|
|
1405
1505
|
clients = clientResolutions.map((r) => r.client);
|
|
@@ -1412,7 +1512,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1412
1512
|
return buildDiscoveryFailedResult(agentUrls, storyboard, discovered.step);
|
|
1413
1513
|
}
|
|
1414
1514
|
profile = discovered.profile;
|
|
1415
|
-
const profileTools = normalizeAgentToolNames(profile?.tools);
|
|
1515
|
+
const profileTools = (0, import_agent_routing.normalizeAgentToolNames)(profile?.tools);
|
|
1416
1516
|
if (!options.agentTools && profileTools) {
|
|
1417
1517
|
options = { ...options, agentTools: profileTools, _profile: profile };
|
|
1418
1518
|
} else if (profile && !options._profile) {
|
|
@@ -1420,7 +1520,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1420
1520
|
}
|
|
1421
1521
|
} else {
|
|
1422
1522
|
profile = options._profile;
|
|
1423
|
-
const profileTools = normalizeAgentToolNames(profile?.tools);
|
|
1523
|
+
const profileTools = (0, import_agent_routing.normalizeAgentToolNames)(profile?.tools);
|
|
1424
1524
|
if (!options.agentTools && profileTools) {
|
|
1425
1525
|
options = { ...options, agentTools: profileTools, _profile: profile };
|
|
1426
1526
|
} else if (!options.agentTools && typeof clients[0]?.getAgentInfo === "function") {
|
|
@@ -1429,7 +1529,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1429
1529
|
return buildDiscoveryFailedResult(agentUrls, storyboard, discovered.step);
|
|
1430
1530
|
}
|
|
1431
1531
|
profile = discovered.profile;
|
|
1432
|
-
const discoveredTools = normalizeAgentToolNames(profile?.tools);
|
|
1532
|
+
const discoveredTools = (0, import_agent_routing.normalizeAgentToolNames)(profile?.tools);
|
|
1433
1533
|
if (discoveredTools) {
|
|
1434
1534
|
options = { ...options, agentTools: discoveredTools, _profile: profile };
|
|
1435
1535
|
} else if (profile && !options._profile) {
|
|
@@ -1438,9 +1538,126 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1438
1538
|
}
|
|
1439
1539
|
}
|
|
1440
1540
|
}
|
|
1541
|
+
if (preSeeded === void 0) {
|
|
1542
|
+
const resetTargets = routingContext && options.agents ? [...routingContext.profiles.entries()].map(([key, profile2]) => ({
|
|
1543
|
+
client: routingContext.clients.get(key),
|
|
1544
|
+
options: (0, import_agent_routing.routedAgentOptions)(options.agents[key], options, profile2)
|
|
1545
|
+
})) : clients.map((client) => ({ client, options }));
|
|
1546
|
+
const resetFailure = await resetControllerStates(resetTargets, storyboard);
|
|
1547
|
+
if (resetFailure) {
|
|
1548
|
+
if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
|
|
1549
|
+
return buildDiscoveryFailedResult(agentUrls, storyboard, resetFailure);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
const allRequires = resolveStoryboardRequires(storyboard, options);
|
|
1553
|
+
let dispatch = routingContext && options.agents ? createRoutingDispatcher(routingContext, options, options.agents) : createDispatcher(agentUrls, clients, "round-robin", dispatchOffset, profile);
|
|
1554
|
+
const routedStepCapabilitySkips = /* @__PURE__ */ new Map();
|
|
1555
|
+
const routedPhaseCapabilitySkips = /* @__PURE__ */ new Map();
|
|
1556
|
+
const routedStepRequirements = /* @__PURE__ */ new Map();
|
|
1557
|
+
const routedRootCapabilitySkips = [];
|
|
1558
|
+
const routedRootRequirementSkips = [];
|
|
1559
|
+
const routedControllerRoutes = /* @__PURE__ */ new Map();
|
|
1560
|
+
const routedErrors = /* @__PURE__ */ new Map();
|
|
1561
|
+
const reportedRoutingErrors = /* @__PURE__ */ new Set();
|
|
1562
|
+
let context = { ...storyboard.context, ...options.context };
|
|
1563
|
+
const routingFailedStep = (step, phaseId, err) => {
|
|
1564
|
+
const detail = (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(
|
|
1565
|
+
err instanceof import_agent_routing.RoutingError ? err.message : err?.message ?? String(err)
|
|
1566
|
+
);
|
|
1567
|
+
const failedAgentKey = step.agent ?? options.default_agent;
|
|
1568
|
+
const failedAgentUrl = failedAgentKey ? options.agents?.[failedAgentKey]?.url : void 0;
|
|
1569
|
+
const failedAgentIndex = failedAgentKey ? Object.keys(options.agents ?? {}).indexOf(failedAgentKey) : -1;
|
|
1570
|
+
return {
|
|
1571
|
+
storyboard_id: storyboard.id,
|
|
1572
|
+
step_id: step.id,
|
|
1573
|
+
phase_id: phaseId,
|
|
1574
|
+
title: step.title,
|
|
1575
|
+
task: step.task,
|
|
1576
|
+
passed: false,
|
|
1577
|
+
duration_ms: 0,
|
|
1578
|
+
validations: [],
|
|
1579
|
+
context,
|
|
1580
|
+
error: detail,
|
|
1581
|
+
...failedAgentUrl && { agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(failedAgentUrl) },
|
|
1582
|
+
...failedAgentIndex >= 0 && { agent_index: failedAgentIndex + 1 },
|
|
1583
|
+
extraction: { path: "none" }
|
|
1584
|
+
};
|
|
1585
|
+
};
|
|
1586
|
+
if (routingContext) {
|
|
1587
|
+
for (const phase of storyboard.phases) {
|
|
1588
|
+
for (const step of phase.steps) {
|
|
1589
|
+
if (step.task === import_loader.VALIDATION_ONLY_TASK) continue;
|
|
1590
|
+
try {
|
|
1591
|
+
const selected = dispatch.nextFor(step);
|
|
1592
|
+
const selectedOptions = selected.options;
|
|
1593
|
+
const rootDetail = evaluateStoryboardCapabilityGates(
|
|
1594
|
+
storyboard,
|
|
1595
|
+
selected.profile,
|
|
1596
|
+
selectedOptions.agentTools,
|
|
1597
|
+
options.adcpVersion
|
|
1598
|
+
);
|
|
1599
|
+
let requirementSkip;
|
|
1600
|
+
if (rootDetail === null && allRequires.includes("request_signer")) {
|
|
1601
|
+
const requirement = await checkRequires(["request_signer"], storyboard, selectedOptions, {
|
|
1602
|
+
...selected.profile,
|
|
1603
|
+
// Routed discovery is authoritative. A legacy agent without a
|
|
1604
|
+
// capabilities response did not opt into request signing.
|
|
1605
|
+
raw_capabilities: selected.profile.raw_capabilities ?? {}
|
|
1606
|
+
});
|
|
1607
|
+
if ("requirement" in requirement) {
|
|
1608
|
+
requirementSkip = requirement;
|
|
1609
|
+
routedStepRequirements.set(step, requirement.requirement);
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
const phaseDetail = phase.requires_capability ? evaluateRequiresCapabilityGate(
|
|
1613
|
+
phase.requires_capability,
|
|
1614
|
+
selected.profile,
|
|
1615
|
+
selectedOptions.agentTools,
|
|
1616
|
+
options.adcpVersion
|
|
1617
|
+
) : null;
|
|
1618
|
+
if (allRequires.includes("controller") && rootDetail === null && phaseDetail === null) {
|
|
1619
|
+
const routeKey = selected.agentKey ?? selected.agentUrl;
|
|
1620
|
+
const routeTools = selectedOptions.agentTools ?? [];
|
|
1621
|
+
const resolvedTask = (0, import_agent_routing.resolveTaskName)(step, selectedOptions) ?? step.task;
|
|
1622
|
+
const previous = routedControllerRoutes.get(routeKey);
|
|
1623
|
+
routedControllerRoutes.set(routeKey, {
|
|
1624
|
+
tools: routeTools,
|
|
1625
|
+
// A `comply_test_controller` step is the back-channel itself,
|
|
1626
|
+
// not the state under test, so it cannot vouch for the route it
|
|
1627
|
+
// is dispatched to. One state-exercising step is enough to mark
|
|
1628
|
+
// the route, whatever order the steps arrive in.
|
|
1629
|
+
stateExercising: (previous?.stateExercising ?? false) || resolvedTask !== "comply_test_controller"
|
|
1630
|
+
});
|
|
1631
|
+
}
|
|
1632
|
+
if (rootDetail !== null) routedRootCapabilitySkips.push(rootDetail);
|
|
1633
|
+
else if (requirementSkip) routedRootRequirementSkips.push(requirementSkip);
|
|
1634
|
+
const detail = rootDetail ?? requirementSkip?.detail ?? phaseDetail;
|
|
1635
|
+
if (detail !== null) routedStepCapabilitySkips.set(step, detail);
|
|
1636
|
+
} catch (error) {
|
|
1637
|
+
routedErrors.set(step, error);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
const callableSteps = phase.steps.filter((step) => step.task !== import_loader.VALIDATION_ONLY_TASK);
|
|
1641
|
+
if (callableSteps.length && callableSteps.every((step) => routedStepCapabilitySkips.has(step))) {
|
|
1642
|
+
routedPhaseCapabilitySkips.set(phase.id, routedStepCapabilitySkips.get(callableSteps[0]));
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
const routedPreflightAssignment = routingContext ? (step) => {
|
|
1647
|
+
if (routedStepCapabilitySkips.has(step)) return void 0;
|
|
1648
|
+
try {
|
|
1649
|
+
return dispatch.nextFor(step);
|
|
1650
|
+
} catch {
|
|
1651
|
+
return void 0;
|
|
1652
|
+
}
|
|
1653
|
+
} : void 0;
|
|
1441
1654
|
const preflightNotices = collectCapabilityNotices(storyboard, options._profile);
|
|
1655
|
+
const callableStepCount = storyboard.phases.reduce(
|
|
1656
|
+
(n, phase) => n + phase.steps.filter((step) => step.task !== import_loader.VALIDATION_ONLY_TASK).length,
|
|
1657
|
+
0
|
|
1658
|
+
);
|
|
1442
1659
|
if (storyboardCapabilityPredicates(storyboard).length > 0) {
|
|
1443
|
-
const unmetDetail = evaluateStoryboardCapabilityGates(storyboard, profile, options.agentTools, options.adcpVersion);
|
|
1660
|
+
const unmetDetail = routingContext ? routedRootCapabilitySkips.length > 0 && routedRootCapabilitySkips.length === callableStepCount ? routedRootCapabilitySkips[0] : null : evaluateStoryboardCapabilityGates(storyboard, profile, options.agentTools, options.adcpVersion);
|
|
1444
1661
|
if (unmetDetail !== null) {
|
|
1445
1662
|
if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
|
|
1446
1663
|
return {
|
|
@@ -1449,21 +1666,71 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1449
1666
|
};
|
|
1450
1667
|
}
|
|
1451
1668
|
}
|
|
1452
|
-
const
|
|
1669
|
+
const establishedRequirements = /* @__PURE__ */ new Map();
|
|
1670
|
+
if (routingContext && allRequires.includes("controller")) {
|
|
1671
|
+
const decided = [...routedControllerRoutes].filter(([, route]) => route.stateExercising);
|
|
1672
|
+
const routes = decided.length > 0 ? decided : [...routedControllerRoutes];
|
|
1673
|
+
if (routedErrors.size > 0 || routes.length === 0) {
|
|
1674
|
+
establishedRequirements.set("controller", { status: "unknown" });
|
|
1675
|
+
} else if (routes.some(([, route]) => route.tools.includes("comply_test_controller"))) {
|
|
1676
|
+
establishedRequirements.set("controller", { status: "met" });
|
|
1677
|
+
} else {
|
|
1678
|
+
const exercised = routes.map(([key]) => key);
|
|
1679
|
+
const exercisedKeys = new Set(exercised);
|
|
1680
|
+
const peersWithController = [...routingContext.profiles.entries()].filter(
|
|
1681
|
+
([key, peer]) => !exercisedKeys.has(key) && (0, import_agent_routing.normalizeAgentToolNames)(peer.tools)?.includes("comply_test_controller")
|
|
1682
|
+
).map(([key]) => key);
|
|
1683
|
+
establishedRequirements.set("controller", {
|
|
1684
|
+
status: "unmet",
|
|
1685
|
+
requirement: "controller",
|
|
1686
|
+
detail: `Storyboard requires 'controller'; no route serving this storyboard's steps advertises comply_test_controller. Route(s) exercised: [${exercised.join(", ")}]. ` + (peersWithController.length ? `Agent(s) [${peersWithController.join(", ")}] in this map do advertise it, but a peer route's controller cannot seed another route's state \u2014 a run-level tool union does not grant it. ` : "") + `Add comply_test_controller to the route that owns the state, or pin the seeding step to that route with 'agent:'.`
|
|
1687
|
+
});
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
if (routingContext && allRequires.includes("request_signer")) {
|
|
1691
|
+
establishedRequirements.set(
|
|
1692
|
+
"request_signer",
|
|
1693
|
+
routedErrors.size === 0 && routedRootRequirementSkips.length > 0 && routedRootRequirementSkips.length === callableStepCount ? { status: "unmet", ...routedRootRequirementSkips[0] } : { status: "unknown" }
|
|
1694
|
+
);
|
|
1695
|
+
}
|
|
1453
1696
|
if (allRequires.length) {
|
|
1454
|
-
const requirementCheck = await checkRequires(
|
|
1697
|
+
const requirementCheck = await checkRequires(
|
|
1698
|
+
allRequires,
|
|
1699
|
+
storyboard,
|
|
1700
|
+
options,
|
|
1701
|
+
routingContext ? void 0 : profile,
|
|
1702
|
+
establishedRequirements
|
|
1703
|
+
);
|
|
1455
1704
|
if ("requirement" in requirementCheck) {
|
|
1456
1705
|
if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1706
|
+
const result2 = buildRequirementUnmetResult(
|
|
1707
|
+
agentUrls,
|
|
1708
|
+
storyboard,
|
|
1709
|
+
requirementCheck.requirement,
|
|
1710
|
+
requirementCheck.detail
|
|
1711
|
+
);
|
|
1712
|
+
for (const phase of storyboard.phases) {
|
|
1713
|
+
const failures = phase.steps.filter((step) => routedErrors.has(step)).map((step) => routingFailedStep(step, phase.id, routedErrors.get(step)));
|
|
1714
|
+
if (failures.length) {
|
|
1715
|
+
result2.phases.push({
|
|
1716
|
+
phase_id: phase.id,
|
|
1717
|
+
phase_title: phase.title,
|
|
1718
|
+
passed: false,
|
|
1719
|
+
steps: failures,
|
|
1720
|
+
duration_ms: 0
|
|
1721
|
+
});
|
|
1722
|
+
result2.failed_count += failures.length;
|
|
1723
|
+
result2.overall_passed = false;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
return { ...result2, notices: preflightNotices };
|
|
1461
1727
|
}
|
|
1462
1728
|
if (requirementCheck.preparedPublisherAuthProbes) {
|
|
1463
1729
|
options = withPreparedTrustedMatchPublisherAuth(options, requirementCheck.preparedPublisherAuthProbes);
|
|
1730
|
+
if (routingContext && options.agents) dispatch = createRoutingDispatcher(routingContext, options, options.agents);
|
|
1464
1731
|
}
|
|
1465
1732
|
}
|
|
1466
|
-
if (storyboard.required_any_of_tools?.length && options.agentTools) {
|
|
1733
|
+
if (storyboard.required_any_of_tools?.length && options.agentTools && !routingContext?.discoveryFailures.length && routedErrors.size === 0) {
|
|
1467
1734
|
const agentTools = new Set(options.agentTools);
|
|
1468
1735
|
const missing = storyboard.required_any_of_tools.find((family) => !family.tools.some((tool) => agentTools.has(tool)));
|
|
1469
1736
|
if (missing) {
|
|
@@ -1475,8 +1742,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1475
1742
|
};
|
|
1476
1743
|
}
|
|
1477
1744
|
}
|
|
1478
|
-
if (storyboard.required_tools?.length && options.agentTools) {
|
|
1479
|
-
const hasAnyRequired = storyboard.required_tools
|
|
1745
|
+
if (storyboard.required_tools?.length && options.agentTools && !routingContext?.discoveryFailures.length && routedErrors.size === 0) {
|
|
1746
|
+
const hasAnyRequired = (0, import_agent_routing.hasAnyRequiredTool)(storyboard.required_tools, options.agentTools);
|
|
1480
1747
|
if (!hasAnyRequired) {
|
|
1481
1748
|
if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
|
|
1482
1749
|
return {
|
|
@@ -1489,18 +1756,26 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1489
1756
|
};
|
|
1490
1757
|
}
|
|
1491
1758
|
}
|
|
1492
|
-
let context = { ...storyboard.context, ...options.context };
|
|
1493
1759
|
if (storyboard.context) (0, import_context.forwardAliasCache)(storyboard.context, context);
|
|
1494
1760
|
if (options.context) (0, import_context.forwardAliasCache)(options.context, context);
|
|
1495
1761
|
const contributions = /* @__PURE__ */ new Set();
|
|
1496
1762
|
const contributionSources = /* @__PURE__ */ new Map();
|
|
1497
1763
|
const priorStepResults = /* @__PURE__ */ new Map();
|
|
1498
1764
|
const priorProbes = /* @__PURE__ */ new Map();
|
|
1765
|
+
const routedPriorProbes = /* @__PURE__ */ new Map();
|
|
1499
1766
|
const contextProvenance = /* @__PURE__ */ new Map();
|
|
1500
1767
|
const priorA2aEnvelopes = /* @__PURE__ */ new Map();
|
|
1501
1768
|
const stepRequestStarts = /* @__PURE__ */ new Map();
|
|
1502
1769
|
const responseDerivedNotApplicableContextKeys = /* @__PURE__ */ new Map();
|
|
1503
1770
|
const capabilityUnavailableContextKeysByPhase = /* @__PURE__ */ new Map();
|
|
1771
|
+
const missingPrerequisiteContextKeysByPhase = /* @__PURE__ */ new Map();
|
|
1772
|
+
const recordUnavailableOutputs = (phaseId, step, keysByPhase = capabilityUnavailableContextKeysByPhase) => {
|
|
1773
|
+
const keys = keysByPhase.get(phaseId) ?? /* @__PURE__ */ new Set();
|
|
1774
|
+
for (const output of step.context_outputs ?? []) {
|
|
1775
|
+
if (output.key) keys.add(output.key);
|
|
1776
|
+
}
|
|
1777
|
+
keysByPhase.set(phaseId, keys);
|
|
1778
|
+
};
|
|
1504
1779
|
const phaseResults = [];
|
|
1505
1780
|
let passedCount = 0;
|
|
1506
1781
|
let failedCount = 0;
|
|
@@ -1511,28 +1786,31 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1511
1786
|
const branchSetsByPhaseId = resolveBranchSets(storyboard);
|
|
1512
1787
|
const effectiveDependsOn = (phase, prior) => phase.depends_on ?? prior;
|
|
1513
1788
|
const cascadeForPhase = (phase, prior) => {
|
|
1514
|
-
if (phaseStatefulCascades.has(phase.id)) {
|
|
1515
|
-
return { tripped: true, trigger: phaseStatefulCascades.get(phase.id) ?? null };
|
|
1516
|
-
}
|
|
1517
1789
|
const ownSpec = branchSetsByPhaseId.get(phase.id);
|
|
1518
1790
|
const ownAnyOfBranchSet = ownSpec?.semantics === "any_of" ? ownSpec.id : void 0;
|
|
1519
|
-
|
|
1520
|
-
|
|
1791
|
+
let capabilityTrigger;
|
|
1792
|
+
let missingStateTrigger;
|
|
1793
|
+
for (const depId of [phase.id, ...effectiveDependsOn(phase, prior)]) {
|
|
1794
|
+
if (depId !== phase.id && ownAnyOfBranchSet !== void 0 && branchSetsByPhaseId.get(depId)?.id === ownAnyOfBranchSet) {
|
|
1521
1795
|
continue;
|
|
1522
1796
|
}
|
|
1523
1797
|
if (phaseStatefulCascades.has(depId)) {
|
|
1524
|
-
|
|
1798
|
+
const trigger2 = phaseStatefulCascades.get(depId) ?? null;
|
|
1799
|
+
if (trigger2 === null) return { tripped: true, trigger: null };
|
|
1800
|
+
if (trigger2.capabilityUnavailable) capabilityTrigger ??= trigger2;
|
|
1801
|
+
else missingStateTrigger ??= trigger2;
|
|
1525
1802
|
}
|
|
1526
1803
|
}
|
|
1527
|
-
|
|
1804
|
+
const trigger = missingStateTrigger ?? capabilityTrigger;
|
|
1805
|
+
return trigger ? { tripped: true, trigger } : { tripped: false };
|
|
1528
1806
|
};
|
|
1529
|
-
const
|
|
1530
|
-
const keys =
|
|
1807
|
+
const unavailableContextKeysForPhase = (phase, prior, keysByPhase = capabilityUnavailableContextKeysByPhase) => {
|
|
1808
|
+
const keys = new Set(keysByPhase.get(phase.id));
|
|
1531
1809
|
const ownSpec = branchSetsByPhaseId.get(phase.id);
|
|
1532
1810
|
const ownAnyOfBranchSet = ownSpec?.semantics === "any_of" ? ownSpec.id : void 0;
|
|
1533
1811
|
for (const depId of effectiveDependsOn(phase, prior)) {
|
|
1534
1812
|
if (ownAnyOfBranchSet !== void 0 && branchSetsByPhaseId.get(depId)?.id === ownAnyOfBranchSet) continue;
|
|
1535
|
-
for (const key of
|
|
1813
|
+
for (const key of keysByPhase.get(depId) ?? []) keys.add(key);
|
|
1536
1814
|
}
|
|
1537
1815
|
return keys;
|
|
1538
1816
|
};
|
|
@@ -1550,7 +1828,6 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1550
1828
|
});
|
|
1551
1829
|
if (webhookReceiver) (0, import_webhook_assertions.armWebhookAssertions)(storyboard, runnerVars, webhookReceiver);
|
|
1552
1830
|
const allSteps = flattenSteps(storyboard);
|
|
1553
|
-
const dispatch = routingContext && options.agents ? createRoutingDispatcher(routingContext, options, options.agents) : createDispatcher(agentUrls, clients, "round-robin", dispatchOffset, profile);
|
|
1554
1831
|
const assertions = (0, import_assertions.resolveAssertions)(storyboard.invariants);
|
|
1555
1832
|
(0, import_assertions.validateStepInvariants)(storyboard, assertions);
|
|
1556
1833
|
const assertionContexts = /* @__PURE__ */ new Map();
|
|
@@ -1568,12 +1845,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1568
1845
|
if (spec.onStart) await spec.onStart(assertionContexts.get(spec.id));
|
|
1569
1846
|
}
|
|
1570
1847
|
const hasExecutableSteps = storyboard.phases.some((p) => p.steps.length > 0);
|
|
1571
|
-
const phaseCapabilitySkipDetails = collectPhaseCapabilitySkipDetails(
|
|
1572
|
-
storyboard,
|
|
1573
|
-
profile,
|
|
1574
|
-
options.agentTools,
|
|
1575
|
-
options.adcpVersion
|
|
1576
|
-
);
|
|
1848
|
+
const phaseCapabilitySkipDetails = routingContext ? routedPhaseCapabilitySkips : collectPhaseCapabilitySkipDetails(storyboard, profile, options.agentTools, options.adcpVersion);
|
|
1577
1849
|
const skipControllerSeedingForPhaseGates = allExecutablePhasesCapabilitySkipped(
|
|
1578
1850
|
storyboard,
|
|
1579
1851
|
phaseCapabilitySkipDetails
|
|
@@ -1604,7 +1876,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1604
1876
|
storyboardRequiresRequestSigner: allRequires.includes("request_signer"),
|
|
1605
1877
|
storyboardRequiresPublisherAuthRunner: storyboard.requires?.includes("trusted_match_publisher_auth_runner") === true
|
|
1606
1878
|
},
|
|
1607
|
-
preflightExcludedPhaseIds
|
|
1879
|
+
preflightExcludedPhaseIds,
|
|
1880
|
+
routedPreflightAssignment
|
|
1608
1881
|
);
|
|
1609
1882
|
let creativeAssetFixtureGapRecorded = false;
|
|
1610
1883
|
if (!hasExecutableSteps) {
|
|
@@ -1649,22 +1922,36 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1649
1922
|
let fixtureResolutionRecords;
|
|
1650
1923
|
let fixtureCoverageGap;
|
|
1651
1924
|
{
|
|
1652
|
-
let
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1925
|
+
let seeding;
|
|
1926
|
+
try {
|
|
1927
|
+
seeding = creativeAssetFixtureGap || skipControllerSeedingForPhaseGates ? null : preSeeded !== void 0 ? preSeeded.result : await (0, import_seeding.runControllerSeeding)(
|
|
1928
|
+
clients[0],
|
|
1929
|
+
storyboard,
|
|
1930
|
+
options,
|
|
1931
|
+
context,
|
|
1932
|
+
clients[0],
|
|
1933
|
+
routingContext ? (task) => {
|
|
1934
|
+
if (!options.agentTools?.includes(task))
|
|
1935
|
+
return { client: clients[0], options: { ...options, agentTools: [] } };
|
|
1936
|
+
const selected = dispatch.nextFor({
|
|
1937
|
+
id: `__fixture_resolution_${task}__`,
|
|
1938
|
+
title: `Fixture resolution via ${task}`,
|
|
1939
|
+
task
|
|
1940
|
+
});
|
|
1941
|
+
return { client: selected.client, options: selected.options };
|
|
1942
|
+
} : void 0
|
|
1943
|
+
);
|
|
1944
|
+
} catch (error) {
|
|
1945
|
+
if (webhookReceiver) await webhookReceiver.close();
|
|
1946
|
+
if (!(error instanceof import_agent_routing.RoutingError)) throw error;
|
|
1947
|
+
if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
|
|
1948
|
+
return buildDiscoveryFailedResult(agentUrls, storyboard, {
|
|
1949
|
+
step: "Resolve fixture agent routes",
|
|
1950
|
+
passed: false,
|
|
1951
|
+
duration_ms: 0,
|
|
1952
|
+
error: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(error.message)
|
|
1659
1953
|
});
|
|
1660
|
-
if (options.agentTools?.includes("comply_test_controller")) {
|
|
1661
|
-
fixtureSeedClient = dispatch.nextFor(fixtureStep("comply_test_controller")).client;
|
|
1662
|
-
}
|
|
1663
|
-
if (options.agentTools?.includes("get_products")) {
|
|
1664
|
-
fixtureDiscoveryClient = dispatch.nextFor(fixtureStep("get_products")).client;
|
|
1665
|
-
}
|
|
1666
1954
|
}
|
|
1667
|
-
const seeding = creativeAssetFixtureGap ? null : skipControllerSeedingForPhaseGates ? null : preSeeded !== void 0 ? preSeeded.result : await (0, import_seeding.runControllerSeeding)(fixtureSeedClient, storyboard, options, context, fixtureDiscoveryClient);
|
|
1668
1955
|
if (seeding) {
|
|
1669
1956
|
const attach = preSeeded === void 0 || preSeeded.attach;
|
|
1670
1957
|
if (attach) {
|
|
@@ -1736,7 +2023,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1736
2023
|
context,
|
|
1737
2024
|
options,
|
|
1738
2025
|
buildExecutionState(),
|
|
1739
|
-
preflightExcludedPhaseIds
|
|
2026
|
+
preflightExcludedPhaseIds,
|
|
2027
|
+
routedPreflightAssignment
|
|
1740
2028
|
);
|
|
1741
2029
|
}
|
|
1742
2030
|
for (const phase of storyboard.phases) {
|
|
@@ -1781,7 +2069,25 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1781
2069
|
}
|
|
1782
2070
|
const phaseCapabilitySkipDetail = phaseCapabilitySkipDetails.get(phase.id);
|
|
1783
2071
|
if (phaseCapabilitySkipDetail !== void 0) {
|
|
1784
|
-
const skippedSteps =
|
|
2072
|
+
const skippedSteps = routingContext ? phase.steps.map((step) => {
|
|
2073
|
+
const selected = step.task === import_loader.VALIDATION_ONLY_TASK ? void 0 : dispatch.nextFor(step);
|
|
2074
|
+
const skipped = buildPhaseCapabilitySkippedSteps(
|
|
2075
|
+
storyboard,
|
|
2076
|
+
{ ...phase, steps: [step] },
|
|
2077
|
+
routedStepCapabilitySkips.get(step) ?? phaseCapabilitySkipDetail,
|
|
2078
|
+
context
|
|
2079
|
+
)[0];
|
|
2080
|
+
return {
|
|
2081
|
+
...skipped,
|
|
2082
|
+
...routedStepRequirements.has(step) && {
|
|
2083
|
+
skip: { ...skipped.skip, requirement: routedStepRequirements.get(step) }
|
|
2084
|
+
},
|
|
2085
|
+
...selected && {
|
|
2086
|
+
agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(selected.agentUrl),
|
|
2087
|
+
agent_index: selected.instanceIndex + 1
|
|
2088
|
+
}
|
|
2089
|
+
};
|
|
2090
|
+
}) : buildPhaseCapabilitySkippedSteps(storyboard, phase, phaseCapabilitySkipDetail, context);
|
|
1785
2091
|
phaseResults.push({
|
|
1786
2092
|
phase_id: phase.id,
|
|
1787
2093
|
phase_title: phase.title,
|
|
@@ -1791,13 +2097,9 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1791
2097
|
});
|
|
1792
2098
|
skippedCount += skippedSteps.length;
|
|
1793
2099
|
phaseCapabilitySkippedIds.add(phase.id);
|
|
1794
|
-
const unavailableKeys = /* @__PURE__ */ new Set();
|
|
1795
2100
|
for (const step of phase.steps) {
|
|
1796
|
-
|
|
1797
|
-
if (output.key) unavailableKeys.add(output.key);
|
|
1798
|
-
}
|
|
2101
|
+
recordUnavailableOutputs(phase.id, step);
|
|
1799
2102
|
}
|
|
1800
|
-
capabilityUnavailableContextKeysByPhase.set(phase.id, unavailableKeys);
|
|
1801
2103
|
if (phase.steps.some((s) => s.stateful)) {
|
|
1802
2104
|
phaseStatefulCascades.set(phase.id, {
|
|
1803
2105
|
stepId: phase.steps.find((s) => s.stateful).id,
|
|
@@ -1811,6 +2113,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1811
2113
|
const stepResults = [];
|
|
1812
2114
|
let phasePassed = true;
|
|
1813
2115
|
let phasePendingNotApplicable = null;
|
|
2116
|
+
let phaseInheritedCapabilityTrigger;
|
|
1814
2117
|
let phaseEstablishedStatefulState = false;
|
|
1815
2118
|
const phaseSubstitutes = /* @__PURE__ */ new Map();
|
|
1816
2119
|
for (const declaringStep of phase.steps) {
|
|
@@ -1823,13 +2126,27 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1823
2126
|
phaseSubstitutes.set(target, arr);
|
|
1824
2127
|
}
|
|
1825
2128
|
}
|
|
1826
|
-
|
|
2129
|
+
const phasePendingMissingTool = { trigger: null };
|
|
1827
2130
|
const phaseRescuedTargets = /* @__PURE__ */ new Set();
|
|
1828
2131
|
const phaseRescueSource = /* @__PURE__ */ new Map();
|
|
1829
2132
|
const phaseStatefulStepIds = phase.steps.filter((s) => s.stateful).map((s) => s.id);
|
|
1830
2133
|
let phaseAbsent = false;
|
|
2134
|
+
const routedOauthAbsent = /* @__PURE__ */ new Set();
|
|
1831
2135
|
let presenceDetected = false;
|
|
2136
|
+
const routedOauthPresent = /* @__PURE__ */ new Set();
|
|
1832
2137
|
if (shouldSkipPhase(phase, options, context)) {
|
|
2138
|
+
const skippedRoutingFailures = routingContext ? phase.steps.filter((step) => routedErrors.has(step)) : [];
|
|
2139
|
+
const skippedCapabilitySteps = routingContext ? phase.steps.filter((step) => routedStepCapabilitySkips.has(step)) : [];
|
|
2140
|
+
for (const step of skippedCapabilitySteps) recordUnavailableOutputs(phase.id, step);
|
|
2141
|
+
if (skippedRoutingFailures.length > 0) {
|
|
2142
|
+
for (const step of skippedRoutingFailures) {
|
|
2143
|
+
recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
|
|
2144
|
+
}
|
|
2145
|
+
if (skippedRoutingFailures.some((step) => step.stateful)) phaseStatefulCascades.set(phase.id, null);
|
|
2146
|
+
}
|
|
2147
|
+
if (skippedRoutingFailures.length > 0 || skippedCapabilitySteps.length > 0) {
|
|
2148
|
+
priorPhaseIds.push(phase.id);
|
|
2149
|
+
}
|
|
1833
2150
|
phaseResults.push({
|
|
1834
2151
|
phase_id: phase.id,
|
|
1835
2152
|
phase_title: phase.title,
|
|
@@ -1849,7 +2166,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1849
2166
|
context,
|
|
1850
2167
|
options,
|
|
1851
2168
|
buildExecutionState(),
|
|
1852
|
-
preflightExcludedPhaseIds
|
|
2169
|
+
preflightExcludedPhaseIds,
|
|
2170
|
+
routedPreflightAssignment
|
|
1853
2171
|
);
|
|
1854
2172
|
if (creativeAssetFixtureGap?.target.phaseId === phase.id) {
|
|
1855
2173
|
const gapStep = buildCreativeAssetFixtureUnavailableStep(
|
|
@@ -1875,7 +2193,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1875
2193
|
continue;
|
|
1876
2194
|
}
|
|
1877
2195
|
}
|
|
1878
|
-
if (!
|
|
2196
|
+
if (!routingContext && phaseContainsOauthMetadataProbe(phase) && !agentAdvertisesOauth(profile)) {
|
|
1879
2197
|
phaseAbsent = true;
|
|
1880
2198
|
}
|
|
1881
2199
|
context = { ...context };
|
|
@@ -1917,9 +2235,66 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1917
2235
|
skippedCount += cascadeSteps.length;
|
|
1918
2236
|
continue;
|
|
1919
2237
|
}
|
|
2238
|
+
const recordHardPrerequisiteFailure = (step, realFailure = false) => {
|
|
2239
|
+
if (realFailure) {
|
|
2240
|
+
phaseStatefulCascades.set(phase.id, null);
|
|
2241
|
+
} else if (!phaseStatefulCascades.has(phase.id) || phaseStatefulCascades.get(phase.id)?.capabilityUnavailable === true) {
|
|
2242
|
+
phaseStatefulCascades.set(phase.id, { stepId: step.id, reason: "prerequisite_failed" });
|
|
2243
|
+
}
|
|
2244
|
+
};
|
|
2245
|
+
const recordHardMissingState = (step, result2) => {
|
|
2246
|
+
const substitutes = phaseSubstitutes.get(step.id);
|
|
2247
|
+
if (substitutes && substitutes.length > 0) {
|
|
2248
|
+
if (phasePendingMissingTool.trigger === null) {
|
|
2249
|
+
phasePendingMissingTool.trigger = {
|
|
2250
|
+
stepId: step.id,
|
|
2251
|
+
reason: result2.skip_reason ?? "missing_tool",
|
|
2252
|
+
substitutes
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
} else {
|
|
2256
|
+
const hasStatefulPeers = phaseStatefulStepIds.length > 1;
|
|
2257
|
+
if (hasStatefulPeers && !phaseStatefulCascades.has(phase.id)) {
|
|
2258
|
+
phaseStatefulCascades.set(phase.id, {
|
|
2259
|
+
stepId: step.id,
|
|
2260
|
+
reason: result2.skip_reason ?? "missing_tool"
|
|
2261
|
+
});
|
|
2262
|
+
} else if (!hasStatefulPeers && result2.skip) {
|
|
2263
|
+
result2.skip = {
|
|
2264
|
+
...result2.skip,
|
|
2265
|
+
detail: result2.skip.detail + soleStatefulExemptionDetail(phase.id)
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
};
|
|
1920
2270
|
for (const step of phase.steps) {
|
|
1921
2271
|
options.signal?.throwIfAborted();
|
|
1922
|
-
if (
|
|
2272
|
+
if (routingContext && step.task === import_loader.VALIDATION_ONLY_TASK) {
|
|
2273
|
+
const result3 = validationOnlyCoverageGap(step, phase.id, context, allSteps, runnerVars, storyboard.id);
|
|
2274
|
+
stepResults.push(result3);
|
|
2275
|
+
priorStepResults.set(step.id, result3);
|
|
2276
|
+
skippedCount++;
|
|
2277
|
+
continue;
|
|
2278
|
+
}
|
|
2279
|
+
let assignment;
|
|
2280
|
+
try {
|
|
2281
|
+
if (routingContext) assignment = dispatch.nextFor(step);
|
|
2282
|
+
} catch (err) {
|
|
2283
|
+
const failed = routingFailedStep(step, phase.id, err);
|
|
2284
|
+
reportedRoutingErrors.add(step);
|
|
2285
|
+
stepResults.push(failed);
|
|
2286
|
+
countedAsFailed.add(failed);
|
|
2287
|
+
priorStepResults.set(step.id, failed);
|
|
2288
|
+
failedCount++;
|
|
2289
|
+
phasePassed = false;
|
|
2290
|
+
recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
|
|
2291
|
+
if (step.stateful) phaseStatefulCascades.set(phase.id, null);
|
|
2292
|
+
continue;
|
|
2293
|
+
}
|
|
2294
|
+
if (routingContext && assignment && phaseContainsOauthMetadataProbe(phase) && !agentAdvertisesOauth(assignment.profile)) {
|
|
2295
|
+
routedOauthAbsent.add(assignment.instanceIndex);
|
|
2296
|
+
}
|
|
2297
|
+
if ((phaseAbsent || assignment && routedOauthAbsent.has(assignment.instanceIndex)) && !routedStepCapabilitySkips.has(step)) {
|
|
1923
2298
|
const cascadeResult = {
|
|
1924
2299
|
storyboard_id: storyboard.id,
|
|
1925
2300
|
step_id: step.id,
|
|
@@ -1940,21 +2315,25 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1940
2315
|
skippedCount++;
|
|
1941
2316
|
continue;
|
|
1942
2317
|
}
|
|
2318
|
+
const selectedOptions = assignment?.options ?? options;
|
|
2319
|
+
const routedCapabilityDetail = routedStepCapabilitySkips.get(step);
|
|
1943
2320
|
const cascade = step.stateful ? cascadeForPhase(phase, priorPhaseIds) : { tripped: false };
|
|
1944
|
-
if (cascade.tripped && step.stateful) {
|
|
1945
|
-
const resolvedTask = resolveTaskName(step,
|
|
1946
|
-
|
|
1947
|
-
|
|
2321
|
+
if (cascade.tripped && step.stateful && routedCapabilityDetail === void 0) {
|
|
2322
|
+
const resolvedTask = (0, import_agent_routing.resolveTaskName)(step, selectedOptions);
|
|
2323
|
+
const missingTool = selectedOptions.agentTools && (routingContext && step.requires_tool && !selectedOptions.agentTools.includes(step.requires_tool) ? step.requires_tool : resolvedTask && resolvedTask !== import_types.MCP_SESSION_PROBE_TASK && !selectedOptions.agentTools.includes(resolvedTask) ? resolvedTask : void 0);
|
|
2324
|
+
if (missingTool) {
|
|
2325
|
+
const missingReason = routingContext && missingTool === "comply_test_controller" ? "missing_test_controller" : "missing_tool";
|
|
2326
|
+
const toolDetail = `Agent did not advertise tool "${missingTool}"; agent tools: [${selectedOptions.agentTools.join(", ")}].`;
|
|
1948
2327
|
const missingToolResult = {
|
|
1949
2328
|
storyboard_id: storyboard.id,
|
|
1950
2329
|
step_id: step.id,
|
|
1951
2330
|
phase_id: phase.id,
|
|
1952
2331
|
title: step.title,
|
|
1953
|
-
task: resolvedTask,
|
|
2332
|
+
task: resolvedTask ?? step.task,
|
|
1954
2333
|
passed: true,
|
|
1955
2334
|
skipped: true,
|
|
1956
|
-
skip_reason:
|
|
1957
|
-
skip: buildSkip(
|
|
2335
|
+
skip_reason: missingReason,
|
|
2336
|
+
skip: buildSkip(missingReason, toolDetail),
|
|
1958
2337
|
duration_ms: 0,
|
|
1959
2338
|
validations: [],
|
|
1960
2339
|
context,
|
|
@@ -1962,12 +2341,42 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1962
2341
|
};
|
|
1963
2342
|
stepResults.push(missingToolResult);
|
|
1964
2343
|
priorStepResults.set(step.id, missingToolResult);
|
|
2344
|
+
if (routingContext) {
|
|
2345
|
+
recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
|
|
2346
|
+
recordHardMissingState(step, missingToolResult);
|
|
2347
|
+
}
|
|
1965
2348
|
skippedCount++;
|
|
1966
2349
|
continue;
|
|
1967
2350
|
}
|
|
1968
2351
|
const trigger = cascade.trigger;
|
|
1969
|
-
|
|
1970
|
-
|
|
2352
|
+
let detail = trigger ? trigger.substitution_chain ? `Skipped: prior stateful step "${trigger.stepId}" skipped (${trigger.reason}); ${trigger.substitution_chain}; state never materialized.` : `Skipped: prior stateful step "${trigger.stepId}" skipped (${trigger.reason}); state never materialized.` : "Skipped: prior stateful step failed.";
|
|
2353
|
+
let capabilityUnavailable = trigger?.capabilityUnavailable === true;
|
|
2354
|
+
if (capabilityUnavailable && routingContext && !import_trusted_match_publisher_auth.TRUSTED_MATCH_PUBLISHER_AUTH_TASKS.has(step.task) && !import_probes.PROBE_TASKS.has(step.task) && !import_webhook_assertions.WEBHOOK_ASSERTION_TASKS.has(step.task) && step.task !== REPLAY_WEBHOOK_VECTOR_TASK && (!step.requires_contract || (selectedOptions.contracts ?? []).includes(step.requires_contract))) {
|
|
2355
|
+
const hardKeys = unavailableContextKeysForPhase(phase, priorPhaseIds, missingPrerequisiteContextKeysByPhase);
|
|
2356
|
+
if (hardKeys.size > 0) {
|
|
2357
|
+
const effectiveRequest = buildEffectiveStepRequest(
|
|
2358
|
+
{ ...step, task: resolvedTask ?? step.task },
|
|
2359
|
+
context,
|
|
2360
|
+
selectedOptions,
|
|
2361
|
+
buildExecutionState(assignment?.agentUrl, assignment?.profile)
|
|
2362
|
+
);
|
|
2363
|
+
const missingKeys = /* @__PURE__ */ new Set([
|
|
2364
|
+
...(effectiveRequest.ok ? findUnresolvedContextVars(effectiveRequest.request) : []).filter((v) => hardKeys.has(v.key)).map((v) => v.key),
|
|
2365
|
+
...(step.context_inputs ?? []).filter((input) => !(input.key in context) && hardKeys.has(input.key)).map((input) => input.key)
|
|
2366
|
+
]);
|
|
2367
|
+
if (missingKeys.size > 0) {
|
|
2368
|
+
capabilityUnavailable = false;
|
|
2369
|
+
detail = `Skipped: context required from a failed or unavailable prerequisite is missing: ${[...missingKeys].join(", ")}.`;
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
if (capabilityUnavailable) {
|
|
2374
|
+
recordUnavailableOutputs(phase.id, step);
|
|
2375
|
+
if (routingContext) phaseInheritedCapabilityTrigger ??= trigger ?? void 0;
|
|
2376
|
+
} else if (routingContext) {
|
|
2377
|
+
recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
|
|
2378
|
+
recordHardPrerequisiteFailure(step, trigger === null);
|
|
2379
|
+
}
|
|
1971
2380
|
stepResults.push({
|
|
1972
2381
|
storyboard_id: storyboard.id,
|
|
1973
2382
|
step_id: step.id,
|
|
@@ -1995,46 +2404,47 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1995
2404
|
skippedCount++;
|
|
1996
2405
|
continue;
|
|
1997
2406
|
}
|
|
1998
|
-
|
|
1999
|
-
try {
|
|
2000
|
-
assignment = dispatch.nextFor(step);
|
|
2001
|
-
} catch (err) {
|
|
2002
|
-
const detail = err instanceof import_agent_routing.RoutingError ? err.message : err?.message ?? String(err);
|
|
2003
|
-
const failed = {
|
|
2004
|
-
storyboard_id: storyboard.id,
|
|
2005
|
-
step_id: step.id,
|
|
2006
|
-
phase_id: phase.id,
|
|
2007
|
-
title: step.title,
|
|
2008
|
-
task: step.task,
|
|
2009
|
-
passed: false,
|
|
2010
|
-
duration_ms: 0,
|
|
2011
|
-
validations: [],
|
|
2012
|
-
context,
|
|
2013
|
-
error: detail,
|
|
2014
|
-
extraction: { path: "none" }
|
|
2015
|
-
};
|
|
2016
|
-
stepResults.push(failed);
|
|
2017
|
-
priorStepResults.set(step.id, failed);
|
|
2018
|
-
failedCount++;
|
|
2019
|
-
phasePassed = false;
|
|
2020
|
-
continue;
|
|
2021
|
-
}
|
|
2407
|
+
assignment ??= dispatch.nextFor(step);
|
|
2022
2408
|
const stepExecutionState = buildExecutionState(assignment.agentUrl, assignment.profile);
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2409
|
+
if (routingContext) {
|
|
2410
|
+
let probes = routedPriorProbes.get(assignment.instanceIndex);
|
|
2411
|
+
if (!probes) {
|
|
2412
|
+
probes = /* @__PURE__ */ new Map();
|
|
2413
|
+
routedPriorProbes.set(assignment.instanceIndex, probes);
|
|
2414
|
+
}
|
|
2415
|
+
stepExecutionState.priorProbes = probes;
|
|
2416
|
+
stepExecutionState.allowPriorProbeFallback = false;
|
|
2417
|
+
}
|
|
2418
|
+
stepExecutionState.capabilityUnavailableContextKeys = unavailableContextKeysForPhase(phase, priorPhaseIds);
|
|
2419
|
+
if (routingContext) {
|
|
2420
|
+
stepExecutionState.missingPrerequisiteContextKeys = unavailableContextKeysForPhase(
|
|
2421
|
+
phase,
|
|
2422
|
+
priorPhaseIds,
|
|
2423
|
+
missingPrerequisiteContextKeysByPhase
|
|
2424
|
+
);
|
|
2425
|
+
}
|
|
2426
|
+
const rawResult = routedCapabilityDetail !== void 0 ? buildPhaseCapabilitySkippedSteps(
|
|
2427
|
+
storyboard,
|
|
2428
|
+
{ ...phase, steps: [step] },
|
|
2429
|
+
routedCapabilityDetail,
|
|
2430
|
+
context
|
|
2431
|
+
)[0] : await executeStep(
|
|
2028
2432
|
assignment.client,
|
|
2029
2433
|
step,
|
|
2030
2434
|
storyboard.id,
|
|
2031
2435
|
phase.id,
|
|
2032
2436
|
context,
|
|
2033
2437
|
allSteps,
|
|
2034
|
-
options,
|
|
2438
|
+
assignment.options ?? options,
|
|
2035
2439
|
stepExecutionState
|
|
2036
2440
|
);
|
|
2037
2441
|
const result2 = { ...rawResult, storyboard_id: storyboard.id };
|
|
2442
|
+
if (routedCapabilityDetail !== void 0 || result2.skip_reason === "capability_prerequisite_unavailable") {
|
|
2443
|
+
recordUnavailableOutputs(phase.id, step);
|
|
2444
|
+
}
|
|
2445
|
+
if (routedCapabilityDetail !== void 0 && routedStepRequirements.has(step)) {
|
|
2446
|
+
result2.skip = { ...result2.skip, requirement: routedStepRequirements.get(step) };
|
|
2447
|
+
}
|
|
2038
2448
|
if (isMultiInstance || useRouting) {
|
|
2039
2449
|
result2.agent_url = (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(assignment.agentUrl);
|
|
2040
2450
|
result2.agent_index = assignment.instanceIndex + 1;
|
|
@@ -2080,11 +2490,13 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2080
2490
|
}
|
|
2081
2491
|
if (step.task === "protected_resource_metadata") {
|
|
2082
2492
|
if (result2.skipped && result2.skip_reason === "oauth_not_advertised") {
|
|
2083
|
-
|
|
2493
|
+
if (routingContext) routedOauthAbsent.add(assignment.instanceIndex);
|
|
2494
|
+
else phaseAbsent = true;
|
|
2084
2495
|
} else {
|
|
2085
2496
|
const status = result2.response?.status;
|
|
2086
2497
|
if (typeof status === "number" && status >= 200 && status < 300) {
|
|
2087
|
-
|
|
2498
|
+
if (routingContext) routedOauthPresent.add(assignment.instanceIndex);
|
|
2499
|
+
else presenceDetected = true;
|
|
2088
2500
|
}
|
|
2089
2501
|
}
|
|
2090
2502
|
}
|
|
@@ -2100,34 +2512,26 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2100
2512
|
if (result2.skipped) {
|
|
2101
2513
|
skippedCount++;
|
|
2102
2514
|
context = result2.context;
|
|
2515
|
+
const hardPrerequisite = isHardMissingStateSkipReason(result2.skip_reason) || result2.skip_reason === "prerequisite_failed";
|
|
2516
|
+
if (result2.skip_reason === "prerequisite_failed" && !result2.passed) phasePassed = false;
|
|
2517
|
+
if (routingContext && hardPrerequisite) {
|
|
2518
|
+
recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
|
|
2519
|
+
if (!result2.passed) {
|
|
2520
|
+
phasePassed = false;
|
|
2521
|
+
if (step.stateful) recordHardPrerequisiteFailure(step);
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2103
2524
|
if (step.stateful) {
|
|
2104
2525
|
if (isHardMissingStateSkipReason(result2.skip_reason)) {
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
|
-
} else {
|
|
2115
|
-
const hasStatefulPeers = phaseStatefulStepIds.length > 1;
|
|
2116
|
-
if (hasStatefulPeers && !phaseStatefulCascades.has(phase.id)) {
|
|
2117
|
-
phaseStatefulCascades.set(phase.id, {
|
|
2118
|
-
stepId: step.id,
|
|
2119
|
-
reason: result2.skip_reason ?? "missing_tool"
|
|
2120
|
-
});
|
|
2121
|
-
} else if (!hasStatefulPeers && result2.skip) {
|
|
2122
|
-
result2.skip = {
|
|
2123
|
-
...result2.skip,
|
|
2124
|
-
detail: result2.skip.detail + soleStatefulExemptionDetail(phase.id)
|
|
2125
|
-
};
|
|
2126
|
-
}
|
|
2127
|
-
}
|
|
2128
|
-
} else if (result2.skip_reason === "not_applicable") {
|
|
2129
|
-
if (phasePendingNotApplicable === null) {
|
|
2130
|
-
phasePendingNotApplicable = { stepId: step.id, reason: "not_applicable" };
|
|
2526
|
+
recordHardMissingState(step, result2);
|
|
2527
|
+
} else if (result2.skip_reason === "not_applicable" || result2.skip_reason === "capability_prerequisite_unavailable") {
|
|
2528
|
+
const capabilityUnavailable = routedCapabilityDetail !== void 0 || result2.skip_reason === "capability_prerequisite_unavailable";
|
|
2529
|
+
if (phasePendingNotApplicable === null || phasePendingNotApplicable.capabilityUnavailable === true && !capabilityUnavailable) {
|
|
2530
|
+
phasePendingNotApplicable = {
|
|
2531
|
+
stepId: step.id,
|
|
2532
|
+
reason: result2.skip_reason,
|
|
2533
|
+
...capabilityUnavailable ? { capabilityUnavailable: true } : {}
|
|
2534
|
+
};
|
|
2131
2535
|
}
|
|
2132
2536
|
}
|
|
2133
2537
|
}
|
|
@@ -2149,7 +2553,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2149
2553
|
}
|
|
2150
2554
|
} else {
|
|
2151
2555
|
phasePassed = false;
|
|
2152
|
-
if (!phase.optional || presenceDetected) {
|
|
2556
|
+
if (!phase.optional || (routingContext ? routedOauthPresent.has(assignment.instanceIndex) : presenceDetected)) {
|
|
2153
2557
|
failedCount++;
|
|
2154
2558
|
countedAsFailed.add(result2);
|
|
2155
2559
|
}
|
|
@@ -2171,7 +2575,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2171
2575
|
context,
|
|
2172
2576
|
options,
|
|
2173
2577
|
stepExecutionState,
|
|
2174
|
-
preflightExcludedPhaseIds
|
|
2578
|
+
preflightExcludedPhaseIds,
|
|
2579
|
+
routedPreflightAssignment
|
|
2175
2580
|
);
|
|
2176
2581
|
}
|
|
2177
2582
|
if (creativeAssetFixtureGap) {
|
|
@@ -2194,6 +2599,15 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2194
2599
|
}
|
|
2195
2600
|
}
|
|
2196
2601
|
}
|
|
2602
|
+
if (phasePendingMissingTool.trigger && !phaseRescuedTargets.has(phasePendingMissingTool.trigger.stepId) && !phaseStatefulCascades.has(phase.id)) {
|
|
2603
|
+
const subs = phasePendingMissingTool.trigger.substitutes;
|
|
2604
|
+
const subsList = subs.length === 1 ? `"${subs[0]}"` : subs.map((s) => `"${s}"`).join(", ");
|
|
2605
|
+
phaseStatefulCascades.set(phase.id, {
|
|
2606
|
+
stepId: phasePendingMissingTool.trigger.stepId,
|
|
2607
|
+
reason: phasePendingMissingTool.trigger.reason,
|
|
2608
|
+
substitution_chain: `declared substitute ${subsList} did not pass`
|
|
2609
|
+
});
|
|
2610
|
+
}
|
|
2197
2611
|
if (phasePendingNotApplicable && !phaseEstablishedStatefulState && !phaseStatefulCascades.has(phase.id)) {
|
|
2198
2612
|
const hadStatefulPeers = phaseStatefulStepIds.some((id) => id !== phasePendingNotApplicable.stepId);
|
|
2199
2613
|
if (hadStatefulPeers) {
|
|
@@ -2208,14 +2622,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2208
2622
|
}
|
|
2209
2623
|
}
|
|
2210
2624
|
}
|
|
2211
|
-
if (
|
|
2212
|
-
|
|
2213
|
-
const subsList = subs.length === 1 ? `"${subs[0]}"` : subs.map((s) => `"${s}"`).join(", ");
|
|
2214
|
-
phaseStatefulCascades.set(phase.id, {
|
|
2215
|
-
stepId: phasePendingMissingTool.stepId,
|
|
2216
|
-
reason: phasePendingMissingTool.reason,
|
|
2217
|
-
substitution_chain: `declared substitute ${subsList} did not pass`
|
|
2218
|
-
});
|
|
2625
|
+
if (phaseInheritedCapabilityTrigger && !phaseStatefulCascades.has(phase.id)) {
|
|
2626
|
+
phaseStatefulCascades.set(phase.id, phaseInheritedCapabilityTrigger);
|
|
2219
2627
|
}
|
|
2220
2628
|
for (const target of phaseRescuedTargets) {
|
|
2221
2629
|
const sourceId = phaseRescueSource.get(target);
|
|
@@ -2236,6 +2644,27 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2236
2644
|
});
|
|
2237
2645
|
priorPhaseIds.push(phase.id);
|
|
2238
2646
|
}
|
|
2647
|
+
for (const phase of storyboard.phases) {
|
|
2648
|
+
const result2 = phaseResults.find((p) => p.phase_id === phase.id);
|
|
2649
|
+
for (const step of phase.steps) {
|
|
2650
|
+
if (!routedErrors.has(step) || reportedRoutingErrors.has(step)) continue;
|
|
2651
|
+
const failed = routingFailedStep(step, phase.id, routedErrors.get(step));
|
|
2652
|
+
const existingIndex = result2.steps.findIndex((row) => row.step_id === step.id);
|
|
2653
|
+
if (existingIndex >= 0) {
|
|
2654
|
+
const existing = result2.steps[existingIndex];
|
|
2655
|
+
if (existing.skipped) skippedCount--;
|
|
2656
|
+
if (countedAsFailed.delete(existing)) failedCount--;
|
|
2657
|
+
result2.steps[existingIndex] = failed;
|
|
2658
|
+
} else {
|
|
2659
|
+
result2.steps.push(failed);
|
|
2660
|
+
}
|
|
2661
|
+
reportedRoutingErrors.add(step);
|
|
2662
|
+
countedAsFailed.add(failed);
|
|
2663
|
+
result2.passed = false;
|
|
2664
|
+
priorStepResults.set(step.id, failed);
|
|
2665
|
+
failedCount++;
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2239
2668
|
const branchSetDelta = creativeAssetFixtureGap ? { skippedDelta: 0 } : applyBranchSetGrading(
|
|
2240
2669
|
storyboard.phases,
|
|
2241
2670
|
phaseResults,
|
|
@@ -2272,8 +2701,9 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2272
2701
|
const phaseResult = phaseResults.find((p) => p.phase_id === phaseDef.id);
|
|
2273
2702
|
return !!phaseResult && phaseResult.passed && phaseResult.steps.some((s) => !s.skipped && s.passed);
|
|
2274
2703
|
});
|
|
2275
|
-
const requiredPhasesPassed = !hasExecutableSteps || requiredPhaseHasExecutedPass || requiredPhasesNonFailingSkipped || failedCount === 0 && requiredPhasesCoveredByCapabilityGates;
|
|
2704
|
+
const requiredPhasesPassed = !hasExecutableSteps || requiredPhaseDefs.every((phaseDef) => phaseResults.find((p) => p.phase_id === phaseDef.id)?.passed === true) && (requiredPhaseHasExecutedPass || requiredPhasesNonFailingSkipped || failedCount === 0 && requiredPhasesCoveredByCapabilityGates);
|
|
2276
2705
|
const storyboardWideFixtureUnavailable = (seedingUnsupported || fixtureUnsatisfied || creativeAssetFixtureGap !== void 0) && failedCount === 0;
|
|
2706
|
+
const hasUnverifiedCoverage = signingCoverageUnverified(phaseResults.flatMap((phase) => phase.steps));
|
|
2277
2707
|
if (seedingPhaseResult) phaseResults.unshift(seedingPhaseResult);
|
|
2278
2708
|
const schemasUsed = collectSchemasUsed(phaseResults);
|
|
2279
2709
|
const strictSummary = summarizeStrictValidation(phaseResults);
|
|
@@ -2297,7 +2727,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2297
2727
|
Object.entries(routingContext.agentMap).map(([specialism, url]) => [specialism, (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(url)])
|
|
2298
2728
|
)
|
|
2299
2729
|
},
|
|
2300
|
-
overall_passed: failedCount === 0 && (requiredPhasesPassed || storyboardWideFixtureUnavailable) && !assertionsFailed,
|
|
2730
|
+
overall_passed: failedCount === 0 && (requiredPhasesPassed || storyboardWideFixtureUnavailable) && !assertionsFailed && !hasUnverifiedCoverage,
|
|
2301
2731
|
phases: phaseResults,
|
|
2302
2732
|
context,
|
|
2303
2733
|
total_duration_ms: Date.now() - start,
|
|
@@ -2347,9 +2777,17 @@ async function runMultiPass(agentUrls, storyboard, options) {
|
|
|
2347
2777
|
options = {
|
|
2348
2778
|
...options,
|
|
2349
2779
|
_profile: preSeedProfile,
|
|
2350
|
-
...options.agentTools ? {} : { agentTools: normalizeAgentToolNames(preSeedProfile.tools) }
|
|
2780
|
+
...options.agentTools ? {} : { agentTools: (0, import_agent_routing.normalizeAgentToolNames)(preSeedProfile.tools) }
|
|
2351
2781
|
};
|
|
2352
2782
|
}
|
|
2783
|
+
const resetFailure = await resetControllerStates(
|
|
2784
|
+
preSeedClients.map((client) => ({ client, options })),
|
|
2785
|
+
storyboard
|
|
2786
|
+
);
|
|
2787
|
+
if (resetFailure) {
|
|
2788
|
+
await (0, import_protocols.closeScopedConnections)(options.protocol);
|
|
2789
|
+
return buildDiscoveryFailedResult(agentUrls, storyboard, resetFailure);
|
|
2790
|
+
}
|
|
2353
2791
|
if (storyboardCapabilityPredicates(storyboard).length > 0) {
|
|
2354
2792
|
const unmetDetail = evaluateStoryboardCapabilityGates(
|
|
2355
2793
|
storyboard,
|
|
@@ -2594,7 +3032,7 @@ async function runStoryboardStepBody(agentUrl, storyboard, stepId, options) {
|
|
|
2594
3032
|
options = {
|
|
2595
3033
|
...options,
|
|
2596
3034
|
...!options._profile && { _profile: profile },
|
|
2597
|
-
...!options.agentTools && { agentTools: normalizeAgentToolNames(profile.tools) }
|
|
3035
|
+
...!options.agentTools && { agentTools: (0, import_agent_routing.normalizeAgentToolNames)(profile.tools) }
|
|
2598
3036
|
};
|
|
2599
3037
|
}
|
|
2600
3038
|
} else {
|
|
@@ -2682,6 +3120,38 @@ async function runStoryboardStepBody(agentUrl, storyboard, stepId, options) {
|
|
|
2682
3120
|
if (ownsWebhookReceiver && webhookReceiver) await webhookReceiver.close();
|
|
2683
3121
|
return { ...result, contributions: Array.from(contributions) };
|
|
2684
3122
|
}
|
|
3123
|
+
function unresolvedStepContextVars(step, request, context, runState) {
|
|
3124
|
+
const unavailableInputs = (step.context_inputs ?? []).filter(
|
|
3125
|
+
(input) => !(input.key in context) && (runState.capabilityUnavailableContextKeys?.has(input.key) === true || runState.missingPrerequisiteContextKeys?.has(input.key) === true)
|
|
3126
|
+
);
|
|
3127
|
+
return [
|
|
3128
|
+
...findUnresolvedContextVars(request),
|
|
3129
|
+
...unavailableInputs.map((input) => ({ key: input.key, token: `$context.${input.key}` }))
|
|
3130
|
+
];
|
|
3131
|
+
}
|
|
3132
|
+
function buildStepRequest(step, effectiveStep, context, options, runnerVars) {
|
|
3133
|
+
let request;
|
|
3134
|
+
if (options.request) {
|
|
3135
|
+
request = (0, import_context.injectContext)({ ...options.request }, context, runnerVars);
|
|
3136
|
+
} else if (step.expect_error && step.sample_request) {
|
|
3137
|
+
request = (0, import_context.injectContext)({ ...step.sample_request }, context, runnerVars);
|
|
3138
|
+
} else if ((0, import_request_builder.hasRequestEnricher)(effectiveStep.task)) {
|
|
3139
|
+
request = (0, import_request_builder.enrichRequest)(effectiveStep, context, options, runnerVars);
|
|
3140
|
+
} else if (step.sample_request) {
|
|
3141
|
+
request = (0, import_context.injectContext)({ ...step.sample_request }, context, runnerVars);
|
|
3142
|
+
} else {
|
|
3143
|
+
request = {};
|
|
3144
|
+
}
|
|
3145
|
+
if (step.context_inputs?.length) {
|
|
3146
|
+
request = (0, import_context.applyContextInputs)(request, step.context_inputs, context);
|
|
3147
|
+
}
|
|
3148
|
+
request = applyBrandInvariant(request, options, effectiveStep.task, { omit_account: step.omit_account });
|
|
3149
|
+
if (options.disable_sandbox === true) {
|
|
3150
|
+
request = applyDisableSandboxHint(request, effectiveStep.task);
|
|
3151
|
+
}
|
|
3152
|
+
request = applyIdempotencyInvariant(request, effectiveStep.task, step);
|
|
3153
|
+
return request;
|
|
3154
|
+
}
|
|
2685
3155
|
async function executeStep(client, step, storyboardId, phaseId, context, allSteps, options, state) {
|
|
2686
3156
|
const runState = state ?? {
|
|
2687
3157
|
contributions: /* @__PURE__ */ new Set(),
|
|
@@ -2731,7 +3201,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
2731
3201
|
extraction: { path: "none", note: "test-kit contract not configured" }
|
|
2732
3202
|
};
|
|
2733
3203
|
}
|
|
2734
|
-
const resolvedTask = resolveTaskName(step, options);
|
|
3204
|
+
const resolvedTask = (0, import_agent_routing.resolveTaskName)(step, options);
|
|
2735
3205
|
if (!resolvedTask) {
|
|
2736
3206
|
if (step.task === "$test_kit.auth.probe_task" && options.agentTools) {
|
|
2737
3207
|
const detail = `Agent does not advertise an auth-required, read-only tool that accepts an empty request body; security auth probes are not applicable to tools [${options.agentTools.join(", ")}].`;
|
|
@@ -2785,6 +3255,9 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
2785
3255
|
extraction: { path: "none" }
|
|
2786
3256
|
};
|
|
2787
3257
|
}
|
|
3258
|
+
if (effectiveStep.task === import_types.MCP_SESSION_PROBE_TASK) {
|
|
3259
|
+
return executeProbeStep(client, effectiveStep, phaseId, context, allSteps, options, runState);
|
|
3260
|
+
}
|
|
2788
3261
|
if (effectiveStep.task === "sync_accounts") {
|
|
2789
3262
|
const rawCaps = options._profile?.raw_capabilities;
|
|
2790
3263
|
if (rawCaps !== void 0) {
|
|
@@ -2830,47 +3303,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
2830
3303
|
extraction: { path: "none" }
|
|
2831
3304
|
};
|
|
2832
3305
|
}
|
|
2833
|
-
let request;
|
|
2834
|
-
if (options.request) {
|
|
2835
|
-
request = (0, import_context.injectContext)({ ...options.request }, context, runState.runnerVars);
|
|
2836
|
-
} else if (step.expect_error && step.sample_request) {
|
|
2837
|
-
request = (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars);
|
|
2838
|
-
} else if ((0, import_request_builder.hasRequestEnricher)(effectiveStep.task)) {
|
|
2839
|
-
request = (0, import_request_builder.enrichRequest)(effectiveStep, context, options, runState.runnerVars);
|
|
2840
|
-
} else if (step.sample_request) {
|
|
2841
|
-
request = (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars);
|
|
2842
|
-
} else {
|
|
2843
|
-
request = {};
|
|
2844
|
-
}
|
|
2845
|
-
if (step.context_inputs?.length) {
|
|
2846
|
-
request = (0, import_context.applyContextInputs)(request, step.context_inputs, context);
|
|
2847
|
-
}
|
|
2848
|
-
const unavailableContextInputs = (step.context_inputs ?? []).filter(
|
|
2849
|
-
(input) => !(input.key in context) && runState.capabilityUnavailableContextKeys?.has(input.key) === true
|
|
2850
|
-
);
|
|
2851
|
-
if (unavailableContextInputs.length > 0) {
|
|
2852
|
-
const detail = "Skipped: context required by a capability-gated phase is unavailable: " + unavailableContextInputs.map((input) => input.key).join(", ") + ".";
|
|
2853
|
-
return {
|
|
2854
|
-
step_id: step.id,
|
|
2855
|
-
phase_id: phaseId,
|
|
2856
|
-
title: step.title,
|
|
2857
|
-
task: step.task,
|
|
2858
|
-
passed: true,
|
|
2859
|
-
skipped: true,
|
|
2860
|
-
skip_reason: "capability_prerequisite_unavailable",
|
|
2861
|
-
skip: buildSkip("not_applicable", detail),
|
|
2862
|
-
duration_ms: 0,
|
|
2863
|
-
validations: [],
|
|
2864
|
-
context,
|
|
2865
|
-
next: getNextStepPreview(step.id, allSteps, context, runState.runnerVars),
|
|
2866
|
-
extraction: { path: "none" }
|
|
2867
|
-
};
|
|
2868
|
-
}
|
|
2869
|
-
request = applyBrandInvariant(request, options, effectiveStep.task, { omit_account: step.omit_account });
|
|
2870
|
-
if (options.disable_sandbox === true) {
|
|
2871
|
-
request = applyDisableSandboxHint(request, effectiveStep.task);
|
|
2872
|
-
}
|
|
2873
|
-
request = applyIdempotencyInvariant(request, effectiveStep.task, step);
|
|
3306
|
+
let request = buildStepRequest(step, effectiveStep, context, options, runState.runnerVars);
|
|
2874
3307
|
const fixtureBinding = applyFixtureBindingsSafely(request, effectiveStep.task, options, runState);
|
|
2875
3308
|
if (!fixtureBinding.ok) {
|
|
2876
3309
|
const next2 = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
|
|
@@ -2913,7 +3346,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
2913
3346
|
effectiveStep.task
|
|
2914
3347
|
);
|
|
2915
3348
|
}
|
|
2916
|
-
const unresolvedContextVars =
|
|
3349
|
+
const unresolvedContextVars = unresolvedStepContextVars(step, request, context, runState);
|
|
2917
3350
|
const unresolvedAssetDirectives = (0, import_creative_assets.findUnresolvedCreativeAssetDirectives)(request).map((path) => ({
|
|
2918
3351
|
key: path,
|
|
2919
3352
|
token: import_creative_assets.BUILD_ASSETS_FROM_FORMAT_DIRECTIVE
|
|
@@ -2922,11 +3355,14 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
2922
3355
|
const hasCapabilityUnavailableContext = unresolvedContextVars.some(
|
|
2923
3356
|
(v) => runState.capabilityUnavailableContextKeys?.has(v.key) === true
|
|
2924
3357
|
);
|
|
2925
|
-
|
|
3358
|
+
const hasMissingToolUnavailableContext = unresolvedContextVars.some(
|
|
3359
|
+
(v) => runState.missingPrerequisiteContextKeys?.has(v.key) === true
|
|
3360
|
+
);
|
|
3361
|
+
if (unresolvedAssetDirectives.length > 0 || unresolvedContextVars.length > 0 && (!step.expect_error || hasCapabilityUnavailableContext || hasMissingToolUnavailableContext)) {
|
|
2926
3362
|
const next2 = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
|
|
2927
3363
|
const responseDerivedDetails = unresolvedVars.map((v) => runState.responseDerivedNotApplicableContextKeys?.get(v.key)).filter((d) => typeof d === "string");
|
|
2928
|
-
const allResponseDerived = responseDerivedDetails.length === unresolvedVars.length && responseDerivedDetails.length > 0;
|
|
2929
|
-
const allCapabilityUnavailable = unresolvedContextVars.length === unresolvedVars.length && unresolvedContextVars.length > 0 && unresolvedContextVars.every((v) => runState.capabilityUnavailableContextKeys?.has(v.key) === true);
|
|
3364
|
+
const allResponseDerived = !hasMissingToolUnavailableContext && responseDerivedDetails.length === unresolvedVars.length && responseDerivedDetails.length > 0;
|
|
3365
|
+
const allCapabilityUnavailable = !hasMissingToolUnavailableContext && unresolvedContextVars.length === unresolvedVars.length && unresolvedContextVars.length > 0 && unresolvedContextVars.every((v) => runState.capabilityUnavailableContextKeys?.has(v.key) === true);
|
|
2930
3366
|
const detail = allResponseDerived ? [...new Set(responseDerivedDetails)].join("; ") : allCapabilityUnavailable ? `Skipped: context required by a capability-gated phase is unavailable: ${unresolvedVars.map((v) => v.key).join(", ")}.` : `Skipped: unresolved context variables from prior steps: ${unresolvedVars.map((v) => v.key).join(", ")}.`;
|
|
2931
3367
|
const synthesized = [];
|
|
2932
3368
|
if (!allResponseDerived && !allCapabilityUnavailable) {
|
|
@@ -3792,6 +4228,9 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
|
|
|
3792
4228
|
fetchFn: options.transport?.trustedFetchFn
|
|
3793
4229
|
};
|
|
3794
4230
|
let requestRecordOverride;
|
|
4231
|
+
let sessionProbeStage;
|
|
4232
|
+
let sessionProbeDetail;
|
|
4233
|
+
let sessionProbeTool;
|
|
3795
4234
|
const contractsInScope = new Set(options.contracts ?? []);
|
|
3796
4235
|
if (step.requires_contract) {
|
|
3797
4236
|
if (!contractsInScope.has(step.requires_contract)) {
|
|
@@ -3873,10 +4312,48 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
|
|
|
3873
4312
|
httpResult.skip_reason = "oauth_not_advertised";
|
|
3874
4313
|
}
|
|
3875
4314
|
} else if (step.task === "oauth_auth_server_metadata") {
|
|
3876
|
-
const prior = runState.priorProbes.get("protected_resource_metadata") ?? findPriorProbe(runState.priorStepResults);
|
|
4315
|
+
const prior = runState.priorProbes.get("protected_resource_metadata") ?? (runState.allowPriorProbeFallback !== false ? findPriorProbe(runState.priorStepResults) : void 0);
|
|
3877
4316
|
httpResult = await (0, import_probes.probeOauthAuthServerMetadata)(prior, probeOpts);
|
|
3878
4317
|
} else if (step.task === "assert_contribution") {
|
|
3879
4318
|
httpResult = void 0;
|
|
4319
|
+
} else if (step.task === import_types.MCP_SESSION_PROBE_TASK) {
|
|
4320
|
+
const plan = planMcpSessionSentinel(step, options, client, runState.agentUrl);
|
|
4321
|
+
if (plan.kind === "error") {
|
|
4322
|
+
httpResult = { url: runState.agentUrl, status: 0, headers: {}, body: null, error: plan.error };
|
|
4323
|
+
} else if (plan.kind === "skip") {
|
|
4324
|
+
httpResult = {
|
|
4325
|
+
url: runState.agentUrl,
|
|
4326
|
+
status: 0,
|
|
4327
|
+
headers: {},
|
|
4328
|
+
body: null,
|
|
4329
|
+
skipped: true,
|
|
4330
|
+
skip_reason: plan.reason,
|
|
4331
|
+
error: plan.detail
|
|
4332
|
+
};
|
|
4333
|
+
} else {
|
|
4334
|
+
const probe = await (0, import_probes.rawMcpSessionProbe)({
|
|
4335
|
+
agentUrl: runState.agentUrl,
|
|
4336
|
+
headers: plan.headers,
|
|
4337
|
+
toolName: plan.toolNames,
|
|
4338
|
+
control: plan.control,
|
|
4339
|
+
// Values the probe withholds but the run's ordinary steps do send, so
|
|
4340
|
+
// a stateful agent's echo cannot land them in this step's evidence.
|
|
4341
|
+
redactValues: runCredentialValues(options),
|
|
4342
|
+
allowPrivateIp: options.allow_http === true,
|
|
4343
|
+
// Honour run cancellation and cap each request well under the shared
|
|
4344
|
+
// 10 s `ssrfSafeFetch` default. The probe additionally bounds the
|
|
4345
|
+
// whole step — candidate walk included — with one shared request /
|
|
4346
|
+
// byte / wall-clock budget, so a tarpitting agent cannot multiply this
|
|
4347
|
+
// per-request cap by the length of its own tool list.
|
|
4348
|
+
...options.signal && { signal: options.signal },
|
|
4349
|
+
timeoutMs: MCP_SESSION_PROBE_REQUEST_TIMEOUT_MS,
|
|
4350
|
+
...options.transport?.trustedFetchFn && { fetchFn: options.transport.trustedFetchFn }
|
|
4351
|
+
});
|
|
4352
|
+
httpResult = probe.httpResult;
|
|
4353
|
+
sessionProbeStage = probe.stage;
|
|
4354
|
+
sessionProbeDetail = probe.detail;
|
|
4355
|
+
sessionProbeTool = probe.gradedTool;
|
|
4356
|
+
}
|
|
3880
4357
|
} else if (step.task === "request_signing_probe") {
|
|
3881
4358
|
httpResult = await (0, import_probe_dispatch.probeRequestSigningVector)(step.id, runState.agentUrl, options);
|
|
3882
4359
|
} else if (step.task === "fetch_brand_jwks") {
|
|
@@ -3953,30 +4430,35 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
|
|
|
3953
4430
|
};
|
|
3954
4431
|
}
|
|
3955
4432
|
const resolvedTargetRequest = targetRequestResult.request;
|
|
3956
|
-
const
|
|
4433
|
+
const advertisedTools = resolveAdvertisedTools(options);
|
|
4434
|
+
const routedPrerequisites = runState.missingPrerequisiteContextKeys !== void 0 && (!advertisedTools || advertisedTools.includes(rateLimitTrip.trip_target_task));
|
|
4435
|
+
const unresolvedContextVars = routedPrerequisites ? unresolvedStepContextVars(targetStep, resolvedTargetRequest, context, runState) : findUnresolvedContextVars(resolvedTargetRequest);
|
|
3957
4436
|
const unresolvedAssetDirectives = (0, import_creative_assets.findUnresolvedCreativeAssetDirectives)(resolvedTargetRequest).map((path) => ({
|
|
3958
4437
|
key: path,
|
|
3959
4438
|
token: import_creative_assets.BUILD_ASSETS_FROM_FORMAT_DIRECTIVE
|
|
3960
4439
|
}));
|
|
3961
4440
|
const unresolvedVars = [...unresolvedContextVars, ...unresolvedAssetDirectives];
|
|
3962
|
-
|
|
4441
|
+
const hardUnavailable = routedPrerequisites && unresolvedContextVars.some((v) => runState.missingPrerequisiteContextKeys?.has(v.key));
|
|
4442
|
+
const capabilityUnavailable = routedPrerequisites && unresolvedContextVars.some((v) => runState.capabilityUnavailableContextKeys?.has(v.key));
|
|
4443
|
+
if (unresolvedAssetDirectives.length > 0 || unresolvedContextVars.length > 0 && (!targetStep.expect_error || hardUnavailable || capabilityUnavailable)) {
|
|
3963
4444
|
const next = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
|
|
3964
|
-
const
|
|
4445
|
+
const allCapabilityUnavailable = capabilityUnavailable && !hardUnavailable && unresolvedAssetDirectives.length === 0 && unresolvedContextVars.every((v) => runState.capabilityUnavailableContextKeys?.has(v.key));
|
|
4446
|
+
const detail = allCapabilityUnavailable ? `Skipped: context required by a capability-gated phase is unavailable: ${unresolvedVars.map((v) => v.key).join(", ")}.` : `Skipped: unresolved context variables from rate_limit_trip.trip_target_sample_request: ${unresolvedVars.map((v) => v.key).join(", ")}.`;
|
|
3965
4447
|
return {
|
|
3966
4448
|
step_id: step.id,
|
|
3967
4449
|
phase_id: phaseId,
|
|
3968
4450
|
title: step.title,
|
|
3969
4451
|
task: step.task,
|
|
3970
|
-
passed:
|
|
4452
|
+
passed: allCapabilityUnavailable,
|
|
3971
4453
|
skipped: true,
|
|
3972
|
-
skip_reason: "prerequisite_failed",
|
|
3973
|
-
skip: buildSkip("prerequisite_failed", detail),
|
|
4454
|
+
skip_reason: allCapabilityUnavailable ? "capability_prerequisite_unavailable" : "prerequisite_failed",
|
|
4455
|
+
skip: buildSkip(allCapabilityUnavailable ? "not_applicable" : "prerequisite_failed", detail),
|
|
3974
4456
|
duration_ms: Date.now() - start,
|
|
3975
4457
|
validations: [],
|
|
3976
4458
|
context,
|
|
3977
4459
|
next,
|
|
3978
4460
|
extraction: { path: "none" },
|
|
3979
|
-
error: detail
|
|
4461
|
+
...!allCapabilityUnavailable && { error: detail }
|
|
3980
4462
|
};
|
|
3981
4463
|
}
|
|
3982
4464
|
const unresolvedRunnerTokens = findUnresolvedRunnerTokens(resolvedTargetRequest);
|
|
@@ -4002,7 +4484,6 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
|
|
|
4002
4484
|
...isPrerequisiteFailure ? { error: detail } : {}
|
|
4003
4485
|
};
|
|
4004
4486
|
}
|
|
4005
|
-
const advertisedTools = resolveAdvertisedTools(options);
|
|
4006
4487
|
if (advertisedTools && !advertisedTools.includes(rateLimitTrip.trip_target_task)) {
|
|
4007
4488
|
const next = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
|
|
4008
4489
|
const detail = `Agent did not advertise tool "${rateLimitTrip.trip_target_task}"; agent tools: [${advertisedTools.join(", ")}].`;
|
|
@@ -4098,7 +4579,7 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
|
|
|
4098
4579
|
if (httpResult?.skipped) {
|
|
4099
4580
|
const detailedReason = httpResult.skip_reason ?? "probe_skipped";
|
|
4100
4581
|
const canonicalReason = import_types.DETAILED_SKIP_TO_CANONICAL[detailedReason] ?? "not_applicable";
|
|
4101
|
-
const detail = CANONICAL_SKIP_DETAILS[detailedReason] ??
|
|
4582
|
+
const detail = CANONICAL_SKIP_DETAILS[detailedReason] ?? redactedHttpResult?.error ?? DETAILED_SKIP_DETAILS[detailedReason] ?? SKIP_DETAILS[canonicalReason];
|
|
4102
4583
|
const selectionResult = selectionForProbeSkip(detailedReason, detail);
|
|
4103
4584
|
return {
|
|
4104
4585
|
step_id: step.id,
|
|
@@ -4145,7 +4626,8 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
|
|
|
4145
4626
|
const allValidationsPassed = validations.every((v) => !(0, import_validations.validationFailsStep)(v));
|
|
4146
4627
|
const fetchOk = httpResult ? !httpResult.error : true;
|
|
4147
4628
|
const passed = fetchOk && allValidationsPassed;
|
|
4148
|
-
const
|
|
4629
|
+
const probeNote = sessionProbeStage !== void 0 ? `MCP session probe graded ${sessionProbeTool ?? "unknown tool"} at ${sessionProbeStage} (${sessionProbeDetail ?? "no detail"})` : "http-probe body parsed as JSON";
|
|
4630
|
+
const extraction = httpResult ? httpResult.error ? { path: "error" } : { path: "structured_content", note: probeNote } : { path: "none" };
|
|
4149
4631
|
return {
|
|
4150
4632
|
step_id: step.id,
|
|
4151
4633
|
phase_id: phaseId,
|
|
@@ -4156,7 +4638,9 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
|
|
|
4156
4638
|
response: redactedHttpResult ?? void 0,
|
|
4157
4639
|
validations,
|
|
4158
4640
|
context,
|
|
4159
|
-
|
|
4641
|
+
// Redacted copy on both branches: the sibling skip branch reads the same
|
|
4642
|
+
// seam, and a probe error can carry an agent URL with OAuth params.
|
|
4643
|
+
error: redactedHttpResult?.error ?? (passed ? void 0 : "Probe validations failed."),
|
|
4160
4644
|
next: getNextStepPreview(step.id, allSteps, context, runState.runnerVars),
|
|
4161
4645
|
request: requestRecord,
|
|
4162
4646
|
...responseRecord && { response_record: responseRecord },
|
|
@@ -4179,26 +4663,7 @@ function applyFixtureBindingsSafely(request, task, options, runState) {
|
|
|
4179
4663
|
}
|
|
4180
4664
|
}
|
|
4181
4665
|
function buildEffectiveStepRequest(step, context, options, runState) {
|
|
4182
|
-
|
|
4183
|
-
if (options.request) {
|
|
4184
|
-
request = (0, import_context.injectContext)({ ...options.request }, context, runState.runnerVars);
|
|
4185
|
-
} else if (step.expect_error && step.sample_request) {
|
|
4186
|
-
request = (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars);
|
|
4187
|
-
} else if ((0, import_request_builder.hasRequestEnricher)(step.task)) {
|
|
4188
|
-
request = (0, import_request_builder.enrichRequest)(step, context, options, runState.runnerVars);
|
|
4189
|
-
} else if (step.sample_request) {
|
|
4190
|
-
request = (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars);
|
|
4191
|
-
} else {
|
|
4192
|
-
request = {};
|
|
4193
|
-
}
|
|
4194
|
-
if (step.context_inputs?.length) {
|
|
4195
|
-
request = (0, import_context.applyContextInputs)(request, step.context_inputs, context);
|
|
4196
|
-
}
|
|
4197
|
-
request = applyBrandInvariant(request, options, step.task, { omit_account: step.omit_account });
|
|
4198
|
-
if (options.disable_sandbox === true) {
|
|
4199
|
-
request = applyDisableSandboxHint(request, step.task);
|
|
4200
|
-
}
|
|
4201
|
-
request = applyIdempotencyInvariant(request, step.task, step);
|
|
4666
|
+
const request = buildStepRequest(step, step, context, options, runState.runnerVars);
|
|
4202
4667
|
const fixtureBinding = applyFixtureBindingsSafely(request, step.task, options, runState);
|
|
4203
4668
|
if (!fixtureBinding.ok) return fixtureBinding;
|
|
4204
4669
|
const creativeAssetExpansion = (0, import_creative_assets.expandCreativeAssetDirectivesWithDiagnostics)(
|
|
@@ -4214,23 +4679,32 @@ function buildEffectiveStepRequest(step, context, options, runState) {
|
|
|
4214
4679
|
request: creativeAssetExpansion.value
|
|
4215
4680
|
};
|
|
4216
4681
|
}
|
|
4217
|
-
function preflightRemainingCreativeAssetDirectives(allSteps, afterGlobalIndex, context, options, runState, excludedPhaseIds = /* @__PURE__ */ new Set()) {
|
|
4682
|
+
function preflightRemainingCreativeAssetDirectives(allSteps, afterGlobalIndex, context, options, runState, excludedPhaseIds = /* @__PURE__ */ new Set(), resolveAssignment) {
|
|
4218
4683
|
const contractsInScope = new Set(options.contracts ?? []);
|
|
4219
4684
|
for (const target of allSteps) {
|
|
4220
4685
|
if (target.globalIndex <= afterGlobalIndex) continue;
|
|
4221
4686
|
if (excludedPhaseIds.has(target.phaseId)) continue;
|
|
4222
|
-
const
|
|
4687
|
+
const assignment = resolveAssignment?.(target.step);
|
|
4688
|
+
if (resolveAssignment && !assignment) continue;
|
|
4689
|
+
const selectedOptions = assignment?.options ?? options;
|
|
4690
|
+
const selectedState = assignment ? {
|
|
4691
|
+
...runState,
|
|
4692
|
+
agentUrl: assignment.agentUrl,
|
|
4693
|
+
agentProfile: assignment.profile,
|
|
4694
|
+
agentLibraryVersion: assignment.profile?.library_version
|
|
4695
|
+
} : runState;
|
|
4696
|
+
const resolvedTask = (0, import_agent_routing.resolveTaskName)(target.step, selectedOptions);
|
|
4223
4697
|
if (!resolvedTask) continue;
|
|
4224
|
-
if (target.step.requires_tool &&
|
|
4698
|
+
if (target.step.requires_tool && selectedOptions.agentTools && !selectedOptions.agentTools.includes(target.step.requires_tool)) {
|
|
4225
4699
|
continue;
|
|
4226
4700
|
}
|
|
4227
4701
|
if (target.step.requires_contract && !contractsInScope.has(target.step.requires_contract)) {
|
|
4228
4702
|
continue;
|
|
4229
4703
|
}
|
|
4230
|
-
if (target.step.task === "expect_rate_limit_not_replayed" && (!contractsInScope.has(import_rate_limit_trip.RATE_LIMIT_TRIP_CONTRACT) ||
|
|
4704
|
+
if (target.step.task === "expect_rate_limit_not_replayed" && (!contractsInScope.has(import_rate_limit_trip.RATE_LIMIT_TRIP_CONTRACT) || selectedOptions.allowLiveSideEffects !== true)) {
|
|
4231
4705
|
continue;
|
|
4232
4706
|
}
|
|
4233
|
-
if (!import_probes.PROBE_TASKS.has(target.step.task) &&
|
|
4707
|
+
if (!import_probes.PROBE_TASKS.has(target.step.task) && selectedOptions.agentTools && !selectedOptions.agentTools.includes(resolvedTask)) {
|
|
4234
4708
|
continue;
|
|
4235
4709
|
}
|
|
4236
4710
|
let requestStep = resolvedTask === target.step.task ? target.step : { ...target.step, task: resolvedTask };
|
|
@@ -4244,7 +4718,7 @@ function preflightRemainingCreativeAssetDirectives(allSteps, afterGlobalIndex, c
|
|
|
4244
4718
|
omit_idempotency_key: true
|
|
4245
4719
|
};
|
|
4246
4720
|
}
|
|
4247
|
-
const request = buildEffectiveStepRequest(requestStep, context,
|
|
4721
|
+
const request = buildEffectiveStepRequest(requestStep, context, selectedOptions, selectedState);
|
|
4248
4722
|
if (!request.ok && "creativeAssetFailure" in request) {
|
|
4249
4723
|
return { target, failure: request.creativeAssetFailure };
|
|
4250
4724
|
}
|
|
@@ -4679,7 +5153,7 @@ function lowerCaseHeaders(headers) {
|
|
|
4679
5153
|
return out;
|
|
4680
5154
|
}
|
|
4681
5155
|
function resolveAdvertisedTools(options) {
|
|
4682
|
-
return options.agentTools ?? normalizeAgentToolNames(options._profile?.tools);
|
|
5156
|
+
return options.agentTools ?? (0, import_agent_routing.normalizeAgentToolNames)(options._profile?.tools);
|
|
4683
5157
|
}
|
|
4684
5158
|
function rateLimitTripObservationToProbeResult(agentUrl, observation) {
|
|
4685
5159
|
if (observation.status === "not_applicable") {
|
|
@@ -4912,23 +5386,6 @@ function phaseUsesRuntimeContext(phase) {
|
|
|
4912
5386
|
const expr = phase.skip_if?.trim();
|
|
4913
5387
|
return expr ? (0, import_phase_condition.phaseConditionUsesContext)(expr) : false;
|
|
4914
5388
|
}
|
|
4915
|
-
function resolveTaskName(step, options) {
|
|
4916
|
-
if (!step.task.startsWith("$test_kit.")) return step.task;
|
|
4917
|
-
const path = step.task.slice("$test_kit.".length).split(".");
|
|
4918
|
-
let value = options.test_kit;
|
|
4919
|
-
for (const segment of path) {
|
|
4920
|
-
if (value == null || typeof value !== "object") {
|
|
4921
|
-
value = void 0;
|
|
4922
|
-
break;
|
|
4923
|
-
}
|
|
4924
|
-
value = value[segment];
|
|
4925
|
-
}
|
|
4926
|
-
const configured = typeof value === "string" && value.length > 0 ? value : step.task_default;
|
|
4927
|
-
if (step.task === "$test_kit.auth.probe_task") {
|
|
4928
|
-
return (0, import_test_kit.selectProbeTask)(configured, options.agentTools);
|
|
4929
|
-
}
|
|
4930
|
-
return configured;
|
|
4931
|
-
}
|
|
4932
5389
|
function defaultAuthHeadersForRawProbe(options) {
|
|
4933
5390
|
const headers = {};
|
|
4934
5391
|
if (options.auth) {
|
|
@@ -4952,6 +5409,354 @@ function defaultAuthHeadersForRawProbe(options) {
|
|
|
4952
5409
|
}
|
|
4953
5410
|
return headers;
|
|
4954
5411
|
}
|
|
5412
|
+
function sessionProbeRoutingHeaders(options) {
|
|
5413
|
+
const headers = {};
|
|
5414
|
+
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5415
|
+
if (!SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase())) continue;
|
|
5416
|
+
try {
|
|
5417
|
+
assertSafeAuthHeaderPart(value, `options.headers.${name}`);
|
|
5418
|
+
} catch {
|
|
5419
|
+
continue;
|
|
5420
|
+
}
|
|
5421
|
+
headers[name] = value;
|
|
5422
|
+
}
|
|
5423
|
+
setHeaderIfAbsent(headers, "X-Test-Session-ID", options.test_session_id, "options.test_session_id");
|
|
5424
|
+
setHeaderIfAbsent(headers, "User-Agent", options.userAgent, "options.userAgent");
|
|
5425
|
+
return headers;
|
|
5426
|
+
}
|
|
5427
|
+
function setHeaderIfAbsent(headers, name, value, label) {
|
|
5428
|
+
if (!value) return;
|
|
5429
|
+
const lower = name.toLowerCase();
|
|
5430
|
+
if (Object.keys(headers).some((existing) => existing.toLowerCase() === lower)) return;
|
|
5431
|
+
try {
|
|
5432
|
+
assertSafeAuthHeaderPart(value, label);
|
|
5433
|
+
} catch {
|
|
5434
|
+
return;
|
|
5435
|
+
}
|
|
5436
|
+
headers[name] = value;
|
|
5437
|
+
}
|
|
5438
|
+
function runCredentialValues(options) {
|
|
5439
|
+
const values = [];
|
|
5440
|
+
const auth = options.auth;
|
|
5441
|
+
if (auth?.type === "bearer" && typeof auth.token === "string") values.push(auth.token);
|
|
5442
|
+
if (auth?.type === "basic") {
|
|
5443
|
+
if (typeof auth.password === "string") values.push(auth.password);
|
|
5444
|
+
if (typeof auth.username === "string" && typeof auth.password === "string") {
|
|
5445
|
+
values.push(`${auth.username}:${auth.password}`);
|
|
5446
|
+
}
|
|
5447
|
+
}
|
|
5448
|
+
if (auth?.type === "oauth" || auth?.type === "oauth_client_credentials") {
|
|
5449
|
+
const token = auth.tokens?.access_token;
|
|
5450
|
+
if (typeof token === "string") values.push(token);
|
|
5451
|
+
}
|
|
5452
|
+
const kit = options.test_kit?.auth;
|
|
5453
|
+
if (typeof kit?.api_key === "string") values.push(kit.api_key);
|
|
5454
|
+
const basic = kit?.basic;
|
|
5455
|
+
if (typeof basic?.password === "string") values.push(basic.password);
|
|
5456
|
+
if (typeof basic?.username === "string" && typeof basic?.password === "string") {
|
|
5457
|
+
values.push(`${basic.username}:${basic.password}`);
|
|
5458
|
+
}
|
|
5459
|
+
if (typeof basic?.credentials === "string") values.push(basic.credentials);
|
|
5460
|
+
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5461
|
+
if (typeof value !== "string" || value.length === 0) continue;
|
|
5462
|
+
if (AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase()) || isCredentialHeaderName(name)) values.push(value);
|
|
5463
|
+
}
|
|
5464
|
+
return values.filter((value) => value.trim().length > 0);
|
|
5465
|
+
}
|
|
5466
|
+
const SESSION_PROBE_ROUTING_HEADERS = /* @__PURE__ */ new Set([
|
|
5467
|
+
"x-tenant-id",
|
|
5468
|
+
"x-tenant",
|
|
5469
|
+
"x-account",
|
|
5470
|
+
"x-account-id",
|
|
5471
|
+
"x-routing-key",
|
|
5472
|
+
"x-partition-key",
|
|
5473
|
+
"x-region",
|
|
5474
|
+
"x-environment",
|
|
5475
|
+
"x-request-id",
|
|
5476
|
+
"x-correlation-id",
|
|
5477
|
+
"x-idempotency-key",
|
|
5478
|
+
"x-test-session-id",
|
|
5479
|
+
"user-agent",
|
|
5480
|
+
"accept-language"
|
|
5481
|
+
]);
|
|
5482
|
+
function unroutableProbeHeader(options) {
|
|
5483
|
+
const runSecrets = runCredentialValues(options);
|
|
5484
|
+
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5485
|
+
const lower = name.toLowerCase();
|
|
5486
|
+
if (SESSION_PROBE_ROUTING_HEADERS.has(lower)) {
|
|
5487
|
+
try {
|
|
5488
|
+
assertSafeAuthHeaderPart(value, `options.headers.${name}`);
|
|
5489
|
+
} catch {
|
|
5490
|
+
return name;
|
|
5491
|
+
}
|
|
5492
|
+
continue;
|
|
5493
|
+
}
|
|
5494
|
+
if (AUTH_OVERRIDE_HEADER_NAMES.has(lower)) continue;
|
|
5495
|
+
if (runSecrets.some((secret) => value.includes(secret))) continue;
|
|
5496
|
+
return name;
|
|
5497
|
+
}
|
|
5498
|
+
return void 0;
|
|
5499
|
+
}
|
|
5500
|
+
function effectiveOAuthAccessToken(client, options, agentUrl) {
|
|
5501
|
+
const live = liveAgentOAuthAccessToken(client, agentUrl);
|
|
5502
|
+
if (live !== void 0) return live;
|
|
5503
|
+
const auth = options.auth;
|
|
5504
|
+
if (auth?.type !== "oauth" && auth?.type !== "oauth_client_credentials") return void 0;
|
|
5505
|
+
const configured = auth.tokens?.access_token;
|
|
5506
|
+
return typeof configured === "string" && configured.length > 0 ? configured : void 0;
|
|
5507
|
+
}
|
|
5508
|
+
function liveAgentOAuthAccessToken(client, agentUrl) {
|
|
5509
|
+
try {
|
|
5510
|
+
const resolved = client?.getAgent?.(TEST_CLIENT_AGENT_ID);
|
|
5511
|
+
if (resolved == null) return void 0;
|
|
5512
|
+
const candidates = [resolved];
|
|
5513
|
+
if (typeof resolved.getAgent === "function") candidates.push(resolved.getAgent());
|
|
5514
|
+
for (const candidate of candidates) {
|
|
5515
|
+
const token = candidate?.oauth_tokens?.access_token;
|
|
5516
|
+
if (typeof token !== "string" || token.length === 0) continue;
|
|
5517
|
+
const configuredUri = candidate?.agent_uri;
|
|
5518
|
+
if (agentUrl !== void 0 && typeof configuredUri === "string" && configuredUri !== agentUrl) continue;
|
|
5519
|
+
if (agentUrl !== void 0 && typeof configuredUri !== "string") continue;
|
|
5520
|
+
return token;
|
|
5521
|
+
}
|
|
5522
|
+
} catch {
|
|
5523
|
+
}
|
|
5524
|
+
return void 0;
|
|
5525
|
+
}
|
|
5526
|
+
const TEST_CLIENT_AGENT_ID = "test";
|
|
5527
|
+
function withMcpBearerParity(headers) {
|
|
5528
|
+
const authorization = headers.authorization;
|
|
5529
|
+
if (authorization === void 0 || !authorization.startsWith("Bearer ")) return headers;
|
|
5530
|
+
const token = authorization.slice("Bearer ".length);
|
|
5531
|
+
if (token.length === 0) return headers;
|
|
5532
|
+
return { ...headers, "x-adcp-auth": token };
|
|
5533
|
+
}
|
|
5534
|
+
function oauthAccessTokenHeaders(options, client, agentUrl) {
|
|
5535
|
+
const token = effectiveOAuthAccessToken(client, options, agentUrl);
|
|
5536
|
+
if (token === void 0) return void 0;
|
|
5537
|
+
try {
|
|
5538
|
+
assertSafeAuthHeaderPart(token, "options.auth.tokens.access_token");
|
|
5539
|
+
} catch {
|
|
5540
|
+
return void 0;
|
|
5541
|
+
}
|
|
5542
|
+
return { authorization: `Bearer ${token}` };
|
|
5543
|
+
}
|
|
5544
|
+
function staticCredentialHeaders(directive, options) {
|
|
5545
|
+
try {
|
|
5546
|
+
const headers = authHeadersForStep(directive, options);
|
|
5547
|
+
return headers.authorization !== void 0 ? { authorization: headers.authorization } : void 0;
|
|
5548
|
+
} catch {
|
|
5549
|
+
}
|
|
5550
|
+
return void 0;
|
|
5551
|
+
}
|
|
5552
|
+
function sessionControlCredentials(mechanism, options, client, agentUrl) {
|
|
5553
|
+
const oauth = oauthAccessTokenHeaders(options, client, agentUrl);
|
|
5554
|
+
const bearer = options.auth?.type === "bearer" ? staticCredentialHeaders({ type: "api_key", value: options.auth.token }, options) : void 0;
|
|
5555
|
+
const basicFromOptions = options.auth?.type === "basic" ? staticCredentialHeaders(
|
|
5556
|
+
{ type: "basic", username: options.auth.username, password: options.auth.password },
|
|
5557
|
+
options
|
|
5558
|
+
) : void 0;
|
|
5559
|
+
const kitApiKey = typeof options.test_kit?.auth?.api_key === "string" && options.test_kit.auth.api_key.length > 0 ? staticCredentialHeaders({ type: "api_key", from_test_kit: true }, options) : void 0;
|
|
5560
|
+
const kitBasic = options.test_kit?.auth?.basic !== void 0 ? staticCredentialHeaders({ type: "basic", from_test_kit: true }, options) : void 0;
|
|
5561
|
+
switch (mechanism) {
|
|
5562
|
+
case "oauth_bearer": {
|
|
5563
|
+
if (oauth) return { headers: oauth };
|
|
5564
|
+
return {
|
|
5565
|
+
unavailable: {
|
|
5566
|
+
reason: `this run holds no OAuth access token, and a static API key or Basic credential is not evidence about the OAuth path at all \u2014 accepting a shared secret says nothing about whether tokens from the issuer advertised in your protected-resource metadata are what gates this resource`,
|
|
5567
|
+
remedy: `Run the storyboard with OAuth so the runner holds a token minted by that issuer (\`adcp --save-auth <alias> <url> --oauth\`, or pass \`--oauth\` to \`storyboard run\`).`
|
|
5568
|
+
}
|
|
5569
|
+
};
|
|
5570
|
+
}
|
|
5571
|
+
case "api_key": {
|
|
5572
|
+
const headers = bearer ?? kitApiKey;
|
|
5573
|
+
if (headers) return { headers };
|
|
5574
|
+
return {
|
|
5575
|
+
unavailable: {
|
|
5576
|
+
reason: `this run holds no valid API key to prove the endpoint accepts one`,
|
|
5577
|
+
remedy: "Declare `auth.api_key` in the test kit, or pass a bearer `options.auth` (CLI: `--auth`)."
|
|
5578
|
+
}
|
|
5579
|
+
};
|
|
5580
|
+
}
|
|
5581
|
+
case "basic": {
|
|
5582
|
+
const headers = basicFromOptions ?? kitBasic;
|
|
5583
|
+
if (headers) return { headers };
|
|
5584
|
+
return {
|
|
5585
|
+
unavailable: {
|
|
5586
|
+
reason: `this run holds no valid Basic credential to prove the endpoint accepts one`,
|
|
5587
|
+
remedy: "Declare `auth.basic` in the test kit, or pass a basic `options.auth`."
|
|
5588
|
+
}
|
|
5589
|
+
};
|
|
5590
|
+
}
|
|
5591
|
+
case "any": {
|
|
5592
|
+
const headers = oauth ?? bearer ?? basicFromOptions ?? kitApiKey ?? kitBasic;
|
|
5593
|
+
if (headers) return { headers };
|
|
5594
|
+
return {
|
|
5595
|
+
unavailable: {
|
|
5596
|
+
reason: `this run holds no valid credential, so a rejection cannot be told apart from an endpoint that refuses every request`,
|
|
5597
|
+
remedy: "Declare `auth.api_key` or `auth.basic` in the test kit, pass `options.auth`, or run with `--oauth`."
|
|
5598
|
+
}
|
|
5599
|
+
};
|
|
5600
|
+
}
|
|
5601
|
+
}
|
|
5602
|
+
}
|
|
5603
|
+
function summarizeAdvertisedTools(tools) {
|
|
5604
|
+
const names = (tools ?? []).slice(0, 20).map((name) => escapeControlChars(name.slice(0, 64)));
|
|
5605
|
+
const overflow = (tools?.length ?? 0) - names.length;
|
|
5606
|
+
return overflow > 0 ? `${names.join(", ")}, \u2026${overflow} more` : names.join(", ");
|
|
5607
|
+
}
|
|
5608
|
+
function escapeControlChars(value) {
|
|
5609
|
+
return value.replace(
|
|
5610
|
+
/[\u0000-\u001f\u007f-\u009f]/g,
|
|
5611
|
+
(char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`
|
|
5612
|
+
);
|
|
5613
|
+
}
|
|
5614
|
+
const SESSION_PROBE_PUBLIC_TIER = /* @__PURE__ */ new Set([
|
|
5615
|
+
"get_adcp_capabilities",
|
|
5616
|
+
"get_products",
|
|
5617
|
+
"list_products",
|
|
5618
|
+
"list_creative_formats"
|
|
5619
|
+
]);
|
|
5620
|
+
const CANONICAL_ADCP_TOOLS = /* @__PURE__ */ new Set([
|
|
5621
|
+
...import_capabilities.MEDIA_BUY_TOOLS,
|
|
5622
|
+
...import_capabilities.CREATIVE_TOOLS,
|
|
5623
|
+
...import_capabilities.SIGNALS_TOOLS,
|
|
5624
|
+
...import_capabilities.GOVERNANCE_TOOLS,
|
|
5625
|
+
...import_capabilities.ACCOUNT_TOOLS,
|
|
5626
|
+
...import_capabilities.BRAND_RIGHTS_TOOLS,
|
|
5627
|
+
...import_capabilities.PROTOCOL_TOOLS,
|
|
5628
|
+
...import_capabilities.EVENT_TRACKING_TOOLS
|
|
5629
|
+
]);
|
|
5630
|
+
const PREFERRED_PROBE_TARGET = "get_principal";
|
|
5631
|
+
function hasNoRequiredRequestFields(tool) {
|
|
5632
|
+
const schema = import_tool_request_schemas.TOOL_REQUEST_SCHEMAS[tool];
|
|
5633
|
+
const shape = schema?.shape;
|
|
5634
|
+
if (!shape) return false;
|
|
5635
|
+
return !Object.values(shape).some((field) => {
|
|
5636
|
+
const candidate = field;
|
|
5637
|
+
if (typeof candidate?.safeParse !== "function") return false;
|
|
5638
|
+
return !candidate.safeParse(void 0).success;
|
|
5639
|
+
});
|
|
5640
|
+
}
|
|
5641
|
+
function protectedToolCandidates(tools) {
|
|
5642
|
+
if (!tools) return [];
|
|
5643
|
+
const advertised = new Set(tools);
|
|
5644
|
+
const eligible = (tool) => advertised.has(tool) && !SESSION_PROBE_PUBLIC_TIER.has(tool) && !import_idempotency2.MUTATING_TASKS.has(tool);
|
|
5645
|
+
const allowlisted = import_test_kit.PROBE_TASK_ALLOWLIST.filter(eligible);
|
|
5646
|
+
const canonicalReads = [...CANONICAL_ADCP_TOOLS].filter((tool) => /^(list|get)_/.test(tool)).filter((tool) => !allowlisted.includes(tool)).filter(eligible).filter(hasNoRequiredRequestFields).sort((a, b) => {
|
|
5647
|
+
if (a === PREFERRED_PROBE_TARGET) return -1;
|
|
5648
|
+
if (b === PREFERRED_PROBE_TARGET) return 1;
|
|
5649
|
+
return a.localeCompare(b);
|
|
5650
|
+
});
|
|
5651
|
+
return [...allowlisted, ...canonicalReads];
|
|
5652
|
+
}
|
|
5653
|
+
function signatureBoundTools(options) {
|
|
5654
|
+
if (options.functional_request_signing === void 0) return /* @__PURE__ */ new Set();
|
|
5655
|
+
const raw = options._profile?.raw_capabilities;
|
|
5656
|
+
if (raw === null || typeof raw !== "object") return "unparseable";
|
|
5657
|
+
const advertised = raw.request_signing;
|
|
5658
|
+
if (advertised === void 0) return /* @__PURE__ */ new Set();
|
|
5659
|
+
if (advertised === null || typeof advertised !== "object") return "unparseable";
|
|
5660
|
+
const buckets = advertised;
|
|
5661
|
+
const bound = /* @__PURE__ */ new Set();
|
|
5662
|
+
for (const bucket of [buckets.required_for, buckets.supported_for]) {
|
|
5663
|
+
if (bucket === void 0) continue;
|
|
5664
|
+
if (!Array.isArray(bucket) || bucket.some((entry) => typeof entry !== "string")) return "unparseable";
|
|
5665
|
+
for (const entry of bucket) bound.add(entry);
|
|
5666
|
+
}
|
|
5667
|
+
return bound;
|
|
5668
|
+
}
|
|
5669
|
+
function selectProtectedToolTarget(tools) {
|
|
5670
|
+
return protectedToolCandidates(tools)[0];
|
|
5671
|
+
}
|
|
5672
|
+
function sessionControlMechanismFor(auth) {
|
|
5673
|
+
if (auth === "none") return "any";
|
|
5674
|
+
switch (auth.type) {
|
|
5675
|
+
case "oauth_bearer":
|
|
5676
|
+
return "oauth_bearer";
|
|
5677
|
+
case "basic":
|
|
5678
|
+
return "basic";
|
|
5679
|
+
case "api_key":
|
|
5680
|
+
return "api_key";
|
|
5681
|
+
}
|
|
5682
|
+
}
|
|
5683
|
+
function planMcpSessionSentinel(step, options, client, agentUrl) {
|
|
5684
|
+
if (options.protocol !== "mcp") {
|
|
5685
|
+
const declared = options.protocol === void 0 ? "no transport" : `"${options.protocol}"`;
|
|
5686
|
+
return {
|
|
5687
|
+
kind: "error",
|
|
5688
|
+
error: `"${import_types.MCP_SESSION_PROBE_TASK}" is an MCP session probe and requires an explicit \`protocol: 'mcp'\` on the run; this run declared ${declared}. A2A has no equivalent parameter-free protected operation, so the runner refuses to substitute one.`
|
|
5689
|
+
};
|
|
5690
|
+
}
|
|
5691
|
+
if (step.auth === void 0) {
|
|
5692
|
+
return {
|
|
5693
|
+
kind: "skip",
|
|
5694
|
+
reason: "session_probe_ungradable",
|
|
5695
|
+
detail: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(
|
|
5696
|
+
`Agent advertises no auth-required, read-only AdCP tool that accepts an empty request body, so the runner fell back to the MCP "${import_types.MCP_SESSION_PROBE_TASK}" session probe. That probe cannot grade a positive static-credential step: its validations assert an AdCP task response body, which no MCP protocol operation produces, so this mechanism's branch cannot contribute auth_mechanism_verified. Remedy: advertise one allowlisted read tool (${import_test_kit.PROBE_TASK_ALLOWLIST_SUMMARY}), or serve RFC 9728 metadata and run with OAuth so the OAuth branch can be verified instead. Advertised tools: [${summarizeAdvertisedTools(options.agentTools)}].`
|
|
5697
|
+
)
|
|
5698
|
+
};
|
|
5699
|
+
}
|
|
5700
|
+
const signatureBound = signatureBoundTools(options);
|
|
5701
|
+
const candidates = protectedToolCandidates(options.agentTools);
|
|
5702
|
+
if (signatureBound === "unparseable") {
|
|
5703
|
+
return {
|
|
5704
|
+
kind: "skip",
|
|
5705
|
+
reason: "session_probe_ungradable",
|
|
5706
|
+
detail: `This run signs functional dispatch (RFC 9421), but the runner could not read which operations your \`request_signing\` capability covers, so it cannot tell whether the session probe's unsigned call would be refused for the signature rather than the credential. Refusing to grade instead of guessing. Remedy: advertise \`request_signing.required_for\` / \`supported_for\` as string arrays, or advertise one allowlisted read tool (${import_test_kit.PROBE_TASK_ALLOWLIST_SUMMARY}) so the probe has a protocol-vouched target.`
|
|
5707
|
+
};
|
|
5708
|
+
}
|
|
5709
|
+
const toolNames = candidates.filter((tool) => !signatureBound.has(tool));
|
|
5710
|
+
if (toolNames.length === 0 && candidates.length > 0) {
|
|
5711
|
+
return {
|
|
5712
|
+
kind: "skip",
|
|
5713
|
+
reason: "session_probe_ungradable",
|
|
5714
|
+
detail: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(
|
|
5715
|
+
`Every protected read the probe could call (${candidates.join(", ")}) is covered by this agent's \`request_signing\` advertisement, and the session probe mints no RFC 9421 signatures. An unsigned call would be refused for the missing signature, which is not evidence about the credential, so the runner refuses to grade it. Remedy: advertise one allowlisted read tool (${import_test_kit.PROBE_TASK_ALLOWLIST_SUMMARY}) outside \`request_signing.required_for\`/\`supported_for\`, or run with OAuth against RFC 9728 metadata so the OAuth branch can be verified instead.`
|
|
5716
|
+
)
|
|
5717
|
+
};
|
|
5718
|
+
}
|
|
5719
|
+
if (toolNames.length === 0) {
|
|
5720
|
+
return {
|
|
5721
|
+
kind: "skip",
|
|
5722
|
+
reason: "session_probe_ungradable",
|
|
5723
|
+
detail: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(
|
|
5724
|
+
`Agent advertises no auth-required, read-only AdCP tool the probe can call with an empty request body, so there is no protected operation to grade. MCP discovery (\`tools/list\`) is not a protected task and public-tier tools (${[...SESSION_PROBE_PUBLIC_TIER].join(", ")}) are served unauthenticated by design. Remedy: advertise one allowlisted read tool (${import_test_kit.PROBE_TASK_ALLOWLIST_SUMMARY}). Advertised tools: [${summarizeAdvertisedTools(options.agentTools)}].`
|
|
5725
|
+
)
|
|
5726
|
+
};
|
|
5727
|
+
}
|
|
5728
|
+
const unroutable = unroutableProbeHeader(options);
|
|
5729
|
+
if (unroutable !== void 0) {
|
|
5730
|
+
return {
|
|
5731
|
+
kind: "skip",
|
|
5732
|
+
reason: "session_probe_ungradable",
|
|
5733
|
+
detail: `The runner cannot classify run header "${escapeControlChars(unroutable.slice(0, 64))}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`
|
|
5734
|
+
};
|
|
5735
|
+
}
|
|
5736
|
+
const routing = sessionProbeRoutingHeaders(options);
|
|
5737
|
+
let headers;
|
|
5738
|
+
try {
|
|
5739
|
+
headers = { ...routing, ...withMcpBearerParity(authHeadersForStep(step.auth, options)) };
|
|
5740
|
+
} catch (err) {
|
|
5741
|
+
return {
|
|
5742
|
+
kind: "error",
|
|
5743
|
+
error: `Step auth configuration error: ${err instanceof Error ? err.message : String(err)}`
|
|
5744
|
+
};
|
|
5745
|
+
}
|
|
5746
|
+
const control = sessionControlCredentials(sessionControlMechanismFor(step.auth), options, client, agentUrl);
|
|
5747
|
+
if ("unavailable" in control) {
|
|
5748
|
+
return { kind: "probe", headers, toolNames, control: { kind: "unavailable", ...control.unavailable } };
|
|
5749
|
+
}
|
|
5750
|
+
if (headers.authorization !== void 0 && control.headers.authorization === headers.authorization) {
|
|
5751
|
+
return { kind: "probe", headers, toolNames, control: { kind: "probe_is_valid_credential" } };
|
|
5752
|
+
}
|
|
5753
|
+
return {
|
|
5754
|
+
kind: "probe",
|
|
5755
|
+
headers,
|
|
5756
|
+
toolNames,
|
|
5757
|
+
control: { kind: "credential", headers: { ...routing, ...withMcpBearerParity(control.headers) } }
|
|
5758
|
+
};
|
|
5759
|
+
}
|
|
4955
5760
|
function authHeadersForStep(directive, options) {
|
|
4956
5761
|
if (directive === "none") return {};
|
|
4957
5762
|
if (directive.type === "basic") return basicAuthHeadersForStep(directive, options);
|
|
@@ -5359,7 +6164,8 @@ function createRoutingDispatcher(ctx, options, agents) {
|
|
|
5359
6164
|
const keyToIndex = new Map(keyOrder.map((k, i) => [k, i]));
|
|
5360
6165
|
return {
|
|
5361
6166
|
nextFor(step) {
|
|
5362
|
-
const
|
|
6167
|
+
const task = (0, import_agent_routing.resolveTaskName)(step, { ...options, agentTools: void 0 });
|
|
6168
|
+
const key = (0, import_agent_routing.resolveAgentForStep)(task ? { ...step, task } : step, options, ctx);
|
|
5363
6169
|
const client = ctx.clients.get(key);
|
|
5364
6170
|
const profile = ctx.profiles.get(key);
|
|
5365
6171
|
const url = agents[key]?.url;
|
|
@@ -5370,11 +6176,21 @@ function createRoutingDispatcher(ctx, options, agents) {
|
|
|
5370
6176
|
`key ${key} unbound`
|
|
5371
6177
|
);
|
|
5372
6178
|
}
|
|
6179
|
+
if (!profile) {
|
|
6180
|
+
const failure = ctx.discoveryFailures.find((failure2) => failure2.agentKey === key);
|
|
6181
|
+
throw new import_agent_routing.RoutingError(
|
|
6182
|
+
`Agent "${key}" has no discovered profile; its task contract cannot be established.` + (failure ? ` Discovery failed: ${failure.underlying}. Fix the agent or select a healthy route.` : ""),
|
|
6183
|
+
step.task,
|
|
6184
|
+
`agent "${key}" failed discovery`
|
|
6185
|
+
);
|
|
6186
|
+
}
|
|
5373
6187
|
return {
|
|
5374
6188
|
client,
|
|
5375
6189
|
agentUrl: url,
|
|
6190
|
+
agentKey: key,
|
|
5376
6191
|
instanceIndex: keyToIndex.get(key) ?? 0,
|
|
5377
|
-
profile
|
|
6192
|
+
profile,
|
|
6193
|
+
options: (0, import_agent_routing.routedAgentOptions)(agents[key], options, profile)
|
|
5378
6194
|
};
|
|
5379
6195
|
}
|
|
5380
6196
|
};
|
|
@@ -5455,7 +6271,10 @@ function getFirstStepPreview(storyboard, context = {}) {
|
|
|
5455
6271
|
0 && (module.exports = {
|
|
5456
6272
|
__defaultAuthHeadersForRawProbeForTest,
|
|
5457
6273
|
__filterResponseHeadersForTest,
|
|
6274
|
+
__protectedToolCandidatesForTest,
|
|
5458
6275
|
__redactSecretsForTest,
|
|
6276
|
+
__selectProtectedToolTargetForTest,
|
|
6277
|
+
__sessionControlCredentialsForTest,
|
|
5459
6278
|
applyAdcpVersionRunOptions,
|
|
5460
6279
|
applyBrandInvariant,
|
|
5461
6280
|
applyDisableSandboxHint,
|
|
@@ -5469,5 +6288,8 @@ function getFirstStepPreview(storyboard, context = {}) {
|
|
|
5469
6288
|
resolveCapabilityPath,
|
|
5470
6289
|
runStoryboard,
|
|
5471
6290
|
runStoryboardStep,
|
|
6291
|
+
signingCoverage,
|
|
6292
|
+
signingCoverageUnverified,
|
|
6293
|
+
storyboardCapabilityPredicates,
|
|
5472
6294
|
summarizeStrictValidation
|
|
5473
6295
|
});
|