@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
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
TASK_FEATURE_MAP
|
|
58
58
|
} from "../utils/capabilities.mjs";
|
|
59
59
|
import { normalizeRequestParams } from "../utils/request-normalizer.mjs";
|
|
60
|
+
import { globalAsyncLocalStorage } from "../utils/global-async-local-storage.mjs";
|
|
60
61
|
import { validateUserAgent } from "../utils/validate-user-agent.mjs";
|
|
61
62
|
import { resolveWebhookUrl, selectWebhookTemplate } from "./webhook-url.mjs";
|
|
62
63
|
import { getV25Adapter } from "../adapters/legacy/v2-5/index.mjs";
|
|
@@ -65,7 +66,388 @@ import {
|
|
|
65
66
|
validateProductsAgainstPropertyPolicy
|
|
66
67
|
} from "../media-buy/property-policy.mjs";
|
|
67
68
|
import { resolvePropertyList } from "../server/targeting-helpers.mjs";
|
|
69
|
+
import {
|
|
70
|
+
CreativeFormatCapabilityError,
|
|
71
|
+
CreativeFormatProjectionError,
|
|
72
|
+
projectMediaBuyCreativesForDelivery,
|
|
73
|
+
projectCreativeForDelivery,
|
|
74
|
+
projectSyncCreativesForDelivery,
|
|
75
|
+
resolveCreativeFormatWireMode,
|
|
76
|
+
stripLegacyCreativeIdentity
|
|
77
|
+
} from "../v2/projection/creative-delivery.mjs";
|
|
78
|
+
import {
|
|
79
|
+
legacyFormatConverterFromCatalogSnapshots
|
|
80
|
+
} from "../v2/projection/catalog-snapshot.mjs";
|
|
81
|
+
import { toCanonicalOnlyResponse } from "../v2/projection/augment-response.mjs";
|
|
82
|
+
import { legacyFormatRefsForDeclaration } from "../v2/projection/legacy-metadata.mjs";
|
|
83
|
+
import { canonicalize as canonicalizeJson } from "../utils/jcs.mjs";
|
|
68
84
|
const CAPABILITY_DISCOVERY_CONTEXT = /* @__PURE__ */ Symbol("capabilityDiscoveryContext");
|
|
85
|
+
function creativeSchemaSupport(value, depth = 0) {
|
|
86
|
+
if (depth > 24 || value === null || typeof value !== "object") return "unknown";
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
let legacy2 = false;
|
|
89
|
+
for (const item of value) {
|
|
90
|
+
const support = creativeSchemaSupport(item, depth + 1);
|
|
91
|
+
if (support === "canonical") return support;
|
|
92
|
+
if (support === "legacy") legacy2 = true;
|
|
93
|
+
}
|
|
94
|
+
return legacy2 ? "legacy" : "unknown";
|
|
95
|
+
}
|
|
96
|
+
const object = value;
|
|
97
|
+
const properties = object.properties;
|
|
98
|
+
if (properties !== null && typeof properties === "object" && !Array.isArray(properties)) {
|
|
99
|
+
const keys = properties;
|
|
100
|
+
if ("creative_id" in keys && "format_kind" in keys) return "canonical";
|
|
101
|
+
if ("creative_id" in keys && "format_id" in keys) return "legacy";
|
|
102
|
+
}
|
|
103
|
+
let legacy = false;
|
|
104
|
+
for (const child of Object.values(object)) {
|
|
105
|
+
const support = creativeSchemaSupport(child, depth + 1);
|
|
106
|
+
if (support === "canonical") return support;
|
|
107
|
+
if (support === "legacy") legacy = true;
|
|
108
|
+
}
|
|
109
|
+
return legacy ? "legacy" : "unknown";
|
|
110
|
+
}
|
|
111
|
+
function hasMediaBuyCreativeFormatData(request) {
|
|
112
|
+
if (request === null || typeof request !== "object" || Array.isArray(request)) return false;
|
|
113
|
+
const record = request;
|
|
114
|
+
return ["packages", "new_packages"].some((key) => {
|
|
115
|
+
const packages = record[key];
|
|
116
|
+
return Array.isArray(packages) && packages.some((pkg) => {
|
|
117
|
+
if (pkg === null || typeof pkg !== "object" || Array.isArray(pkg)) return false;
|
|
118
|
+
const packageRecord = pkg;
|
|
119
|
+
return Array.isArray(packageRecord.creatives) || Array.isArray(packageRecord.format_option_refs) || Array.isArray(packageRecord.format_ids) || typeof packageRecord.format_kind === "string" || Object.getOwnPropertySymbols(packageRecord).length > 0;
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
const CANONICAL_CREATIVE_ACTIVITY_TASKS = /* @__PURE__ */ new Set([
|
|
124
|
+
"get_products",
|
|
125
|
+
"create_media_buy",
|
|
126
|
+
"update_media_buy",
|
|
127
|
+
"sync_creatives",
|
|
128
|
+
"list_creatives",
|
|
129
|
+
"get_media_buys",
|
|
130
|
+
"get_media_buy_delivery",
|
|
131
|
+
"get_creative_delivery"
|
|
132
|
+
]);
|
|
133
|
+
const TASK_SCOPED_STATE_LIMIT = 1e4;
|
|
134
|
+
const CANONICAL_PACKAGE_ROUTE_TASKS = /* @__PURE__ */ new Set(["create_media_buy", "update_media_buy", "get_media_buys"]);
|
|
135
|
+
const canonicalCreativeRoutingSnapshots = /* @__PURE__ */ new WeakSet();
|
|
136
|
+
function canonicalAccountRoutingSnapshot(value) {
|
|
137
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
138
|
+
const account = value;
|
|
139
|
+
if (typeof account.account_id === "string") return Object.freeze({ account_id: account.account_id });
|
|
140
|
+
if (!account.brand || typeof account.brand !== "object" || Array.isArray(account.brand) || typeof account.operator !== "string") {
|
|
141
|
+
return void 0;
|
|
142
|
+
}
|
|
143
|
+
const sourceBrand = account.brand;
|
|
144
|
+
if (typeof sourceBrand.domain !== "string") return void 0;
|
|
145
|
+
const brand = Object.freeze({
|
|
146
|
+
domain: sourceBrand.domain,
|
|
147
|
+
...typeof sourceBrand.brand_id === "string" ? { brand_id: sourceBrand.brand_id } : {}
|
|
148
|
+
});
|
|
149
|
+
return Object.freeze({
|
|
150
|
+
brand,
|
|
151
|
+
operator: account.operator,
|
|
152
|
+
...typeof account.sandbox === "boolean" ? { sandbox: account.sandbox } : {}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
function canonicalOptionRefRoutingSnapshot(value) {
|
|
156
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
157
|
+
const ref = value;
|
|
158
|
+
if (typeof ref.format_option_id !== "string") return void 0;
|
|
159
|
+
if (ref.scope === "publisher" || typeof ref.publisher_domain === "string") {
|
|
160
|
+
if (typeof ref.publisher_domain !== "string") return void 0;
|
|
161
|
+
return Object.freeze({
|
|
162
|
+
scope: "publisher",
|
|
163
|
+
publisher_domain: ref.publisher_domain,
|
|
164
|
+
format_option_id: ref.format_option_id
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return Object.freeze({ scope: "product", format_option_id: ref.format_option_id });
|
|
168
|
+
}
|
|
169
|
+
function canonicalPackageRouteSelectorSnapshot(value) {
|
|
170
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
171
|
+
const selector = value;
|
|
172
|
+
const formatOptionRefs = Array.isArray(selector.format_option_refs) ? selector.format_option_refs.map(canonicalOptionRefRoutingSnapshot).filter((ref) => ref !== void 0) : [];
|
|
173
|
+
const snapshot = {
|
|
174
|
+
...typeof selector.package_id === "string" ? { package_id: selector.package_id } : {},
|
|
175
|
+
...typeof selector.product_id === "string" ? { product_id: selector.product_id } : {},
|
|
176
|
+
...formatOptionRefs.length > 0 ? { format_option_refs: Object.freeze(formatOptionRefs) } : {}
|
|
177
|
+
};
|
|
178
|
+
return Object.keys(snapshot).length > 0 ? Object.freeze(snapshot) : void 0;
|
|
179
|
+
}
|
|
180
|
+
function canonicalCreativeRoutingSnapshot(taskType, request) {
|
|
181
|
+
if (!CANONICAL_PACKAGE_ROUTE_TASKS.has(taskType) || !request || typeof request !== "object" || Array.isArray(request)) {
|
|
182
|
+
return void 0;
|
|
183
|
+
}
|
|
184
|
+
if (canonicalCreativeRoutingSnapshots.has(request)) {
|
|
185
|
+
return request;
|
|
186
|
+
}
|
|
187
|
+
const record = request;
|
|
188
|
+
const account = canonicalAccountRoutingSnapshot(record.account);
|
|
189
|
+
if (!account) return void 0;
|
|
190
|
+
const packageSnapshots = (key) => Object.freeze(
|
|
191
|
+
(Array.isArray(record[key]) ? record[key] : []).map(canonicalPackageRouteSelectorSnapshot).filter((selector) => selector !== void 0)
|
|
192
|
+
);
|
|
193
|
+
const packages = packageSnapshots("packages");
|
|
194
|
+
const newPackages = packageSnapshots("new_packages");
|
|
195
|
+
const snapshot = Object.freeze({
|
|
196
|
+
account,
|
|
197
|
+
...packages.length > 0 ? { packages } : {},
|
|
198
|
+
...newPackages.length > 0 ? { new_packages: newPackages } : {}
|
|
199
|
+
});
|
|
200
|
+
canonicalCreativeRoutingSnapshots.add(snapshot);
|
|
201
|
+
return snapshot;
|
|
202
|
+
}
|
|
203
|
+
const canonicalCreativeExecutionStorage = globalAsyncLocalStorage("canonicalCreativeExecution");
|
|
204
|
+
function prepareCanonicalCreativePayload(value, taskType, active = /* @__PURE__ */ new WeakSet(), prepared = /* @__PURE__ */ new WeakMap()) {
|
|
205
|
+
if (value === null || typeof value !== "object") return value;
|
|
206
|
+
for (let owner = value; owner !== null; owner = Object.getPrototypeOf(owner)) {
|
|
207
|
+
const toJSON = Object.getOwnPropertyDescriptor(owner, "toJSON");
|
|
208
|
+
if (toJSON && (!("value" in toJSON) || typeof toJSON.value === "function")) {
|
|
209
|
+
throw new CreativeFormatProjectionError(
|
|
210
|
+
taskType,
|
|
211
|
+
"(response:toJSON)",
|
|
212
|
+
"custom or accessor toJSON hooks cannot cross the canonical creative boundary safely"
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (active.has(value)) {
|
|
217
|
+
throw new CreativeFormatProjectionError(
|
|
218
|
+
taskType,
|
|
219
|
+
"(response:cycle)",
|
|
220
|
+
"cyclic values cannot cross the canonical creative boundary"
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const cached = prepared.get(value);
|
|
224
|
+
if (cached !== void 0) return cached;
|
|
225
|
+
active.add(value);
|
|
226
|
+
try {
|
|
227
|
+
const isArray = Array.isArray(value);
|
|
228
|
+
const prototype = Object.getPrototypeOf(value);
|
|
229
|
+
const plain = isArray ? prototype === Array.prototype : prototype === Object.prototype || prototype === null;
|
|
230
|
+
const output = isArray ? [] : Object.create(prototype === null ? null : Object.prototype);
|
|
231
|
+
prepared.set(value, output);
|
|
232
|
+
let changed = !plain;
|
|
233
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
234
|
+
if (isArray && key === "length") continue;
|
|
235
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
236
|
+
if (!descriptor) continue;
|
|
237
|
+
if (!("value" in descriptor)) {
|
|
238
|
+
throw new CreativeFormatProjectionError(
|
|
239
|
+
taskType,
|
|
240
|
+
`(response:${String(key)})`,
|
|
241
|
+
"accessors cannot cross the canonical creative boundary safely"
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
if (!descriptor.enumerable) continue;
|
|
245
|
+
const safe = prepareCanonicalCreativePayload(descriptor.value, taskType, active, prepared);
|
|
246
|
+
if (safe !== descriptor.value) changed = true;
|
|
247
|
+
Object.defineProperty(output, key, { ...descriptor, value: safe });
|
|
248
|
+
}
|
|
249
|
+
if (!changed) {
|
|
250
|
+
prepared.set(value, value);
|
|
251
|
+
return value;
|
|
252
|
+
}
|
|
253
|
+
return output;
|
|
254
|
+
} finally {
|
|
255
|
+
active.delete(value);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function projectPreparedCanonicalCreativeResponseValue(value, taskType, legacyFormatConverter, selectorContainer = {}) {
|
|
259
|
+
if (Array.isArray(value)) {
|
|
260
|
+
return value.map(
|
|
261
|
+
(item) => projectPreparedCanonicalCreativeResponseValue(item, taskType, legacyFormatConverter, selectorContainer)
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
if (!value || typeof value !== "object") return value;
|
|
265
|
+
let projected = value;
|
|
266
|
+
const isProduct = typeof projected.product_id === "string" && ("name" in projected || "description" in projected) && (Array.isArray(projected.format_ids) || Array.isArray(projected.format_options));
|
|
267
|
+
if (isProduct) {
|
|
268
|
+
const canonical = toCanonicalOnlyResponse(
|
|
269
|
+
{ products: [projected] },
|
|
270
|
+
{ legacyFormatConverter }
|
|
271
|
+
);
|
|
272
|
+
if (canonical.diagnostics.length > 0 || canonical.response.products.length !== 1) {
|
|
273
|
+
throw new CreativeFormatProjectionError(
|
|
274
|
+
taskType,
|
|
275
|
+
`(product:${String(projected.product_id)})`,
|
|
276
|
+
"legacy product formats in the response have no complete canonical representation"
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
projected = canonical.response.products[0];
|
|
280
|
+
} else if ((typeof projected.package_id === "string" || typeof projected.product_id === "string") && Array.isArray(projected.format_ids)) {
|
|
281
|
+
projected = projectMediaBuyCreativesForDelivery(
|
|
282
|
+
{ packages: [projected] },
|
|
283
|
+
"canonical",
|
|
284
|
+
taskType === "update_media_buy" ? "update_media_buy" : "create_media_buy",
|
|
285
|
+
legacyFormatConverter
|
|
286
|
+
).packages[0];
|
|
287
|
+
}
|
|
288
|
+
if (typeof projected.creative_id === "string" && (projected.format_id !== void 0 || typeof projected.format_kind === "string")) {
|
|
289
|
+
projected = projectCreativeForDelivery(
|
|
290
|
+
projected,
|
|
291
|
+
selectorContainer,
|
|
292
|
+
"canonical",
|
|
293
|
+
taskType,
|
|
294
|
+
legacyFormatConverter
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
const nextSelector = Array.isArray(projected.format_ids) || Array.isArray(projected.format_options) || Array.isArray(projected.format_option_refs) ? projected : selectorContainer;
|
|
298
|
+
let changed = projected !== value;
|
|
299
|
+
const next = { ...projected };
|
|
300
|
+
for (const [key, child] of Object.entries(projected)) {
|
|
301
|
+
const childProjected = projectPreparedCanonicalCreativeResponseValue(
|
|
302
|
+
child,
|
|
303
|
+
taskType,
|
|
304
|
+
legacyFormatConverter,
|
|
305
|
+
nextSelector
|
|
306
|
+
);
|
|
307
|
+
if (childProjected !== child) {
|
|
308
|
+
next[key] = childProjected;
|
|
309
|
+
changed = true;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return changed ? next : projected;
|
|
313
|
+
}
|
|
314
|
+
function projectCanonicalCreativeResponseValue(value, taskType, legacyFormatConverter, selectorContainer = {}) {
|
|
315
|
+
return projectPreparedCanonicalCreativeResponseValue(
|
|
316
|
+
prepareCanonicalCreativePayload(value, taskType),
|
|
317
|
+
taskType,
|
|
318
|
+
legacyFormatConverter,
|
|
319
|
+
selectorContainer
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
function projectCanonicalCreativeAncillaryValue(value, taskType, legacyFormatConverter) {
|
|
323
|
+
try {
|
|
324
|
+
return stripLegacyCreativeIdentity(projectCanonicalCreativeResponseValue(value, taskType, legacyFormatConverter));
|
|
325
|
+
} catch (error) {
|
|
326
|
+
if (!(error instanceof CreativeFormatProjectionError)) throw error;
|
|
327
|
+
return { omitted: true, reason: "canonical creative payload unavailable" };
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function canonicalCreativeActivity(activity) {
|
|
331
|
+
const active = canonicalCreativeExecutionStorage.getStore();
|
|
332
|
+
const effectiveTaskType = active?.taskType && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(active.taskType) ? active.taskType : activity.task_type;
|
|
333
|
+
if (!CANONICAL_CREATIVE_ACTIVITY_TASKS.has(effectiveTaskType) || activity.payload === void 0) {
|
|
334
|
+
return activity;
|
|
335
|
+
}
|
|
336
|
+
const converter = active?.taskType === effectiveTaskType ? active.legacyFormatConverter : void 0;
|
|
337
|
+
const source = activity.type === "protocol_request" && active?.taskType === effectiveTaskType && active.canonicalRequest !== void 0 ? { params: active.canonicalRequest } : activity.payload;
|
|
338
|
+
try {
|
|
339
|
+
return {
|
|
340
|
+
...activity,
|
|
341
|
+
payload: stripLegacyCreativeIdentity(projectCanonicalCreativeResponseValue(source, effectiveTaskType, converter))
|
|
342
|
+
};
|
|
343
|
+
} catch (error) {
|
|
344
|
+
if (!(error instanceof CreativeFormatProjectionError)) throw error;
|
|
345
|
+
return { ...activity, payload: { omitted: true, reason: "canonical creative payload unavailable" } };
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function canonicalCreativeDiagnosticBody(body, taskType) {
|
|
349
|
+
if (body === void 0) return void 0;
|
|
350
|
+
try {
|
|
351
|
+
const active = canonicalCreativeExecutionStorage.getStore();
|
|
352
|
+
const converter = active?.taskType === taskType ? active.legacyFormatConverter : void 0;
|
|
353
|
+
return JSON.stringify(
|
|
354
|
+
stripLegacyCreativeIdentity(projectCanonicalCreativeResponseValue(JSON.parse(body), taskType, converter))
|
|
355
|
+
);
|
|
356
|
+
} catch {
|
|
357
|
+
return "[canonical creative payload omitted]";
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function canonicalCreativeTransportActivity(event) {
|
|
361
|
+
const active = canonicalCreativeExecutionStorage.getStore();
|
|
362
|
+
const taskType = active?.taskType && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(active.taskType) ? active.taskType : event.taskType ?? event.tool;
|
|
363
|
+
if (!taskType || !CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType)) return event;
|
|
364
|
+
return {
|
|
365
|
+
...event,
|
|
366
|
+
...event.requestBody !== void 0 && {
|
|
367
|
+
requestBody: canonicalCreativeDiagnosticBody(event.requestBody, taskType)
|
|
368
|
+
},
|
|
369
|
+
...event.responseBody !== void 0 && {
|
|
370
|
+
responseBody: canonicalCreativeDiagnosticBody(event.responseBody, taskType)
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
function canonicalCreativeErrorInstance(error, legacySource) {
|
|
375
|
+
const own = {};
|
|
376
|
+
const descriptors = Object.getOwnPropertyDescriptors(error);
|
|
377
|
+
for (const [key, descriptor] of Object.entries(descriptors)) {
|
|
378
|
+
if ("value" in descriptor) own[key] = descriptor.value;
|
|
379
|
+
}
|
|
380
|
+
const { legacySource: _dropLegacySource, own: safeOwn } = stripLegacyCreativeIdentity({ own, legacySource });
|
|
381
|
+
void _dropLegacySource;
|
|
382
|
+
const clone = Object.create(Object.getPrototypeOf(error));
|
|
383
|
+
for (const [key, value] of Object.entries(safeOwn)) {
|
|
384
|
+
const descriptor = descriptors[key];
|
|
385
|
+
if (!descriptor || !("value" in descriptor)) continue;
|
|
386
|
+
Object.defineProperty(clone, key, { ...descriptor, value });
|
|
387
|
+
}
|
|
388
|
+
for (const symbol of Object.getOwnPropertySymbols(error)) {
|
|
389
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, symbol);
|
|
390
|
+
if (!descriptor || !("value" in descriptor)) continue;
|
|
391
|
+
const safe = stripLegacyCreativeIdentity({ value: descriptor.value, legacySource });
|
|
392
|
+
Object.defineProperty(clone, symbol, { ...descriptor, value: safe.value });
|
|
393
|
+
}
|
|
394
|
+
return stripLegacyCreativeIdentity(clone);
|
|
395
|
+
}
|
|
396
|
+
const PRIMARY_ADCP_TASK_NAMES = {
|
|
397
|
+
get_products: true,
|
|
398
|
+
create_media_buy: true,
|
|
399
|
+
update_media_buy: true,
|
|
400
|
+
sync_creatives: true,
|
|
401
|
+
list_creatives: true,
|
|
402
|
+
get_media_buys: true,
|
|
403
|
+
get_media_buy_delivery: true,
|
|
404
|
+
get_creative_delivery: true,
|
|
405
|
+
provide_performance_feedback: true,
|
|
406
|
+
get_signals: true,
|
|
407
|
+
activate_signal: true,
|
|
408
|
+
get_adcp_capabilities: true,
|
|
409
|
+
list_accounts: true,
|
|
410
|
+
sync_accounts: true,
|
|
411
|
+
sync_audiences: true,
|
|
412
|
+
create_property_list: true,
|
|
413
|
+
get_property_list: true,
|
|
414
|
+
update_property_list: true,
|
|
415
|
+
list_property_lists: true,
|
|
416
|
+
delete_property_list: true,
|
|
417
|
+
si_get_offering: true,
|
|
418
|
+
si_initiate_session: true,
|
|
419
|
+
si_send_message: true,
|
|
420
|
+
si_terminate_session: true,
|
|
421
|
+
get_brand_identity: true,
|
|
422
|
+
sync_plans: true,
|
|
423
|
+
check_governance: true,
|
|
424
|
+
report_plan_outcome: true,
|
|
425
|
+
get_plan_audit_logs: true,
|
|
426
|
+
context_match: true,
|
|
427
|
+
identity_match: true
|
|
428
|
+
};
|
|
429
|
+
const STANDARD_ADCP_TASK_NAMES = /* @__PURE__ */ new Set([
|
|
430
|
+
...Object.keys(PRIMARY_ADCP_TASK_NAMES),
|
|
431
|
+
"list_creative_formats",
|
|
432
|
+
"list_transformers",
|
|
433
|
+
"preview_creative",
|
|
434
|
+
"build_creative",
|
|
435
|
+
// These standard protocol tools still carry legacy creative `format_id`
|
|
436
|
+
// identity through artifacts, manifests, standards, or rights constraints.
|
|
437
|
+
// They are available only through explicitly named *Legacy APIs until a
|
|
438
|
+
// lossless canonical projection exists.
|
|
439
|
+
"list_content_standards",
|
|
440
|
+
"get_content_standards",
|
|
441
|
+
"create_content_standards",
|
|
442
|
+
"update_content_standards",
|
|
443
|
+
"calibrate_content",
|
|
444
|
+
"validate_content_delivery",
|
|
445
|
+
"get_media_buy_artifacts",
|
|
446
|
+
"get_creative_features",
|
|
447
|
+
"get_rights",
|
|
448
|
+
"acquire_rights",
|
|
449
|
+
"update_rights"
|
|
450
|
+
]);
|
|
69
451
|
class UnsupportedFeatureError extends Error {
|
|
70
452
|
constructor(feature, serverVersion, message) {
|
|
71
453
|
super(message || `Feature '${feature}' requires AdCP v3 but server is ${serverVersion}`);
|
|
@@ -136,6 +518,14 @@ function propertyListReferenceFromRequest(params) {
|
|
|
136
518
|
...typeof ref.auth_token === "string" ? { auth_token: ref.auth_token } : {}
|
|
137
519
|
};
|
|
138
520
|
}
|
|
521
|
+
function productPolicyRequestSnapshot(requestParams) {
|
|
522
|
+
const account = canonicalAccountRoutingSnapshot(requestParams.account);
|
|
523
|
+
const propertyList = propertyListReferenceFromRequest(requestParams);
|
|
524
|
+
return Object.freeze({
|
|
525
|
+
...account ? { account } : {},
|
|
526
|
+
...propertyList ? { property_list: Object.freeze(propertyList) } : {}
|
|
527
|
+
});
|
|
528
|
+
}
|
|
139
529
|
function hasProductPropertyPolicyRules(policy) {
|
|
140
530
|
return Boolean(
|
|
141
531
|
policy.allowedDomains?.length || policy.allowedPropertyIdentifiers?.length || policy.requireAllowedPropertyMatch || policy.excludedDomains?.length || policy.excludedPropertyIds?.length || policy.strict || policy.unknownSelectorBehavior || policy.missingPublisherPropertiesBehavior
|
|
@@ -196,8 +586,8 @@ class SingleAgentClient {
|
|
|
196
586
|
...config.validation?.requests != null && { requests: config.validation.requests },
|
|
197
587
|
...config.validation?.responses != null && { responses: config.validation.responses }
|
|
198
588
|
},
|
|
199
|
-
onActivity: config.onActivity,
|
|
200
|
-
onTransportActivity: config.onTransportActivity,
|
|
589
|
+
onActivity: config.onActivity ? (activity) => config.onActivity(canonicalCreativeActivity(activity)) : void 0,
|
|
590
|
+
onTransportActivity: config.onTransportActivity ? (event) => config.onTransportActivity(canonicalCreativeTransportActivity(event)) : void 0,
|
|
201
591
|
governance: config.governance,
|
|
202
592
|
adcpVersion: this.resolvedAdcpVersion,
|
|
203
593
|
...config.wireAdcpVersion !== void 0 && { wireAdcpVersion: config.wireAdcpVersion },
|
|
@@ -232,7 +622,237 @@ class SingleAgentClient {
|
|
|
232
622
|
_syntheticV2WarningFired = false;
|
|
233
623
|
// Gate: emit the synthetic-v2 warning once per client instance
|
|
234
624
|
productPolicyRequestParamsByTask = /* @__PURE__ */ new Map();
|
|
625
|
+
canonicalCreativeTaskAssociations = /* @__PURE__ */ new Map();
|
|
626
|
+
canonicalLegacyRoutes = /* @__PURE__ */ new Map();
|
|
235
627
|
resolvedAdcpVersion;
|
|
628
|
+
resolveLegacyFormatConverter(override, projectionCatalogs = this.config.projectionCatalogs) {
|
|
629
|
+
return legacyFormatConverterFromCatalogSnapshots(projectionCatalogs, override ?? this.config.legacyFormatConverter);
|
|
630
|
+
}
|
|
631
|
+
canonicalAccountScope(account) {
|
|
632
|
+
if (account === void 0) return "none";
|
|
633
|
+
return canonicalizeJson(canonicalAccountRoutingSnapshot(account) ?? account);
|
|
634
|
+
}
|
|
635
|
+
canonicalLegacyRouteKey(account, productId, ref) {
|
|
636
|
+
return canonicalizeJson([
|
|
637
|
+
this.canonicalAccountScope(account),
|
|
638
|
+
productId,
|
|
639
|
+
ref.scope,
|
|
640
|
+
ref.scope === "publisher" ? ref.publisher_domain.toLowerCase() : "",
|
|
641
|
+
ref.format_option_id
|
|
642
|
+
]);
|
|
643
|
+
}
|
|
644
|
+
canonicalLegacyPackageRouteKey(account, packageId) {
|
|
645
|
+
return canonicalizeJson([this.canonicalAccountScope(account), "package", packageId]);
|
|
646
|
+
}
|
|
647
|
+
sameCanonicalOptionRef(left, right) {
|
|
648
|
+
return left.scope === right.scope && left.format_option_id === right.format_option_id && (left.scope !== "publisher" || right.scope === "publisher" && left.publisher_domain.toLowerCase() === right.publisher_domain.toLowerCase());
|
|
649
|
+
}
|
|
650
|
+
rememberCanonicalLegacyRoute(key, route) {
|
|
651
|
+
this.canonicalLegacyRoutes.delete(key);
|
|
652
|
+
this.canonicalLegacyRoutes.set(key, {
|
|
653
|
+
...route,
|
|
654
|
+
refs: Object.freeze(route.refs.map((ref) => Object.freeze({ ...ref })))
|
|
655
|
+
});
|
|
656
|
+
while (this.canonicalLegacyRoutes.size > TASK_SCOPED_STATE_LIMIT) {
|
|
657
|
+
const oldest = this.canonicalLegacyRoutes.keys().next().value;
|
|
658
|
+
if (oldest === void 0) break;
|
|
659
|
+
this.canonicalLegacyRoutes.delete(oldest);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
invalidateCanonicalProductRoutes(products, account) {
|
|
663
|
+
const accountScope = this.canonicalAccountScope(account);
|
|
664
|
+
const productIds = /* @__PURE__ */ new Set();
|
|
665
|
+
for (const value of products) {
|
|
666
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
667
|
+
const productId = value.product_id;
|
|
668
|
+
if (typeof productId === "string") productIds.add(productId);
|
|
669
|
+
}
|
|
670
|
+
if (productIds.size === 0) return;
|
|
671
|
+
for (const [key, route] of this.canonicalLegacyRoutes) {
|
|
672
|
+
if (route.kind === "product" && route.accountScope === accountScope && productIds.has(route.productId)) {
|
|
673
|
+
this.canonicalLegacyRoutes.delete(key);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
rememberCanonicalProductRoutes(products, account, authoritativeProducts = products) {
|
|
678
|
+
this.invalidateCanonicalProductRoutes(authoritativeProducts, account);
|
|
679
|
+
const accountScope = this.canonicalAccountScope(account);
|
|
680
|
+
for (const value of products) {
|
|
681
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
682
|
+
const product = value;
|
|
683
|
+
if (typeof product.product_id !== "string" || !Array.isArray(product.format_options)) continue;
|
|
684
|
+
for (const optionValue of product.format_options) {
|
|
685
|
+
if (!optionValue || typeof optionValue !== "object" || Array.isArray(optionValue)) continue;
|
|
686
|
+
const option = optionValue;
|
|
687
|
+
if (typeof option.format_option_id !== "string") continue;
|
|
688
|
+
const ref = typeof option.publisher_domain === "string" ? {
|
|
689
|
+
scope: "publisher",
|
|
690
|
+
publisher_domain: option.publisher_domain,
|
|
691
|
+
format_option_id: option.format_option_id
|
|
692
|
+
} : { scope: "product", format_option_id: option.format_option_id };
|
|
693
|
+
const refs = legacyFormatRefsForDeclaration(option);
|
|
694
|
+
if (refs.length === 0) continue;
|
|
695
|
+
this.rememberCanonicalLegacyRoute(this.canonicalLegacyRouteKey(account, product.product_id, ref), {
|
|
696
|
+
kind: "product",
|
|
697
|
+
accountScope,
|
|
698
|
+
productId: product.product_id,
|
|
699
|
+
optionRef: ref,
|
|
700
|
+
refs
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
routeForOption(account, productId, optionRef) {
|
|
706
|
+
const accountScope = this.canonicalAccountScope(account);
|
|
707
|
+
const exactKey = this.canonicalLegacyRouteKey(account, productId, optionRef);
|
|
708
|
+
const exact = this.canonicalLegacyRoutes.get(exactKey);
|
|
709
|
+
if (exact) {
|
|
710
|
+
this.canonicalLegacyRoutes.delete(exactKey);
|
|
711
|
+
this.canonicalLegacyRoutes.set(exactKey, exact);
|
|
712
|
+
return exact;
|
|
713
|
+
}
|
|
714
|
+
const candidates = [...this.canonicalLegacyRoutes.entries()].filter(
|
|
715
|
+
([, route]) => route.kind === "product" && route.productId === productId && this.sameCanonicalOptionRef(route.optionRef, optionRef)
|
|
716
|
+
);
|
|
717
|
+
if (candidates.length !== 1) return void 0;
|
|
718
|
+
const [key, candidate] = candidates[0];
|
|
719
|
+
if (accountScope === "none" || candidate.accountScope !== "none") return void 0;
|
|
720
|
+
this.canonicalLegacyRoutes.delete(key);
|
|
721
|
+
this.canonicalLegacyRoutes.set(key, candidate);
|
|
722
|
+
return candidate;
|
|
723
|
+
}
|
|
724
|
+
routeForPackage(account, packageId) {
|
|
725
|
+
const exactKey = this.canonicalLegacyPackageRouteKey(account, packageId);
|
|
726
|
+
const exact = this.canonicalLegacyRoutes.get(exactKey);
|
|
727
|
+
if (exact) {
|
|
728
|
+
this.canonicalLegacyRoutes.delete(exactKey);
|
|
729
|
+
this.canonicalLegacyRoutes.set(exactKey, exact);
|
|
730
|
+
return exact;
|
|
731
|
+
}
|
|
732
|
+
return void 0;
|
|
733
|
+
}
|
|
734
|
+
packageIdsFromSelector(selector) {
|
|
735
|
+
const ids = /* @__PURE__ */ new Set();
|
|
736
|
+
if (typeof selector.package_id === "string") ids.add(selector.package_id);
|
|
737
|
+
if (Array.isArray(selector.selector_containers)) {
|
|
738
|
+
for (const value of selector.selector_containers) {
|
|
739
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
740
|
+
for (const id of this.packageIdsFromSelector(value)) ids.add(id);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
return [...ids];
|
|
744
|
+
}
|
|
745
|
+
cachedCanonicalLegacyRefs(context, account) {
|
|
746
|
+
const selector = context.source === "product" ? context.declaration : context.source === "creative" ? context.selector : context.selector;
|
|
747
|
+
const productId = context.source === "product" ? context.productId : typeof selector.product_id === "string" ? selector.product_id : void 0;
|
|
748
|
+
if (!productId) {
|
|
749
|
+
const packageIds = this.packageIdsFromSelector(selector);
|
|
750
|
+
if (packageIds.length === 0) return void 0;
|
|
751
|
+
const routes = packageIds.map((packageId) => this.routeForPackage(account, packageId));
|
|
752
|
+
if (routes.some((route) => route === void 0)) return void 0;
|
|
753
|
+
const normalized = routes.map(
|
|
754
|
+
(route) => canonicalizeJson(
|
|
755
|
+
route.refs.map((ref) => ({ ...ref })).sort((left, right) => canonicalizeJson(left).localeCompare(canonicalizeJson(right)))
|
|
756
|
+
)
|
|
757
|
+
);
|
|
758
|
+
if (!normalized.every((value) => value === normalized[0])) return void 0;
|
|
759
|
+
return routes[0].refs.map((value) => ({ ...value }));
|
|
760
|
+
}
|
|
761
|
+
const rawRefs = [];
|
|
762
|
+
if (context.source === "product") rawRefs.push(context.declaration);
|
|
763
|
+
if (context.source === "creative" && context.creative.format_option_ref !== void 0) {
|
|
764
|
+
rawRefs.push(context.creative.format_option_ref);
|
|
765
|
+
} else if (Array.isArray(selector.format_option_refs)) {
|
|
766
|
+
rawRefs.push(...selector.format_option_refs);
|
|
767
|
+
}
|
|
768
|
+
const optionRefs = [];
|
|
769
|
+
for (const value of rawRefs) {
|
|
770
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
771
|
+
const record = value;
|
|
772
|
+
if (typeof record.format_option_id !== "string") continue;
|
|
773
|
+
if (record.scope === "publisher" || typeof record.publisher_domain === "string") {
|
|
774
|
+
if (typeof record.publisher_domain !== "string") continue;
|
|
775
|
+
optionRefs.push({
|
|
776
|
+
scope: "publisher",
|
|
777
|
+
publisher_domain: record.publisher_domain,
|
|
778
|
+
format_option_id: record.format_option_id
|
|
779
|
+
});
|
|
780
|
+
} else {
|
|
781
|
+
optionRefs.push({ scope: "product", format_option_id: record.format_option_id });
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (optionRefs.length === 0) return void 0;
|
|
785
|
+
const resolved = [];
|
|
786
|
+
for (const ref of optionRefs) {
|
|
787
|
+
const route = this.routeForOption(account, productId, ref);
|
|
788
|
+
if (!route) return void 0;
|
|
789
|
+
resolved.push(...route.refs.map((value) => ({ ...value })));
|
|
790
|
+
}
|
|
791
|
+
return resolved;
|
|
792
|
+
}
|
|
793
|
+
rememberCanonicalPackageRoutes(response, request) {
|
|
794
|
+
if (!response || typeof response !== "object" || Array.isArray(response)) return;
|
|
795
|
+
const requestRecord = request && typeof request === "object" && !Array.isArray(request) ? request : void 0;
|
|
796
|
+
const account = requestRecord?.account;
|
|
797
|
+
if (account === void 0) return;
|
|
798
|
+
const accountScope = this.canonicalAccountScope(account);
|
|
799
|
+
const requestPackages = ["packages", "new_packages"].flatMap(
|
|
800
|
+
(key) => Array.isArray(requestRecord?.[key]) ? requestRecord[key].filter(
|
|
801
|
+
(value) => Boolean(value && typeof value === "object" && !Array.isArray(value))
|
|
802
|
+
) : []
|
|
803
|
+
);
|
|
804
|
+
const responsePackages = [];
|
|
805
|
+
const visit = (value, depth = 0) => {
|
|
806
|
+
if (depth > 8 || !value || typeof value !== "object") return;
|
|
807
|
+
if (Array.isArray(value)) {
|
|
808
|
+
for (const item of value) visit(item, depth + 1);
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
const record = value;
|
|
812
|
+
if (typeof record.package_id === "string") responsePackages.push(record);
|
|
813
|
+
for (const key of ["packages", "affected_packages", "media_buys"]) {
|
|
814
|
+
if (record[key] !== void 0) visit(record[key], depth + 1);
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
visit(response);
|
|
818
|
+
for (const pkg of responsePackages) {
|
|
819
|
+
const packageId = pkg.package_id;
|
|
820
|
+
let selector = pkg;
|
|
821
|
+
let refs = this.cachedCanonicalLegacyRefs(
|
|
822
|
+
{ source: "selector", selector, operation: "package_route", field: packageId },
|
|
823
|
+
account
|
|
824
|
+
);
|
|
825
|
+
if (!refs) {
|
|
826
|
+
const byPackageId = requestPackages.filter((value) => value.package_id === packageId);
|
|
827
|
+
const productId = typeof pkg.product_id === "string" ? pkg.product_id : void 0;
|
|
828
|
+
const byProduct = productId ? requestPackages.filter((value) => value.product_id === productId) : [];
|
|
829
|
+
const matches = byPackageId.length === 1 ? byPackageId : byProduct.length === 1 ? byProduct : [];
|
|
830
|
+
selector = matches[0];
|
|
831
|
+
if (selector) {
|
|
832
|
+
refs = this.cachedCanonicalLegacyRefs(
|
|
833
|
+
{ source: "selector", selector, operation: "package_route", field: packageId },
|
|
834
|
+
account
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
if (!refs || refs.length === 0) continue;
|
|
839
|
+
this.rememberCanonicalLegacyRoute(this.canonicalLegacyPackageRouteKey(account, packageId), {
|
|
840
|
+
kind: "package",
|
|
841
|
+
accountScope,
|
|
842
|
+
packageId,
|
|
843
|
+
refs
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
rememberCanonicalPackageRoutesForTask(taskType, response, request) {
|
|
848
|
+
if (taskType === "create_media_buy" || taskType === "update_media_buy" || taskType === "get_media_buys") {
|
|
849
|
+
this.rememberCanonicalPackageRoutes(response, request);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
resolveCanonicalFormatLegacyResolver(override, account) {
|
|
853
|
+
const configured = this.config.canonicalFormatLegacyResolver;
|
|
854
|
+
return (context) => override?.(context) ?? this.cachedCanonicalLegacyRefs(context, account) ?? configured?.(context);
|
|
855
|
+
}
|
|
236
856
|
/**
|
|
237
857
|
* Returns the AdCP protocol version this client is configured to speak.
|
|
238
858
|
*
|
|
@@ -269,6 +889,10 @@ class SingleAgentClient {
|
|
|
269
889
|
...this.normalizedAgent,
|
|
270
890
|
agent_uri: this.discoveredEndpoint
|
|
271
891
|
};
|
|
892
|
+
if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials) {
|
|
893
|
+
const { shareNonInteractiveOAuthProvider } = await import("../auth/oauth/provider-cache.mjs");
|
|
894
|
+
shareNonInteractiveOAuthProvider(this.normalizedAgent, this.discoveredAgent);
|
|
895
|
+
}
|
|
272
896
|
return this.discoveredAgent;
|
|
273
897
|
}
|
|
274
898
|
if (this.normalizedAgent.oauth_client_credentials) {
|
|
@@ -281,7 +905,12 @@ class SingleAgentClient {
|
|
|
281
905
|
}
|
|
282
906
|
const discoveredEndpoint = await this.discoverMCPEndpoint(this.normalizedAgent.agent_uri, options);
|
|
283
907
|
if (usesScopedFetch) {
|
|
284
|
-
|
|
908
|
+
const discoveredAgent = { ...this.normalizedAgent, agent_uri: discoveredEndpoint };
|
|
909
|
+
if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials) {
|
|
910
|
+
const { shareNonInteractiveOAuthProvider } = await import("../auth/oauth/provider-cache.mjs");
|
|
911
|
+
shareNonInteractiveOAuthProvider(this.normalizedAgent, discoveredAgent);
|
|
912
|
+
}
|
|
913
|
+
return discoveredAgent;
|
|
285
914
|
}
|
|
286
915
|
this.discoveredEndpoint = discoveredEndpoint;
|
|
287
916
|
this.canonicalBaseUrl = this.computeBaseUrl(this.discoveredEndpoint);
|
|
@@ -289,6 +918,10 @@ class SingleAgentClient {
|
|
|
289
918
|
...this.normalizedAgent,
|
|
290
919
|
agent_uri: this.discoveredEndpoint
|
|
291
920
|
};
|
|
921
|
+
if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials) {
|
|
922
|
+
const { shareNonInteractiveOAuthProvider } = await import("../auth/oauth/provider-cache.mjs");
|
|
923
|
+
shareNonInteractiveOAuthProvider(this.normalizedAgent, this.discoveredAgent);
|
|
924
|
+
}
|
|
292
925
|
return this.discoveredAgent;
|
|
293
926
|
}
|
|
294
927
|
/**
|
|
@@ -444,8 +1077,10 @@ class SingleAgentClient {
|
|
|
444
1077
|
const authToken = this.normalizedAgent.oauth_client_credentials ? this.normalizedAgent.oauth_tokens?.access_token : this.agent.auth_token;
|
|
445
1078
|
const agentHeaders = this.agent.headers;
|
|
446
1079
|
const authHeaders = { ...agentHeaders, ...createMCPAuthHeaders(authToken) };
|
|
447
|
-
const
|
|
1080
|
+
const oauth = this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials ? await import("../auth/oauth/index.mjs") : void 0;
|
|
1081
|
+
const authProvider = oauth ? (await import("../auth/oauth/provider-cache.mjs")).getNonInteractiveOAuthProvider(this.normalizedAgent, {
|
|
448
1082
|
agentHint: this.normalizedAgent.id,
|
|
1083
|
+
storage: oauth.getAgentStorage(this.normalizedAgent),
|
|
449
1084
|
allowHttp: isLikelyPrivateUrl(this.normalizedAgent.agent_uri)
|
|
450
1085
|
}) : void 0;
|
|
451
1086
|
const testEndpoint = async (url) => {
|
|
@@ -643,8 +1278,9 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
643
1278
|
* This is the lower-level receiver primitive for integrations that need to
|
|
644
1279
|
* map malformed webhooks to precise HTTP responses. It verifies the legacy
|
|
645
1280
|
* HMAC profile when `webhookSecret` is configured, parses raw JSON bodies,
|
|
646
|
-
* validates the transport envelope shape, and returns the
|
|
647
|
-
* result plus routing metadata.
|
|
1281
|
+
* validates the transport envelope shape, and returns the canonicalized
|
|
1282
|
+
* AdCP result plus routing metadata. Legacy wire inspection is intentionally
|
|
1283
|
+
* confined to the transport adapter and is not returned by this primary API.
|
|
648
1284
|
*/
|
|
649
1285
|
async verifyAndParseWebhook(options) {
|
|
650
1286
|
const rawBody = options.rawBody ?? rawBodyFromUnknown(options.body);
|
|
@@ -676,37 +1312,107 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
676
1312
|
if (!parsedPayload.ok) {
|
|
677
1313
|
return parsedPayload;
|
|
678
1314
|
}
|
|
1315
|
+
const parsedTaskType = isObjectRecord(parsedPayload.payload) && typeof parsedPayload.payload.task_type === "string" ? parsedPayload.payload.task_type : void 0;
|
|
1316
|
+
const payloadRecord = isObjectRecord(parsedPayload.payload) ? parsedPayload.payload : void 0;
|
|
1317
|
+
const associatedTaskTypes = new Set(
|
|
1318
|
+
[
|
|
1319
|
+
options.operationId,
|
|
1320
|
+
typeof payloadRecord?.operation_id === "string" ? payloadRecord.operation_id : void 0,
|
|
1321
|
+
typeof payloadRecord?.task_id === "string" ? payloadRecord.task_id : void 0,
|
|
1322
|
+
typeof payloadRecord?.context_id === "string" ? payloadRecord.context_id : void 0
|
|
1323
|
+
].flatMap((id) => {
|
|
1324
|
+
const taskType = this.canonicalCreativeTaskAssociation(id)?.taskType;
|
|
1325
|
+
return taskType ? [taskType] : [];
|
|
1326
|
+
})
|
|
1327
|
+
);
|
|
1328
|
+
const associatedTaskType = associatedTaskTypes.size === 1 ? [...associatedTaskTypes][0] : void 0;
|
|
1329
|
+
const routedTaskType = options.taskType === "unknown" ? void 0 : options.taskType;
|
|
1330
|
+
const declaredTaskType = routedTaskType ?? parsedTaskType;
|
|
1331
|
+
if (associatedTaskTypes.size > 1 || associatedTaskType !== void 0 && declaredTaskType !== void 0 && associatedTaskType !== declaredTaskType) {
|
|
1332
|
+
return {
|
|
1333
|
+
ok: false,
|
|
1334
|
+
code: "webhook_envelope_invalid",
|
|
1335
|
+
message: "Webhook task_type does not match the locally tracked task association."
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
let normalizedTaskType = associatedTaskType ?? declaredTaskType;
|
|
679
1339
|
try {
|
|
680
1340
|
const normalizedPayload = this.normalizeWebhookPayload(
|
|
681
1341
|
parsedPayload.payload,
|
|
682
|
-
|
|
1342
|
+
normalizedTaskType ?? "unknown",
|
|
683
1343
|
options.operationId ?? "unknown"
|
|
684
1344
|
);
|
|
1345
|
+
normalizedTaskType = normalizedPayload.task_type;
|
|
1346
|
+
if (associatedTaskType !== void 0 && normalizedPayload.task_type !== associatedTaskType) {
|
|
1347
|
+
return {
|
|
1348
|
+
ok: false,
|
|
1349
|
+
code: "webhook_envelope_invalid",
|
|
1350
|
+
message: "Webhook task_type does not match the locally tracked task association."
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
1353
|
+
const metadata = {
|
|
1354
|
+
operation_id: normalizedPayload.operation_id,
|
|
1355
|
+
context_id: normalizedPayload.context_id,
|
|
1356
|
+
task_id: normalizedPayload.task_id,
|
|
1357
|
+
agent_id: this.agent.id,
|
|
1358
|
+
task_type: normalizedPayload.task_type,
|
|
1359
|
+
status: normalizedPayload.status,
|
|
1360
|
+
message: normalizedPayload.message,
|
|
1361
|
+
timestamp: normalizedPayload.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1362
|
+
idempotency_key: normalizedPayload.idempotency_key,
|
|
1363
|
+
protocol: normalizedPayload.protocol ?? "mcp"
|
|
1364
|
+
};
|
|
1365
|
+
const canonicalResult = this.canonicalizeWebhookCreativeResult(metadata, normalizedPayload.result);
|
|
1366
|
+
const canonicalCreativeTask = CANONICAL_CREATIVE_ACTIVITY_TASKS.has(normalizedPayload.task_type);
|
|
1367
|
+
const legacyFormatConverter = this.legacyFormatConverterForWebhook(metadata);
|
|
1368
|
+
const canonicalEnvelope = canonicalCreativeTask ? stripLegacyCreativeIdentity(
|
|
1369
|
+
projectCanonicalCreativeResponseValue(
|
|
1370
|
+
parsedPayload.payload,
|
|
1371
|
+
normalizedPayload.task_type,
|
|
1372
|
+
legacyFormatConverter
|
|
1373
|
+
)
|
|
1374
|
+
) : parsedPayload.payload;
|
|
1375
|
+
const canonicalMessage = canonicalCreativeTask ? stripLegacyCreativeIdentity({
|
|
1376
|
+
message: normalizedPayload.message,
|
|
1377
|
+
legacySource: parsedPayload.payload
|
|
1378
|
+
}).message : normalizedPayload.message;
|
|
685
1379
|
return {
|
|
686
1380
|
ok: true,
|
|
687
1381
|
protocol: normalizedPayload.protocol ?? "mcp",
|
|
688
|
-
envelope:
|
|
689
|
-
result:
|
|
1382
|
+
envelope: canonicalEnvelope,
|
|
1383
|
+
result: canonicalResult,
|
|
690
1384
|
metadata: {
|
|
691
1385
|
operationId: normalizedPayload.operation_id,
|
|
692
1386
|
contextId: normalizedPayload.context_id,
|
|
693
1387
|
taskId: normalizedPayload.task_id,
|
|
694
1388
|
taskType: normalizedPayload.task_type,
|
|
695
1389
|
status: normalizedPayload.status,
|
|
696
|
-
message:
|
|
1390
|
+
message: canonicalMessage,
|
|
697
1391
|
timestamp: normalizedPayload.timestamp,
|
|
698
1392
|
idempotencyKey: normalizedPayload.idempotency_key
|
|
699
1393
|
}
|
|
700
1394
|
};
|
|
701
1395
|
} catch (error) {
|
|
1396
|
+
const canonicalCreativeTask = normalizedTaskType !== void 0 && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(normalizedTaskType);
|
|
702
1397
|
if (error instanceof WebhookDispatchError) {
|
|
703
|
-
|
|
1398
|
+
if (!canonicalCreativeTask) {
|
|
1399
|
+
return { ok: false, code: error.code, message: error.message };
|
|
1400
|
+
}
|
|
1401
|
+
const safe = stripLegacyCreativeIdentity({
|
|
1402
|
+
message: error.message,
|
|
1403
|
+
legacySource: parsedPayload.payload
|
|
1404
|
+
});
|
|
1405
|
+
return { ok: false, code: error.code, message: safe.message };
|
|
1406
|
+
}
|
|
1407
|
+
const message = error instanceof Error ? error.message : "Webhook payload could not be normalized.";
|
|
1408
|
+
if (canonicalCreativeTask) {
|
|
1409
|
+
const safe = stripLegacyCreativeIdentity({ message, legacySource: parsedPayload.payload });
|
|
1410
|
+
return { ok: false, code: "webhook_result_invalid", message: safe.message };
|
|
704
1411
|
}
|
|
705
1412
|
return {
|
|
706
1413
|
ok: false,
|
|
707
1414
|
code: "webhook_result_invalid",
|
|
708
|
-
message:
|
|
709
|
-
cause: error
|
|
1415
|
+
message: "Webhook payload could not be normalized."
|
|
710
1416
|
};
|
|
711
1417
|
}
|
|
712
1418
|
}
|
|
@@ -722,36 +1428,88 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
722
1428
|
timestamp: parsed.metadata.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
723
1429
|
idempotency_key: parsed.metadata.idempotencyKey,
|
|
724
1430
|
protocol: parsed.protocol,
|
|
725
|
-
rawHTTPPayload: parsed.envelope
|
|
1431
|
+
rawHTTPPayload: CANONICAL_CREATIVE_ACTIVITY_TASKS.has(parsed.metadata.taskType) ? stripLegacyCreativeIdentity(parsed.envelope) : parsed.envelope
|
|
726
1432
|
};
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
metadata
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1433
|
+
this.rememberCanonicalCreativeWebhookContext(metadata);
|
|
1434
|
+
try {
|
|
1435
|
+
const canonicalResult = this.canonicalizeWebhookCreativeResult(metadata, parsed.result);
|
|
1436
|
+
const policyDispatch = await this.applyProductPropertyPolicyToWebhookResult(
|
|
1437
|
+
canonicalResult,
|
|
1438
|
+
metadata
|
|
1439
|
+
);
|
|
1440
|
+
const webhookResult = policyDispatch.result;
|
|
1441
|
+
metadata = policyDispatch.metadata;
|
|
1442
|
+
await this.config.onActivity?.(
|
|
1443
|
+
canonicalCreativeActivity({
|
|
1444
|
+
type: "webhook_received",
|
|
1445
|
+
operation_id: metadata.operation_id,
|
|
1446
|
+
agent_id: metadata.agent_id,
|
|
1447
|
+
context_id: metadata.context_id,
|
|
1448
|
+
task_id: metadata.task_id,
|
|
1449
|
+
task_type: metadata.task_type,
|
|
1450
|
+
status: metadata.status,
|
|
1451
|
+
payload: canonicalResult,
|
|
1452
|
+
timestamp: metadata.timestamp
|
|
1453
|
+
})
|
|
1454
|
+
);
|
|
1455
|
+
if (policyDispatch.suppressHandler) return true;
|
|
1456
|
+
if (this.asyncHandler) {
|
|
1457
|
+
await this.asyncHandler.handleWebhook({ result: webhookResult, metadata });
|
|
1458
|
+
return true;
|
|
1459
|
+
}
|
|
1460
|
+
return false;
|
|
1461
|
+
} finally {
|
|
1462
|
+
this.executor.observeExternalTaskStatus(
|
|
1463
|
+
metadata.operation_id,
|
|
1464
|
+
metadata.status,
|
|
1465
|
+
metadata.rawHTTPPayload
|
|
1466
|
+
);
|
|
745
1467
|
this.forgetProductPolicyRequestParams(metadata);
|
|
746
|
-
return true;
|
|
747
1468
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1469
|
+
}
|
|
1470
|
+
rememberCanonicalCreativeWebhookContext(metadata) {
|
|
1471
|
+
if (!metadata.context_id || !CANONICAL_CREATIVE_ACTIVITY_TASKS.has(metadata.task_type)) return;
|
|
1472
|
+
const association = this.canonicalCreativeTaskAssociation(metadata.operation_id) ?? this.canonicalCreativeTaskAssociation(metadata.task_id) ?? this.canonicalCreativeTaskAssociation(metadata.context_id);
|
|
1473
|
+
if (!association) return;
|
|
1474
|
+
this.rememberCanonicalCreativeTaskAssociation(
|
|
1475
|
+
metadata.context_id,
|
|
1476
|
+
association.taskType,
|
|
1477
|
+
association.legacyFormatConverter,
|
|
1478
|
+
association.routingSnapshot
|
|
1479
|
+
);
|
|
1480
|
+
}
|
|
1481
|
+
canonicalizeWebhookCreativeResult(metadata, result) {
|
|
1482
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) return result;
|
|
1483
|
+
const taskType = metadata.task_type;
|
|
1484
|
+
const legacyFormatConverter = this.legacyFormatConverterForWebhook(metadata);
|
|
1485
|
+
const response = result;
|
|
1486
|
+
if (taskType === "get_products" && Array.isArray(response.products)) {
|
|
1487
|
+
const { response: canonical2, diagnostics } = toCanonicalOnlyResponse(
|
|
1488
|
+
response,
|
|
1489
|
+
{ legacyFormatConverter }
|
|
1490
|
+
);
|
|
1491
|
+
const requestParams = this.productPolicyRequestParamsForWebhook(metadata);
|
|
1492
|
+
this.rememberCanonicalProductRoutes(canonical2.products, requestParams.account, response.products);
|
|
1493
|
+
const { _message: _dropLegacyMessage, ...safe } = canonical2;
|
|
1494
|
+
void _dropLegacyMessage;
|
|
1495
|
+
return stripLegacyCreativeIdentity({ ...safe, projection: { diagnostics } });
|
|
1496
|
+
}
|
|
1497
|
+
if (taskType === "list_creatives" && Array.isArray(response.creatives)) {
|
|
1498
|
+
const { _message: _dropLegacyMessage, ...safe } = response;
|
|
1499
|
+
void _dropLegacyMessage;
|
|
1500
|
+
return stripLegacyCreativeIdentity({
|
|
1501
|
+
...safe,
|
|
1502
|
+
creatives: response.creatives.map(
|
|
1503
|
+
(creative) => projectCreativeForDelivery(creative, {}, "canonical", "list_creatives", legacyFormatConverter)
|
|
1504
|
+
)
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
const canonical = CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType) ? stripLegacyCreativeIdentity(projectCanonicalCreativeResponseValue(result, taskType, legacyFormatConverter)) : result;
|
|
1508
|
+
const association = this.canonicalCreativeTaskAssociation(metadata.operation_id) ?? this.canonicalCreativeTaskAssociation(metadata.task_id) ?? this.canonicalCreativeTaskAssociation(metadata.context_id);
|
|
1509
|
+
if (metadata.status === "completed") {
|
|
1510
|
+
this.rememberCanonicalPackageRoutesForTask(taskType, canonical, association?.routingSnapshot);
|
|
752
1511
|
}
|
|
753
|
-
|
|
754
|
-
return false;
|
|
1512
|
+
return canonical;
|
|
755
1513
|
}
|
|
756
1514
|
/**
|
|
757
1515
|
* Normalize webhook payload - handles both MCP and A2A webhook formats
|
|
@@ -790,7 +1548,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
790
1548
|
if (typeof payload.status !== "string" || !WEBHOOK_TASK_STATUSES.has(payload.status)) {
|
|
791
1549
|
throw new WebhookDispatchError(
|
|
792
1550
|
"webhook_envelope_invalid",
|
|
793
|
-
`Invalid MCP webhook envelope: unsupported top-level status
|
|
1551
|
+
`Invalid MCP webhook envelope: unsupported top-level status. Expected one of ${Array.from(WEBHOOK_TASK_STATUSES).join(", ")}.`
|
|
794
1552
|
);
|
|
795
1553
|
}
|
|
796
1554
|
if (typeof payload.timestamp !== "string" || Number.isNaN(Date.parse(payload.timestamp))) {
|
|
@@ -830,7 +1588,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
830
1588
|
} catch (error) {
|
|
831
1589
|
throw new WebhookDispatchError(
|
|
832
1590
|
"webhook_result_invalid",
|
|
833
|
-
|
|
1591
|
+
"Failed to unwrap A2A webhook payload artifacts.",
|
|
834
1592
|
error
|
|
835
1593
|
);
|
|
836
1594
|
}
|
|
@@ -862,7 +1620,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
862
1620
|
}
|
|
863
1621
|
throw new WebhookDispatchError(
|
|
864
1622
|
"webhook_unsupported_payload",
|
|
865
|
-
|
|
1623
|
+
"Unsupported webhook payload format. Expected an MCP webhook envelope with top-level idempotency_key, operation_id, task_id, task_type, status, timestamp, and result, or an A2A Task/TaskStatusUpdateEvent with AdCP data nested in status.message.parts[].data or task artifacts."
|
|
866
1624
|
);
|
|
867
1625
|
}
|
|
868
1626
|
/**
|
|
@@ -1003,7 +1761,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1003
1761
|
*
|
|
1004
1762
|
* Automatically adapts requests for v2 servers and normalizes responses.
|
|
1005
1763
|
*/
|
|
1006
|
-
async executeAndHandle(taskType, handlerName, params, inputHandler, options) {
|
|
1764
|
+
async executeAndHandle(taskType, handlerName, params, inputHandler, options, transformCompletedResponse, legacyFormatConverter, canonicalRequest) {
|
|
1007
1765
|
throwIfAborted(options?.signal);
|
|
1008
1766
|
let normalizedParams = normalizeRequestParams(taskType, params, {
|
|
1009
1767
|
skipIdempotencyAutoInject: options?.skipIdempotencyAutoInject,
|
|
@@ -1051,13 +1809,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1051
1809
|
if (serverVersion === "v2") {
|
|
1052
1810
|
this.executor.validateAdaptedRequestAgainstV2(taskType, adaptedParams, v25DriftLogs);
|
|
1053
1811
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
taskType,
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1812
|
+
const canonicalInputHandler = this.canonicalCreativeInputHandler(taskType, inputHandler);
|
|
1813
|
+
let result = await canonicalCreativeExecutionStorage.run(
|
|
1814
|
+
{ taskType, legacyFormatConverter, canonicalRequest: canonicalRequest ?? normalizedParams },
|
|
1815
|
+
() => this.executor.executeTask(
|
|
1816
|
+
agent,
|
|
1817
|
+
taskType,
|
|
1818
|
+
adaptedParams,
|
|
1819
|
+
canonicalInputHandler,
|
|
1820
|
+
effectiveOptions,
|
|
1821
|
+
serverVersion
|
|
1822
|
+
)
|
|
1061
1823
|
);
|
|
1062
1824
|
const postAdapterLogs = [...inputSchemaStripLogs, ...v25DriftLogs];
|
|
1063
1825
|
if (postAdapterLogs.length > 0) {
|
|
@@ -1066,9 +1828,26 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1066
1828
|
if (result.success && result.data) {
|
|
1067
1829
|
result.data = this.normalizeResponseToV3(taskType, result.data);
|
|
1068
1830
|
}
|
|
1069
|
-
result = this.wrapProductPolicySubmittedContinuation(result, taskType, normalizedParams);
|
|
1070
|
-
|
|
1831
|
+
result = this.wrapProductPolicySubmittedContinuation(result, taskType, normalizedParams, options);
|
|
1832
|
+
if (result.status === "working") {
|
|
1833
|
+
this.rememberProductPolicyRequestParams(taskType, normalizedParams, result, options);
|
|
1834
|
+
}
|
|
1835
|
+
this.rememberLegacyFormatConverter(taskType, legacyFormatConverter, result, options);
|
|
1071
1836
|
result = await this.applyProductPropertyPolicy(result, taskType, normalizedParams);
|
|
1837
|
+
if (CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType)) {
|
|
1838
|
+
const routingSnapshot = canonicalCreativeRoutingSnapshot(taskType, canonicalRequest ?? normalizedParams);
|
|
1839
|
+
result = this.canonicalizeCreativeTaskResult(result, taskType, transformCompletedResponse, legacyFormatConverter);
|
|
1840
|
+
result = this.wrapCanonicalCreativeContinuations(
|
|
1841
|
+
result,
|
|
1842
|
+
taskType,
|
|
1843
|
+
transformCompletedResponse,
|
|
1844
|
+
legacyFormatConverter,
|
|
1845
|
+
routingSnapshot
|
|
1846
|
+
);
|
|
1847
|
+
this.rememberCanonicalCreativeTaskIds(result, taskType, legacyFormatConverter, routingSnapshot);
|
|
1848
|
+
} else if (result.status === "completed" && result.success && result.data && transformCompletedResponse) {
|
|
1849
|
+
result = { ...result, data: transformCompletedResponse(result.data) };
|
|
1850
|
+
}
|
|
1072
1851
|
if (result.status === "completed" && result.success && this.asyncHandler) {
|
|
1073
1852
|
const handler = this.config.handlers?.[handlerName];
|
|
1074
1853
|
if (handler) {
|
|
@@ -1078,6 +1857,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1078
1857
|
task_id: result.metadata.taskId,
|
|
1079
1858
|
agent_id: this.agent.id,
|
|
1080
1859
|
task_type: taskType,
|
|
1860
|
+
status: result.status,
|
|
1081
1861
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1082
1862
|
};
|
|
1083
1863
|
await handler(result.data, metadata);
|
|
@@ -1085,6 +1865,255 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1085
1865
|
}
|
|
1086
1866
|
return result;
|
|
1087
1867
|
}
|
|
1868
|
+
canonicalCreativeInputHandler(taskType, inputHandler) {
|
|
1869
|
+
if (!inputHandler || !CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType)) return inputHandler;
|
|
1870
|
+
return async (context) => {
|
|
1871
|
+
const active = canonicalCreativeExecutionStorage.getStore();
|
|
1872
|
+
const converter = this.resolveLegacyFormatConverter(
|
|
1873
|
+
active?.taskType === taskType ? active.legacyFormatConverter : void 0
|
|
1874
|
+
);
|
|
1875
|
+
const project = (value) => projectCanonicalCreativeAncillaryValue(value, taskType, converter);
|
|
1876
|
+
const messages = context.messages.map((message) => ({
|
|
1877
|
+
...message,
|
|
1878
|
+
content: project(message.content)
|
|
1879
|
+
}));
|
|
1880
|
+
const safeContext = {
|
|
1881
|
+
...context,
|
|
1882
|
+
messages,
|
|
1883
|
+
inputRequest: project(context.inputRequest),
|
|
1884
|
+
getSummary: () => messages.map((message) => `${message.role}: ${JSON.stringify(message.content)}`).join("\n"),
|
|
1885
|
+
getPreviousResponse: (field) => project(context.getPreviousResponse(field))
|
|
1886
|
+
};
|
|
1887
|
+
return inputHandler(safeContext);
|
|
1888
|
+
};
|
|
1889
|
+
}
|
|
1890
|
+
projectCanonicalCreativeData(taskType, data, transform, legacyFormatConverter) {
|
|
1891
|
+
let projected = this.normalizeResponseToV3(taskType, data);
|
|
1892
|
+
const record = projected && typeof projected === "object" ? projected : void 0;
|
|
1893
|
+
const canProjectRead = taskType === "get_products" ? Array.isArray(record?.products) : taskType === "list_creatives" ? Array.isArray(record?.creatives) : true;
|
|
1894
|
+
if (transform && canProjectRead) {
|
|
1895
|
+
projected = transform(projected);
|
|
1896
|
+
} else if (canProjectRead && taskType === "get_products" && record) {
|
|
1897
|
+
const active = canonicalCreativeExecutionStorage.getStore();
|
|
1898
|
+
const { response, diagnostics } = toCanonicalOnlyResponse(record, {
|
|
1899
|
+
legacyFormatConverter: this.resolveLegacyFormatConverter(
|
|
1900
|
+
legacyFormatConverter ?? (active?.taskType === taskType ? active.legacyFormatConverter : void 0)
|
|
1901
|
+
),
|
|
1902
|
+
projectionCatalogs: this.config.projectionCatalogs
|
|
1903
|
+
});
|
|
1904
|
+
const { _message: _dropLegacyMessage, ...canonical } = response;
|
|
1905
|
+
void _dropLegacyMessage;
|
|
1906
|
+
projected = { ...canonical, projection: { diagnostics } };
|
|
1907
|
+
} else if (canProjectRead && taskType === "list_creatives" && record) {
|
|
1908
|
+
const active = canonicalCreativeExecutionStorage.getStore();
|
|
1909
|
+
const activeLegacyFormatConverter = this.resolveLegacyFormatConverter(
|
|
1910
|
+
legacyFormatConverter ?? (active?.taskType === taskType ? active.legacyFormatConverter : void 0)
|
|
1911
|
+
);
|
|
1912
|
+
const { _message: _dropLegacyMessage, ...safe } = record;
|
|
1913
|
+
void _dropLegacyMessage;
|
|
1914
|
+
projected = {
|
|
1915
|
+
...safe,
|
|
1916
|
+
creatives: record.creatives.map(
|
|
1917
|
+
(creative) => projectCreativeForDelivery(
|
|
1918
|
+
creative,
|
|
1919
|
+
{},
|
|
1920
|
+
"canonical",
|
|
1921
|
+
"list_creatives",
|
|
1922
|
+
activeLegacyFormatConverter
|
|
1923
|
+
)
|
|
1924
|
+
)
|
|
1925
|
+
};
|
|
1926
|
+
} else if (canProjectRead && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType)) {
|
|
1927
|
+
const active = canonicalCreativeExecutionStorage.getStore();
|
|
1928
|
+
projected = projectCanonicalCreativeResponseValue(
|
|
1929
|
+
projected,
|
|
1930
|
+
taskType,
|
|
1931
|
+
this.resolveLegacyFormatConverter(
|
|
1932
|
+
legacyFormatConverter ?? (active?.taskType === taskType ? active.legacyFormatConverter : void 0)
|
|
1933
|
+
)
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
return stripLegacyCreativeIdentity(projected);
|
|
1937
|
+
}
|
|
1938
|
+
canonicalizeCreativeTaskResult(result, taskType, transform, legacyFormatConverter) {
|
|
1939
|
+
const projectedData = result.data !== void 0 ? this.projectCanonicalCreativeData(taskType, result.data, transform, legacyFormatConverter) : void 0;
|
|
1940
|
+
const errorInstance = result.errorInstance;
|
|
1941
|
+
const converter = this.resolveLegacyFormatConverter(legacyFormatConverter);
|
|
1942
|
+
const metadataRecord = result.metadata;
|
|
1943
|
+
const semanticMetadata = {
|
|
1944
|
+
...metadataRecord,
|
|
1945
|
+
...metadataRecord.inputRequest !== void 0 && {
|
|
1946
|
+
inputRequest: projectCanonicalCreativeAncillaryValue(metadataRecord.inputRequest, taskType, converter)
|
|
1947
|
+
}
|
|
1948
|
+
};
|
|
1949
|
+
const semanticConversation = result.conversation?.map((message) => ({
|
|
1950
|
+
...message,
|
|
1951
|
+
content: projectCanonicalCreativeAncillaryValue(message.content, taskType, converter)
|
|
1952
|
+
}));
|
|
1953
|
+
const safe = stripLegacyCreativeIdentity({
|
|
1954
|
+
data: projectedData,
|
|
1955
|
+
metadata: semanticMetadata,
|
|
1956
|
+
conversation: semanticConversation,
|
|
1957
|
+
debug_logs: result.debug_logs,
|
|
1958
|
+
adcpError: result.adcpError,
|
|
1959
|
+
error: result.error,
|
|
1960
|
+
governance: result.governance,
|
|
1961
|
+
governanceOutcome: result.governanceOutcome,
|
|
1962
|
+
governanceOutcomeError: result.governanceOutcomeError,
|
|
1963
|
+
deferredQuestion: result.deferred?.question,
|
|
1964
|
+
// Token source only: discarded below, but lets the sanitizer remove exact
|
|
1965
|
+
// legacy IDs/URLs when the seller repeats them in messages or diagnostics.
|
|
1966
|
+
legacySource: result.data
|
|
1967
|
+
});
|
|
1968
|
+
const safeErrorInstance = errorInstance ? canonicalCreativeErrorInstance(errorInstance, result.data) : void 0;
|
|
1969
|
+
const safeDeferred = result.deferred ? { ...result.deferred, ...result.deferred.question !== void 0 && { question: safe.deferredQuestion } } : void 0;
|
|
1970
|
+
return attachMatch({
|
|
1971
|
+
...result,
|
|
1972
|
+
...result.data !== void 0 && { data: safe.data },
|
|
1973
|
+
metadata: safe.metadata,
|
|
1974
|
+
...result.conversation !== void 0 && { conversation: safe.conversation },
|
|
1975
|
+
...result.debug_logs !== void 0 && { debug_logs: safe.debug_logs },
|
|
1976
|
+
...result.adcpError !== void 0 && { adcpError: safe.adcpError },
|
|
1977
|
+
...result.error !== void 0 && { error: safe.error },
|
|
1978
|
+
...result.governance !== void 0 && { governance: safe.governance },
|
|
1979
|
+
...result.governanceOutcome !== void 0 && { governanceOutcome: safe.governanceOutcome },
|
|
1980
|
+
...result.governanceOutcomeError !== void 0 && { governanceOutcomeError: safe.governanceOutcomeError },
|
|
1981
|
+
...safeDeferred !== void 0 && { deferred: safeDeferred },
|
|
1982
|
+
...safeErrorInstance !== void 0 && { errorInstance: safeErrorInstance }
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
canonicalizeCreativeTaskInfo(taskInfo, taskType, transform, legacyFormatConverter) {
|
|
1986
|
+
const source = taskInfo.result;
|
|
1987
|
+
const projected = source !== void 0 ? this.projectCanonicalCreativeData(taskType, source, transform, legacyFormatConverter) : void 0;
|
|
1988
|
+
const { legacySource: _dropLegacySource, ...safe } = stripLegacyCreativeIdentity({
|
|
1989
|
+
...taskInfo,
|
|
1990
|
+
taskType,
|
|
1991
|
+
...source !== void 0 && { result: projected },
|
|
1992
|
+
legacySource: source
|
|
1993
|
+
});
|
|
1994
|
+
void _dropLegacySource;
|
|
1995
|
+
return safe;
|
|
1996
|
+
}
|
|
1997
|
+
wrapCanonicalCreativeContinuations(result, taskType, transform, legacyFormatConverter, routingRequest) {
|
|
1998
|
+
const routingSnapshot = canonicalCreativeRoutingSnapshot(taskType, routingRequest);
|
|
1999
|
+
if (result.submitted) {
|
|
2000
|
+
const submitted = result.submitted;
|
|
2001
|
+
result = {
|
|
2002
|
+
...result,
|
|
2003
|
+
submitted: {
|
|
2004
|
+
...submitted,
|
|
2005
|
+
track: async (transport) => {
|
|
2006
|
+
const canonical = this.canonicalizeCreativeTaskInfo(
|
|
2007
|
+
await canonicalCreativeExecutionStorage.run(
|
|
2008
|
+
{ taskType, legacyFormatConverter },
|
|
2009
|
+
() => submitted.track(transport)
|
|
2010
|
+
),
|
|
2011
|
+
taskType,
|
|
2012
|
+
transform,
|
|
2013
|
+
legacyFormatConverter
|
|
2014
|
+
);
|
|
2015
|
+
if (canonical.status === "completed" && canonical.result !== void 0) {
|
|
2016
|
+
this.rememberCanonicalPackageRoutesForTask(taskType, canonical.result, routingSnapshot);
|
|
2017
|
+
}
|
|
2018
|
+
return canonical;
|
|
2019
|
+
},
|
|
2020
|
+
waitForCompletion: async (pollInterval, signal) => {
|
|
2021
|
+
const completed = await canonicalCreativeExecutionStorage.run(
|
|
2022
|
+
{ taskType, legacyFormatConverter },
|
|
2023
|
+
() => submitted.waitForCompletion(pollInterval, signal)
|
|
2024
|
+
);
|
|
2025
|
+
const canonical = this.canonicalizeCreativeTaskResult(
|
|
2026
|
+
completed,
|
|
2027
|
+
taskType,
|
|
2028
|
+
transform,
|
|
2029
|
+
legacyFormatConverter
|
|
2030
|
+
);
|
|
2031
|
+
if (canonical.success && canonical.status === "completed" && canonical.data !== void 0) {
|
|
2032
|
+
this.rememberCanonicalPackageRoutesForTask(taskType, canonical.data, routingSnapshot);
|
|
2033
|
+
}
|
|
2034
|
+
this.rememberCanonicalCreativeTaskIds(canonical, taskType, legacyFormatConverter, routingSnapshot);
|
|
2035
|
+
return this.wrapCanonicalCreativeContinuations(
|
|
2036
|
+
canonical,
|
|
2037
|
+
taskType,
|
|
2038
|
+
transform,
|
|
2039
|
+
legacyFormatConverter,
|
|
2040
|
+
routingSnapshot
|
|
2041
|
+
);
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
if (result.deferred) {
|
|
2047
|
+
const deferred = result.deferred;
|
|
2048
|
+
result = {
|
|
2049
|
+
...result,
|
|
2050
|
+
deferred: {
|
|
2051
|
+
...deferred,
|
|
2052
|
+
resume: async (input) => {
|
|
2053
|
+
const resumed = await canonicalCreativeExecutionStorage.run(
|
|
2054
|
+
{ taskType, legacyFormatConverter },
|
|
2055
|
+
() => deferred.resume(input)
|
|
2056
|
+
);
|
|
2057
|
+
const canonical = this.canonicalizeCreativeTaskResult(resumed, taskType, transform, legacyFormatConverter);
|
|
2058
|
+
if (canonical.success && canonical.status === "completed" && canonical.data !== void 0) {
|
|
2059
|
+
this.rememberCanonicalPackageRoutesForTask(taskType, canonical.data, routingSnapshot);
|
|
2060
|
+
}
|
|
2061
|
+
this.rememberCanonicalCreativeTaskIds(canonical, taskType, legacyFormatConverter, routingSnapshot);
|
|
2062
|
+
return this.wrapCanonicalCreativeContinuations(
|
|
2063
|
+
canonical,
|
|
2064
|
+
taskType,
|
|
2065
|
+
transform,
|
|
2066
|
+
legacyFormatConverter,
|
|
2067
|
+
routingSnapshot
|
|
2068
|
+
);
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
return attachMatch(result);
|
|
2074
|
+
}
|
|
2075
|
+
rememberCanonicalCreativeTaskIds(result, taskType, legacyFormatConverter, routingRequest) {
|
|
2076
|
+
const routingSnapshot = canonicalCreativeRoutingSnapshot(taskType, routingRequest);
|
|
2077
|
+
const keys = [
|
|
2078
|
+
result.metadata.taskId,
|
|
2079
|
+
result.metadata.contextId,
|
|
2080
|
+
result.metadata.serverTaskId,
|
|
2081
|
+
result.submitted?.taskId
|
|
2082
|
+
];
|
|
2083
|
+
for (const key of keys) {
|
|
2084
|
+
if (!key) continue;
|
|
2085
|
+
this.rememberCanonicalCreativeTaskAssociation(key, taskType, legacyFormatConverter, routingSnapshot);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
rememberCanonicalCreativeTaskAssociation(key, taskType, legacyFormatConverter, canonicalRequest) {
|
|
2089
|
+
const previous = this.canonicalCreativeTaskAssociations.get(key);
|
|
2090
|
+
const routingSnapshot = canonicalCreativeRoutingSnapshot(taskType, canonicalRequest);
|
|
2091
|
+
const effectiveRoutingSnapshot = routingSnapshot ?? (previous?.taskType === taskType ? previous.routingSnapshot : void 0);
|
|
2092
|
+
this.canonicalCreativeTaskAssociations.delete(key);
|
|
2093
|
+
this.canonicalCreativeTaskAssociations.set(key, {
|
|
2094
|
+
taskType,
|
|
2095
|
+
legacyFormatConverter,
|
|
2096
|
+
...effectiveRoutingSnapshot ? { routingSnapshot: effectiveRoutingSnapshot } : {}
|
|
2097
|
+
});
|
|
2098
|
+
while (this.canonicalCreativeTaskAssociations.size > TASK_SCOPED_STATE_LIMIT) {
|
|
2099
|
+
const oldest = this.canonicalCreativeTaskAssociations.keys().next().value;
|
|
2100
|
+
if (oldest === void 0) break;
|
|
2101
|
+
this.canonicalCreativeTaskAssociations.delete(oldest);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
canonicalCreativeTaskAssociation(key) {
|
|
2105
|
+
if (!key) return void 0;
|
|
2106
|
+
const association = this.canonicalCreativeTaskAssociations.get(key);
|
|
2107
|
+
if (!association) return void 0;
|
|
2108
|
+
this.canonicalCreativeTaskAssociations.delete(key);
|
|
2109
|
+
this.canonicalCreativeTaskAssociations.set(key, association);
|
|
2110
|
+
return association;
|
|
2111
|
+
}
|
|
2112
|
+
forgetCanonicalCreativeTaskAssociationKeys(keys) {
|
|
2113
|
+
for (const key of keys) {
|
|
2114
|
+
if (key) this.canonicalCreativeTaskAssociations.delete(key);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
1088
2117
|
/**
|
|
1089
2118
|
* Drop products that arrive without a usable `pricing_options[]` array from a
|
|
1090
2119
|
* completed `get_products` response. `pricing_options` is required and
|
|
@@ -1295,20 +2324,62 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1295
2324
|
return result;
|
|
1296
2325
|
}
|
|
1297
2326
|
rememberProductPolicyRequestParams(taskType, requestParams, result, options) {
|
|
2327
|
+
this.rememberProductPolicyRequestState(
|
|
2328
|
+
taskType,
|
|
2329
|
+
{ request: productPolicyRequestSnapshot(requestParams) },
|
|
2330
|
+
result,
|
|
2331
|
+
options
|
|
2332
|
+
);
|
|
2333
|
+
}
|
|
2334
|
+
rememberProductPolicyRequestState(taskType, requestState, result, options) {
|
|
1298
2335
|
if (taskType !== "get_products") return;
|
|
1299
2336
|
if (result.status !== "submitted" && result.status !== "working") return;
|
|
1300
2337
|
const keys = /* @__PURE__ */ new Set();
|
|
1301
2338
|
if (result.metadata.taskId) keys.add(result.metadata.taskId);
|
|
1302
2339
|
if (result.metadata.contextId) keys.add(result.metadata.contextId);
|
|
1303
2340
|
if (result.metadata.serverTaskId) keys.add(result.metadata.serverTaskId);
|
|
2341
|
+
if (result.submitted?.taskId) keys.add(result.submitted.taskId);
|
|
1304
2342
|
if (options?.taskId) keys.add(options.taskId);
|
|
1305
2343
|
if (options?.contextId) keys.add(options.contextId);
|
|
1306
2344
|
for (const key of keys) {
|
|
1307
|
-
this.productPolicyRequestParamsByTask.
|
|
2345
|
+
this.productPolicyRequestParamsByTask.delete(key);
|
|
2346
|
+
this.productPolicyRequestParamsByTask.set(key, requestState);
|
|
2347
|
+
while (this.productPolicyRequestParamsByTask.size > TASK_SCOPED_STATE_LIMIT) {
|
|
2348
|
+
const oldest = this.productPolicyRequestParamsByTask.keys().next().value;
|
|
2349
|
+
if (oldest === void 0) break;
|
|
2350
|
+
this.productPolicyRequestParamsByTask.delete(oldest);
|
|
2351
|
+
}
|
|
1308
2352
|
}
|
|
1309
2353
|
}
|
|
2354
|
+
rememberLegacyFormatConverter(taskType, converter, result, options) {
|
|
2355
|
+
if (!converter || taskType !== "get_products" && taskType !== "list_creatives") return;
|
|
2356
|
+
const metadata = result.metadata;
|
|
2357
|
+
const keys = [
|
|
2358
|
+
metadata.operationId,
|
|
2359
|
+
metadata.taskId,
|
|
2360
|
+
metadata.contextId,
|
|
2361
|
+
metadata.serverTaskId,
|
|
2362
|
+
options?.taskId,
|
|
2363
|
+
options?.contextId
|
|
2364
|
+
];
|
|
2365
|
+
for (const key of keys) {
|
|
2366
|
+
if (key) this.rememberCanonicalCreativeTaskAssociation(key, taskType, converter);
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
legacyFormatConverterForWebhook(metadata) {
|
|
2370
|
+
return this.canonicalCreativeTaskAssociation(metadata.operation_id)?.legacyFormatConverter ?? this.canonicalCreativeTaskAssociation(metadata.task_id)?.legacyFormatConverter ?? this.canonicalCreativeTaskAssociation(metadata.context_id)?.legacyFormatConverter ?? this.resolveLegacyFormatConverter();
|
|
2371
|
+
}
|
|
1310
2372
|
forgetProductPolicyRequestParams(metadata) {
|
|
1311
|
-
|
|
2373
|
+
const aliases = [metadata.operation_id, metadata.task_id, metadata.context_id];
|
|
2374
|
+
const states = new Set(
|
|
2375
|
+
aliases.filter((key) => key !== void 0).map((key) => this.productPolicyRequestParamsByTask.get(key)).filter((value) => value !== void 0)
|
|
2376
|
+
);
|
|
2377
|
+
for (const state of states) state.request = void 0;
|
|
2378
|
+
this.forgetProductPolicyRequestParamKeys(aliases);
|
|
2379
|
+
if (states.size === 0) return;
|
|
2380
|
+
for (const [key, state] of this.productPolicyRequestParamsByTask) {
|
|
2381
|
+
if (states.has(state)) this.productPolicyRequestParamsByTask.delete(key);
|
|
2382
|
+
}
|
|
1312
2383
|
}
|
|
1313
2384
|
forgetProductPolicyRequestParamKeys(keys) {
|
|
1314
2385
|
for (const key of keys) {
|
|
@@ -1316,38 +2387,61 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1316
2387
|
this.productPolicyRequestParamsByTask.delete(key);
|
|
1317
2388
|
}
|
|
1318
2389
|
}
|
|
1319
|
-
wrapProductPolicySubmittedContinuation(result, taskType, requestParams) {
|
|
2390
|
+
wrapProductPolicySubmittedContinuation(result, taskType, requestParams, options) {
|
|
1320
2391
|
if (taskType !== "get_products" || result.status !== "submitted" || !result.submitted) return result;
|
|
1321
2392
|
const submitted = result.submitted;
|
|
2393
|
+
const policyState = {
|
|
2394
|
+
request: productPolicyRequestSnapshot(requestParams)
|
|
2395
|
+
};
|
|
2396
|
+
this.rememberProductPolicyRequestState(taskType, policyState, result, options);
|
|
2397
|
+
const retainedKeys = [
|
|
2398
|
+
result.metadata.taskId,
|
|
2399
|
+
result.metadata.contextId,
|
|
2400
|
+
result.metadata.serverTaskId,
|
|
2401
|
+
submitted.taskId,
|
|
2402
|
+
options?.taskId,
|
|
2403
|
+
options?.contextId
|
|
2404
|
+
];
|
|
1322
2405
|
result.submitted = {
|
|
1323
2406
|
...submitted,
|
|
1324
2407
|
track: async (transport) => {
|
|
1325
2408
|
const taskInfo = await submitted.track(transport);
|
|
1326
|
-
const
|
|
1327
|
-
|
|
1328
|
-
this.
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
2409
|
+
const terminal = ["completed", "failed", "rejected", "canceled"].includes(taskInfo.status);
|
|
2410
|
+
try {
|
|
2411
|
+
return await this.applyProductPropertyPolicyToTaskInfo(
|
|
2412
|
+
taskInfo,
|
|
2413
|
+
taskType,
|
|
2414
|
+
policyState.request ?? {}
|
|
2415
|
+
);
|
|
2416
|
+
} finally {
|
|
2417
|
+
if (terminal) {
|
|
2418
|
+
policyState.request = void 0;
|
|
2419
|
+
this.forgetProductPolicyRequestParamKeys([...retainedKeys, taskInfo.taskId]);
|
|
2420
|
+
}
|
|
1333
2421
|
}
|
|
1334
|
-
return processed;
|
|
1335
2422
|
},
|
|
1336
2423
|
waitForCompletion: async (pollInterval, signal) => {
|
|
1337
2424
|
let completed = await submitted.waitForCompletion(pollInterval, signal);
|
|
1338
2425
|
if (completed.success && completed.data) {
|
|
1339
2426
|
completed.data = this.normalizeResponseToV3(taskType, completed.data);
|
|
1340
2427
|
}
|
|
1341
|
-
const
|
|
1342
|
-
|
|
1343
|
-
this.
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
2428
|
+
const terminal = completed.status === "completed" || completed.status === "failed";
|
|
2429
|
+
try {
|
|
2430
|
+
return await this.applyProductPropertyPolicy(
|
|
2431
|
+
completed,
|
|
2432
|
+
taskType,
|
|
2433
|
+
policyState.request ?? {}
|
|
2434
|
+
);
|
|
2435
|
+
} finally {
|
|
2436
|
+
if (terminal) {
|
|
2437
|
+
policyState.request = void 0;
|
|
2438
|
+
this.forgetProductPolicyRequestParamKeys([
|
|
2439
|
+
...retainedKeys,
|
|
2440
|
+
completed.metadata.taskId,
|
|
2441
|
+
completed.metadata.serverTaskId
|
|
2442
|
+
]);
|
|
2443
|
+
}
|
|
1349
2444
|
}
|
|
1350
|
-
return processed;
|
|
1351
2445
|
}
|
|
1352
2446
|
};
|
|
1353
2447
|
return result;
|
|
@@ -1385,7 +2479,15 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1385
2479
|
};
|
|
1386
2480
|
}
|
|
1387
2481
|
productPolicyRequestParamsForWebhook(metadata) {
|
|
1388
|
-
return this.executor.getRequestParams(metadata.operation_id) ?? this.executor.getRequestParams(metadata.task_id) ?? this.
|
|
2482
|
+
return this.executor.getRequestParams(metadata.operation_id) ?? this.executor.getRequestParams(metadata.task_id) ?? this.productPolicyRequestParamsForKey(metadata.operation_id) ?? this.productPolicyRequestParamsForKey(metadata.task_id) ?? this.productPolicyRequestParamsForKey(metadata.context_id) ?? {};
|
|
2483
|
+
}
|
|
2484
|
+
productPolicyRequestParamsForKey(key) {
|
|
2485
|
+
if (!key) return void 0;
|
|
2486
|
+
const state = this.productPolicyRequestParamsByTask.get(key);
|
|
2487
|
+
if (!state?.request) return void 0;
|
|
2488
|
+
this.productPolicyRequestParamsByTask.delete(key);
|
|
2489
|
+
this.productPolicyRequestParamsByTask.set(key, state);
|
|
2490
|
+
return state.request;
|
|
1389
2491
|
}
|
|
1390
2492
|
async applyProductPropertyPolicyToWebhookResult(result, metadata) {
|
|
1391
2493
|
if (metadata.task_type !== "get_products" || metadata.status !== "completed" || !result) {
|
|
@@ -1580,30 +2682,57 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1580
2682
|
* ```
|
|
1581
2683
|
*/
|
|
1582
2684
|
async getProducts(params, inputHandler, options) {
|
|
2685
|
+
const { legacyFormatConverter, projectionCatalogs, ...taskOptions } = options ?? {};
|
|
2686
|
+
const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
|
|
2687
|
+
legacyFormatConverter,
|
|
2688
|
+
projectionCatalogs ?? this.config.projectionCatalogs
|
|
2689
|
+
);
|
|
2690
|
+
const account = canonicalAccountRoutingSnapshot(params.account);
|
|
1583
2691
|
return this.executeAndHandle(
|
|
1584
2692
|
"get_products",
|
|
1585
2693
|
"onGetProductsStatusChange",
|
|
1586
2694
|
params,
|
|
1587
2695
|
inputHandler,
|
|
1588
|
-
|
|
2696
|
+
taskOptions,
|
|
2697
|
+
(data) => {
|
|
2698
|
+
const { response, diagnostics } = toCanonicalOnlyResponse(data, {
|
|
2699
|
+
legacyFormatConverter: effectiveLegacyFormatConverter,
|
|
2700
|
+
projectionCatalogs: projectionCatalogs ?? this.config.projectionCatalogs
|
|
2701
|
+
});
|
|
2702
|
+
const authoritativeProducts = Array.isArray(data.products) ? data.products : response.products;
|
|
2703
|
+
this.rememberCanonicalProductRoutes(response.products, account, authoritativeProducts);
|
|
2704
|
+
const { _message: _dropLegacyMessage, ...canonical } = response;
|
|
2705
|
+
void _dropLegacyMessage;
|
|
2706
|
+
return { ...canonical, projection: { diagnostics } };
|
|
2707
|
+
},
|
|
2708
|
+
effectiveLegacyFormatConverter
|
|
1589
2709
|
);
|
|
1590
2710
|
}
|
|
2711
|
+
/** @deprecated Explicit raw-wire escape hatch for migration tooling. */
|
|
2712
|
+
async getProductsLegacy(params, inputHandler, options) {
|
|
2713
|
+
return this.executeTaskUnprojected("get_products", params, inputHandler, options);
|
|
2714
|
+
}
|
|
1591
2715
|
/**
|
|
1592
|
-
* List
|
|
2716
|
+
* List a legacy named-format catalog for migration tooling.
|
|
1593
2717
|
*
|
|
1594
2718
|
* @param params - Format listing parameters
|
|
1595
2719
|
* @param inputHandler - Handler for clarification requests
|
|
1596
2720
|
* @param options - Task execution options
|
|
2721
|
+
* @deprecated Canonical applications discover `format_options[]` through `getProducts()`.
|
|
1597
2722
|
*/
|
|
1598
|
-
async
|
|
2723
|
+
async listCreativeFormatsLegacy(params, inputHandler, options) {
|
|
1599
2724
|
return this.executeAndHandle(
|
|
1600
2725
|
"list_creative_formats",
|
|
1601
|
-
"
|
|
2726
|
+
"onListCreativeFormatsLegacyStatusChange",
|
|
1602
2727
|
params,
|
|
1603
2728
|
inputHandler,
|
|
1604
2729
|
options
|
|
1605
2730
|
);
|
|
1606
2731
|
}
|
|
2732
|
+
/** @deprecated Migration-only access to legacy creative transformer declarations. */
|
|
2733
|
+
async listTransformersLegacy(params, inputHandler, options) {
|
|
2734
|
+
return this.executeTaskUnprojected("list_transformers", params, inputHandler, options);
|
|
2735
|
+
}
|
|
1607
2736
|
/**
|
|
1608
2737
|
* Create a new media buy
|
|
1609
2738
|
*
|
|
@@ -1612,6 +2741,23 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1612
2741
|
* @param options - Task execution options
|
|
1613
2742
|
*/
|
|
1614
2743
|
async createMediaBuy(params, inputHandler, options) {
|
|
2744
|
+
const { legacyFormatConverter, projectionCatalogs, canonicalFormatLegacyResolver, ...taskOptions } = options ?? {};
|
|
2745
|
+
const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
|
|
2746
|
+
legacyFormatConverter,
|
|
2747
|
+
projectionCatalogs ?? this.config.projectionCatalogs
|
|
2748
|
+
);
|
|
2749
|
+
const effectiveCanonicalFormatLegacyResolver = this.resolveCanonicalFormatLegacyResolver(
|
|
2750
|
+
canonicalFormatLegacyResolver,
|
|
2751
|
+
params.account
|
|
2752
|
+
);
|
|
2753
|
+
const hasCreativeFormatData = hasMediaBuyCreativeFormatData(params);
|
|
2754
|
+
if (hasCreativeFormatData) {
|
|
2755
|
+
this.validateBeforeCreativeCapabilityProbe("create_media_buy", params, taskOptions);
|
|
2756
|
+
}
|
|
2757
|
+
const wireMode = hasCreativeFormatData ? this.resolveCreativeFormatWireMode(
|
|
2758
|
+
"create_media_buy",
|
|
2759
|
+
await this.getCapabilities({ signal: taskOptions.signal, transport: taskOptions.transport })
|
|
2760
|
+
) : "canonical";
|
|
1615
2761
|
if (this.config.webhookUrlTemplate && !options?.disableWebhook) {
|
|
1616
2762
|
const now = /* @__PURE__ */ new Date();
|
|
1617
2763
|
const year = now.getUTCFullYear();
|
|
@@ -1646,9 +2792,28 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1646
2792
|
};
|
|
1647
2793
|
}
|
|
1648
2794
|
}
|
|
1649
|
-
|
|
2795
|
+
const result = await this.executeAndHandle(
|
|
1650
2796
|
"create_media_buy",
|
|
1651
2797
|
"onCreateMediaBuyStatusChange",
|
|
2798
|
+
projectMediaBuyCreativesForDelivery(
|
|
2799
|
+
params,
|
|
2800
|
+
wireMode,
|
|
2801
|
+
"create_media_buy",
|
|
2802
|
+
effectiveLegacyFormatConverter,
|
|
2803
|
+
effectiveCanonicalFormatLegacyResolver
|
|
2804
|
+
),
|
|
2805
|
+
inputHandler,
|
|
2806
|
+
taskOptions,
|
|
2807
|
+
void 0,
|
|
2808
|
+
effectiveLegacyFormatConverter,
|
|
2809
|
+
params
|
|
2810
|
+
);
|
|
2811
|
+
if (result.data !== void 0) this.rememberCanonicalPackageRoutes(result.data, params);
|
|
2812
|
+
return result;
|
|
2813
|
+
}
|
|
2814
|
+
/** @deprecated Compatibility-only entry point for callers still holding legacy creative `format_id` values. */
|
|
2815
|
+
async createMediaBuyLegacy(params, inputHandler, options) {
|
|
2816
|
+
return await this.createMediaBuy(
|
|
1652
2817
|
params,
|
|
1653
2818
|
inputHandler,
|
|
1654
2819
|
options
|
|
@@ -1662,9 +2827,45 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1662
2827
|
* @param options - Task execution options
|
|
1663
2828
|
*/
|
|
1664
2829
|
async updateMediaBuy(params, inputHandler, options) {
|
|
1665
|
-
|
|
2830
|
+
const { legacyFormatConverter, projectionCatalogs, canonicalFormatLegacyResolver, ...taskOptions } = options ?? {};
|
|
2831
|
+
const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
|
|
2832
|
+
legacyFormatConverter,
|
|
2833
|
+
projectionCatalogs ?? this.config.projectionCatalogs
|
|
2834
|
+
);
|
|
2835
|
+
const effectiveCanonicalFormatLegacyResolver = this.resolveCanonicalFormatLegacyResolver(
|
|
2836
|
+
canonicalFormatLegacyResolver,
|
|
2837
|
+
params.account
|
|
2838
|
+
);
|
|
2839
|
+
const hasCreativeFormatData = hasMediaBuyCreativeFormatData(params);
|
|
2840
|
+
if (hasCreativeFormatData) {
|
|
2841
|
+
this.validateBeforeCreativeCapabilityProbe("update_media_buy", params, taskOptions);
|
|
2842
|
+
}
|
|
2843
|
+
const wireMode = hasCreativeFormatData ? this.resolveCreativeFormatWireMode(
|
|
2844
|
+
"update_media_buy",
|
|
2845
|
+
await this.getCapabilities({ signal: taskOptions.signal, transport: taskOptions.transport })
|
|
2846
|
+
) : "canonical";
|
|
2847
|
+
const result = await this.executeAndHandle(
|
|
1666
2848
|
"update_media_buy",
|
|
1667
2849
|
"onUpdateMediaBuyStatusChange",
|
|
2850
|
+
projectMediaBuyCreativesForDelivery(
|
|
2851
|
+
params,
|
|
2852
|
+
wireMode,
|
|
2853
|
+
"update_media_buy",
|
|
2854
|
+
effectiveLegacyFormatConverter,
|
|
2855
|
+
effectiveCanonicalFormatLegacyResolver
|
|
2856
|
+
),
|
|
2857
|
+
inputHandler,
|
|
2858
|
+
taskOptions,
|
|
2859
|
+
void 0,
|
|
2860
|
+
effectiveLegacyFormatConverter,
|
|
2861
|
+
params
|
|
2862
|
+
);
|
|
2863
|
+
if (result.data !== void 0) this.rememberCanonicalPackageRoutes(result.data, params);
|
|
2864
|
+
return result;
|
|
2865
|
+
}
|
|
2866
|
+
/** @deprecated Compatibility-only entry point for callers still holding legacy creative `format_id` values. */
|
|
2867
|
+
async updateMediaBuyLegacy(params, inputHandler, options) {
|
|
2868
|
+
return await this.updateMediaBuy(
|
|
1668
2869
|
params,
|
|
1669
2870
|
inputHandler,
|
|
1670
2871
|
options
|
|
@@ -1678,41 +2879,149 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1678
2879
|
* @param options - Task execution options
|
|
1679
2880
|
*/
|
|
1680
2881
|
async syncCreatives(params, inputHandler, options) {
|
|
2882
|
+
const {
|
|
2883
|
+
creativeFormatProjection,
|
|
2884
|
+
legacyFormatConverter,
|
|
2885
|
+
projectionCatalogs,
|
|
2886
|
+
canonicalFormatLegacyResolver,
|
|
2887
|
+
...taskOptions
|
|
2888
|
+
} = options ?? {};
|
|
2889
|
+
const effectiveCanonicalFormatLegacyResolver = this.resolveCanonicalFormatLegacyResolver(
|
|
2890
|
+
canonicalFormatLegacyResolver,
|
|
2891
|
+
params.account
|
|
2892
|
+
);
|
|
2893
|
+
const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
|
|
2894
|
+
creativeFormatProjection?.legacyFormatConverter ?? legacyFormatConverter,
|
|
2895
|
+
projectionCatalogs ?? this.config.projectionCatalogs
|
|
2896
|
+
);
|
|
2897
|
+
this.validateBeforeCreativeCapabilityProbe("sync_creatives", params, taskOptions);
|
|
2898
|
+
const wireMode = this.resolveCreativeFormatWireMode(
|
|
2899
|
+
"sync_creatives",
|
|
2900
|
+
await this.getCapabilities({ signal: taskOptions.signal, transport: taskOptions.transport })
|
|
2901
|
+
);
|
|
2902
|
+
const configuredSelectorContainers = [
|
|
2903
|
+
...creativeFormatProjection?.selectorContainers ?? []
|
|
2904
|
+
];
|
|
2905
|
+
const configuredPackageIds = new Set(
|
|
2906
|
+
configuredSelectorContainers.flatMap(
|
|
2907
|
+
(container) => typeof container.package_id === "string" ? [container.package_id] : []
|
|
2908
|
+
)
|
|
2909
|
+
);
|
|
2910
|
+
const assignmentPackageContainers = Array.isArray(params.assignments) ? params.assignments.flatMap(
|
|
2911
|
+
(assignment) => typeof assignment.package_id === "string" && !configuredPackageIds.has(assignment.package_id) ? [{ package_id: assignment.package_id }] : []
|
|
2912
|
+
) : [];
|
|
2913
|
+
const wireParams = projectSyncCreativesForDelivery(
|
|
2914
|
+
params,
|
|
2915
|
+
[...configuredSelectorContainers, ...assignmentPackageContainers],
|
|
2916
|
+
wireMode,
|
|
2917
|
+
effectiveLegacyFormatConverter,
|
|
2918
|
+
effectiveCanonicalFormatLegacyResolver
|
|
2919
|
+
);
|
|
1681
2920
|
return this.executeAndHandle(
|
|
1682
2921
|
"sync_creatives",
|
|
1683
2922
|
"onSyncCreativesStatusChange",
|
|
2923
|
+
wireParams,
|
|
2924
|
+
inputHandler,
|
|
2925
|
+
taskOptions,
|
|
2926
|
+
void 0,
|
|
2927
|
+
effectiveLegacyFormatConverter,
|
|
2928
|
+
params
|
|
2929
|
+
);
|
|
2930
|
+
}
|
|
2931
|
+
/** @deprecated Compatibility-only entry point for callers still holding legacy creative `format_id` values. */
|
|
2932
|
+
async syncCreativesLegacy(params, inputHandler, options) {
|
|
2933
|
+
return await this.syncCreatives(
|
|
1684
2934
|
params,
|
|
1685
2935
|
inputHandler,
|
|
1686
2936
|
options
|
|
1687
2937
|
);
|
|
1688
2938
|
}
|
|
2939
|
+
resolveCreativeFormatWireMode(taskType, capabilities) {
|
|
2940
|
+
const wireRelease = this.config.wireAdcpVersion ?? this.resolvedAdcpVersion;
|
|
2941
|
+
const declared = resolveCreativeFormatWireMode(capabilities, wireRelease);
|
|
2942
|
+
const schema = creativeSchemaSupport(this.cachedToolSchemas?.get(taskType));
|
|
2943
|
+
if (declared !== "unknown" && schema !== "unknown" && declared !== schema) {
|
|
2944
|
+
throw new CreativeFormatCapabilityError(
|
|
2945
|
+
`Seller capability and ${taskType} input schema disagree about canonical creative support`
|
|
2946
|
+
);
|
|
2947
|
+
}
|
|
2948
|
+
const resolved = declared !== "unknown" ? declared : schema;
|
|
2949
|
+
const release = /^v?(\d+)\.(\d+)(?:\.|-|$)/.exec(wireRelease.trim());
|
|
2950
|
+
const canonicalRequiredByBuyerPin = release !== null && (Number(release[1]) > 3 || Number(release[1]) === 3 && Number(release[2]) >= 2);
|
|
2951
|
+
if (resolved === "unknown" && canonicalRequiredByBuyerPin) {
|
|
2952
|
+
throw new CreativeFormatCapabilityError(
|
|
2953
|
+
`Cannot prove which AdCP release the seller serves for ${taskType}; a 3.2+ client will not guess a legacy creative wire shape`
|
|
2954
|
+
);
|
|
2955
|
+
}
|
|
2956
|
+
return resolved;
|
|
2957
|
+
}
|
|
2958
|
+
/** Validate malformed creative payloads before capability discovery can perform I/O. */
|
|
2959
|
+
validateBeforeCreativeCapabilityProbe(taskType, params, options) {
|
|
2960
|
+
if (options.skipIdempotencyAutoInject || options.skipAccountValidation) return;
|
|
2961
|
+
let normalizedParams = normalizeRequestParams(taskType, params);
|
|
2962
|
+
if (isMutatingTask(taskType) && normalizedParams && typeof normalizedParams === "object" && !normalizedParams.idempotency_key) {
|
|
2963
|
+
normalizedParams = { ...normalizedParams, idempotency_key: generateIdempotencyKey() };
|
|
2964
|
+
}
|
|
2965
|
+
this.validateRequest(taskType, normalizedParams);
|
|
2966
|
+
}
|
|
1689
2967
|
/**
|
|
1690
|
-
* List
|
|
2968
|
+
* List creatives through the canonical SDK boundary.
|
|
2969
|
+
*
|
|
2970
|
+
* Legacy format filters are rejected and returned creative identities are
|
|
2971
|
+
* projected to `format_kind` / `format_option_ref`. Migration tooling that
|
|
2972
|
+
* needs the negotiated raw wire shape must call `listCreativesLegacy()`.
|
|
1691
2973
|
*
|
|
1692
2974
|
* @param params - Creative listing parameters
|
|
1693
2975
|
* @param inputHandler - Handler for clarification requests
|
|
1694
2976
|
* @param options - Task execution options
|
|
1695
2977
|
*/
|
|
1696
2978
|
async listCreatives(params, inputHandler, options) {
|
|
2979
|
+
const { legacyFormatConverter, projectionCatalogs, ...taskOptions } = options ?? {};
|
|
2980
|
+
const effectiveLegacyFormatConverter = this.resolveLegacyFormatConverter(
|
|
2981
|
+
legacyFormatConverter,
|
|
2982
|
+
projectionCatalogs ?? this.config.projectionCatalogs
|
|
2983
|
+
);
|
|
1697
2984
|
return this.executeAndHandle(
|
|
1698
2985
|
"list_creatives",
|
|
1699
2986
|
"onListCreativesStatusChange",
|
|
1700
2987
|
params,
|
|
1701
2988
|
inputHandler,
|
|
1702
|
-
|
|
2989
|
+
taskOptions,
|
|
2990
|
+
(data) => {
|
|
2991
|
+
const { _message: _dropLegacyMessage, ...safe } = data;
|
|
2992
|
+
void _dropLegacyMessage;
|
|
2993
|
+
return {
|
|
2994
|
+
...safe,
|
|
2995
|
+
creatives: data.creatives.map(
|
|
2996
|
+
(creative) => projectCreativeForDelivery(
|
|
2997
|
+
creative,
|
|
2998
|
+
{},
|
|
2999
|
+
"canonical",
|
|
3000
|
+
"list_creatives",
|
|
3001
|
+
effectiveLegacyFormatConverter
|
|
3002
|
+
)
|
|
3003
|
+
)
|
|
3004
|
+
};
|
|
3005
|
+
},
|
|
3006
|
+
effectiveLegacyFormatConverter
|
|
1703
3007
|
);
|
|
1704
3008
|
}
|
|
3009
|
+
/** @deprecated Explicit raw-wire escape hatch for migration tooling. */
|
|
3010
|
+
async listCreativesLegacy(params, inputHandler, options) {
|
|
3011
|
+
return this.executeTaskUnprojected("list_creatives", params, inputHandler, options);
|
|
3012
|
+
}
|
|
1705
3013
|
/**
|
|
1706
|
-
* Preview a creative
|
|
3014
|
+
* Preview a creative through the legacy named-format protocol.
|
|
1707
3015
|
*
|
|
1708
3016
|
* @param params - Preview creative parameters
|
|
1709
3017
|
* @param inputHandler - Handler for clarification requests
|
|
1710
3018
|
* @param options - Task execution options
|
|
3019
|
+
* @deprecated Migration-only access to `format_id`-based creative preview.
|
|
1711
3020
|
*/
|
|
1712
|
-
async
|
|
3021
|
+
async previewCreativeLegacy(params, inputHandler, options) {
|
|
1713
3022
|
return this.executeAndHandle(
|
|
1714
3023
|
"preview_creative",
|
|
1715
|
-
"
|
|
3024
|
+
"onPreviewCreativeLegacyStatusChange",
|
|
1716
3025
|
params,
|
|
1717
3026
|
inputHandler,
|
|
1718
3027
|
options
|
|
@@ -1726,13 +3035,18 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1726
3035
|
* @param options - Task execution options
|
|
1727
3036
|
*/
|
|
1728
3037
|
async getMediaBuys(params, inputHandler, options) {
|
|
1729
|
-
|
|
3038
|
+
const { legacyFormatConverter, projectionCatalogs, ...taskOptions } = options ?? {};
|
|
3039
|
+
const result = await this.executeAndHandle(
|
|
1730
3040
|
"get_media_buys",
|
|
1731
3041
|
"onGetMediaBuysStatusChange",
|
|
1732
3042
|
params,
|
|
1733
3043
|
inputHandler,
|
|
1734
|
-
|
|
3044
|
+
taskOptions,
|
|
3045
|
+
void 0,
|
|
3046
|
+
this.resolveLegacyFormatConverter(legacyFormatConverter, projectionCatalogs ?? this.config.projectionCatalogs)
|
|
1735
3047
|
);
|
|
3048
|
+
if (result.data !== void 0) this.rememberCanonicalPackageRoutes(result.data, params);
|
|
3049
|
+
return result;
|
|
1736
3050
|
}
|
|
1737
3051
|
/**
|
|
1738
3052
|
* Get media buy delivery information
|
|
@@ -1742,12 +3056,28 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1742
3056
|
* @param options - Task execution options
|
|
1743
3057
|
*/
|
|
1744
3058
|
async getMediaBuyDelivery(params, inputHandler, options) {
|
|
3059
|
+
const { legacyFormatConverter, projectionCatalogs, ...taskOptions } = options ?? {};
|
|
1745
3060
|
return this.executeAndHandle(
|
|
1746
3061
|
"get_media_buy_delivery",
|
|
1747
3062
|
"onGetMediaBuyDeliveryStatusChange",
|
|
1748
3063
|
params,
|
|
1749
3064
|
inputHandler,
|
|
1750
|
-
|
|
3065
|
+
taskOptions,
|
|
3066
|
+
void 0,
|
|
3067
|
+
this.resolveLegacyFormatConverter(legacyFormatConverter, projectionCatalogs ?? this.config.projectionCatalogs)
|
|
3068
|
+
);
|
|
3069
|
+
}
|
|
3070
|
+
/** Retrieve canonical creative-level and variant-level delivery metrics. */
|
|
3071
|
+
async getCreativeDelivery(params, inputHandler, options) {
|
|
3072
|
+
const { legacyFormatConverter, ...taskOptions } = options ?? {};
|
|
3073
|
+
return this.executeAndHandle(
|
|
3074
|
+
"get_creative_delivery",
|
|
3075
|
+
"onGetCreativeDeliveryStatusChange",
|
|
3076
|
+
params,
|
|
3077
|
+
inputHandler,
|
|
3078
|
+
taskOptions,
|
|
3079
|
+
void 0,
|
|
3080
|
+
legacyFormatConverter
|
|
1751
3081
|
);
|
|
1752
3082
|
}
|
|
1753
3083
|
/**
|
|
@@ -1874,12 +3204,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1874
3204
|
}
|
|
1875
3205
|
// ====== CREATIVE BUILD TASKS ======
|
|
1876
3206
|
/**
|
|
1877
|
-
* Build a creative
|
|
3207
|
+
* Build a creative through the legacy named-format protocol.
|
|
3208
|
+
* @deprecated Migration-only access to `target_format_id`-based creative building.
|
|
1878
3209
|
*/
|
|
1879
|
-
async
|
|
3210
|
+
async buildCreativeLegacy(params, inputHandler, options) {
|
|
1880
3211
|
return this.executeAndHandle(
|
|
1881
3212
|
"build_creative",
|
|
1882
|
-
"
|
|
3213
|
+
"onBuildCreativeLegacyStatusChange",
|
|
1883
3214
|
params,
|
|
1884
3215
|
inputHandler,
|
|
1885
3216
|
options
|
|
@@ -1986,10 +3317,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1986
3317
|
/**
|
|
1987
3318
|
* List content standards
|
|
1988
3319
|
*/
|
|
1989
|
-
async
|
|
3320
|
+
async listContentStandardsLegacy(params, inputHandler, options) {
|
|
1990
3321
|
return this.executeAndHandle(
|
|
1991
3322
|
"list_content_standards",
|
|
1992
|
-
"
|
|
3323
|
+
"onListContentStandardsLegacyStatusChange",
|
|
1993
3324
|
params,
|
|
1994
3325
|
inputHandler,
|
|
1995
3326
|
options
|
|
@@ -1998,10 +3329,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
1998
3329
|
/**
|
|
1999
3330
|
* Get content standards
|
|
2000
3331
|
*/
|
|
2001
|
-
async
|
|
3332
|
+
async getContentStandardsLegacy(params, inputHandler, options) {
|
|
2002
3333
|
return this.executeAndHandle(
|
|
2003
3334
|
"get_content_standards",
|
|
2004
|
-
"
|
|
3335
|
+
"onGetContentStandardsLegacyStatusChange",
|
|
2005
3336
|
params,
|
|
2006
3337
|
inputHandler,
|
|
2007
3338
|
options
|
|
@@ -2010,10 +3341,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2010
3341
|
/**
|
|
2011
3342
|
* Calibrate content against standards
|
|
2012
3343
|
*/
|
|
2013
|
-
async
|
|
3344
|
+
async calibrateContentLegacy(params, inputHandler, options) {
|
|
2014
3345
|
return this.executeAndHandle(
|
|
2015
3346
|
"calibrate_content",
|
|
2016
|
-
"
|
|
3347
|
+
"onCalibrateContentLegacyStatusChange",
|
|
2017
3348
|
params,
|
|
2018
3349
|
inputHandler,
|
|
2019
3350
|
options
|
|
@@ -2022,10 +3353,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2022
3353
|
/**
|
|
2023
3354
|
* Validate content delivery
|
|
2024
3355
|
*/
|
|
2025
|
-
async
|
|
3356
|
+
async validateContentDeliveryLegacy(params, inputHandler, options) {
|
|
2026
3357
|
return this.executeAndHandle(
|
|
2027
3358
|
"validate_content_delivery",
|
|
2028
|
-
"
|
|
3359
|
+
"onValidateContentDeliveryLegacyStatusChange",
|
|
2029
3360
|
params,
|
|
2030
3361
|
inputHandler,
|
|
2031
3362
|
options
|
|
@@ -2080,25 +3411,62 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2080
3411
|
options
|
|
2081
3412
|
);
|
|
2082
3413
|
}
|
|
2083
|
-
|
|
3414
|
+
async executeTask(taskName, params, inputHandler, options) {
|
|
3415
|
+
switch (taskName) {
|
|
3416
|
+
case "get_products":
|
|
3417
|
+
return this.getProducts(params, inputHandler, options);
|
|
3418
|
+
case "create_media_buy":
|
|
3419
|
+
return await this.createMediaBuy(
|
|
3420
|
+
params,
|
|
3421
|
+
inputHandler,
|
|
3422
|
+
options
|
|
3423
|
+
);
|
|
3424
|
+
case "update_media_buy":
|
|
3425
|
+
return await this.updateMediaBuy(
|
|
3426
|
+
params,
|
|
3427
|
+
inputHandler,
|
|
3428
|
+
options
|
|
3429
|
+
);
|
|
3430
|
+
case "sync_creatives":
|
|
3431
|
+
return await this.syncCreatives(
|
|
3432
|
+
params,
|
|
3433
|
+
inputHandler,
|
|
3434
|
+
options
|
|
3435
|
+
);
|
|
3436
|
+
case "list_creatives":
|
|
3437
|
+
return this.listCreatives(params, inputHandler, options);
|
|
3438
|
+
case "get_media_buys":
|
|
3439
|
+
return this.getMediaBuys(params, inputHandler, options);
|
|
3440
|
+
case "get_media_buy_delivery":
|
|
3441
|
+
return this.getMediaBuyDelivery(params, inputHandler, options);
|
|
3442
|
+
case "get_creative_delivery":
|
|
3443
|
+
return this.getCreativeDelivery(params, inputHandler, options);
|
|
3444
|
+
}
|
|
3445
|
+
return this.executeTaskUnprojected(taskName, params, inputHandler, options);
|
|
3446
|
+
}
|
|
2084
3447
|
/**
|
|
2085
|
-
* Execute
|
|
3448
|
+
* Execute an extension task that is not part of the standard AdCP task set.
|
|
2086
3449
|
*
|
|
2087
|
-
*
|
|
2088
|
-
*
|
|
2089
|
-
*
|
|
2090
|
-
* @param options - Task execution options
|
|
2091
|
-
*
|
|
2092
|
-
* @example
|
|
2093
|
-
* ```typescript
|
|
2094
|
-
* const result = await client.executeTask(
|
|
2095
|
-
* 'get_products',
|
|
2096
|
-
* { brief: 'Coffee brands' },
|
|
2097
|
-
* handler
|
|
2098
|
-
* );
|
|
2099
|
-
* ```
|
|
3450
|
+
* Keeping custom tasks on an explicitly named API prevents a response-type
|
|
3451
|
+
* generic from weakening the canonical request types enforced by
|
|
3452
|
+
* `executeTask()` for standard creative-boundary tasks.
|
|
2100
3453
|
*/
|
|
2101
|
-
async
|
|
3454
|
+
async executeCustomTask(taskName, params, inputHandler, options) {
|
|
3455
|
+
if (STANDARD_ADCP_TASK_NAMES.has(taskName)) {
|
|
3456
|
+
throw new Error(
|
|
3457
|
+
`executeCustomTask() cannot execute standard AdCP task "${taskName}". Use its typed primary method, or an explicitly named *Legacy method for legacy creative tools.`
|
|
3458
|
+
);
|
|
3459
|
+
}
|
|
3460
|
+
return this.executeTaskUnprojected(taskName, params, inputHandler, options);
|
|
3461
|
+
}
|
|
3462
|
+
/**
|
|
3463
|
+
* Explicit raw-task compatibility escape hatch for conformance and migration tooling.
|
|
3464
|
+
* @deprecated Application code should use typed primary methods or `executeTask()`.
|
|
3465
|
+
*/
|
|
3466
|
+
async executeTaskLegacy(taskName, params, inputHandler, options) {
|
|
3467
|
+
return this.executeTaskUnprojected(taskName, params, inputHandler, options);
|
|
3468
|
+
}
|
|
3469
|
+
async executeTaskUnprojected(taskName, params, inputHandler, options) {
|
|
2102
3470
|
throwIfAborted(options?.signal);
|
|
2103
3471
|
const startTime = Date.now();
|
|
2104
3472
|
try {
|
|
@@ -2153,8 +3521,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2153
3521
|
if (result.success && result.data) {
|
|
2154
3522
|
result.data = this.normalizeResponseToV3(taskName, result.data);
|
|
2155
3523
|
}
|
|
2156
|
-
result = this.wrapProductPolicySubmittedContinuation(result, taskName, normalizedParams);
|
|
2157
|
-
|
|
3524
|
+
result = this.wrapProductPolicySubmittedContinuation(result, taskName, normalizedParams, options);
|
|
3525
|
+
if (result.status === "working") {
|
|
3526
|
+
this.rememberProductPolicyRequestParams(taskName, normalizedParams, result, options);
|
|
3527
|
+
}
|
|
2158
3528
|
result = await this.applyProductPropertyPolicy(result, taskName, normalizedParams);
|
|
2159
3529
|
return result;
|
|
2160
3530
|
} catch (error) {
|
|
@@ -2232,19 +3602,58 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2232
3602
|
*/
|
|
2233
3603
|
async continueConversation(message, contextId, inputHandler) {
|
|
2234
3604
|
const agent = await this.ensureEndpointDiscovered();
|
|
2235
|
-
|
|
3605
|
+
const creativeAssociation = this.canonicalCreativeTaskAssociation(contextId);
|
|
3606
|
+
if (!creativeAssociation) {
|
|
3607
|
+
return this.executor.executeTask(agent, "continue_conversation", { message }, inputHandler, { contextId });
|
|
3608
|
+
}
|
|
3609
|
+
const { taskType: creativeTaskType } = creativeAssociation;
|
|
3610
|
+
const legacyFormatConverter = this.resolveLegacyFormatConverter(creativeAssociation.legacyFormatConverter);
|
|
3611
|
+
const result = await canonicalCreativeExecutionStorage.run(
|
|
3612
|
+
{ taskType: creativeTaskType, legacyFormatConverter },
|
|
3613
|
+
() => this.executor.executeTask(
|
|
3614
|
+
agent,
|
|
3615
|
+
"continue_conversation",
|
|
3616
|
+
{ message },
|
|
3617
|
+
this.canonicalCreativeInputHandler(creativeTaskType, inputHandler),
|
|
3618
|
+
{ contextId }
|
|
3619
|
+
)
|
|
3620
|
+
);
|
|
3621
|
+
const canonical = this.canonicalizeCreativeTaskResult(result, creativeTaskType, void 0, legacyFormatConverter);
|
|
3622
|
+
this.rememberCanonicalCreativeTaskIds(
|
|
3623
|
+
canonical,
|
|
3624
|
+
creativeTaskType,
|
|
3625
|
+
legacyFormatConverter,
|
|
3626
|
+
creativeAssociation.routingSnapshot
|
|
3627
|
+
);
|
|
3628
|
+
return this.wrapCanonicalCreativeContinuations(
|
|
3629
|
+
canonical,
|
|
3630
|
+
creativeTaskType,
|
|
3631
|
+
void 0,
|
|
3632
|
+
legacyFormatConverter,
|
|
3633
|
+
creativeAssociation.routingSnapshot
|
|
3634
|
+
);
|
|
2236
3635
|
}
|
|
2237
3636
|
/**
|
|
2238
3637
|
* Get conversation history for a task
|
|
2239
3638
|
*/
|
|
2240
3639
|
getConversationHistory(taskId) {
|
|
2241
|
-
|
|
3640
|
+
const history = this.executor.getConversationHistory(taskId);
|
|
3641
|
+
const association = this.canonicalCreativeTaskAssociation(taskId);
|
|
3642
|
+
if (!association) return history;
|
|
3643
|
+
const { taskType } = association;
|
|
3644
|
+
const converter = this.resolveLegacyFormatConverter(association.legacyFormatConverter);
|
|
3645
|
+
return history?.map((message) => ({
|
|
3646
|
+
...message,
|
|
3647
|
+
content: projectCanonicalCreativeAncillaryValue(message.content, taskType, converter)
|
|
3648
|
+
}));
|
|
2242
3649
|
}
|
|
2243
3650
|
/**
|
|
2244
3651
|
* Clear conversation history for a task
|
|
2245
3652
|
*/
|
|
2246
3653
|
clearConversationHistory(taskId) {
|
|
2247
3654
|
this.executor.clearConversationHistory(taskId);
|
|
3655
|
+
this.forgetCanonicalCreativeTaskAssociationKeys([taskId]);
|
|
3656
|
+
this.productPolicyRequestParamsByTask.delete(taskId);
|
|
2248
3657
|
}
|
|
2249
3658
|
// ====== AGENT INFORMATION ======
|
|
2250
3659
|
/**
|
|
@@ -2385,7 +3794,23 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2385
3794
|
* Get active tasks for this agent
|
|
2386
3795
|
*/
|
|
2387
3796
|
getActiveTasks() {
|
|
2388
|
-
return this.executor.getActiveTasks().filter((task) => task.agent.id === this.agent.id)
|
|
3797
|
+
return this.executor.getActiveTasks().filter((task) => task.agent.id === this.agent.id).map((task) => {
|
|
3798
|
+
if (!CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskName)) return task;
|
|
3799
|
+
const converter = this.resolveLegacyFormatConverter(
|
|
3800
|
+
this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter
|
|
3801
|
+
);
|
|
3802
|
+
return stripLegacyCreativeIdentity({
|
|
3803
|
+
...task,
|
|
3804
|
+
params: projectCanonicalCreativeAncillaryValue(task.params, task.taskName, converter),
|
|
3805
|
+
messages: task.messages.map((message) => ({
|
|
3806
|
+
...message,
|
|
3807
|
+
content: projectCanonicalCreativeAncillaryValue(message.content, task.taskName, converter)
|
|
3808
|
+
})),
|
|
3809
|
+
...task.pendingInput !== void 0 && {
|
|
3810
|
+
pendingInput: projectCanonicalCreativeAncillaryValue(task.pendingInput, task.taskName, converter)
|
|
3811
|
+
}
|
|
3812
|
+
});
|
|
3813
|
+
});
|
|
2389
3814
|
}
|
|
2390
3815
|
// ====== TASK MANAGEMENT & NOTIFICATIONS ======
|
|
2391
3816
|
/**
|
|
@@ -2402,7 +3827,15 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2402
3827
|
* ```
|
|
2403
3828
|
*/
|
|
2404
3829
|
async listTasks() {
|
|
2405
|
-
|
|
3830
|
+
const tasks = await this.executor.getTaskList(this.agent.id);
|
|
3831
|
+
return tasks.map(
|
|
3832
|
+
(task) => CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskType) ? this.canonicalizeCreativeTaskInfo(
|
|
3833
|
+
task,
|
|
3834
|
+
task.taskType,
|
|
3835
|
+
void 0,
|
|
3836
|
+
this.resolveLegacyFormatConverter(this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter)
|
|
3837
|
+
) : task
|
|
3838
|
+
);
|
|
2406
3839
|
}
|
|
2407
3840
|
/**
|
|
2408
3841
|
* Get detailed information about a specific task
|
|
@@ -2411,7 +3844,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2411
3844
|
* @returns Promise resolving to task information
|
|
2412
3845
|
*/
|
|
2413
3846
|
async getTaskInfo(taskId) {
|
|
2414
|
-
|
|
3847
|
+
const task = await this.executor.getTaskInfo(taskId);
|
|
3848
|
+
return task && CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskType) ? this.canonicalizeCreativeTaskInfo(
|
|
3849
|
+
task,
|
|
3850
|
+
task.taskType,
|
|
3851
|
+
void 0,
|
|
3852
|
+
this.resolveLegacyFormatConverter(this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter)
|
|
3853
|
+
) : task;
|
|
2415
3854
|
}
|
|
2416
3855
|
/**
|
|
2417
3856
|
* Subscribe to task notifications for this agent
|
|
@@ -2433,7 +3872,19 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2433
3872
|
* ```
|
|
2434
3873
|
*/
|
|
2435
3874
|
onTaskUpdate(callback) {
|
|
2436
|
-
return this.executor.onTaskUpdate(
|
|
3875
|
+
return this.executor.onTaskUpdate(
|
|
3876
|
+
this.agent.id,
|
|
3877
|
+
(task) => callback(
|
|
3878
|
+
CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskType) ? this.canonicalizeCreativeTaskInfo(
|
|
3879
|
+
task,
|
|
3880
|
+
task.taskType,
|
|
3881
|
+
void 0,
|
|
3882
|
+
this.resolveLegacyFormatConverter(
|
|
3883
|
+
this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter
|
|
3884
|
+
)
|
|
3885
|
+
) : task
|
|
3886
|
+
)
|
|
3887
|
+
);
|
|
2437
3888
|
}
|
|
2438
3889
|
/**
|
|
2439
3890
|
* Subscribe to all task events (create, update, complete, error)
|
|
@@ -2442,7 +3893,23 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2442
3893
|
* @returns Unsubscribe function
|
|
2443
3894
|
*/
|
|
2444
3895
|
onTaskEvents(callbacks) {
|
|
2445
|
-
|
|
3896
|
+
const safe = (task) => CANONICAL_CREATIVE_ACTIVITY_TASKS.has(task.taskType) ? this.canonicalizeCreativeTaskInfo(
|
|
3897
|
+
task,
|
|
3898
|
+
task.taskType,
|
|
3899
|
+
void 0,
|
|
3900
|
+
this.resolveLegacyFormatConverter(this.canonicalCreativeTaskAssociation(task.taskId)?.legacyFormatConverter)
|
|
3901
|
+
) : task;
|
|
3902
|
+
return this.executor.onTaskEvents(this.agent.id, {
|
|
3903
|
+
...callbacks.onTaskCreated && { onTaskCreated: (task) => callbacks.onTaskCreated(safe(task)) },
|
|
3904
|
+
...callbacks.onTaskUpdated && { onTaskUpdated: (task) => callbacks.onTaskUpdated(safe(task)) },
|
|
3905
|
+
...callbacks.onTaskCompleted && { onTaskCompleted: (task) => callbacks.onTaskCompleted(safe(task)) },
|
|
3906
|
+
...callbacks.onTaskFailed && {
|
|
3907
|
+
onTaskFailed: (task, error) => {
|
|
3908
|
+
const safeTask = safe(task);
|
|
3909
|
+
callbacks.onTaskFailed(safeTask, safeTask.error ?? stripLegacyCreativeIdentity(error));
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
});
|
|
2446
3913
|
}
|
|
2447
3914
|
/**
|
|
2448
3915
|
* Register webhook URL for receiving task notifications
|
|
@@ -2556,9 +4023,11 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2556
4023
|
}
|
|
2557
4024
|
let authProvider;
|
|
2558
4025
|
if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials) {
|
|
2559
|
-
const {
|
|
2560
|
-
|
|
4026
|
+
const { getAgentStorage } = await import("../auth/oauth/index.mjs");
|
|
4027
|
+
const { getNonInteractiveOAuthProvider } = await import("../auth/oauth/provider-cache.mjs");
|
|
4028
|
+
authProvider = getNonInteractiveOAuthProvider(this.normalizedAgent, {
|
|
2561
4029
|
agentHint: this.normalizedAgent.id,
|
|
4030
|
+
storage: getAgentStorage(this.normalizedAgent),
|
|
2562
4031
|
allowHttp: isLikelyPrivateUrl(this.normalizedAgent.agent_uri)
|
|
2563
4032
|
});
|
|
2564
4033
|
connectOptions.authProvider = authProvider;
|
|
@@ -2728,7 +4197,9 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2728
4197
|
);
|
|
2729
4198
|
if (discoveryContext) discoveryContext.toolSchemas = discoveredToolSchemas;
|
|
2730
4199
|
if (!usesScopedFetch) this.cachedToolSchemas = discoveredToolSchemas;
|
|
2731
|
-
const
|
|
4200
|
+
const advertisesCapabilitiesTool = tools.some((t) => t.name === "get_adcp_capabilities");
|
|
4201
|
+
const officialA2ALifecycle = this.normalizedAgent.protocol === "a2a" && tools.some((tool) => ["tasks/get", "get_task_status", "list_tasks"].includes(tool.name));
|
|
4202
|
+
const hasCapabilitiesTool = advertisesCapabilitiesTool || officialA2ALifecycle;
|
|
2732
4203
|
if (hasCapabilitiesTool) {
|
|
2733
4204
|
try {
|
|
2734
4205
|
const agent = await this.ensureEndpointDiscovered(options);
|
|
@@ -2741,10 +4212,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2741
4212
|
throw createTimeoutError(requestTimeoutMs);
|
|
2742
4213
|
}
|
|
2743
4214
|
if (result.success && result.data) {
|
|
2744
|
-
const
|
|
2745
|
-
if (!usesScopedFetch) this.cachedCapabilities =
|
|
2746
|
-
this.maybeWarnV2Sunset(
|
|
2747
|
-
return
|
|
4215
|
+
const capabilities2 = augmentCapabilitiesFromTools(parseCapabilitiesResponse(result.data), tools);
|
|
4216
|
+
if (!usesScopedFetch) this.cachedCapabilities = capabilities2;
|
|
4217
|
+
this.maybeWarnV2Sunset(capabilities2);
|
|
4218
|
+
return capabilities2;
|
|
4219
|
+
}
|
|
4220
|
+
if (!advertisesCapabilitiesTool) {
|
|
4221
|
+
throw new Error("unadvertised official A2A capability probe was not supported");
|
|
2748
4222
|
}
|
|
2749
4223
|
if (result.data && looksLikeV3Capabilities(result.data)) {
|
|
2750
4224
|
console.warn(
|
|
@@ -2757,10 +4231,10 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2757
4231
|
version: "v3",
|
|
2758
4232
|
majorVersions: parsed.majorVersions.includes(3) ? parsed.majorVersions : [3]
|
|
2759
4233
|
};
|
|
2760
|
-
const
|
|
2761
|
-
if (!usesScopedFetch) this.cachedCapabilities =
|
|
2762
|
-
this.maybeWarnV2Sunset(
|
|
2763
|
-
return
|
|
4234
|
+
const capabilities2 = augmentCapabilitiesFromTools(v3Capabilities, tools);
|
|
4235
|
+
if (!usesScopedFetch) this.cachedCapabilities = capabilities2;
|
|
4236
|
+
this.maybeWarnV2Sunset(capabilities2);
|
|
4237
|
+
return capabilities2;
|
|
2764
4238
|
}
|
|
2765
4239
|
console.warn(
|
|
2766
4240
|
`[AdCP] Agent "${this.agent.id}" advertises get_adcp_capabilities but the call returned non-success and the response is not v3-shaped \u2014 treating as v3 (synthetic) since the agent has the v3-only discovery tool. This client routes to v3 adapters, but calls reading capability details (idempotency TTL, supported_versions, feature flags) will fail until the agent operator fixes the capabilities endpoint.`,
|
|
@@ -2774,14 +4248,18 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
2774
4248
|
if (error instanceof AuthenticationRequiredError || error instanceof TaskTimeoutError || isAbortOrTimeoutError(error)) {
|
|
2775
4249
|
throw error;
|
|
2776
4250
|
}
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
4251
|
+
if (advertisesCapabilitiesTool) {
|
|
4252
|
+
console.warn(
|
|
4253
|
+
`[AdCP] Agent "${this.agent.id}" advertises get_adcp_capabilities but the call threw \u2014 treating as v3 (synthetic) since the agent has the v3-only discovery tool. This client routes to v3 adapters, but calls reading capability details (idempotency TTL, supported_versions, feature flags) will fail until the agent operator fixes the capabilities endpoint.`
|
|
4254
|
+
);
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
if (advertisesCapabilitiesTool) {
|
|
4258
|
+
const capabilities2 = augmentCapabilitiesFromTools(buildSyntheticV3Capabilities(tools), tools);
|
|
4259
|
+
if (!usesScopedFetch) this.cachedCapabilities = capabilities2;
|
|
4260
|
+
this.maybeWarnV2Sunset(capabilities2);
|
|
4261
|
+
return capabilities2;
|
|
2780
4262
|
}
|
|
2781
|
-
const capabilities2 = augmentCapabilitiesFromTools(buildSyntheticV3Capabilities(tools), tools);
|
|
2782
|
-
if (!usesScopedFetch) this.cachedCapabilities = capabilities2;
|
|
2783
|
-
this.maybeWarnV2Sunset(capabilities2);
|
|
2784
|
-
return capabilities2;
|
|
2785
4263
|
}
|
|
2786
4264
|
console.warn(
|
|
2787
4265
|
`[AdCP] Agent "${this.agent.id}" detected as v2 (no get_adcp_capabilities tool). Tools: [${tools.map((t) => t.name).join(", ")}]`
|
|
@@ -3101,38 +4579,18 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
3101
4579
|
}
|
|
3102
4580
|
// ====== STATIC HELPER METHODS ======
|
|
3103
4581
|
/**
|
|
3104
|
-
* Query a creative
|
|
4582
|
+
* Query a legacy creative-agent named-format catalog.
|
|
3105
4583
|
*
|
|
3106
|
-
*
|
|
3107
|
-
* (
|
|
3108
|
-
* before creating a media buy.
|
|
4584
|
+
* Canonical applications discover seller-supported declarations through
|
|
4585
|
+
* `AgentClient.getProducts()` and consume `format_options[]` instead.
|
|
3109
4586
|
*
|
|
3110
4587
|
* @param creativeAgentUrl - URL of the creative agent (e.g., 'https://creative.adcontextprotocol.org/mcp')
|
|
3111
4588
|
* @param protocol - Protocol to use ('mcp' or 'a2a'), defaults to 'mcp'
|
|
3112
4589
|
* @returns Promise resolving to the list of available formats
|
|
3113
4590
|
*
|
|
3114
|
-
* @
|
|
3115
|
-
* ```typescript
|
|
3116
|
-
* // Discover formats from the standard creative agent
|
|
3117
|
-
* const formats = await SingleAgentClient.discoverCreativeFormats(
|
|
3118
|
-
* 'https://creative.adcontextprotocol.org/mcp'
|
|
3119
|
-
* );
|
|
3120
|
-
*
|
|
3121
|
-
* // Find a specific format
|
|
3122
|
-
* const banner = formats.find(f => f.format_id.id === 'display_300x250_image');
|
|
3123
|
-
*
|
|
3124
|
-
* // Use the format in a media buy
|
|
3125
|
-
* await salesAgent.createMediaBuy({
|
|
3126
|
-
* packages: [{
|
|
3127
|
-
* format_ids: [{
|
|
3128
|
-
* agent_url: banner.format_id.agent_url,
|
|
3129
|
-
* id: banner.format_id.id
|
|
3130
|
-
* }]
|
|
3131
|
-
* }]
|
|
3132
|
-
* });
|
|
3133
|
-
* ```
|
|
4591
|
+
* @deprecated Migration-only helper for the legacy named-format protocol.
|
|
3134
4592
|
*/
|
|
3135
|
-
static async
|
|
4593
|
+
static async discoverCreativeFormatsLegacy(creativeAgentUrl, protocol = "mcp") {
|
|
3136
4594
|
const client = new SingleAgentClient(
|
|
3137
4595
|
{
|
|
3138
4596
|
id: "creative_agent_discovery",
|
|
@@ -3142,7 +4600,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
3142
4600
|
},
|
|
3143
4601
|
{}
|
|
3144
4602
|
);
|
|
3145
|
-
const result = await client.
|
|
4603
|
+
const result = await client.listCreativeFormatsLegacy({});
|
|
3146
4604
|
if (!result.success || !result.data) {
|
|
3147
4605
|
throw new Error(`Failed to discover creative formats: ${result.error || "Unknown error"}`);
|
|
3148
4606
|
}
|
|
@@ -3222,12 +4680,11 @@ function parseWebhookBody(value) {
|
|
|
3222
4680
|
const raw = Buffer.isBuffer(value) || value instanceof Uint8Array ? Buffer.from(value).toString("utf8") : value;
|
|
3223
4681
|
try {
|
|
3224
4682
|
return { ok: true, payload: JSON.parse(raw) };
|
|
3225
|
-
} catch
|
|
4683
|
+
} catch {
|
|
3226
4684
|
return {
|
|
3227
4685
|
ok: false,
|
|
3228
4686
|
code: "webhook_envelope_invalid",
|
|
3229
|
-
message: "Webhook body must be valid JSON."
|
|
3230
|
-
cause: error
|
|
4687
|
+
message: "Webhook body must be valid JSON."
|
|
3231
4688
|
};
|
|
3232
4689
|
}
|
|
3233
4690
|
}
|
|
@@ -3248,13 +4705,6 @@ function missingMcpWebhookFields(payload) {
|
|
|
3248
4705
|
return typeof value !== "string" || value.length === 0;
|
|
3249
4706
|
});
|
|
3250
4707
|
}
|
|
3251
|
-
function safeJsonPreview(value) {
|
|
3252
|
-
try {
|
|
3253
|
-
return JSON.stringify(value).substring(0, 200);
|
|
3254
|
-
} catch {
|
|
3255
|
-
return "[unserializable payload]";
|
|
3256
|
-
}
|
|
3257
|
-
}
|
|
3258
4708
|
function webhookErrorHttpStatus(error) {
|
|
3259
4709
|
if (error instanceof WebhookDispatchError) {
|
|
3260
4710
|
if (error.code === "webhook_signature_invalid" || error.code === "webhook_timestamp_invalid") {
|