@adcp/sdk 12.0.0 → 12.0.2
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/dist/lib/adapters/content-standards-adapter.mjs +0 -6
- package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
- package/dist/lib/adapters/derived-account-store.mjs +0 -6
- package/dist/lib/adapters/derived-account-store.mjs.map +1 -1
- package/dist/lib/adapters/governance-adapter.mjs +0 -6
- package/dist/lib/adapters/governance-adapter.mjs.map +1 -1
- package/dist/lib/adapters/implicit-account-store.mjs +0 -6
- package/dist/lib/adapters/implicit-account-store.mjs.map +1 -1
- package/dist/lib/adapters/index.mjs +0 -6
- package/dist/lib/adapters/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/index.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/types.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs +0 -6
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs.map +1 -1
- package/dist/lib/adapters/property-list-adapter.mjs +0 -6
- package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
- package/dist/lib/adapters/roster-account-store.mjs +0 -6
- package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
- package/dist/lib/adapters/si-session-manager.mjs +0 -6
- package/dist/lib/adapters/si-session-manager.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/brand-fields.mjs +0 -6
- package/dist/lib/adapters/version/3.0/brand-fields.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/get-products.mjs +0 -6
- package/dist/lib/adapters/version/3.0/get-products.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/index.mjs +0 -6
- package/dist/lib/adapters/version/3.0/index.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs +0 -6
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs.map +1 -1
- package/dist/lib/adapters/version/index.mjs +0 -6
- package/dist/lib/adapters/version/index.mjs.map +1 -1
- package/dist/lib/adapters/version/types.mjs +0 -6
- package/dist/lib/advanced.mjs +0 -6
- package/dist/lib/advanced.mjs.map +1 -1
- package/dist/lib/agents/index.generated.mjs +0 -6
- package/dist/lib/agents/index.generated.mjs.map +1 -1
- package/dist/lib/auth/index.mjs +0 -6
- package/dist/lib/auth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +0 -6
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs.map +1 -1
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +0 -6
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs.map +1 -1
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/authorization-required.mjs +0 -6
- package/dist/lib/auth/oauth/authorization-required.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnose.mjs +0 -6
- package/dist/lib/auth/oauth/diagnose.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnostics.mjs +0 -6
- package/dist/lib/auth/oauth/diagnostics.mjs.map +1 -1
- package/dist/lib/auth/oauth/discovery.mjs +0 -6
- package/dist/lib/auth/oauth/discovery.mjs.map +1 -1
- package/dist/lib/auth/oauth/file-storage.mjs +0 -6
- package/dist/lib/auth/oauth/file-storage.mjs.map +1 -1
- package/dist/lib/auth/oauth/index.mjs +0 -6
- package/dist/lib/auth/oauth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/secret-resolver.mjs +0 -6
- package/dist/lib/auth/oauth/secret-resolver.mjs.map +1 -1
- package/dist/lib/auth/oauth/storage-registry.mjs +0 -6
- package/dist/lib/auth/oauth/storage-registry.mjs.map +1 -1
- package/dist/lib/auth/oauth/types.mjs +0 -6
- package/dist/lib/auth/oauth/types.mjs.map +1 -1
- package/dist/lib/auth/oauth/web-flow.mjs +0 -6
- package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
- package/dist/lib/brand/index.mjs +0 -6
- package/dist/lib/brand/index.mjs.map +1 -1
- package/dist/lib/canonical-references/index.mjs +6 -7
- package/dist/lib/canonical-references/index.mjs.map +1 -1
- package/dist/lib/client/index.mjs +0 -6
- package/dist/lib/client/index.mjs.map +1 -1
- package/dist/lib/compliance/index.mjs +0 -6
- package/dist/lib/compliance/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/index.mjs +0 -6
- package/dist/lib/compliance-fixtures/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs +0 -6
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs.map +1 -1
- package/dist/lib/conformance/index.mjs +0 -6
- package/dist/lib/conformance/index.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformError.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs.map +1 -1
- package/dist/lib/conformance/oracle.mjs +0 -6
- package/dist/lib/conformance/oracle.mjs.map +1 -1
- package/dist/lib/conformance/runConformance.mjs +0 -6
- package/dist/lib/conformance/runConformance.mjs.map +1 -1
- package/dist/lib/conformance/runners.mjs +0 -6
- package/dist/lib/conformance/runners.mjs.map +1 -1
- package/dist/lib/conformance/schemaArbitrary.mjs +0 -6
- package/dist/lib/conformance/schemaArbitrary.mjs.map +1 -1
- package/dist/lib/conformance/schemaLoader.mjs +5 -6
- package/dist/lib/conformance/schemaLoader.mjs.map +1 -1
- package/dist/lib/conformance/seeder.mjs +0 -6
- package/dist/lib/conformance/seeder.mjs.map +1 -1
- package/dist/lib/conformance/types.mjs +0 -6
- package/dist/lib/conformance/types.mjs.map +1 -1
- package/dist/lib/conformance/webhook.mjs +0 -6
- package/dist/lib/conformance/webhook.mjs.map +1 -1
- package/dist/lib/core/ADCPMultiAgentClient.mjs +0 -6
- package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
- package/dist/lib/core/AgentClient.mjs +0 -6
- package/dist/lib/core/AgentClient.mjs.map +1 -1
- package/dist/lib/core/AsyncHandler.mjs +0 -6
- package/dist/lib/core/AsyncHandler.mjs.map +1 -1
- package/dist/lib/core/ConfigurationManager.mjs +0 -6
- package/dist/lib/core/ConfigurationManager.mjs.map +1 -1
- package/dist/lib/core/ConversationTypes.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
- package/dist/lib/core/GovernanceMiddleware.mjs +0 -6
- package/dist/lib/core/GovernanceMiddleware.mjs.map +1 -1
- package/dist/lib/core/GovernanceTypes.mjs +0 -6
- package/dist/lib/core/GovernanceTypes.mjs.map +1 -1
- package/dist/lib/core/ProtocolResponseParser.mjs +0 -6
- package/dist/lib/core/ProtocolResponseParser.mjs.map +1 -1
- package/dist/lib/core/ResponseValidator.mjs +0 -6
- package/dist/lib/core/ResponseValidator.mjs.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +0 -6
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskEventTypes.mjs +0 -6
- package/dist/lib/core/TaskEventTypes.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +0 -6
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/core/match.mjs +0 -6
- package/dist/lib/core/match.mjs.map +1 -1
- package/dist/lib/core/task-status.mjs +0 -6
- package/dist/lib/core/task-status.mjs.map +1 -1
- package/dist/lib/core/webhook-url.mjs +0 -6
- package/dist/lib/core/webhook-url.mjs.map +1 -1
- package/dist/lib/discovery/adagents-redirects.mjs +0 -6
- package/dist/lib/discovery/adagents-redirects.mjs.map +1 -1
- package/dist/lib/discovery/agent-directory.mjs +0 -6
- package/dist/lib/discovery/agent-directory.mjs.map +1 -1
- package/dist/lib/discovery/inline-publisher-properties.mjs +0 -6
- package/dist/lib/discovery/inline-publisher-properties.mjs.map +1 -1
- package/dist/lib/discovery/network-consistency-checker.mjs +0 -6
- package/dist/lib/discovery/network-consistency-checker.mjs.map +1 -1
- package/dist/lib/discovery/property-crawler.mjs +0 -6
- package/dist/lib/discovery/property-crawler.mjs.map +1 -1
- package/dist/lib/discovery/property-index.mjs +0 -6
- package/dist/lib/discovery/property-index.mjs.map +1 -1
- package/dist/lib/discovery/publisher-property-selector.mjs +0 -6
- package/dist/lib/discovery/publisher-property-selector.mjs.map +1 -1
- package/dist/lib/discovery/resolve-agent-properties.mjs +0 -6
- package/dist/lib/discovery/resolve-agent-properties.mjs.map +1 -1
- package/dist/lib/discovery/types.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs.map +1 -1
- package/dist/lib/enums.mjs +0 -6
- package/dist/lib/enums.mjs.map +1 -1
- package/dist/lib/errors/index.mjs +0 -6
- package/dist/lib/errors/index.mjs.map +1 -1
- package/dist/lib/express-mcp/index.mjs +0 -6
- package/dist/lib/express-mcp/index.mjs.map +1 -1
- package/dist/lib/governance/index.mjs +0 -6
- package/dist/lib/governance/index.mjs.map +1 -1
- package/dist/lib/handlers/types.mjs +0 -6
- package/dist/lib/handlers/types.mjs.map +1 -1
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +0 -6
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/media-buy/available-actions.mjs +0 -6
- package/dist/lib/media-buy/available-actions.mjs.map +1 -1
- package/dist/lib/media-buy/index.mjs +0 -6
- package/dist/lib/media-buy/index.mjs.map +1 -1
- package/dist/lib/media-buy/preflight.mjs +0 -6
- package/dist/lib/media-buy/preflight.mjs.map +1 -1
- package/dist/lib/media-buy/property-policy.mjs +0 -6
- package/dist/lib/media-buy/property-policy.mjs.map +1 -1
- package/dist/lib/media-buy/types.mjs +0 -6
- package/dist/lib/media-buy/types.mjs.map +1 -1
- package/dist/lib/media-buy/update-fields.generated.mjs +0 -6
- package/dist/lib/media-buy/update-fields.generated.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/server.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/server.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-template/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/server.mjs +0 -6
- package/dist/lib/mock-server/creative-template/server.mjs.map +1 -1
- package/dist/lib/mock-server/index.mjs +0 -6
- package/dist/lib/mock-server/index.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-social/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/server.mjs +0 -6
- package/dist/lib/mock-server/sales-social/server.mjs.map +1 -1
- package/dist/lib/mock-server/scenario.mjs +0 -6
- package/dist/lib/mock-server/scenario.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/server.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/server.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs.map +1 -1
- package/dist/lib/net/address-guards.mjs +0 -6
- package/dist/lib/net/address-guards.mjs.map +1 -1
- package/dist/lib/net/index.mjs +0 -6
- package/dist/lib/net/index.mjs.map +1 -1
- package/dist/lib/net/ssrf-fetch.mjs +0 -6
- package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
- package/dist/lib/observability/index.mjs +0 -6
- package/dist/lib/observability/index.mjs.map +1 -1
- package/dist/lib/observability/tracing.mjs +6 -7
- package/dist/lib/observability/tracing.mjs.map +1 -1
- package/dist/lib/protocols/a2a.mjs +0 -6
- package/dist/lib/protocols/a2a.mjs.map +1 -1
- package/dist/lib/protocols/abort.mjs +0 -6
- package/dist/lib/protocols/abort.mjs.map +1 -1
- package/dist/lib/protocols/index.mjs +0 -6
- package/dist/lib/protocols/index.mjs.map +1 -1
- package/dist/lib/protocols/mcp-modern.mjs +0 -6
- package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
- package/dist/lib/protocols/mcp-tasks.mjs +0 -6
- package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
- package/dist/lib/protocols/mcp.mjs +0 -6
- package/dist/lib/protocols/mcp.mjs.map +1 -1
- package/dist/lib/protocols/rawResponseCapture.mjs +0 -6
- package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
- package/dist/lib/protocols/responseSizeLimit.mjs +0 -6
- package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
- package/dist/lib/protocols/transportDiagnostics.mjs +0 -6
- package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
- package/dist/lib/registry/cursor-store.mjs +0 -6
- package/dist/lib/registry/cursor-store.mjs.map +1 -1
- package/dist/lib/registry/feed-stream.mjs +0 -6
- package/dist/lib/registry/feed-stream.mjs.map +1 -1
- package/dist/lib/registry/index.mjs +0 -6
- package/dist/lib/registry/index.mjs.map +1 -1
- package/dist/lib/registry/property-registry.mjs +0 -6
- package/dist/lib/registry/property-registry.mjs.map +1 -1
- package/dist/lib/registry/sync.mjs +0 -6
- package/dist/lib/registry/sync.mjs.map +1 -1
- package/dist/lib/registry/types.generated.mjs +0 -6
- package/dist/lib/registry/types.mjs +0 -6
- package/dist/lib/schemas/index.mjs +0 -6
- package/dist/lib/schemas/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/a2a-adapter.mjs +0 -6
- package/dist/lib/server/a2a-adapter.mjs.map +1 -1
- package/dist/lib/server/account-mode.mjs +0 -6
- package/dist/lib/server/account-mode.mjs.map +1 -1
- package/dist/lib/server/adcp-server.mjs +0 -6
- package/dist/lib/server/adcp-server.mjs.map +1 -1
- package/dist/lib/server/auth-introspection.mjs +0 -6
- package/dist/lib/server/auth-introspection.mjs.map +1 -1
- package/dist/lib/server/auth-signature.mjs +0 -6
- package/dist/lib/server/auth-signature.mjs.map +1 -1
- package/dist/lib/server/auth.mjs +0 -6
- package/dist/lib/server/auth.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +13 -0
- package/dist/lib/server/create-adcp-server.d.ts +13 -0
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +3 -2
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +3 -8
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/credential-policy.mjs +0 -6
- package/dist/lib/server/credential-policy.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/memory.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/memory.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/pg.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/pg.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/redis.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/redis.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/index.mjs +0 -6
- package/dist/lib/server/ctx-metadata/index.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/store.mjs +0 -6
- package/dist/lib/server/ctx-metadata/store.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/wire-shape.mjs +0 -6
- package/dist/lib/server/ctx-metadata/wire-shape.mjs.map +1 -1
- package/dist/lib/server/decisioning/account.mjs +0 -6
- package/dist/lib/server/decisioning/account.mjs.map +1 -1
- package/dist/lib/server/decisioning/admin-router.mjs +0 -6
- package/dist/lib/server/decisioning/admin-router.mjs.map +1 -1
- package/dist/lib/server/decisioning/assembly-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/async-outcome.mjs +0 -6
- package/dist/lib/server/decisioning/async-outcome.mjs.map +1 -1
- package/dist/lib/server/decisioning/buyer-agent.mjs +0 -6
- package/dist/lib/server/decisioning/buyer-agent.mjs.map +1 -1
- package/dist/lib/server/decisioning/capabilities.mjs +0 -6
- package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
- package/dist/lib/server/decisioning/compose.mjs +0 -6
- package/dist/lib/server/decisioning/compose.mjs.map +1 -1
- package/dist/lib/server/decisioning/context.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs.map +1 -1
- package/dist/lib/server/decisioning/helpers.mjs +0 -6
- package/dist/lib/server/decisioning/helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +0 -6
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/list-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/pagination.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/platform.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/index.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/store.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/store.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
- package/dist/lib/server/decisioning/resolve-presets.mjs +0 -6
- package/dist/lib/server/decisioning/resolve-presets.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/audiences.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/brand-rights.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/campaign-governance.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/content-standards.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/lists.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sales.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/signals.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-changes.mjs +0 -6
- package/dist/lib/server/decisioning/status-changes.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-mappers.mjs +0 -6
- package/dist/lib/server/decisioning/status-mappers.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-registry.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-store.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
- package/dist/lib/server/decisioning/validate-specialisms.mjs +0 -6
- package/dist/lib/server/decisioning/validate-specialisms.mjs.map +1 -1
- package/dist/lib/server/dynamic-registry.mjs +0 -6
- package/dist/lib/server/dynamic-registry.mjs.map +1 -1
- package/dist/lib/server/envelope-allowlist.mjs +0 -6
- package/dist/lib/server/envelope-allowlist.mjs.map +1 -1
- package/dist/lib/server/error-arm-tools.mjs +5 -6
- package/dist/lib/server/error-arm-tools.mjs.map +1 -1
- package/dist/lib/server/errors.mjs +0 -6
- package/dist/lib/server/errors.mjs.map +1 -1
- package/dist/lib/server/example-tld-guard.mjs +0 -6
- package/dist/lib/server/example-tld-guard.mjs.map +1 -1
- package/dist/lib/server/express-adapter.mjs +0 -6
- package/dist/lib/server/express-adapter.mjs.map +1 -1
- package/dist/lib/server/governance.mjs +0 -6
- package/dist/lib/server/governance.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/lazy.mjs +0 -6
- package/dist/lib/server/idempotency/backends/lazy.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/memory.mjs +0 -6
- package/dist/lib/server/idempotency/backends/memory.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/pg.mjs +0 -6
- package/dist/lib/server/idempotency/backends/pg.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/redis.mjs +0 -6
- package/dist/lib/server/idempotency/backends/redis.mjs.map +1 -1
- package/dist/lib/server/idempotency/index.mjs +0 -6
- package/dist/lib/server/idempotency/index.mjs.map +1 -1
- package/dist/lib/server/idempotency/store.mjs +0 -6
- package/dist/lib/server/idempotency/store.mjs.map +1 -1
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs +0 -6
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/legacy/v5/index.d.mts +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
- package/dist/lib/server/legacy/v5/index.js.map +1 -1
- package/dist/lib/server/legacy/v5/index.mjs +0 -6
- package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
- package/dist/lib/server/mcp-modern-server.mjs +0 -6
- package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
- package/dist/lib/server/media-buy-actions.mjs +0 -6
- package/dist/lib/server/media-buy-actions.mjs.map +1 -1
- package/dist/lib/server/media-buy-helpers.mjs +0 -6
- package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
- package/dist/lib/server/media-buy-store.mjs +0 -6
- package/dist/lib/server/media-buy-store.mjs.map +1 -1
- package/dist/lib/server/normalize-errors.mjs +0 -6
- package/dist/lib/server/normalize-errors.mjs.map +1 -1
- package/dist/lib/server/operational-platform.mjs +0 -6
- package/dist/lib/server/operational-platform.mjs.map +1 -1
- package/dist/lib/server/pick-safe-details.mjs +0 -6
- package/dist/lib/server/pick-safe-details.mjs.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
- package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
- package/dist/lib/server/postgres-state-store.mjs +0 -6
- package/dist/lib/server/postgres-state-store.mjs.map +1 -1
- package/dist/lib/server/postgres-task-store.mjs +0 -6
- package/dist/lib/server/postgres-task-store.mjs.map +1 -1
- package/dist/lib/server/product-defaults.mjs +0 -6
- package/dist/lib/server/product-defaults.mjs.map +1 -1
- package/dist/lib/server/redact.mjs +0 -6
- package/dist/lib/server/redact.mjs.map +1 -1
- package/dist/lib/server/responses.mjs +0 -6
- package/dist/lib/server/responses.mjs.map +1 -1
- package/dist/lib/server/serve.mjs +0 -6
- package/dist/lib/server/serve.mjs.map +1 -1
- package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
- package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
- package/dist/lib/server/socket-mode/index.mjs +0 -6
- package/dist/lib/server/socket-mode/index.mjs.map +1 -1
- package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
- package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
- package/dist/lib/server/state-machine.mjs +0 -6
- package/dist/lib/server/state-machine.mjs.map +1 -1
- package/dist/lib/server/state-store.mjs +0 -6
- package/dist/lib/server/state-store.mjs.map +1 -1
- package/dist/lib/server/structured-serialize.mjs +0 -6
- package/dist/lib/server/structured-serialize.mjs.map +1 -1
- package/dist/lib/server/targeting-helpers.mjs +0 -6
- package/dist/lib/server/targeting-helpers.mjs.map +1 -1
- package/dist/lib/server/tasks.mjs +0 -6
- package/dist/lib/server/tasks.mjs.map +1 -1
- package/dist/lib/server/test-controller-bridge.mjs +0 -6
- package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
- package/dist/lib/server/test-controller.mjs +0 -6
- package/dist/lib/server/test-controller.mjs.map +1 -1
- package/dist/lib/server/upstream-helpers.mjs +0 -6
- package/dist/lib/server/upstream-helpers.mjs.map +1 -1
- package/dist/lib/server/webhook-emitter.mjs +0 -6
- package/dist/lib/server/webhook-emitter.mjs.map +1 -1
- package/dist/lib/server/wire-safe.mjs +0 -6
- package/dist/lib/server/wire-safe.mjs.map +1 -1
- package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
- package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
- package/dist/lib/server/wrap-envelope.mjs +0 -6
- package/dist/lib/server/wrap-envelope.mjs.map +1 -1
- package/dist/lib/signing/agent-context.mjs +0 -6
- package/dist/lib/signing/agent-context.mjs.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +0 -6
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
- package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
- package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
- package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
- package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/index.mjs +0 -6
- package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
- package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
- package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
- package/dist/lib/signing/brand-jwks.mjs +0 -6
- package/dist/lib/signing/brand-jwks.mjs.map +1 -1
- package/dist/lib/signing/canonicalize.mjs +0 -6
- package/dist/lib/signing/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/capability-cache.mjs +0 -6
- package/dist/lib/signing/capability-cache.mjs.map +1 -1
- package/dist/lib/signing/capability-priming.mjs +0 -6
- package/dist/lib/signing/capability-priming.mjs.map +1 -1
- package/dist/lib/signing/client.mjs +0 -6
- package/dist/lib/signing/client.mjs.map +1 -1
- package/dist/lib/signing/content-digest.mjs +0 -6
- package/dist/lib/signing/content-digest.mjs.map +1 -1
- package/dist/lib/signing/crypto.mjs +0 -6
- package/dist/lib/signing/crypto.mjs.map +1 -1
- package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
- package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
- package/dist/lib/signing/errors.mjs +0 -6
- package/dist/lib/signing/errors.mjs.map +1 -1
- package/dist/lib/signing/fetch-async.mjs +0 -6
- package/dist/lib/signing/fetch-async.mjs.map +1 -1
- package/dist/lib/signing/fetch.mjs +0 -6
- package/dist/lib/signing/fetch.mjs.map +1 -1
- package/dist/lib/signing/index.mjs +0 -6
- package/dist/lib/signing/index.mjs.map +1 -1
- package/dist/lib/signing/jwks-helpers.mjs +0 -6
- package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
- package/dist/lib/signing/jwks-https.mjs +0 -6
- package/dist/lib/signing/jwks-https.mjs.map +1 -1
- package/dist/lib/signing/jwks.mjs +0 -6
- package/dist/lib/signing/jwks.mjs.map +1 -1
- package/dist/lib/signing/middleware.mjs +0 -6
- package/dist/lib/signing/middleware.mjs.map +1 -1
- package/dist/lib/signing/parser.mjs +0 -6
- package/dist/lib/signing/parser.mjs.map +1 -1
- package/dist/lib/signing/postgres-replay-store.mjs +0 -6
- package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
- package/dist/lib/signing/protocol-response.mjs +0 -6
- package/dist/lib/signing/protocol-response.mjs.map +1 -1
- package/dist/lib/signing/provider.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
- package/dist/lib/signing/replay.mjs +0 -6
- package/dist/lib/signing/replay.mjs.map +1 -1
- package/dist/lib/signing/request-context.mjs +0 -6
- package/dist/lib/signing/request-context.mjs.map +1 -1
- package/dist/lib/signing/revocation-https.mjs +0 -6
- package/dist/lib/signing/revocation-https.mjs.map +1 -1
- package/dist/lib/signing/revocation.mjs +0 -6
- package/dist/lib/signing/revocation.mjs.map +1 -1
- package/dist/lib/signing/server.mjs +0 -6
- package/dist/lib/signing/server.mjs.map +1 -1
- package/dist/lib/signing/signer-async.mjs +0 -6
- package/dist/lib/signing/signer-async.mjs.map +1 -1
- package/dist/lib/signing/signer.mjs +0 -6
- package/dist/lib/signing/signer.mjs.map +1 -1
- package/dist/lib/signing/testing.mjs +0 -6
- package/dist/lib/signing/testing.mjs.map +1 -1
- package/dist/lib/signing/types.mjs +0 -6
- package/dist/lib/signing/types.mjs.map +1 -1
- package/dist/lib/signing/verifier.mjs +0 -6
- package/dist/lib/signing/verifier.mjs.map +1 -1
- package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
- package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
- package/dist/lib/signing/webhook-verifier.mjs +0 -6
- package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
- package/dist/lib/storage/MemoryStorage.mjs +0 -6
- package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
- package/dist/lib/storage/interfaces.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
- package/dist/lib/substitution/encoder/index.mjs +0 -6
- package/dist/lib/substitution/encoder/index.mjs.map +1 -1
- package/dist/lib/substitution/index.mjs +0 -6
- package/dist/lib/substitution/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
- package/dist/lib/substitution/observer/alignment.mjs +0 -6
- package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
- package/dist/lib/substitution/observer/assertions.mjs +0 -6
- package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
- package/dist/lib/substitution/observer/html-parser.mjs +0 -6
- package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
- package/dist/lib/substitution/observer/index.mjs +0 -6
- package/dist/lib/substitution/observer/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/ssrf.mjs +0 -6
- package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
- package/dist/lib/substitution/rfc3986.mjs +0 -6
- package/dist/lib/substitution/rfc3986.mjs.map +1 -1
- package/dist/lib/substitution/translate.mjs +0 -6
- package/dist/lib/substitution/translate.mjs.map +1 -1
- package/dist/lib/substitution/types.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs.map +1 -1
- package/dist/lib/testing/agent-tester.mjs +0 -6
- package/dist/lib/testing/agent-tester.mjs.map +1 -1
- package/dist/lib/testing/client.mjs +0 -6
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/compliance/briefs.mjs +0 -6
- package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +0 -6
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.mjs +0 -6
- package/dist/lib/testing/compliance/index.mjs.map +1 -1
- package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
- package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
- package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
- package/dist/lib/testing/compliance/summary.mjs +0 -6
- package/dist/lib/testing/compliance/summary.mjs.map +1 -1
- package/dist/lib/testing/compliance/types.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs.map +1 -1
- package/dist/lib/testing/controller-assertions.mjs +0 -6
- package/dist/lib/testing/controller-assertions.mjs.map +1 -1
- package/dist/lib/testing/formatter.mjs +0 -6
- package/dist/lib/testing/formatter.mjs.map +1 -1
- package/dist/lib/testing/index.mjs +0 -6
- package/dist/lib/testing/index.mjs.map +1 -1
- package/dist/lib/testing/local-agent-runner.mjs +0 -6
- package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
- package/dist/lib/testing/orchestrator.mjs +0 -6
- package/dist/lib/testing/orchestrator.mjs.map +1 -1
- package/dist/lib/testing/personas/index.mjs +0 -6
- package/dist/lib/testing/personas/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
- package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
- package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
- package/dist/lib/testing/scenarios/creative.mjs +0 -6
- package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
- package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
- package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
- package/dist/lib/testing/scenarios/discovery.mjs +0 -6
- package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
- package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
- package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/governance.mjs +0 -6
- package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/health.mjs +0 -6
- package/dist/lib/testing/scenarios/health.mjs.map +1 -1
- package/dist/lib/testing/scenarios/index.mjs +0 -6
- package/dist/lib/testing/scenarios/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
- package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/signals.mjs +0 -6
- package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
- package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
- package/dist/lib/testing/seed-merge.mjs +0 -6
- package/dist/lib/testing/seed-merge.mjs.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
- package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
- package/dist/lib/testing/storyboard/assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
- package/dist/lib/testing/storyboard/compliance.mjs +5 -6
- package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
- package/dist/lib/testing/storyboard/context.mjs +0 -6
- package/dist/lib/testing/storyboard/context.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs +0 -6
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/junit.mjs +0 -6
- package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +0 -6
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/path.mjs +0 -6
- package/dist/lib/testing/storyboard/path.mjs.map +1 -1
- package/dist/lib/testing/storyboard/probes.mjs +0 -6
- package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +0 -6
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
- package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
- package/dist/lib/testing/storyboard/seeding.mjs +0 -6
- package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +0 -6
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs +0 -6
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +0 -6
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
- package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
- package/dist/lib/testing/stubs/index.mjs +0 -6
- package/dist/lib/testing/stubs/index.mjs.map +1 -1
- package/dist/lib/testing/test-controller.mjs +0 -6
- package/dist/lib/testing/test-controller.mjs.map +1 -1
- package/dist/lib/testing/test-helpers.mjs +0 -6
- package/dist/lib/testing/test-helpers.mjs.map +1 -1
- package/dist/lib/testing/types.mjs +0 -6
- package/dist/lib/types/adcp.mjs +0 -6
- package/dist/lib/types/adcp.mjs.map +1 -1
- package/dist/lib/types/asset-instances.mjs +0 -6
- package/dist/lib/types/compat.mjs +0 -6
- package/dist/lib/types/compat.mjs.map +1 -1
- package/dist/lib/types/core.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs.map +1 -1
- package/dist/lib/types/error-codes.mjs +0 -6
- package/dist/lib/types/error-codes.mjs.map +1 -1
- package/dist/lib/types/error-details.aliases.mjs +0 -6
- package/dist/lib/types/error-details.aliases.mjs.map +1 -1
- package/dist/lib/types/format-asset-slots.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
- package/dist/lib/types/index.mjs +0 -6
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/inline-enums.aliases.mjs +0 -6
- package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
- package/dist/lib/types/inline-enums.generated.mjs +0 -6
- package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
- package/dist/lib/types/manifest.generated.mjs +0 -6
- package/dist/lib/types/manifest.generated.mjs.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +0 -6
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.mjs +0 -6
- package/dist/lib/types/server-payload.mjs +0 -6
- package/dist/lib/types/sync-rows.mjs +0 -6
- package/dist/lib/types/tools.generated.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs.map +1 -1
- package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
- package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
- package/dist/lib/upstream-recorder/constants.mjs +0 -6
- package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
- package/dist/lib/upstream-recorder/index.mjs +0 -6
- package/dist/lib/upstream-recorder/index.mjs.map +1 -1
- package/dist/lib/upstream-recorder/recorder.mjs +0 -6
- package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
- package/dist/lib/upstream-recorder/types.mjs +0 -6
- package/dist/lib/upstream-recorder/types.mjs.map +1 -1
- package/dist/lib/utils/a2a-artifacts.mjs +0 -6
- package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
- package/dist/lib/utils/a2a-discovery.mjs +0 -6
- package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
- package/dist/lib/utils/activation-key-builders.mjs +0 -6
- package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
- package/dist/lib/utils/adcp-version-config.mjs +0 -6
- package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
- package/dist/lib/utils/asset-builders.mjs +0 -6
- package/dist/lib/utils/asset-builders.mjs.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
- package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
- package/dist/lib/utils/capabilities.mjs +0 -6
- package/dist/lib/utils/capabilities.mjs.map +1 -1
- package/dist/lib/utils/capability-rollups.mjs +0 -6
- package/dist/lib/utils/capability-rollups.mjs.map +1 -1
- package/dist/lib/utils/creative-adapter.mjs +0 -6
- package/dist/lib/utils/creative-adapter.mjs.map +1 -1
- package/dist/lib/utils/creative-delivery.mjs +0 -6
- package/dist/lib/utils/creative-delivery.mjs.map +1 -1
- package/dist/lib/utils/deprecation.mjs +0 -6
- package/dist/lib/utils/deprecation.mjs.map +1 -1
- package/dist/lib/utils/envelope-status-compat.mjs +0 -6
- package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
- package/dist/lib/utils/error-extraction.mjs +0 -6
- package/dist/lib/utils/error-extraction.mjs.map +1 -1
- package/dist/lib/utils/extract-result.mjs +0 -6
- package/dist/lib/utils/extract-result.mjs.map +1 -1
- package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
- package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
- package/dist/lib/utils/format-assets.mjs +0 -6
- package/dist/lib/utils/format-assets.mjs.map +1 -1
- package/dist/lib/utils/format-render-builders.mjs +0 -6
- package/dist/lib/utils/format-render-builders.mjs.map +1 -1
- package/dist/lib/utils/format-renders.mjs +0 -6
- package/dist/lib/utils/format-renders.mjs.map +1 -1
- package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
- package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
- package/dist/lib/utils/glob.mjs +0 -6
- package/dist/lib/utils/glob.mjs.map +1 -1
- package/dist/lib/utils/global-async-local-storage.mjs +0 -6
- package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
- package/dist/lib/utils/idempotency.mjs +0 -6
- package/dist/lib/utils/idempotency.mjs.map +1 -1
- package/dist/lib/utils/index.mjs +0 -6
- package/dist/lib/utils/index.mjs.map +1 -1
- package/dist/lib/utils/jcs.mjs +0 -6
- package/dist/lib/utils/jcs.mjs.map +1 -1
- package/dist/lib/utils/json-depth.mjs +0 -6
- package/dist/lib/utils/json-depth.mjs.map +1 -1
- package/dist/lib/utils/logger.mjs +0 -6
- package/dist/lib/utils/logger.mjs.map +1 -1
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
- package/dist/lib/utils/media-buy-status.mjs +0 -6
- package/dist/lib/utils/media-buy-status.mjs.map +1 -1
- package/dist/lib/utils/pagination.mjs +0 -6
- package/dist/lib/utils/pagination.mjs.map +1 -1
- package/dist/lib/utils/preview-creative-builders.mjs +0 -6
- package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
- package/dist/lib/utils/preview-normalizer.mjs +0 -6
- package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
- package/dist/lib/utils/preview-utils.mjs +0 -6
- package/dist/lib/utils/preview-utils.mjs.map +1 -1
- package/dist/lib/utils/pricing-adapter.mjs +0 -6
- package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
- package/dist/lib/utils/probe-policy.mjs +0 -6
- package/dist/lib/utils/probe-policy.mjs.map +1 -1
- package/dist/lib/utils/protocol-detection.mjs +0 -6
- package/dist/lib/utils/protocol-detection.mjs.map +1 -1
- package/dist/lib/utils/redact-secrets.mjs +0 -6
- package/dist/lib/utils/redact-secrets.mjs.map +1 -1
- package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
- package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
- package/dist/lib/utils/render-builders.mjs +0 -6
- package/dist/lib/utils/render-builders.mjs.map +1 -1
- package/dist/lib/utils/request-normalizer.mjs +0 -6
- package/dist/lib/utils/request-normalizer.mjs.map +1 -1
- package/dist/lib/utils/response-schemas.mjs +0 -6
- package/dist/lib/utils/response-schemas.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +0 -6
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/utils/retry.mjs +0 -6
- package/dist/lib/utils/retry.mjs.map +1 -1
- package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
- package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
- package/dist/lib/utils/signal-id-builders.mjs +0 -6
- package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
- package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
- package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
- package/dist/lib/utils/task-state.mjs +0 -6
- package/dist/lib/utils/task-state.mjs.map +1 -1
- package/dist/lib/utils/tool-request-schemas.mjs +0 -6
- package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
- package/dist/lib/utils/typeGuards.mjs +0 -6
- package/dist/lib/utils/typeGuards.mjs.map +1 -1
- package/dist/lib/utils/union-errors.mjs +0 -6
- package/dist/lib/utils/union-errors.mjs.map +1 -1
- package/dist/lib/utils/validate-user-agent.mjs +0 -6
- package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
- package/dist/lib/v2/format-schema/fetch.mjs +0 -6
- package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
- package/dist/lib/v2/format-schema/index.mjs +0 -6
- package/dist/lib/v2/format-schema/index.mjs.map +1 -1
- package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
- package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
- package/dist/lib/v2/format-schema/resolver.mjs +7 -8
- package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
- package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
- package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
- package/dist/lib/v2/projection/augment-response.mjs +0 -6
- package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
- package/dist/lib/v2/projection/builders.mjs +0 -6
- package/dist/lib/v2/projection/builders.mjs.map +1 -1
- package/dist/lib/v2/projection/cache-versions.mjs +0 -6
- package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
- package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
- package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
- package/dist/lib/v2/projection/catalog.mjs +5 -6
- package/dist/lib/v2/projection/catalog.mjs.map +1 -1
- package/dist/lib/v2/projection/constants.mjs +0 -6
- package/dist/lib/v2/projection/constants.mjs.map +1 -1
- package/dist/lib/v2/projection/index.mjs +0 -6
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/registry.mjs +5 -6
- package/dist/lib/v2/projection/registry.mjs.map +1 -1
- package/dist/lib/v2/projection/types.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
- package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
- package/dist/lib/v2/projection/write-side.mjs +0 -6
- package/dist/lib/v2/projection/write-side.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
- package/dist/lib/validation/client-hooks.mjs +0 -6
- package/dist/lib/validation/client-hooks.mjs.map +1 -1
- package/dist/lib/validation/hints.mjs +0 -6
- package/dist/lib/validation/hints.mjs.map +1 -1
- package/dist/lib/validation/index.mjs +0 -6
- package/dist/lib/validation/index.mjs.map +1 -1
- package/dist/lib/validation/schema-errors.mjs +0 -6
- package/dist/lib/validation/schema-errors.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +5 -6
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/validation/schema-validator.mjs +0 -6
- package/dist/lib/validation/schema-validator.mjs.map +1 -1
- package/dist/lib/validation/sync-creatives.mjs +0 -6
- package/dist/lib/validation/sync-creatives.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -9
- package/dist/lib/version.mjs.map +1 -1
- package/dist/lib/webhooks/index.mjs +0 -6
- package/dist/lib/webhooks/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/adcp-version-config.ts"],"sourcesContent":["// Validation helpers for the per-instance `adcpVersion` constructor option.\n//\n// Stage 2 plumbed the option onto every client/server constructor with a\n// fence: cross-major pins were rejected at construction because the wire\n// field and validators still keyed off the global `ADCP_MAJOR_VERSION`.\n//\n// Stage 3 lifts that fence. Validators now key off the resolved bundle in\n// `dist/lib/schemas-data/<MAJOR.MINOR>/`, and the protocol layer derives\n// the wire-level `adcp_major_version` from the per-instance pin. Construction\n// now accepts any pin that has a schema bundle reachable from the SDK build,\n// and rejects pins for which no bundle is present (`'4.0.0'` while the SDK\n// only ships major-3 schemas, mistyped versions, etc.) with a clear pointer\n// at `sync-schemas` + `build:lib`.\n\nimport { ADCP_VERSION, COMPATIBLE_ADCP_VERSIONS, parseAdcpMajorVersion } from '../version';\nimport { ConfigurationError } from '../errors';\nimport { hasSchemaBundle, resolveBundleKey, toReleasePrecisionWire } from '../validation/schema-loader';\n\n/**\n * Resolve and validate a configured `adcpVersion`. Returns the value to store\n * on the instance — either the caller's pin or the SDK default.\n *\n * Throws `ConfigurationError` when:\n * - The pin is unparseable as a semver / legacy alias\n * - The pin parses but no schema bundle exists for the resolved key\n *\n * Cross-major pins are accepted as long as the corresponding bundle ships\n * with this SDK build (e.g. `'3.1.0-beta.1'` when `dist/lib/schemas-data/\n * 3.1.0-beta.1/` exists). Pins of the SDK's currently-pinned `ADCP_VERSION`\n * always succeed without an fs check — the bundle is guaranteed.\n */\nexport function resolveAdcpVersion(adcpVersion: string | undefined): string {\n if (adcpVersion === undefined) return ADCP_VERSION;\n\n const major = parseAdcpMajorVersion(adcpVersion);\n if (!Number.isFinite(major)) {\n throw new ConfigurationError(\n `adcpVersion ${JSON.stringify(adcpVersion)} is not a valid AdCP version. ` +\n `Expected a semver string (e.g. '3.0.1', '3.1.0-beta.1') or a legacy alias. ` +\n `Currently bundled: ${listBundledVersions().join(', ')}.`,\n 'adcpVersion'\n );\n }\n\n // Skip the bundle-existence check when the pin resolves to the same bundle\n // as the SDK default — every published tarball includes that bundle by\n // construction. The bundle-key compare (rather than literal-string compare)\n // catches the common patterns: `'3.0'`, `'3.0.0'`, and `'3.0.1'` all\n // resolve to the same `'3.0'` bundle when `ADCP_VERSION === '3.0.1'`, so\n // none of those paths pay an fs round-trip.\n if (resolveBundleKey(adcpVersion) === resolveBundleKey(ADCP_VERSION)) return adcpVersion;\n\n if (!hasSchemaBundle(adcpVersion)) {\n const resolvedKey = resolveBundleKey(adcpVersion);\n throw new ConfigurationError(\n `adcpVersion ${JSON.stringify(adcpVersion)} resolves to bundle key \"${resolvedKey}\", ` +\n `but no schema bundle for that key ships with this SDK build. ` +\n `Currently bundled: ${listBundledVersions().join(', ')}. ` +\n `If you're testing against a beta that the spec repo has tagged but the SDK hasn't synced yet, ` +\n `run \\`npm run sync-schemas\\` and \\`npm run build:lib\\` to populate the cache, ` +\n `then re-construct.`,\n 'adcpVersion'\n );\n }\n\n return adcpVersion;\n}\n\nexport function adcpVersionAliases(version: string, includeFamilyAlias = true): Set<string> {\n const aliases = new Set<string>([version]);\n const add = (value: string) => {\n aliases.add(value);\n if (includeFamilyAlias) {\n const family = prereleaseFamilyAlias(value);\n if (family) aliases.add(family);\n }\n };\n\n try {\n add(resolveBundleKey(version));\n } catch {\n // Keep the raw version only; the caller will report the mismatch.\n }\n try {\n add(toReleasePrecisionWire(version));\n } catch {\n // Keep the raw version only; the caller will report the mismatch.\n }\n return aliases;\n}\n\nexport function isAdcpVersionSupported(version: string, supportedVersions: readonly string[]): boolean {\n if (supportedVersions.length === 0) return true;\n const aliases = adcpVersionAliases(version);\n return supportedVersions.some(v => {\n for (const supportedAlias of adcpVersionAliases(v, false)) {\n if (aliases.has(supportedAlias)) return true;\n }\n return false;\n });\n}\n\nexport function isPre31AdcpVersion(version: string | undefined): boolean {\n if (version === undefined) return false;\n const trimmed = version.trim();\n if (trimmed.length === 0) return false;\n\n const withoutLegacyPrefix = trimmed.startsWith('v') ? trimmed.slice(1) : trimmed;\n const match = /^(\\d+)(?:\\.(\\d+))?/.exec(withoutLegacyPrefix);\n if (!match?.[1]) return false;\n\n const major = Number.parseInt(match[1], 10);\n if (!Number.isFinite(major)) return false;\n if (major < 3) return true;\n if (major > 3) return false;\n\n const minor = match[2] === undefined ? 0 : Number.parseInt(match[2], 10);\n return Number.isFinite(minor) && minor < 1;\n}\n\n/** Does the seller advertise AdCP 3.1+ support (via get_adcp_capabilities)? */\nexport function sellerAdvertises31(caps: { supportedVersions?: string[]; buildVersion?: string } | undefined): boolean {\n if (!caps) return false;\n if (caps.buildVersion && !isPre31AdcpVersion(caps.buildVersion)) return true;\n return (caps.supportedVersions ?? []).some(v => !isPre31AdcpVersion(v));\n}\n\n/**\n * Whether to omit AdCP 3.1-only request fields from the wire. Omit when the\n * client is pinned below 3.1, or when the seller does not advertise 3.1\n * support (legacy 3.0 sellers, and sellers whose capabilities were synthesized\n * from a tool list rather than declared).\n */\nexport function shouldOmit31Fields(\n resolvedClientVersion: string | undefined,\n caps: { supportedVersions?: string[]; buildVersion?: string } | undefined\n): boolean {\n if (isPre31AdcpVersion(resolvedClientVersion)) return true;\n return !sellerAdvertises31(caps);\n}\n\n/**\n * Strip the AdCP 3.1-only `brand_kit_override` field from a BrandReference.\n * `industries` and `data_subject_contestation` are declared in AdCP 3.0 and\n * must be left on the wire for 3.0 sellers that accept and route on them.\n * Returns the original reference unchanged when `brand_kit_override` is absent.\n */\nexport function omit31BrandFields<T>(brand: T): T {\n if (!brand || typeof brand !== 'object' || Array.isArray(brand)) return brand;\n const b = brand as Record<string, unknown>;\n if (!('brand_kit_override' in b)) return brand;\n const { brand_kit_override, ...rest } = b;\n return rest as T;\n}\n\nfunction prereleaseFamilyAlias(version: string): string | undefined {\n const match = /^(\\d+\\.\\d+-[0-9A-Za-z-]+)\\.\\d+$/.exec(version);\n return match?.[1];\n}\n\n/**\n * Filter `COMPATIBLE_ADCP_VERSIONS` to entries with a shipped bundle on this\n * SDK build. The compatibility list is the historical set of accepted version\n * strings (legacy aliases, superseded betas, current GA), but only a subset\n * has bundles in `dist/lib/schemas-data/` at any given build. Returning\n * \"currently bundled: v2.5, v2.6, v3, 3.0.0-beta.3, 3.0.0, 3.0.1\" would\n * mislead a caller who pinned `'v2.5'` and got \"no bundle\".\n *\n * Always includes `ADCP_VERSION` even when its bundle hasn't been built yet\n * (dev-tree case) so the error remains actionable on first build.\n */\nfunction listBundledVersions(): string[] {\n const bundled = COMPATIBLE_ADCP_VERSIONS.filter(v => hasSchemaBundle(v));\n if (!bundled.includes(ADCP_VERSION as (typeof COMPATIBLE_ADCP_VERSIONS)[number])) {\n return [ADCP_VERSION, ...bundled];\n }\n return [...bundled];\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/adcp-version-config.ts"],"sourcesContent":["// Validation helpers for the per-instance `adcpVersion` constructor option.\n//\n// Stage 2 plumbed the option onto every client/server constructor with a\n// fence: cross-major pins were rejected at construction because the wire\n// field and validators still keyed off the global `ADCP_MAJOR_VERSION`.\n//\n// Stage 3 lifts that fence. Validators now key off the resolved bundle in\n// `dist/lib/schemas-data/<MAJOR.MINOR>/`, and the protocol layer derives\n// the wire-level `adcp_major_version` from the per-instance pin. Construction\n// now accepts any pin that has a schema bundle reachable from the SDK build,\n// and rejects pins for which no bundle is present (`'4.0.0'` while the SDK\n// only ships major-3 schemas, mistyped versions, etc.) with a clear pointer\n// at `sync-schemas` + `build:lib`.\n\nimport { ADCP_VERSION, COMPATIBLE_ADCP_VERSIONS, parseAdcpMajorVersion } from '../version';\nimport { ConfigurationError } from '../errors';\nimport { hasSchemaBundle, resolveBundleKey, toReleasePrecisionWire } from '../validation/schema-loader';\n\n/**\n * Resolve and validate a configured `adcpVersion`. Returns the value to store\n * on the instance — either the caller's pin or the SDK default.\n *\n * Throws `ConfigurationError` when:\n * - The pin is unparseable as a semver / legacy alias\n * - The pin parses but no schema bundle exists for the resolved key\n *\n * Cross-major pins are accepted as long as the corresponding bundle ships\n * with this SDK build (e.g. `'3.1.0-beta.1'` when `dist/lib/schemas-data/\n * 3.1.0-beta.1/` exists). Pins of the SDK's currently-pinned `ADCP_VERSION`\n * always succeed without an fs check — the bundle is guaranteed.\n */\nexport function resolveAdcpVersion(adcpVersion: string | undefined): string {\n if (adcpVersion === undefined) return ADCP_VERSION;\n\n const major = parseAdcpMajorVersion(adcpVersion);\n if (!Number.isFinite(major)) {\n throw new ConfigurationError(\n `adcpVersion ${JSON.stringify(adcpVersion)} is not a valid AdCP version. ` +\n `Expected a semver string (e.g. '3.0.1', '3.1.0-beta.1') or a legacy alias. ` +\n `Currently bundled: ${listBundledVersions().join(', ')}.`,\n 'adcpVersion'\n );\n }\n\n // Skip the bundle-existence check when the pin resolves to the same bundle\n // as the SDK default — every published tarball includes that bundle by\n // construction. The bundle-key compare (rather than literal-string compare)\n // catches the common patterns: `'3.0'`, `'3.0.0'`, and `'3.0.1'` all\n // resolve to the same `'3.0'` bundle when `ADCP_VERSION === '3.0.1'`, so\n // none of those paths pay an fs round-trip.\n if (resolveBundleKey(adcpVersion) === resolveBundleKey(ADCP_VERSION)) return adcpVersion;\n\n if (!hasSchemaBundle(adcpVersion)) {\n const resolvedKey = resolveBundleKey(adcpVersion);\n throw new ConfigurationError(\n `adcpVersion ${JSON.stringify(adcpVersion)} resolves to bundle key \"${resolvedKey}\", ` +\n `but no schema bundle for that key ships with this SDK build. ` +\n `Currently bundled: ${listBundledVersions().join(', ')}. ` +\n `If you're testing against a beta that the spec repo has tagged but the SDK hasn't synced yet, ` +\n `run \\`npm run sync-schemas\\` and \\`npm run build:lib\\` to populate the cache, ` +\n `then re-construct.`,\n 'adcpVersion'\n );\n }\n\n return adcpVersion;\n}\n\nexport function adcpVersionAliases(version: string, includeFamilyAlias = true): Set<string> {\n const aliases = new Set<string>([version]);\n const add = (value: string) => {\n aliases.add(value);\n if (includeFamilyAlias) {\n const family = prereleaseFamilyAlias(value);\n if (family) aliases.add(family);\n }\n };\n\n try {\n add(resolveBundleKey(version));\n } catch {\n // Keep the raw version only; the caller will report the mismatch.\n }\n try {\n add(toReleasePrecisionWire(version));\n } catch {\n // Keep the raw version only; the caller will report the mismatch.\n }\n return aliases;\n}\n\nexport function isAdcpVersionSupported(version: string, supportedVersions: readonly string[]): boolean {\n if (supportedVersions.length === 0) return true;\n const aliases = adcpVersionAliases(version);\n return supportedVersions.some(v => {\n for (const supportedAlias of adcpVersionAliases(v, false)) {\n if (aliases.has(supportedAlias)) return true;\n }\n return false;\n });\n}\n\nexport function isPre31AdcpVersion(version: string | undefined): boolean {\n if (version === undefined) return false;\n const trimmed = version.trim();\n if (trimmed.length === 0) return false;\n\n const withoutLegacyPrefix = trimmed.startsWith('v') ? trimmed.slice(1) : trimmed;\n const match = /^(\\d+)(?:\\.(\\d+))?/.exec(withoutLegacyPrefix);\n if (!match?.[1]) return false;\n\n const major = Number.parseInt(match[1], 10);\n if (!Number.isFinite(major)) return false;\n if (major < 3) return true;\n if (major > 3) return false;\n\n const minor = match[2] === undefined ? 0 : Number.parseInt(match[2], 10);\n return Number.isFinite(minor) && minor < 1;\n}\n\n/** Does the seller advertise AdCP 3.1+ support (via get_adcp_capabilities)? */\nexport function sellerAdvertises31(caps: { supportedVersions?: string[]; buildVersion?: string } | undefined): boolean {\n if (!caps) return false;\n if (caps.buildVersion && !isPre31AdcpVersion(caps.buildVersion)) return true;\n return (caps.supportedVersions ?? []).some(v => !isPre31AdcpVersion(v));\n}\n\n/**\n * Whether to omit AdCP 3.1-only request fields from the wire. Omit when the\n * client is pinned below 3.1, or when the seller does not advertise 3.1\n * support (legacy 3.0 sellers, and sellers whose capabilities were synthesized\n * from a tool list rather than declared).\n */\nexport function shouldOmit31Fields(\n resolvedClientVersion: string | undefined,\n caps: { supportedVersions?: string[]; buildVersion?: string } | undefined\n): boolean {\n if (isPre31AdcpVersion(resolvedClientVersion)) return true;\n return !sellerAdvertises31(caps);\n}\n\n/**\n * Strip the AdCP 3.1-only `brand_kit_override` field from a BrandReference.\n * `industries` and `data_subject_contestation` are declared in AdCP 3.0 and\n * must be left on the wire for 3.0 sellers that accept and route on them.\n * Returns the original reference unchanged when `brand_kit_override` is absent.\n */\nexport function omit31BrandFields<T>(brand: T): T {\n if (!brand || typeof brand !== 'object' || Array.isArray(brand)) return brand;\n const b = brand as Record<string, unknown>;\n if (!('brand_kit_override' in b)) return brand;\n const { brand_kit_override, ...rest } = b;\n return rest as T;\n}\n\nfunction prereleaseFamilyAlias(version: string): string | undefined {\n const match = /^(\\d+\\.\\d+-[0-9A-Za-z-]+)\\.\\d+$/.exec(version);\n return match?.[1];\n}\n\n/**\n * Filter `COMPATIBLE_ADCP_VERSIONS` to entries with a shipped bundle on this\n * SDK build. The compatibility list is the historical set of accepted version\n * strings (legacy aliases, superseded betas, current GA), but only a subset\n * has bundles in `dist/lib/schemas-data/` at any given build. Returning\n * \"currently bundled: v2.5, v2.6, v3, 3.0.0-beta.3, 3.0.0, 3.0.1\" would\n * mislead a caller who pinned `'v2.5'` and got \"no bundle\".\n *\n * Always includes `ADCP_VERSION` even when its bundle hasn't been built yet\n * (dev-tree case) so the error remains actionable on first build.\n */\nfunction listBundledVersions(): string[] {\n const bundled = COMPATIBLE_ADCP_VERSIONS.filter(v => hasSchemaBundle(v));\n if (!bundled.includes(ADCP_VERSION as (typeof COMPATIBLE_ADCP_VERSIONS)[number])) {\n return [ADCP_VERSION, ...bundled];\n }\n return [...bundled];\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
function imageAsset(fields) {
|
|
8
2
|
return { ...fields, asset_type: "image" };
|
|
9
3
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/asset-builders.ts"],"sourcesContent":["// Typed factory helpers for creative asset objects.\n//\n// Every asset interface in the schema carries an `asset_type` literal\n// discriminator (e.g. `asset_type: 'image'`) that's always the canonical\n// tag for its class. Requiring callers to type it by hand is boilerplate\n// that the compiler already knows the answer to. These builders take the\n// rest of the asset shape and inject the discriminator, so\n// `imageAsset({ url, width, height })` produces a valid `ImageAsset`\n// without repeating `asset_type: 'image'` at every call site.\n\nimport type {\n AudioAsset,\n CSSAsset,\n HTMLAsset,\n ImageAsset,\n JavaScriptAsset,\n MarkdownAsset,\n TextAsset,\n URLAsset,\n VideoAsset,\n WebhookAsset,\n} from '../types/tools.generated';\n\n// Intersecting with `{ asset_type: Tag }` instead of relying on the imported\n// type's own discriminator keeps these builders robust across schema\n// regenerations, whether or not the generated interface carries the tag.\ntype Tagged<T, Tag extends string> = Omit<T, 'asset_type'> & { asset_type: Tag };\n\n// Spread order matters: the discriminator is written last so a runtime\n// bypass (e.g. an `as unknown` cast that slips `asset_type` into `fields`)\n// can't clobber it.\n\n/** Build an `ImageAsset` with `asset_type: 'image'` injected. */\nexport function imageAsset(fields: Omit<ImageAsset, 'asset_type'>): Tagged<ImageAsset, 'image'> {\n return { ...fields, asset_type: 'image' };\n}\n\n/** Build a `VideoAsset` with `asset_type: 'video'` injected. */\nexport function videoAsset(fields: Omit<VideoAsset, 'asset_type'>): Tagged<VideoAsset, 'video'> {\n return { ...fields, asset_type: 'video' };\n}\n\n/** Build an `AudioAsset` with `asset_type: 'audio'` injected. */\nexport function audioAsset(fields: Omit<AudioAsset, 'asset_type'>): Tagged<AudioAsset, 'audio'> {\n return { ...fields, asset_type: 'audio' };\n}\n\n/** Build a `TextAsset` with `asset_type: 'text'` injected. */\nexport function textAsset(fields: Omit<TextAsset, 'asset_type'>): Tagged<TextAsset, 'text'> {\n return { ...fields, asset_type: 'text' };\n}\n\n/** Build a `URLAsset` with `asset_type: 'url'` injected. */\nexport function urlAsset(fields: Omit<URLAsset, 'asset_type'>): Tagged<URLAsset, 'url'> {\n return { ...fields, asset_type: 'url' };\n}\n\n/** Build an `HTMLAsset` with `asset_type: 'html'` injected. */\nexport function htmlAsset(fields: Omit<HTMLAsset, 'asset_type'>): Tagged<HTMLAsset, 'html'> {\n return { ...fields, asset_type: 'html' };\n}\n\n/** Build a `JavaScriptAsset` with `asset_type: 'javascript'` injected. */\nexport function javascriptAsset(fields: Omit<JavaScriptAsset, 'asset_type'>): Tagged<JavaScriptAsset, 'javascript'> {\n return { ...fields, asset_type: 'javascript' };\n}\n\n/** Build a `CSSAsset` with `asset_type: 'css'` injected. */\nexport function cssAsset(fields: Omit<CSSAsset, 'asset_type'>): Tagged<CSSAsset, 'css'> {\n return { ...fields, asset_type: 'css' };\n}\n\n/** Build a `MarkdownAsset` with `asset_type: 'markdown'` injected. */\nexport function markdownAsset(fields: Omit<MarkdownAsset, 'asset_type'>): Tagged<MarkdownAsset, 'markdown'> {\n return { ...fields, asset_type: 'markdown' };\n}\n\n/** Build a `WebhookAsset` with `asset_type: 'webhook'` injected. */\nexport function webhookAsset(fields: Omit<WebhookAsset, 'asset_type'>): Tagged<WebhookAsset, 'webhook'> {\n return { ...fields, asset_type: 'webhook' };\n}\n\n/**\n * Grouped accessor for every creative-asset builder. `Asset.image({...})`\n * reads better in assets-by-role manifests and gives one-dot autocomplete\n * over the whole family. The individual named exports remain the primary\n * entry points.\n */\nexport const Asset = {\n image: imageAsset,\n video: videoAsset,\n audio: audioAsset,\n text: textAsset,\n url: urlAsset,\n html: htmlAsset,\n javascript: javascriptAsset,\n css: cssAsset,\n markdown: markdownAsset,\n webhook: webhookAsset,\n} as const;\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/asset-builders.ts"],"sourcesContent":["// Typed factory helpers for creative asset objects.\n//\n// Every asset interface in the schema carries an `asset_type` literal\n// discriminator (e.g. `asset_type: 'image'`) that's always the canonical\n// tag for its class. Requiring callers to type it by hand is boilerplate\n// that the compiler already knows the answer to. These builders take the\n// rest of the asset shape and inject the discriminator, so\n// `imageAsset({ url, width, height })` produces a valid `ImageAsset`\n// without repeating `asset_type: 'image'` at every call site.\n\nimport type {\n AudioAsset,\n CSSAsset,\n HTMLAsset,\n ImageAsset,\n JavaScriptAsset,\n MarkdownAsset,\n TextAsset,\n URLAsset,\n VideoAsset,\n WebhookAsset,\n} from '../types/tools.generated';\n\n// Intersecting with `{ asset_type: Tag }` instead of relying on the imported\n// type's own discriminator keeps these builders robust across schema\n// regenerations, whether or not the generated interface carries the tag.\ntype Tagged<T, Tag extends string> = Omit<T, 'asset_type'> & { asset_type: Tag };\n\n// Spread order matters: the discriminator is written last so a runtime\n// bypass (e.g. an `as unknown` cast that slips `asset_type` into `fields`)\n// can't clobber it.\n\n/** Build an `ImageAsset` with `asset_type: 'image'` injected. */\nexport function imageAsset(fields: Omit<ImageAsset, 'asset_type'>): Tagged<ImageAsset, 'image'> {\n return { ...fields, asset_type: 'image' };\n}\n\n/** Build a `VideoAsset` with `asset_type: 'video'` injected. */\nexport function videoAsset(fields: Omit<VideoAsset, 'asset_type'>): Tagged<VideoAsset, 'video'> {\n return { ...fields, asset_type: 'video' };\n}\n\n/** Build an `AudioAsset` with `asset_type: 'audio'` injected. */\nexport function audioAsset(fields: Omit<AudioAsset, 'asset_type'>): Tagged<AudioAsset, 'audio'> {\n return { ...fields, asset_type: 'audio' };\n}\n\n/** Build a `TextAsset` with `asset_type: 'text'` injected. */\nexport function textAsset(fields: Omit<TextAsset, 'asset_type'>): Tagged<TextAsset, 'text'> {\n return { ...fields, asset_type: 'text' };\n}\n\n/** Build a `URLAsset` with `asset_type: 'url'` injected. */\nexport function urlAsset(fields: Omit<URLAsset, 'asset_type'>): Tagged<URLAsset, 'url'> {\n return { ...fields, asset_type: 'url' };\n}\n\n/** Build an `HTMLAsset` with `asset_type: 'html'` injected. */\nexport function htmlAsset(fields: Omit<HTMLAsset, 'asset_type'>): Tagged<HTMLAsset, 'html'> {\n return { ...fields, asset_type: 'html' };\n}\n\n/** Build a `JavaScriptAsset` with `asset_type: 'javascript'` injected. */\nexport function javascriptAsset(fields: Omit<JavaScriptAsset, 'asset_type'>): Tagged<JavaScriptAsset, 'javascript'> {\n return { ...fields, asset_type: 'javascript' };\n}\n\n/** Build a `CSSAsset` with `asset_type: 'css'` injected. */\nexport function cssAsset(fields: Omit<CSSAsset, 'asset_type'>): Tagged<CSSAsset, 'css'> {\n return { ...fields, asset_type: 'css' };\n}\n\n/** Build a `MarkdownAsset` with `asset_type: 'markdown'` injected. */\nexport function markdownAsset(fields: Omit<MarkdownAsset, 'asset_type'>): Tagged<MarkdownAsset, 'markdown'> {\n return { ...fields, asset_type: 'markdown' };\n}\n\n/** Build a `WebhookAsset` with `asset_type: 'webhook'` injected. */\nexport function webhookAsset(fields: Omit<WebhookAsset, 'asset_type'>): Tagged<WebhookAsset, 'webhook'> {\n return { ...fields, asset_type: 'webhook' };\n}\n\n/**\n * Grouped accessor for every creative-asset builder. `Asset.image({...})`\n * reads better in assets-by-role manifests and gives one-dot autocomplete\n * over the whole family. The individual named exports remain the primary\n * entry points.\n */\nexport const Asset = {\n image: imageAsset,\n video: videoAsset,\n audio: audioAsset,\n text: textAsset,\n url: urlAsset,\n html: htmlAsset,\n javascript: javascriptAsset,\n css: cssAsset,\n markdown: markdownAsset,\n webhook: webhookAsset,\n} as const;\n"],"mappings":"AAiCO,SAAS,WAAW,QAAqE;AAC9F,SAAO,EAAE,GAAG,QAAQ,YAAY,QAAQ;AAC1C;AAGO,SAAS,WAAW,QAAqE;AAC9F,SAAO,EAAE,GAAG,QAAQ,YAAY,QAAQ;AAC1C;AAGO,SAAS,WAAW,QAAqE;AAC9F,SAAO,EAAE,GAAG,QAAQ,YAAY,QAAQ;AAC1C;AAGO,SAAS,UAAU,QAAkE;AAC1F,SAAO,EAAE,GAAG,QAAQ,YAAY,OAAO;AACzC;AAGO,SAAS,SAAS,QAA+D;AACtF,SAAO,EAAE,GAAG,QAAQ,YAAY,MAAM;AACxC;AAGO,SAAS,UAAU,QAAkE;AAC1F,SAAO,EAAE,GAAG,QAAQ,YAAY,OAAO;AACzC;AAGO,SAAS,gBAAgB,QAAoF;AAClH,SAAO,EAAE,GAAG,QAAQ,YAAY,aAAa;AAC/C;AAGO,SAAS,SAAS,QAA+D;AACtF,SAAO,EAAE,GAAG,QAAQ,YAAY,MAAM;AACxC;AAGO,SAAS,cAAc,QAA8E;AAC1G,SAAO,EAAE,GAAG,QAAQ,YAAY,WAAW;AAC7C;AAGO,SAAS,aAAa,QAA2E;AACtG,SAAO,EAAE,GAAG,QAAQ,YAAY,UAAU;AAC5C;AAQO,MAAM,QAAQ;AAAA,EACnB,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,UAAU;AAAA,EACV,SAAS;AACX;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
function singleBuildCreativeReturn(manifest) {
|
|
8
2
|
return manifest;
|
|
9
3
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/build-creative-return-builders.ts"],"sourcesContent":["// Typed factory helpers for `build_creative` return values. Four shapes:\n// 1. bare `CreativeManifest` — auto-wrapped as `{ creative_manifest }`\n// 2. bare `CreativeManifest[]` — auto-wrapped as `{ creative_manifests }`\n// 3. shaped `BuildCreativeSuccess` — passthrough\n// 4. shaped `BuildCreativeMultiSuccess` — passthrough multi-format\n//\n// Adopters writing the shaped envelope by hand consistently miss the\n// distinction between single (`creative_manifest`) and multi\n// (`creative_manifests`) field names. SHAPE-GOTCHAS §5.\n\nimport type { BuildCreativeSuccess, BuildCreativeMultiSuccess, CreativeManifest } from '../types/core.generated';\n\ntype SingleEnvelopeFields = Omit<BuildCreativeSuccess, 'creative_manifest'> & { manifest: CreativeManifest };\ntype MultiEnvelopeFields = Omit<BuildCreativeMultiSuccess, 'creative_manifests'> & { manifests: CreativeManifest[] };\n\n/** Bare single-format manifest. Framework wraps as `{ creative_manifest }`. */\nexport function singleBuildCreativeReturn(manifest: CreativeManifest): CreativeManifest {\n return manifest;\n}\n\n/** Bare multi-format manifest array. Framework wraps as `{ creative_manifests }`. */\nexport function multiBuildCreativeReturn(manifests: CreativeManifest[]): CreativeManifest[] {\n return manifests;\n}\n\n/** Shaped `BuildCreativeSuccess`. `manifest` field renamed to `creative_manifest` on wire. */\nexport function singleEnvelopedBuildCreativeReturn(fields: SingleEnvelopeFields): BuildCreativeSuccess {\n const { manifest, ...rest } = fields;\n return { ...rest, creative_manifest: manifest };\n}\n\n/** Shaped `BuildCreativeMultiSuccess`. `manifests` renamed to `creative_manifests` on wire. */\nexport function multiEnvelopedBuildCreativeReturn(fields: MultiEnvelopeFields): BuildCreativeMultiSuccess {\n const { manifests, ...rest } = fields;\n return { ...rest, creative_manifests: manifests };\n}\n\n/** Grouped accessor for the four `build_creative` return shapes. */\nexport const buildCreativeReturn = {\n single: singleBuildCreativeReturn,\n multi: multiBuildCreativeReturn,\n singleEnveloped: singleEnvelopedBuildCreativeReturn,\n multiEnveloped: multiEnvelopedBuildCreativeReturn,\n} as const;\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/build-creative-return-builders.ts"],"sourcesContent":["// Typed factory helpers for `build_creative` return values. Four shapes:\n// 1. bare `CreativeManifest` — auto-wrapped as `{ creative_manifest }`\n// 2. bare `CreativeManifest[]` — auto-wrapped as `{ creative_manifests }`\n// 3. shaped `BuildCreativeSuccess` — passthrough\n// 4. shaped `BuildCreativeMultiSuccess` — passthrough multi-format\n//\n// Adopters writing the shaped envelope by hand consistently miss the\n// distinction between single (`creative_manifest`) and multi\n// (`creative_manifests`) field names. SHAPE-GOTCHAS §5.\n\nimport type { BuildCreativeSuccess, BuildCreativeMultiSuccess, CreativeManifest } from '../types/core.generated';\n\ntype SingleEnvelopeFields = Omit<BuildCreativeSuccess, 'creative_manifest'> & { manifest: CreativeManifest };\ntype MultiEnvelopeFields = Omit<BuildCreativeMultiSuccess, 'creative_manifests'> & { manifests: CreativeManifest[] };\n\n/** Bare single-format manifest. Framework wraps as `{ creative_manifest }`. */\nexport function singleBuildCreativeReturn(manifest: CreativeManifest): CreativeManifest {\n return manifest;\n}\n\n/** Bare multi-format manifest array. Framework wraps as `{ creative_manifests }`. */\nexport function multiBuildCreativeReturn(manifests: CreativeManifest[]): CreativeManifest[] {\n return manifests;\n}\n\n/** Shaped `BuildCreativeSuccess`. `manifest` field renamed to `creative_manifest` on wire. */\nexport function singleEnvelopedBuildCreativeReturn(fields: SingleEnvelopeFields): BuildCreativeSuccess {\n const { manifest, ...rest } = fields;\n return { ...rest, creative_manifest: manifest };\n}\n\n/** Shaped `BuildCreativeMultiSuccess`. `manifests` renamed to `creative_manifests` on wire. */\nexport function multiEnvelopedBuildCreativeReturn(fields: MultiEnvelopeFields): BuildCreativeMultiSuccess {\n const { manifests, ...rest } = fields;\n return { ...rest, creative_manifests: manifests };\n}\n\n/** Grouped accessor for the four `build_creative` return shapes. */\nexport const buildCreativeReturn = {\n single: singleBuildCreativeReturn,\n multi: multiBuildCreativeReturn,\n singleEnveloped: singleEnvelopedBuildCreativeReturn,\n multiEnveloped: multiEnvelopedBuildCreativeReturn,\n} as const;\n"],"mappings":"AAgBO,SAAS,0BAA0B,UAA8C;AACtF,SAAO;AACT;AAGO,SAAS,yBAAyB,WAAmD;AAC1F,SAAO;AACT;AAGO,SAAS,mCAAmC,QAAoD;AACrG,QAAM,EAAE,UAAU,GAAG,KAAK,IAAI;AAC9B,SAAO,EAAE,GAAG,MAAM,mBAAmB,SAAS;AAChD;AAGO,SAAS,kCAAkC,QAAwD;AACxG,QAAM,EAAE,WAAW,GAAG,KAAK,IAAI;AAC/B,SAAO,EAAE,GAAG,MAAM,oBAAoB,UAAU;AAClD;AAGO,MAAM,sBAAsB;AAAA,EACjC,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,iBAAiB;AAAA,EACjB,gBAAgB;AAClB;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import { applyAdcpErrorAllowlist } from "../server/errors.mjs";
|
|
8
2
|
const DEFAULT_CODE_POLICY = {
|
|
9
3
|
// Transients — server-side, retry-safe with same idempotency_key.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/buyer-retry-policy.ts"],"sourcesContent":["/**\n * Buyer-side retry policy for AdCP errors.\n *\n * Translates an `AdcpStructuredError` into an actionable `RetryDecision`,\n * baked with operator-grade defaults so naive buyer agent loops don't:\n *\n * - Retry-storm on revoked credentials (`AUTH_REQUIRED`).\n * - Auto-mutate-and-resubmit on policy/governance/compliance signals\n * (which looks like evasion to seller-side reviewers).\n * - Spin on `*_NOT_FOUND` errors with a stale id instead of re-discovering.\n * - Hold the same `idempotency_key` after a `correctable` correction\n * (which lets the seller's replay-window dedupe ignore the new payload).\n *\n * The spec's `recovery` field is a 3-class enum (`transient` / `correctable`\n * / `terminal`); the operator semantic varies WITHIN `correctable`. This\n * module hardcodes the operator-grade interpretation per code.\n *\n * @public\n */\n\nimport type { AdcpStructuredError, ErrorCode } from '../server/decisioning/async-outcome';\nimport { applyAdcpErrorAllowlist } from '../server/errors';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * What the buyer agent should do next. Discriminated by `action`.\n *\n * - `retry`: replay with the SAME `idempotency_key` after `delayMs`. Use for\n * server-side transients (`RATE_LIMITED`, `SERVICE_UNAVAILABLE`, `CONFLICT`).\n * - `mutate-and-retry`: apply the seller's correction hint (read\n * `error.field` / `error.suggestion`), then call again with a FRESH\n * `idempotency_key` because the payload is now semantically different.\n * - `escalate`: stop the agent loop and surface to a human. Includes\n * commercial-relationship signals, auth failures, terminal errors,\n * attempt-cap exhaustion, and unknown vendor codes.\n */\nexport type RetryDecision =\n | {\n action: 'retry';\n /** Delay before the retry, in milliseconds. Honors `error.retry_after` when present. */\n delayMs: number;\n /** Maximum attempts (including the original) before escalating. */\n attemptCap: number;\n /** Caller MUST replay with the same `idempotency_key`. */\n sameIdempotencyKey: true;\n reason: string;\n }\n | {\n action: 'mutate-and-retry';\n /**\n * Suggested pre-retry delay in milliseconds. Lightweight jitter so fleet\n * operators don't all hit the seller in the same instant after a\n * correlated storm (e.g., `PROPOSAL_EXPIRED` across thousands of\n * campaigns at once).\n */\n delayMs: number;\n /** Maximum attempts (including the original) before escalating. */\n attemptCap: number;\n /** Caller MUST mint a fresh `idempotency_key` because the payload changes. */\n sameIdempotencyKey: false;\n reason: 'redirect' | 'budget' | 'requote' | 'validation' | 'capability' | 'state';\n /** The field the seller flagged. Mirrors `error.field`. */\n field?: string;\n /** The seller's correction hint. Mirrors `error.suggestion`. */\n suggestion?: string;\n }\n | {\n action: 'escalate';\n reason:\n | 'commercial' // POLICY_VIOLATION / COMPLIANCE_UNSATISFIED / GOVERNANCE_DENIED / billing-family (BILLING_NOT_SUPPORTED / BILLING_NOT_PERMITTED_FOR_AGENT / BILLING_OUT_OF_BAND / PAYMENT_TERMS_NOT_SUPPORTED) / provenance-rejection (PROVENANCE_VERIFIER_NOT_ACCEPTED / PROVENANCE_CLAIM_CONTRADICTED) — human review. Some billing+provenance codes are spec-correctable but we operator-grade override (auto-retrying billing-value alternatives or swapping verifiers without operator policy is precisely the evasion pattern this surface is designed to prevent).\n | 'auth' // AUTH_REQUIRED / PERMISSION_DENIED / SCOPE_INSUFFICIENT / READ_ONLY_SCOPE / FIELD_NOT_PERMITTED / ACTION_NOT_ALLOWED — operator must rotate creds / grant access\n | 'governance_unreachable' // GOVERNANCE_UNAVAILABLE / CAMPAIGN_SUSPENDED — out-of-band\n | 'idempotency_check_required' // IDEMPOTENCY_EXPIRED / CONFIGURATION_ERROR — buyer MUST do a natural-key check before minting a new key (spec safety constraint to prevent double-creation)\n | 'capability' // FORMAT_PROJECTION_FAILED / FORMAT_DECLARATION_DIVERGENT / FORMAT_DECLARATION_V1_AMBIGUOUS / FORMAT_OPTION_UNRESOLVED / PRIVATE_FIELD_IN_PUBLIC_PLACEMENT / FORMAT_DECLARATION_V1_LOSSY_MULTI_SIZE / PIXEL_TRACKER_LOSSY_DOWNGRADE / PIXEL_TRACKER_UPGRADE_INFERRED — implementation choice problem (operator needs to pick a different adapter or surface the advisory to the buyer); distinct from 'commercial' so dashboards can filter\n | 'terminal' // spec recovery 'terminal' (account suspended, budget exhausted, CREDENTIAL_IN_ARGS, RETENTION_EXPIRED, STALE_RESPONSE — advisory paired with a populated success payload; consume the payload, surface the advisory, do not retry …)\n | 'attempts_exhausted' // hit attemptCap — caller already retried as many times as the policy allows\n | 'unknown'; // non-standard code, no policy override — buyer surfaces to user\n /** Human-facing message. Mirrors `error.message`. */\n message: string;\n /**\n * Safe code-specific details for UX routing. Currently populated for\n * `AUTHORIZATION_REQUIRED` after the same allowlist/sanitizer used on\n * server error envelopes.\n */\n details?: Record<string, unknown>;\n /** Convenience mirror of `details.missing_connections` for auth UX handoffs. */\n missing_connections?: unknown[];\n /** Convenience auth URL, from top-level details or the first missing connection that provides one. */\n authorization_url?: string;\n /** Convenience auth instructions, from top-level details or the first missing connection that provides them. */\n authorization_instructions?: string;\n };\n\n/**\n * Context the caller passes about the current state of the operation.\n */\nexport interface RetryContext {\n /** Current attempt number, 1-indexed. The original call is attempt 1. */\n attempt?: number;\n /** Prior errors on this logical operation. Used for repeat-failure escalation. */\n history?: AdcpStructuredError[];\n}\n\n/**\n * Override hook for adopters with vertical-specific policy needs.\n * Receives the error + context; returns a `RetryDecision` or `null` to fall\n * through to the default policy.\n */\nexport type RetryDecisionOverride = (error: AdcpStructuredError, ctx: RetryContext) => RetryDecision | null;\n\n// ---------------------------------------------------------------------------\n// Default per-code policy table\n// ---------------------------------------------------------------------------\n\ntype CodePolicy =\n | {\n action: 'retry';\n attemptCap: number;\n baseDelayMs: number;\n /** When true, scales `baseDelayMs` by 2^(attempt-1), clamped to 3600s. */\n expBackoff?: boolean;\n }\n | {\n action: 'mutate-and-retry';\n attemptCap: number;\n reason: Extract<RetryDecision, { action: 'mutate-and-retry' }>['reason'];\n /** Pre-retry delay (jitter window). Helps fleet operators avoid a thundering herd. */\n baseDelayMs?: number;\n }\n | {\n action: 'escalate';\n escalateReason: Extract<RetryDecision, { action: 'escalate' }>['reason'];\n };\n\n/**\n * Defaults per standard error code. Each entry is operator-grade — what the\n * buyer SHOULD do, not just what the spec's `recovery` field says.\n *\n * Where this diverges from the spec's `recovery`:\n * - `POLICY_VIOLATION`, `COMPLIANCE_UNSATISFIED`, `GOVERNANCE_DENIED` are\n * spec-`correctable` but escalate here (commercial-relationship signals;\n * auto-tweak looks like evasion).\n * - `AUTH_REQUIRED` is spec-`correctable` but escalate here (the deprecated\n * 3.0.x code conflates missing-creds with revoked-creds; 3.1 sellers\n * emit `AUTH_MISSING` / `AUTH_INVALID` instead, each handled below).\n * - `GOVERNANCE_UNAVAILABLE`, `CAMPAIGN_SUSPENDED` are spec-`transient` but\n * escalate here (out-of-band — agent can't unblock).\n */\nconst DEFAULT_CODE_POLICY: Record<ErrorCode, CodePolicy> = {\n // Transients — server-side, retry-safe with same idempotency_key.\n RATE_LIMITED: { action: 'retry', attemptCap: 5, baseDelayMs: 1000, expBackoff: true },\n SERVICE_UNAVAILABLE: { action: 'retry', attemptCap: 3, baseDelayMs: 1000, expBackoff: true },\n CONFLICT: { action: 'retry', attemptCap: 2, baseDelayMs: 0 },\n\n // Out-of-band transients — agent can't unblock; surface to operator.\n GOVERNANCE_UNAVAILABLE: { action: 'escalate', escalateReason: 'governance_unreachable' },\n CAMPAIGN_SUSPENDED: { action: 'escalate', escalateReason: 'governance_unreachable' },\n\n // Resource-not-found — re-discover and retry. attemptCap: 3 so a buyer with\n // a stale cache can list, mutate, list-again-on-second-staleness, and still\n // succeed before escalation.\n ACCOUNT_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n MEDIA_BUY_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PACKAGE_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PRODUCT_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n CREATIVE_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n SIGNAL_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n SESSION_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PLAN_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n REFERENCE_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n\n // Stale-resource — re-discover. Same as not-found family.\n PRODUCT_EXPIRED: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PROPOSAL_EXPIRED: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PRODUCT_UNAVAILABLE: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n\n // Capability mismatch — drop the unsupported field and retry.\n UNSUPPORTED_FEATURE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n VERSION_UNSUPPORTED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n\n // Re-quote — go back to get_products in 'refine' mode against the proposal.\n TERMS_REJECTED: { action: 'mutate-and-retry', attemptCap: 3, reason: 'requote', baseDelayMs: 250 },\n REQUOTE_REQUIRED: { action: 'mutate-and-retry', attemptCap: 3, reason: 'requote', baseDelayMs: 250 },\n PROPOSAL_NOT_COMMITTED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'requote', baseDelayMs: 250 },\n IO_REQUIRED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'requote', baseDelayMs: 250 },\n\n // Budget — adjust and retry.\n BUDGET_TOO_LOW: { action: 'mutate-and-retry', attemptCap: 2, reason: 'budget', baseDelayMs: 250 },\n BUDGET_EXCEEDED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'budget', baseDelayMs: 250 },\n BUDGET_CAP_REACHED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'budget', baseDelayMs: 250 },\n AUDIENCE_TOO_SMALL: { action: 'mutate-and-retry', attemptCap: 2, reason: 'budget', baseDelayMs: 250 },\n\n // Validation / state — read issues[] and patch.\n INVALID_REQUEST: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n VALIDATION_ERROR: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n INVALID_STATE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'state', baseDelayMs: 250 },\n NOT_CANCELLABLE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'state', baseDelayMs: 250 },\n\n // Idempotency:\n // - CONFLICT (different payload, same key in window) — fresh key + retry is safe;\n // the seller already rejected the new payload before doing any work.\n // - EXPIRED (cached response evicted past replay_ttl) — DO NOT auto-retry. The\n // spec explicitly warns: if the prior call may have succeeded, the buyer\n // MUST do a natural-key check (e.g., get_media_buys by buyer_ref) BEFORE\n // minting a new key. Otherwise this is exactly how double-creation happens.\n IDEMPOTENCY_CONFLICT: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n IDEMPOTENCY_EXPIRED: { action: 'escalate', escalateReason: 'idempotency_check_required' },\n\n // Creative deadline — buyer can re-negotiate or surface to user.\n CREATIVE_DEADLINE_EXCEEDED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'state', baseDelayMs: 250 },\n CREATIVE_INACCESSIBLE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n\n // Account state — operator must resolve.\n // ACCOUNT_AMBIGUOUS: spec says \"pass explicit account_id\" but the agent\n // typically doesn't have the right id cached without going back to\n // list_accounts — escalating with the seller's hint is more honest than\n // burning a retry on a guaranteed-wrong replay.\n ACCOUNT_AMBIGUOUS: { action: 'escalate', escalateReason: 'auth' },\n ACCOUNT_SETUP_REQUIRED: { action: 'escalate', escalateReason: 'auth' },\n ACCOUNT_PAYMENT_REQUIRED: { action: 'escalate', escalateReason: 'auth' },\n ACCOUNT_SUSPENDED: { action: 'escalate', escalateReason: 'terminal' },\n BUDGET_EXHAUSTED: { action: 'escalate', escalateReason: 'terminal' },\n\n // SI session — recreate.\n SESSION_TERMINATED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'redirect', baseDelayMs: 250 },\n\n // Creative rejection — surface to user; agent shouldn't auto-modify creative.\n // (Format-mismatch rejections are technically buyer-fixable, but the spec\n // doesn't structurally distinguish them from brand-safety rejections; pessimistic\n // default. Adopters with creative-template platforms can override per-code.)\n CREATIVE_REJECTED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Commercial-relationship signals — DO NOT auto-tweak. Human in loop.\n POLICY_VIOLATION: { action: 'escalate', escalateReason: 'commercial' },\n COMPLIANCE_UNSATISFIED: { action: 'escalate', escalateReason: 'commercial' },\n GOVERNANCE_DENIED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Auth — 3.0.x emitted `AUTH_REQUIRED` for both missing and revoked\n // credentials; 3.1+ splits into `AUTH_MISSING` (correctable) and\n // `AUTH_INVALID` (terminal — auto-retry hammers SSO endpoints on\n // revoked tokens).\n //\n // All three escalate by default. The agent typically can't re-handshake\n // without an operator-supplied credential refresh path, so even\n // `AUTH_MISSING` escalates rather than burning a retry on a\n // guaranteed-empty `Authorization` header. Adopters with a refresh-token\n // resolver wire `AUTH_MISSING` to `mutate-and-retry` via the override hook.\n AUTH_REQUIRED: { action: 'escalate', escalateReason: 'auth' },\n AUTH_MISSING: { action: 'escalate', escalateReason: 'auth' },\n AUTH_INVALID: { action: 'escalate', escalateReason: 'terminal' },\n AUTHORIZATION_REQUIRED: { action: 'escalate', escalateReason: 'auth' },\n PERMISSION_DENIED: { action: 'escalate', escalateReason: 'auth' },\n\n // Agent-status terminals — adcp#3906 consolidates the 3.0.5 placeholder\n // shape (PERMISSION_DENIED + details.status:'suspended'|'blocked') into\n // dedicated codes. Both are terminal at the wire level — a buyer cannot\n // recover by retrying. Suspension lifts at the seller's BuyerAgent record,\n // not in response to client behavior.\n AGENT_SUSPENDED: { action: 'escalate', escalateReason: 'terminal' },\n AGENT_BLOCKED: { action: 'escalate', escalateReason: 'terminal' },\n\n // Resource-not-found — proposal variant joins the not-found family.\n PROPOSAL_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n\n // Configuration / ops — halt, not retry. Seller misconfiguration; operator\n // must intervene before another call has any chance of succeeding.\n CONFIGURATION_ERROR: { action: 'escalate', escalateReason: 'idempotency_check_required' },\n\n // Idempotency — IN_FLIGHT means the seller is still processing a prior\n // submission with this key; safe to retry with same key after backoff.\n IDEMPOTENCY_IN_FLIGHT: { action: 'retry', attemptCap: 3, baseDelayMs: 500 },\n\n // Capability mismatch — drop the unsupported field/granularity and retry.\n UNSUPPORTED_GRANULARITY: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n UNSUPPORTED_PROVISIONING: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n MULTI_FINALIZE_UNSUPPORTED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n\n // Creative value rejection — commercial signal; don't auto-tweak.\n CREATIVE_VALUE_NOT_ALLOWED: { action: 'escalate', escalateReason: 'commercial' },\n EVALUATOR_AGENT_NOT_ACCEPTED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Brand required — validation; patch and retry.\n BRAND_REQUIRED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n\n // Scope / permission — operator must adjust API key scopes.\n SCOPE_INSUFFICIENT: { action: 'escalate', escalateReason: 'auth' },\n READ_ONLY_SCOPE: { action: 'escalate', escalateReason: 'auth' },\n FIELD_NOT_PERMITTED: { action: 'escalate', escalateReason: 'auth' },\n ACTION_NOT_ALLOWED: { action: 'escalate', escalateReason: 'auth' },\n\n // Provenance — most are correctable by attaching the missing metadata;\n // verifier-not-accepted / claim-contradicted are commercial rejections.\n PROVENANCE_REQUIRED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n PROVENANCE_DIGITAL_SOURCE_TYPE_MISSING: {\n action: 'mutate-and-retry',\n attemptCap: 2,\n reason: 'validation',\n baseDelayMs: 250,\n },\n PROVENANCE_DISCLOSURE_MISSING: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n PROVENANCE_EMBEDDED_MISSING: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n PROVENANCE_VERIFIER_NOT_ACCEPTED: { action: 'escalate', escalateReason: 'commercial' },\n PROVENANCE_CLAIM_CONTRADICTED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Billing / payment terms — commercial-relationship signals; human in loop.\n BILLING_NOT_SUPPORTED: { action: 'escalate', escalateReason: 'commercial' },\n BILLING_NOT_PERMITTED_FOR_AGENT: { action: 'escalate', escalateReason: 'commercial' },\n BILLING_OUT_OF_BAND: { action: 'escalate', escalateReason: 'commercial' },\n PAYMENT_TERMS_NOT_SUPPORTED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Format-projection — capability mismatch between buyer's declared format\n // and what the seller can render. Buyer typically needs a different\n // creative-template specialism, not a payload tweak. Surface to operator\n // via `capability` so dashboards can filter implementation-choice tickets\n // from commercial-policy ones.\n //\n // NOTE: spec marks several FORMAT_DECLARATION_* codes as advisory (emitted\n // in `errors[]` on a 200-success response, not on failure). The retry\n // policy still fires when an adopter routes them through `decideRetry()`,\n // so the policy here is \"what to do if a caller hands us this code\" — for\n // a 200-success+advisory shape, the caller should typically not invoke\n // the retry policy at all. Tracked separately.\n FORMAT_PROJECTION_FAILED: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_DECLARATION_DIVERGENT: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_DECLARATION_V1_AMBIGUOUS: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_OPTION_UNRESOLVED: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_NOT_SUPPORTED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n UNPRICEABLE_OUTPUT: { action: 'escalate', escalateReason: 'commercial' },\n PRIVATE_FIELD_IN_PUBLIC_PLACEMENT: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_DECLARATION_V1_LOSSY_MULTI_SIZE: { action: 'escalate', escalateReason: 'capability' },\n\n // Pixel-tracker — buyer's tracker shape doesn't fit the seller's surface.\n PIXEL_TRACKER_LOSSY_DOWNGRADE: { action: 'escalate', escalateReason: 'capability' },\n PIXEL_TRACKER_UPGRADE_INFERRED: { action: 'escalate', escalateReason: 'capability' },\n\n // Security violation — credentials in args; terminate immediately. Retrying\n // would re-leak. Operator must rotate the leaked credential and refactor\n // the call site before any further calls.\n CREDENTIAL_IN_ARGS: { action: 'escalate', escalateReason: 'terminal' },\n\n // STALE_RESPONSE is an advisory: seller responded from a stale cache,\n // payload still populated. No retry — surface the advisory to operator\n // and consume the payload as if it were fresh.\n STALE_RESPONSE: { action: 'escalate', escalateReason: 'terminal' },\n\n // Creative/catalog input correction.\n SIGNAL_TARGETING_INCOMPATIBLE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n FEED_FETCH_FAILED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n INVALID_FEED_FORMAT: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n ITEM_VALIDATION_FAILED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n CATALOG_LIMIT_EXCEEDED: { action: 'escalate', escalateReason: 'commercial' },\n};\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/** Cap on any computed retry delay. Mirrors the spec's `retry_after` range [1, 3600]. */\nconst MAX_DELAY_MS = 3_600_000;\n\nfunction clampDelayMs(\n retryAfterSeconds: number | undefined,\n fallbackMs: number,\n attempt: number,\n exp: boolean\n): number {\n if (typeof retryAfterSeconds === 'number' && retryAfterSeconds > 0) {\n return Math.max(1, Math.min(3600, Math.floor(retryAfterSeconds))) * 1000;\n }\n if (exp) {\n return Math.min(MAX_DELAY_MS, fallbackMs * Math.pow(2, Math.max(0, attempt - 1)));\n }\n return Math.min(MAX_DELAY_MS, fallbackMs);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction authorizationRequiredEscalationContext(\n error: AdcpStructuredError\n): Partial<Extract<RetryDecision, { action: 'escalate' }>> {\n if (error.code !== 'AUTHORIZATION_REQUIRED' || error.details === undefined) return {};\n\n const sanitized = applyAdcpErrorAllowlist('AUTHORIZATION_REQUIRED', {\n code: error.code,\n message: error.message,\n recovery: error.recovery,\n details: error.details,\n });\n const details = sanitized.details;\n if (!isRecord(details)) return {};\n\n const missingConnections = Array.isArray(details.missing_connections) ? details.missing_connections : undefined;\n const firstMissing = missingConnections?.find(isRecord);\n const authorizationUrl =\n typeof details.authorization_url === 'string'\n ? details.authorization_url\n : typeof firstMissing?.authorization_url === 'string'\n ? firstMissing.authorization_url\n : undefined;\n const authorizationInstructions =\n typeof details.authorization_instructions === 'string'\n ? details.authorization_instructions\n : typeof firstMissing?.authorization_instructions === 'string'\n ? firstMissing.authorization_instructions\n : undefined;\n\n return {\n details,\n ...(missingConnections !== undefined && { missing_connections: missingConnections }),\n ...(authorizationUrl !== undefined && { authorization_url: authorizationUrl }),\n ...(authorizationInstructions !== undefined && { authorization_instructions: authorizationInstructions }),\n };\n}\n\nfunction applyPolicy(\n policy: CodePolicy | undefined,\n error: AdcpStructuredError,\n attempt: number,\n fallbackByRecovery: 'mutate' | 'escalate-unknown'\n): RetryDecision {\n if (!policy) {\n // No per-code policy entry — fall back by recovery class.\n if (error.recovery === 'transient') {\n const delayMs = clampDelayMs(error.retry_after, 1000, attempt, true);\n return {\n action: 'retry',\n delayMs,\n attemptCap: 3,\n sameIdempotencyKey: true,\n reason: `transient (${error.code})`,\n };\n }\n if (error.recovery === 'terminal') {\n return { action: 'escalate', reason: 'terminal', message: error.message };\n }\n if (fallbackByRecovery === 'mutate') {\n const jitterMs = Math.floor(250 * (0.5 + Math.random() * 0.5));\n return {\n action: 'mutate-and-retry',\n delayMs: jitterMs,\n attemptCap: 2,\n sameIdempotencyKey: false,\n reason: 'validation',\n ...(error.field !== undefined && { field: error.field }),\n ...(error.suggestion !== undefined && { suggestion: error.suggestion }),\n };\n }\n return { action: 'escalate', reason: 'unknown', message: error.message };\n }\n\n if (policy.action === 'escalate') {\n return {\n action: 'escalate',\n reason: policy.escalateReason,\n message: error.message,\n ...authorizationRequiredEscalationContext(error),\n };\n }\n\n if (attempt >= policy.attemptCap) {\n return { action: 'escalate', reason: 'attempts_exhausted', message: error.message };\n }\n\n if (policy.action === 'retry') {\n const delayMs = clampDelayMs(error.retry_after, policy.baseDelayMs, attempt, policy.expBackoff ?? false);\n return {\n action: 'retry',\n delayMs,\n attemptCap: policy.attemptCap,\n sameIdempotencyKey: true,\n reason: `transient (${error.code})`,\n };\n }\n\n // mutate-and-retry. Add small jitter (50-100% of baseDelayMs, default\n // 250ms) so fleet operators don't all hit the seller at once after a\n // correlated storm (e.g., PROPOSAL_EXPIRED across thousands of campaigns).\n const base = policy.baseDelayMs ?? 250;\n const jitterMs = Math.floor(base * (0.5 + Math.random() * 0.5));\n return {\n action: 'mutate-and-retry',\n delayMs: Math.min(MAX_DELAY_MS, jitterMs),\n attemptCap: policy.attemptCap,\n sameIdempotencyKey: false,\n reason: policy.reason,\n ...(error.field !== undefined && { field: error.field }),\n ...(error.suggestion !== undefined && { suggestion: error.suggestion }),\n };\n}\n\n/**\n * Buyer-side retry policy with operator-grade defaults per AdCP error code.\n *\n * @example\n * ```ts\n * import { decideRetry, type RetryDecision } from '@adcp/sdk';\n *\n * try {\n * return await callAgent({ idempotency_key: key, ... });\n * } catch (e) {\n * const error = extractAdcpError(e);\n * const decision = decideRetry(error, { attempt });\n *\n * if (decision.action === 'retry') {\n * await sleep(decision.delayMs);\n * return callAgent({ idempotency_key: key, ... }); // SAME key\n * }\n * if (decision.action === 'mutate-and-retry') {\n * // Apply correction (decision.field, decision.suggestion), fresh key.\n * return callAgent({ idempotency_key: crypto.randomUUID(), ... });\n * }\n * throw new Error(`Escalate: ${decision.reason} — ${decision.message}`);\n * }\n * ```\n */\nexport class BuyerRetryPolicy {\n private readonly overrides: ReadonlyMap<string, RetryDecisionOverride>;\n private readonly unknownCode: 'mutate' | 'escalate';\n\n constructor(\n opts: {\n /**\n * Per-code override functions. Keyed by error code (typed as\n * `Partial<Record<ErrorCode, RetryDecisionOverride>>` so typos like\n * `POLICY_VIOLATIN` fail compile). Returns `null` to fall through to\n * the default policy.\n */\n overrides?: Partial<Record<ErrorCode, RetryDecisionOverride>> & Record<string, RetryDecisionOverride>;\n /**\n * What to do when the error code is not in the standard vocabulary\n * AND has no per-code override. `'escalate'` (default) is the safer\n * choice for unknown vendor codes — buyer surfaces to user.\n * `'mutate'` lets the buyer attempt a generic correction-and-retry.\n */\n unknownCode?: 'mutate' | 'escalate';\n } = {}\n ) {\n this.overrides = new Map(Object.entries(opts.overrides ?? {}));\n this.unknownCode = opts.unknownCode ?? 'escalate';\n }\n\n decide(error: AdcpStructuredError, ctx: RetryContext = {}): RetryDecision {\n const attempt = Math.max(1, ctx.attempt ?? 1);\n const override = this.overrides.get(error.code);\n if (override) {\n const result = override(error, { ...ctx, attempt });\n if (result) return result;\n }\n const policy = DEFAULT_CODE_POLICY[error.code as ErrorCode];\n return applyPolicy(policy, error, attempt, this.unknownCode === 'mutate' ? 'mutate' : 'escalate-unknown');\n }\n}\n\nconst defaultPolicy = new BuyerRetryPolicy();\n\n/**\n * Decide what a buyer should do next given an AdCP error.\n *\n * Convenience wrapper for `new BuyerRetryPolicy().decide(error, ctx)`.\n * Use the class directly when you need per-code overrides.\n *\n * @public\n */\nexport function decideRetry(error: AdcpStructuredError, ctx: RetryContext = {}): RetryDecision {\n return defaultPolicy.decide(error, ctx);\n}\n"],"mappings":"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","names":["jitterMs"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/buyer-retry-policy.ts"],"sourcesContent":["/**\n * Buyer-side retry policy for AdCP errors.\n *\n * Translates an `AdcpStructuredError` into an actionable `RetryDecision`,\n * baked with operator-grade defaults so naive buyer agent loops don't:\n *\n * - Retry-storm on revoked credentials (`AUTH_REQUIRED`).\n * - Auto-mutate-and-resubmit on policy/governance/compliance signals\n * (which looks like evasion to seller-side reviewers).\n * - Spin on `*_NOT_FOUND` errors with a stale id instead of re-discovering.\n * - Hold the same `idempotency_key` after a `correctable` correction\n * (which lets the seller's replay-window dedupe ignore the new payload).\n *\n * The spec's `recovery` field is a 3-class enum (`transient` / `correctable`\n * / `terminal`); the operator semantic varies WITHIN `correctable`. This\n * module hardcodes the operator-grade interpretation per code.\n *\n * @public\n */\n\nimport type { AdcpStructuredError, ErrorCode } from '../server/decisioning/async-outcome';\nimport { applyAdcpErrorAllowlist } from '../server/errors';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * What the buyer agent should do next. Discriminated by `action`.\n *\n * - `retry`: replay with the SAME `idempotency_key` after `delayMs`. Use for\n * server-side transients (`RATE_LIMITED`, `SERVICE_UNAVAILABLE`, `CONFLICT`).\n * - `mutate-and-retry`: apply the seller's correction hint (read\n * `error.field` / `error.suggestion`), then call again with a FRESH\n * `idempotency_key` because the payload is now semantically different.\n * - `escalate`: stop the agent loop and surface to a human. Includes\n * commercial-relationship signals, auth failures, terminal errors,\n * attempt-cap exhaustion, and unknown vendor codes.\n */\nexport type RetryDecision =\n | {\n action: 'retry';\n /** Delay before the retry, in milliseconds. Honors `error.retry_after` when present. */\n delayMs: number;\n /** Maximum attempts (including the original) before escalating. */\n attemptCap: number;\n /** Caller MUST replay with the same `idempotency_key`. */\n sameIdempotencyKey: true;\n reason: string;\n }\n | {\n action: 'mutate-and-retry';\n /**\n * Suggested pre-retry delay in milliseconds. Lightweight jitter so fleet\n * operators don't all hit the seller in the same instant after a\n * correlated storm (e.g., `PROPOSAL_EXPIRED` across thousands of\n * campaigns at once).\n */\n delayMs: number;\n /** Maximum attempts (including the original) before escalating. */\n attemptCap: number;\n /** Caller MUST mint a fresh `idempotency_key` because the payload changes. */\n sameIdempotencyKey: false;\n reason: 'redirect' | 'budget' | 'requote' | 'validation' | 'capability' | 'state';\n /** The field the seller flagged. Mirrors `error.field`. */\n field?: string;\n /** The seller's correction hint. Mirrors `error.suggestion`. */\n suggestion?: string;\n }\n | {\n action: 'escalate';\n reason:\n | 'commercial' // POLICY_VIOLATION / COMPLIANCE_UNSATISFIED / GOVERNANCE_DENIED / billing-family (BILLING_NOT_SUPPORTED / BILLING_NOT_PERMITTED_FOR_AGENT / BILLING_OUT_OF_BAND / PAYMENT_TERMS_NOT_SUPPORTED) / provenance-rejection (PROVENANCE_VERIFIER_NOT_ACCEPTED / PROVENANCE_CLAIM_CONTRADICTED) — human review. Some billing+provenance codes are spec-correctable but we operator-grade override (auto-retrying billing-value alternatives or swapping verifiers without operator policy is precisely the evasion pattern this surface is designed to prevent).\n | 'auth' // AUTH_REQUIRED / PERMISSION_DENIED / SCOPE_INSUFFICIENT / READ_ONLY_SCOPE / FIELD_NOT_PERMITTED / ACTION_NOT_ALLOWED — operator must rotate creds / grant access\n | 'governance_unreachable' // GOVERNANCE_UNAVAILABLE / CAMPAIGN_SUSPENDED — out-of-band\n | 'idempotency_check_required' // IDEMPOTENCY_EXPIRED / CONFIGURATION_ERROR — buyer MUST do a natural-key check before minting a new key (spec safety constraint to prevent double-creation)\n | 'capability' // FORMAT_PROJECTION_FAILED / FORMAT_DECLARATION_DIVERGENT / FORMAT_DECLARATION_V1_AMBIGUOUS / FORMAT_OPTION_UNRESOLVED / PRIVATE_FIELD_IN_PUBLIC_PLACEMENT / FORMAT_DECLARATION_V1_LOSSY_MULTI_SIZE / PIXEL_TRACKER_LOSSY_DOWNGRADE / PIXEL_TRACKER_UPGRADE_INFERRED — implementation choice problem (operator needs to pick a different adapter or surface the advisory to the buyer); distinct from 'commercial' so dashboards can filter\n | 'terminal' // spec recovery 'terminal' (account suspended, budget exhausted, CREDENTIAL_IN_ARGS, RETENTION_EXPIRED, STALE_RESPONSE — advisory paired with a populated success payload; consume the payload, surface the advisory, do not retry …)\n | 'attempts_exhausted' // hit attemptCap — caller already retried as many times as the policy allows\n | 'unknown'; // non-standard code, no policy override — buyer surfaces to user\n /** Human-facing message. Mirrors `error.message`. */\n message: string;\n /**\n * Safe code-specific details for UX routing. Currently populated for\n * `AUTHORIZATION_REQUIRED` after the same allowlist/sanitizer used on\n * server error envelopes.\n */\n details?: Record<string, unknown>;\n /** Convenience mirror of `details.missing_connections` for auth UX handoffs. */\n missing_connections?: unknown[];\n /** Convenience auth URL, from top-level details or the first missing connection that provides one. */\n authorization_url?: string;\n /** Convenience auth instructions, from top-level details or the first missing connection that provides them. */\n authorization_instructions?: string;\n };\n\n/**\n * Context the caller passes about the current state of the operation.\n */\nexport interface RetryContext {\n /** Current attempt number, 1-indexed. The original call is attempt 1. */\n attempt?: number;\n /** Prior errors on this logical operation. Used for repeat-failure escalation. */\n history?: AdcpStructuredError[];\n}\n\n/**\n * Override hook for adopters with vertical-specific policy needs.\n * Receives the error + context; returns a `RetryDecision` or `null` to fall\n * through to the default policy.\n */\nexport type RetryDecisionOverride = (error: AdcpStructuredError, ctx: RetryContext) => RetryDecision | null;\n\n// ---------------------------------------------------------------------------\n// Default per-code policy table\n// ---------------------------------------------------------------------------\n\ntype CodePolicy =\n | {\n action: 'retry';\n attemptCap: number;\n baseDelayMs: number;\n /** When true, scales `baseDelayMs` by 2^(attempt-1), clamped to 3600s. */\n expBackoff?: boolean;\n }\n | {\n action: 'mutate-and-retry';\n attemptCap: number;\n reason: Extract<RetryDecision, { action: 'mutate-and-retry' }>['reason'];\n /** Pre-retry delay (jitter window). Helps fleet operators avoid a thundering herd. */\n baseDelayMs?: number;\n }\n | {\n action: 'escalate';\n escalateReason: Extract<RetryDecision, { action: 'escalate' }>['reason'];\n };\n\n/**\n * Defaults per standard error code. Each entry is operator-grade — what the\n * buyer SHOULD do, not just what the spec's `recovery` field says.\n *\n * Where this diverges from the spec's `recovery`:\n * - `POLICY_VIOLATION`, `COMPLIANCE_UNSATISFIED`, `GOVERNANCE_DENIED` are\n * spec-`correctable` but escalate here (commercial-relationship signals;\n * auto-tweak looks like evasion).\n * - `AUTH_REQUIRED` is spec-`correctable` but escalate here (the deprecated\n * 3.0.x code conflates missing-creds with revoked-creds; 3.1 sellers\n * emit `AUTH_MISSING` / `AUTH_INVALID` instead, each handled below).\n * - `GOVERNANCE_UNAVAILABLE`, `CAMPAIGN_SUSPENDED` are spec-`transient` but\n * escalate here (out-of-band — agent can't unblock).\n */\nconst DEFAULT_CODE_POLICY: Record<ErrorCode, CodePolicy> = {\n // Transients — server-side, retry-safe with same idempotency_key.\n RATE_LIMITED: { action: 'retry', attemptCap: 5, baseDelayMs: 1000, expBackoff: true },\n SERVICE_UNAVAILABLE: { action: 'retry', attemptCap: 3, baseDelayMs: 1000, expBackoff: true },\n CONFLICT: { action: 'retry', attemptCap: 2, baseDelayMs: 0 },\n\n // Out-of-band transients — agent can't unblock; surface to operator.\n GOVERNANCE_UNAVAILABLE: { action: 'escalate', escalateReason: 'governance_unreachable' },\n CAMPAIGN_SUSPENDED: { action: 'escalate', escalateReason: 'governance_unreachable' },\n\n // Resource-not-found — re-discover and retry. attemptCap: 3 so a buyer with\n // a stale cache can list, mutate, list-again-on-second-staleness, and still\n // succeed before escalation.\n ACCOUNT_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n MEDIA_BUY_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PACKAGE_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PRODUCT_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n CREATIVE_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n SIGNAL_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n SESSION_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PLAN_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n REFERENCE_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n\n // Stale-resource — re-discover. Same as not-found family.\n PRODUCT_EXPIRED: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PROPOSAL_EXPIRED: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n PRODUCT_UNAVAILABLE: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n\n // Capability mismatch — drop the unsupported field and retry.\n UNSUPPORTED_FEATURE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n VERSION_UNSUPPORTED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n\n // Re-quote — go back to get_products in 'refine' mode against the proposal.\n TERMS_REJECTED: { action: 'mutate-and-retry', attemptCap: 3, reason: 'requote', baseDelayMs: 250 },\n REQUOTE_REQUIRED: { action: 'mutate-and-retry', attemptCap: 3, reason: 'requote', baseDelayMs: 250 },\n PROPOSAL_NOT_COMMITTED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'requote', baseDelayMs: 250 },\n IO_REQUIRED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'requote', baseDelayMs: 250 },\n\n // Budget — adjust and retry.\n BUDGET_TOO_LOW: { action: 'mutate-and-retry', attemptCap: 2, reason: 'budget', baseDelayMs: 250 },\n BUDGET_EXCEEDED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'budget', baseDelayMs: 250 },\n BUDGET_CAP_REACHED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'budget', baseDelayMs: 250 },\n AUDIENCE_TOO_SMALL: { action: 'mutate-and-retry', attemptCap: 2, reason: 'budget', baseDelayMs: 250 },\n\n // Validation / state — read issues[] and patch.\n INVALID_REQUEST: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n VALIDATION_ERROR: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n INVALID_STATE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'state', baseDelayMs: 250 },\n NOT_CANCELLABLE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'state', baseDelayMs: 250 },\n\n // Idempotency:\n // - CONFLICT (different payload, same key in window) — fresh key + retry is safe;\n // the seller already rejected the new payload before doing any work.\n // - EXPIRED (cached response evicted past replay_ttl) — DO NOT auto-retry. The\n // spec explicitly warns: if the prior call may have succeeded, the buyer\n // MUST do a natural-key check (e.g., get_media_buys by buyer_ref) BEFORE\n // minting a new key. Otherwise this is exactly how double-creation happens.\n IDEMPOTENCY_CONFLICT: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n IDEMPOTENCY_EXPIRED: { action: 'escalate', escalateReason: 'idempotency_check_required' },\n\n // Creative deadline — buyer can re-negotiate or surface to user.\n CREATIVE_DEADLINE_EXCEEDED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'state', baseDelayMs: 250 },\n CREATIVE_INACCESSIBLE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n\n // Account state — operator must resolve.\n // ACCOUNT_AMBIGUOUS: spec says \"pass explicit account_id\" but the agent\n // typically doesn't have the right id cached without going back to\n // list_accounts — escalating with the seller's hint is more honest than\n // burning a retry on a guaranteed-wrong replay.\n ACCOUNT_AMBIGUOUS: { action: 'escalate', escalateReason: 'auth' },\n ACCOUNT_SETUP_REQUIRED: { action: 'escalate', escalateReason: 'auth' },\n ACCOUNT_PAYMENT_REQUIRED: { action: 'escalate', escalateReason: 'auth' },\n ACCOUNT_SUSPENDED: { action: 'escalate', escalateReason: 'terminal' },\n BUDGET_EXHAUSTED: { action: 'escalate', escalateReason: 'terminal' },\n\n // SI session — recreate.\n SESSION_TERMINATED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'redirect', baseDelayMs: 250 },\n\n // Creative rejection — surface to user; agent shouldn't auto-modify creative.\n // (Format-mismatch rejections are technically buyer-fixable, but the spec\n // doesn't structurally distinguish them from brand-safety rejections; pessimistic\n // default. Adopters with creative-template platforms can override per-code.)\n CREATIVE_REJECTED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Commercial-relationship signals — DO NOT auto-tweak. Human in loop.\n POLICY_VIOLATION: { action: 'escalate', escalateReason: 'commercial' },\n COMPLIANCE_UNSATISFIED: { action: 'escalate', escalateReason: 'commercial' },\n GOVERNANCE_DENIED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Auth — 3.0.x emitted `AUTH_REQUIRED` for both missing and revoked\n // credentials; 3.1+ splits into `AUTH_MISSING` (correctable) and\n // `AUTH_INVALID` (terminal — auto-retry hammers SSO endpoints on\n // revoked tokens).\n //\n // All three escalate by default. The agent typically can't re-handshake\n // without an operator-supplied credential refresh path, so even\n // `AUTH_MISSING` escalates rather than burning a retry on a\n // guaranteed-empty `Authorization` header. Adopters with a refresh-token\n // resolver wire `AUTH_MISSING` to `mutate-and-retry` via the override hook.\n AUTH_REQUIRED: { action: 'escalate', escalateReason: 'auth' },\n AUTH_MISSING: { action: 'escalate', escalateReason: 'auth' },\n AUTH_INVALID: { action: 'escalate', escalateReason: 'terminal' },\n AUTHORIZATION_REQUIRED: { action: 'escalate', escalateReason: 'auth' },\n PERMISSION_DENIED: { action: 'escalate', escalateReason: 'auth' },\n\n // Agent-status terminals — adcp#3906 consolidates the 3.0.5 placeholder\n // shape (PERMISSION_DENIED + details.status:'suspended'|'blocked') into\n // dedicated codes. Both are terminal at the wire level — a buyer cannot\n // recover by retrying. Suspension lifts at the seller's BuyerAgent record,\n // not in response to client behavior.\n AGENT_SUSPENDED: { action: 'escalate', escalateReason: 'terminal' },\n AGENT_BLOCKED: { action: 'escalate', escalateReason: 'terminal' },\n\n // Resource-not-found — proposal variant joins the not-found family.\n PROPOSAL_NOT_FOUND: { action: 'mutate-and-retry', attemptCap: 3, reason: 'redirect', baseDelayMs: 250 },\n\n // Configuration / ops — halt, not retry. Seller misconfiguration; operator\n // must intervene before another call has any chance of succeeding.\n CONFIGURATION_ERROR: { action: 'escalate', escalateReason: 'idempotency_check_required' },\n\n // Idempotency — IN_FLIGHT means the seller is still processing a prior\n // submission with this key; safe to retry with same key after backoff.\n IDEMPOTENCY_IN_FLIGHT: { action: 'retry', attemptCap: 3, baseDelayMs: 500 },\n\n // Capability mismatch — drop the unsupported field/granularity and retry.\n UNSUPPORTED_GRANULARITY: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n UNSUPPORTED_PROVISIONING: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n MULTI_FINALIZE_UNSUPPORTED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n\n // Creative value rejection — commercial signal; don't auto-tweak.\n CREATIVE_VALUE_NOT_ALLOWED: { action: 'escalate', escalateReason: 'commercial' },\n EVALUATOR_AGENT_NOT_ACCEPTED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Brand required — validation; patch and retry.\n BRAND_REQUIRED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n\n // Scope / permission — operator must adjust API key scopes.\n SCOPE_INSUFFICIENT: { action: 'escalate', escalateReason: 'auth' },\n READ_ONLY_SCOPE: { action: 'escalate', escalateReason: 'auth' },\n FIELD_NOT_PERMITTED: { action: 'escalate', escalateReason: 'auth' },\n ACTION_NOT_ALLOWED: { action: 'escalate', escalateReason: 'auth' },\n\n // Provenance — most are correctable by attaching the missing metadata;\n // verifier-not-accepted / claim-contradicted are commercial rejections.\n PROVENANCE_REQUIRED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n PROVENANCE_DIGITAL_SOURCE_TYPE_MISSING: {\n action: 'mutate-and-retry',\n attemptCap: 2,\n reason: 'validation',\n baseDelayMs: 250,\n },\n PROVENANCE_DISCLOSURE_MISSING: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n PROVENANCE_EMBEDDED_MISSING: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n PROVENANCE_VERIFIER_NOT_ACCEPTED: { action: 'escalate', escalateReason: 'commercial' },\n PROVENANCE_CLAIM_CONTRADICTED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Billing / payment terms — commercial-relationship signals; human in loop.\n BILLING_NOT_SUPPORTED: { action: 'escalate', escalateReason: 'commercial' },\n BILLING_NOT_PERMITTED_FOR_AGENT: { action: 'escalate', escalateReason: 'commercial' },\n BILLING_OUT_OF_BAND: { action: 'escalate', escalateReason: 'commercial' },\n PAYMENT_TERMS_NOT_SUPPORTED: { action: 'escalate', escalateReason: 'commercial' },\n\n // Format-projection — capability mismatch between buyer's declared format\n // and what the seller can render. Buyer typically needs a different\n // creative-template specialism, not a payload tweak. Surface to operator\n // via `capability` so dashboards can filter implementation-choice tickets\n // from commercial-policy ones.\n //\n // NOTE: spec marks several FORMAT_DECLARATION_* codes as advisory (emitted\n // in `errors[]` on a 200-success response, not on failure). The retry\n // policy still fires when an adopter routes them through `decideRetry()`,\n // so the policy here is \"what to do if a caller hands us this code\" — for\n // a 200-success+advisory shape, the caller should typically not invoke\n // the retry policy at all. Tracked separately.\n FORMAT_PROJECTION_FAILED: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_DECLARATION_DIVERGENT: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_DECLARATION_V1_AMBIGUOUS: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_OPTION_UNRESOLVED: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_NOT_SUPPORTED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'capability', baseDelayMs: 250 },\n UNPRICEABLE_OUTPUT: { action: 'escalate', escalateReason: 'commercial' },\n PRIVATE_FIELD_IN_PUBLIC_PLACEMENT: { action: 'escalate', escalateReason: 'capability' },\n FORMAT_DECLARATION_V1_LOSSY_MULTI_SIZE: { action: 'escalate', escalateReason: 'capability' },\n\n // Pixel-tracker — buyer's tracker shape doesn't fit the seller's surface.\n PIXEL_TRACKER_LOSSY_DOWNGRADE: { action: 'escalate', escalateReason: 'capability' },\n PIXEL_TRACKER_UPGRADE_INFERRED: { action: 'escalate', escalateReason: 'capability' },\n\n // Security violation — credentials in args; terminate immediately. Retrying\n // would re-leak. Operator must rotate the leaked credential and refactor\n // the call site before any further calls.\n CREDENTIAL_IN_ARGS: { action: 'escalate', escalateReason: 'terminal' },\n\n // STALE_RESPONSE is an advisory: seller responded from a stale cache,\n // payload still populated. No retry — surface the advisory to operator\n // and consume the payload as if it were fresh.\n STALE_RESPONSE: { action: 'escalate', escalateReason: 'terminal' },\n\n // Creative/catalog input correction.\n SIGNAL_TARGETING_INCOMPATIBLE: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n FEED_FETCH_FAILED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n INVALID_FEED_FORMAT: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n ITEM_VALIDATION_FAILED: { action: 'mutate-and-retry', attemptCap: 2, reason: 'validation', baseDelayMs: 250 },\n CATALOG_LIMIT_EXCEEDED: { action: 'escalate', escalateReason: 'commercial' },\n};\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/** Cap on any computed retry delay. Mirrors the spec's `retry_after` range [1, 3600]. */\nconst MAX_DELAY_MS = 3_600_000;\n\nfunction clampDelayMs(\n retryAfterSeconds: number | undefined,\n fallbackMs: number,\n attempt: number,\n exp: boolean\n): number {\n if (typeof retryAfterSeconds === 'number' && retryAfterSeconds > 0) {\n return Math.max(1, Math.min(3600, Math.floor(retryAfterSeconds))) * 1000;\n }\n if (exp) {\n return Math.min(MAX_DELAY_MS, fallbackMs * Math.pow(2, Math.max(0, attempt - 1)));\n }\n return Math.min(MAX_DELAY_MS, fallbackMs);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction authorizationRequiredEscalationContext(\n error: AdcpStructuredError\n): Partial<Extract<RetryDecision, { action: 'escalate' }>> {\n if (error.code !== 'AUTHORIZATION_REQUIRED' || error.details === undefined) return {};\n\n const sanitized = applyAdcpErrorAllowlist('AUTHORIZATION_REQUIRED', {\n code: error.code,\n message: error.message,\n recovery: error.recovery,\n details: error.details,\n });\n const details = sanitized.details;\n if (!isRecord(details)) return {};\n\n const missingConnections = Array.isArray(details.missing_connections) ? details.missing_connections : undefined;\n const firstMissing = missingConnections?.find(isRecord);\n const authorizationUrl =\n typeof details.authorization_url === 'string'\n ? details.authorization_url\n : typeof firstMissing?.authorization_url === 'string'\n ? firstMissing.authorization_url\n : undefined;\n const authorizationInstructions =\n typeof details.authorization_instructions === 'string'\n ? details.authorization_instructions\n : typeof firstMissing?.authorization_instructions === 'string'\n ? firstMissing.authorization_instructions\n : undefined;\n\n return {\n details,\n ...(missingConnections !== undefined && { missing_connections: missingConnections }),\n ...(authorizationUrl !== undefined && { authorization_url: authorizationUrl }),\n ...(authorizationInstructions !== undefined && { authorization_instructions: authorizationInstructions }),\n };\n}\n\nfunction applyPolicy(\n policy: CodePolicy | undefined,\n error: AdcpStructuredError,\n attempt: number,\n fallbackByRecovery: 'mutate' | 'escalate-unknown'\n): RetryDecision {\n if (!policy) {\n // No per-code policy entry — fall back by recovery class.\n if (error.recovery === 'transient') {\n const delayMs = clampDelayMs(error.retry_after, 1000, attempt, true);\n return {\n action: 'retry',\n delayMs,\n attemptCap: 3,\n sameIdempotencyKey: true,\n reason: `transient (${error.code})`,\n };\n }\n if (error.recovery === 'terminal') {\n return { action: 'escalate', reason: 'terminal', message: error.message };\n }\n if (fallbackByRecovery === 'mutate') {\n const jitterMs = Math.floor(250 * (0.5 + Math.random() * 0.5));\n return {\n action: 'mutate-and-retry',\n delayMs: jitterMs,\n attemptCap: 2,\n sameIdempotencyKey: false,\n reason: 'validation',\n ...(error.field !== undefined && { field: error.field }),\n ...(error.suggestion !== undefined && { suggestion: error.suggestion }),\n };\n }\n return { action: 'escalate', reason: 'unknown', message: error.message };\n }\n\n if (policy.action === 'escalate') {\n return {\n action: 'escalate',\n reason: policy.escalateReason,\n message: error.message,\n ...authorizationRequiredEscalationContext(error),\n };\n }\n\n if (attempt >= policy.attemptCap) {\n return { action: 'escalate', reason: 'attempts_exhausted', message: error.message };\n }\n\n if (policy.action === 'retry') {\n const delayMs = clampDelayMs(error.retry_after, policy.baseDelayMs, attempt, policy.expBackoff ?? false);\n return {\n action: 'retry',\n delayMs,\n attemptCap: policy.attemptCap,\n sameIdempotencyKey: true,\n reason: `transient (${error.code})`,\n };\n }\n\n // mutate-and-retry. Add small jitter (50-100% of baseDelayMs, default\n // 250ms) so fleet operators don't all hit the seller at once after a\n // correlated storm (e.g., PROPOSAL_EXPIRED across thousands of campaigns).\n const base = policy.baseDelayMs ?? 250;\n const jitterMs = Math.floor(base * (0.5 + Math.random() * 0.5));\n return {\n action: 'mutate-and-retry',\n delayMs: Math.min(MAX_DELAY_MS, jitterMs),\n attemptCap: policy.attemptCap,\n sameIdempotencyKey: false,\n reason: policy.reason,\n ...(error.field !== undefined && { field: error.field }),\n ...(error.suggestion !== undefined && { suggestion: error.suggestion }),\n };\n}\n\n/**\n * Buyer-side retry policy with operator-grade defaults per AdCP error code.\n *\n * @example\n * ```ts\n * import { decideRetry, type RetryDecision } from '@adcp/sdk';\n *\n * try {\n * return await callAgent({ idempotency_key: key, ... });\n * } catch (e) {\n * const error = extractAdcpError(e);\n * const decision = decideRetry(error, { attempt });\n *\n * if (decision.action === 'retry') {\n * await sleep(decision.delayMs);\n * return callAgent({ idempotency_key: key, ... }); // SAME key\n * }\n * if (decision.action === 'mutate-and-retry') {\n * // Apply correction (decision.field, decision.suggestion), fresh key.\n * return callAgent({ idempotency_key: crypto.randomUUID(), ... });\n * }\n * throw new Error(`Escalate: ${decision.reason} — ${decision.message}`);\n * }\n * ```\n */\nexport class BuyerRetryPolicy {\n private readonly overrides: ReadonlyMap<string, RetryDecisionOverride>;\n private readonly unknownCode: 'mutate' | 'escalate';\n\n constructor(\n opts: {\n /**\n * Per-code override functions. Keyed by error code (typed as\n * `Partial<Record<ErrorCode, RetryDecisionOverride>>` so typos like\n * `POLICY_VIOLATIN` fail compile). Returns `null` to fall through to\n * the default policy.\n */\n overrides?: Partial<Record<ErrorCode, RetryDecisionOverride>> & Record<string, RetryDecisionOverride>;\n /**\n * What to do when the error code is not in the standard vocabulary\n * AND has no per-code override. `'escalate'` (default) is the safer\n * choice for unknown vendor codes — buyer surfaces to user.\n * `'mutate'` lets the buyer attempt a generic correction-and-retry.\n */\n unknownCode?: 'mutate' | 'escalate';\n } = {}\n ) {\n this.overrides = new Map(Object.entries(opts.overrides ?? {}));\n this.unknownCode = opts.unknownCode ?? 'escalate';\n }\n\n decide(error: AdcpStructuredError, ctx: RetryContext = {}): RetryDecision {\n const attempt = Math.max(1, ctx.attempt ?? 1);\n const override = this.overrides.get(error.code);\n if (override) {\n const result = override(error, { ...ctx, attempt });\n if (result) return result;\n }\n const policy = DEFAULT_CODE_POLICY[error.code as ErrorCode];\n return applyPolicy(policy, error, attempt, this.unknownCode === 'mutate' ? 'mutate' : 'escalate-unknown');\n }\n}\n\nconst defaultPolicy = new BuyerRetryPolicy();\n\n/**\n * Decide what a buyer should do next given an AdCP error.\n *\n * Convenience wrapper for `new BuyerRetryPolicy().decide(error, ctx)`.\n * Use the class directly when you need per-code overrides.\n *\n * @public\n */\nexport function decideRetry(error: AdcpStructuredError, ctx: RetryContext = {}): RetryDecision {\n return defaultPolicy.decide(error, ctx);\n}\n"],"mappings":"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","names":["jitterMs"]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
function getRawNested(obj, ...keys) {
|
|
8
2
|
let current = obj;
|
|
9
3
|
for (const key of keys) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/capabilities.ts"],"sourcesContent":["/**\n * AdCP Capabilities utilities\n *\n * Provides types and helpers for working with agent capabilities,\n * including synthetic capabilities for v2 servers that don't support\n * the get_adcp_capabilities tool.\n */\n\n/**\n * Detected AdCP major version\n */\nexport type AdcpMajorVersion = 2 | 3;\n\n/**\n * Supported AdCP protocols/domains\n */\nexport type AdcpProtocol =\n | 'media_buy'\n | 'signals'\n | 'governance'\n | 'creative'\n | 'sponsored_intelligence'\n | 'trusted_match'\n | 'compliance_testing'\n | 'brand'\n | 'measurement';\n\n/**\n * Media buy features available on the agent\n */\nexport interface MediaBuyFeatures {\n /**\n * Agent accepts package-scoped inline creative uploads in\n * create_media_buy/update_media_buy via `packages[].creatives`.\n *\n * This is distinct from creative-library support. Use\n * `supportsSyncCreatives(caps)` when deciding whether to call the\n * library-scoped `sync_creatives` tool.\n */\n inlineCreativeManagement?: boolean;\n /** Agent supports property_list filtering in get_products */\n propertyListFiltering?: boolean;\n /** Agent supports content standards validation */\n contentStandards?: boolean;\n /** Agent supports conversion event tracking (sync_event_sources, log_event) */\n conversionTracking?: boolean;\n /** Agent supports first-party CRM audience management (sync_audiences) */\n audienceTargeting?: boolean;\n}\n\n/**\n * Account management capabilities declared by the seller\n */\nexport interface AccountCapabilities {\n /**\n * Whether the seller requires operator-level credentials.\n * When false (default), the agent authenticates once and declares brands/operators via sync_accounts.\n * When true, each operator must authenticate independently.\n */\n requireOperatorAuth: boolean;\n\n /**\n * OAuth authorization endpoint for obtaining operator-level credentials.\n * Present when the seller supports OAuth for operator authentication.\n * May be absent even when requireOperatorAuth is true — in that case,\n * operators obtain credentials out-of-band (e.g., seller portal, API key).\n */\n authorizationEndpoint?: string;\n\n /**\n * Billing models this seller supports (e.g., 'operator', 'agent').\n */\n supportedBilling: ('operator' | 'agent' | 'advertiser')[];\n\n /**\n * Default billing model applied when omitted from sync_accounts.\n */\n defaultBilling?: 'operator' | 'agent' | 'advertiser';\n\n /**\n * Whether an active account is required before calling get_products.\n */\n requiredForProducts: boolean;\n\n /**\n * Whether the seller supports sandbox accounts for testing.\n * For implicit accounts (require_operator_auth: false), declare sandbox via sync_accounts\n * with sandbox: true and reference by natural key. For explicit accounts\n * (require_operator_auth: true), discover pre-existing test accounts via list_accounts.\n */\n sandbox: boolean;\n}\n\n/**\n * Creative protocol capabilities declared by the agent.\n */\nexport interface CreativeCapabilities {\n /** Agent can validate compliance requirements while building creatives */\n supportsCompliance: boolean;\n /** Agent exposes a creative library addressable via creative_id */\n hasCreativeLibrary: boolean;\n /** Agent can generate creatives from a natural-language brief */\n supportsGeneration: boolean;\n /** Agent can adapt an existing creative to a new format */\n supportsTransformation: boolean;\n}\n\n/**\n * Idempotency capabilities declared by the seller.\n *\n * Clients MUST NOT fall back to an assumed TTL when the seller omits this —\n * `getIdempotencyReplayTtlSeconds()` throws when the declaration is missing\n * on a v3 server rather than silently defaulting to 24h. A seller without the\n * declaration is non-compliant and unsafe for retry-sensitive operations.\n */\nexport interface IdempotencyCapabilities {\n /**\n * Seconds the seller retains cached `(principal, idempotency_key, payload)`\n * tuples. BYOK callers compare their persisted key's age against this to\n * decide whether a fresh key + natural-key lookup is safer than reusing.\n */\n replayTtlSeconds: number;\n}\n\n/**\n * Normalized capabilities response that works for both v2 and v3 servers\n */\nexport interface AdcpCapabilities {\n /** Detected version ('v2' or 'v3') */\n version: 'v2' | 'v3';\n\n /**\n * Array of supported major versions (e.g., [2] or [2, 3]).\n * @deprecated Use {@link supportedVersions} for release-precision negotiation.\n * Removed in AdCP 4.0 per spec PR `adcontextprotocol/adcp#3493`. Continues\n * to be emitted alongside the new field through 3.x.\n */\n majorVersions: AdcpMajorVersion[];\n\n /**\n * Array of supported AdCP releases at release precision (`'3.0'`, `'3.1'`,\n * `'3.1.0-beta.1'`). Stable releases use `MAJOR.MINOR`; pre-releases use\n * the full pre-release tag. Set when the seller is on AdCP 3.1+ per spec\n * PR `adcontextprotocol/adcp#3493`. `undefined` on legacy 3.0-only sellers.\n */\n supportedVersions?: string[];\n\n /**\n * Full semver build of the seller's released AdCP version (e.g. `'3.1.2'`,\n * `'3.1.0-beta.1+sha.abc'`). Advisory — patch differences within the same\n * release-precision are non-breaking by spec convention. `undefined` on\n * legacy 3.0-only sellers.\n */\n buildVersion?: string;\n\n /** Supported protocols */\n protocols: AdcpProtocol[];\n\n /** Public specialism ids declared by this agent */\n specialisms?: string[];\n\n /** Media buy specific features */\n features: MediaBuyFeatures;\n\n /** Account management capabilities */\n account?: AccountCapabilities;\n\n /** Creative protocol capabilities */\n creative?: CreativeCapabilities;\n\n /** Idempotency replay capabilities (v3 sellers declaring `adcp.idempotency`) */\n idempotency?: IdempotencyCapabilities;\n\n /** Supported extension namespaces (e.g., 'scope3', 'garm') */\n extensions: string[];\n\n /**\n * Experimental AdCP surfaces this agent implements. Dot-namespaced feature\n * ids (e.g. `brand.rights_lifecycle`, `governance.campaign`, `trusted_match.core`)\n * sellers declare when they opt into surfaces whose schemas carry\n * `x-status: experimental`. Consumers should gate any reliance on\n * experimental fields on presence of the matching id here.\n *\n * See https://adcontextprotocol.org/docs/reference/experimental-status\n */\n experimentalFeatures?: string[];\n\n /** Publisher domains covered by this agent */\n publisherDomains?: string[];\n\n /** Supported advertising channels */\n channels?: string[];\n\n /** Last updated timestamp (if provided by server) */\n lastUpdated?: string;\n\n /** Whether this was synthesized from tool list (v2) or from get_adcp_capabilities (v3) */\n _synthetic: boolean;\n\n /** Raw response from get_adcp_capabilities (only for v3) */\n _raw?: Record<string, unknown>;\n}\n\n/**\n * Safely traverse nested keys in a Record<string, unknown>.\n */\nfunction getRawNested(obj: Record<string, unknown> | undefined, ...keys: string[]): unknown {\n let current: unknown = obj;\n for (const key of keys) {\n if (current == null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[key];\n }\n return current;\n}\n\n/**\n * Tool info for capability detection\n */\nexport interface ToolInfo {\n name: string;\n description?: string;\n}\n\n/**\n * Known AdCP tool names for protocol detection.\n * These map to task names in the AdCP schema index (kebab-case -> snake_case).\n *\n * Note: Some tools appear in multiple arrays (e.g., list_creative_formats is in\n * both MEDIA_BUY_TOOLS and CREATIVE_TOOLS). This is intentional — these tools\n * serve multiple domains, and their presence should activate all relevant\n * protocols when `detectProtocols()` runs.\n *\n * **Why these aren't manifest-derived (#1192).** The AdCP manifest\n * (`schemas/cache/{version}/manifest.json`) carries a single primary `protocol`\n * per tool — `list_creative_formats` is `media-buy` there, never `creative`.\n * That's an authoring convenience (where does the tool's spec page live), not\n * a capability-declaration semantic. The cross-listing here captures\n * operator reality: a CMP that exposes only `build_creative` /\n * `list_creative_formats` / `sync_creatives` IS a creative agent, and a buyer\n * discovering it via `tools/list` should see the `creative` protocol family.\n * Migrating to manifest-primary would silently flip `detectProtocols()`\n * results for cross-listed tools and break CMP↔DSP discovery flows. The\n * drift guard at `test/lib/capabilities-tools-drift.test.js` keeps the arrays\n * locked to recognized manifest tools (catches typos and removed-upstream\n * tools) without forcing the arrays to match the manifest's single-valued\n * view. See PR #1298 for the design rationale.\n */\nexport const MEDIA_BUY_TOOLS = [\n 'get_products',\n 'list_creative_formats', // Also in CREATIVE_TOOLS - serves both domains\n 'create_media_buy',\n 'update_media_buy',\n 'sync_creatives',\n 'list_creatives', // Also in CREATIVE_TOOLS - serves both domains\n 'get_media_buy_delivery',\n 'provide_performance_feedback',\n 'sync_audiences',\n 'sync_event_sources',\n 'sync_catalogs',\n 'log_event',\n] as const;\n\nexport const SIGNALS_TOOLS = ['get_signals', 'activate_signal'] as const;\n\nexport const GOVERNANCE_TOOLS = [\n // Property list management\n 'create_property_list',\n 'update_property_list',\n 'get_property_list',\n 'list_property_lists',\n 'delete_property_list',\n // Collection list management (program-level brand safety)\n 'create_collection_list',\n 'update_collection_list',\n 'get_collection_list',\n 'list_collection_lists',\n 'delete_collection_list',\n // Content standards\n 'list_content_standards',\n 'get_content_standards',\n 'create_content_standards',\n 'update_content_standards',\n 'calibrate_content',\n 'validate_content_delivery',\n 'get_media_buy_artifacts',\n // Campaign governance\n 'sync_plans',\n 'check_governance',\n 'report_plan_outcome',\n 'get_plan_audit_logs',\n // Creative governance\n 'get_creative_features',\n] as const;\n\nexport const CREATIVE_TOOLS = [\n 'build_creative',\n 'list_creative_formats',\n 'list_transformers',\n 'preview_creative',\n 'list_creatives',\n 'sync_creatives', // Also in MEDIA_BUY_TOOLS - serves both domains\n] as const;\n\nexport const SPONSORED_INTELLIGENCE_TOOLS = [\n 'si_get_offering',\n 'si_initiate_session',\n 'si_send_message',\n 'si_terminate_session',\n] as const;\n\nexport const TRUSTED_MATCH_TOOLS = ['context_match', 'identity_match'] as const;\n\nexport const COMPLIANCE_TOOLS = ['comply_test_controller'] as const;\n\n// `creative_approval` is intentionally absent — it's webhook-only (the buyer\n// POSTs to the `approval_webhook` URL returned by `acquire_rights`), not an\n// MCP/A2A tool the seller exposes. Adopters wire it via their HTTP server\n// using `BrandRightsPlatform.reviewCreativeApproval`.\nexport const BRAND_RIGHTS_TOOLS = [\n 'get_brand_identity',\n 'search_brands',\n 'get_rights',\n 'acquire_rights',\n 'update_rights',\n] as const;\n\nexport const EVENT_TRACKING_TOOLS = ['sync_event_sources', 'log_event'] as const;\n\nexport const ACCOUNT_TOOLS = ['list_accounts', 'sync_accounts'] as const;\n\nexport const PROTOCOL_TOOLS = ['get_adcp_capabilities', 'get_task_status', 'list_tasks'] as const;\n\n/**\n * Build synthetic capabilities from a list of available tools.\n * Used for v2 servers that don't support get_adcp_capabilities.\n */\n/**\n * Tool-group → protocol mapping for detection from tools/list.\n */\nconst TOOL_PROTOCOL_MAP: [readonly string[], AdcpProtocol][] = [\n [MEDIA_BUY_TOOLS, 'media_buy'],\n [SIGNALS_TOOLS, 'signals'],\n [GOVERNANCE_TOOLS, 'governance'],\n [CREATIVE_TOOLS, 'creative'],\n [SPONSORED_INTELLIGENCE_TOOLS, 'sponsored_intelligence'],\n [TRUSTED_MATCH_TOOLS, 'trusted_match'],\n [COMPLIANCE_TOOLS, 'compliance_testing'],\n [BRAND_RIGHTS_TOOLS, 'brand'],\n];\n\n/**\n * Detect protocols from tool names.\n */\nfunction detectProtocolsFromTools(toolNames: Set<string>): AdcpProtocol[] {\n const protocols: AdcpProtocol[] = [];\n for (const [tools, protocol] of TOOL_PROTOCOL_MAP) {\n if (tools.some(t => toolNames.has(t))) {\n protocols.push(protocol);\n }\n }\n return protocols;\n}\n\n/**\n * Augment declared capabilities with compliance_testing if the tool is present\n * but no `compliance_testing` capability block / protocol entry was advertised.\n *\n * Per AdCP 3.0, agents declare comply_test_controller support via the\n * top-level `capabilities.compliance_testing` block. `parseCapabilitiesResponse`\n * already promotes that block into the internal `protocols` list, so if we\n * reach this function with the tool present but the protocol missing, the\n * agent forgot the declaration. We auto-bridge (the SDK's internal type can\n * treat the agent as compliance-capable) and warn the agent once so they can\n * ship the proper block.\n *\n * Other protocols (media_buy, signals, etc.) are NOT augmented because a stub\n * or partial tool registration could produce false positives.\n */\nexport function augmentCapabilitiesFromTools(capabilities: AdcpCapabilities, tools: ToolInfo[]): AdcpCapabilities {\n const toolNames = new Set(tools.map(t => t.name));\n const hasComplianceTool = COMPLIANCE_TOOLS.some(t => toolNames.has(t));\n if (!hasComplianceTool || capabilities.protocols.includes('compliance_testing')) {\n return capabilities;\n }\n console.error(\n `[AdCP] Agent exposes comply_test_controller but omits the \\`compliance_testing\\` capability block ` +\n `from get_adcp_capabilities. Per AdCP 3.0, declare \\`capabilities.compliance_testing.scenarios\\` ` +\n `— not \\`supported_protocols\\`. The SDK is treating the agent as compliance-capable for this request.`\n );\n return {\n ...capabilities,\n protocols: [...capabilities.protocols, 'compliance_testing'],\n };\n}\n\nexport function buildSyntheticCapabilities(tools: ToolInfo[]): AdcpCapabilities {\n const toolNames = new Set(tools.map(t => t.name));\n const protocols = detectProtocolsFromTools(toolNames);\n\n // Detect features from tool presence\n const features: MediaBuyFeatures = {\n // Tool lists do not declare package-scoped inline creative upload support.\n inlineCreativeManagement: false,\n // Property list filtering is v3 only\n propertyListFiltering: false,\n // Content standards is v3 only\n contentStandards: false,\n // Conversion tracking if event tracking tools are available\n conversionTracking: EVENT_TRACKING_TOOLS.some(t => toolNames.has(t)),\n // Audience targeting if sync_audiences is available\n audienceTargeting: toolNames.has('sync_audiences'),\n };\n\n return {\n version: 'v2',\n majorVersions: [2],\n protocols,\n features,\n extensions: [],\n _synthetic: true,\n };\n}\n\n/**\n * Build synthetic v3 capabilities when the agent advertises\n * `get_adcp_capabilities` (a v3-only tool) but the call itself failed —\n * either the executor threw, or the response was non-success with no\n * structurally v3-shaped data (the case `looksLikeV3Capabilities` would\n * have caught).\n *\n * The agent is verifiably v3 because the v3-only discovery tool is\n * present in `tools/list`. Falling back to v2 synthetic in this case\n * triggers v2.5-schema lookups that have nothing to do with the original\n * failure, cascading \"AdCP schema data for version v2.5 not found\"\n * across every subsequent step. Treating as v3 (synthetic) lets the\n * caller continue against the right adapter set; the underlying\n * `get_adcp_capabilities` failure still surfaces in logs at the\n * call site.\n *\n * Sets `_synthetic: true` so version-compat checks know detail-level\n * fields (idempotency TTL, supportedVersions) are unknown — callers\n * skip those checks rather than throw `VersionUnsupportedError` on a\n * verifiably-v3 agent.\n *\n * Refs: #1217 (carve-out from #1197/closed), #1189 / #1201 (the v3-shape\n * heuristic this complements).\n */\nexport function buildSyntheticV3Capabilities(tools: ToolInfo[]): AdcpCapabilities {\n const toolNames = new Set(tools.map(t => t.name));\n const protocols = detectProtocolsFromTools(toolNames);\n\n const features: MediaBuyFeatures = {\n // Tool lists do not declare package-scoped inline creative upload support.\n inlineCreativeManagement: false,\n propertyListFiltering: false,\n contentStandards: false,\n conversionTracking: EVENT_TRACKING_TOOLS.some(t => toolNames.has(t)),\n audienceTargeting: toolNames.has('sync_audiences'),\n };\n\n return {\n version: 'v3',\n majorVersions: [3],\n protocols,\n features,\n extensions: [],\n _synthetic: true,\n };\n}\n\n/**\n * Heuristic: does this `get_adcp_capabilities` response look v3-shaped?\n *\n * Used by callers (e.g. SingleAgentClient.getCapabilities) when the response\n * fails strict schema validation but is structurally non-empty. The question\n * the heuristic answers is \"is this a v3 agent with a wire-shape bug, or a\n * v2 agent that happens to advertise the tool?\". Falling back to v2 in the\n * former case masks the original bug behind cascading v2.5-schema-not-found\n * errors; treating it as v3 surfaces the wire-shape bug at its source.\n *\n * Affirmative v3 signals (any one is enough):\n * - `adcp` block (only v3 servers carry the `{ major_versions, idempotency, ... }` envelope)\n * - `supported_protocols` array (v3-only top-level field)\n * - any v3 protocol-level capability block (`media_buy`, `signals`, `creative`, `brand`,\n * `governance`, `sponsored_intelligence`, `compliance_testing`, `account`)\n *\n * v2 servers don't expose `get_adcp_capabilities` at all (the tool itself is\n * a v3-only addition), so reaching this function with a non-empty payload\n * already strongly implies v3 — but we belt-and-suspenders the structural\n * check to avoid mis-promoting genuinely empty / null responses.\n */\nexport function looksLikeV3Capabilities(data: unknown): boolean {\n if (!isPlainObject(data)) return false;\n if (isPlainObject(data.adcp)) return true;\n if (Array.isArray(data.supported_protocols)) return true;\n const v3Blocks = [\n 'account',\n 'media_buy',\n 'signals',\n 'creative',\n 'brand',\n 'governance',\n 'sponsored_intelligence',\n 'compliance_testing',\n ] as const;\n return v3Blocks.some(block => isPlainObject(data[block]));\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction declaresSpecialism(specialisms: readonly string[] | undefined, specialism: string): boolean {\n return specialisms?.includes(specialism) === true;\n}\n\nfunction hasContentStandardsSupport(capabilities: Pick<AdcpCapabilities, 'features' | 'specialisms'>): boolean {\n return (\n capabilities.features.contentStandards === true || declaresSpecialism(capabilities.specialisms, 'content-standards')\n );\n}\n\n/**\n * Parse a get_adcp_capabilities response into normalized form\n */\nexport function parseCapabilitiesResponse(response: any): AdcpCapabilities {\n const majorVersions = (response.adcp?.major_versions ?? [2]) as AdcpMajorVersion[];\n const highestVersion = Math.max(...majorVersions) as AdcpMajorVersion;\n const specialisms = Array.isArray(response.specialisms)\n ? response.specialisms.filter((s: unknown): s is string => typeof s === 'string')\n : undefined;\n const declaresContentStandardsSpecialism = declaresSpecialism(specialisms, 'content-standards');\n\n // AdCP 3.1+ release-precision capability fields per spec PR\n // `adcontextprotocol/adcp#3493`. Both fields are optional during the 3.x\n // SHOULD-emit phase; legacy 3.0 sellers won't carry them. Filter\n // `supported_versions` to strings — a misbehaving seller emitting\n // `['3.0', 42, null]` shouldn't poison the typed array. Match the\n // filtering that `extractVersionUnsupportedDetails` already does so the\n // two seller-input surfaces have the same safety contract.\n const supportedVersions = Array.isArray(response.adcp?.supported_versions)\n ? (response.adcp.supported_versions as unknown[]).filter((v): v is string => typeof v === 'string')\n : undefined;\n const buildVersion = typeof response.adcp?.build_version === 'string' ? response.adcp.build_version : undefined;\n\n // Per AdCP 3.0, `compliance_testing` is declared as a top-level\n // capability block, not as a value in `supported_protocols`. Normalize\n // legacy callers (who grep for `protocols.includes('compliance_testing')`)\n // by promoting the block into the protocols list at parse time — the\n // internal `AdcpCapabilities.protocols` shape is the SDK's own normalization\n // and doesn't need to match the wire.\n const wireProtocols = (response.supported_protocols ?? []) as AdcpProtocol[];\n const protocols =\n response.compliance_testing && !wireProtocols.includes('compliance_testing' as AdcpProtocol)\n ? ([...wireProtocols, 'compliance_testing'] as AdcpProtocol[])\n : wireProtocols;\n\n const features: MediaBuyFeatures = {\n inlineCreativeManagement: response.media_buy?.features?.inline_creative_management ?? false,\n propertyListFiltering: response.media_buy?.features?.property_list_filtering ?? false,\n contentStandards: response.media_buy?.features?.content_standards === true || declaresContentStandardsSpecialism,\n conversionTracking: response.media_buy?.features?.conversion_tracking ?? false,\n audienceTargeting: response.media_buy?.features?.audience_targeting ?? false,\n };\n\n let account: AccountCapabilities | undefined;\n if (response.account) {\n account = {\n requireOperatorAuth: response.account.require_operator_auth ?? false,\n authorizationEndpoint: response.account.authorization_endpoint,\n supportedBilling: response.account.supported_billing ?? [],\n defaultBilling: response.account.default_billing,\n requiredForProducts: response.account.required_for_products ?? false,\n sandbox: response.account.sandbox ?? false,\n };\n }\n\n let creative: CreativeCapabilities | undefined;\n if (response.creative) {\n creative = {\n supportsCompliance: response.creative.supports_compliance ?? false,\n hasCreativeLibrary: response.creative.has_creative_library ?? false,\n supportsGeneration: response.creative.supports_generation ?? false,\n supportsTransformation: response.creative.supports_transformation ?? false,\n };\n }\n\n // adcp.idempotency.replay_ttl_seconds is REQUIRED per spec when the seller\n // supports mutating tools. Absence is surfaced downstream as a fail-closed\n // error in getIdempotencyReplayTtlSeconds() — we deliberately do NOT default.\n let idempotency: IdempotencyCapabilities | undefined;\n const rawTtl = response.adcp?.idempotency?.replay_ttl_seconds;\n if (typeof rawTtl === 'number' && Number.isFinite(rawTtl) && rawTtl > 0) {\n idempotency = { replayTtlSeconds: rawTtl };\n }\n\n return {\n version: highestVersion >= 3 ? 'v3' : 'v2',\n majorVersions,\n supportedVersions,\n buildVersion,\n protocols,\n specialisms,\n features,\n account,\n creative,\n idempotency,\n extensions: response.extensions_supported ?? [],\n experimentalFeatures: Array.isArray(response.experimental_features)\n ? response.experimental_features.filter((f: unknown): f is string => typeof f === 'string')\n : undefined,\n publisherDomains: response.media_buy?.portfolio?.publisher_domains,\n channels: response.media_buy?.portfolio?.channels,\n lastUpdated: response.last_updated,\n _synthetic: false,\n _raw: response,\n };\n}\n\n/**\n * Check if capabilities indicate v3 support\n */\nexport function supportsV3(capabilities: AdcpCapabilities): boolean {\n return capabilities.majorVersions.includes(3);\n}\n\n/**\n * Check if a specific protocol is supported\n */\nexport function supportsProtocol(capabilities: AdcpCapabilities, protocol: AdcpProtocol): boolean {\n return capabilities.protocols.includes(protocol);\n}\n\n/**\n * Check if property list filtering is supported (v3 feature)\n */\nexport function supportsPropertyListFiltering(capabilities: AdcpCapabilities): boolean {\n return capabilities.features.propertyListFiltering ?? false;\n}\n\n/**\n * Check if content standards are supported (v3 feature)\n */\nexport function supportsContentStandards(capabilities: AdcpCapabilities): boolean {\n return hasContentStandardsSupport(capabilities);\n}\n\n/**\n * Check whether the seller advertises a creative library suitable for the\n * library-scoped `sync_creatives` workflow.\n *\n * This intentionally keys off `creative.has_creative_library`, not tool-list\n * presence. A seller can expose inline package creatives without a reusable\n * library, and `sync_creatives` is not safe to replace with inline\n * create/update media-buy calls unless the buyer supplies package context.\n */\nexport function supportsSyncCreatives(capabilities: AdcpCapabilities): boolean {\n return capabilities.creative?.hasCreativeLibrary === true;\n}\n\n/**\n * Check if the seller requires per-operator authentication\n */\nexport function requiresOperatorAuth(capabilities: AdcpCapabilities): boolean {\n return capabilities.account?.requireOperatorAuth ?? false;\n}\n\n/**\n * Check if an active account is required before calling get_products\n */\nexport function requiresAccountForProducts(capabilities: AdcpCapabilities): boolean {\n return capabilities.account?.requiredForProducts ?? false;\n}\n\n/**\n * Check if the seller supports sandbox accounts\n */\nexport function supportsSandbox(capabilities: AdcpCapabilities): boolean {\n return capabilities.account?.sandbox ?? false;\n}\n\n/**\n * Check if the agent has opted into a specific experimental AdCP surface.\n *\n * Experimental surfaces carry `x-status: experimental` in the spec and their\n * fields may change between minor releases. Consumers should gate any\n * reliance on experimental fields on a positive check here.\n *\n * @param capabilities — normalized capabilities from `parseCapabilitiesResponse`\n * @param featureId — dot-namespaced id (e.g. `brand.rights_lifecycle`)\n *\n * @example\n * ```ts\n * if (supportsExperimentalFeature(caps, 'brand.rights_lifecycle')) {\n * // safe to call acquire_rights / release_rights and read their responses\n * }\n * ```\n */\nexport function supportsExperimentalFeature(capabilities: AdcpCapabilities, featureId: string): boolean {\n return capabilities.experimentalFeatures?.includes(featureId) ?? false;\n}\n\n/**\n * Feature name that can be checked via supports()/require().\n *\n * Supported namespaces:\n * - Plain names resolve to media_buy.features (e.g., 'audience_targeting')\n * - 'media_buy', 'signals', etc. check supported_protocols\n * - 'ext:<name>' checks extensions_supported (e.g., 'ext:scope3')\n * - 'targeting.<name>' checks media_buy.execution.targeting (e.g., 'targeting.geo_countries')\n */\nexport type FeatureName = string;\n\n/**\n * Map of task names to features they require.\n *\n * When validateFeatures is enabled (default), SingleAgentClient checks\n * these features against seller capabilities before sending a request.\n * Tasks not listed here have no feature requirements.\n */\nexport const TASK_FEATURE_MAP: Record<string, FeatureName[]> = {\n // Core media buy tasks require the media_buy protocol\n get_products: ['media_buy'],\n // list_creative_formats intentionally omitted — serves both media-buy and creative domains\n create_media_buy: ['media_buy'],\n update_media_buy: ['media_buy'],\n get_media_buys: ['media_buy'],\n get_media_buy_delivery: ['media_buy'],\n provide_performance_feedback: ['media_buy'],\n\n // sync_creatives intentionally omitted — serves both media-buy and creative domains\n // list_creatives intentionally omitted — serves both media-buy and creative domains\n\n // Audience management\n sync_audiences: ['media_buy', 'audience_targeting'],\n sync_catalogs: ['media_buy'],\n\n // Event tracking / conversion\n sync_event_sources: ['media_buy', 'conversion_tracking'],\n log_event: ['media_buy', 'conversion_tracking'],\n\n // Signals protocol\n get_signals: ['signals'],\n activate_signal: ['signals'],\n\n // Creative protocol\n build_creative: ['creative'],\n list_transformers: ['creative'],\n preview_creative: ['creative'],\n\n // Governance protocol\n create_property_list: ['governance'],\n update_property_list: ['governance'],\n get_property_list: ['governance'],\n list_property_lists: ['governance'],\n delete_property_list: ['governance'],\n list_content_standards: ['governance', 'content_standards'],\n get_content_standards: ['governance', 'content_standards'],\n create_content_standards: ['governance', 'content_standards'],\n update_content_standards: ['governance', 'content_standards'],\n calibrate_content: ['governance', 'content_standards'],\n validate_content_delivery: ['governance', 'content_standards'],\n get_media_buy_artifacts: ['governance'],\n\n // Campaign governance\n sync_plans: ['governance'],\n check_governance: ['governance'],\n report_plan_outcome: ['governance'],\n get_plan_audit_logs: ['governance'],\n\n // Creative governance\n get_creative_features: ['governance'],\n\n // Sponsored intelligence protocol\n si_get_offering: ['sponsored_intelligence'],\n si_initiate_session: ['sponsored_intelligence'],\n si_send_message: ['sponsored_intelligence'],\n si_terminate_session: ['sponsored_intelligence'],\n\n // Trusted match protocol\n context_match: ['trusted_match'],\n identity_match: ['trusted_match'],\n\n // Compliance protocol\n comply_test_controller: ['compliance_testing'],\n\n // Brand rights protocol\n get_brand_identity: ['brand'],\n search_brands: ['brand'],\n get_rights: ['brand'],\n acquire_rights: ['brand'],\n update_rights: ['brand'],\n};\n\n/**\n * Map of media_buy.features field names to their camelCase keys in MediaBuyFeatures.\n */\nconst FEATURE_KEY_MAP: Record<string, keyof MediaBuyFeatures> = {\n inline_creative_management: 'inlineCreativeManagement',\n property_list_filtering: 'propertyListFiltering',\n content_standards: 'contentStandards',\n conversion_tracking: 'conversionTracking',\n audience_targeting: 'audienceTargeting',\n audience_management: 'audienceTargeting', // legacy alias\n};\n\n/**\n * Resolve whether a single feature is supported by the given capabilities.\n *\n * Absent = unsupported (returns false).\n */\nexport function resolveFeature(capabilities: AdcpCapabilities, feature: FeatureName): boolean {\n // Protocol-level check (e.g., 'media_buy', 'signals')\n if (capabilities.protocols.includes(feature as AdcpProtocol)) {\n return true;\n }\n\n // Extension check (e.g., 'ext:scope3')\n if (feature.startsWith('ext:')) {\n const extName = feature.slice(4);\n return capabilities.extensions.includes(extName);\n }\n\n // Experimental-surface check (e.g., 'experimental:brand.rights_lifecycle')\n if (feature.startsWith('experimental:')) {\n const featureId = feature.slice('experimental:'.length);\n return supportsExperimentalFeature(capabilities, featureId);\n }\n\n // Targeting check (e.g., 'targeting.geo_countries')\n if (feature.startsWith('targeting.')) {\n const targetingKey = feature.slice(10);\n const targeting = getRawNested(capabilities._raw, 'media_buy', 'execution', 'targeting');\n if (!targeting || typeof targeting !== 'object') return false;\n return !!(targeting as Record<string, unknown>)[targetingKey];\n }\n\n // Media buy features (e.g., 'audience_targeting', 'conversion_tracking')\n const featureKey = FEATURE_KEY_MAP[feature];\n if (featureKey) {\n if (featureKey === 'contentStandards') {\n return supportsContentStandards(capabilities);\n }\n return capabilities.features[featureKey] ?? false;\n }\n\n // Check raw media_buy.features for features not in the normalized map\n const rawFeatures = getRawNested(capabilities._raw, 'media_buy', 'features');\n if (rawFeatures && typeof rawFeatures === 'object' && feature in rawFeatures) {\n return !!(rawFeatures as Record<string, unknown>)[feature];\n }\n\n // Unknown feature — absent means unsupported\n return false;\n}\n\n/**\n * List all declared feature names from capabilities (for error messages).\n */\nexport function listDeclaredFeatures(capabilities: AdcpCapabilities): string[] {\n const features: string[] = [];\n\n // Protocols\n for (const p of capabilities.protocols) {\n features.push(p);\n }\n\n // Media buy features\n for (const [snakeKey, camelKey] of Object.entries(FEATURE_KEY_MAP)) {\n const declared =\n camelKey === 'contentStandards'\n ? supportsContentStandards(capabilities)\n : (capabilities.features[camelKey] ?? false);\n if (declared) {\n features.push(snakeKey);\n }\n }\n\n // Public specialism declarations\n for (const specialism of capabilities.specialisms ?? []) {\n features.push(`specialism:${specialism}`);\n }\n\n // Extensions\n for (const ext of capabilities.extensions) {\n features.push(`ext:${ext}`);\n }\n\n // Experimental surfaces\n for (const id of capabilities.experimentalFeatures ?? []) {\n features.push(`experimental:${id}`);\n }\n\n // Targeting (from raw response)\n const targeting = getRawNested(capabilities._raw, 'media_buy', 'execution', 'targeting');\n if (targeting && typeof targeting === 'object') {\n for (const [key, value] of Object.entries(targeting)) {\n if (value === true || (typeof value === 'object' && value !== null)) {\n features.push(`targeting.${key}`);\n }\n }\n }\n\n return [...new Set(features)];\n}\n"],"mappings":";;;;;;AA8MA,SAAS,aAAa,QAA6C,MAAyB;AAC1F,MAAI,UAAmB;AACvB,aAAW,OAAO,MAAM;AACtB,QAAI,WAAW,QAAQ,OAAO,YAAY,SAAU,QAAO;AAC3D,cAAW,QAAoC,GAAG;AAAA,EACpD;AACA,SAAO;AACT;AAkCO,MAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,gBAAgB,CAAC,eAAe,iBAAiB;AAEvD,MAAM,mBAAmB;AAAA;AAAA,EAE9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AACF;AAEO,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AACF;AAEO,MAAM,+BAA+B;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,sBAAsB,CAAC,iBAAiB,gBAAgB;AAE9D,MAAM,mBAAmB,CAAC,wBAAwB;AAMlD,MAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,uBAAuB,CAAC,sBAAsB,WAAW;AAE/D,MAAM,gBAAgB,CAAC,iBAAiB,eAAe;AAEvD,MAAM,iBAAiB,CAAC,yBAAyB,mBAAmB,YAAY;AASvF,MAAM,oBAAyD;AAAA,EAC7D,CAAC,iBAAiB,WAAW;AAAA,EAC7B,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,kBAAkB,YAAY;AAAA,EAC/B,CAAC,gBAAgB,UAAU;AAAA,EAC3B,CAAC,8BAA8B,wBAAwB;AAAA,EACvD,CAAC,qBAAqB,eAAe;AAAA,EACrC,CAAC,kBAAkB,oBAAoB;AAAA,EACvC,CAAC,oBAAoB,OAAO;AAC9B;AAKA,SAAS,yBAAyB,WAAwC;AACxE,QAAM,YAA4B,CAAC;AACnC,aAAW,CAAC,OAAO,QAAQ,KAAK,mBAAmB;AACjD,QAAI,MAAM,KAAK,OAAK,UAAU,IAAI,CAAC,CAAC,GAAG;AACrC,gBAAU,KAAK,QAAQ;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AACT;AAiBO,SAAS,6BAA6B,cAAgC,OAAqC;AAChH,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC;AAChD,QAAM,oBAAoB,iBAAiB,KAAK,OAAK,UAAU,IAAI,CAAC,CAAC;AACrE,MAAI,CAAC,qBAAqB,aAAa,UAAU,SAAS,oBAAoB,GAAG;AAC/E,WAAO;AAAA,EACT;AACA,UAAQ;AAAA,IACN;AAAA,EAGF;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,CAAC,GAAG,aAAa,WAAW,oBAAoB;AAAA,EAC7D;AACF;AAEO,SAAS,2BAA2B,OAAqC;AAC9E,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC;AAChD,QAAM,YAAY,yBAAyB,SAAS;AAGpD,QAAM,WAA6B;AAAA;AAAA,IAEjC,0BAA0B;AAAA;AAAA,IAE1B,uBAAuB;AAAA;AAAA,IAEvB,kBAAkB;AAAA;AAAA,IAElB,oBAAoB,qBAAqB,KAAK,OAAK,UAAU,IAAI,CAAC,CAAC;AAAA;AAAA,IAEnE,mBAAmB,UAAU,IAAI,gBAAgB;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe,CAAC,CAAC;AAAA,IACjB;AAAA,IACA;AAAA,IACA,YAAY,CAAC;AAAA,IACb,YAAY;AAAA,EACd;AACF;AA0BO,SAAS,6BAA6B,OAAqC;AAChF,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC;AAChD,QAAM,YAAY,yBAAyB,SAAS;AAEpD,QAAM,WAA6B;AAAA;AAAA,IAEjC,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,kBAAkB;AAAA,IAClB,oBAAoB,qBAAqB,KAAK,OAAK,UAAU,IAAI,CAAC,CAAC;AAAA,IACnE,mBAAmB,UAAU,IAAI,gBAAgB;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe,CAAC,CAAC;AAAA,IACjB;AAAA,IACA;AAAA,IACA,YAAY,CAAC;AAAA,IACb,YAAY;AAAA,EACd;AACF;AAuBO,SAAS,wBAAwB,MAAwB;AAC9D,MAAI,CAAC,cAAc,IAAI,EAAG,QAAO;AACjC,MAAI,cAAc,KAAK,IAAI,EAAG,QAAO;AACrC,MAAI,MAAM,QAAQ,KAAK,mBAAmB,EAAG,QAAO;AACpD,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,SAAS,KAAK,WAAS,cAAc,KAAK,KAAK,CAAC,CAAC;AAC1D;AAEA,SAAS,cAAc,OAAkD;AACvE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,mBAAmB,aAA4C,YAA6B;AACnG,SAAO,aAAa,SAAS,UAAU,MAAM;AAC/C;AAEA,SAAS,2BAA2B,cAA2E;AAC7G,SACE,aAAa,SAAS,qBAAqB,QAAQ,mBAAmB,aAAa,aAAa,mBAAmB;AAEvH;AAKO,SAAS,0BAA0B,UAAiC;AACzE,QAAM,gBAAiB,SAAS,MAAM,kBAAkB,CAAC,CAAC;AAC1D,QAAM,iBAAiB,KAAK,IAAI,GAAG,aAAa;AAChD,QAAM,cAAc,MAAM,QAAQ,SAAS,WAAW,IAClD,SAAS,YAAY,OAAO,CAAC,MAA4B,OAAO,MAAM,QAAQ,IAC9E;AACJ,QAAM,qCAAqC,mBAAmB,aAAa,mBAAmB;AAS9F,QAAM,oBAAoB,MAAM,QAAQ,SAAS,MAAM,kBAAkB,IACpE,SAAS,KAAK,mBAAiC,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAChG;AACJ,QAAM,eAAe,OAAO,SAAS,MAAM,kBAAkB,WAAW,SAAS,KAAK,gBAAgB;AAQtG,QAAM,gBAAiB,SAAS,uBAAuB,CAAC;AACxD,QAAM,YACJ,SAAS,sBAAsB,CAAC,cAAc,SAAS,oBAAoC,IACtF,CAAC,GAAG,eAAe,oBAAoB,IACxC;AAEN,QAAM,WAA6B;AAAA,IACjC,0BAA0B,SAAS,WAAW,UAAU,8BAA8B;AAAA,IACtF,uBAAuB,SAAS,WAAW,UAAU,2BAA2B;AAAA,IAChF,kBAAkB,SAAS,WAAW,UAAU,sBAAsB,QAAQ;AAAA,IAC9E,oBAAoB,SAAS,WAAW,UAAU,uBAAuB;AAAA,IACzE,mBAAmB,SAAS,WAAW,UAAU,sBAAsB;AAAA,EACzE;AAEA,MAAI;AACJ,MAAI,SAAS,SAAS;AACpB,cAAU;AAAA,MACR,qBAAqB,SAAS,QAAQ,yBAAyB;AAAA,MAC/D,uBAAuB,SAAS,QAAQ;AAAA,MACxC,kBAAkB,SAAS,QAAQ,qBAAqB,CAAC;AAAA,MACzD,gBAAgB,SAAS,QAAQ;AAAA,MACjC,qBAAqB,SAAS,QAAQ,yBAAyB;AAAA,MAC/D,SAAS,SAAS,QAAQ,WAAW;AAAA,IACvC;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,SAAS,UAAU;AACrB,eAAW;AAAA,MACT,oBAAoB,SAAS,SAAS,uBAAuB;AAAA,MAC7D,oBAAoB,SAAS,SAAS,wBAAwB;AAAA,MAC9D,oBAAoB,SAAS,SAAS,uBAAuB;AAAA,MAC7D,wBAAwB,SAAS,SAAS,2BAA2B;AAAA,IACvE;AAAA,EACF;AAKA,MAAI;AACJ,QAAM,SAAS,SAAS,MAAM,aAAa;AAC3C,MAAI,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,KAAK,SAAS,GAAG;AACvE,kBAAc,EAAE,kBAAkB,OAAO;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL,SAAS,kBAAkB,IAAI,OAAO;AAAA,IACtC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,SAAS,wBAAwB,CAAC;AAAA,IAC9C,sBAAsB,MAAM,QAAQ,SAAS,qBAAqB,IAC9D,SAAS,sBAAsB,OAAO,CAAC,MAA4B,OAAO,MAAM,QAAQ,IACxF;AAAA,IACJ,kBAAkB,SAAS,WAAW,WAAW;AAAA,IACjD,UAAU,SAAS,WAAW,WAAW;AAAA,IACzC,aAAa,SAAS;AAAA,IACtB,YAAY;AAAA,IACZ,MAAM;AAAA,EACR;AACF;AAKO,SAAS,WAAW,cAAyC;AAClE,SAAO,aAAa,cAAc,SAAS,CAAC;AAC9C;AAKO,SAAS,iBAAiB,cAAgC,UAAiC;AAChG,SAAO,aAAa,UAAU,SAAS,QAAQ;AACjD;AAKO,SAAS,8BAA8B,cAAyC;AACrF,SAAO,aAAa,SAAS,yBAAyB;AACxD;AAKO,SAAS,yBAAyB,cAAyC;AAChF,SAAO,2BAA2B,YAAY;AAChD;AAWO,SAAS,sBAAsB,cAAyC;AAC7E,SAAO,aAAa,UAAU,uBAAuB;AACvD;AAKO,SAAS,qBAAqB,cAAyC;AAC5E,SAAO,aAAa,SAAS,uBAAuB;AACtD;AAKO,SAAS,2BAA2B,cAAyC;AAClF,SAAO,aAAa,SAAS,uBAAuB;AACtD;AAKO,SAAS,gBAAgB,cAAyC;AACvE,SAAO,aAAa,SAAS,WAAW;AAC1C;AAmBO,SAAS,4BAA4B,cAAgC,WAA4B;AACtG,SAAO,aAAa,sBAAsB,SAAS,SAAS,KAAK;AACnE;AAoBO,MAAM,mBAAkD;AAAA;AAAA,EAE7D,cAAc,CAAC,WAAW;AAAA;AAAA,EAE1B,kBAAkB,CAAC,WAAW;AAAA,EAC9B,kBAAkB,CAAC,WAAW;AAAA,EAC9B,gBAAgB,CAAC,WAAW;AAAA,EAC5B,wBAAwB,CAAC,WAAW;AAAA,EACpC,8BAA8B,CAAC,WAAW;AAAA;AAAA;AAAA;AAAA,EAM1C,gBAAgB,CAAC,aAAa,oBAAoB;AAAA,EAClD,eAAe,CAAC,WAAW;AAAA;AAAA,EAG3B,oBAAoB,CAAC,aAAa,qBAAqB;AAAA,EACvD,WAAW,CAAC,aAAa,qBAAqB;AAAA;AAAA,EAG9C,aAAa,CAAC,SAAS;AAAA,EACvB,iBAAiB,CAAC,SAAS;AAAA;AAAA,EAG3B,gBAAgB,CAAC,UAAU;AAAA,EAC3B,mBAAmB,CAAC,UAAU;AAAA,EAC9B,kBAAkB,CAAC,UAAU;AAAA;AAAA,EAG7B,sBAAsB,CAAC,YAAY;AAAA,EACnC,sBAAsB,CAAC,YAAY;AAAA,EACnC,mBAAmB,CAAC,YAAY;AAAA,EAChC,qBAAqB,CAAC,YAAY;AAAA,EAClC,sBAAsB,CAAC,YAAY;AAAA,EACnC,wBAAwB,CAAC,cAAc,mBAAmB;AAAA,EAC1D,uBAAuB,CAAC,cAAc,mBAAmB;AAAA,EACzD,0BAA0B,CAAC,cAAc,mBAAmB;AAAA,EAC5D,0BAA0B,CAAC,cAAc,mBAAmB;AAAA,EAC5D,mBAAmB,CAAC,cAAc,mBAAmB;AAAA,EACrD,2BAA2B,CAAC,cAAc,mBAAmB;AAAA,EAC7D,yBAAyB,CAAC,YAAY;AAAA;AAAA,EAGtC,YAAY,CAAC,YAAY;AAAA,EACzB,kBAAkB,CAAC,YAAY;AAAA,EAC/B,qBAAqB,CAAC,YAAY;AAAA,EAClC,qBAAqB,CAAC,YAAY;AAAA;AAAA,EAGlC,uBAAuB,CAAC,YAAY;AAAA;AAAA,EAGpC,iBAAiB,CAAC,wBAAwB;AAAA,EAC1C,qBAAqB,CAAC,wBAAwB;AAAA,EAC9C,iBAAiB,CAAC,wBAAwB;AAAA,EAC1C,sBAAsB,CAAC,wBAAwB;AAAA;AAAA,EAG/C,eAAe,CAAC,eAAe;AAAA,EAC/B,gBAAgB,CAAC,eAAe;AAAA;AAAA,EAGhC,wBAAwB,CAAC,oBAAoB;AAAA;AAAA,EAG7C,oBAAoB,CAAC,OAAO;AAAA,EAC5B,eAAe,CAAC,OAAO;AAAA,EACvB,YAAY,CAAC,OAAO;AAAA,EACpB,gBAAgB,CAAC,OAAO;AAAA,EACxB,eAAe,CAAC,OAAO;AACzB;AAKA,MAAM,kBAA0D;AAAA,EAC9D,4BAA4B;AAAA,EAC5B,yBAAyB;AAAA,EACzB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,qBAAqB;AAAA;AACvB;AAOO,SAAS,eAAe,cAAgC,SAA+B;AAE5F,MAAI,aAAa,UAAU,SAAS,OAAuB,GAAG;AAC5D,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,WAAW,MAAM,GAAG;AAC9B,UAAM,UAAU,QAAQ,MAAM,CAAC;AAC/B,WAAO,aAAa,WAAW,SAAS,OAAO;AAAA,EACjD;AAGA,MAAI,QAAQ,WAAW,eAAe,GAAG;AACvC,UAAM,YAAY,QAAQ,MAAM,gBAAgB,MAAM;AACtD,WAAO,4BAA4B,cAAc,SAAS;AAAA,EAC5D;AAGA,MAAI,QAAQ,WAAW,YAAY,GAAG;AACpC,UAAM,eAAe,QAAQ,MAAM,EAAE;AACrC,UAAM,YAAY,aAAa,aAAa,MAAM,aAAa,aAAa,WAAW;AACvF,QAAI,CAAC,aAAa,OAAO,cAAc,SAAU,QAAO;AACxD,WAAO,CAAC,CAAE,UAAsC,YAAY;AAAA,EAC9D;AAGA,QAAM,aAAa,gBAAgB,OAAO;AAC1C,MAAI,YAAY;AACd,QAAI,eAAe,oBAAoB;AACrC,aAAO,yBAAyB,YAAY;AAAA,IAC9C;AACA,WAAO,aAAa,SAAS,UAAU,KAAK;AAAA,EAC9C;AAGA,QAAM,cAAc,aAAa,aAAa,MAAM,aAAa,UAAU;AAC3E,MAAI,eAAe,OAAO,gBAAgB,YAAY,WAAW,aAAa;AAC5E,WAAO,CAAC,CAAE,YAAwC,OAAO;AAAA,EAC3D;AAGA,SAAO;AACT;AAKO,SAAS,qBAAqB,cAA0C;AAC7E,QAAM,WAAqB,CAAC;AAG5B,aAAW,KAAK,aAAa,WAAW;AACtC,aAAS,KAAK,CAAC;AAAA,EACjB;AAGA,aAAW,CAAC,UAAU,QAAQ,KAAK,OAAO,QAAQ,eAAe,GAAG;AAClE,UAAM,WACJ,aAAa,qBACT,yBAAyB,YAAY,IACpC,aAAa,SAAS,QAAQ,KAAK;AAC1C,QAAI,UAAU;AACZ,eAAS,KAAK,QAAQ;AAAA,IACxB;AAAA,EACF;AAGA,aAAW,cAAc,aAAa,eAAe,CAAC,GAAG;AACvD,aAAS,KAAK,cAAc,UAAU,EAAE;AAAA,EAC1C;AAGA,aAAW,OAAO,aAAa,YAAY;AACzC,aAAS,KAAK,OAAO,GAAG,EAAE;AAAA,EAC5B;AAGA,aAAW,MAAM,aAAa,wBAAwB,CAAC,GAAG;AACxD,aAAS,KAAK,gBAAgB,EAAE,EAAE;AAAA,EACpC;AAGA,QAAM,YAAY,aAAa,aAAa,MAAM,aAAa,aAAa,WAAW;AACvF,MAAI,aAAa,OAAO,cAAc,UAAU;AAC9C,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACpD,UAAI,UAAU,QAAS,OAAO,UAAU,YAAY,UAAU,MAAO;AACnE,iBAAS,KAAK,aAAa,GAAG,EAAE;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AAC9B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/capabilities.ts"],"sourcesContent":["/**\n * AdCP Capabilities utilities\n *\n * Provides types and helpers for working with agent capabilities,\n * including synthetic capabilities for v2 servers that don't support\n * the get_adcp_capabilities tool.\n */\n\n/**\n * Detected AdCP major version\n */\nexport type AdcpMajorVersion = 2 | 3;\n\n/**\n * Supported AdCP protocols/domains\n */\nexport type AdcpProtocol =\n | 'media_buy'\n | 'signals'\n | 'governance'\n | 'creative'\n | 'sponsored_intelligence'\n | 'trusted_match'\n | 'compliance_testing'\n | 'brand'\n | 'measurement';\n\n/**\n * Media buy features available on the agent\n */\nexport interface MediaBuyFeatures {\n /**\n * Agent accepts package-scoped inline creative uploads in\n * create_media_buy/update_media_buy via `packages[].creatives`.\n *\n * This is distinct from creative-library support. Use\n * `supportsSyncCreatives(caps)` when deciding whether to call the\n * library-scoped `sync_creatives` tool.\n */\n inlineCreativeManagement?: boolean;\n /** Agent supports property_list filtering in get_products */\n propertyListFiltering?: boolean;\n /** Agent supports content standards validation */\n contentStandards?: boolean;\n /** Agent supports conversion event tracking (sync_event_sources, log_event) */\n conversionTracking?: boolean;\n /** Agent supports first-party CRM audience management (sync_audiences) */\n audienceTargeting?: boolean;\n}\n\n/**\n * Account management capabilities declared by the seller\n */\nexport interface AccountCapabilities {\n /**\n * Whether the seller requires operator-level credentials.\n * When false (default), the agent authenticates once and declares brands/operators via sync_accounts.\n * When true, each operator must authenticate independently.\n */\n requireOperatorAuth: boolean;\n\n /**\n * OAuth authorization endpoint for obtaining operator-level credentials.\n * Present when the seller supports OAuth for operator authentication.\n * May be absent even when requireOperatorAuth is true — in that case,\n * operators obtain credentials out-of-band (e.g., seller portal, API key).\n */\n authorizationEndpoint?: string;\n\n /**\n * Billing models this seller supports (e.g., 'operator', 'agent').\n */\n supportedBilling: ('operator' | 'agent' | 'advertiser')[];\n\n /**\n * Default billing model applied when omitted from sync_accounts.\n */\n defaultBilling?: 'operator' | 'agent' | 'advertiser';\n\n /**\n * Whether an active account is required before calling get_products.\n */\n requiredForProducts: boolean;\n\n /**\n * Whether the seller supports sandbox accounts for testing.\n * For implicit accounts (require_operator_auth: false), declare sandbox via sync_accounts\n * with sandbox: true and reference by natural key. For explicit accounts\n * (require_operator_auth: true), discover pre-existing test accounts via list_accounts.\n */\n sandbox: boolean;\n}\n\n/**\n * Creative protocol capabilities declared by the agent.\n */\nexport interface CreativeCapabilities {\n /** Agent can validate compliance requirements while building creatives */\n supportsCompliance: boolean;\n /** Agent exposes a creative library addressable via creative_id */\n hasCreativeLibrary: boolean;\n /** Agent can generate creatives from a natural-language brief */\n supportsGeneration: boolean;\n /** Agent can adapt an existing creative to a new format */\n supportsTransformation: boolean;\n}\n\n/**\n * Idempotency capabilities declared by the seller.\n *\n * Clients MUST NOT fall back to an assumed TTL when the seller omits this —\n * `getIdempotencyReplayTtlSeconds()` throws when the declaration is missing\n * on a v3 server rather than silently defaulting to 24h. A seller without the\n * declaration is non-compliant and unsafe for retry-sensitive operations.\n */\nexport interface IdempotencyCapabilities {\n /**\n * Seconds the seller retains cached `(principal, idempotency_key, payload)`\n * tuples. BYOK callers compare their persisted key's age against this to\n * decide whether a fresh key + natural-key lookup is safer than reusing.\n */\n replayTtlSeconds: number;\n}\n\n/**\n * Normalized capabilities response that works for both v2 and v3 servers\n */\nexport interface AdcpCapabilities {\n /** Detected version ('v2' or 'v3') */\n version: 'v2' | 'v3';\n\n /**\n * Array of supported major versions (e.g., [2] or [2, 3]).\n * @deprecated Use {@link supportedVersions} for release-precision negotiation.\n * Removed in AdCP 4.0 per spec PR `adcontextprotocol/adcp#3493`. Continues\n * to be emitted alongside the new field through 3.x.\n */\n majorVersions: AdcpMajorVersion[];\n\n /**\n * Array of supported AdCP releases at release precision (`'3.0'`, `'3.1'`,\n * `'3.1.0-beta.1'`). Stable releases use `MAJOR.MINOR`; pre-releases use\n * the full pre-release tag. Set when the seller is on AdCP 3.1+ per spec\n * PR `adcontextprotocol/adcp#3493`. `undefined` on legacy 3.0-only sellers.\n */\n supportedVersions?: string[];\n\n /**\n * Full semver build of the seller's released AdCP version (e.g. `'3.1.2'`,\n * `'3.1.0-beta.1+sha.abc'`). Advisory — patch differences within the same\n * release-precision are non-breaking by spec convention. `undefined` on\n * legacy 3.0-only sellers.\n */\n buildVersion?: string;\n\n /** Supported protocols */\n protocols: AdcpProtocol[];\n\n /** Public specialism ids declared by this agent */\n specialisms?: string[];\n\n /** Media buy specific features */\n features: MediaBuyFeatures;\n\n /** Account management capabilities */\n account?: AccountCapabilities;\n\n /** Creative protocol capabilities */\n creative?: CreativeCapabilities;\n\n /** Idempotency replay capabilities (v3 sellers declaring `adcp.idempotency`) */\n idempotency?: IdempotencyCapabilities;\n\n /** Supported extension namespaces (e.g., 'scope3', 'garm') */\n extensions: string[];\n\n /**\n * Experimental AdCP surfaces this agent implements. Dot-namespaced feature\n * ids (e.g. `brand.rights_lifecycle`, `governance.campaign`, `trusted_match.core`)\n * sellers declare when they opt into surfaces whose schemas carry\n * `x-status: experimental`. Consumers should gate any reliance on\n * experimental fields on presence of the matching id here.\n *\n * See https://adcontextprotocol.org/docs/reference/experimental-status\n */\n experimentalFeatures?: string[];\n\n /** Publisher domains covered by this agent */\n publisherDomains?: string[];\n\n /** Supported advertising channels */\n channels?: string[];\n\n /** Last updated timestamp (if provided by server) */\n lastUpdated?: string;\n\n /** Whether this was synthesized from tool list (v2) or from get_adcp_capabilities (v3) */\n _synthetic: boolean;\n\n /** Raw response from get_adcp_capabilities (only for v3) */\n _raw?: Record<string, unknown>;\n}\n\n/**\n * Safely traverse nested keys in a Record<string, unknown>.\n */\nfunction getRawNested(obj: Record<string, unknown> | undefined, ...keys: string[]): unknown {\n let current: unknown = obj;\n for (const key of keys) {\n if (current == null || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[key];\n }\n return current;\n}\n\n/**\n * Tool info for capability detection\n */\nexport interface ToolInfo {\n name: string;\n description?: string;\n}\n\n/**\n * Known AdCP tool names for protocol detection.\n * These map to task names in the AdCP schema index (kebab-case -> snake_case).\n *\n * Note: Some tools appear in multiple arrays (e.g., list_creative_formats is in\n * both MEDIA_BUY_TOOLS and CREATIVE_TOOLS). This is intentional — these tools\n * serve multiple domains, and their presence should activate all relevant\n * protocols when `detectProtocols()` runs.\n *\n * **Why these aren't manifest-derived (#1192).** The AdCP manifest\n * (`schemas/cache/{version}/manifest.json`) carries a single primary `protocol`\n * per tool — `list_creative_formats` is `media-buy` there, never `creative`.\n * That's an authoring convenience (where does the tool's spec page live), not\n * a capability-declaration semantic. The cross-listing here captures\n * operator reality: a CMP that exposes only `build_creative` /\n * `list_creative_formats` / `sync_creatives` IS a creative agent, and a buyer\n * discovering it via `tools/list` should see the `creative` protocol family.\n * Migrating to manifest-primary would silently flip `detectProtocols()`\n * results for cross-listed tools and break CMP↔DSP discovery flows. The\n * drift guard at `test/lib/capabilities-tools-drift.test.js` keeps the arrays\n * locked to recognized manifest tools (catches typos and removed-upstream\n * tools) without forcing the arrays to match the manifest's single-valued\n * view. See PR #1298 for the design rationale.\n */\nexport const MEDIA_BUY_TOOLS = [\n 'get_products',\n 'list_creative_formats', // Also in CREATIVE_TOOLS - serves both domains\n 'create_media_buy',\n 'update_media_buy',\n 'sync_creatives',\n 'list_creatives', // Also in CREATIVE_TOOLS - serves both domains\n 'get_media_buy_delivery',\n 'provide_performance_feedback',\n 'sync_audiences',\n 'sync_event_sources',\n 'sync_catalogs',\n 'log_event',\n] as const;\n\nexport const SIGNALS_TOOLS = ['get_signals', 'activate_signal'] as const;\n\nexport const GOVERNANCE_TOOLS = [\n // Property list management\n 'create_property_list',\n 'update_property_list',\n 'get_property_list',\n 'list_property_lists',\n 'delete_property_list',\n // Collection list management (program-level brand safety)\n 'create_collection_list',\n 'update_collection_list',\n 'get_collection_list',\n 'list_collection_lists',\n 'delete_collection_list',\n // Content standards\n 'list_content_standards',\n 'get_content_standards',\n 'create_content_standards',\n 'update_content_standards',\n 'calibrate_content',\n 'validate_content_delivery',\n 'get_media_buy_artifacts',\n // Campaign governance\n 'sync_plans',\n 'check_governance',\n 'report_plan_outcome',\n 'get_plan_audit_logs',\n // Creative governance\n 'get_creative_features',\n] as const;\n\nexport const CREATIVE_TOOLS = [\n 'build_creative',\n 'list_creative_formats',\n 'list_transformers',\n 'preview_creative',\n 'list_creatives',\n 'sync_creatives', // Also in MEDIA_BUY_TOOLS - serves both domains\n] as const;\n\nexport const SPONSORED_INTELLIGENCE_TOOLS = [\n 'si_get_offering',\n 'si_initiate_session',\n 'si_send_message',\n 'si_terminate_session',\n] as const;\n\nexport const TRUSTED_MATCH_TOOLS = ['context_match', 'identity_match'] as const;\n\nexport const COMPLIANCE_TOOLS = ['comply_test_controller'] as const;\n\n// `creative_approval` is intentionally absent — it's webhook-only (the buyer\n// POSTs to the `approval_webhook` URL returned by `acquire_rights`), not an\n// MCP/A2A tool the seller exposes. Adopters wire it via their HTTP server\n// using `BrandRightsPlatform.reviewCreativeApproval`.\nexport const BRAND_RIGHTS_TOOLS = [\n 'get_brand_identity',\n 'search_brands',\n 'get_rights',\n 'acquire_rights',\n 'update_rights',\n] as const;\n\nexport const EVENT_TRACKING_TOOLS = ['sync_event_sources', 'log_event'] as const;\n\nexport const ACCOUNT_TOOLS = ['list_accounts', 'sync_accounts'] as const;\n\nexport const PROTOCOL_TOOLS = ['get_adcp_capabilities', 'get_task_status', 'list_tasks'] as const;\n\n/**\n * Build synthetic capabilities from a list of available tools.\n * Used for v2 servers that don't support get_adcp_capabilities.\n */\n/**\n * Tool-group → protocol mapping for detection from tools/list.\n */\nconst TOOL_PROTOCOL_MAP: [readonly string[], AdcpProtocol][] = [\n [MEDIA_BUY_TOOLS, 'media_buy'],\n [SIGNALS_TOOLS, 'signals'],\n [GOVERNANCE_TOOLS, 'governance'],\n [CREATIVE_TOOLS, 'creative'],\n [SPONSORED_INTELLIGENCE_TOOLS, 'sponsored_intelligence'],\n [TRUSTED_MATCH_TOOLS, 'trusted_match'],\n [COMPLIANCE_TOOLS, 'compliance_testing'],\n [BRAND_RIGHTS_TOOLS, 'brand'],\n];\n\n/**\n * Detect protocols from tool names.\n */\nfunction detectProtocolsFromTools(toolNames: Set<string>): AdcpProtocol[] {\n const protocols: AdcpProtocol[] = [];\n for (const [tools, protocol] of TOOL_PROTOCOL_MAP) {\n if (tools.some(t => toolNames.has(t))) {\n protocols.push(protocol);\n }\n }\n return protocols;\n}\n\n/**\n * Augment declared capabilities with compliance_testing if the tool is present\n * but no `compliance_testing` capability block / protocol entry was advertised.\n *\n * Per AdCP 3.0, agents declare comply_test_controller support via the\n * top-level `capabilities.compliance_testing` block. `parseCapabilitiesResponse`\n * already promotes that block into the internal `protocols` list, so if we\n * reach this function with the tool present but the protocol missing, the\n * agent forgot the declaration. We auto-bridge (the SDK's internal type can\n * treat the agent as compliance-capable) and warn the agent once so they can\n * ship the proper block.\n *\n * Other protocols (media_buy, signals, etc.) are NOT augmented because a stub\n * or partial tool registration could produce false positives.\n */\nexport function augmentCapabilitiesFromTools(capabilities: AdcpCapabilities, tools: ToolInfo[]): AdcpCapabilities {\n const toolNames = new Set(tools.map(t => t.name));\n const hasComplianceTool = COMPLIANCE_TOOLS.some(t => toolNames.has(t));\n if (!hasComplianceTool || capabilities.protocols.includes('compliance_testing')) {\n return capabilities;\n }\n console.error(\n `[AdCP] Agent exposes comply_test_controller but omits the \\`compliance_testing\\` capability block ` +\n `from get_adcp_capabilities. Per AdCP 3.0, declare \\`capabilities.compliance_testing.scenarios\\` ` +\n `— not \\`supported_protocols\\`. The SDK is treating the agent as compliance-capable for this request.`\n );\n return {\n ...capabilities,\n protocols: [...capabilities.protocols, 'compliance_testing'],\n };\n}\n\nexport function buildSyntheticCapabilities(tools: ToolInfo[]): AdcpCapabilities {\n const toolNames = new Set(tools.map(t => t.name));\n const protocols = detectProtocolsFromTools(toolNames);\n\n // Detect features from tool presence\n const features: MediaBuyFeatures = {\n // Tool lists do not declare package-scoped inline creative upload support.\n inlineCreativeManagement: false,\n // Property list filtering is v3 only\n propertyListFiltering: false,\n // Content standards is v3 only\n contentStandards: false,\n // Conversion tracking if event tracking tools are available\n conversionTracking: EVENT_TRACKING_TOOLS.some(t => toolNames.has(t)),\n // Audience targeting if sync_audiences is available\n audienceTargeting: toolNames.has('sync_audiences'),\n };\n\n return {\n version: 'v2',\n majorVersions: [2],\n protocols,\n features,\n extensions: [],\n _synthetic: true,\n };\n}\n\n/**\n * Build synthetic v3 capabilities when the agent advertises\n * `get_adcp_capabilities` (a v3-only tool) but the call itself failed —\n * either the executor threw, or the response was non-success with no\n * structurally v3-shaped data (the case `looksLikeV3Capabilities` would\n * have caught).\n *\n * The agent is verifiably v3 because the v3-only discovery tool is\n * present in `tools/list`. Falling back to v2 synthetic in this case\n * triggers v2.5-schema lookups that have nothing to do with the original\n * failure, cascading \"AdCP schema data for version v2.5 not found\"\n * across every subsequent step. Treating as v3 (synthetic) lets the\n * caller continue against the right adapter set; the underlying\n * `get_adcp_capabilities` failure still surfaces in logs at the\n * call site.\n *\n * Sets `_synthetic: true` so version-compat checks know detail-level\n * fields (idempotency TTL, supportedVersions) are unknown — callers\n * skip those checks rather than throw `VersionUnsupportedError` on a\n * verifiably-v3 agent.\n *\n * Refs: #1217 (carve-out from #1197/closed), #1189 / #1201 (the v3-shape\n * heuristic this complements).\n */\nexport function buildSyntheticV3Capabilities(tools: ToolInfo[]): AdcpCapabilities {\n const toolNames = new Set(tools.map(t => t.name));\n const protocols = detectProtocolsFromTools(toolNames);\n\n const features: MediaBuyFeatures = {\n // Tool lists do not declare package-scoped inline creative upload support.\n inlineCreativeManagement: false,\n propertyListFiltering: false,\n contentStandards: false,\n conversionTracking: EVENT_TRACKING_TOOLS.some(t => toolNames.has(t)),\n audienceTargeting: toolNames.has('sync_audiences'),\n };\n\n return {\n version: 'v3',\n majorVersions: [3],\n protocols,\n features,\n extensions: [],\n _synthetic: true,\n };\n}\n\n/**\n * Heuristic: does this `get_adcp_capabilities` response look v3-shaped?\n *\n * Used by callers (e.g. SingleAgentClient.getCapabilities) when the response\n * fails strict schema validation but is structurally non-empty. The question\n * the heuristic answers is \"is this a v3 agent with a wire-shape bug, or a\n * v2 agent that happens to advertise the tool?\". Falling back to v2 in the\n * former case masks the original bug behind cascading v2.5-schema-not-found\n * errors; treating it as v3 surfaces the wire-shape bug at its source.\n *\n * Affirmative v3 signals (any one is enough):\n * - `adcp` block (only v3 servers carry the `{ major_versions, idempotency, ... }` envelope)\n * - `supported_protocols` array (v3-only top-level field)\n * - any v3 protocol-level capability block (`media_buy`, `signals`, `creative`, `brand`,\n * `governance`, `sponsored_intelligence`, `compliance_testing`, `account`)\n *\n * v2 servers don't expose `get_adcp_capabilities` at all (the tool itself is\n * a v3-only addition), so reaching this function with a non-empty payload\n * already strongly implies v3 — but we belt-and-suspenders the structural\n * check to avoid mis-promoting genuinely empty / null responses.\n */\nexport function looksLikeV3Capabilities(data: unknown): boolean {\n if (!isPlainObject(data)) return false;\n if (isPlainObject(data.adcp)) return true;\n if (Array.isArray(data.supported_protocols)) return true;\n const v3Blocks = [\n 'account',\n 'media_buy',\n 'signals',\n 'creative',\n 'brand',\n 'governance',\n 'sponsored_intelligence',\n 'compliance_testing',\n ] as const;\n return v3Blocks.some(block => isPlainObject(data[block]));\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction declaresSpecialism(specialisms: readonly string[] | undefined, specialism: string): boolean {\n return specialisms?.includes(specialism) === true;\n}\n\nfunction hasContentStandardsSupport(capabilities: Pick<AdcpCapabilities, 'features' | 'specialisms'>): boolean {\n return (\n capabilities.features.contentStandards === true || declaresSpecialism(capabilities.specialisms, 'content-standards')\n );\n}\n\n/**\n * Parse a get_adcp_capabilities response into normalized form\n */\nexport function parseCapabilitiesResponse(response: any): AdcpCapabilities {\n const majorVersions = (response.adcp?.major_versions ?? [2]) as AdcpMajorVersion[];\n const highestVersion = Math.max(...majorVersions) as AdcpMajorVersion;\n const specialisms = Array.isArray(response.specialisms)\n ? response.specialisms.filter((s: unknown): s is string => typeof s === 'string')\n : undefined;\n const declaresContentStandardsSpecialism = declaresSpecialism(specialisms, 'content-standards');\n\n // AdCP 3.1+ release-precision capability fields per spec PR\n // `adcontextprotocol/adcp#3493`. Both fields are optional during the 3.x\n // SHOULD-emit phase; legacy 3.0 sellers won't carry them. Filter\n // `supported_versions` to strings — a misbehaving seller emitting\n // `['3.0', 42, null]` shouldn't poison the typed array. Match the\n // filtering that `extractVersionUnsupportedDetails` already does so the\n // two seller-input surfaces have the same safety contract.\n const supportedVersions = Array.isArray(response.adcp?.supported_versions)\n ? (response.adcp.supported_versions as unknown[]).filter((v): v is string => typeof v === 'string')\n : undefined;\n const buildVersion = typeof response.adcp?.build_version === 'string' ? response.adcp.build_version : undefined;\n\n // Per AdCP 3.0, `compliance_testing` is declared as a top-level\n // capability block, not as a value in `supported_protocols`. Normalize\n // legacy callers (who grep for `protocols.includes('compliance_testing')`)\n // by promoting the block into the protocols list at parse time — the\n // internal `AdcpCapabilities.protocols` shape is the SDK's own normalization\n // and doesn't need to match the wire.\n const wireProtocols = (response.supported_protocols ?? []) as AdcpProtocol[];\n const protocols =\n response.compliance_testing && !wireProtocols.includes('compliance_testing' as AdcpProtocol)\n ? ([...wireProtocols, 'compliance_testing'] as AdcpProtocol[])\n : wireProtocols;\n\n const features: MediaBuyFeatures = {\n inlineCreativeManagement: response.media_buy?.features?.inline_creative_management ?? false,\n propertyListFiltering: response.media_buy?.features?.property_list_filtering ?? false,\n contentStandards: response.media_buy?.features?.content_standards === true || declaresContentStandardsSpecialism,\n conversionTracking: response.media_buy?.features?.conversion_tracking ?? false,\n audienceTargeting: response.media_buy?.features?.audience_targeting ?? false,\n };\n\n let account: AccountCapabilities | undefined;\n if (response.account) {\n account = {\n requireOperatorAuth: response.account.require_operator_auth ?? false,\n authorizationEndpoint: response.account.authorization_endpoint,\n supportedBilling: response.account.supported_billing ?? [],\n defaultBilling: response.account.default_billing,\n requiredForProducts: response.account.required_for_products ?? false,\n sandbox: response.account.sandbox ?? false,\n };\n }\n\n let creative: CreativeCapabilities | undefined;\n if (response.creative) {\n creative = {\n supportsCompliance: response.creative.supports_compliance ?? false,\n hasCreativeLibrary: response.creative.has_creative_library ?? false,\n supportsGeneration: response.creative.supports_generation ?? false,\n supportsTransformation: response.creative.supports_transformation ?? false,\n };\n }\n\n // adcp.idempotency.replay_ttl_seconds is REQUIRED per spec when the seller\n // supports mutating tools. Absence is surfaced downstream as a fail-closed\n // error in getIdempotencyReplayTtlSeconds() — we deliberately do NOT default.\n let idempotency: IdempotencyCapabilities | undefined;\n const rawTtl = response.adcp?.idempotency?.replay_ttl_seconds;\n if (typeof rawTtl === 'number' && Number.isFinite(rawTtl) && rawTtl > 0) {\n idempotency = { replayTtlSeconds: rawTtl };\n }\n\n return {\n version: highestVersion >= 3 ? 'v3' : 'v2',\n majorVersions,\n supportedVersions,\n buildVersion,\n protocols,\n specialisms,\n features,\n account,\n creative,\n idempotency,\n extensions: response.extensions_supported ?? [],\n experimentalFeatures: Array.isArray(response.experimental_features)\n ? response.experimental_features.filter((f: unknown): f is string => typeof f === 'string')\n : undefined,\n publisherDomains: response.media_buy?.portfolio?.publisher_domains,\n channels: response.media_buy?.portfolio?.channels,\n lastUpdated: response.last_updated,\n _synthetic: false,\n _raw: response,\n };\n}\n\n/**\n * Check if capabilities indicate v3 support\n */\nexport function supportsV3(capabilities: AdcpCapabilities): boolean {\n return capabilities.majorVersions.includes(3);\n}\n\n/**\n * Check if a specific protocol is supported\n */\nexport function supportsProtocol(capabilities: AdcpCapabilities, protocol: AdcpProtocol): boolean {\n return capabilities.protocols.includes(protocol);\n}\n\n/**\n * Check if property list filtering is supported (v3 feature)\n */\nexport function supportsPropertyListFiltering(capabilities: AdcpCapabilities): boolean {\n return capabilities.features.propertyListFiltering ?? false;\n}\n\n/**\n * Check if content standards are supported (v3 feature)\n */\nexport function supportsContentStandards(capabilities: AdcpCapabilities): boolean {\n return hasContentStandardsSupport(capabilities);\n}\n\n/**\n * Check whether the seller advertises a creative library suitable for the\n * library-scoped `sync_creatives` workflow.\n *\n * This intentionally keys off `creative.has_creative_library`, not tool-list\n * presence. A seller can expose inline package creatives without a reusable\n * library, and `sync_creatives` is not safe to replace with inline\n * create/update media-buy calls unless the buyer supplies package context.\n */\nexport function supportsSyncCreatives(capabilities: AdcpCapabilities): boolean {\n return capabilities.creative?.hasCreativeLibrary === true;\n}\n\n/**\n * Check if the seller requires per-operator authentication\n */\nexport function requiresOperatorAuth(capabilities: AdcpCapabilities): boolean {\n return capabilities.account?.requireOperatorAuth ?? false;\n}\n\n/**\n * Check if an active account is required before calling get_products\n */\nexport function requiresAccountForProducts(capabilities: AdcpCapabilities): boolean {\n return capabilities.account?.requiredForProducts ?? false;\n}\n\n/**\n * Check if the seller supports sandbox accounts\n */\nexport function supportsSandbox(capabilities: AdcpCapabilities): boolean {\n return capabilities.account?.sandbox ?? false;\n}\n\n/**\n * Check if the agent has opted into a specific experimental AdCP surface.\n *\n * Experimental surfaces carry `x-status: experimental` in the spec and their\n * fields may change between minor releases. Consumers should gate any\n * reliance on experimental fields on a positive check here.\n *\n * @param capabilities — normalized capabilities from `parseCapabilitiesResponse`\n * @param featureId — dot-namespaced id (e.g. `brand.rights_lifecycle`)\n *\n * @example\n * ```ts\n * if (supportsExperimentalFeature(caps, 'brand.rights_lifecycle')) {\n * // safe to call acquire_rights / release_rights and read their responses\n * }\n * ```\n */\nexport function supportsExperimentalFeature(capabilities: AdcpCapabilities, featureId: string): boolean {\n return capabilities.experimentalFeatures?.includes(featureId) ?? false;\n}\n\n/**\n * Feature name that can be checked via supports()/require().\n *\n * Supported namespaces:\n * - Plain names resolve to media_buy.features (e.g., 'audience_targeting')\n * - 'media_buy', 'signals', etc. check supported_protocols\n * - 'ext:<name>' checks extensions_supported (e.g., 'ext:scope3')\n * - 'targeting.<name>' checks media_buy.execution.targeting (e.g., 'targeting.geo_countries')\n */\nexport type FeatureName = string;\n\n/**\n * Map of task names to features they require.\n *\n * When validateFeatures is enabled (default), SingleAgentClient checks\n * these features against seller capabilities before sending a request.\n * Tasks not listed here have no feature requirements.\n */\nexport const TASK_FEATURE_MAP: Record<string, FeatureName[]> = {\n // Core media buy tasks require the media_buy protocol\n get_products: ['media_buy'],\n // list_creative_formats intentionally omitted — serves both media-buy and creative domains\n create_media_buy: ['media_buy'],\n update_media_buy: ['media_buy'],\n get_media_buys: ['media_buy'],\n get_media_buy_delivery: ['media_buy'],\n provide_performance_feedback: ['media_buy'],\n\n // sync_creatives intentionally omitted — serves both media-buy and creative domains\n // list_creatives intentionally omitted — serves both media-buy and creative domains\n\n // Audience management\n sync_audiences: ['media_buy', 'audience_targeting'],\n sync_catalogs: ['media_buy'],\n\n // Event tracking / conversion\n sync_event_sources: ['media_buy', 'conversion_tracking'],\n log_event: ['media_buy', 'conversion_tracking'],\n\n // Signals protocol\n get_signals: ['signals'],\n activate_signal: ['signals'],\n\n // Creative protocol\n build_creative: ['creative'],\n list_transformers: ['creative'],\n preview_creative: ['creative'],\n\n // Governance protocol\n create_property_list: ['governance'],\n update_property_list: ['governance'],\n get_property_list: ['governance'],\n list_property_lists: ['governance'],\n delete_property_list: ['governance'],\n list_content_standards: ['governance', 'content_standards'],\n get_content_standards: ['governance', 'content_standards'],\n create_content_standards: ['governance', 'content_standards'],\n update_content_standards: ['governance', 'content_standards'],\n calibrate_content: ['governance', 'content_standards'],\n validate_content_delivery: ['governance', 'content_standards'],\n get_media_buy_artifacts: ['governance'],\n\n // Campaign governance\n sync_plans: ['governance'],\n check_governance: ['governance'],\n report_plan_outcome: ['governance'],\n get_plan_audit_logs: ['governance'],\n\n // Creative governance\n get_creative_features: ['governance'],\n\n // Sponsored intelligence protocol\n si_get_offering: ['sponsored_intelligence'],\n si_initiate_session: ['sponsored_intelligence'],\n si_send_message: ['sponsored_intelligence'],\n si_terminate_session: ['sponsored_intelligence'],\n\n // Trusted match protocol\n context_match: ['trusted_match'],\n identity_match: ['trusted_match'],\n\n // Compliance protocol\n comply_test_controller: ['compliance_testing'],\n\n // Brand rights protocol\n get_brand_identity: ['brand'],\n search_brands: ['brand'],\n get_rights: ['brand'],\n acquire_rights: ['brand'],\n update_rights: ['brand'],\n};\n\n/**\n * Map of media_buy.features field names to their camelCase keys in MediaBuyFeatures.\n */\nconst FEATURE_KEY_MAP: Record<string, keyof MediaBuyFeatures> = {\n inline_creative_management: 'inlineCreativeManagement',\n property_list_filtering: 'propertyListFiltering',\n content_standards: 'contentStandards',\n conversion_tracking: 'conversionTracking',\n audience_targeting: 'audienceTargeting',\n audience_management: 'audienceTargeting', // legacy alias\n};\n\n/**\n * Resolve whether a single feature is supported by the given capabilities.\n *\n * Absent = unsupported (returns false).\n */\nexport function resolveFeature(capabilities: AdcpCapabilities, feature: FeatureName): boolean {\n // Protocol-level check (e.g., 'media_buy', 'signals')\n if (capabilities.protocols.includes(feature as AdcpProtocol)) {\n return true;\n }\n\n // Extension check (e.g., 'ext:scope3')\n if (feature.startsWith('ext:')) {\n const extName = feature.slice(4);\n return capabilities.extensions.includes(extName);\n }\n\n // Experimental-surface check (e.g., 'experimental:brand.rights_lifecycle')\n if (feature.startsWith('experimental:')) {\n const featureId = feature.slice('experimental:'.length);\n return supportsExperimentalFeature(capabilities, featureId);\n }\n\n // Targeting check (e.g., 'targeting.geo_countries')\n if (feature.startsWith('targeting.')) {\n const targetingKey = feature.slice(10);\n const targeting = getRawNested(capabilities._raw, 'media_buy', 'execution', 'targeting');\n if (!targeting || typeof targeting !== 'object') return false;\n return !!(targeting as Record<string, unknown>)[targetingKey];\n }\n\n // Media buy features (e.g., 'audience_targeting', 'conversion_tracking')\n const featureKey = FEATURE_KEY_MAP[feature];\n if (featureKey) {\n if (featureKey === 'contentStandards') {\n return supportsContentStandards(capabilities);\n }\n return capabilities.features[featureKey] ?? false;\n }\n\n // Check raw media_buy.features for features not in the normalized map\n const rawFeatures = getRawNested(capabilities._raw, 'media_buy', 'features');\n if (rawFeatures && typeof rawFeatures === 'object' && feature in rawFeatures) {\n return !!(rawFeatures as Record<string, unknown>)[feature];\n }\n\n // Unknown feature — absent means unsupported\n return false;\n}\n\n/**\n * List all declared feature names from capabilities (for error messages).\n */\nexport function listDeclaredFeatures(capabilities: AdcpCapabilities): string[] {\n const features: string[] = [];\n\n // Protocols\n for (const p of capabilities.protocols) {\n features.push(p);\n }\n\n // Media buy features\n for (const [snakeKey, camelKey] of Object.entries(FEATURE_KEY_MAP)) {\n const declared =\n camelKey === 'contentStandards'\n ? supportsContentStandards(capabilities)\n : (capabilities.features[camelKey] ?? false);\n if (declared) {\n features.push(snakeKey);\n }\n }\n\n // Public specialism declarations\n for (const specialism of capabilities.specialisms ?? []) {\n features.push(`specialism:${specialism}`);\n }\n\n // Extensions\n for (const ext of capabilities.extensions) {\n features.push(`ext:${ext}`);\n }\n\n // Experimental surfaces\n for (const id of capabilities.experimentalFeatures ?? []) {\n features.push(`experimental:${id}`);\n }\n\n // Targeting (from raw response)\n const targeting = getRawNested(capabilities._raw, 'media_buy', 'execution', 'targeting');\n if (targeting && typeof targeting === 'object') {\n for (const [key, value] of Object.entries(targeting)) {\n if (value === true || (typeof value === 'object' && value !== null)) {\n features.push(`targeting.${key}`);\n }\n }\n }\n\n return [...new Set(features)];\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
function rollupOptimizationMetricsFromProducts(products) {
|
|
8
2
|
const seen = /* @__PURE__ */ new Set();
|
|
9
3
|
for (const p of products) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/capability-rollups.ts"],"sourcesContent":["/**\n * Helpers for deriving seller-level capability summaries from the\n * product catalog. Some `get_adcp_capabilities.media_buy.*` fields are\n * rollups of facts that already live at the product level — hand-\n * maintaining the rollup is a drift surface (out of sync the moment a\n * product changes). These helpers compute the rollup so the declaration\n * stays mechanically derived.\n *\n * Adopters call the helpers at startup (or whenever their catalog\n * mutates) and pass the result to `platform.capabilities.*`:\n *\n * ```ts\n * import { rollupOptimizationMetricsFromProducts } from '@adcp/sdk';\n *\n * const products = await loadProductCatalog();\n * const platform: DecisioningPlatform = {\n * capabilities: {\n * supported_optimization_metrics: rollupOptimizationMetricsFromProducts(products),\n * // ...\n * },\n * };\n * ```\n *\n * @public\n */\n\nimport type { Product } from '../types/tools.generated';\n\nexport type OptimizationMetric = NonNullable<NonNullable<Product['metric_optimization']>['supported_metrics']>[number];\n\n/** Minimum shape needed to derive the rollup — accepts any object that\n * carries the spec's `metric_optimization.supported_metrics` array. */\nexport interface ProductMetricOptimizationLike {\n metric_optimization?: {\n supported_metrics?: ReadonlyArray<OptimizationMetric>;\n };\n}\n\n/**\n * Compute `media_buy.supported_optimization_metrics` from a product\n * catalog. Per AdCP 3.1 (adcp#4669), this field is the array union of\n * every product's `metric_optimization.supported_metrics`.\n *\n * Returns a sorted, de-duplicated array. Empty union → empty array;\n * callers SHOULD treat an empty result as \"omit the field\" (the wire\n * description says an absent field means \"seller declares no specific\n * guarantees\").\n *\n * Stable ordering (alphabetical) so the declaration doesn't churn on\n * insertion order. Pure function; safe to call repeatedly.\n *\n * @example\n * ```ts\n * const products: ProductMetricOptimizationLike[] = [\n * { metric_optimization: { supported_metrics: ['clicks', 'views'] } },\n * { metric_optimization: { supported_metrics: ['views', 'completed_views'] } },\n * ];\n * rollupOptimizationMetricsFromProducts(products);\n * // → ['clicks', 'completed_views', 'views']\n * ```\n */\nexport function rollupOptimizationMetricsFromProducts<T extends ProductMetricOptimizationLike = Product>(\n products: ReadonlyArray<T>\n): OptimizationMetric[] {\n const seen = new Set<OptimizationMetric>();\n for (const p of products) {\n const metrics = p.metric_optimization?.supported_metrics;\n if (!Array.isArray(metrics)) continue;\n for (const m of metrics) {\n if (typeof m === 'string' && m.length > 0) seen.add(m as OptimizationMetric);\n }\n }\n return Array.from(seen).sort();\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/capability-rollups.ts"],"sourcesContent":["/**\n * Helpers for deriving seller-level capability summaries from the\n * product catalog. Some `get_adcp_capabilities.media_buy.*` fields are\n * rollups of facts that already live at the product level — hand-\n * maintaining the rollup is a drift surface (out of sync the moment a\n * product changes). These helpers compute the rollup so the declaration\n * stays mechanically derived.\n *\n * Adopters call the helpers at startup (or whenever their catalog\n * mutates) and pass the result to `platform.capabilities.*`:\n *\n * ```ts\n * import { rollupOptimizationMetricsFromProducts } from '@adcp/sdk';\n *\n * const products = await loadProductCatalog();\n * const platform: DecisioningPlatform = {\n * capabilities: {\n * supported_optimization_metrics: rollupOptimizationMetricsFromProducts(products),\n * // ...\n * },\n * };\n * ```\n *\n * @public\n */\n\nimport type { Product } from '../types/tools.generated';\n\nexport type OptimizationMetric = NonNullable<NonNullable<Product['metric_optimization']>['supported_metrics']>[number];\n\n/** Minimum shape needed to derive the rollup — accepts any object that\n * carries the spec's `metric_optimization.supported_metrics` array. */\nexport interface ProductMetricOptimizationLike {\n metric_optimization?: {\n supported_metrics?: ReadonlyArray<OptimizationMetric>;\n };\n}\n\n/**\n * Compute `media_buy.supported_optimization_metrics` from a product\n * catalog. Per AdCP 3.1 (adcp#4669), this field is the array union of\n * every product's `metric_optimization.supported_metrics`.\n *\n * Returns a sorted, de-duplicated array. Empty union → empty array;\n * callers SHOULD treat an empty result as \"omit the field\" (the wire\n * description says an absent field means \"seller declares no specific\n * guarantees\").\n *\n * Stable ordering (alphabetical) so the declaration doesn't churn on\n * insertion order. Pure function; safe to call repeatedly.\n *\n * @example\n * ```ts\n * const products: ProductMetricOptimizationLike[] = [\n * { metric_optimization: { supported_metrics: ['clicks', 'views'] } },\n * { metric_optimization: { supported_metrics: ['views', 'completed_views'] } },\n * ];\n * rollupOptimizationMetricsFromProducts(products);\n * // → ['clicks', 'completed_views', 'views']\n * ```\n */\nexport function rollupOptimizationMetricsFromProducts<T extends ProductMetricOptimizationLike = Product>(\n products: ReadonlyArray<T>\n): OptimizationMetric[] {\n const seen = new Set<OptimizationMetric>();\n for (const p of products) {\n const metrics = p.metric_optimization?.supported_metrics;\n if (!Array.isArray(metrics)) continue;\n for (const m of metrics) {\n if (typeof m === 'string' && m.length > 0) seen.add(m as OptimizationMetric);\n }\n }\n return Array.from(seen).sort();\n}\n"],"mappings":"AA6DO,SAAS,sCACd,UACsB;AACtB,QAAM,OAAO,oBAAI,IAAwB;AACzC,aAAW,KAAK,UAAU;AACxB,UAAM,UAAU,EAAE,qBAAqB;AACvC,QAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAC7B,eAAW,KAAK,SAAS;AACvB,UAAI,OAAO,MAAM,YAAY,EAAE,SAAS,EAAG,MAAK,IAAI,CAAuB;AAAA,IAC7E;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI,EAAE,KAAK;AAC/B;","names":[]}
|