@adcp/sdk 12.1.1 → 13.0.0-rc.0
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/README.md +19 -3
- package/bin/adcp-fuzz.js +3 -1
- package/dist/lib/adapters/content-standards-adapter.d.mts +9 -9
- package/dist/lib/adapters/content-standards-adapter.d.ts +9 -9
- package/dist/lib/adapters/content-standards-adapter.d.ts.map +1 -1
- package/dist/lib/adapters/content-standards-adapter.js +22 -22
- package/dist/lib/adapters/content-standards-adapter.js.map +1 -1
- package/dist/lib/adapters/content-standards-adapter.mjs +18 -18
- package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
- package/dist/lib/adapters/index.d.mts +2 -2
- package/dist/lib/adapters/index.d.ts +2 -2
- package/dist/lib/adapters/index.d.ts.map +1 -1
- package/dist/lib/adapters/index.js +10 -10
- package/dist/lib/adapters/index.js.map +1 -1
- package/dist/lib/adapters/index.mjs +9 -9
- package/dist/lib/adapters/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/provider-cache.d.mts +7 -0
- package/dist/lib/auth/oauth/provider-cache.d.ts +8 -0
- package/dist/lib/auth/oauth/provider-cache.d.ts.map +1 -0
- package/dist/lib/auth/oauth/provider-cache.js +44 -0
- package/dist/lib/auth/oauth/provider-cache.js.map +1 -0
- package/dist/lib/auth/oauth/provider-cache.mjs +19 -0
- package/dist/lib/auth/oauth/provider-cache.mjs.map +1 -0
- package/dist/lib/conformance/invariants/uniformError.js +1 -1
- package/dist/lib/conformance/invariants/uniformError.js.map +1 -1
- package/dist/lib/conformance/invariants/uniformError.mjs +1 -1
- package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
- package/dist/lib/conformance/runners.js +1 -1
- package/dist/lib/conformance/runners.js.map +1 -1
- package/dist/lib/conformance/runners.mjs +1 -1
- package/dist/lib/conformance/runners.mjs.map +1 -1
- package/dist/lib/conformance/seeder.js +5 -5
- package/dist/lib/conformance/seeder.js.map +1 -1
- package/dist/lib/conformance/seeder.mjs +5 -5
- package/dist/lib/conformance/seeder.mjs.map +1 -1
- package/dist/lib/core/ADCPMultiAgentClient.d.mts +26 -29
- package/dist/lib/core/ADCPMultiAgentClient.d.ts +26 -29
- package/dist/lib/core/ADCPMultiAgentClient.d.ts.map +1 -1
- package/dist/lib/core/ADCPMultiAgentClient.js +27 -19
- package/dist/lib/core/ADCPMultiAgentClient.js.map +1 -1
- package/dist/lib/core/ADCPMultiAgentClient.mjs +27 -19
- package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
- package/dist/lib/core/AgentClient.d.mts +148 -138
- package/dist/lib/core/AgentClient.d.ts +148 -138
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/AgentClient.js +174 -85
- package/dist/lib/core/AgentClient.js.map +1 -1
- package/dist/lib/core/AgentClient.mjs +174 -85
- package/dist/lib/core/AgentClient.mjs.map +1 -1
- package/dist/lib/core/AsyncHandler.d.mts +18 -16
- package/dist/lib/core/AsyncHandler.d.ts +18 -16
- package/dist/lib/core/AsyncHandler.d.ts.map +1 -1
- package/dist/lib/core/AsyncHandler.js +22 -1
- package/dist/lib/core/AsyncHandler.js.map +1 -1
- package/dist/lib/core/AsyncHandler.mjs +22 -1
- package/dist/lib/core/AsyncHandler.mjs.map +1 -1
- package/dist/lib/core/ConversationTypes.d.mts +6 -2
- package/dist/lib/core/ConversationTypes.d.ts +6 -2
- package/dist/lib/core/ConversationTypes.d.ts.map +1 -1
- package/dist/lib/core/ConversationTypes.js.map +1 -1
- package/dist/lib/core/CreativeAgentClient.d.mts +41 -17
- package/dist/lib/core/CreativeAgentClient.d.ts +41 -17
- package/dist/lib/core/CreativeAgentClient.d.ts.map +1 -1
- package/dist/lib/core/CreativeAgentClient.js +39 -12
- package/dist/lib/core/CreativeAgentClient.js.map +1 -1
- package/dist/lib/core/CreativeAgentClient.mjs +39 -12
- package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.mts +127 -50
- package/dist/lib/core/SingleAgentClient.d.ts +127 -50
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +1617 -177
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +1627 -177
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.d.mts +9 -0
- package/dist/lib/core/TaskExecutor.d.ts +9 -0
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +136 -43
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +136 -43
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/index.d.mts +111 -17
- package/dist/lib/index.d.ts +111 -17
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +94 -94
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +93 -94
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/protocols/index.d.ts.map +1 -1
- package/dist/lib/protocols/index.js +6 -15
- package/dist/lib/protocols/index.js.map +1 -1
- package/dist/lib/protocols/index.mjs +6 -16
- package/dist/lib/protocols/index.mjs.map +1 -1
- package/dist/lib/protocols/mcp-modern.d.ts.map +1 -1
- package/dist/lib/protocols/mcp-modern.js +87 -12
- package/dist/lib/protocols/mcp-modern.js.map +1 -1
- package/dist/lib/protocols/mcp-modern.mjs +89 -12
- package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +6 -0
- package/dist/lib/server/create-adcp-server.d.ts +6 -0
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +295 -48
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +301 -50
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/decisioning/assembly-helpers.d.mts +27 -13
- package/dist/lib/server/decisioning/assembly-helpers.d.ts +27 -13
- package/dist/lib/server/decisioning/assembly-helpers.d.ts.map +1 -1
- package/dist/lib/server/decisioning/assembly-helpers.js +136 -14
- package/dist/lib/server/decisioning/assembly-helpers.js.map +1 -1
- package/dist/lib/server/decisioning/assembly-helpers.mjs +134 -13
- package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.d.mts +13 -12
- package/dist/lib/server/decisioning/index.d.ts +13 -12
- package/dist/lib/server/decisioning/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.js +6 -0
- package/dist/lib/server/decisioning/index.js.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +9 -3
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/list-helpers.d.mts +13 -3
- package/dist/lib/server/decisioning/list-helpers.d.ts +13 -3
- package/dist/lib/server/decisioning/list-helpers.d.ts.map +1 -1
- package/dist/lib/server/decisioning/list-helpers.js +13 -3
- package/dist/lib/server/decisioning/list-helpers.js.map +1 -1
- package/dist/lib/server/decisioning/list-helpers.mjs +11 -2
- package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.d.mts +5 -3
- package/dist/lib/server/decisioning/manifest-helpers.d.ts +5 -3
- package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/dispatch.d.mts +2 -2
- package/dist/lib/server/decisioning/proposal/dispatch.d.ts +2 -2
- package/dist/lib/server/decisioning/proposal/dispatch.d.ts.map +1 -1
- package/dist/lib/server/decisioning/proposal/dispatch.js.map +1 -1
- package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/index.d.mts +1 -1
- package/dist/lib/server/decisioning/proposal/index.d.ts +1 -1
- package/dist/lib/server/decisioning/proposal/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/proposal/index.js.map +1 -1
- package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/lifecycle.d.mts +3 -2
- package/dist/lib/server/decisioning/proposal/lifecycle.d.ts +3 -2
- package/dist/lib/server/decisioning/proposal/lifecycle.d.ts.map +1 -1
- package/dist/lib/server/decisioning/proposal/lifecycle.js.map +1 -1
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/mock-manager.d.mts +3 -3
- package/dist/lib/server/decisioning/proposal/mock-manager.d.ts +3 -3
- package/dist/lib/server/decisioning/proposal/mock-manager.d.ts.map +1 -1
- package/dist/lib/server/decisioning/proposal/mock-manager.js.map +1 -1
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.d.mts +10 -6
- package/dist/lib/server/decisioning/proposal/types.d.ts +10 -6
- package/dist/lib/server/decisioning/proposal/types.d.ts.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.js.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +21 -2
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +21 -2
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +754 -81
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +763 -81
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/brand-rights.d.mts +9 -9
- package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts +9 -9
- package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/brand-rights.js.map +1 -1
- package/dist/lib/server/decisioning/specialisms/content-standards.d.mts +16 -16
- package/dist/lib/server/decisioning/specialisms/content-standards.d.ts +16 -16
- package/dist/lib/server/decisioning/specialisms/content-standards.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/content-standards.js.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.mts +15 -13
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +15 -13
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative.d.mts +12 -11
- package/dist/lib/server/decisioning/specialisms/creative.d.ts +12 -11
- package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.mts +25 -15
- package/dist/lib/server/decisioning/specialisms/sales.d.ts +25 -15
- package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
- package/dist/lib/server/index.d.mts +3 -3
- package/dist/lib/server/index.d.ts +3 -3
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js +72 -72
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs +36 -36
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/legacy/v5/index.d.mts +1 -0
- package/dist/lib/server/legacy/v5/index.d.ts +1 -0
- package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
- package/dist/lib/server/legacy/v5/index.js +74 -1
- package/dist/lib/server/legacy/v5/index.js.map +1 -1
- package/dist/lib/server/legacy/v5/index.mjs +75 -1
- package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
- package/dist/lib/server/responses.d.mts +2 -2
- package/dist/lib/server/responses.d.ts +2 -2
- package/dist/lib/server/responses.js.map +1 -1
- package/dist/lib/server/responses.mjs.map +1 -1
- package/dist/lib/testing/client.js +1 -1
- package/dist/lib/testing/client.js.map +1 -1
- package/dist/lib/testing/client.mjs +1 -1
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.js +6 -6
- package/dist/lib/testing/scenarios/brand-rights.js.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.mjs +6 -6
- package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
- package/dist/lib/testing/scenarios/creative.js +7 -7
- package/dist/lib/testing/scenarios/creative.js.map +1 -1
- package/dist/lib/testing/scenarios/creative.mjs +7 -7
- package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
- package/dist/lib/testing/scenarios/discovery.js +2 -2
- package/dist/lib/testing/scenarios/discovery.js.map +1 -1
- package/dist/lib/testing/scenarios/discovery.mjs +2 -2
- package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.js +11 -11
- package/dist/lib/testing/scenarios/edge-cases.js.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.mjs +11 -11
- package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
- package/dist/lib/testing/scenarios/governance.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/governance.js +16 -22
- package/dist/lib/testing/scenarios/governance.js.map +1 -1
- package/dist/lib/testing/scenarios/governance.mjs +16 -22
- package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.js +5 -5
- package/dist/lib/testing/scenarios/media-buy.js.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.mjs +5 -5
- package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.js +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.js.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.mjs +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.d.ts.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.js +4 -3
- package/dist/lib/testing/scenarios/trusted-match.js.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.mjs +4 -3
- package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.d.mts +3 -4
- package/dist/lib/testing/storyboard/shape-drift-hints.d.ts +3 -4
- package/dist/lib/testing/storyboard/shape-drift-hints.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.js +27 -27
- package/dist/lib/testing/storyboard/shape-drift-hints.js.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs +27 -27
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/task-map.js +43 -5
- package/dist/lib/testing/storyboard/task-map.js.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +43 -5
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/test-helpers.d.mts +2 -2
- package/dist/lib/testing/test-helpers.d.ts +2 -2
- package/dist/lib/testing/test-helpers.js.map +1 -1
- package/dist/lib/testing/test-helpers.mjs.map +1 -1
- package/dist/lib/types/adcp.d.mts +14 -14
- package/dist/lib/types/adcp.d.ts +14 -14
- package/dist/lib/types/adcp.d.ts.map +1 -1
- package/dist/lib/types/adcp.js.map +1 -1
- package/dist/lib/types/adcp.mjs.map +1 -1
- package/dist/lib/types/index.d.mts +2 -2
- package/dist/lib/types/index.d.ts +2 -2
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/utils/capabilities.d.mts +6 -0
- package/dist/lib/utils/capabilities.d.ts +6 -0
- package/dist/lib/utils/capabilities.d.ts.map +1 -1
- package/dist/lib/utils/capabilities.js +4 -0
- package/dist/lib/utils/capabilities.js.map +1 -1
- package/dist/lib/utils/capabilities.mjs +4 -0
- package/dist/lib/utils/capabilities.mjs.map +1 -1
- package/dist/lib/utils/creative-delivery.d.mts +52 -10
- package/dist/lib/utils/creative-delivery.d.ts +52 -10
- package/dist/lib/utils/creative-delivery.d.ts.map +1 -1
- package/dist/lib/utils/creative-delivery.js +104 -9
- package/dist/lib/utils/creative-delivery.js.map +1 -1
- package/dist/lib/utils/creative-delivery.mjs +104 -8
- package/dist/lib/utils/creative-delivery.mjs.map +1 -1
- package/dist/lib/utils/format-assets.d.mts +41 -38
- package/dist/lib/utils/format-assets.d.ts +41 -38
- package/dist/lib/utils/format-assets.d.ts.map +1 -1
- package/dist/lib/utils/format-assets.js +3 -1
- package/dist/lib/utils/format-assets.js.map +1 -1
- package/dist/lib/utils/format-assets.mjs +3 -1
- package/dist/lib/utils/format-assets.mjs.map +1 -1
- package/dist/lib/utils/index.d.mts +8 -8
- package/dist/lib/utils/index.d.ts +8 -8
- package/dist/lib/utils/index.d.ts.map +1 -1
- package/dist/lib/utils/index.js +11 -9
- package/dist/lib/utils/index.js.map +1 -1
- package/dist/lib/utils/index.mjs +9 -8
- package/dist/lib/utils/index.mjs.map +1 -1
- package/dist/lib/utils/preview-utils.d.mts +11 -8
- package/dist/lib/utils/preview-utils.d.ts +11 -8
- package/dist/lib/utils/preview-utils.d.ts.map +1 -1
- package/dist/lib/utils/preview-utils.js +4 -4
- package/dist/lib/utils/preview-utils.js.map +1 -1
- package/dist/lib/utils/preview-utils.mjs +3 -3
- package/dist/lib/utils/preview-utils.mjs.map +1 -1
- package/dist/lib/utils/tool-request-schemas.d.mts +2 -2
- package/dist/lib/utils/tool-request-schemas.d.ts +2 -2
- package/dist/lib/v2/projection/aao-reference-formats.json +492 -0
- package/dist/lib/v2/projection/augment-response.d.mts +31 -11
- package/dist/lib/v2/projection/augment-response.d.ts +31 -11
- package/dist/lib/v2/projection/augment-response.d.ts.map +1 -1
- package/dist/lib/v2/projection/augment-response.js +233 -27
- package/dist/lib/v2/projection/augment-response.js.map +1 -1
- package/dist/lib/v2/projection/augment-response.mjs +232 -27
- package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
- package/dist/lib/v2/projection/builders.d.mts +7 -6
- package/dist/lib/v2/projection/builders.d.ts +7 -6
- package/dist/lib/v2/projection/builders.d.ts.map +1 -1
- package/dist/lib/v2/projection/builders.js +11 -8
- package/dist/lib/v2/projection/builders.js.map +1 -1
- package/dist/lib/v2/projection/builders.mjs +9 -6
- package/dist/lib/v2/projection/builders.mjs.map +1 -1
- package/dist/lib/v2/projection/catalog-snapshot.d.mts +47 -0
- package/dist/lib/v2/projection/catalog-snapshot.d.ts +48 -0
- package/dist/lib/v2/projection/catalog-snapshot.d.ts.map +1 -0
- package/dist/lib/v2/projection/catalog-snapshot.js +291 -0
- package/dist/lib/v2/projection/catalog-snapshot.js.map +1 -0
- package/dist/lib/v2/projection/catalog-snapshot.mjs +265 -0
- package/dist/lib/v2/projection/catalog-snapshot.mjs.map +1 -0
- package/dist/lib/v2/projection/catalog.d.mts +23 -2
- package/dist/lib/v2/projection/catalog.d.ts +23 -2
- package/dist/lib/v2/projection/catalog.d.ts.map +1 -1
- package/dist/lib/v2/projection/catalog.js +34 -10
- package/dist/lib/v2/projection/catalog.js.map +1 -1
- package/dist/lib/v2/projection/catalog.mjs +33 -10
- package/dist/lib/v2/projection/catalog.mjs.map +1 -1
- package/dist/lib/v2/projection/creative-delivery.d.mts +157 -0
- package/dist/lib/v2/projection/creative-delivery.d.ts +158 -0
- package/dist/lib/v2/projection/creative-delivery.d.ts.map +1 -0
- package/dist/lib/v2/projection/creative-delivery.js +967 -0
- package/dist/lib/v2/projection/creative-delivery.js.map +1 -0
- package/dist/lib/v2/projection/creative-delivery.mjs +941 -0
- package/dist/lib/v2/projection/creative-delivery.mjs.map +1 -0
- package/dist/lib/v2/projection/index.d.mts +8 -6
- package/dist/lib/v2/projection/index.d.ts +8 -6
- package/dist/lib/v2/projection/index.d.ts.map +1 -1
- package/dist/lib/v2/projection/index.js +26 -4
- package/dist/lib/v2/projection/index.js.map +1 -1
- package/dist/lib/v2/projection/index.mjs +28 -4
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/legacy-metadata.d.mts +21 -0
- package/dist/lib/v2/projection/legacy-metadata.d.ts +22 -0
- package/dist/lib/v2/projection/legacy-metadata.d.ts.map +1 -0
- package/dist/lib/v2/projection/legacy-metadata.js +73 -0
- package/dist/lib/v2/projection/legacy-metadata.js.map +1 -0
- package/dist/lib/v2/projection/legacy-metadata.mjs +45 -0
- package/dist/lib/v2/projection/legacy-metadata.mjs.map +1 -0
- package/dist/lib/v2/projection/types.d.mts +29 -23
- package/dist/lib/v2/projection/types.d.ts +29 -23
- package/dist/lib/v2/projection/types.d.ts.map +1 -1
- package/dist/lib/v2/projection/types.js.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.d.mts +29 -6
- package/dist/lib/v2/projection/v1-to-v2.d.ts +29 -6
- package/dist/lib/v2/projection/v1-to-v2.d.ts.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.js +218 -9
- package/dist/lib/v2/projection/v1-to-v2.js.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.mjs +219 -10
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.d.mts +31 -2
- package/dist/lib/v2/projection/v2-to-v1.d.ts +31 -2
- package/dist/lib/v2/projection/v2-to-v1.d.ts.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.js +138 -7
- package/dist/lib/v2/projection/v2-to-v1.js.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.mjs +135 -6
- package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
- package/dist/lib/v2/projection/write-side.d.mts +12 -13
- package/dist/lib/v2/projection/write-side.d.ts +12 -13
- package/dist/lib/v2/projection/write-side.d.ts.map +1 -1
- package/dist/lib/v2/projection/write-side.js +16 -12
- package/dist/lib/v2/projection/write-side.js.map +1 -1
- package/dist/lib/v2/projection/write-side.mjs +16 -12
- package/dist/lib/v2/projection/write-side.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/guides/BUILD-AN-AGENT.md +7 -2
- package/docs/guides/PREVIEW-ASSET-DURABILITY.md +6 -2
- package/docs/llms.txt +1 -0
- package/examples/README.md +1 -1
- package/examples/batch-preview-test.ts +3 -3
- package/examples/conversation-client.ts +2 -2
- package/examples/debug-preview-response.ts +1 -1
- package/examples/decisioning-platform-broadcast-tv.ts +10 -4
- package/examples/decisioning-platform-mock-seller.ts +16 -9
- package/examples/decisioning-platform-programmatic.ts +18 -7
- package/examples/error-compliant-server.ts +26 -16
- package/examples/generative-creative-demo.ts +7 -19
- package/examples/hello_creative_adapter_ad_server.ts +37 -16
- package/examples/hello_creative_adapter_template.ts +12 -10
- package/examples/hello_seller_adapter_guaranteed.ts +52 -23
- package/examples/hello_seller_adapter_multi_tenant.ts +6 -3
- package/examples/hello_seller_adapter_non_guaranteed.ts +54 -26
- package/examples/hello_seller_adapter_proposal_mode.ts +40 -14
- package/examples/hello_seller_adapter_social.ts +2 -7
- package/examples/inspect-card-formats.ts +1 -1
- package/examples/simple-getting-started.ts +1 -1
- package/examples/test-helpers-demo.ts +1 -1
- package/package.json +2 -2
- package/skills/build-decisioning-creative-template/SKILL.md +11 -11
- package/skills/build-decisioning-platform/advanced/REFERENCE.md +8 -2
|
@@ -19,11 +19,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var adapters_exports = {};
|
|
20
20
|
__export(adapters_exports, {
|
|
21
21
|
AISISessionManager: () => import_si_session_manager.AISISessionManager,
|
|
22
|
-
ContentStandardsAdapter: () => import_content_standards_adapter.ContentStandardsAdapter,
|
|
23
|
-
ContentStandardsErrorCodes: () => import_content_standards_adapter.ContentStandardsErrorCodes,
|
|
24
22
|
GovernanceAdapter: () => import_governance_adapter.GovernanceAdapter,
|
|
25
23
|
GovernanceAdapterErrorCodes: () => import_governance_adapter.GovernanceAdapterErrorCodes,
|
|
26
24
|
InMemoryImplicitAccountStore: () => import_implicit_account_store.InMemoryImplicitAccountStore,
|
|
25
|
+
LegacyContentStandardsAdapter: () => import_content_standards_adapter.LegacyContentStandardsAdapter,
|
|
26
|
+
LegacyContentStandardsErrorCodes: () => import_content_standards_adapter.LegacyContentStandardsErrorCodes,
|
|
27
27
|
PropertyListAdapter: () => import_property_list_adapter.PropertyListAdapter,
|
|
28
28
|
PropertyListErrorCodes: () => import_property_list_adapter.PropertyListErrorCodes,
|
|
29
29
|
SIErrorCodes: () => import_si_session_manager.SIErrorCodes,
|
|
@@ -31,14 +31,14 @@ __export(adapters_exports, {
|
|
|
31
31
|
createDerivedAccountStore: () => import_derived_account_store.createDerivedAccountStore,
|
|
32
32
|
createOAuthPassthroughResolver: () => import_oauth_passthrough_resolver.createOAuthPassthroughResolver,
|
|
33
33
|
createRosterAccountStore: () => import_roster_account_store.createRosterAccountStore,
|
|
34
|
-
defaultContentStandardsAdapter: () => import_content_standards_adapter.defaultContentStandardsAdapter,
|
|
35
34
|
defaultGovernanceAdapter: () => import_governance_adapter.defaultGovernanceAdapter,
|
|
36
35
|
defaultImplicitKeyFn: () => import_implicit_account_store.defaultImplicitKeyFn,
|
|
37
36
|
defaultPropertyListAdapter: () => import_property_list_adapter.defaultPropertyListAdapter,
|
|
38
37
|
defaultSISessionManager: () => import_si_session_manager.defaultSISessionManager,
|
|
39
|
-
isContentStandardsError: () => import_content_standards_adapter.isContentStandardsError,
|
|
40
38
|
isGovernanceAdapterError: () => import_governance_adapter.isGovernanceAdapterError,
|
|
41
|
-
|
|
39
|
+
isLegacyContentStandardsError: () => import_content_standards_adapter.isLegacyContentStandardsError,
|
|
40
|
+
isPropertyListError: () => import_property_list_adapter.isPropertyListError,
|
|
41
|
+
legacyDefaultContentStandardsAdapter: () => import_content_standards_adapter.legacyDefaultContentStandardsAdapter
|
|
42
42
|
});
|
|
43
43
|
module.exports = __toCommonJS(adapters_exports);
|
|
44
44
|
var import_content_standards_adapter = require('./content-standards-adapter.js');
|
|
@@ -52,11 +52,11 @@ var import_derived_account_store = require('./derived-account-store.js');
|
|
|
52
52
|
// Annotate the CommonJS export names for ESM import in node:
|
|
53
53
|
0 && (module.exports = {
|
|
54
54
|
AISISessionManager,
|
|
55
|
-
ContentStandardsAdapter,
|
|
56
|
-
ContentStandardsErrorCodes,
|
|
57
55
|
GovernanceAdapter,
|
|
58
56
|
GovernanceAdapterErrorCodes,
|
|
59
57
|
InMemoryImplicitAccountStore,
|
|
58
|
+
LegacyContentStandardsAdapter,
|
|
59
|
+
LegacyContentStandardsErrorCodes,
|
|
60
60
|
PropertyListAdapter,
|
|
61
61
|
PropertyListErrorCodes,
|
|
62
62
|
SIErrorCodes,
|
|
@@ -64,13 +64,13 @@ var import_derived_account_store = require('./derived-account-store.js');
|
|
|
64
64
|
createDerivedAccountStore,
|
|
65
65
|
createOAuthPassthroughResolver,
|
|
66
66
|
createRosterAccountStore,
|
|
67
|
-
defaultContentStandardsAdapter,
|
|
68
67
|
defaultGovernanceAdapter,
|
|
69
68
|
defaultImplicitKeyFn,
|
|
70
69
|
defaultPropertyListAdapter,
|
|
71
70
|
defaultSISessionManager,
|
|
72
|
-
isContentStandardsError,
|
|
73
71
|
isGovernanceAdapterError,
|
|
74
|
-
|
|
72
|
+
isLegacyContentStandardsError,
|
|
73
|
+
isPropertyListError,
|
|
74
|
+
legacyDefaultContentStandardsAdapter
|
|
75
75
|
});
|
|
76
76
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/adapters/index.ts"],"sourcesContent":["/**\n * Server-Side Adapters\n *\n * These adapters allow publishers/brands to plug in their business logic\n * when implementing AdCP servers. Each adapter provides a stub implementation\n * that can be extended or replaced.\n *\n * Usage:\n * -
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/adapters/index.ts"],"sourcesContent":["/**\n * Server-Side Adapters\n *\n * These adapters allow publishers/brands to plug in their business logic\n * when implementing AdCP servers. Each adapter provides a stub implementation\n * that can be extended or replaced.\n *\n * Usage:\n * - LegacyContentStandardsAdapter: Maintain raw content-standard integrations during migration\n * - PropertyListAdapter: Manage buyer-defined property lists\n * - SISessionManager: Handle Sponsored Intelligence conversational sessions\n * - InMemoryImplicitAccountStore: AccountStore for resolution: 'implicit' platforms\n */\n\n// Content Standards\nexport {\n LegacyContentStandardsAdapter,\n type LegacyIContentStandardsAdapter,\n type LegacyContentEvaluationResult,\n LegacyContentStandardsErrorCodes,\n isLegacyContentStandardsError,\n legacyDefaultContentStandardsAdapter,\n} from './content-standards-adapter';\n\n// Property Lists\nexport {\n PropertyListAdapter,\n type IPropertyListAdapter,\n type ResolvedProperty,\n PropertyListErrorCodes,\n isPropertyListError,\n defaultPropertyListAdapter,\n} from './property-list-adapter';\n\n// Governance (seller-side committed checks)\nexport {\n GovernanceAdapter,\n defaultGovernanceAdapter,\n type IGovernanceAdapter,\n type GovernanceAdapterConfig,\n type GovernanceAdapterErrorCode,\n type CommittedCheckRequest,\n GovernanceAdapterErrorCodes,\n isGovernanceAdapterError,\n} from './governance-adapter';\n\n// Sponsored Intelligence Sessions\nexport {\n SISessionManager,\n AISISessionManager,\n type ISISessionManager,\n type SISession,\n SIErrorCodes,\n defaultSISessionManager,\n} from './si-session-manager';\n\n// Implicit Account Store (resolution: 'implicit') — Shape A reference adapter.\nexport {\n InMemoryImplicitAccountStore,\n defaultImplicitKeyFn,\n type ImplicitAccountStoreOptions,\n} from './implicit-account-store';\n\n// OAuth pass-through resolver — closes adcp-client#1363. Shape B factory\n// for adapters wrapping a vendor OAuth + ad-account API; replaces the ~30\n// LOC of bearer-extract + listing-fetch + match-by-id boilerplate every\n// such adapter re-derives by hand.\nexport { createOAuthPassthroughResolver, type OAuthPassthroughResolverOptions } from './oauth-passthrough-resolver';\n\n// Roster-backed AccountStore — Shape C factory for `resolution: 'explicit'`\n// publisher-curated platforms. Adopters bring their own roster source (admin-UI\n// managed DB row, in-memory map, file); the helper provides AccountStore\n// plumbing (resolve dispatch, optional list, ctx threading) with no opinion on\n// where the roster lives.\nexport { createRosterAccountStore, type RosterAccountStoreOptions } from './roster-account-store';\n\n// Derived AccountStore — Shape D factory for `resolution: 'derived'` single-\n// tenant agents (no account_id on the wire; auth principal alone identifies\n// the tenant). Closes adcp-client#1462. Replaces ~25–30 LOC of bearer-extract +\n// throw-AUTH_REQUIRED + return-singleton boilerplate Shape D adopters write today.\nexport { createDerivedAccountStore, type DerivedAccountStoreOptions } from './derived-account-store';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA,uCAOO;AAGP,mCAOO;AAGP,gCASO;AAGP,gCAOO;AAGP,oCAIO;AAMP,wCAAqF;AAOrF,kCAAyE;AAMzE,mCAA2E;","names":[]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
LegacyContentStandardsAdapter,
|
|
3
|
+
LegacyContentStandardsErrorCodes,
|
|
4
|
+
isLegacyContentStandardsError,
|
|
5
|
+
legacyDefaultContentStandardsAdapter
|
|
6
6
|
} from "./content-standards-adapter.mjs";
|
|
7
7
|
import {
|
|
8
8
|
PropertyListAdapter,
|
|
@@ -31,11 +31,11 @@ import { createRosterAccountStore } from "./roster-account-store.mjs";
|
|
|
31
31
|
import { createDerivedAccountStore } from "./derived-account-store.mjs";
|
|
32
32
|
export {
|
|
33
33
|
AISISessionManager,
|
|
34
|
-
ContentStandardsAdapter,
|
|
35
|
-
ContentStandardsErrorCodes,
|
|
36
34
|
GovernanceAdapter,
|
|
37
35
|
GovernanceAdapterErrorCodes,
|
|
38
36
|
InMemoryImplicitAccountStore,
|
|
37
|
+
LegacyContentStandardsAdapter,
|
|
38
|
+
LegacyContentStandardsErrorCodes,
|
|
39
39
|
PropertyListAdapter,
|
|
40
40
|
PropertyListErrorCodes,
|
|
41
41
|
SIErrorCodes,
|
|
@@ -43,13 +43,13 @@ export {
|
|
|
43
43
|
createDerivedAccountStore,
|
|
44
44
|
createOAuthPassthroughResolver,
|
|
45
45
|
createRosterAccountStore,
|
|
46
|
-
defaultContentStandardsAdapter,
|
|
47
46
|
defaultGovernanceAdapter,
|
|
48
47
|
defaultImplicitKeyFn,
|
|
49
48
|
defaultPropertyListAdapter,
|
|
50
49
|
defaultSISessionManager,
|
|
51
|
-
isContentStandardsError,
|
|
52
50
|
isGovernanceAdapterError,
|
|
53
|
-
|
|
51
|
+
isLegacyContentStandardsError,
|
|
52
|
+
isPropertyListError,
|
|
53
|
+
legacyDefaultContentStandardsAdapter
|
|
54
54
|
};
|
|
55
55
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/adapters/index.ts"],"sourcesContent":["/**\n * Server-Side Adapters\n *\n * These adapters allow publishers/brands to plug in their business logic\n * when implementing AdCP servers. Each adapter provides a stub implementation\n * that can be extended or replaced.\n *\n * Usage:\n * -
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/adapters/index.ts"],"sourcesContent":["/**\n * Server-Side Adapters\n *\n * These adapters allow publishers/brands to plug in their business logic\n * when implementing AdCP servers. Each adapter provides a stub implementation\n * that can be extended or replaced.\n *\n * Usage:\n * - LegacyContentStandardsAdapter: Maintain raw content-standard integrations during migration\n * - PropertyListAdapter: Manage buyer-defined property lists\n * - SISessionManager: Handle Sponsored Intelligence conversational sessions\n * - InMemoryImplicitAccountStore: AccountStore for resolution: 'implicit' platforms\n */\n\n// Content Standards\nexport {\n LegacyContentStandardsAdapter,\n type LegacyIContentStandardsAdapter,\n type LegacyContentEvaluationResult,\n LegacyContentStandardsErrorCodes,\n isLegacyContentStandardsError,\n legacyDefaultContentStandardsAdapter,\n} from './content-standards-adapter';\n\n// Property Lists\nexport {\n PropertyListAdapter,\n type IPropertyListAdapter,\n type ResolvedProperty,\n PropertyListErrorCodes,\n isPropertyListError,\n defaultPropertyListAdapter,\n} from './property-list-adapter';\n\n// Governance (seller-side committed checks)\nexport {\n GovernanceAdapter,\n defaultGovernanceAdapter,\n type IGovernanceAdapter,\n type GovernanceAdapterConfig,\n type GovernanceAdapterErrorCode,\n type CommittedCheckRequest,\n GovernanceAdapterErrorCodes,\n isGovernanceAdapterError,\n} from './governance-adapter';\n\n// Sponsored Intelligence Sessions\nexport {\n SISessionManager,\n AISISessionManager,\n type ISISessionManager,\n type SISession,\n SIErrorCodes,\n defaultSISessionManager,\n} from './si-session-manager';\n\n// Implicit Account Store (resolution: 'implicit') — Shape A reference adapter.\nexport {\n InMemoryImplicitAccountStore,\n defaultImplicitKeyFn,\n type ImplicitAccountStoreOptions,\n} from './implicit-account-store';\n\n// OAuth pass-through resolver — closes adcp-client#1363. Shape B factory\n// for adapters wrapping a vendor OAuth + ad-account API; replaces the ~30\n// LOC of bearer-extract + listing-fetch + match-by-id boilerplate every\n// such adapter re-derives by hand.\nexport { createOAuthPassthroughResolver, type OAuthPassthroughResolverOptions } from './oauth-passthrough-resolver';\n\n// Roster-backed AccountStore — Shape C factory for `resolution: 'explicit'`\n// publisher-curated platforms. Adopters bring their own roster source (admin-UI\n// managed DB row, in-memory map, file); the helper provides AccountStore\n// plumbing (resolve dispatch, optional list, ctx threading) with no opinion on\n// where the roster lives.\nexport { createRosterAccountStore, type RosterAccountStoreOptions } from './roster-account-store';\n\n// Derived AccountStore — Shape D factory for `resolution: 'derived'` single-\n// tenant agents (no account_id on the wire; auth principal alone identifies\n// the tenant). Closes adcp-client#1462. Replaces ~25–30 LOC of bearer-extract +\n// throw-AUTH_REQUIRED + return-singleton boilerplate Shape D adopters write today.\nexport { createDerivedAccountStore, type DerivedAccountStoreOptions } from './derived-account-store';\n"],"mappings":"AAeA;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EAKA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAMP,SAAS,sCAA4E;AAOrF,SAAS,gCAAgE;AAMzE,SAAS,iCAAkE;","names":[]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createNonInteractiveOAuthProvider } from './index.mjs';
|
|
2
|
+
import type { MCPOAuthProvider } from './MCPOAuthProvider.mjs';
|
|
3
|
+
import type { AgentConfig } from './types.mjs';
|
|
4
|
+
/** Reuse one refresh-capable provider for repeated calls in the same agent authorization context. */
|
|
5
|
+
export declare function getNonInteractiveOAuthProvider(agent: AgentConfig, options?: Parameters<typeof createNonInteractiveOAuthProvider>[1]): MCPOAuthProvider;
|
|
6
|
+
/** Preserve provider identity when endpoint discovery creates a derived AgentConfig object. */
|
|
7
|
+
export declare function shareNonInteractiveOAuthProvider(source: AgentConfig, target: AgentConfig): void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createNonInteractiveOAuthProvider } from './index';
|
|
2
|
+
import type { MCPOAuthProvider } from './MCPOAuthProvider';
|
|
3
|
+
import type { AgentConfig } from './types';
|
|
4
|
+
/** Reuse one refresh-capable provider for repeated calls in the same agent authorization context. */
|
|
5
|
+
export declare function getNonInteractiveOAuthProvider(agent: AgentConfig, options?: Parameters<typeof createNonInteractiveOAuthProvider>[1]): MCPOAuthProvider;
|
|
6
|
+
/** Preserve provider identity when endpoint discovery creates a derived AgentConfig object. */
|
|
7
|
+
export declare function shareNonInteractiveOAuthProvider(source: AgentConfig, target: AgentConfig): void;
|
|
8
|
+
//# sourceMappingURL=provider-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-cache.d.ts","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/provider-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI3C,qGAAqG;AACrG,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,WAAW,EAClB,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,iCAAiC,CAAC,CAAC,CAAC,CAAC,GAChE,gBAAgB,CAOlB;AAED,+FAA+F;AAC/F,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAG/F"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var provider_cache_exports = {};
|
|
20
|
+
__export(provider_cache_exports, {
|
|
21
|
+
getNonInteractiveOAuthProvider: () => getNonInteractiveOAuthProvider,
|
|
22
|
+
shareNonInteractiveOAuthProvider: () => shareNonInteractiveOAuthProvider
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(provider_cache_exports);
|
|
25
|
+
var import_index = require('./index.js');
|
|
26
|
+
const nonInteractiveOAuthProviderCache = /* @__PURE__ */ new WeakMap();
|
|
27
|
+
function getNonInteractiveOAuthProvider(agent, options) {
|
|
28
|
+
let provider = nonInteractiveOAuthProviderCache.get(agent);
|
|
29
|
+
if (!provider) {
|
|
30
|
+
provider = (0, import_index.createNonInteractiveOAuthProvider)(agent, options);
|
|
31
|
+
nonInteractiveOAuthProviderCache.set(agent, provider);
|
|
32
|
+
}
|
|
33
|
+
return provider;
|
|
34
|
+
}
|
|
35
|
+
function shareNonInteractiveOAuthProvider(source, target) {
|
|
36
|
+
const provider = nonInteractiveOAuthProviderCache.get(source);
|
|
37
|
+
if (provider) nonInteractiveOAuthProviderCache.set(target, provider);
|
|
38
|
+
}
|
|
39
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
40
|
+
0 && (module.exports = {
|
|
41
|
+
getNonInteractiveOAuthProvider,
|
|
42
|
+
shareNonInteractiveOAuthProvider
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=provider-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/auth/oauth/provider-cache.ts"],"sourcesContent":["import { createNonInteractiveOAuthProvider } from './index';\nimport type { MCPOAuthProvider } from './MCPOAuthProvider';\nimport type { AgentConfig } from './types';\n\nconst nonInteractiveOAuthProviderCache = new WeakMap<AgentConfig, MCPOAuthProvider>();\n\n/** Reuse one refresh-capable provider for repeated calls in the same agent authorization context. */\nexport function getNonInteractiveOAuthProvider(\n agent: AgentConfig,\n options?: Parameters<typeof createNonInteractiveOAuthProvider>[1]\n): MCPOAuthProvider {\n let provider = nonInteractiveOAuthProviderCache.get(agent);\n if (!provider) {\n provider = createNonInteractiveOAuthProvider(agent, options);\n nonInteractiveOAuthProviderCache.set(agent, provider);\n }\n return provider;\n}\n\n/** Preserve provider identity when endpoint discovery creates a derived AgentConfig object. */\nexport function shareNonInteractiveOAuthProvider(source: AgentConfig, target: AgentConfig): void {\n const provider = nonInteractiveOAuthProviderCache.get(source);\n if (provider) nonInteractiveOAuthProviderCache.set(target, provider);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkD;AAIlD,MAAM,mCAAmC,oBAAI,QAAuC;AAG7E,SAAS,+BACd,OACA,SACkB;AAClB,MAAI,WAAW,iCAAiC,IAAI,KAAK;AACzD,MAAI,CAAC,UAAU;AACb,mBAAW,gDAAkC,OAAO,OAAO;AAC3D,qCAAiC,IAAI,OAAO,QAAQ;AAAA,EACtD;AACA,SAAO;AACT;AAGO,SAAS,iCAAiC,QAAqB,QAA2B;AAC/F,QAAM,WAAW,iCAAiC,IAAI,MAAM;AAC5D,MAAI,SAAU,kCAAiC,IAAI,QAAQ,QAAQ;AACrE;","names":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createNonInteractiveOAuthProvider } from "./index.mjs";
|
|
2
|
+
const nonInteractiveOAuthProviderCache = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
function getNonInteractiveOAuthProvider(agent, options) {
|
|
4
|
+
let provider = nonInteractiveOAuthProviderCache.get(agent);
|
|
5
|
+
if (!provider) {
|
|
6
|
+
provider = createNonInteractiveOAuthProvider(agent, options);
|
|
7
|
+
nonInteractiveOAuthProviderCache.set(agent, provider);
|
|
8
|
+
}
|
|
9
|
+
return provider;
|
|
10
|
+
}
|
|
11
|
+
function shareNonInteractiveOAuthProvider(source, target) {
|
|
12
|
+
const provider = nonInteractiveOAuthProviderCache.get(source);
|
|
13
|
+
if (provider) nonInteractiveOAuthProviderCache.set(target, provider);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
getNonInteractiveOAuthProvider,
|
|
17
|
+
shareNonInteractiveOAuthProvider
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=provider-cache.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/auth/oauth/provider-cache.ts"],"sourcesContent":["import { createNonInteractiveOAuthProvider } from './index';\nimport type { MCPOAuthProvider } from './MCPOAuthProvider';\nimport type { AgentConfig } from './types';\n\nconst nonInteractiveOAuthProviderCache = new WeakMap<AgentConfig, MCPOAuthProvider>();\n\n/** Reuse one refresh-capable provider for repeated calls in the same agent authorization context. */\nexport function getNonInteractiveOAuthProvider(\n agent: AgentConfig,\n options?: Parameters<typeof createNonInteractiveOAuthProvider>[1]\n): MCPOAuthProvider {\n let provider = nonInteractiveOAuthProviderCache.get(agent);\n if (!provider) {\n provider = createNonInteractiveOAuthProvider(agent, options);\n nonInteractiveOAuthProviderCache.set(agent, provider);\n }\n return provider;\n}\n\n/** Preserve provider identity when endpoint discovery creates a derived AgentConfig object. */\nexport function shareNonInteractiveOAuthProvider(source: AgentConfig, target: AgentConfig): void {\n const provider = nonInteractiveOAuthProviderCache.get(source);\n if (provider) nonInteractiveOAuthProviderCache.set(target, provider);\n}\n"],"mappings":"AAAA,SAAS,yCAAyC;AAIlD,MAAM,mCAAmC,oBAAI,QAAuC;AAG7E,SAAS,+BACd,OACA,SACkB;AAClB,MAAI,WAAW,iCAAiC,IAAI,KAAK;AACzD,MAAI,CAAC,UAAU;AACb,eAAW,kCAAkC,OAAO,OAAO;AAC3D,qCAAiC,IAAI,OAAO,QAAQ;AAAA,EACtD;AACA,SAAO;AACT;AAGO,SAAS,iCAAiC,QAAqB,QAA2B;AAC/F,QAAM,WAAW,iCAAiC,IAAI,MAAM;AAC5D,MAAI,SAAU,kCAAiC,IAAI,QAAQ,QAAQ;AACrE;","names":[]}
|
|
@@ -120,7 +120,7 @@ async function runUniformErrorInvariant(tool, options) {
|
|
|
120
120
|
async function capturedProbe(agent, tool, request, options) {
|
|
121
121
|
try {
|
|
122
122
|
const { captures } = await (0, import_rawResponseCapture.withRawResponseCapture)(async () => {
|
|
123
|
-
await agent.
|
|
123
|
+
await agent.executeTaskLegacy(tool, request);
|
|
124
124
|
}, options);
|
|
125
125
|
const toolCallCapture = lastPostCapture(captures);
|
|
126
126
|
if (!toolCallCapture) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/conformance/invariants/uniformError.ts"],"sourcesContent":["// Uniform error response invariant (adcp spec § error-handling).\n//\n// The spec MUSTs that a seller returns byte-equivalent responses for\n// \"the id exists but the caller lacks access\" vs \"the id does not\n// exist\" — through every observable channel (error code/message/field/\n// details, HTTP status, A2A task state / MCP isError, response headers,\n// latency distribution). Distinguishing the two leaks cross-tenant\n// existence information.\n//\n// This invariant exercises the MUST with a paired probe: two requests\n// to the same tool, compared byte-for-byte.\n//\n// Pairing modes:\n// - baseline: two fresh UUIDs, single auth token. Catches id-echo\n// leaks, header divergence, and grossly different latency. Does\n// not catch cross-tenant leaks — both ids are impossible, so the\n// \"inaccessible vs unknown\" branch never fires.\n// - cross-tenant: one seeded id owned by tenant A plus one fresh\n// UUID, both probed as tenant B. Catches the full MUST.\n//\n// Tool coverage is keyed by TOOL_ID_CONFIG below. A tool must expose\n// a single scalar \"lookup id\" field and have a matching seeder before\n// it can be probed.\n\nimport { AgentClient } from '../../core/AgentClient';\nimport { randomUUID } from 'node:crypto';\nimport { withRawResponseCapture, type RawHttpCapture } from '../../protocols/rawResponseCapture';\nimport type { ConformanceFixtures, ConformanceToolName } from '../types';\nimport { compareProbes, type ProbeComparisonResult } from './uniformErrorComparator';\n\nexport type UniformErrorVerdict = 'pass' | 'fail' | 'skipped';\n\nexport interface UniformErrorReport {\n tool: ConformanceToolName;\n /** Which pairing actually ran. */\n mode: 'baseline' | 'cross-tenant';\n verdict: UniformErrorVerdict;\n /** Populated on verdict === 'skipped'. */\n skipReason?: string;\n /** Populated on verdict !== 'skipped'. */\n differences?: string[];\n /** Probe summaries for diagnostics. Sanitized via `summarizeCapture`. */\n probes?: {\n inaccessibleOrRandomA: ProbeSummary;\n impossibleOrRandomB: ProbeSummary;\n };\n}\n\nexport interface ProbeSummary {\n /** Label describing what kind of id was probed. */\n label: 'cross-tenant' | 'impossible' | 'random-a' | 'random-b';\n status: number | null;\n headers: Record<string, string>;\n body: string;\n latencyMs: number;\n /** Whether the capture body was truncated. */\n bodyTruncated: boolean;\n}\n\n/**\n * Per-tool configuration for the invariant. Each tool that can be\n * probed declares:\n * - the single id field to mutate\n * - the fixture key that holds a seeded id (for cross-tenant mode)\n * - a minimal request builder given the id\n *\n * Extending coverage to more tools is additive — populate a new entry.\n */\ninterface ToolIdConfig {\n idField: string;\n /**\n * Fixture pool that holds a seeded \"accessible to tenant A\" id for\n * cross-tenant mode. When omitted, cross-tenant mode is unavailable\n * for this tool — baseline is the only mode. Useful for tools whose\n * ids don't come from a seeder (catalog-style lookups, provider-\n * owned signals, etc.).\n */\n fixtureKey?: keyof ConformanceFixtures;\n buildRequest: (id: string) => Record<string, unknown>;\n}\n\nconst TOOL_ID_CONFIG: Partial<Record<ConformanceToolName, ToolIdConfig>> = {\n get_property_list: {\n idField: 'list_id',\n fixtureKey: 'list_ids',\n buildRequest: id => ({ list_id: id }),\n },\n get_content_standards: {\n idField: 'standards_id',\n fixtureKey: 'standards_ids',\n buildRequest: id => ({ standards_id: id }),\n },\n get_media_buy_delivery: {\n idField: 'media_buy_id',\n fixtureKey: 'media_buy_ids',\n buildRequest: id => {\n // Spec-min request: one buy id + a date range wide enough to avoid\n // per-seller reporting-window rejection. Dates are arbitrary — the\n // resolution happens before access-check per the spec, so the\n // response must be byte-equivalent regardless of window.\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { media_buy_ids: [id], start_date: start, end_date: end };\n },\n },\n get_creative_delivery: {\n idField: 'creative_id',\n fixtureKey: 'creative_ids',\n buildRequest: id => {\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { creative_ids: [id], start_date: start, end_date: end };\n },\n },\n tasks_get: {\n idField: 'task_id',\n fixtureKey: 'task_ids',\n buildRequest: id => ({ task_id: id }),\n },\n get_signals: {\n idField: 'signal_ids',\n // No seeder for signals today (catalog signals are provider-\n // controlled, not agent-created). Baseline-only: two fresh UUIDs\n // wrapped in a SignalID shape, probed under the single caller\n // token. Cross-tenant mode becomes available when the signals\n // protocol grows a create/sync path and a seeder produces ids.\n buildRequest: id => ({\n signal_ids: [{ source: 'catalog', data_provider_domain: 'conformance.example', id }],\n }),\n },\n};\n\n/** Tools eligible for the uniform-error probe. Used by the runner wiring. */\nexport function toolsEligibleForUniformError(): ConformanceToolName[] {\n return Object.keys(TOOL_ID_CONFIG) as ConformanceToolName[];\n}\n\nexport interface ProbeOptions {\n /** Agent client that probes with the \"caller\" credentials (tenant B in cross-tenant mode). */\n prober: AgentClient;\n /** Fixtures accumulated so far — drawn from for cross-tenant mode. */\n fixtures: ConformanceFixtures;\n /** Whether a distinct cross-tenant token was configured. When false, mode is 'baseline'. */\n crossTenantConfigured: boolean;\n /**\n * Cap individual probe body size in the capture. Defaults to the\n * rawResponseCapture default. Not usually worth overriding.\n */\n maxBodyBytes?: number;\n}\n\nexport async function runUniformErrorInvariant(\n tool: ConformanceToolName,\n options: ProbeOptions\n): Promise<UniformErrorReport> {\n const config = TOOL_ID_CONFIG[tool];\n if (!config) {\n return {\n tool,\n mode: options.crossTenantConfigured ? 'cross-tenant' : 'baseline',\n verdict: 'skipped',\n skipReason: 'tool not in TOOL_ID_CONFIG',\n };\n }\n\n // Resolve the pair of ids under probe.\n //\n // Cross-tenant mode needs a seeded id (tenant A owns the resource;\n // tenant B is probing it — that's the \"exists but inaccessible\" leg).\n // Missing seeded id (or a tool with no fixtureKey at all, like\n // get_signals) → fall back to baseline rather than skipping; the\n // baseline still catches id-echo and header-divergence leaks.\n const seededPool = config.fixtureKey ? (options.fixtures[config.fixtureKey] ?? []) : [];\n const seededId = seededPool[0];\n const mode: UniformErrorReport['mode'] = options.crossTenantConfigured && seededId ? 'cross-tenant' : 'baseline';\n\n const idA = mode === 'cross-tenant' ? (seededId as string) : randomUUID();\n const idB = randomUUID();\n const labelA: ProbeSummary['label'] = mode === 'cross-tenant' ? 'cross-tenant' : 'random-a';\n const labelB: ProbeSummary['label'] = mode === 'cross-tenant' ? 'impossible' : 'random-b';\n\n const captureOpts = { maxBodyBytes: options.maxBodyBytes };\n\n const probeA = await capturedProbe(options.prober, tool, config.buildRequest(idA), captureOpts);\n const probeB = await capturedProbe(options.prober, tool, config.buildRequest(idB), captureOpts);\n\n if (!probeA.capture || !probeB.capture) {\n // One side didn't produce a capture — the underlying transport\n // surfaced an error before we could observe the response (e.g.,\n // the SDK threw an AuthenticationRequiredError). Report the root\n // cause so the operator knows why the invariant skipped.\n const reason = probeA.error ?? probeB.error ?? 'no capture observed';\n return {\n tool,\n mode,\n verdict: 'skipped',\n skipReason: `probe did not produce a raw capture (${reason})`,\n };\n }\n\n const comparison = compareProbes(probeA.capture, probeB.capture);\n\n return {\n tool,\n mode,\n verdict: comparison.equivalent ? 'pass' : 'fail',\n differences: comparison.differences,\n probes: {\n inaccessibleOrRandomA: summarizeCapture(probeA.capture, labelA),\n impossibleOrRandomB: summarizeCapture(probeB.capture, labelB),\n },\n };\n}\n\ninterface ProbeOutcome {\n capture?: RawHttpCapture;\n /** Error message when executeTask threw before producing a capture. */\n error?: string;\n}\n\n/**\n * Execute a probe inside a capture context and return the tool-call\n * response. Filters captures to POST — MCP's tool call and A2A's\n * `sendMessage` are both POSTs, while A2A's `/.well-known/agent.json`\n * discovery (issued on a fresh client) is a GET that we must not\n * confuse with the tool response.\n */\nasync function capturedProbe(\n agent: AgentClient,\n tool: ConformanceToolName,\n request: Record<string, unknown>,\n options: { maxBodyBytes?: number }\n): Promise<ProbeOutcome> {\n try {\n const { captures } = await withRawResponseCapture(async () => {\n await agent.executeTask(tool, request);\n }, options);\n const toolCallCapture = lastPostCapture(captures);\n if (!toolCallCapture) {\n return { error: 'captured only non-POST traffic' };\n }\n return { capture: toolCallCapture };\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction lastPostCapture(captures: readonly RawHttpCapture[]): RawHttpCapture | undefined {\n for (let i = captures.length - 1; i >= 0; i--) {\n const cap = captures[i];\n if (cap && cap.method === 'POST') return cap;\n }\n return undefined;\n}\n\nfunction summarizeCapture(cap: RawHttpCapture, label: ProbeSummary['label']): ProbeSummary {\n return {\n label,\n status: cap.status,\n headers: cap.headers,\n body: cap.body,\n latencyMs: cap.latencyMs,\n bodyTruncated: cap.bodyTruncated,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/conformance/invariants/uniformError.ts"],"sourcesContent":["// Uniform error response invariant (adcp spec § error-handling).\n//\n// The spec MUSTs that a seller returns byte-equivalent responses for\n// \"the id exists but the caller lacks access\" vs \"the id does not\n// exist\" — through every observable channel (error code/message/field/\n// details, HTTP status, A2A task state / MCP isError, response headers,\n// latency distribution). Distinguishing the two leaks cross-tenant\n// existence information.\n//\n// This invariant exercises the MUST with a paired probe: two requests\n// to the same tool, compared byte-for-byte.\n//\n// Pairing modes:\n// - baseline: two fresh UUIDs, single auth token. Catches id-echo\n// leaks, header divergence, and grossly different latency. Does\n// not catch cross-tenant leaks — both ids are impossible, so the\n// \"inaccessible vs unknown\" branch never fires.\n// - cross-tenant: one seeded id owned by tenant A plus one fresh\n// UUID, both probed as tenant B. Catches the full MUST.\n//\n// Tool coverage is keyed by TOOL_ID_CONFIG below. A tool must expose\n// a single scalar \"lookup id\" field and have a matching seeder before\n// it can be probed.\n\nimport { AgentClient } from '../../core/AgentClient';\nimport { randomUUID } from 'node:crypto';\nimport { withRawResponseCapture, type RawHttpCapture } from '../../protocols/rawResponseCapture';\nimport type { ConformanceFixtures, ConformanceToolName } from '../types';\nimport { compareProbes, type ProbeComparisonResult } from './uniformErrorComparator';\n\nexport type UniformErrorVerdict = 'pass' | 'fail' | 'skipped';\n\nexport interface UniformErrorReport {\n tool: ConformanceToolName;\n /** Which pairing actually ran. */\n mode: 'baseline' | 'cross-tenant';\n verdict: UniformErrorVerdict;\n /** Populated on verdict === 'skipped'. */\n skipReason?: string;\n /** Populated on verdict !== 'skipped'. */\n differences?: string[];\n /** Probe summaries for diagnostics. Sanitized via `summarizeCapture`. */\n probes?: {\n inaccessibleOrRandomA: ProbeSummary;\n impossibleOrRandomB: ProbeSummary;\n };\n}\n\nexport interface ProbeSummary {\n /** Label describing what kind of id was probed. */\n label: 'cross-tenant' | 'impossible' | 'random-a' | 'random-b';\n status: number | null;\n headers: Record<string, string>;\n body: string;\n latencyMs: number;\n /** Whether the capture body was truncated. */\n bodyTruncated: boolean;\n}\n\n/**\n * Per-tool configuration for the invariant. Each tool that can be\n * probed declares:\n * - the single id field to mutate\n * - the fixture key that holds a seeded id (for cross-tenant mode)\n * - a minimal request builder given the id\n *\n * Extending coverage to more tools is additive — populate a new entry.\n */\ninterface ToolIdConfig {\n idField: string;\n /**\n * Fixture pool that holds a seeded \"accessible to tenant A\" id for\n * cross-tenant mode. When omitted, cross-tenant mode is unavailable\n * for this tool — baseline is the only mode. Useful for tools whose\n * ids don't come from a seeder (catalog-style lookups, provider-\n * owned signals, etc.).\n */\n fixtureKey?: keyof ConformanceFixtures;\n buildRequest: (id: string) => Record<string, unknown>;\n}\n\nconst TOOL_ID_CONFIG: Partial<Record<ConformanceToolName, ToolIdConfig>> = {\n get_property_list: {\n idField: 'list_id',\n fixtureKey: 'list_ids',\n buildRequest: id => ({ list_id: id }),\n },\n get_content_standards: {\n idField: 'standards_id',\n fixtureKey: 'standards_ids',\n buildRequest: id => ({ standards_id: id }),\n },\n get_media_buy_delivery: {\n idField: 'media_buy_id',\n fixtureKey: 'media_buy_ids',\n buildRequest: id => {\n // Spec-min request: one buy id + a date range wide enough to avoid\n // per-seller reporting-window rejection. Dates are arbitrary — the\n // resolution happens before access-check per the spec, so the\n // response must be byte-equivalent regardless of window.\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { media_buy_ids: [id], start_date: start, end_date: end };\n },\n },\n get_creative_delivery: {\n idField: 'creative_id',\n fixtureKey: 'creative_ids',\n buildRequest: id => {\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { creative_ids: [id], start_date: start, end_date: end };\n },\n },\n tasks_get: {\n idField: 'task_id',\n fixtureKey: 'task_ids',\n buildRequest: id => ({ task_id: id }),\n },\n get_signals: {\n idField: 'signal_ids',\n // No seeder for signals today (catalog signals are provider-\n // controlled, not agent-created). Baseline-only: two fresh UUIDs\n // wrapped in a SignalID shape, probed under the single caller\n // token. Cross-tenant mode becomes available when the signals\n // protocol grows a create/sync path and a seeder produces ids.\n buildRequest: id => ({\n signal_ids: [{ source: 'catalog', data_provider_domain: 'conformance.example', id }],\n }),\n },\n};\n\n/** Tools eligible for the uniform-error probe. Used by the runner wiring. */\nexport function toolsEligibleForUniformError(): ConformanceToolName[] {\n return Object.keys(TOOL_ID_CONFIG) as ConformanceToolName[];\n}\n\nexport interface ProbeOptions {\n /** Agent client that probes with the \"caller\" credentials (tenant B in cross-tenant mode). */\n prober: AgentClient;\n /** Fixtures accumulated so far — drawn from for cross-tenant mode. */\n fixtures: ConformanceFixtures;\n /** Whether a distinct cross-tenant token was configured. When false, mode is 'baseline'. */\n crossTenantConfigured: boolean;\n /**\n * Cap individual probe body size in the capture. Defaults to the\n * rawResponseCapture default. Not usually worth overriding.\n */\n maxBodyBytes?: number;\n}\n\nexport async function runUniformErrorInvariant(\n tool: ConformanceToolName,\n options: ProbeOptions\n): Promise<UniformErrorReport> {\n const config = TOOL_ID_CONFIG[tool];\n if (!config) {\n return {\n tool,\n mode: options.crossTenantConfigured ? 'cross-tenant' : 'baseline',\n verdict: 'skipped',\n skipReason: 'tool not in TOOL_ID_CONFIG',\n };\n }\n\n // Resolve the pair of ids under probe.\n //\n // Cross-tenant mode needs a seeded id (tenant A owns the resource;\n // tenant B is probing it — that's the \"exists but inaccessible\" leg).\n // Missing seeded id (or a tool with no fixtureKey at all, like\n // get_signals) → fall back to baseline rather than skipping; the\n // baseline still catches id-echo and header-divergence leaks.\n const seededPool = config.fixtureKey ? (options.fixtures[config.fixtureKey] ?? []) : [];\n const seededId = seededPool[0];\n const mode: UniformErrorReport['mode'] = options.crossTenantConfigured && seededId ? 'cross-tenant' : 'baseline';\n\n const idA = mode === 'cross-tenant' ? (seededId as string) : randomUUID();\n const idB = randomUUID();\n const labelA: ProbeSummary['label'] = mode === 'cross-tenant' ? 'cross-tenant' : 'random-a';\n const labelB: ProbeSummary['label'] = mode === 'cross-tenant' ? 'impossible' : 'random-b';\n\n const captureOpts = { maxBodyBytes: options.maxBodyBytes };\n\n const probeA = await capturedProbe(options.prober, tool, config.buildRequest(idA), captureOpts);\n const probeB = await capturedProbe(options.prober, tool, config.buildRequest(idB), captureOpts);\n\n if (!probeA.capture || !probeB.capture) {\n // One side didn't produce a capture — the underlying transport\n // surfaced an error before we could observe the response (e.g.,\n // the SDK threw an AuthenticationRequiredError). Report the root\n // cause so the operator knows why the invariant skipped.\n const reason = probeA.error ?? probeB.error ?? 'no capture observed';\n return {\n tool,\n mode,\n verdict: 'skipped',\n skipReason: `probe did not produce a raw capture (${reason})`,\n };\n }\n\n const comparison = compareProbes(probeA.capture, probeB.capture);\n\n return {\n tool,\n mode,\n verdict: comparison.equivalent ? 'pass' : 'fail',\n differences: comparison.differences,\n probes: {\n inaccessibleOrRandomA: summarizeCapture(probeA.capture, labelA),\n impossibleOrRandomB: summarizeCapture(probeB.capture, labelB),\n },\n };\n}\n\ninterface ProbeOutcome {\n capture?: RawHttpCapture;\n /** Error message when executeTask threw before producing a capture. */\n error?: string;\n}\n\n/**\n * Execute a probe inside a capture context and return the tool-call\n * response. Filters captures to POST — MCP's tool call and A2A's\n * `sendMessage` are both POSTs, while A2A's `/.well-known/agent.json`\n * discovery (issued on a fresh client) is a GET that we must not\n * confuse with the tool response.\n */\nasync function capturedProbe(\n agent: AgentClient,\n tool: ConformanceToolName,\n request: Record<string, unknown>,\n options: { maxBodyBytes?: number }\n): Promise<ProbeOutcome> {\n try {\n const { captures } = await withRawResponseCapture(async () => {\n await agent.executeTaskLegacy(tool, request);\n }, options);\n const toolCallCapture = lastPostCapture(captures);\n if (!toolCallCapture) {\n return { error: 'captured only non-POST traffic' };\n }\n return { capture: toolCallCapture };\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction lastPostCapture(captures: readonly RawHttpCapture[]): RawHttpCapture | undefined {\n for (let i = captures.length - 1; i >= 0; i--) {\n const cap = captures[i];\n if (cap && cap.method === 'POST') return cap;\n }\n return undefined;\n}\n\nfunction summarizeCapture(cap: RawHttpCapture, label: ProbeSummary['label']): ProbeSummary {\n return {\n label,\n status: cap.status,\n headers: cap.headers,\n body: cap.body,\n latencyMs: cap.latencyMs,\n bodyTruncated: cap.bodyTruncated,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBA,yBAA2B;AAC3B,gCAA4D;AAE5D,oCAA0D;AAqD1D,MAAM,iBAAqE;AAAA,EACzE,mBAAmB;AAAA,IACjB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,cAAc,SAAO,EAAE,SAAS,GAAG;AAAA,EACrC;AAAA,EACA,uBAAuB;AAAA,IACrB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,cAAc,SAAO,EAAE,cAAc,GAAG;AAAA,EAC1C;AAAA,EACA,wBAAwB;AAAA,IACtB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,cAAc,QAAM;AAKlB,YAAM,MAAM,oBAAI,KAAK;AACrB,YAAM,QAAQ,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,KAAS,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC/E,YAAM,MAAM,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,KAAS,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC7E,aAAO,EAAE,eAAe,CAAC,EAAE,GAAG,YAAY,OAAO,UAAU,IAAI;AAAA,IACjE;AAAA,EACF;AAAA,EACA,uBAAuB;AAAA,IACrB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,cAAc,QAAM;AAClB,YAAM,MAAM,oBAAI,KAAK;AACrB,YAAM,QAAQ,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,KAAS,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC/E,YAAM,MAAM,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,KAAS,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC7E,aAAO,EAAE,cAAc,CAAC,EAAE,GAAG,YAAY,OAAO,UAAU,IAAI;AAAA,IAChE;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,cAAc,SAAO,EAAE,SAAS,GAAG;AAAA,EACrC;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMT,cAAc,SAAO;AAAA,MACnB,YAAY,CAAC,EAAE,QAAQ,WAAW,sBAAsB,uBAAuB,GAAG,CAAC;AAAA,IACrF;AAAA,EACF;AACF;AAGO,SAAS,+BAAsD;AACpE,SAAO,OAAO,KAAK,cAAc;AACnC;AAgBA,eAAsB,yBACpB,MACA,SAC6B;AAC7B,QAAM,SAAS,eAAe,IAAI;AAClC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL;AAAA,MACA,MAAM,QAAQ,wBAAwB,iBAAiB;AAAA,MACvD,SAAS;AAAA,MACT,YAAY;AAAA,IACd;AAAA,EACF;AASA,QAAM,aAAa,OAAO,aAAc,QAAQ,SAAS,OAAO,UAAU,KAAK,CAAC,IAAK,CAAC;AACtF,QAAM,WAAW,WAAW,CAAC;AAC7B,QAAM,OAAmC,QAAQ,yBAAyB,WAAW,iBAAiB;AAEtG,QAAM,MAAM,SAAS,iBAAkB,eAAsB,+BAAW;AACxE,QAAM,UAAM,+BAAW;AACvB,QAAM,SAAgC,SAAS,iBAAiB,iBAAiB;AACjF,QAAM,SAAgC,SAAS,iBAAiB,eAAe;AAE/E,QAAM,cAAc,EAAE,cAAc,QAAQ,aAAa;AAEzD,QAAM,SAAS,MAAM,cAAc,QAAQ,QAAQ,MAAM,OAAO,aAAa,GAAG,GAAG,WAAW;AAC9F,QAAM,SAAS,MAAM,cAAc,QAAQ,QAAQ,MAAM,OAAO,aAAa,GAAG,GAAG,WAAW;AAE9F,MAAI,CAAC,OAAO,WAAW,CAAC,OAAO,SAAS;AAKtC,UAAM,SAAS,OAAO,SAAS,OAAO,SAAS;AAC/C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,YAAY,wCAAwC,MAAM;AAAA,IAC5D;AAAA,EACF;AAEA,QAAM,iBAAa,6CAAc,OAAO,SAAS,OAAO,OAAO;AAE/D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,WAAW,aAAa,SAAS;AAAA,IAC1C,aAAa,WAAW;AAAA,IACxB,QAAQ;AAAA,MACN,uBAAuB,iBAAiB,OAAO,SAAS,MAAM;AAAA,MAC9D,qBAAqB,iBAAiB,OAAO,SAAS,MAAM;AAAA,IAC9D;AAAA,EACF;AACF;AAeA,eAAe,cACb,OACA,MACA,SACA,SACuB;AACvB,MAAI;AACF,UAAM,EAAE,SAAS,IAAI,UAAM,kDAAuB,YAAY;AAC5D,YAAM,MAAM,kBAAkB,MAAM,OAAO;AAAA,IAC7C,GAAG,OAAO;AACV,UAAM,kBAAkB,gBAAgB,QAAQ;AAChD,QAAI,CAAC,iBAAiB;AACpB,aAAO,EAAE,OAAO,iCAAiC;AAAA,IACnD;AACA,WAAO,EAAE,SAAS,gBAAgB;AAAA,EACpC,SAAS,KAAK;AACZ,WAAO,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,EACnE;AACF;AAEA,SAAS,gBAAgB,UAAiE;AACxF,WAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,UAAM,MAAM,SAAS,CAAC;AACtB,QAAI,OAAO,IAAI,WAAW,OAAQ,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,KAAqB,OAA4C;AACzF,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,IAAI;AAAA,IACZ,SAAS,IAAI;AAAA,IACb,MAAM,IAAI;AAAA,IACV,WAAW,IAAI;AAAA,IACf,eAAe,IAAI;AAAA,EACrB;AACF;","names":[]}
|
|
@@ -96,7 +96,7 @@ async function runUniformErrorInvariant(tool, options) {
|
|
|
96
96
|
async function capturedProbe(agent, tool, request, options) {
|
|
97
97
|
try {
|
|
98
98
|
const { captures } = await withRawResponseCapture(async () => {
|
|
99
|
-
await agent.
|
|
99
|
+
await agent.executeTaskLegacy(tool, request);
|
|
100
100
|
}, options);
|
|
101
101
|
const toolCallCapture = lastPostCapture(captures);
|
|
102
102
|
if (!toolCallCapture) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/conformance/invariants/uniformError.ts"],"sourcesContent":["// Uniform error response invariant (adcp spec § error-handling).\n//\n// The spec MUSTs that a seller returns byte-equivalent responses for\n// \"the id exists but the caller lacks access\" vs \"the id does not\n// exist\" — through every observable channel (error code/message/field/\n// details, HTTP status, A2A task state / MCP isError, response headers,\n// latency distribution). Distinguishing the two leaks cross-tenant\n// existence information.\n//\n// This invariant exercises the MUST with a paired probe: two requests\n// to the same tool, compared byte-for-byte.\n//\n// Pairing modes:\n// - baseline: two fresh UUIDs, single auth token. Catches id-echo\n// leaks, header divergence, and grossly different latency. Does\n// not catch cross-tenant leaks — both ids are impossible, so the\n// \"inaccessible vs unknown\" branch never fires.\n// - cross-tenant: one seeded id owned by tenant A plus one fresh\n// UUID, both probed as tenant B. Catches the full MUST.\n//\n// Tool coverage is keyed by TOOL_ID_CONFIG below. A tool must expose\n// a single scalar \"lookup id\" field and have a matching seeder before\n// it can be probed.\n\nimport { AgentClient } from '../../core/AgentClient';\nimport { randomUUID } from 'node:crypto';\nimport { withRawResponseCapture, type RawHttpCapture } from '../../protocols/rawResponseCapture';\nimport type { ConformanceFixtures, ConformanceToolName } from '../types';\nimport { compareProbes, type ProbeComparisonResult } from './uniformErrorComparator';\n\nexport type UniformErrorVerdict = 'pass' | 'fail' | 'skipped';\n\nexport interface UniformErrorReport {\n tool: ConformanceToolName;\n /** Which pairing actually ran. */\n mode: 'baseline' | 'cross-tenant';\n verdict: UniformErrorVerdict;\n /** Populated on verdict === 'skipped'. */\n skipReason?: string;\n /** Populated on verdict !== 'skipped'. */\n differences?: string[];\n /** Probe summaries for diagnostics. Sanitized via `summarizeCapture`. */\n probes?: {\n inaccessibleOrRandomA: ProbeSummary;\n impossibleOrRandomB: ProbeSummary;\n };\n}\n\nexport interface ProbeSummary {\n /** Label describing what kind of id was probed. */\n label: 'cross-tenant' | 'impossible' | 'random-a' | 'random-b';\n status: number | null;\n headers: Record<string, string>;\n body: string;\n latencyMs: number;\n /** Whether the capture body was truncated. */\n bodyTruncated: boolean;\n}\n\n/**\n * Per-tool configuration for the invariant. Each tool that can be\n * probed declares:\n * - the single id field to mutate\n * - the fixture key that holds a seeded id (for cross-tenant mode)\n * - a minimal request builder given the id\n *\n * Extending coverage to more tools is additive — populate a new entry.\n */\ninterface ToolIdConfig {\n idField: string;\n /**\n * Fixture pool that holds a seeded \"accessible to tenant A\" id for\n * cross-tenant mode. When omitted, cross-tenant mode is unavailable\n * for this tool — baseline is the only mode. Useful for tools whose\n * ids don't come from a seeder (catalog-style lookups, provider-\n * owned signals, etc.).\n */\n fixtureKey?: keyof ConformanceFixtures;\n buildRequest: (id: string) => Record<string, unknown>;\n}\n\nconst TOOL_ID_CONFIG: Partial<Record<ConformanceToolName, ToolIdConfig>> = {\n get_property_list: {\n idField: 'list_id',\n fixtureKey: 'list_ids',\n buildRequest: id => ({ list_id: id }),\n },\n get_content_standards: {\n idField: 'standards_id',\n fixtureKey: 'standards_ids',\n buildRequest: id => ({ standards_id: id }),\n },\n get_media_buy_delivery: {\n idField: 'media_buy_id',\n fixtureKey: 'media_buy_ids',\n buildRequest: id => {\n // Spec-min request: one buy id + a date range wide enough to avoid\n // per-seller reporting-window rejection. Dates are arbitrary — the\n // resolution happens before access-check per the spec, so the\n // response must be byte-equivalent regardless of window.\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { media_buy_ids: [id], start_date: start, end_date: end };\n },\n },\n get_creative_delivery: {\n idField: 'creative_id',\n fixtureKey: 'creative_ids',\n buildRequest: id => {\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { creative_ids: [id], start_date: start, end_date: end };\n },\n },\n tasks_get: {\n idField: 'task_id',\n fixtureKey: 'task_ids',\n buildRequest: id => ({ task_id: id }),\n },\n get_signals: {\n idField: 'signal_ids',\n // No seeder for signals today (catalog signals are provider-\n // controlled, not agent-created). Baseline-only: two fresh UUIDs\n // wrapped in a SignalID shape, probed under the single caller\n // token. Cross-tenant mode becomes available when the signals\n // protocol grows a create/sync path and a seeder produces ids.\n buildRequest: id => ({\n signal_ids: [{ source: 'catalog', data_provider_domain: 'conformance.example', id }],\n }),\n },\n};\n\n/** Tools eligible for the uniform-error probe. Used by the runner wiring. */\nexport function toolsEligibleForUniformError(): ConformanceToolName[] {\n return Object.keys(TOOL_ID_CONFIG) as ConformanceToolName[];\n}\n\nexport interface ProbeOptions {\n /** Agent client that probes with the \"caller\" credentials (tenant B in cross-tenant mode). */\n prober: AgentClient;\n /** Fixtures accumulated so far — drawn from for cross-tenant mode. */\n fixtures: ConformanceFixtures;\n /** Whether a distinct cross-tenant token was configured. When false, mode is 'baseline'. */\n crossTenantConfigured: boolean;\n /**\n * Cap individual probe body size in the capture. Defaults to the\n * rawResponseCapture default. Not usually worth overriding.\n */\n maxBodyBytes?: number;\n}\n\nexport async function runUniformErrorInvariant(\n tool: ConformanceToolName,\n options: ProbeOptions\n): Promise<UniformErrorReport> {\n const config = TOOL_ID_CONFIG[tool];\n if (!config) {\n return {\n tool,\n mode: options.crossTenantConfigured ? 'cross-tenant' : 'baseline',\n verdict: 'skipped',\n skipReason: 'tool not in TOOL_ID_CONFIG',\n };\n }\n\n // Resolve the pair of ids under probe.\n //\n // Cross-tenant mode needs a seeded id (tenant A owns the resource;\n // tenant B is probing it — that's the \"exists but inaccessible\" leg).\n // Missing seeded id (or a tool with no fixtureKey at all, like\n // get_signals) → fall back to baseline rather than skipping; the\n // baseline still catches id-echo and header-divergence leaks.\n const seededPool = config.fixtureKey ? (options.fixtures[config.fixtureKey] ?? []) : [];\n const seededId = seededPool[0];\n const mode: UniformErrorReport['mode'] = options.crossTenantConfigured && seededId ? 'cross-tenant' : 'baseline';\n\n const idA = mode === 'cross-tenant' ? (seededId as string) : randomUUID();\n const idB = randomUUID();\n const labelA: ProbeSummary['label'] = mode === 'cross-tenant' ? 'cross-tenant' : 'random-a';\n const labelB: ProbeSummary['label'] = mode === 'cross-tenant' ? 'impossible' : 'random-b';\n\n const captureOpts = { maxBodyBytes: options.maxBodyBytes };\n\n const probeA = await capturedProbe(options.prober, tool, config.buildRequest(idA), captureOpts);\n const probeB = await capturedProbe(options.prober, tool, config.buildRequest(idB), captureOpts);\n\n if (!probeA.capture || !probeB.capture) {\n // One side didn't produce a capture — the underlying transport\n // surfaced an error before we could observe the response (e.g.,\n // the SDK threw an AuthenticationRequiredError). Report the root\n // cause so the operator knows why the invariant skipped.\n const reason = probeA.error ?? probeB.error ?? 'no capture observed';\n return {\n tool,\n mode,\n verdict: 'skipped',\n skipReason: `probe did not produce a raw capture (${reason})`,\n };\n }\n\n const comparison = compareProbes(probeA.capture, probeB.capture);\n\n return {\n tool,\n mode,\n verdict: comparison.equivalent ? 'pass' : 'fail',\n differences: comparison.differences,\n probes: {\n inaccessibleOrRandomA: summarizeCapture(probeA.capture, labelA),\n impossibleOrRandomB: summarizeCapture(probeB.capture, labelB),\n },\n };\n}\n\ninterface ProbeOutcome {\n capture?: RawHttpCapture;\n /** Error message when executeTask threw before producing a capture. */\n error?: string;\n}\n\n/**\n * Execute a probe inside a capture context and return the tool-call\n * response. Filters captures to POST — MCP's tool call and A2A's\n * `sendMessage` are both POSTs, while A2A's `/.well-known/agent.json`\n * discovery (issued on a fresh client) is a GET that we must not\n * confuse with the tool response.\n */\nasync function capturedProbe(\n agent: AgentClient,\n tool: ConformanceToolName,\n request: Record<string, unknown>,\n options: { maxBodyBytes?: number }\n): Promise<ProbeOutcome> {\n try {\n const { captures } = await withRawResponseCapture(async () => {\n await agent.executeTask(tool, request);\n }, options);\n const toolCallCapture = lastPostCapture(captures);\n if (!toolCallCapture) {\n return { error: 'captured only non-POST traffic' };\n }\n return { capture: toolCallCapture };\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction lastPostCapture(captures: readonly RawHttpCapture[]): RawHttpCapture | undefined {\n for (let i = captures.length - 1; i >= 0; i--) {\n const cap = captures[i];\n if (cap && cap.method === 'POST') return cap;\n }\n return undefined;\n}\n\nfunction summarizeCapture(cap: RawHttpCapture, label: ProbeSummary['label']): ProbeSummary {\n return {\n label,\n status: cap.status,\n headers: cap.headers,\n body: cap.body,\n latencyMs: cap.latencyMs,\n bodyTruncated: cap.bodyTruncated,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/conformance/invariants/uniformError.ts"],"sourcesContent":["// Uniform error response invariant (adcp spec § error-handling).\n//\n// The spec MUSTs that a seller returns byte-equivalent responses for\n// \"the id exists but the caller lacks access\" vs \"the id does not\n// exist\" — through every observable channel (error code/message/field/\n// details, HTTP status, A2A task state / MCP isError, response headers,\n// latency distribution). Distinguishing the two leaks cross-tenant\n// existence information.\n//\n// This invariant exercises the MUST with a paired probe: two requests\n// to the same tool, compared byte-for-byte.\n//\n// Pairing modes:\n// - baseline: two fresh UUIDs, single auth token. Catches id-echo\n// leaks, header divergence, and grossly different latency. Does\n// not catch cross-tenant leaks — both ids are impossible, so the\n// \"inaccessible vs unknown\" branch never fires.\n// - cross-tenant: one seeded id owned by tenant A plus one fresh\n// UUID, both probed as tenant B. Catches the full MUST.\n//\n// Tool coverage is keyed by TOOL_ID_CONFIG below. A tool must expose\n// a single scalar \"lookup id\" field and have a matching seeder before\n// it can be probed.\n\nimport { AgentClient } from '../../core/AgentClient';\nimport { randomUUID } from 'node:crypto';\nimport { withRawResponseCapture, type RawHttpCapture } from '../../protocols/rawResponseCapture';\nimport type { ConformanceFixtures, ConformanceToolName } from '../types';\nimport { compareProbes, type ProbeComparisonResult } from './uniformErrorComparator';\n\nexport type UniformErrorVerdict = 'pass' | 'fail' | 'skipped';\n\nexport interface UniformErrorReport {\n tool: ConformanceToolName;\n /** Which pairing actually ran. */\n mode: 'baseline' | 'cross-tenant';\n verdict: UniformErrorVerdict;\n /** Populated on verdict === 'skipped'. */\n skipReason?: string;\n /** Populated on verdict !== 'skipped'. */\n differences?: string[];\n /** Probe summaries for diagnostics. Sanitized via `summarizeCapture`. */\n probes?: {\n inaccessibleOrRandomA: ProbeSummary;\n impossibleOrRandomB: ProbeSummary;\n };\n}\n\nexport interface ProbeSummary {\n /** Label describing what kind of id was probed. */\n label: 'cross-tenant' | 'impossible' | 'random-a' | 'random-b';\n status: number | null;\n headers: Record<string, string>;\n body: string;\n latencyMs: number;\n /** Whether the capture body was truncated. */\n bodyTruncated: boolean;\n}\n\n/**\n * Per-tool configuration for the invariant. Each tool that can be\n * probed declares:\n * - the single id field to mutate\n * - the fixture key that holds a seeded id (for cross-tenant mode)\n * - a minimal request builder given the id\n *\n * Extending coverage to more tools is additive — populate a new entry.\n */\ninterface ToolIdConfig {\n idField: string;\n /**\n * Fixture pool that holds a seeded \"accessible to tenant A\" id for\n * cross-tenant mode. When omitted, cross-tenant mode is unavailable\n * for this tool — baseline is the only mode. Useful for tools whose\n * ids don't come from a seeder (catalog-style lookups, provider-\n * owned signals, etc.).\n */\n fixtureKey?: keyof ConformanceFixtures;\n buildRequest: (id: string) => Record<string, unknown>;\n}\n\nconst TOOL_ID_CONFIG: Partial<Record<ConformanceToolName, ToolIdConfig>> = {\n get_property_list: {\n idField: 'list_id',\n fixtureKey: 'list_ids',\n buildRequest: id => ({ list_id: id }),\n },\n get_content_standards: {\n idField: 'standards_id',\n fixtureKey: 'standards_ids',\n buildRequest: id => ({ standards_id: id }),\n },\n get_media_buy_delivery: {\n idField: 'media_buy_id',\n fixtureKey: 'media_buy_ids',\n buildRequest: id => {\n // Spec-min request: one buy id + a date range wide enough to avoid\n // per-seller reporting-window rejection. Dates are arbitrary — the\n // resolution happens before access-check per the spec, so the\n // response must be byte-equivalent regardless of window.\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { media_buy_ids: [id], start_date: start, end_date: end };\n },\n },\n get_creative_delivery: {\n idField: 'creative_id',\n fixtureKey: 'creative_ids',\n buildRequest: id => {\n const now = new Date();\n const start = new Date(now.getTime() - 7 * 86400_000).toISOString().slice(0, 10);\n const end = new Date(now.getTime() + 7 * 86400_000).toISOString().slice(0, 10);\n return { creative_ids: [id], start_date: start, end_date: end };\n },\n },\n tasks_get: {\n idField: 'task_id',\n fixtureKey: 'task_ids',\n buildRequest: id => ({ task_id: id }),\n },\n get_signals: {\n idField: 'signal_ids',\n // No seeder for signals today (catalog signals are provider-\n // controlled, not agent-created). Baseline-only: two fresh UUIDs\n // wrapped in a SignalID shape, probed under the single caller\n // token. Cross-tenant mode becomes available when the signals\n // protocol grows a create/sync path and a seeder produces ids.\n buildRequest: id => ({\n signal_ids: [{ source: 'catalog', data_provider_domain: 'conformance.example', id }],\n }),\n },\n};\n\n/** Tools eligible for the uniform-error probe. Used by the runner wiring. */\nexport function toolsEligibleForUniformError(): ConformanceToolName[] {\n return Object.keys(TOOL_ID_CONFIG) as ConformanceToolName[];\n}\n\nexport interface ProbeOptions {\n /** Agent client that probes with the \"caller\" credentials (tenant B in cross-tenant mode). */\n prober: AgentClient;\n /** Fixtures accumulated so far — drawn from for cross-tenant mode. */\n fixtures: ConformanceFixtures;\n /** Whether a distinct cross-tenant token was configured. When false, mode is 'baseline'. */\n crossTenantConfigured: boolean;\n /**\n * Cap individual probe body size in the capture. Defaults to the\n * rawResponseCapture default. Not usually worth overriding.\n */\n maxBodyBytes?: number;\n}\n\nexport async function runUniformErrorInvariant(\n tool: ConformanceToolName,\n options: ProbeOptions\n): Promise<UniformErrorReport> {\n const config = TOOL_ID_CONFIG[tool];\n if (!config) {\n return {\n tool,\n mode: options.crossTenantConfigured ? 'cross-tenant' : 'baseline',\n verdict: 'skipped',\n skipReason: 'tool not in TOOL_ID_CONFIG',\n };\n }\n\n // Resolve the pair of ids under probe.\n //\n // Cross-tenant mode needs a seeded id (tenant A owns the resource;\n // tenant B is probing it — that's the \"exists but inaccessible\" leg).\n // Missing seeded id (or a tool with no fixtureKey at all, like\n // get_signals) → fall back to baseline rather than skipping; the\n // baseline still catches id-echo and header-divergence leaks.\n const seededPool = config.fixtureKey ? (options.fixtures[config.fixtureKey] ?? []) : [];\n const seededId = seededPool[0];\n const mode: UniformErrorReport['mode'] = options.crossTenantConfigured && seededId ? 'cross-tenant' : 'baseline';\n\n const idA = mode === 'cross-tenant' ? (seededId as string) : randomUUID();\n const idB = randomUUID();\n const labelA: ProbeSummary['label'] = mode === 'cross-tenant' ? 'cross-tenant' : 'random-a';\n const labelB: ProbeSummary['label'] = mode === 'cross-tenant' ? 'impossible' : 'random-b';\n\n const captureOpts = { maxBodyBytes: options.maxBodyBytes };\n\n const probeA = await capturedProbe(options.prober, tool, config.buildRequest(idA), captureOpts);\n const probeB = await capturedProbe(options.prober, tool, config.buildRequest(idB), captureOpts);\n\n if (!probeA.capture || !probeB.capture) {\n // One side didn't produce a capture — the underlying transport\n // surfaced an error before we could observe the response (e.g.,\n // the SDK threw an AuthenticationRequiredError). Report the root\n // cause so the operator knows why the invariant skipped.\n const reason = probeA.error ?? probeB.error ?? 'no capture observed';\n return {\n tool,\n mode,\n verdict: 'skipped',\n skipReason: `probe did not produce a raw capture (${reason})`,\n };\n }\n\n const comparison = compareProbes(probeA.capture, probeB.capture);\n\n return {\n tool,\n mode,\n verdict: comparison.equivalent ? 'pass' : 'fail',\n differences: comparison.differences,\n probes: {\n inaccessibleOrRandomA: summarizeCapture(probeA.capture, labelA),\n impossibleOrRandomB: summarizeCapture(probeB.capture, labelB),\n },\n };\n}\n\ninterface ProbeOutcome {\n capture?: RawHttpCapture;\n /** Error message when executeTask threw before producing a capture. */\n error?: string;\n}\n\n/**\n * Execute a probe inside a capture context and return the tool-call\n * response. Filters captures to POST — MCP's tool call and A2A's\n * `sendMessage` are both POSTs, while A2A's `/.well-known/agent.json`\n * discovery (issued on a fresh client) is a GET that we must not\n * confuse with the tool response.\n */\nasync function capturedProbe(\n agent: AgentClient,\n tool: ConformanceToolName,\n request: Record<string, unknown>,\n options: { maxBodyBytes?: number }\n): Promise<ProbeOutcome> {\n try {\n const { captures } = await withRawResponseCapture(async () => {\n await agent.executeTaskLegacy(tool, request);\n }, options);\n const toolCallCapture = lastPostCapture(captures);\n if (!toolCallCapture) {\n return { error: 'captured only non-POST traffic' };\n }\n return { capture: toolCallCapture };\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction lastPostCapture(captures: readonly RawHttpCapture[]): RawHttpCapture | undefined {\n for (let i = captures.length - 1; i >= 0; i--) {\n const cap = captures[i];\n if (cap && cap.method === 'POST') return cap;\n }\n return undefined;\n}\n\nfunction summarizeCapture(cap: RawHttpCapture, label: ProbeSummary['label']): ProbeSummary {\n return {\n label,\n status: cap.status,\n headers: cap.headers,\n body: cap.body,\n latencyMs: cap.latencyMs,\n bodyTruncated: cap.bodyTruncated,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -60,7 +60,7 @@ async function runToolFuzz(tool, agent, options) {
|
|
|
60
60
|
const probeRequest = "adcp_major_version" in request || "adcp_version" in request ? { ...request, adcp_major_version: import_version.ADCP_MAJOR_VERSION } : request;
|
|
61
61
|
let result;
|
|
62
62
|
try {
|
|
63
|
-
result = await agent.
|
|
63
|
+
result = await agent.executeTaskLegacy(tool, probeRequest);
|
|
64
64
|
} catch (err2) {
|
|
65
65
|
const message = err2?.message ?? String(err2);
|
|
66
66
|
if (err2?.name === "FeatureUnsupportedError" || /does not support/i.test(message)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/conformance/runners.ts"],"sourcesContent":["import fc from 'fast-check';\nimport type { AgentClient } from '../core/AgentClient';\nimport type {\n ConformanceFailure,\n ConformanceFixtures,\n ConformanceToolName,\n ConformanceToolStats,\n SkipReason,\n} from './types';\nimport { schemaToArbitrary } from './schemaArbitrary';\nimport { ADCP_MAJOR_VERSION } from '../version';\nimport { loadRequestSchema, type ConformanceSchemaOptions } from './schemaLoader';\nimport { evaluate, prepareResponseValidator } from './oracle';\n\nexport interface RunnerOptions {\n seed: number;\n numRuns: number;\n authToken?: string;\n /** Cap per-failure serialized payload size (bytes). */\n maxFailurePayloadBytes: number;\n /** ID pools for Tier-2 fixture injection. See ConformanceFixtures. */\n fixtures?: ConformanceFixtures;\n /** Schema bundle override for same-PR / external conformance runs. */\n schemas?: ConformanceSchemaOptions;\n}\n\nexport interface RunnerResult {\n stats: ConformanceToolStats;\n failures: ConformanceFailure[];\n}\n\n/**\n * Fuzz a single tool against a connected agent. Uses fast-check's\n * `fc.check` for property generation + shrinking; a response that trips\n * the oracle is minimized to the smallest request that still reproduces\n * the failure before it's collected in the report.\n *\n * Returns the tool skipped when the agent declares it unsupported or when\n * the response schema can't be compiled — those aren't oracle failures,\n * they're environmental conditions.\n */\nexport async function runToolFuzz(\n tool: ConformanceToolName,\n agent: AgentClient,\n options: RunnerOptions\n): Promise<RunnerResult> {\n // Compile the response schema up front. Ajv sometimes fails on bundled\n // schemas that still carry unresolved `$defs` refs (known upstream gap) —\n // skip the tool cleanly rather than flag every run as invalid.\n try {\n prepareResponseValidator(tool, options.schemas);\n } catch (err) {\n return {\n stats: skipStats('unresolvable_schema', (err as Error)?.message),\n failures: [],\n };\n }\n\n const schema = loadRequestSchema(tool, options.schemas);\n const arb = schemaToArbitrary(schema, { fixtures: options.fixtures }) as fc.Arbitrary<Record<string, unknown>>;\n\n // Counts only increment on fresh samples. `fc.check` re-runs the property\n // during shrinking; we don't want those replays in the accepted/rejected\n // tally. Track the minimum sample count we've seen and skip stat updates\n // on replayed samples by hashing the sample.\n const seenSamples = new Set<string>();\n const stats: ConformanceToolStats = { runs: 0, accepted: 0, rejected: 0, failed: 0, skipped: false };\n let transportUnsupported: string | null = null;\n\n const property = fc.asyncProperty(arb, async request => {\n const sampleKey = safeHash(request);\n const isFreshSample = !seenSamples.has(sampleKey);\n if (isFreshSample) {\n seenSamples.add(sampleKey);\n stats.runs++;\n }\n\n // Pin transport-envelope fields the buyer SDK manages itself.\n // `applyVersionEnvelope` (PR #1073) auto-fills these on outbound\n // requests, but the schema-driven arbitrary may overwrite them with\n // out-of-window integers (1-99 per schema bounds). `createAdcpServer`'s\n // single-field VERSION_UNSUPPORTED check (#1075) would then reject\n // every probe before the handler runs, masking handler bugs the\n // fuzzer is meant to catch. Version negotiation is exercised\n // separately by storyboards (`error_compliance/unsupported_major_version`).\n const probeRequest =\n 'adcp_major_version' in request || 'adcp_version' in request\n ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION }\n : request;\n\n let result;\n try {\n result = await agent.executeTask(tool, probeRequest);\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // SDK throws FeatureUnsupportedError when the agent's declared\n // capabilities don't list the tool. That's the agent saying \"not\n // my job\" — not a conformance failure.\n if ((err as Error)?.name === 'FeatureUnsupportedError' || /does not support/i.test(message)) {\n transportUnsupported = message;\n return; // pass — we'll convert the whole tool to skipped below\n }\n throw new InvariantViolation({ thrown: String(err), name: (err as Error)?.name, message }, [\n 'unhandled transport error: ' + message,\n ]);\n }\n\n const verdict = evaluate({ tool, request, result, authToken: options.authToken, schemas: options.schemas });\n if (isFreshSample) {\n if (verdict.verdict === 'accepted') stats.accepted++;\n else if (verdict.verdict === 'rejected') stats.rejected++;\n }\n\n if (verdict.verdict === 'invalid') {\n throw new InvariantViolation(result, verdict.invariantFailures);\n }\n });\n\n const details = await fc.check(property, {\n seed: options.seed,\n numRuns: options.numRuns,\n verbose: 0,\n });\n\n if (transportUnsupported) {\n return { stats: skipStats('feature_unsupported', transportUnsupported), failures: [] };\n }\n\n if (!details.failed) {\n return { stats, failures: [] };\n }\n\n stats.failed = 1;\n const shrunkInput = (details.counterexample as [Record<string, unknown>] | null)?.[0];\n const err = details.errorInstance;\n const invariantFailures =\n err instanceof InvariantViolation\n ? err.invariantFailures\n : ['fuzz assertion failed: ' + ((err as Error | undefined)?.message ?? 'unknown')];\n const response = err instanceof InvariantViolation ? err.response : undefined;\n\n return {\n stats,\n failures: [\n {\n tool,\n path: details.counterexamplePath ?? undefined,\n seed: options.seed,\n shrunk: (details.numShrinks ?? 0) > 0,\n input: truncateForReport(shrunkInput, options.maxFailurePayloadBytes),\n response: truncateForReport(response, options.maxFailurePayloadBytes),\n verdict: 'invalid',\n invariantFailures,\n },\n ],\n };\n}\n\nfunction skipStats(reason: SkipReason, detail?: string): ConformanceToolStats {\n return {\n runs: 0,\n accepted: 0,\n rejected: 0,\n failed: 0,\n skipped: true,\n skipReason: reason,\n ...(detail ? { _detail: detail } : {}),\n } as ConformanceToolStats;\n}\n\nfunction safeHash(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForReport(value: unknown, maxBytes: number): unknown {\n if (value === undefined || value === null) return value;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? '';\n } catch {\n return { _truncated: true, _reason: 'unserializable' };\n }\n if (serialized.length <= maxBytes) return value;\n return {\n _truncated: true,\n _originalBytes: serialized.length,\n preview: serialized.slice(0, Math.max(256, maxBytes - 64)),\n };\n}\n\nclass InvariantViolation extends Error {\n constructor(\n public readonly response: unknown,\n public readonly invariantFailures: string[]\n ) {\n super(invariantFailures.join('; '));\n this.name = 'InvariantViolation';\n }\n}\n"],"mappings":"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","names":["err","fc"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/conformance/runners.ts"],"sourcesContent":["import fc from 'fast-check';\nimport type { AgentClient } from '../core/AgentClient';\nimport type {\n ConformanceFailure,\n ConformanceFixtures,\n ConformanceToolName,\n ConformanceToolStats,\n SkipReason,\n} from './types';\nimport { schemaToArbitrary } from './schemaArbitrary';\nimport { ADCP_MAJOR_VERSION } from '../version';\nimport { loadRequestSchema, type ConformanceSchemaOptions } from './schemaLoader';\nimport { evaluate, prepareResponseValidator } from './oracle';\n\nexport interface RunnerOptions {\n seed: number;\n numRuns: number;\n authToken?: string;\n /** Cap per-failure serialized payload size (bytes). */\n maxFailurePayloadBytes: number;\n /** ID pools for Tier-2 fixture injection. See ConformanceFixtures. */\n fixtures?: ConformanceFixtures;\n /** Schema bundle override for same-PR / external conformance runs. */\n schemas?: ConformanceSchemaOptions;\n}\n\nexport interface RunnerResult {\n stats: ConformanceToolStats;\n failures: ConformanceFailure[];\n}\n\n/**\n * Fuzz a single tool against a connected agent. Uses fast-check's\n * `fc.check` for property generation + shrinking; a response that trips\n * the oracle is minimized to the smallest request that still reproduces\n * the failure before it's collected in the report.\n *\n * Returns the tool skipped when the agent declares it unsupported or when\n * the response schema can't be compiled — those aren't oracle failures,\n * they're environmental conditions.\n */\nexport async function runToolFuzz(\n tool: ConformanceToolName,\n agent: AgentClient,\n options: RunnerOptions\n): Promise<RunnerResult> {\n // Compile the response schema up front. Ajv sometimes fails on bundled\n // schemas that still carry unresolved `$defs` refs (known upstream gap) —\n // skip the tool cleanly rather than flag every run as invalid.\n try {\n prepareResponseValidator(tool, options.schemas);\n } catch (err) {\n return {\n stats: skipStats('unresolvable_schema', (err as Error)?.message),\n failures: [],\n };\n }\n\n const schema = loadRequestSchema(tool, options.schemas);\n const arb = schemaToArbitrary(schema, { fixtures: options.fixtures }) as fc.Arbitrary<Record<string, unknown>>;\n\n // Counts only increment on fresh samples. `fc.check` re-runs the property\n // during shrinking; we don't want those replays in the accepted/rejected\n // tally. Track the minimum sample count we've seen and skip stat updates\n // on replayed samples by hashing the sample.\n const seenSamples = new Set<string>();\n const stats: ConformanceToolStats = { runs: 0, accepted: 0, rejected: 0, failed: 0, skipped: false };\n let transportUnsupported: string | null = null;\n\n const property = fc.asyncProperty(arb, async request => {\n const sampleKey = safeHash(request);\n const isFreshSample = !seenSamples.has(sampleKey);\n if (isFreshSample) {\n seenSamples.add(sampleKey);\n stats.runs++;\n }\n\n // Pin transport-envelope fields the buyer SDK manages itself.\n // `applyVersionEnvelope` (PR #1073) auto-fills these on outbound\n // requests, but the schema-driven arbitrary may overwrite them with\n // out-of-window integers (1-99 per schema bounds). `createAdcpServer`'s\n // single-field VERSION_UNSUPPORTED check (#1075) would then reject\n // every probe before the handler runs, masking handler bugs the\n // fuzzer is meant to catch. Version negotiation is exercised\n // separately by storyboards (`error_compliance/unsupported_major_version`).\n const probeRequest =\n 'adcp_major_version' in request || 'adcp_version' in request\n ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION }\n : request;\n\n let result;\n try {\n result = await agent.executeTaskLegacy(tool, probeRequest);\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // SDK throws FeatureUnsupportedError when the agent's declared\n // capabilities don't list the tool. That's the agent saying \"not\n // my job\" — not a conformance failure.\n if ((err as Error)?.name === 'FeatureUnsupportedError' || /does not support/i.test(message)) {\n transportUnsupported = message;\n return; // pass — we'll convert the whole tool to skipped below\n }\n throw new InvariantViolation({ thrown: String(err), name: (err as Error)?.name, message }, [\n 'unhandled transport error: ' + message,\n ]);\n }\n\n const verdict = evaluate({ tool, request, result, authToken: options.authToken, schemas: options.schemas });\n if (isFreshSample) {\n if (verdict.verdict === 'accepted') stats.accepted++;\n else if (verdict.verdict === 'rejected') stats.rejected++;\n }\n\n if (verdict.verdict === 'invalid') {\n throw new InvariantViolation(result, verdict.invariantFailures);\n }\n });\n\n const details = await fc.check(property, {\n seed: options.seed,\n numRuns: options.numRuns,\n verbose: 0,\n });\n\n if (transportUnsupported) {\n return { stats: skipStats('feature_unsupported', transportUnsupported), failures: [] };\n }\n\n if (!details.failed) {\n return { stats, failures: [] };\n }\n\n stats.failed = 1;\n const shrunkInput = (details.counterexample as [Record<string, unknown>] | null)?.[0];\n const err = details.errorInstance;\n const invariantFailures =\n err instanceof InvariantViolation\n ? err.invariantFailures\n : ['fuzz assertion failed: ' + ((err as Error | undefined)?.message ?? 'unknown')];\n const response = err instanceof InvariantViolation ? err.response : undefined;\n\n return {\n stats,\n failures: [\n {\n tool,\n path: details.counterexamplePath ?? undefined,\n seed: options.seed,\n shrunk: (details.numShrinks ?? 0) > 0,\n input: truncateForReport(shrunkInput, options.maxFailurePayloadBytes),\n response: truncateForReport(response, options.maxFailurePayloadBytes),\n verdict: 'invalid',\n invariantFailures,\n },\n ],\n };\n}\n\nfunction skipStats(reason: SkipReason, detail?: string): ConformanceToolStats {\n return {\n runs: 0,\n accepted: 0,\n rejected: 0,\n failed: 0,\n skipped: true,\n skipReason: reason,\n ...(detail ? { _detail: detail } : {}),\n } as ConformanceToolStats;\n}\n\nfunction safeHash(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForReport(value: unknown, maxBytes: number): unknown {\n if (value === undefined || value === null) return value;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? '';\n } catch {\n return { _truncated: true, _reason: 'unserializable' };\n }\n if (serialized.length <= maxBytes) return value;\n return {\n _truncated: true,\n _originalBytes: serialized.length,\n preview: serialized.slice(0, Math.max(256, maxBytes - 64)),\n };\n}\n\nclass InvariantViolation extends Error {\n constructor(\n public readonly response: unknown,\n public readonly invariantFailures: string[]\n ) {\n super(invariantFailures.join('; '));\n this.name = 'InvariantViolation';\n }\n}\n"],"mappings":"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","names":["err","fc"]}
|
|
@@ -27,7 +27,7 @@ async function runToolFuzz(tool, agent, options) {
|
|
|
27
27
|
const probeRequest = "adcp_major_version" in request || "adcp_version" in request ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION } : request;
|
|
28
28
|
let result;
|
|
29
29
|
try {
|
|
30
|
-
result = await agent.
|
|
30
|
+
result = await agent.executeTaskLegacy(tool, probeRequest);
|
|
31
31
|
} catch (err2) {
|
|
32
32
|
const message = err2?.message ?? String(err2);
|
|
33
33
|
if (err2?.name === "FeatureUnsupportedError" || /does not support/i.test(message)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/conformance/runners.ts"],"sourcesContent":["import fc from 'fast-check';\nimport type { AgentClient } from '../core/AgentClient';\nimport type {\n ConformanceFailure,\n ConformanceFixtures,\n ConformanceToolName,\n ConformanceToolStats,\n SkipReason,\n} from './types';\nimport { schemaToArbitrary } from './schemaArbitrary';\nimport { ADCP_MAJOR_VERSION } from '../version';\nimport { loadRequestSchema, type ConformanceSchemaOptions } from './schemaLoader';\nimport { evaluate, prepareResponseValidator } from './oracle';\n\nexport interface RunnerOptions {\n seed: number;\n numRuns: number;\n authToken?: string;\n /** Cap per-failure serialized payload size (bytes). */\n maxFailurePayloadBytes: number;\n /** ID pools for Tier-2 fixture injection. See ConformanceFixtures. */\n fixtures?: ConformanceFixtures;\n /** Schema bundle override for same-PR / external conformance runs. */\n schemas?: ConformanceSchemaOptions;\n}\n\nexport interface RunnerResult {\n stats: ConformanceToolStats;\n failures: ConformanceFailure[];\n}\n\n/**\n * Fuzz a single tool against a connected agent. Uses fast-check's\n * `fc.check` for property generation + shrinking; a response that trips\n * the oracle is minimized to the smallest request that still reproduces\n * the failure before it's collected in the report.\n *\n * Returns the tool skipped when the agent declares it unsupported or when\n * the response schema can't be compiled — those aren't oracle failures,\n * they're environmental conditions.\n */\nexport async function runToolFuzz(\n tool: ConformanceToolName,\n agent: AgentClient,\n options: RunnerOptions\n): Promise<RunnerResult> {\n // Compile the response schema up front. Ajv sometimes fails on bundled\n // schemas that still carry unresolved `$defs` refs (known upstream gap) —\n // skip the tool cleanly rather than flag every run as invalid.\n try {\n prepareResponseValidator(tool, options.schemas);\n } catch (err) {\n return {\n stats: skipStats('unresolvable_schema', (err as Error)?.message),\n failures: [],\n };\n }\n\n const schema = loadRequestSchema(tool, options.schemas);\n const arb = schemaToArbitrary(schema, { fixtures: options.fixtures }) as fc.Arbitrary<Record<string, unknown>>;\n\n // Counts only increment on fresh samples. `fc.check` re-runs the property\n // during shrinking; we don't want those replays in the accepted/rejected\n // tally. Track the minimum sample count we've seen and skip stat updates\n // on replayed samples by hashing the sample.\n const seenSamples = new Set<string>();\n const stats: ConformanceToolStats = { runs: 0, accepted: 0, rejected: 0, failed: 0, skipped: false };\n let transportUnsupported: string | null = null;\n\n const property = fc.asyncProperty(arb, async request => {\n const sampleKey = safeHash(request);\n const isFreshSample = !seenSamples.has(sampleKey);\n if (isFreshSample) {\n seenSamples.add(sampleKey);\n stats.runs++;\n }\n\n // Pin transport-envelope fields the buyer SDK manages itself.\n // `applyVersionEnvelope` (PR #1073) auto-fills these on outbound\n // requests, but the schema-driven arbitrary may overwrite them with\n // out-of-window integers (1-99 per schema bounds). `createAdcpServer`'s\n // single-field VERSION_UNSUPPORTED check (#1075) would then reject\n // every probe before the handler runs, masking handler bugs the\n // fuzzer is meant to catch. Version negotiation is exercised\n // separately by storyboards (`error_compliance/unsupported_major_version`).\n const probeRequest =\n 'adcp_major_version' in request || 'adcp_version' in request\n ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION }\n : request;\n\n let result;\n try {\n result = await agent.executeTask(tool, probeRequest);\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // SDK throws FeatureUnsupportedError when the agent's declared\n // capabilities don't list the tool. That's the agent saying \"not\n // my job\" — not a conformance failure.\n if ((err as Error)?.name === 'FeatureUnsupportedError' || /does not support/i.test(message)) {\n transportUnsupported = message;\n return; // pass — we'll convert the whole tool to skipped below\n }\n throw new InvariantViolation({ thrown: String(err), name: (err as Error)?.name, message }, [\n 'unhandled transport error: ' + message,\n ]);\n }\n\n const verdict = evaluate({ tool, request, result, authToken: options.authToken, schemas: options.schemas });\n if (isFreshSample) {\n if (verdict.verdict === 'accepted') stats.accepted++;\n else if (verdict.verdict === 'rejected') stats.rejected++;\n }\n\n if (verdict.verdict === 'invalid') {\n throw new InvariantViolation(result, verdict.invariantFailures);\n }\n });\n\n const details = await fc.check(property, {\n seed: options.seed,\n numRuns: options.numRuns,\n verbose: 0,\n });\n\n if (transportUnsupported) {\n return { stats: skipStats('feature_unsupported', transportUnsupported), failures: [] };\n }\n\n if (!details.failed) {\n return { stats, failures: [] };\n }\n\n stats.failed = 1;\n const shrunkInput = (details.counterexample as [Record<string, unknown>] | null)?.[0];\n const err = details.errorInstance;\n const invariantFailures =\n err instanceof InvariantViolation\n ? err.invariantFailures\n : ['fuzz assertion failed: ' + ((err as Error | undefined)?.message ?? 'unknown')];\n const response = err instanceof InvariantViolation ? err.response : undefined;\n\n return {\n stats,\n failures: [\n {\n tool,\n path: details.counterexamplePath ?? undefined,\n seed: options.seed,\n shrunk: (details.numShrinks ?? 0) > 0,\n input: truncateForReport(shrunkInput, options.maxFailurePayloadBytes),\n response: truncateForReport(response, options.maxFailurePayloadBytes),\n verdict: 'invalid',\n invariantFailures,\n },\n ],\n };\n}\n\nfunction skipStats(reason: SkipReason, detail?: string): ConformanceToolStats {\n return {\n runs: 0,\n accepted: 0,\n rejected: 0,\n failed: 0,\n skipped: true,\n skipReason: reason,\n ...(detail ? { _detail: detail } : {}),\n } as ConformanceToolStats;\n}\n\nfunction safeHash(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForReport(value: unknown, maxBytes: number): unknown {\n if (value === undefined || value === null) return value;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? '';\n } catch {\n return { _truncated: true, _reason: 'unserializable' };\n }\n if (serialized.length <= maxBytes) return value;\n return {\n _truncated: true,\n _originalBytes: serialized.length,\n preview: serialized.slice(0, Math.max(256, maxBytes - 64)),\n };\n}\n\nclass InvariantViolation extends Error {\n constructor(\n public readonly response: unknown,\n public readonly invariantFailures: string[]\n ) {\n super(invariantFailures.join('; '));\n this.name = 'InvariantViolation';\n }\n}\n"],"mappings":"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","names":["err"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/conformance/runners.ts"],"sourcesContent":["import fc from 'fast-check';\nimport type { AgentClient } from '../core/AgentClient';\nimport type {\n ConformanceFailure,\n ConformanceFixtures,\n ConformanceToolName,\n ConformanceToolStats,\n SkipReason,\n} from './types';\nimport { schemaToArbitrary } from './schemaArbitrary';\nimport { ADCP_MAJOR_VERSION } from '../version';\nimport { loadRequestSchema, type ConformanceSchemaOptions } from './schemaLoader';\nimport { evaluate, prepareResponseValidator } from './oracle';\n\nexport interface RunnerOptions {\n seed: number;\n numRuns: number;\n authToken?: string;\n /** Cap per-failure serialized payload size (bytes). */\n maxFailurePayloadBytes: number;\n /** ID pools for Tier-2 fixture injection. See ConformanceFixtures. */\n fixtures?: ConformanceFixtures;\n /** Schema bundle override for same-PR / external conformance runs. */\n schemas?: ConformanceSchemaOptions;\n}\n\nexport interface RunnerResult {\n stats: ConformanceToolStats;\n failures: ConformanceFailure[];\n}\n\n/**\n * Fuzz a single tool against a connected agent. Uses fast-check's\n * `fc.check` for property generation + shrinking; a response that trips\n * the oracle is minimized to the smallest request that still reproduces\n * the failure before it's collected in the report.\n *\n * Returns the tool skipped when the agent declares it unsupported or when\n * the response schema can't be compiled — those aren't oracle failures,\n * they're environmental conditions.\n */\nexport async function runToolFuzz(\n tool: ConformanceToolName,\n agent: AgentClient,\n options: RunnerOptions\n): Promise<RunnerResult> {\n // Compile the response schema up front. Ajv sometimes fails on bundled\n // schemas that still carry unresolved `$defs` refs (known upstream gap) —\n // skip the tool cleanly rather than flag every run as invalid.\n try {\n prepareResponseValidator(tool, options.schemas);\n } catch (err) {\n return {\n stats: skipStats('unresolvable_schema', (err as Error)?.message),\n failures: [],\n };\n }\n\n const schema = loadRequestSchema(tool, options.schemas);\n const arb = schemaToArbitrary(schema, { fixtures: options.fixtures }) as fc.Arbitrary<Record<string, unknown>>;\n\n // Counts only increment on fresh samples. `fc.check` re-runs the property\n // during shrinking; we don't want those replays in the accepted/rejected\n // tally. Track the minimum sample count we've seen and skip stat updates\n // on replayed samples by hashing the sample.\n const seenSamples = new Set<string>();\n const stats: ConformanceToolStats = { runs: 0, accepted: 0, rejected: 0, failed: 0, skipped: false };\n let transportUnsupported: string | null = null;\n\n const property = fc.asyncProperty(arb, async request => {\n const sampleKey = safeHash(request);\n const isFreshSample = !seenSamples.has(sampleKey);\n if (isFreshSample) {\n seenSamples.add(sampleKey);\n stats.runs++;\n }\n\n // Pin transport-envelope fields the buyer SDK manages itself.\n // `applyVersionEnvelope` (PR #1073) auto-fills these on outbound\n // requests, but the schema-driven arbitrary may overwrite them with\n // out-of-window integers (1-99 per schema bounds). `createAdcpServer`'s\n // single-field VERSION_UNSUPPORTED check (#1075) would then reject\n // every probe before the handler runs, masking handler bugs the\n // fuzzer is meant to catch. Version negotiation is exercised\n // separately by storyboards (`error_compliance/unsupported_major_version`).\n const probeRequest =\n 'adcp_major_version' in request || 'adcp_version' in request\n ? { ...request, adcp_major_version: ADCP_MAJOR_VERSION }\n : request;\n\n let result;\n try {\n result = await agent.executeTaskLegacy(tool, probeRequest);\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n // SDK throws FeatureUnsupportedError when the agent's declared\n // capabilities don't list the tool. That's the agent saying \"not\n // my job\" — not a conformance failure.\n if ((err as Error)?.name === 'FeatureUnsupportedError' || /does not support/i.test(message)) {\n transportUnsupported = message;\n return; // pass — we'll convert the whole tool to skipped below\n }\n throw new InvariantViolation({ thrown: String(err), name: (err as Error)?.name, message }, [\n 'unhandled transport error: ' + message,\n ]);\n }\n\n const verdict = evaluate({ tool, request, result, authToken: options.authToken, schemas: options.schemas });\n if (isFreshSample) {\n if (verdict.verdict === 'accepted') stats.accepted++;\n else if (verdict.verdict === 'rejected') stats.rejected++;\n }\n\n if (verdict.verdict === 'invalid') {\n throw new InvariantViolation(result, verdict.invariantFailures);\n }\n });\n\n const details = await fc.check(property, {\n seed: options.seed,\n numRuns: options.numRuns,\n verbose: 0,\n });\n\n if (transportUnsupported) {\n return { stats: skipStats('feature_unsupported', transportUnsupported), failures: [] };\n }\n\n if (!details.failed) {\n return { stats, failures: [] };\n }\n\n stats.failed = 1;\n const shrunkInput = (details.counterexample as [Record<string, unknown>] | null)?.[0];\n const err = details.errorInstance;\n const invariantFailures =\n err instanceof InvariantViolation\n ? err.invariantFailures\n : ['fuzz assertion failed: ' + ((err as Error | undefined)?.message ?? 'unknown')];\n const response = err instanceof InvariantViolation ? err.response : undefined;\n\n return {\n stats,\n failures: [\n {\n tool,\n path: details.counterexamplePath ?? undefined,\n seed: options.seed,\n shrunk: (details.numShrinks ?? 0) > 0,\n input: truncateForReport(shrunkInput, options.maxFailurePayloadBytes),\n response: truncateForReport(response, options.maxFailurePayloadBytes),\n verdict: 'invalid',\n invariantFailures,\n },\n ],\n };\n}\n\nfunction skipStats(reason: SkipReason, detail?: string): ConformanceToolStats {\n return {\n runs: 0,\n accepted: 0,\n rejected: 0,\n failed: 0,\n skipped: true,\n skipReason: reason,\n ...(detail ? { _detail: detail } : {}),\n } as ConformanceToolStats;\n}\n\nfunction safeHash(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\nfunction truncateForReport(value: unknown, maxBytes: number): unknown {\n if (value === undefined || value === null) return value;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? '';\n } catch {\n return { _truncated: true, _reason: 'unserializable' };\n }\n if (serialized.length <= maxBytes) return value;\n return {\n _truncated: true,\n _originalBytes: serialized.length,\n preview: serialized.slice(0, Math.max(256, maxBytes - 64)),\n };\n}\n\nclass InvariantViolation extends Error {\n constructor(\n public readonly response: unknown,\n public readonly invariantFailures: string[]\n ) {\n super(invariantFailures.join('; '));\n this.name = 'InvariantViolation';\n }\n}\n"],"mappings":"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","names":["err"]}
|
|
@@ -98,7 +98,7 @@ async function seedPropertyList({ agent }) {
|
|
|
98
98
|
return { ids: { list_ids: [listId] }, warnings: [] };
|
|
99
99
|
}
|
|
100
100
|
async function seedContentStandards({ agent }) {
|
|
101
|
-
const result = await agent.
|
|
101
|
+
const result = await agent.executeTaskLegacy("create_content_standards", {
|
|
102
102
|
idempotency_key: (0, import_idempotency.generateIdempotencyKey)(),
|
|
103
103
|
scope: { languages_any: ["en"] },
|
|
104
104
|
policies: [
|
|
@@ -126,7 +126,7 @@ async function seedContentStandards({ agent }) {
|
|
|
126
126
|
}
|
|
127
127
|
async function seedMediaBuy({ agent, brand }) {
|
|
128
128
|
const warnings = [];
|
|
129
|
-
const products = await agent.
|
|
129
|
+
const products = await agent.executeTaskLegacy("get_products", {
|
|
130
130
|
brief: "Conformance fuzzer seed \u2014 any product acceptable"
|
|
131
131
|
});
|
|
132
132
|
if (!products.success || products.status !== "completed" || !products.data) {
|
|
@@ -155,7 +155,7 @@ async function seedMediaBuy({ agent, brand }) {
|
|
|
155
155
|
const end = new Date(now.getTime() + 8 * 24 * 60 * 60 * 1e3);
|
|
156
156
|
const brandRef = { domain: brand.domain };
|
|
157
157
|
if (brand.brand_id) brandRef.brand_id = brand.brand_id;
|
|
158
|
-
const result = await agent.
|
|
158
|
+
const result = await agent.executeTaskLegacy("create_media_buy", {
|
|
159
159
|
idempotency_key: (0, import_idempotency.generateIdempotencyKey)(),
|
|
160
160
|
account: { brand: brandRef, operator: brand.domain },
|
|
161
161
|
brand: brandRef,
|
|
@@ -197,7 +197,7 @@ function summarizeResult(result) {
|
|
|
197
197
|
}
|
|
198
198
|
async function seedSyncCreatives({ agent, brand }) {
|
|
199
199
|
const warnings = [];
|
|
200
|
-
const formatsResult = await agent.
|
|
200
|
+
const formatsResult = await agent.executeTaskLegacy("list_creative_formats", {});
|
|
201
201
|
if (!formatsResult.success || formatsResult.status !== "completed" || !formatsResult.data) {
|
|
202
202
|
return {
|
|
203
203
|
ids: {},
|
|
@@ -220,7 +220,7 @@ async function seedSyncCreatives({ agent, brand }) {
|
|
|
220
220
|
const manifest = synthesizeManifestAssets(picked);
|
|
221
221
|
const creativeId = `cf_creative_${UNIQUE_TAG()}`;
|
|
222
222
|
const tag = UNIQUE_TAG();
|
|
223
|
-
const result = await agent.
|
|
223
|
+
const result = await agent.executeTaskLegacy("sync_creatives", {
|
|
224
224
|
idempotency_key: (0, import_idempotency.generateIdempotencyKey)(),
|
|
225
225
|
account: {
|
|
226
226
|
brand: { domain: brand.domain, ...brand.brand_id ? { brand_id: brand.brand_id } : {} },
|