@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,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 { getOrCreateClient, runStep, getOrDiscoverProfile, validateResponseSchema } from "../client.mjs";
|
|
8
2
|
const V3_CHANNELS = /* @__PURE__ */ new Set([
|
|
9
3
|
"display",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/scenarios/schema-compliance.ts"],"sourcesContent":["/**\n * Schema Compliance Testing\n *\n * Validates that an agent's responses use correct v3 field names and enum values.\n * Uses GET-only operations — no writes required.\n *\n * Checks:\n * - Channel enum values (hard fail on invalid values)\n * - Pricing field names: fixed_price (not fixed_rate), floor_price top-level\n * - Format assets: assets array with required boolean (not assets_required)\n */\n\nimport type { Product } from '../../types/core.generated';\nimport type {\n GetProductsResponse,\n GetSignalsResponse,\n ListCreativeFormatsResponse,\n Format,\n} from '../../types/tools.generated';\nimport type { TestOptions, TestStepResult, AgentProfile, TaskResult } from '../types';\nimport { getOrCreateClient, runStep, getOrDiscoverProfile, validateResponseSchema } from '../client';\n\n// v3 channel taxonomy — 19 channels\nconst V3_CHANNELS = new Set([\n 'display',\n 'olv',\n 'social',\n 'search',\n 'ctv',\n 'linear_tv',\n 'radio',\n 'streaming_audio',\n 'podcast',\n 'dooh',\n 'ooh',\n 'print',\n 'cinema',\n 'email',\n 'gaming',\n 'retail_media',\n 'influencer',\n 'affiliate',\n 'product_placement',\n]);\n\nexport async function testSchemaCompliance(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n if (!profile.tools.includes('get_products') && !profile.tools.includes('get_signals')) {\n // Path A: no supported discovery tool — skip field-shape checks gracefully\n steps.push({\n step: 'Schema compliance check support',\n passed: true,\n duration_ms: 0,\n details: 'Agent does not advertise get_products or get_signals — discovery field-shape checks skipped',\n warnings: ['Schema compliance: no supported discovery tool (get_products, get_signals) found; checks skipped'],\n });\n // Fall through to list_creative_formats check below\n } else if (profile.tools.includes('get_signals') && !profile.tools.includes('get_products')) {\n // Path B: signals agent — validate GetSignalsResponse schema and field semantics\n const { result: signalsResult, step: signalsStep } = await runStep<TaskResult>(\n 'Get signals (schema compliance)',\n 'get_signals',\n async () =>\n client.getSignals({\n signal_spec: options.brief || 'Schema compliance test — retrieve all available signals',\n }) as Promise<TaskResult>\n );\n\n if (!signalsResult?.success || !signalsResult?.data) {\n signalsStep.passed = false;\n signalsStep.error = signalsResult?.error || 'get_signals returned no data';\n steps.push(signalsStep);\n return { steps, profile };\n }\n steps.push(signalsStep);\n\n const signalsData = signalsResult.data as GetSignalsResponse;\n // Zod schema validation covers required-field presence (signal_agent_segment_id, name, signal_type).\n steps.push(validateResponseSchema('get_signals', signalsData));\n\n const signals = signalsData.signals ?? [];\n steps.push({\n step: 'Validate signal required fields',\n passed: true,\n duration_ms: 0,\n details:\n signals.length === 0\n ? 'Agent returned no signals — field-shape checks skipped'\n : `${signals.length} signal(s) validated via schema check (signal_agent_segment_id, name, signal_type)`,\n warnings:\n signals.length === 0\n ? ['No signals returned; cannot validate signal_agent_segment_id, name, signal_type fields']\n : undefined,\n });\n // Fall through to list_creative_formats check below\n } else {\n // Path C: get_products present — existing product catalog checks\n const { result: productsResult, step: productsStep } = await runStep<TaskResult>(\n 'Get products (schema compliance)',\n 'get_products',\n async () =>\n client.getProducts({\n buying_mode: 'brief',\n brief: options.brief || 'Schema compliance test — retrieve all available products',\n brand: options.brand,\n }) as Promise<TaskResult>\n );\n\n if (!productsResult?.success || !productsResult?.data) {\n productsStep.passed = false;\n productsStep.error = productsResult?.error || 'get_products returned no data';\n steps.push(productsStep);\n return { steps, profile };\n }\n steps.push(productsStep);\n\n const data = productsResult.data as GetProductsResponse;\n const products: Product[] = data.products || [];\n\n // --- Zod schema validation (catches missing required fields + invalid enum values) ---\n steps.push(validateResponseSchema('get_products', data));\n\n if (products.length === 0) {\n steps.push({\n step: 'Schema compliance: no products to validate',\n passed: true,\n duration_ms: 0,\n details: 'Agent returned no products — schema compliance checks skipped',\n warnings: ['No products returned; cannot validate channel, pricing, or format field schemas'],\n });\n return { steps, profile };\n }\n\n // --- Channel enum validation (hard fail) ---\n const invalidChannels: string[] = [];\n const allChannels = new Set<string>();\n\n for (const product of products) {\n for (const channel of product.channels || []) {\n allChannels.add(channel);\n if (!V3_CHANNELS.has(channel)) {\n invalidChannels.push(`\"${channel}\" in product ${product.product_id}`);\n }\n }\n }\n\n steps.push({\n step: 'Validate channel enum values',\n passed: invalidChannels.length === 0,\n duration_ms: 0,\n details:\n invalidChannels.length === 0\n ? `All ${allChannels.size} channel value(s) are valid v3 channels: ${Array.from(allChannels).join(', ')}`\n : `Invalid channel values detected (not in v3 taxonomy): ${invalidChannels.join('; ')}`,\n error:\n invalidChannels.length > 0\n ? `Channel enum violations: ${invalidChannels.join('; ')}. Valid channels: ${Array.from(V3_CHANNELS).join(', ')}`\n : undefined,\n response_preview: JSON.stringify(\n {\n channels_found: Array.from(allChannels),\n invalid_channels: invalidChannels,\n },\n null,\n 2\n ),\n });\n\n // --- Pricing field name validation (warn, not fail) ---\n const pricingIssues: string[] = [];\n const pricingChecked: string[] = [];\n let fixedPriceFound = false;\n\n for (const product of products) {\n for (const option of product.pricing_options || []) {\n const optionId = option.pricing_option_id || '(unknown)';\n // Cast to Record for deprecated-field checks — compliance testing intentionally\n // probes fields that may not exist on the generated PricingOption union\n const raw = option as unknown as Record<string, unknown>;\n\n // Check for deprecated fixed_rate field\n if ('fixed_rate' in raw) {\n pricingIssues.push(`pricing_option ${optionId} uses deprecated \"fixed_rate\" — should be \"fixed_price\"`);\n }\n if ('fixed_price' in raw) {\n fixedPriceFound = true;\n pricingChecked.push(optionId);\n }\n\n // Check for floor_price inside price_guidance (deprecated location)\n const pg = raw.price_guidance as Record<string, unknown> | undefined;\n if (pg && 'floor' in pg) {\n pricingIssues.push(\n `pricing_option ${optionId} has \"floor\" inside price_guidance — should be top-level \"floor_price\"`\n );\n }\n if ('floor_price' in raw) {\n pricingChecked.push(`${optionId} (floor_price)`);\n }\n }\n }\n\n const pricingPassed = pricingIssues.length === 0;\n const pricingDetails =\n pricingIssues.length > 0\n ? `Pricing field issues: ${pricingIssues.join('; ')}`\n : fixedPriceFound\n ? `Pricing fields valid (checked ${pricingChecked.length} option(s))`\n : 'No fixed-price products found to validate (agent may be auction-only — cannot confirm field names)';\n\n steps.push({\n step: 'Validate pricing field names',\n passed: pricingPassed,\n duration_ms: 0,\n details: pricingDetails,\n error: pricingIssues.length > 0 ? pricingIssues.join('; ') : undefined,\n warnings:\n !fixedPriceFound && pricingIssues.length === 0\n ? [\n 'No fixed-price products found. If agent supports fixed pricing, verify it uses \"fixed_price\" (not \"fixed_rate\") and \"floor_price\" at the pricing option level (not inside price_guidance).',\n ]\n : undefined,\n response_preview: JSON.stringify(\n {\n issues: pricingIssues,\n options_checked: pricingChecked,\n },\n null,\n 2\n ),\n });\n }\n\n // --- Format assets structure (optional: list_creative_formats) ---\n // Runs for all agent types that advertise list_creative_formats, regardless of discovery path\n if (profile.tools.includes('list_creative_formats')) {\n const { result: formatsResult, step: formatsStep } = await runStep<TaskResult>(\n 'Get creative formats (check assets structure)',\n 'list_creative_formats',\n async () => client.listCreativeFormats({}) as Promise<TaskResult>\n );\n\n if (formatsResult?.success && formatsResult?.data) {\n steps.push(validateResponseSchema('list_creative_formats', formatsResult.data));\n const formatsData = formatsResult.data as ListCreativeFormatsResponse;\n const formats: Format[] = formatsData.formats || [];\n const assetsIssues: string[] = [];\n let formatsChecked = 0;\n\n for (const format of formats) {\n formatsChecked++;\n const formatIdStr = typeof format.format_id === 'object' ? format.format_id.id : String(format.format_id);\n // Check for deprecated assets_required field\n if ('assets_required' in format) {\n assetsIssues.push(\n `format ${formatIdStr} uses deprecated \"assets_required\" — should be \"assets\" array with \"required\" boolean`\n );\n }\n // Validate assets array structure\n if (Array.isArray(format.assets)) {\n for (const asset of format.assets) {\n if (!('required' in asset)) {\n assetsIssues.push(`format ${formatIdStr} asset missing \"required\" boolean field`);\n }\n }\n }\n }\n\n formatsStep.details =\n assetsIssues.length === 0\n ? `Format assets valid across ${formatsChecked} format(s)`\n : `Format asset issues: ${assetsIssues.join('; ')}`;\n formatsStep.passed = assetsIssues.length === 0;\n formatsStep.error = assetsIssues.length > 0 ? assetsIssues.join('; ') : undefined;\n }\n steps.push(formatsStep);\n }\n\n return { steps, profile };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/scenarios/schema-compliance.ts"],"sourcesContent":["/**\n * Schema Compliance Testing\n *\n * Validates that an agent's responses use correct v3 field names and enum values.\n * Uses GET-only operations — no writes required.\n *\n * Checks:\n * - Channel enum values (hard fail on invalid values)\n * - Pricing field names: fixed_price (not fixed_rate), floor_price top-level\n * - Format assets: assets array with required boolean (not assets_required)\n */\n\nimport type { Product } from '../../types/core.generated';\nimport type {\n GetProductsResponse,\n GetSignalsResponse,\n ListCreativeFormatsResponse,\n Format,\n} from '../../types/tools.generated';\nimport type { TestOptions, TestStepResult, AgentProfile, TaskResult } from '../types';\nimport { getOrCreateClient, runStep, getOrDiscoverProfile, validateResponseSchema } from '../client';\n\n// v3 channel taxonomy — 19 channels\nconst V3_CHANNELS = new Set([\n 'display',\n 'olv',\n 'social',\n 'search',\n 'ctv',\n 'linear_tv',\n 'radio',\n 'streaming_audio',\n 'podcast',\n 'dooh',\n 'ooh',\n 'print',\n 'cinema',\n 'email',\n 'gaming',\n 'retail_media',\n 'influencer',\n 'affiliate',\n 'product_placement',\n]);\n\nexport async function testSchemaCompliance(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n if (!profile.tools.includes('get_products') && !profile.tools.includes('get_signals')) {\n // Path A: no supported discovery tool — skip field-shape checks gracefully\n steps.push({\n step: 'Schema compliance check support',\n passed: true,\n duration_ms: 0,\n details: 'Agent does not advertise get_products or get_signals — discovery field-shape checks skipped',\n warnings: ['Schema compliance: no supported discovery tool (get_products, get_signals) found; checks skipped'],\n });\n // Fall through to list_creative_formats check below\n } else if (profile.tools.includes('get_signals') && !profile.tools.includes('get_products')) {\n // Path B: signals agent — validate GetSignalsResponse schema and field semantics\n const { result: signalsResult, step: signalsStep } = await runStep<TaskResult>(\n 'Get signals (schema compliance)',\n 'get_signals',\n async () =>\n client.getSignals({\n signal_spec: options.brief || 'Schema compliance test — retrieve all available signals',\n }) as Promise<TaskResult>\n );\n\n if (!signalsResult?.success || !signalsResult?.data) {\n signalsStep.passed = false;\n signalsStep.error = signalsResult?.error || 'get_signals returned no data';\n steps.push(signalsStep);\n return { steps, profile };\n }\n steps.push(signalsStep);\n\n const signalsData = signalsResult.data as GetSignalsResponse;\n // Zod schema validation covers required-field presence (signal_agent_segment_id, name, signal_type).\n steps.push(validateResponseSchema('get_signals', signalsData));\n\n const signals = signalsData.signals ?? [];\n steps.push({\n step: 'Validate signal required fields',\n passed: true,\n duration_ms: 0,\n details:\n signals.length === 0\n ? 'Agent returned no signals — field-shape checks skipped'\n : `${signals.length} signal(s) validated via schema check (signal_agent_segment_id, name, signal_type)`,\n warnings:\n signals.length === 0\n ? ['No signals returned; cannot validate signal_agent_segment_id, name, signal_type fields']\n : undefined,\n });\n // Fall through to list_creative_formats check below\n } else {\n // Path C: get_products present — existing product catalog checks\n const { result: productsResult, step: productsStep } = await runStep<TaskResult>(\n 'Get products (schema compliance)',\n 'get_products',\n async () =>\n client.getProducts({\n buying_mode: 'brief',\n brief: options.brief || 'Schema compliance test — retrieve all available products',\n brand: options.brand,\n }) as Promise<TaskResult>\n );\n\n if (!productsResult?.success || !productsResult?.data) {\n productsStep.passed = false;\n productsStep.error = productsResult?.error || 'get_products returned no data';\n steps.push(productsStep);\n return { steps, profile };\n }\n steps.push(productsStep);\n\n const data = productsResult.data as GetProductsResponse;\n const products: Product[] = data.products || [];\n\n // --- Zod schema validation (catches missing required fields + invalid enum values) ---\n steps.push(validateResponseSchema('get_products', data));\n\n if (products.length === 0) {\n steps.push({\n step: 'Schema compliance: no products to validate',\n passed: true,\n duration_ms: 0,\n details: 'Agent returned no products — schema compliance checks skipped',\n warnings: ['No products returned; cannot validate channel, pricing, or format field schemas'],\n });\n return { steps, profile };\n }\n\n // --- Channel enum validation (hard fail) ---\n const invalidChannels: string[] = [];\n const allChannels = new Set<string>();\n\n for (const product of products) {\n for (const channel of product.channels || []) {\n allChannels.add(channel);\n if (!V3_CHANNELS.has(channel)) {\n invalidChannels.push(`\"${channel}\" in product ${product.product_id}`);\n }\n }\n }\n\n steps.push({\n step: 'Validate channel enum values',\n passed: invalidChannels.length === 0,\n duration_ms: 0,\n details:\n invalidChannels.length === 0\n ? `All ${allChannels.size} channel value(s) are valid v3 channels: ${Array.from(allChannels).join(', ')}`\n : `Invalid channel values detected (not in v3 taxonomy): ${invalidChannels.join('; ')}`,\n error:\n invalidChannels.length > 0\n ? `Channel enum violations: ${invalidChannels.join('; ')}. Valid channels: ${Array.from(V3_CHANNELS).join(', ')}`\n : undefined,\n response_preview: JSON.stringify(\n {\n channels_found: Array.from(allChannels),\n invalid_channels: invalidChannels,\n },\n null,\n 2\n ),\n });\n\n // --- Pricing field name validation (warn, not fail) ---\n const pricingIssues: string[] = [];\n const pricingChecked: string[] = [];\n let fixedPriceFound = false;\n\n for (const product of products) {\n for (const option of product.pricing_options || []) {\n const optionId = option.pricing_option_id || '(unknown)';\n // Cast to Record for deprecated-field checks — compliance testing intentionally\n // probes fields that may not exist on the generated PricingOption union\n const raw = option as unknown as Record<string, unknown>;\n\n // Check for deprecated fixed_rate field\n if ('fixed_rate' in raw) {\n pricingIssues.push(`pricing_option ${optionId} uses deprecated \"fixed_rate\" — should be \"fixed_price\"`);\n }\n if ('fixed_price' in raw) {\n fixedPriceFound = true;\n pricingChecked.push(optionId);\n }\n\n // Check for floor_price inside price_guidance (deprecated location)\n const pg = raw.price_guidance as Record<string, unknown> | undefined;\n if (pg && 'floor' in pg) {\n pricingIssues.push(\n `pricing_option ${optionId} has \"floor\" inside price_guidance — should be top-level \"floor_price\"`\n );\n }\n if ('floor_price' in raw) {\n pricingChecked.push(`${optionId} (floor_price)`);\n }\n }\n }\n\n const pricingPassed = pricingIssues.length === 0;\n const pricingDetails =\n pricingIssues.length > 0\n ? `Pricing field issues: ${pricingIssues.join('; ')}`\n : fixedPriceFound\n ? `Pricing fields valid (checked ${pricingChecked.length} option(s))`\n : 'No fixed-price products found to validate (agent may be auction-only — cannot confirm field names)';\n\n steps.push({\n step: 'Validate pricing field names',\n passed: pricingPassed,\n duration_ms: 0,\n details: pricingDetails,\n error: pricingIssues.length > 0 ? pricingIssues.join('; ') : undefined,\n warnings:\n !fixedPriceFound && pricingIssues.length === 0\n ? [\n 'No fixed-price products found. If agent supports fixed pricing, verify it uses \"fixed_price\" (not \"fixed_rate\") and \"floor_price\" at the pricing option level (not inside price_guidance).',\n ]\n : undefined,\n response_preview: JSON.stringify(\n {\n issues: pricingIssues,\n options_checked: pricingChecked,\n },\n null,\n 2\n ),\n });\n }\n\n // --- Format assets structure (optional: list_creative_formats) ---\n // Runs for all agent types that advertise list_creative_formats, regardless of discovery path\n if (profile.tools.includes('list_creative_formats')) {\n const { result: formatsResult, step: formatsStep } = await runStep<TaskResult>(\n 'Get creative formats (check assets structure)',\n 'list_creative_formats',\n async () => client.listCreativeFormats({}) as Promise<TaskResult>\n );\n\n if (formatsResult?.success && formatsResult?.data) {\n steps.push(validateResponseSchema('list_creative_formats', formatsResult.data));\n const formatsData = formatsResult.data as ListCreativeFormatsResponse;\n const formats: Format[] = formatsData.formats || [];\n const assetsIssues: string[] = [];\n let formatsChecked = 0;\n\n for (const format of formats) {\n formatsChecked++;\n const formatIdStr = typeof format.format_id === 'object' ? format.format_id.id : String(format.format_id);\n // Check for deprecated assets_required field\n if ('assets_required' in format) {\n assetsIssues.push(\n `format ${formatIdStr} uses deprecated \"assets_required\" — should be \"assets\" array with \"required\" boolean`\n );\n }\n // Validate assets array structure\n if (Array.isArray(format.assets)) {\n for (const asset of format.assets) {\n if (!('required' in asset)) {\n assetsIssues.push(`format ${formatIdStr} asset missing \"required\" boolean field`);\n }\n }\n }\n }\n\n formatsStep.details =\n assetsIssues.length === 0\n ? `Format assets valid across ${formatsChecked} format(s)`\n : `Format asset issues: ${assetsIssues.join('; ')}`;\n formatsStep.passed = assetsIssues.length === 0;\n formatsStep.error = assetsIssues.length > 0 ? assetsIssues.join('; ') : undefined;\n }\n steps.push(formatsStep);\n }\n\n return { steps, profile };\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
|
import { randomUUID } from "crypto";
|
|
8
2
|
import { getOrCreateClient, runStep, getOrDiscoverProfile, discoverSignals, validateResponseSchema } from "../client.mjs";
|
|
9
3
|
async function testSignalsFlow(agentUrl, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/scenarios/signals.ts"],"sourcesContent":["/**\n * Signals Agent Testing Scenarios\n *\n * Tests signals agent capabilities including:\n * - get_signals\n * - activate_signal\n *\n * Discovers real signals from the agent, tests multiple signal types,\n * tests activation with various destination configurations,\n * and validates proper error handling for invalid signals.\n */\n\nimport { randomUUID } from 'crypto';\n\nimport type { TestOptions, TestStepResult, AgentProfile, TaskResult } from '../types';\nimport type { ActivateSignalSuccess, Destination, GetSignalsResponse } from '../../types/tools.generated';\nimport { getOrCreateClient, runStep, getOrDiscoverProfile, discoverSignals, validateResponseSchema } from '../client';\n\n/**\n * Test: Signals Flow (for signals agents)\n *\n * Flow: get_signals -> activate_signal (with real signal IDs)\n */\nexport async function testSignalsFlow(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n // Discover agent profile\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n // Discover available signals\n const {\n signals: discoveredSignals,\n rawSignals: firstRawSignals,\n step: signalsStep,\n schemaStep,\n } = await discoverSignals(client, profile, options);\n steps.push(signalsStep);\n if (schemaStep) steps.push(schemaStep);\n\n // Use mutable array to collect signals\n const allSignals: NonNullable<AgentProfile['supported_signals']> = discoveredSignals || [];\n let governanceRawSignals: GetSignalsResponse['signals'] = firstRawSignals;\n\n if (!signalsStep.passed || allSignals.length === 0) {\n // If get_signals failed or returned empty, try with more specific briefs\n const fallbackBriefs = [\n 'audience segments for technology enthusiasts',\n 'demographic targeting options',\n 'behavioral audience data',\n 'first-party data segments',\n ];\n\n for (const brief of fallbackBriefs) {\n const {\n signals: retrySignals,\n rawSignals: retryRawSignals,\n step: retryStep,\n } = await discoverSignals(client, profile, {\n ...options,\n brief,\n });\n\n retryStep.step = `Discover signals: \"${brief.substring(0, 30)}...\"`;\n steps.push(retryStep);\n\n if (retrySignals && retrySignals.length > 0) {\n allSignals.push(...retrySignals);\n governanceRawSignals = retryRawSignals;\n break;\n }\n }\n }\n\n // Store discovered signals in profile\n profile.supported_signals = allSignals;\n\n // Check for governance metadata on discovered signals (advisory).\n // restricted_attributes/policy_categories are defined on SignalDefinition\n // (the adagents.json signal_catalog), but may pass through on get_signals\n // response items via additionalProperties. We accept either surface here.\n const govSignals = governanceRawSignals ?? [];\n if (govSignals.length > 0) {\n type GovSignal = NonNullable<GetSignalsResponse['signals']>[number] & {\n restricted_attributes?: string[];\n policy_categories?: string[];\n };\n const withRestrictedAttrs = govSignals.filter(\n (s): s is GovSignal => ((s as GovSignal).restricted_attributes?.length ?? 0) > 0\n );\n const withPolicyCategories = govSignals.filter(\n (s): s is GovSignal => ((s as GovSignal).policy_categories?.length ?? 0) > 0\n );\n\n if (withRestrictedAttrs.length === 0 && withPolicyCategories.length === 0) {\n steps.push({\n step: 'Governance metadata on signals (advisory)',\n task: 'get_signals',\n passed: true,\n duration_ms: 0,\n details: `None of ${govSignals.length} signal(s) declare restricted_attributes or policy_categories. Governance agents will fall back to semantic inference for these signals.`,\n warnings: [\n 'Signals without declared governance metadata require LLM-based inference for compliance checking. Per AdCP 3.0, declare restricted_attributes and policy_categories on signal_catalog entries in adagents.json (they may also pass through on get_signals response items).',\n ],\n });\n } else {\n steps.push({\n step: 'Governance metadata on signals (advisory)',\n task: 'get_signals',\n passed: true,\n duration_ms: 0,\n details: `${withRestrictedAttrs.length}/${govSignals.length} signal(s) declare restricted_attributes, ${withPolicyCategories.length}/${govSignals.length} declare policy_categories`,\n });\n }\n }\n\n // If we still have no signals, we can't continue\n if (allSignals.length === 0) {\n steps.push({\n step: 'Signal activation tests',\n task: undefined,\n passed: false,\n duration_ms: 0,\n error: 'No signals discovered from agent - cannot test activation',\n });\n return { steps, profile };\n }\n\n // Select signals to test\n const signalsToTest = selectSignalsToTest(allSignals, options);\n\n // Test activate_signal with real signal IDs\n if (profile.tools.includes('activate_signal')) {\n for (const signal of signalsToTest) {\n // Test activation with various destination configurations\n const destinations = getTestDestinations();\n\n for (const destination of destinations.slice(0, 2)) {\n // Test max 2 destinations per signal\n const { result, step } = await runStep<TaskResult>(\n `Activate signal: ${signal.name || signal.signal_id} -> ${'platform' in destination ? destination.platform : destination.agent_url}`,\n 'activate_signal',\n async () =>\n client.activateSignal({\n signal_agent_segment_id: signal.signal_id,\n destinations: [destination],\n idempotency_key: randomUUID(),\n })\n );\n\n if (result?.success && result?.data) {\n steps.push(validateResponseSchema('activate_signal', result.data));\n const data = result.data as ActivateSignalSuccess;\n const firstDeployment = data.deployments?.[0];\n step.details = `Signal activation submitted`;\n step.response_preview = JSON.stringify(\n {\n deployments_count: data.deployments?.length,\n first_deployment: firstDeployment,\n destination: 'platform' in destination ? destination.platform : destination.agent_url,\n },\n null,\n 2\n );\n step.created_id = firstDeployment\n ? 'platform' in firstDeployment\n ? firstDeployment.platform\n : firstDeployment.agent_url\n : undefined;\n } else if (result && !result.success) {\n // Check if this is an expected failure (e.g., destination not supported)\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('invalid destination')) {\n step.passed = true;\n step.details = `Expected rejection: ${error}`;\n } else {\n step.passed = false;\n step.error = result.error || 'activate_signal failed';\n }\n }\n steps.push(step);\n }\n }\n\n // Test activation with invalid signal ID (error case)\n const { result: errorResult, step: errorStep } = await runStep<TaskResult>(\n 'Activate signal: invalid ID (error expected)',\n 'activate_signal',\n async () =>\n client.activateSignal({\n signal_agent_segment_id: 'INVALID_SIGNAL_ID_DOES_NOT_EXIST_12345',\n destinations: [\n {\n type: 'platform',\n platform: 'test-platform',\n account: 'test-account',\n },\n ],\n idempotency_key: randomUUID(),\n })\n );\n\n // This should fail - if it succeeds with invalid signal, that's a bug\n if (errorResult?.success) {\n errorStep.passed = false;\n errorStep.error = 'Expected error for invalid signal_id but got success';\n } else {\n errorStep.passed = true;\n errorStep.details = 'Correctly rejected invalid signal_id';\n }\n steps.push(errorStep);\n }\n\n return { steps, profile };\n}\n\n/**\n * Select which signals to test based on options\n */\nfunction selectSignalsToTest(\n signals: NonNullable<AgentProfile['supported_signals']>,\n options: TestOptions\n): NonNullable<AgentProfile['supported_signals']> {\n // If specific signal types requested, filter to those\n if (options.signal_types?.length) {\n const filtered = signals.filter(s => s.type && options.signal_types!.includes(s.type));\n if (filtered.length > 0) return filtered.slice(0, 3);\n }\n\n // Default: test one signal of each type, max 3 total\n const byType = new Map<string, NonNullable<AgentProfile['supported_signals']>[0]>();\n for (const signal of signals) {\n const type = signal.type || 'unknown';\n if (!byType.has(type)) {\n byType.set(type, signal);\n }\n }\n\n const selected = Array.from(byType.values()).slice(0, 3);\n return selected.length > 0 ? selected : signals.slice(0, 1);\n}\n\n/**\n * Get test destination configurations for signal activation\n */\nfunction getTestDestinations(): Destination[] {\n return [\n {\n type: 'platform',\n platform: 'dv360',\n account: 'test-dv360-account',\n },\n {\n type: 'platform',\n platform: 'trade-desk',\n account: 'test-ttd-account',\n },\n {\n type: 'platform',\n platform: 'meta',\n account: 'test-meta-account',\n },\n {\n type: 'platform',\n platform: 'google-ads',\n account: 'test-google-account',\n },\n ];\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/scenarios/signals.ts"],"sourcesContent":["/**\n * Signals Agent Testing Scenarios\n *\n * Tests signals agent capabilities including:\n * - get_signals\n * - activate_signal\n *\n * Discovers real signals from the agent, tests multiple signal types,\n * tests activation with various destination configurations,\n * and validates proper error handling for invalid signals.\n */\n\nimport { randomUUID } from 'crypto';\n\nimport type { TestOptions, TestStepResult, AgentProfile, TaskResult } from '../types';\nimport type { ActivateSignalSuccess, Destination, GetSignalsResponse } from '../../types/tools.generated';\nimport { getOrCreateClient, runStep, getOrDiscoverProfile, discoverSignals, validateResponseSchema } from '../client';\n\n/**\n * Test: Signals Flow (for signals agents)\n *\n * Flow: get_signals -> activate_signal (with real signal IDs)\n */\nexport async function testSignalsFlow(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n // Discover agent profile\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n // Discover available signals\n const {\n signals: discoveredSignals,\n rawSignals: firstRawSignals,\n step: signalsStep,\n schemaStep,\n } = await discoverSignals(client, profile, options);\n steps.push(signalsStep);\n if (schemaStep) steps.push(schemaStep);\n\n // Use mutable array to collect signals\n const allSignals: NonNullable<AgentProfile['supported_signals']> = discoveredSignals || [];\n let governanceRawSignals: GetSignalsResponse['signals'] = firstRawSignals;\n\n if (!signalsStep.passed || allSignals.length === 0) {\n // If get_signals failed or returned empty, try with more specific briefs\n const fallbackBriefs = [\n 'audience segments for technology enthusiasts',\n 'demographic targeting options',\n 'behavioral audience data',\n 'first-party data segments',\n ];\n\n for (const brief of fallbackBriefs) {\n const {\n signals: retrySignals,\n rawSignals: retryRawSignals,\n step: retryStep,\n } = await discoverSignals(client, profile, {\n ...options,\n brief,\n });\n\n retryStep.step = `Discover signals: \"${brief.substring(0, 30)}...\"`;\n steps.push(retryStep);\n\n if (retrySignals && retrySignals.length > 0) {\n allSignals.push(...retrySignals);\n governanceRawSignals = retryRawSignals;\n break;\n }\n }\n }\n\n // Store discovered signals in profile\n profile.supported_signals = allSignals;\n\n // Check for governance metadata on discovered signals (advisory).\n // restricted_attributes/policy_categories are defined on SignalDefinition\n // (the adagents.json signal_catalog), but may pass through on get_signals\n // response items via additionalProperties. We accept either surface here.\n const govSignals = governanceRawSignals ?? [];\n if (govSignals.length > 0) {\n type GovSignal = NonNullable<GetSignalsResponse['signals']>[number] & {\n restricted_attributes?: string[];\n policy_categories?: string[];\n };\n const withRestrictedAttrs = govSignals.filter(\n (s): s is GovSignal => ((s as GovSignal).restricted_attributes?.length ?? 0) > 0\n );\n const withPolicyCategories = govSignals.filter(\n (s): s is GovSignal => ((s as GovSignal).policy_categories?.length ?? 0) > 0\n );\n\n if (withRestrictedAttrs.length === 0 && withPolicyCategories.length === 0) {\n steps.push({\n step: 'Governance metadata on signals (advisory)',\n task: 'get_signals',\n passed: true,\n duration_ms: 0,\n details: `None of ${govSignals.length} signal(s) declare restricted_attributes or policy_categories. Governance agents will fall back to semantic inference for these signals.`,\n warnings: [\n 'Signals without declared governance metadata require LLM-based inference for compliance checking. Per AdCP 3.0, declare restricted_attributes and policy_categories on signal_catalog entries in adagents.json (they may also pass through on get_signals response items).',\n ],\n });\n } else {\n steps.push({\n step: 'Governance metadata on signals (advisory)',\n task: 'get_signals',\n passed: true,\n duration_ms: 0,\n details: `${withRestrictedAttrs.length}/${govSignals.length} signal(s) declare restricted_attributes, ${withPolicyCategories.length}/${govSignals.length} declare policy_categories`,\n });\n }\n }\n\n // If we still have no signals, we can't continue\n if (allSignals.length === 0) {\n steps.push({\n step: 'Signal activation tests',\n task: undefined,\n passed: false,\n duration_ms: 0,\n error: 'No signals discovered from agent - cannot test activation',\n });\n return { steps, profile };\n }\n\n // Select signals to test\n const signalsToTest = selectSignalsToTest(allSignals, options);\n\n // Test activate_signal with real signal IDs\n if (profile.tools.includes('activate_signal')) {\n for (const signal of signalsToTest) {\n // Test activation with various destination configurations\n const destinations = getTestDestinations();\n\n for (const destination of destinations.slice(0, 2)) {\n // Test max 2 destinations per signal\n const { result, step } = await runStep<TaskResult>(\n `Activate signal: ${signal.name || signal.signal_id} -> ${'platform' in destination ? destination.platform : destination.agent_url}`,\n 'activate_signal',\n async () =>\n client.activateSignal({\n signal_agent_segment_id: signal.signal_id,\n destinations: [destination],\n idempotency_key: randomUUID(),\n })\n );\n\n if (result?.success && result?.data) {\n steps.push(validateResponseSchema('activate_signal', result.data));\n const data = result.data as ActivateSignalSuccess;\n const firstDeployment = data.deployments?.[0];\n step.details = `Signal activation submitted`;\n step.response_preview = JSON.stringify(\n {\n deployments_count: data.deployments?.length,\n first_deployment: firstDeployment,\n destination: 'platform' in destination ? destination.platform : destination.agent_url,\n },\n null,\n 2\n );\n step.created_id = firstDeployment\n ? 'platform' in firstDeployment\n ? firstDeployment.platform\n : firstDeployment.agent_url\n : undefined;\n } else if (result && !result.success) {\n // Check if this is an expected failure (e.g., destination not supported)\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('invalid destination')) {\n step.passed = true;\n step.details = `Expected rejection: ${error}`;\n } else {\n step.passed = false;\n step.error = result.error || 'activate_signal failed';\n }\n }\n steps.push(step);\n }\n }\n\n // Test activation with invalid signal ID (error case)\n const { result: errorResult, step: errorStep } = await runStep<TaskResult>(\n 'Activate signal: invalid ID (error expected)',\n 'activate_signal',\n async () =>\n client.activateSignal({\n signal_agent_segment_id: 'INVALID_SIGNAL_ID_DOES_NOT_EXIST_12345',\n destinations: [\n {\n type: 'platform',\n platform: 'test-platform',\n account: 'test-account',\n },\n ],\n idempotency_key: randomUUID(),\n })\n );\n\n // This should fail - if it succeeds with invalid signal, that's a bug\n if (errorResult?.success) {\n errorStep.passed = false;\n errorStep.error = 'Expected error for invalid signal_id but got success';\n } else {\n errorStep.passed = true;\n errorStep.details = 'Correctly rejected invalid signal_id';\n }\n steps.push(errorStep);\n }\n\n return { steps, profile };\n}\n\n/**\n * Select which signals to test based on options\n */\nfunction selectSignalsToTest(\n signals: NonNullable<AgentProfile['supported_signals']>,\n options: TestOptions\n): NonNullable<AgentProfile['supported_signals']> {\n // If specific signal types requested, filter to those\n if (options.signal_types?.length) {\n const filtered = signals.filter(s => s.type && options.signal_types!.includes(s.type));\n if (filtered.length > 0) return filtered.slice(0, 3);\n }\n\n // Default: test one signal of each type, max 3 total\n const byType = new Map<string, NonNullable<AgentProfile['supported_signals']>[0]>();\n for (const signal of signals) {\n const type = signal.type || 'unknown';\n if (!byType.has(type)) {\n byType.set(type, signal);\n }\n }\n\n const selected = Array.from(byType.values()).slice(0, 3);\n return selected.length > 0 ? selected : signals.slice(0, 1);\n}\n\n/**\n * Get test destination configurations for signal activation\n */\nfunction getTestDestinations(): Destination[] {\n return [\n {\n type: 'platform',\n platform: 'dv360',\n account: 'test-dv360-account',\n },\n {\n type: 'platform',\n platform: 'trade-desk',\n account: 'test-ttd-account',\n },\n {\n type: 'platform',\n platform: 'meta',\n account: 'test-meta-account',\n },\n {\n type: 'platform',\n platform: 'google-ads',\n account: 'test-google-account',\n },\n ];\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
|
import { getOrCreateClient, runStep, getOrDiscoverProfile } from "../client.mjs";
|
|
8
2
|
import { SPONSORED_INTELLIGENCE_TOOLS } from "../../utils/capabilities.mjs";
|
|
9
3
|
async function testSISessionLifecycle(agentUrl, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/scenarios/sponsored-intelligence.ts"],"sourcesContent":["/**\n * Sponsored Intelligence (SI) Protocol Testing Scenarios (v3)\n *\n * Tests SI agent capabilities including:\n * - Session lifecycle (initiate -> messages -> terminate)\n * - Offering availability checks\n * - Message exchange patterns\n * - Handoff flows\n */\n\nimport type { TestOptions, TestStepResult, AgentProfile, TaskResult } from '../types';\nimport { getOrCreateClient, runStep, getOrDiscoverProfile } from '../client';\nimport { SPONSORED_INTELLIGENCE_TOOLS } from '../../utils/capabilities';\nimport type {\n SIGetOfferingRequest,\n SIGetOfferingResponse,\n SIInitiateSessionRequest,\n SIInitiateSessionResponse,\n SISendMessageRequest,\n SISendMessageResponse,\n SITerminateSessionRequest,\n SITerminateSessionResponse,\n} from '../../types/tools.generated';\n\n/**\n * Test: SI Session Lifecycle\n *\n * Flow: si_get_offering -> si_initiate_session -> si_send_message (x2-3)\n * -> si_terminate_session -> verify terminated\n */\nexport async function testSISessionLifecycle(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n // Discover agent profile\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n // Check if agent supports any SI tools\n const hasSITools = SPONSORED_INTELLIGENCE_TOOLS.some(t => profile.tools.includes(t));\n if (!hasSITools) {\n steps.push({\n step: 'SI support check',\n passed: false,\n duration_ms: 0,\n error: 'Agent does not support Sponsored Intelligence tools',\n details: `Required tools: ${SPONSORED_INTELLIGENCE_TOOLS.join(', ')}. Available: ${profile.tools.join(', ')}`,\n });\n return { steps, profile };\n }\n\n profile.supports_si = true;\n let sessionId: string | undefined;\n let offeringToken: string | undefined;\n let offeringAvailable = false;\n const collectedUIElements: unknown[][] = [];\n\n // Test: si_get_offering\n if (profile.tools.includes('si_get_offering')) {\n const offeringId = options.si_offering_id || 'e2e-test-offering';\n const { result, step } = await runStep<TaskResult>(\n 'Get SI offering',\n 'si_get_offering',\n async () =>\n client.siGetOffering({\n offering_id: offeringId,\n intent: options.si_context || 'E2E testing - checking SI offering availability',\n } as unknown as SIGetOfferingRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as SIGetOfferingResponse;\n const dataRecord = result.data as unknown as Record<string, unknown>;\n offeringAvailable = data.available === true;\n offeringToken = data.offering_token ?? undefined;\n step.details = offeringAvailable\n ? `Offering available${offeringToken ? ' (token received)' : ''}`\n : `Offering unavailable: ${data.unavailable_reason || 'no reason provided'}`;\n step.response_preview = JSON.stringify(\n {\n available: data.available,\n offering_token: offeringToken ? '***' : undefined,\n title: dataRecord.title,\n description: dataRecord.description,\n capabilities: dataRecord.capabilities,\n unavailable_reason: data.unavailable_reason,\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'SI not supported by this agent (expected for some agents)';\n } else {\n step.passed = false;\n step.error = result.error || 'si_get_offering failed';\n }\n }\n steps.push(step);\n }\n\n // Test: si_initiate_session\n if (profile.tools.includes('si_initiate_session')) {\n const { result, step } = await runStep<TaskResult>(\n 'Initiate SI session',\n 'si_initiate_session',\n async () =>\n client.siInitiateSession({\n offering_id: options.si_offering_id || 'e2e-test-offering',\n offering_token: offeringToken,\n intent: options.si_context || 'E2E testing - initiating conversation about products',\n identity: {\n consent_granted: false,\n anonymous_session_id: `e2e-anon-${Date.now()}`,\n },\n placement: 'e2e-test-placement',\n supported_capabilities: {\n modalities: {\n conversational: true,\n rich_media: true,\n },\n },\n } as unknown as SIInitiateSessionRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as SIInitiateSessionResponse;\n sessionId = data.session_id;\n step.created_id = sessionId;\n if (Array.isArray(data.response?.ui_elements) && data.response.ui_elements.length > 0) {\n collectedUIElements.push(data.response.ui_elements);\n }\n step.details = sessionId\n ? `Session created: ${sessionId}`\n : 'Session initiation completed (no session_id returned)';\n step.response_preview = JSON.stringify(\n {\n session_id: sessionId,\n response_message: data.response?.message?.substring(0, 100),\n has_ui_elements: !!data.response?.ui_elements?.length,\n negotiated_capabilities: data.negotiated_capabilities,\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'SI session initiation not supported by this agent';\n } else {\n step.passed = false;\n step.error = result.error || 'si_initiate_session failed';\n }\n }\n steps.push(step);\n }\n\n // Test: si_send_message (if we have a session)\n if (profile.tools.includes('si_send_message') && sessionId) {\n const testMessages = [\n 'What products do you have available?',\n 'Can you tell me more about your best seller?',\n 'What is the price range?',\n ];\n\n for (let i = 0; i < Math.min(testMessages.length, 3); i++) {\n const message = testMessages[i]!;\n const { result, step } = await runStep<TaskResult>(\n `Send message ${i + 1}: \"${message.substring(0, 30)}...\"`,\n 'si_send_message',\n async () =>\n client.siSendMessage({\n session_id: sessionId,\n message,\n metadata: {\n test_iteration: i + 1,\n },\n } as unknown as SISendMessageRequest) as Promise<TaskResult>\n );\n\n let sessionEnded = false;\n if (result?.success && result?.data) {\n const data = result.data as SISendMessageResponse;\n if (Array.isArray(data.response?.ui_elements) && data.response.ui_elements.length > 0) {\n collectedUIElements.push(data.response.ui_elements);\n }\n step.details = `Session status: ${data.session_status || 'active'}`;\n step.response_preview = JSON.stringify(\n {\n session_id: data.session_id,\n session_status: data.session_status,\n response_message: data.response?.message?.substring(0, 100),\n has_ui_elements: !!data.response?.ui_elements?.length,\n },\n null,\n 2\n );\n const status = data.session_status as string;\n sessionEnded = status === 'complete' || status === 'terminated';\n } else if (result && !result.success) {\n step.passed = false;\n step.error = result.error || 'si_send_message failed';\n }\n steps.push(step);\n // If session is no longer active, stop sending messages\n if (sessionEnded) {\n break;\n }\n }\n\n // Validate UI element schemas only when elements were actually returned\n if (collectedUIElements.length > 0) {\n steps.push(validateUIElements(collectedUIElements));\n }\n }\n\n // Test: si_terminate_session (if we have a session)\n if (profile.tools.includes('si_terminate_session') && sessionId) {\n const { result, step } = await runStep<TaskResult>(\n 'Terminate SI session',\n 'si_terminate_session',\n async () =>\n client.siTerminateSession({\n session_id: sessionId,\n reason: 'user_exit',\n termination_context: {\n summary: 'E2E test session completed successfully',\n },\n } as unknown as SITerminateSessionRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as SITerminateSessionResponse;\n step.details = data.terminated ? 'Session terminated' : 'Termination not confirmed';\n step.response_preview = JSON.stringify(\n {\n session_id: data.session_id,\n terminated: data.terminated,\n has_acp_handoff: !!data.acp_handoff,\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n step.passed = false;\n step.error = result.error || 'si_terminate_session failed';\n }\n steps.push(step);\n\n // Test: send message to terminated session (should fail)\n if (profile.tools.includes('si_send_message')) {\n const { result: errorResult, step: errorStep } = await runStep<TaskResult>(\n 'Send message to terminated session (error expected)',\n 'si_send_message',\n async () =>\n client.siSendMessage({\n session_id: sessionId,\n message: 'This should fail',\n } as unknown as SISendMessageRequest) as Promise<TaskResult>\n );\n\n if (errorResult?.success) {\n // Check if session_status indicates terminated\n const data = errorResult.data as SISendMessageResponse;\n const status = data.session_status as string;\n if (status === 'complete' || status === 'terminated') {\n errorStep.passed = true;\n errorStep.details = 'Session correctly reports terminated status';\n } else {\n errorStep.passed = false;\n errorStep.error = 'Expected error for terminated session but message was accepted';\n }\n } else {\n errorStep.passed = true;\n errorStep.details = 'Correctly rejected message to terminated session';\n }\n steps.push(errorStep);\n }\n }\n\n return { steps, profile };\n}\n\n// Valid UI element types per si-ui-element.json schema\nconst SI_UI_ELEMENT_TYPES = [\n 'text',\n 'link',\n 'image',\n 'product_card',\n 'carousel',\n 'action_button',\n 'app_handoff',\n 'integration_actions',\n] as const;\n\n// Required data fields per element type (per si-ui-element.json schema)\nconst SI_UI_ELEMENT_REQUIRED_FIELDS: Record<string, string[]> = {\n text: ['message'],\n link: ['url', 'label'],\n image: ['url', 'alt'],\n product_card: ['title', 'price'],\n carousel: ['items'],\n action_button: ['label', 'action'],\n app_handoff: [], // no required data fields in si-ui-element.json (uses top-level apps object)\n integration_actions: ['actions'],\n};\n\n/**\n * Validate UI elements collected from SI session responses.\n * Returns a single TestStepResult summarizing all found types and any violations.\n */\nfunction validateUIElements(elementArrays: unknown[][]): TestStepResult {\n const foundTypes = new Set<string>();\n const invalidElements: string[] = [];\n\n for (const elements of elementArrays) {\n for (const el of elements) {\n if (!el || typeof el !== 'object') {\n invalidElements.push('non-object element');\n continue;\n }\n const element = el as Record<string, unknown>;\n const type = element.type as string | undefined;\n\n if (!type) {\n invalidElements.push('element missing required \"type\" field');\n continue;\n }\n\n if (!SI_UI_ELEMENT_TYPES.includes(type as (typeof SI_UI_ELEMENT_TYPES)[number])) {\n invalidElements.push(`unknown type \"${type}\"`);\n continue;\n }\n\n foundTypes.add(type);\n\n // Check type-specific required fields in data\n const requiredFields = SI_UI_ELEMENT_REQUIRED_FIELDS[type];\n if (requiredFields && requiredFields.length > 0) {\n if (!element.data || typeof element.data !== 'object') {\n invalidElements.push(`${type} element missing required \"data\" object`);\n } else {\n const data = element.data as Record<string, unknown>;\n for (const field of requiredFields) {\n if (!(field in data)) {\n invalidElements.push(`${type} element missing required data.${field}`);\n }\n }\n }\n }\n }\n }\n\n const typesFound = Array.from(foundTypes);\n const passed = invalidElements.length === 0;\n\n return {\n step: 'Validate SI UI element schemas',\n passed,\n duration_ms: 0,\n details:\n typesFound.length > 0\n ? `Found ${typesFound.length} element type(s): ${typesFound.join(', ')}${invalidElements.length > 0 ? `. Violations: ${invalidElements.join('; ')}` : ''}`\n : 'No UI elements returned (agent may not support rich media)',\n error: passed ? undefined : `UI element schema violations: ${invalidElements.join('; ')}`,\n response_preview: JSON.stringify({ found_types: typesFound, invalid_elements: invalidElements }, null, 2),\n warnings: typesFound.length === 0 ? ['Agent returned no UI elements in this session'] : undefined,\n };\n}\n\n/**\n * Test: SI Handoff\n *\n * Tests the ACP handoff mechanism in si_terminate_session.\n * Flow: si_get_offering -> si_initiate_session -> si_send_message (purchase intent)\n * -> si_terminate_session (reason: handoff_transaction) -> validate acp_handoff structure\n */\nexport async function testSIHandoff(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n const hasRequiredTools =\n profile.tools.includes('si_initiate_session') && profile.tools.includes('si_terminate_session');\n if (!hasRequiredTools) {\n steps.push({\n step: 'SI handoff support check',\n passed: false,\n duration_ms: 0,\n error: 'Agent does not support si_initiate_session + si_terminate_session (required for handoff testing)',\n });\n return { steps, profile };\n }\n\n profile.supports_si = true;\n let sessionId: string | undefined;\n let offeringToken: string | undefined;\n\n // Get offering token if available\n if (profile.tools.includes('si_get_offering')) {\n const { result, step } = await runStep<TaskResult>(\n 'Get SI offering (handoff)',\n 'si_get_offering',\n async () =>\n client.siGetOffering({\n offering_id: options.si_offering_id || 'e2e-test-offering',\n intent: 'E2E testing - preparing for handoff flow',\n } as unknown as SIGetOfferingRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n offeringToken = (result.data as SIGetOfferingResponse).offering_token ?? undefined;\n step.details = 'Offering retrieved for handoff test';\n }\n steps.push(step);\n }\n\n // Initiate session\n const { result: initResult, step: initStep } = await runStep<TaskResult>(\n 'Initiate SI session (handoff)',\n 'si_initiate_session',\n async () =>\n client.siInitiateSession({\n offering_id: options.si_offering_id || 'e2e-test-offering',\n offering_token: offeringToken,\n intent: options.si_context || 'E2E testing - initiating session for handoff test',\n identity: {\n consent_granted: false,\n anonymous_session_id: `e2e-anon-${Date.now()}`,\n },\n placement: 'e2e-test-placement',\n supported_capabilities: {\n modalities: { conversational: true },\n },\n } as unknown as SIInitiateSessionRequest) as Promise<TaskResult>\n );\n\n if (initResult?.success && initResult?.data) {\n sessionId = (initResult.data as SIInitiateSessionResponse).session_id;\n initStep.details = sessionId ? `Session created: ${sessionId}` : 'Session created (no session_id)';\n } else if (initResult && !initResult.success) {\n const error = initResult.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n initStep.passed = true;\n initStep.details = 'SI not supported by this agent';\n } else {\n initStep.passed = false;\n initStep.error = initResult.error || 'si_initiate_session failed';\n }\n }\n steps.push(initStep);\n\n if (!sessionId) {\n return { steps, profile };\n }\n\n // Send a purchase-intent message to set up the handoff\n if (profile.tools.includes('si_send_message')) {\n const { result, step } = await runStep<TaskResult>(\n 'Send purchase intent message',\n 'si_send_message',\n async () =>\n client.siSendMessage({\n session_id: sessionId,\n message: \"I'd like to purchase this product. Can you set up a transaction?\",\n } as unknown as SISendMessageRequest) as Promise<TaskResult>\n );\n\n if (result?.success) {\n step.details = 'Purchase intent sent';\n } else if (result && !result.success) {\n step.passed = false;\n step.error = result.error || 'si_send_message failed';\n }\n steps.push(step);\n }\n\n // Terminate with handoff_transaction reason\n const { result: termResult, step: termStep } = await runStep<TaskResult>(\n 'Terminate SI session (handoff_transaction)',\n 'si_terminate_session',\n async () =>\n client.siTerminateSession({\n session_id: sessionId,\n reason: 'handoff_transaction',\n termination_context: {\n summary: 'E2E test - terminating for handoff validation',\n transaction_intent: {\n intent: 'purchase',\n },\n },\n } as unknown as SITerminateSessionRequest) as Promise<TaskResult>\n );\n\n let termData: SITerminateSessionResponse | undefined;\n if (termResult?.success && termResult?.data) {\n termData = termResult.data as SITerminateSessionResponse;\n termStep.details = termData.terminated\n ? `Terminated with${termData.acp_handoff ? '' : 'out'} ACP handoff`\n : 'Termination not confirmed';\n termStep.response_preview = JSON.stringify(\n {\n session_id: termData.session_id,\n terminated: termData.terminated,\n acp_handoff: termData.acp_handoff ? '(present)' : undefined,\n },\n null,\n 2\n );\n } else if (termResult && !termResult.success) {\n termStep.passed = false;\n termStep.error = termResult.error || 'si_terminate_session failed';\n }\n steps.push(termStep);\n\n // Validate acp_handoff structure (only when termination succeeded)\n if (termData) {\n if (termData.acp_handoff) {\n const handoff = termData.acp_handoff;\n const hasCheckoutUrl = typeof handoff.checkout_url === 'string';\n const hasCheckoutToken = typeof handoff.checkout_token === 'string';\n const hasAnyHandoffField = hasCheckoutUrl || hasCheckoutToken;\n\n steps.push({\n step: 'Validate ACP handoff structure',\n passed: hasAnyHandoffField,\n duration_ms: 0,\n details: hasAnyHandoffField\n ? `Handoff has ${[hasCheckoutUrl && 'checkout_url', hasCheckoutToken && 'checkout_token'].filter(Boolean).join(', ')}`\n : 'acp_handoff returned but missing both checkout_url and checkout_token',\n error: hasAnyHandoffField\n ? undefined\n : 'acp_handoff object present but has no checkout_url or checkout_token — at least one is required',\n response_preview: JSON.stringify(\n {\n has_checkout_url: hasCheckoutUrl,\n has_checkout_token: hasCheckoutToken,\n has_payload: !!handoff.payload,\n has_expires_at: !!handoff.expires_at,\n },\n null,\n 2\n ),\n });\n } else {\n steps.push({\n step: 'Validate ACP handoff structure',\n passed: true,\n duration_ms: 0,\n details: 'No acp_handoff in response (agent may not support transaction handoff)',\n warnings: ['Agent terminated with handoff_transaction reason but returned no acp_handoff object'],\n });\n }\n }\n\n return { steps, profile };\n}\n\n/**\n * Test: SI Availability Check\n *\n * Quick test to check SI offering availability without full session lifecycle\n */\nexport async function testSIAvailability(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n // Discover agent profile\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n // Check if agent supports si_get_offering\n if (!profile.tools.includes('si_get_offering')) {\n steps.push({\n step: 'SI availability check support',\n passed: false,\n duration_ms: 0,\n error: 'Agent does not support si_get_offering tool',\n });\n return { steps, profile };\n }\n\n profile.supports_si = true;\n\n // Test: si_get_offering with provided or default offering ID\n const offeringId = options.si_offering_id || 'e2e-test-offering';\n const { result, step } = await runStep<TaskResult>(\n 'Check SI offering availability',\n 'si_get_offering',\n async () =>\n client.siGetOffering({\n offering_id: offeringId,\n intent: options.si_context || 'E2E testing - checking SI availability',\n } as unknown as SIGetOfferingRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as SIGetOfferingResponse;\n const dataRecord = result.data as unknown as Record<string, unknown>;\n step.details = data.available\n ? 'SI offering is available'\n : `SI offering unavailable: ${data.unavailable_reason || 'no reason'}`;\n step.response_preview = JSON.stringify(\n {\n available: data.available,\n title: dataRecord.title,\n description: dataRecord.description,\n capabilities: dataRecord.capabilities,\n unavailable_reason: data.unavailable_reason,\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'SI not supported by this agent';\n } else {\n step.passed = false;\n step.error = result.error || 'si_get_offering failed';\n }\n }\n steps.push(step);\n\n // Test: si_get_offering with invalid offering ID (should return unavailable, not error)\n const { result: invalidResult, step: invalidStep } = await runStep<TaskResult>(\n 'Check invalid offering availability',\n 'si_get_offering',\n async () =>\n client.siGetOffering({\n offering_id: 'INVALID_OFFERING_ID_DOES_NOT_EXIST_12345',\n intent: 'E2E testing - checking unavailable offering',\n } as unknown as SIGetOfferingRequest) as Promise<TaskResult>\n );\n\n if (invalidResult?.success && invalidResult?.data) {\n const data = invalidResult.data as SIGetOfferingResponse;\n if (data.available === false) {\n invalidStep.passed = true;\n invalidStep.details = 'Correctly reports invalid offering as unavailable';\n } else {\n invalidStep.passed = false;\n invalidStep.error = 'Expected unavailable for invalid offering but got available';\n }\n invalidStep.response_preview = JSON.stringify(\n {\n available: data.available,\n unavailable_reason: data.unavailable_reason,\n },\n null,\n 2\n );\n } else if (invalidResult && !invalidResult.success) {\n // Also acceptable to return an error for invalid offering\n invalidStep.passed = true;\n invalidStep.details = 'Correctly rejected invalid offering ID';\n }\n steps.push(invalidStep);\n\n return { steps, profile };\n}\n\n/**\n * Check if agent has any SI protocol tools\n */\nexport function hasSITools(tools: string[]): boolean {\n return SPONSORED_INTELLIGENCE_TOOLS.some(t => tools.includes(t));\n}\n"],"mappings":"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","names":["hasSITools"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/scenarios/sponsored-intelligence.ts"],"sourcesContent":["/**\n * Sponsored Intelligence (SI) Protocol Testing Scenarios (v3)\n *\n * Tests SI agent capabilities including:\n * - Session lifecycle (initiate -> messages -> terminate)\n * - Offering availability checks\n * - Message exchange patterns\n * - Handoff flows\n */\n\nimport type { TestOptions, TestStepResult, AgentProfile, TaskResult } from '../types';\nimport { getOrCreateClient, runStep, getOrDiscoverProfile } from '../client';\nimport { SPONSORED_INTELLIGENCE_TOOLS } from '../../utils/capabilities';\nimport type {\n SIGetOfferingRequest,\n SIGetOfferingResponse,\n SIInitiateSessionRequest,\n SIInitiateSessionResponse,\n SISendMessageRequest,\n SISendMessageResponse,\n SITerminateSessionRequest,\n SITerminateSessionResponse,\n} from '../../types/tools.generated';\n\n/**\n * Test: SI Session Lifecycle\n *\n * Flow: si_get_offering -> si_initiate_session -> si_send_message (x2-3)\n * -> si_terminate_session -> verify terminated\n */\nexport async function testSISessionLifecycle(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n // Discover agent profile\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n // Check if agent supports any SI tools\n const hasSITools = SPONSORED_INTELLIGENCE_TOOLS.some(t => profile.tools.includes(t));\n if (!hasSITools) {\n steps.push({\n step: 'SI support check',\n passed: false,\n duration_ms: 0,\n error: 'Agent does not support Sponsored Intelligence tools',\n details: `Required tools: ${SPONSORED_INTELLIGENCE_TOOLS.join(', ')}. Available: ${profile.tools.join(', ')}`,\n });\n return { steps, profile };\n }\n\n profile.supports_si = true;\n let sessionId: string | undefined;\n let offeringToken: string | undefined;\n let offeringAvailable = false;\n const collectedUIElements: unknown[][] = [];\n\n // Test: si_get_offering\n if (profile.tools.includes('si_get_offering')) {\n const offeringId = options.si_offering_id || 'e2e-test-offering';\n const { result, step } = await runStep<TaskResult>(\n 'Get SI offering',\n 'si_get_offering',\n async () =>\n client.siGetOffering({\n offering_id: offeringId,\n intent: options.si_context || 'E2E testing - checking SI offering availability',\n } as unknown as SIGetOfferingRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as SIGetOfferingResponse;\n const dataRecord = result.data as unknown as Record<string, unknown>;\n offeringAvailable = data.available === true;\n offeringToken = data.offering_token ?? undefined;\n step.details = offeringAvailable\n ? `Offering available${offeringToken ? ' (token received)' : ''}`\n : `Offering unavailable: ${data.unavailable_reason || 'no reason provided'}`;\n step.response_preview = JSON.stringify(\n {\n available: data.available,\n offering_token: offeringToken ? '***' : undefined,\n title: dataRecord.title,\n description: dataRecord.description,\n capabilities: dataRecord.capabilities,\n unavailable_reason: data.unavailable_reason,\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'SI not supported by this agent (expected for some agents)';\n } else {\n step.passed = false;\n step.error = result.error || 'si_get_offering failed';\n }\n }\n steps.push(step);\n }\n\n // Test: si_initiate_session\n if (profile.tools.includes('si_initiate_session')) {\n const { result, step } = await runStep<TaskResult>(\n 'Initiate SI session',\n 'si_initiate_session',\n async () =>\n client.siInitiateSession({\n offering_id: options.si_offering_id || 'e2e-test-offering',\n offering_token: offeringToken,\n intent: options.si_context || 'E2E testing - initiating conversation about products',\n identity: {\n consent_granted: false,\n anonymous_session_id: `e2e-anon-${Date.now()}`,\n },\n placement: 'e2e-test-placement',\n supported_capabilities: {\n modalities: {\n conversational: true,\n rich_media: true,\n },\n },\n } as unknown as SIInitiateSessionRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as SIInitiateSessionResponse;\n sessionId = data.session_id;\n step.created_id = sessionId;\n if (Array.isArray(data.response?.ui_elements) && data.response.ui_elements.length > 0) {\n collectedUIElements.push(data.response.ui_elements);\n }\n step.details = sessionId\n ? `Session created: ${sessionId}`\n : 'Session initiation completed (no session_id returned)';\n step.response_preview = JSON.stringify(\n {\n session_id: sessionId,\n response_message: data.response?.message?.substring(0, 100),\n has_ui_elements: !!data.response?.ui_elements?.length,\n negotiated_capabilities: data.negotiated_capabilities,\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'SI session initiation not supported by this agent';\n } else {\n step.passed = false;\n step.error = result.error || 'si_initiate_session failed';\n }\n }\n steps.push(step);\n }\n\n // Test: si_send_message (if we have a session)\n if (profile.tools.includes('si_send_message') && sessionId) {\n const testMessages = [\n 'What products do you have available?',\n 'Can you tell me more about your best seller?',\n 'What is the price range?',\n ];\n\n for (let i = 0; i < Math.min(testMessages.length, 3); i++) {\n const message = testMessages[i]!;\n const { result, step } = await runStep<TaskResult>(\n `Send message ${i + 1}: \"${message.substring(0, 30)}...\"`,\n 'si_send_message',\n async () =>\n client.siSendMessage({\n session_id: sessionId,\n message,\n metadata: {\n test_iteration: i + 1,\n },\n } as unknown as SISendMessageRequest) as Promise<TaskResult>\n );\n\n let sessionEnded = false;\n if (result?.success && result?.data) {\n const data = result.data as SISendMessageResponse;\n if (Array.isArray(data.response?.ui_elements) && data.response.ui_elements.length > 0) {\n collectedUIElements.push(data.response.ui_elements);\n }\n step.details = `Session status: ${data.session_status || 'active'}`;\n step.response_preview = JSON.stringify(\n {\n session_id: data.session_id,\n session_status: data.session_status,\n response_message: data.response?.message?.substring(0, 100),\n has_ui_elements: !!data.response?.ui_elements?.length,\n },\n null,\n 2\n );\n const status = data.session_status as string;\n sessionEnded = status === 'complete' || status === 'terminated';\n } else if (result && !result.success) {\n step.passed = false;\n step.error = result.error || 'si_send_message failed';\n }\n steps.push(step);\n // If session is no longer active, stop sending messages\n if (sessionEnded) {\n break;\n }\n }\n\n // Validate UI element schemas only when elements were actually returned\n if (collectedUIElements.length > 0) {\n steps.push(validateUIElements(collectedUIElements));\n }\n }\n\n // Test: si_terminate_session (if we have a session)\n if (profile.tools.includes('si_terminate_session') && sessionId) {\n const { result, step } = await runStep<TaskResult>(\n 'Terminate SI session',\n 'si_terminate_session',\n async () =>\n client.siTerminateSession({\n session_id: sessionId,\n reason: 'user_exit',\n termination_context: {\n summary: 'E2E test session completed successfully',\n },\n } as unknown as SITerminateSessionRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as SITerminateSessionResponse;\n step.details = data.terminated ? 'Session terminated' : 'Termination not confirmed';\n step.response_preview = JSON.stringify(\n {\n session_id: data.session_id,\n terminated: data.terminated,\n has_acp_handoff: !!data.acp_handoff,\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n step.passed = false;\n step.error = result.error || 'si_terminate_session failed';\n }\n steps.push(step);\n\n // Test: send message to terminated session (should fail)\n if (profile.tools.includes('si_send_message')) {\n const { result: errorResult, step: errorStep } = await runStep<TaskResult>(\n 'Send message to terminated session (error expected)',\n 'si_send_message',\n async () =>\n client.siSendMessage({\n session_id: sessionId,\n message: 'This should fail',\n } as unknown as SISendMessageRequest) as Promise<TaskResult>\n );\n\n if (errorResult?.success) {\n // Check if session_status indicates terminated\n const data = errorResult.data as SISendMessageResponse;\n const status = data.session_status as string;\n if (status === 'complete' || status === 'terminated') {\n errorStep.passed = true;\n errorStep.details = 'Session correctly reports terminated status';\n } else {\n errorStep.passed = false;\n errorStep.error = 'Expected error for terminated session but message was accepted';\n }\n } else {\n errorStep.passed = true;\n errorStep.details = 'Correctly rejected message to terminated session';\n }\n steps.push(errorStep);\n }\n }\n\n return { steps, profile };\n}\n\n// Valid UI element types per si-ui-element.json schema\nconst SI_UI_ELEMENT_TYPES = [\n 'text',\n 'link',\n 'image',\n 'product_card',\n 'carousel',\n 'action_button',\n 'app_handoff',\n 'integration_actions',\n] as const;\n\n// Required data fields per element type (per si-ui-element.json schema)\nconst SI_UI_ELEMENT_REQUIRED_FIELDS: Record<string, string[]> = {\n text: ['message'],\n link: ['url', 'label'],\n image: ['url', 'alt'],\n product_card: ['title', 'price'],\n carousel: ['items'],\n action_button: ['label', 'action'],\n app_handoff: [], // no required data fields in si-ui-element.json (uses top-level apps object)\n integration_actions: ['actions'],\n};\n\n/**\n * Validate UI elements collected from SI session responses.\n * Returns a single TestStepResult summarizing all found types and any violations.\n */\nfunction validateUIElements(elementArrays: unknown[][]): TestStepResult {\n const foundTypes = new Set<string>();\n const invalidElements: string[] = [];\n\n for (const elements of elementArrays) {\n for (const el of elements) {\n if (!el || typeof el !== 'object') {\n invalidElements.push('non-object element');\n continue;\n }\n const element = el as Record<string, unknown>;\n const type = element.type as string | undefined;\n\n if (!type) {\n invalidElements.push('element missing required \"type\" field');\n continue;\n }\n\n if (!SI_UI_ELEMENT_TYPES.includes(type as (typeof SI_UI_ELEMENT_TYPES)[number])) {\n invalidElements.push(`unknown type \"${type}\"`);\n continue;\n }\n\n foundTypes.add(type);\n\n // Check type-specific required fields in data\n const requiredFields = SI_UI_ELEMENT_REQUIRED_FIELDS[type];\n if (requiredFields && requiredFields.length > 0) {\n if (!element.data || typeof element.data !== 'object') {\n invalidElements.push(`${type} element missing required \"data\" object`);\n } else {\n const data = element.data as Record<string, unknown>;\n for (const field of requiredFields) {\n if (!(field in data)) {\n invalidElements.push(`${type} element missing required data.${field}`);\n }\n }\n }\n }\n }\n }\n\n const typesFound = Array.from(foundTypes);\n const passed = invalidElements.length === 0;\n\n return {\n step: 'Validate SI UI element schemas',\n passed,\n duration_ms: 0,\n details:\n typesFound.length > 0\n ? `Found ${typesFound.length} element type(s): ${typesFound.join(', ')}${invalidElements.length > 0 ? `. Violations: ${invalidElements.join('; ')}` : ''}`\n : 'No UI elements returned (agent may not support rich media)',\n error: passed ? undefined : `UI element schema violations: ${invalidElements.join('; ')}`,\n response_preview: JSON.stringify({ found_types: typesFound, invalid_elements: invalidElements }, null, 2),\n warnings: typesFound.length === 0 ? ['Agent returned no UI elements in this session'] : undefined,\n };\n}\n\n/**\n * Test: SI Handoff\n *\n * Tests the ACP handoff mechanism in si_terminate_session.\n * Flow: si_get_offering -> si_initiate_session -> si_send_message (purchase intent)\n * -> si_terminate_session (reason: handoff_transaction) -> validate acp_handoff structure\n */\nexport async function testSIHandoff(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n const hasRequiredTools =\n profile.tools.includes('si_initiate_session') && profile.tools.includes('si_terminate_session');\n if (!hasRequiredTools) {\n steps.push({\n step: 'SI handoff support check',\n passed: false,\n duration_ms: 0,\n error: 'Agent does not support si_initiate_session + si_terminate_session (required for handoff testing)',\n });\n return { steps, profile };\n }\n\n profile.supports_si = true;\n let sessionId: string | undefined;\n let offeringToken: string | undefined;\n\n // Get offering token if available\n if (profile.tools.includes('si_get_offering')) {\n const { result, step } = await runStep<TaskResult>(\n 'Get SI offering (handoff)',\n 'si_get_offering',\n async () =>\n client.siGetOffering({\n offering_id: options.si_offering_id || 'e2e-test-offering',\n intent: 'E2E testing - preparing for handoff flow',\n } as unknown as SIGetOfferingRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n offeringToken = (result.data as SIGetOfferingResponse).offering_token ?? undefined;\n step.details = 'Offering retrieved for handoff test';\n }\n steps.push(step);\n }\n\n // Initiate session\n const { result: initResult, step: initStep } = await runStep<TaskResult>(\n 'Initiate SI session (handoff)',\n 'si_initiate_session',\n async () =>\n client.siInitiateSession({\n offering_id: options.si_offering_id || 'e2e-test-offering',\n offering_token: offeringToken,\n intent: options.si_context || 'E2E testing - initiating session for handoff test',\n identity: {\n consent_granted: false,\n anonymous_session_id: `e2e-anon-${Date.now()}`,\n },\n placement: 'e2e-test-placement',\n supported_capabilities: {\n modalities: { conversational: true },\n },\n } as unknown as SIInitiateSessionRequest) as Promise<TaskResult>\n );\n\n if (initResult?.success && initResult?.data) {\n sessionId = (initResult.data as SIInitiateSessionResponse).session_id;\n initStep.details = sessionId ? `Session created: ${sessionId}` : 'Session created (no session_id)';\n } else if (initResult && !initResult.success) {\n const error = initResult.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n initStep.passed = true;\n initStep.details = 'SI not supported by this agent';\n } else {\n initStep.passed = false;\n initStep.error = initResult.error || 'si_initiate_session failed';\n }\n }\n steps.push(initStep);\n\n if (!sessionId) {\n return { steps, profile };\n }\n\n // Send a purchase-intent message to set up the handoff\n if (profile.tools.includes('si_send_message')) {\n const { result, step } = await runStep<TaskResult>(\n 'Send purchase intent message',\n 'si_send_message',\n async () =>\n client.siSendMessage({\n session_id: sessionId,\n message: \"I'd like to purchase this product. Can you set up a transaction?\",\n } as unknown as SISendMessageRequest) as Promise<TaskResult>\n );\n\n if (result?.success) {\n step.details = 'Purchase intent sent';\n } else if (result && !result.success) {\n step.passed = false;\n step.error = result.error || 'si_send_message failed';\n }\n steps.push(step);\n }\n\n // Terminate with handoff_transaction reason\n const { result: termResult, step: termStep } = await runStep<TaskResult>(\n 'Terminate SI session (handoff_transaction)',\n 'si_terminate_session',\n async () =>\n client.siTerminateSession({\n session_id: sessionId,\n reason: 'handoff_transaction',\n termination_context: {\n summary: 'E2E test - terminating for handoff validation',\n transaction_intent: {\n intent: 'purchase',\n },\n },\n } as unknown as SITerminateSessionRequest) as Promise<TaskResult>\n );\n\n let termData: SITerminateSessionResponse | undefined;\n if (termResult?.success && termResult?.data) {\n termData = termResult.data as SITerminateSessionResponse;\n termStep.details = termData.terminated\n ? `Terminated with${termData.acp_handoff ? '' : 'out'} ACP handoff`\n : 'Termination not confirmed';\n termStep.response_preview = JSON.stringify(\n {\n session_id: termData.session_id,\n terminated: termData.terminated,\n acp_handoff: termData.acp_handoff ? '(present)' : undefined,\n },\n null,\n 2\n );\n } else if (termResult && !termResult.success) {\n termStep.passed = false;\n termStep.error = termResult.error || 'si_terminate_session failed';\n }\n steps.push(termStep);\n\n // Validate acp_handoff structure (only when termination succeeded)\n if (termData) {\n if (termData.acp_handoff) {\n const handoff = termData.acp_handoff;\n const hasCheckoutUrl = typeof handoff.checkout_url === 'string';\n const hasCheckoutToken = typeof handoff.checkout_token === 'string';\n const hasAnyHandoffField = hasCheckoutUrl || hasCheckoutToken;\n\n steps.push({\n step: 'Validate ACP handoff structure',\n passed: hasAnyHandoffField,\n duration_ms: 0,\n details: hasAnyHandoffField\n ? `Handoff has ${[hasCheckoutUrl && 'checkout_url', hasCheckoutToken && 'checkout_token'].filter(Boolean).join(', ')}`\n : 'acp_handoff returned but missing both checkout_url and checkout_token',\n error: hasAnyHandoffField\n ? undefined\n : 'acp_handoff object present but has no checkout_url or checkout_token — at least one is required',\n response_preview: JSON.stringify(\n {\n has_checkout_url: hasCheckoutUrl,\n has_checkout_token: hasCheckoutToken,\n has_payload: !!handoff.payload,\n has_expires_at: !!handoff.expires_at,\n },\n null,\n 2\n ),\n });\n } else {\n steps.push({\n step: 'Validate ACP handoff structure',\n passed: true,\n duration_ms: 0,\n details: 'No acp_handoff in response (agent may not support transaction handoff)',\n warnings: ['Agent terminated with handoff_transaction reason but returned no acp_handoff object'],\n });\n }\n }\n\n return { steps, profile };\n}\n\n/**\n * Test: SI Availability Check\n *\n * Quick test to check SI offering availability without full session lifecycle\n */\nexport async function testSIAvailability(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n // Discover agent profile\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n // Check if agent supports si_get_offering\n if (!profile.tools.includes('si_get_offering')) {\n steps.push({\n step: 'SI availability check support',\n passed: false,\n duration_ms: 0,\n error: 'Agent does not support si_get_offering tool',\n });\n return { steps, profile };\n }\n\n profile.supports_si = true;\n\n // Test: si_get_offering with provided or default offering ID\n const offeringId = options.si_offering_id || 'e2e-test-offering';\n const { result, step } = await runStep<TaskResult>(\n 'Check SI offering availability',\n 'si_get_offering',\n async () =>\n client.siGetOffering({\n offering_id: offeringId,\n intent: options.si_context || 'E2E testing - checking SI availability',\n } as unknown as SIGetOfferingRequest) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as SIGetOfferingResponse;\n const dataRecord = result.data as unknown as Record<string, unknown>;\n step.details = data.available\n ? 'SI offering is available'\n : `SI offering unavailable: ${data.unavailable_reason || 'no reason'}`;\n step.response_preview = JSON.stringify(\n {\n available: data.available,\n title: dataRecord.title,\n description: dataRecord.description,\n capabilities: dataRecord.capabilities,\n unavailable_reason: data.unavailable_reason,\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'SI not supported by this agent';\n } else {\n step.passed = false;\n step.error = result.error || 'si_get_offering failed';\n }\n }\n steps.push(step);\n\n // Test: si_get_offering with invalid offering ID (should return unavailable, not error)\n const { result: invalidResult, step: invalidStep } = await runStep<TaskResult>(\n 'Check invalid offering availability',\n 'si_get_offering',\n async () =>\n client.siGetOffering({\n offering_id: 'INVALID_OFFERING_ID_DOES_NOT_EXIST_12345',\n intent: 'E2E testing - checking unavailable offering',\n } as unknown as SIGetOfferingRequest) as Promise<TaskResult>\n );\n\n if (invalidResult?.success && invalidResult?.data) {\n const data = invalidResult.data as SIGetOfferingResponse;\n if (data.available === false) {\n invalidStep.passed = true;\n invalidStep.details = 'Correctly reports invalid offering as unavailable';\n } else {\n invalidStep.passed = false;\n invalidStep.error = 'Expected unavailable for invalid offering but got available';\n }\n invalidStep.response_preview = JSON.stringify(\n {\n available: data.available,\n unavailable_reason: data.unavailable_reason,\n },\n null,\n 2\n );\n } else if (invalidResult && !invalidResult.success) {\n // Also acceptable to return an error for invalid offering\n invalidStep.passed = true;\n invalidStep.details = 'Correctly rejected invalid offering ID';\n }\n steps.push(invalidStep);\n\n return { steps, profile };\n}\n\n/**\n * Check if agent has any SI protocol tools\n */\nexport function hasSITools(tools: string[]): boolean {\n return SPONSORED_INTELLIGENCE_TOOLS.some(t => tools.includes(t));\n}\n"],"mappings":"AAWA,SAAS,mBAAmB,SAAS,4BAA4B;AACjE,SAAS,oCAAoC;AAkB7C,eAAsB,uBACpB,UACA,SAC8D;AAC9D,QAAM,QAA0B,CAAC;AACjC,QAAM,SAAS,kBAAkB,UAAU,OAAO;AAGlD,QAAM,EAAE,SAAS,MAAM,YAAY,IAAI,MAAM,qBAAqB,QAAQ,OAAO;AACjF,QAAM,KAAK,WAAW;AAEtB,MAAI,CAAC,YAAY,QAAQ;AACvB,WAAO,EAAE,OAAO,QAAQ;AAAA,EAC1B;AAGA,QAAMA,cAAa,6BAA6B,KAAK,OAAK,QAAQ,MAAM,SAAS,CAAC,CAAC;AACnF,MAAI,CAACA,aAAY;AACf,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,MACP,SAAS,mBAAmB,6BAA6B,KAAK,IAAI,CAAC,gBAAgB,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,IAC7G,CAAC;AACD,WAAO,EAAE,OAAO,QAAQ;AAAA,EAC1B;AAEA,UAAQ,cAAc;AACtB,MAAI;AACJ,MAAI;AACJ,MAAI,oBAAoB;AACxB,QAAM,sBAAmC,CAAC;AAG1C,MAAI,QAAQ,MAAM,SAAS,iBAAiB,GAAG;AAC7C,UAAM,aAAa,QAAQ,kBAAkB;AAC7C,UAAM,EAAE,QAAQ,KAAK,IAAI,MAAM;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,YACE,OAAO,cAAc;AAAA,QACnB,aAAa;AAAA,QACb,QAAQ,QAAQ,cAAc;AAAA,MAChC,CAAoC;AAAA,IACxC;AAEA,QAAI,QAAQ,WAAW,QAAQ,MAAM;AACnC,YAAM,OAAO,OAAO;AACpB,YAAM,aAAa,OAAO;AAC1B,0BAAoB,KAAK,cAAc;AACvC,sBAAgB,KAAK,kBAAkB;AACvC,WAAK,UAAU,oBACX,qBAAqB,gBAAgB,sBAAsB,EAAE,KAC7D,yBAAyB,KAAK,sBAAsB,oBAAoB;AAC5E,WAAK,mBAAmB,KAAK;AAAA,QAC3B;AAAA,UACE,WAAW,KAAK;AAAA,UAChB,gBAAgB,gBAAgB,QAAQ;AAAA,UACxC,OAAO,WAAW;AAAA,UAClB,aAAa,WAAW;AAAA,UACxB,cAAc,WAAW;AAAA,UACzB,oBAAoB,KAAK;AAAA,QAC3B;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,WAAW,UAAU,CAAC,OAAO,SAAS;AACpC,YAAM,QAAQ,OAAO,SAAS;AAC9B,UAAI,MAAM,SAAS,eAAe,KAAK,MAAM,SAAS,iBAAiB,GAAG;AACxE,aAAK,SAAS;AACd,aAAK,UAAU;AAAA,MACjB,OAAO;AACL,aAAK,SAAS;AACd,aAAK,QAAQ,OAAO,SAAS;AAAA,MAC/B;AAAA,IACF;AACA,UAAM,KAAK,IAAI;AAAA,EACjB;AAGA,MAAI,QAAQ,MAAM,SAAS,qBAAqB,GAAG;AACjD,UAAM,EAAE,QAAQ,KAAK,IAAI,MAAM;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,YACE,OAAO,kBAAkB;AAAA,QACvB,aAAa,QAAQ,kBAAkB;AAAA,QACvC,gBAAgB;AAAA,QAChB,QAAQ,QAAQ,cAAc;AAAA,QAC9B,UAAU;AAAA,UACR,iBAAiB;AAAA,UACjB,sBAAsB,YAAY,KAAK,IAAI,CAAC;AAAA,QAC9C;AAAA,QACA,WAAW;AAAA,QACX,wBAAwB;AAAA,UACtB,YAAY;AAAA,YACV,gBAAgB;AAAA,YAChB,YAAY;AAAA,UACd;AAAA,QACF;AAAA,MACF,CAAwC;AAAA,IAC5C;AAEA,QAAI,QAAQ,WAAW,QAAQ,MAAM;AACnC,YAAM,OAAO,OAAO;AACpB,kBAAY,KAAK;AACjB,WAAK,aAAa;AAClB,UAAI,MAAM,QAAQ,KAAK,UAAU,WAAW,KAAK,KAAK,SAAS,YAAY,SAAS,GAAG;AACrF,4BAAoB,KAAK,KAAK,SAAS,WAAW;AAAA,MACpD;AACA,WAAK,UAAU,YACX,oBAAoB,SAAS,KAC7B;AACJ,WAAK,mBAAmB,KAAK;AAAA,QAC3B;AAAA,UACE,YAAY;AAAA,UACZ,kBAAkB,KAAK,UAAU,SAAS,UAAU,GAAG,GAAG;AAAA,UAC1D,iBAAiB,CAAC,CAAC,KAAK,UAAU,aAAa;AAAA,UAC/C,yBAAyB,KAAK;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,WAAW,UAAU,CAAC,OAAO,SAAS;AACpC,YAAM,QAAQ,OAAO,SAAS;AAC9B,UAAI,MAAM,SAAS,eAAe,KAAK,MAAM,SAAS,iBAAiB,GAAG;AACxE,aAAK,SAAS;AACd,aAAK,UAAU;AAAA,MACjB,OAAO;AACL,aAAK,SAAS;AACd,aAAK,QAAQ,OAAO,SAAS;AAAA,MAC/B;AAAA,IACF;AACA,UAAM,KAAK,IAAI;AAAA,EACjB;AAGA,MAAI,QAAQ,MAAM,SAAS,iBAAiB,KAAK,WAAW;AAC1D,UAAM,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,KAAK,IAAI,aAAa,QAAQ,CAAC,GAAG,KAAK;AACzD,YAAM,UAAU,aAAa,CAAC;AAC9B,YAAM,EAAE,QAAQ,KAAK,IAAI,MAAM;AAAA,QAC7B,gBAAgB,IAAI,CAAC,MAAM,QAAQ,UAAU,GAAG,EAAE,CAAC;AAAA,QACnD;AAAA,QACA,YACE,OAAO,cAAc;AAAA,UACnB,YAAY;AAAA,UACZ;AAAA,UACA,UAAU;AAAA,YACR,gBAAgB,IAAI;AAAA,UACtB;AAAA,QACF,CAAoC;AAAA,MACxC;AAEA,UAAI,eAAe;AACnB,UAAI,QAAQ,WAAW,QAAQ,MAAM;AACnC,cAAM,OAAO,OAAO;AACpB,YAAI,MAAM,QAAQ,KAAK,UAAU,WAAW,KAAK,KAAK,SAAS,YAAY,SAAS,GAAG;AACrF,8BAAoB,KAAK,KAAK,SAAS,WAAW;AAAA,QACpD;AACA,aAAK,UAAU,mBAAmB,KAAK,kBAAkB,QAAQ;AACjE,aAAK,mBAAmB,KAAK;AAAA,UAC3B;AAAA,YACE,YAAY,KAAK;AAAA,YACjB,gBAAgB,KAAK;AAAA,YACrB,kBAAkB,KAAK,UAAU,SAAS,UAAU,GAAG,GAAG;AAAA,YAC1D,iBAAiB,CAAC,CAAC,KAAK,UAAU,aAAa;AAAA,UACjD;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,SAAS,KAAK;AACpB,uBAAe,WAAW,cAAc,WAAW;AAAA,MACrD,WAAW,UAAU,CAAC,OAAO,SAAS;AACpC,aAAK,SAAS;AACd,aAAK,QAAQ,OAAO,SAAS;AAAA,MAC/B;AACA,YAAM,KAAK,IAAI;AAEf,UAAI,cAAc;AAChB;AAAA,MACF;AAAA,IACF;AAGA,QAAI,oBAAoB,SAAS,GAAG;AAClC,YAAM,KAAK,mBAAmB,mBAAmB,CAAC;AAAA,IACpD;AAAA,EACF;AAGA,MAAI,QAAQ,MAAM,SAAS,sBAAsB,KAAK,WAAW;AAC/D,UAAM,EAAE,QAAQ,KAAK,IAAI,MAAM;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,YACE,OAAO,mBAAmB;AAAA,QACxB,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,qBAAqB;AAAA,UACnB,SAAS;AAAA,QACX;AAAA,MACF,CAAyC;AAAA,IAC7C;AAEA,QAAI,QAAQ,WAAW,QAAQ,MAAM;AACnC,YAAM,OAAO,OAAO;AACpB,WAAK,UAAU,KAAK,aAAa,uBAAuB;AACxD,WAAK,mBAAmB,KAAK;AAAA,QAC3B;AAAA,UACE,YAAY,KAAK;AAAA,UACjB,YAAY,KAAK;AAAA,UACjB,iBAAiB,CAAC,CAAC,KAAK;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,WAAW,UAAU,CAAC,OAAO,SAAS;AACpC,WAAK,SAAS;AACd,WAAK,QAAQ,OAAO,SAAS;AAAA,IAC/B;AACA,UAAM,KAAK,IAAI;AAGf,QAAI,QAAQ,MAAM,SAAS,iBAAiB,GAAG;AAC7C,YAAM,EAAE,QAAQ,aAAa,MAAM,UAAU,IAAI,MAAM;AAAA,QACrD;AAAA,QACA;AAAA,QACA,YACE,OAAO,cAAc;AAAA,UACnB,YAAY;AAAA,UACZ,SAAS;AAAA,QACX,CAAoC;AAAA,MACxC;AAEA,UAAI,aAAa,SAAS;AAExB,cAAM,OAAO,YAAY;AACzB,cAAM,SAAS,KAAK;AACpB,YAAI,WAAW,cAAc,WAAW,cAAc;AACpD,oBAAU,SAAS;AACnB,oBAAU,UAAU;AAAA,QACtB,OAAO;AACL,oBAAU,SAAS;AACnB,oBAAU,QAAQ;AAAA,QACpB;AAAA,MACF,OAAO;AACL,kBAAU,SAAS;AACnB,kBAAU,UAAU;AAAA,MACtB;AACA,YAAM,KAAK,SAAS;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,QAAQ;AAC1B;AAGA,MAAM,sBAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,MAAM,gCAA0D;AAAA,EAC9D,MAAM,CAAC,SAAS;AAAA,EAChB,MAAM,CAAC,OAAO,OAAO;AAAA,EACrB,OAAO,CAAC,OAAO,KAAK;AAAA,EACpB,cAAc,CAAC,SAAS,OAAO;AAAA,EAC/B,UAAU,CAAC,OAAO;AAAA,EAClB,eAAe,CAAC,SAAS,QAAQ;AAAA,EACjC,aAAa,CAAC;AAAA;AAAA,EACd,qBAAqB,CAAC,SAAS;AACjC;AAMA,SAAS,mBAAmB,eAA4C;AACtE,QAAM,aAAa,oBAAI,IAAY;AACnC,QAAM,kBAA4B,CAAC;AAEnC,aAAW,YAAY,eAAe;AACpC,eAAW,MAAM,UAAU;AACzB,UAAI,CAAC,MAAM,OAAO,OAAO,UAAU;AACjC,wBAAgB,KAAK,oBAAoB;AACzC;AAAA,MACF;AACA,YAAM,UAAU;AAChB,YAAM,OAAO,QAAQ;AAErB,UAAI,CAAC,MAAM;AACT,wBAAgB,KAAK,uCAAuC;AAC5D;AAAA,MACF;AAEA,UAAI,CAAC,oBAAoB,SAAS,IAA4C,GAAG;AAC/E,wBAAgB,KAAK,iBAAiB,IAAI,GAAG;AAC7C;AAAA,MACF;AAEA,iBAAW,IAAI,IAAI;AAGnB,YAAM,iBAAiB,8BAA8B,IAAI;AACzD,UAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,YAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,UAAU;AACrD,0BAAgB,KAAK,GAAG,IAAI,yCAAyC;AAAA,QACvE,OAAO;AACL,gBAAM,OAAO,QAAQ;AACrB,qBAAW,SAAS,gBAAgB;AAClC,gBAAI,EAAE,SAAS,OAAO;AACpB,8BAAgB,KAAK,GAAG,IAAI,kCAAkC,KAAK,EAAE;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,KAAK,UAAU;AACxC,QAAM,SAAS,gBAAgB,WAAW;AAE1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,aAAa;AAAA,IACb,SACE,WAAW,SAAS,IAChB,SAAS,WAAW,MAAM,qBAAqB,WAAW,KAAK,IAAI,CAAC,GAAG,gBAAgB,SAAS,IAAI,iBAAiB,gBAAgB,KAAK,IAAI,CAAC,KAAK,EAAE,KACtJ;AAAA,IACN,OAAO,SAAS,SAAY,iCAAiC,gBAAgB,KAAK,IAAI,CAAC;AAAA,IACvF,kBAAkB,KAAK,UAAU,EAAE,aAAa,YAAY,kBAAkB,gBAAgB,GAAG,MAAM,CAAC;AAAA,IACxG,UAAU,WAAW,WAAW,IAAI,CAAC,+CAA+C,IAAI;AAAA,EAC1F;AACF;AASA,eAAsB,cACpB,UACA,SAC8D;AAC9D,QAAM,QAA0B,CAAC;AACjC,QAAM,SAAS,kBAAkB,UAAU,OAAO;AAElD,QAAM,EAAE,SAAS,MAAM,YAAY,IAAI,MAAM,qBAAqB,QAAQ,OAAO;AACjF,QAAM,KAAK,WAAW;AAEtB,MAAI,CAAC,YAAY,QAAQ;AACvB,WAAO,EAAE,OAAO,QAAQ;AAAA,EAC1B;AAEA,QAAM,mBACJ,QAAQ,MAAM,SAAS,qBAAqB,KAAK,QAAQ,MAAM,SAAS,sBAAsB;AAChG,MAAI,CAAC,kBAAkB;AACrB,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,IACT,CAAC;AACD,WAAO,EAAE,OAAO,QAAQ;AAAA,EAC1B;AAEA,UAAQ,cAAc;AACtB,MAAI;AACJ,MAAI;AAGJ,MAAI,QAAQ,MAAM,SAAS,iBAAiB,GAAG;AAC7C,UAAM,EAAE,QAAQ,KAAK,IAAI,MAAM;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,YACE,OAAO,cAAc;AAAA,QACnB,aAAa,QAAQ,kBAAkB;AAAA,QACvC,QAAQ;AAAA,MACV,CAAoC;AAAA,IACxC;AAEA,QAAI,QAAQ,WAAW,QAAQ,MAAM;AACnC,sBAAiB,OAAO,KAA+B,kBAAkB;AACzE,WAAK,UAAU;AAAA,IACjB;AACA,UAAM,KAAK,IAAI;AAAA,EACjB;AAGA,QAAM,EAAE,QAAQ,YAAY,MAAM,SAAS,IAAI,MAAM;AAAA,IACnD;AAAA,IACA;AAAA,IACA,YACE,OAAO,kBAAkB;AAAA,MACvB,aAAa,QAAQ,kBAAkB;AAAA,MACvC,gBAAgB;AAAA,MAChB,QAAQ,QAAQ,cAAc;AAAA,MAC9B,UAAU;AAAA,QACR,iBAAiB;AAAA,QACjB,sBAAsB,YAAY,KAAK,IAAI,CAAC;AAAA,MAC9C;AAAA,MACA,WAAW;AAAA,MACX,wBAAwB;AAAA,QACtB,YAAY,EAAE,gBAAgB,KAAK;AAAA,MACrC;AAAA,IACF,CAAwC;AAAA,EAC5C;AAEA,MAAI,YAAY,WAAW,YAAY,MAAM;AAC3C,gBAAa,WAAW,KAAmC;AAC3D,aAAS,UAAU,YAAY,oBAAoB,SAAS,KAAK;AAAA,EACnE,WAAW,cAAc,CAAC,WAAW,SAAS;AAC5C,UAAM,QAAQ,WAAW,SAAS;AAClC,QAAI,MAAM,SAAS,eAAe,KAAK,MAAM,SAAS,iBAAiB,GAAG;AACxE,eAAS,SAAS;AAClB,eAAS,UAAU;AAAA,IACrB,OAAO;AACL,eAAS,SAAS;AAClB,eAAS,QAAQ,WAAW,SAAS;AAAA,IACvC;AAAA,EACF;AACA,QAAM,KAAK,QAAQ;AAEnB,MAAI,CAAC,WAAW;AACd,WAAO,EAAE,OAAO,QAAQ;AAAA,EAC1B;AAGA,MAAI,QAAQ,MAAM,SAAS,iBAAiB,GAAG;AAC7C,UAAM,EAAE,QAAQ,KAAK,IAAI,MAAM;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,YACE,OAAO,cAAc;AAAA,QACnB,YAAY;AAAA,QACZ,SAAS;AAAA,MACX,CAAoC;AAAA,IACxC;AAEA,QAAI,QAAQ,SAAS;AACnB,WAAK,UAAU;AAAA,IACjB,WAAW,UAAU,CAAC,OAAO,SAAS;AACpC,WAAK,SAAS;AACd,WAAK,QAAQ,OAAO,SAAS;AAAA,IAC/B;AACA,UAAM,KAAK,IAAI;AAAA,EACjB;AAGA,QAAM,EAAE,QAAQ,YAAY,MAAM,SAAS,IAAI,MAAM;AAAA,IACnD;AAAA,IACA;AAAA,IACA,YACE,OAAO,mBAAmB;AAAA,MACxB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,qBAAqB;AAAA,QACnB,SAAS;AAAA,QACT,oBAAoB;AAAA,UAClB,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF,CAAyC;AAAA,EAC7C;AAEA,MAAI;AACJ,MAAI,YAAY,WAAW,YAAY,MAAM;AAC3C,eAAW,WAAW;AACtB,aAAS,UAAU,SAAS,aACxB,kBAAkB,SAAS,cAAc,KAAK,KAAK,iBACnD;AACJ,aAAS,mBAAmB,KAAK;AAAA,MAC/B;AAAA,QACE,YAAY,SAAS;AAAA,QACrB,YAAY,SAAS;AAAA,QACrB,aAAa,SAAS,cAAc,cAAc;AAAA,MACpD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,WAAW,cAAc,CAAC,WAAW,SAAS;AAC5C,aAAS,SAAS;AAClB,aAAS,QAAQ,WAAW,SAAS;AAAA,EACvC;AACA,QAAM,KAAK,QAAQ;AAGnB,MAAI,UAAU;AACZ,QAAI,SAAS,aAAa;AACxB,YAAM,UAAU,SAAS;AACzB,YAAM,iBAAiB,OAAO,QAAQ,iBAAiB;AACvD,YAAM,mBAAmB,OAAO,QAAQ,mBAAmB;AAC3D,YAAM,qBAAqB,kBAAkB;AAE7C,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,SAAS,qBACL,eAAe,CAAC,kBAAkB,gBAAgB,oBAAoB,gBAAgB,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC,KAClH;AAAA,QACJ,OAAO,qBACH,SACA;AAAA,QACJ,kBAAkB,KAAK;AAAA,UACrB;AAAA,YACE,kBAAkB;AAAA,YAClB,oBAAoB;AAAA,YACpB,aAAa,CAAC,CAAC,QAAQ;AAAA,YACvB,gBAAgB,CAAC,CAAC,QAAQ;AAAA,UAC5B;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,SAAS;AAAA,QACT,UAAU,CAAC,qFAAqF;AAAA,MAClG,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,QAAQ;AAC1B;AAOA,eAAsB,mBACpB,UACA,SAC8D;AAC9D,QAAM,QAA0B,CAAC;AACjC,QAAM,SAAS,kBAAkB,UAAU,OAAO;AAGlD,QAAM,EAAE,SAAS,MAAM,YAAY,IAAI,MAAM,qBAAqB,QAAQ,OAAO;AACjF,QAAM,KAAK,WAAW;AAEtB,MAAI,CAAC,YAAY,QAAQ;AACvB,WAAO,EAAE,OAAO,QAAQ;AAAA,EAC1B;AAGA,MAAI,CAAC,QAAQ,MAAM,SAAS,iBAAiB,GAAG;AAC9C,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,OAAO;AAAA,IACT,CAAC;AACD,WAAO,EAAE,OAAO,QAAQ;AAAA,EAC1B;AAEA,UAAQ,cAAc;AAGtB,QAAM,aAAa,QAAQ,kBAAkB;AAC7C,QAAM,EAAE,QAAQ,KAAK,IAAI,MAAM;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,YACE,OAAO,cAAc;AAAA,MACnB,aAAa;AAAA,MACb,QAAQ,QAAQ,cAAc;AAAA,IAChC,CAAoC;AAAA,EACxC;AAEA,MAAI,QAAQ,WAAW,QAAQ,MAAM;AACnC,UAAM,OAAO,OAAO;AACpB,UAAM,aAAa,OAAO;AAC1B,SAAK,UAAU,KAAK,YAChB,6BACA,4BAA4B,KAAK,sBAAsB,WAAW;AACtE,SAAK,mBAAmB,KAAK;AAAA,MAC3B;AAAA,QACE,WAAW,KAAK;AAAA,QAChB,OAAO,WAAW;AAAA,QAClB,aAAa,WAAW;AAAA,QACxB,cAAc,WAAW;AAAA,QACzB,oBAAoB,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,WAAW,UAAU,CAAC,OAAO,SAAS;AACpC,UAAM,QAAQ,OAAO,SAAS;AAC9B,QAAI,MAAM,SAAS,eAAe,KAAK,MAAM,SAAS,iBAAiB,GAAG;AACxE,WAAK,SAAS;AACd,WAAK,UAAU;AAAA,IACjB,OAAO;AACL,WAAK,SAAS;AACd,WAAK,QAAQ,OAAO,SAAS;AAAA,IAC/B;AAAA,EACF;AACA,QAAM,KAAK,IAAI;AAGf,QAAM,EAAE,QAAQ,eAAe,MAAM,YAAY,IAAI,MAAM;AAAA,IACzD;AAAA,IACA;AAAA,IACA,YACE,OAAO,cAAc;AAAA,MACnB,aAAa;AAAA,MACb,QAAQ;AAAA,IACV,CAAoC;AAAA,EACxC;AAEA,MAAI,eAAe,WAAW,eAAe,MAAM;AACjD,UAAM,OAAO,cAAc;AAC3B,QAAI,KAAK,cAAc,OAAO;AAC5B,kBAAY,SAAS;AACrB,kBAAY,UAAU;AAAA,IACxB,OAAO;AACL,kBAAY,SAAS;AACrB,kBAAY,QAAQ;AAAA,IACtB;AACA,gBAAY,mBAAmB,KAAK;AAAA,MAClC;AAAA,QACE,WAAW,KAAK;AAAA,QAChB,oBAAoB,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,WAAW,iBAAiB,CAAC,cAAc,SAAS;AAElD,gBAAY,SAAS;AACrB,gBAAY,UAAU;AAAA,EACxB;AACA,QAAM,KAAK,WAAW;AAEtB,SAAO,EAAE,OAAO,QAAQ;AAC1B;AAKO,SAAS,WAAW,OAA0B;AACnD,SAAO,6BAA6B,KAAK,OAAK,MAAM,SAAS,CAAC,CAAC;AACjE;","names":["hasSITools"]}
|
|
@@ -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 { getOrCreateClient, runStep, getOrDiscoverProfile } from "../client.mjs";
|
|
8
2
|
import { TRUSTED_MATCH_TOOLS } from "../../utils/capabilities.mjs";
|
|
9
3
|
async function testTrustedMatchFlow(agentUrl, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/scenarios/trusted-match.ts"],"sourcesContent":["/**\n * Trusted Match Protocol (TMP) Testing Scenarios (v3)\n *\n * Tests TMP agent capabilities including:\n * - context_match — evaluates packages against content context (no user identity)\n * - identity_match — evaluates user eligibility for packages using an opaque identity token (no page context)\n */\n\nimport type { TestOptions, TestStepResult, AgentProfile, TaskResult } from '../types';\nimport { getOrCreateClient, runStep, getOrDiscoverProfile } from '../client';\nimport { TRUSTED_MATCH_TOOLS } from '../../utils/capabilities';\n\n/**\n * Test: Trusted Match Flow\n *\n * Flow: discover profile -> check TMP tools -> context_match -> identity_match\n */\nexport async function testTrustedMatchFlow(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n // Discover agent profile\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n // Check if agent supports any TMP tools\n const hasTMP = TRUSTED_MATCH_TOOLS.some(t => profile.tools.includes(t));\n if (!hasTMP) {\n steps.push({\n step: 'TMP support check',\n passed: false,\n duration_ms: 0,\n error: 'Agent does not support Trusted Match Protocol tools',\n details: `Required tools: ${TRUSTED_MATCH_TOOLS.join(', ')}. Available: ${profile.tools.join(', ')}`,\n });\n return { steps, profile };\n }\n\n // Test: context_match\n if (profile.tools.includes('context_match')) {\n const { result, step } = await runStep<TaskResult>(\n 'Context match: evaluate packages against page context',\n 'context_match',\n async () =>\n client.executeTask('context_match', {\n type: 'context_match_request',\n request_id: `e2e-ctx-${Date.now()}`,\n property_rid: '00000000-0000-7000-0000-000000000001',\n property_type: 'web',\n placement_id: 'e2e-test-placement',\n context_signals: {\n topics: ['632'],\n taxonomy_source: 'iab',\n taxonomy_id: 7,\n sentiment: 'positive',\n keywords: ['technology', 'innovation'],\n language: 'en',\n },\n geo: {\n country: 'US',\n region: 'US-CA',\n },\n }) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as Record<string, unknown>;\n const offers = Array.isArray(data['offers']) ? data['offers'] : [];\n step.details = `Context match returned ${offers.length} offer(s)`;\n step.response_preview = JSON.stringify(\n {\n request_id: data['request_id'],\n offers_count: offers.length,\n cache_ttl: data['cache_ttl'],\n has_signals: !!data['signals'],\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'Context match not supported by this agent (expected for some agents)';\n } else {\n step.passed = false;\n step.error = result.error || 'context_match failed';\n }\n }\n steps.push(step);\n }\n\n // Test: identity_match\n if (profile.tools.includes('identity_match')) {\n const { result, step } = await runStep<TaskResult>(\n 'Identity match: evaluate user eligibility for packages',\n 'identity_match',\n async () =>\n client.executeTask('identity_match', {\n type: 'identity_match_request',\n request_id: `e2e-id-${Date.now()}`,\n user_token: 'e2e-test-opaque-token',\n uid_type: 'publisher_first_party',\n package_ids: ['e2e-test-package-001', 'e2e-test-package-002'],\n consent: {\n gdpr: false,\n },\n }) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as Record<string, unknown>;\n const eligibleIds = Array.isArray(data['eligible_package_ids']) ? data['eligible_package_ids'] : [];\n step.details = `Identity match returned ${eligibleIds.length} eligible package(s)`;\n step.response_preview = JSON.stringify(\n {\n request_id: data['request_id'],\n eligible_package_ids: eligibleIds,\n ttl_sec: data['ttl_sec'],\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'Identity match not supported by this agent (expected for some agents)';\n } else {\n step.passed = false;\n step.error = result.error || 'identity_match failed';\n }\n }\n steps.push(step);\n }\n\n return { steps, profile };\n}\n\n/**\n * Check if agent has any TMP tools\n */\nexport function hasTrustedMatchTools(tools: string[]): boolean {\n return TRUSTED_MATCH_TOOLS.some(t => tools.includes(t));\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/scenarios/trusted-match.ts"],"sourcesContent":["/**\n * Trusted Match Protocol (TMP) Testing Scenarios (v3)\n *\n * Tests TMP agent capabilities including:\n * - context_match — evaluates packages against content context (no user identity)\n * - identity_match — evaluates user eligibility for packages using an opaque identity token (no page context)\n */\n\nimport type { TestOptions, TestStepResult, AgentProfile, TaskResult } from '../types';\nimport { getOrCreateClient, runStep, getOrDiscoverProfile } from '../client';\nimport { TRUSTED_MATCH_TOOLS } from '../../utils/capabilities';\n\n/**\n * Test: Trusted Match Flow\n *\n * Flow: discover profile -> check TMP tools -> context_match -> identity_match\n */\nexport async function testTrustedMatchFlow(\n agentUrl: string,\n options: TestOptions\n): Promise<{ steps: TestStepResult[]; profile?: AgentProfile }> {\n const steps: TestStepResult[] = [];\n const client = getOrCreateClient(agentUrl, options);\n\n // Discover agent profile\n const { profile, step: profileStep } = await getOrDiscoverProfile(client, options);\n steps.push(profileStep);\n\n if (!profileStep.passed) {\n return { steps, profile };\n }\n\n // Check if agent supports any TMP tools\n const hasTMP = TRUSTED_MATCH_TOOLS.some(t => profile.tools.includes(t));\n if (!hasTMP) {\n steps.push({\n step: 'TMP support check',\n passed: false,\n duration_ms: 0,\n error: 'Agent does not support Trusted Match Protocol tools',\n details: `Required tools: ${TRUSTED_MATCH_TOOLS.join(', ')}. Available: ${profile.tools.join(', ')}`,\n });\n return { steps, profile };\n }\n\n // Test: context_match\n if (profile.tools.includes('context_match')) {\n const { result, step } = await runStep<TaskResult>(\n 'Context match: evaluate packages against page context',\n 'context_match',\n async () =>\n client.executeTask('context_match', {\n type: 'context_match_request',\n request_id: `e2e-ctx-${Date.now()}`,\n property_rid: '00000000-0000-7000-0000-000000000001',\n property_type: 'web',\n placement_id: 'e2e-test-placement',\n context_signals: {\n topics: ['632'],\n taxonomy_source: 'iab',\n taxonomy_id: 7,\n sentiment: 'positive',\n keywords: ['technology', 'innovation'],\n language: 'en',\n },\n geo: {\n country: 'US',\n region: 'US-CA',\n },\n }) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as Record<string, unknown>;\n const offers = Array.isArray(data['offers']) ? data['offers'] : [];\n step.details = `Context match returned ${offers.length} offer(s)`;\n step.response_preview = JSON.stringify(\n {\n request_id: data['request_id'],\n offers_count: offers.length,\n cache_ttl: data['cache_ttl'],\n has_signals: !!data['signals'],\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'Context match not supported by this agent (expected for some agents)';\n } else {\n step.passed = false;\n step.error = result.error || 'context_match failed';\n }\n }\n steps.push(step);\n }\n\n // Test: identity_match\n if (profile.tools.includes('identity_match')) {\n const { result, step } = await runStep<TaskResult>(\n 'Identity match: evaluate user eligibility for packages',\n 'identity_match',\n async () =>\n client.executeTask('identity_match', {\n type: 'identity_match_request',\n request_id: `e2e-id-${Date.now()}`,\n user_token: 'e2e-test-opaque-token',\n uid_type: 'publisher_first_party',\n package_ids: ['e2e-test-package-001', 'e2e-test-package-002'],\n consent: {\n gdpr: false,\n },\n }) as Promise<TaskResult>\n );\n\n if (result?.success && result?.data) {\n const data = result.data as Record<string, unknown>;\n const eligibleIds = Array.isArray(data['eligible_package_ids']) ? data['eligible_package_ids'] : [];\n step.details = `Identity match returned ${eligibleIds.length} eligible package(s)`;\n step.response_preview = JSON.stringify(\n {\n request_id: data['request_id'],\n eligible_package_ids: eligibleIds,\n ttl_sec: data['ttl_sec'],\n },\n null,\n 2\n );\n } else if (result && !result.success) {\n const error = result.error || '';\n if (error.includes('not supported') || error.includes('not implemented')) {\n step.passed = true;\n step.details = 'Identity match not supported by this agent (expected for some agents)';\n } else {\n step.passed = false;\n step.error = result.error || 'identity_match failed';\n }\n }\n steps.push(step);\n }\n\n return { steps, profile };\n}\n\n/**\n * Check if agent has any TMP tools\n */\nexport function hasTrustedMatchTools(tools: string[]): boolean {\n return TRUSTED_MATCH_TOOLS.some(t => tools.includes(t));\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 isPlainObject(value) {
|
|
8
2
|
if (value === null || typeof value !== "object") return false;
|
|
9
3
|
if (Array.isArray(value)) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/testing/seed-merge.ts"],"sourcesContent":["/**\n * Seed fixture merge helpers.\n *\n * Every seller that implements a `seed_*` scenario hits the same pattern:\n * take a baseline object that fills in defaults (channels, delivery_type,\n * pricing skeleton, reporting capabilities, ...), overlay whatever sparse\n * fields the storyboard's fixture declares, and ignore `undefined`/`null`\n * entries so an empty fixture leaves the defaults intact. These helpers\n * centralize that permissive merge so sellers don't reinvent it per seed kind.\n *\n * The five seed kinds map 1:1 with the `seed_*` scenarios dispatched by\n * `comply_test_controller`:\n *\n * - `seed_product` → {@link mergeSeedProduct}\n * - `seed_pricing_option` → {@link mergeSeedPricingOption}\n * - `seed_creative` → {@link mergeSeedCreative}\n * - `seed_plan` → {@link mergeSeedPlan}\n * - `seed_media_buy` → {@link mergeSeedMediaBuy}\n *\n * The generic {@link mergeSeed} replaces arrays wholesale — safe default\n * for unknown shapes. Typed wrappers layer **by-id overlay** on top for\n * well-known id-keyed arrays so sellers can seed a single `pricing_options`\n * entry and have it overlay the matching base entry without dropping the\n * rest (see {@link overlayById}).\n *\n * @example\n * ```ts\n * import { mergeSeedProduct } from '@adcp/sdk/testing';\n *\n * const baseline: Partial<Product> = {\n * delivery_type: 'guaranteed',\n * channels: ['display'],\n * pricing_options: [\n * { pricing_option_id: 'default', pricing_model: 'cpm', currency: 'USD', rate: 10 },\n * ],\n * };\n *\n * // Fixture carries only the fields the storyboard wants to override.\n * const merged = mergeSeedProduct(baseline, { product_id: 'prd-1', name: 'Homepage Takeover' });\n * // merged.delivery_type === 'guaranteed' (from baseline)\n * // merged.product_id === 'prd-1' (from fixture)\n * ```\n */\n\nimport type { Product, PricingOption } from '../types/tools.generated';\nimport type { MediaBuy } from '../types/core.generated';\n\n/**\n * Plain-object guard. Class instances, `Date`, `Map`, `Set`, and arrays fail\n * this check — they're treated as opaque leaves that replace their target\n * rather than merge. Matches the capability-overrides predicate in\n * `create-adcp-server.ts` so both paths agree on what counts as \"mergeable\".\n */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Reject Map/Set payloads loudly so silent stringification (→ `{}` via\n * `JSON.stringify`) can't ship. These types aren't expected in seed fixtures\n * — storyboards serialize over JSON — and allowing them would let a caller\n * pass a Map and never notice the merge dropped it on the floor.\n */\nfunction rejectUnsupportedCollection(value: unknown, path: string): void {\n if (value instanceof Map) {\n throw new TypeError(\n `mergeSeed: Map is not supported in seed fixtures at ${path}. Convert to a plain object before seeding.`\n );\n }\n if (value instanceof Set) {\n throw new TypeError(\n `mergeSeed: Set is not supported in seed fixtures at ${path}. Convert to an array before seeding.`\n );\n }\n}\n\n/**\n * Deep-merge `seed` onto `base`.\n *\n * Merge rules:\n * - `undefined` or `null` in `seed` → keep the `base` value untouched.\n * Every other falsy leaf (`0`, `false`, `\"\"`, `[]`) DOES override base.\n * - Plain-object values recurse (deep merge per key).\n * - Arrays REPLACE rather than concat — storyboards that seed arrays\n * expect to define the full list; concat would silently inflate\n * `pricing_options`, `publisher_properties`, and similar fields past\n * what the fixture declared. Typed wrappers layer per-array by-id\n * overlay on top for known id-keyed fields (see {@link overlayById}).\n * - `Map` / `Set` throw — not expected in seed payloads (see\n * {@link rejectUnsupportedCollection}).\n * - Other leaves (strings, numbers, booleans, Dates, class instances)\n * replace the base value.\n *\n * Neither input is mutated; a fresh object tree is returned.\n */\nexport function mergeSeed<T>(base: T, seed: Partial<T> | null | undefined): T {\n if (seed === null || seed === undefined) return base;\n rejectUnsupportedCollection(seed, '$');\n\n if (!isPlainObject(base) || !isPlainObject(seed)) {\n // One side is a leaf — a caller passing a non-object seed wants to\n // override with whatever leaf/array it carries.\n return (seed as T) ?? base;\n }\n\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(seed as Record<string, unknown>)) {\n if (value === undefined || value === null) continue;\n rejectUnsupportedCollection(value, `$.${key}`);\n\n const existing = out[key];\n if (isPlainObject(existing) && isPlainObject(value)) {\n out[key] = mergeSeed(existing, value);\n continue;\n }\n // Array replaces (documented above). Leaves replace.\n out[key] = value;\n }\n return out as T;\n}\n\n/**\n * Identity predicate for by-id array overlay. Returns a key that uniquely\n * identifies an item for matching, or `undefined` if the item can't be\n * identified (in which case the overlay falls through to append).\n */\ntype IdentityFn<T> = (item: T) => string | undefined;\n\n/**\n * Overlay a seed array onto a base array by a well-known id field.\n *\n * Semantics:\n * - Seed entries whose identity matches a base entry deep-merge onto\n * that base entry (via {@link mergeSeed}).\n * - Seed entries with no matching base entry append to the result.\n * - Base entries not referenced by any seed entry stay untouched.\n * - Seed entries missing an identity (e.g., no `pricing_option_id`)\n * append unconditionally — the fallback matches \"array replaces\" for\n * the un-identifiable tail but preserves the matched overlays.\n *\n * Neither input is mutated.\n *\n * @param base Base array (may be `undefined`).\n * @param seed Seed array (may be `undefined`).\n * @param identity Returns the id for matching; either a property name or a fn.\n */\nexport function overlayById<T>(\n base: readonly T[] | undefined,\n seed: readonly T[] | undefined,\n identity: IdentityFn<T> | keyof T\n): T[] | undefined {\n if (seed === undefined) return base ? [...base] : undefined;\n if (base === undefined || base.length === 0) return [...seed];\n\n const idOf: IdentityFn<T> =\n typeof identity === 'function'\n ? identity\n : (item: T) => {\n const v = (item as Record<string, unknown>)[identity as string];\n return typeof v === 'string' ? v : undefined;\n };\n\n const out: T[] = [];\n const seedById = new Map<string, T>();\n const seedUnkeyed: T[] = [];\n const consumed = new Set<string>();\n\n for (const item of seed) {\n const id = idOf(item);\n if (id !== undefined) seedById.set(id, item);\n else seedUnkeyed.push(item);\n }\n\n for (const baseItem of base) {\n const id = idOf(baseItem);\n if (id !== undefined && seedById.has(id)) {\n const seedItem = seedById.get(id)!;\n consumed.add(id);\n out.push(mergeSeed(baseItem, seedItem as Partial<T>));\n } else {\n out.push(baseItem);\n }\n }\n\n for (const [id, item] of seedById) {\n if (!consumed.has(id)) out.push(item);\n }\n for (const item of seedUnkeyed) out.push(item);\n\n return out;\n}\n\n// ────────────────────────────────────────────────────────────\n// Typed wrappers — one per seed kind.\n// ────────────────────────────────────────────────────────────\n//\n// Each wrapper delegates to `mergeSeed` for the top-level object merge,\n// then layers by-id overlay on known id-keyed arrays so sellers can seed\n// a single entry without replacing the rest.\n\n/**\n * Merge a `seed_product` fixture onto a baseline `Product` (or a partial\n * defaults object).\n *\n * **By-id overlay** is applied to:\n * - `pricing_options[]` — keyed by `pricing_option_id`. Seeding one\n * `{ pricing_option_id: 'premium', rate: 25 }` overlays the matching\n * base entry; other base pricing options stay put.\n * - `publisher_properties[]` — keyed by `publisher_domain` + `selection_type`\n * composite (PublisherPropertySelector is a discriminated union, no\n * single id field). Compact-form entries that carry `publisher_domains[]`\n * instead are keyed by the sorted, lowercased domain list joined with\n * `,` + `selection_type` so a re-seeded compact selector overlays its\n * counterpart instead of duplicating.\n *\n * Other arrays (`channels`, `format_ids`, `placements`, ...) still replace\n * wholesale per the {@link mergeSeed} default.\n */\nexport function mergeSeedProduct<TBase extends Partial<Product> = Partial<Product>>(\n base: TBase,\n seed: Partial<Product> | null | undefined\n): TBase {\n const merged = mergeSeed(base, seed as Partial<TBase>);\n if (!isPlainObject(merged) || !seed) return merged;\n\n const seedObj = seed as Partial<Product>;\n const out = merged as Record<string, unknown>;\n\n if (Array.isArray(seedObj.pricing_options)) {\n const overlaid = overlayById(\n (base as Partial<Product>).pricing_options as readonly PricingOption[] | undefined,\n seedObj.pricing_options,\n 'pricing_option_id'\n );\n if (overlaid !== undefined) out.pricing_options = overlaid;\n }\n\n if (Array.isArray(seedObj.publisher_properties)) {\n const overlaid = overlayById(\n (base as Partial<Product>).publisher_properties,\n seedObj.publisher_properties,\n item => {\n const domain = (item as { publisher_domain?: unknown }).publisher_domain;\n const domains = (item as { publisher_domains?: unknown }).publisher_domains;\n const sel = (item as { selection_type?: unknown }).selection_type;\n if (typeof sel !== 'string') return undefined;\n if (typeof domain === 'string') return `${domain.toLowerCase()}::${sel}`;\n if (Array.isArray(domains) && domains.length > 0 && domains.every(d => typeof d === 'string')) {\n // JSON.stringify the sorted-lowercased list — guarantees `['a,b']`\n // and `['a','b']` produce distinct keys (`[\"a,b\"]` vs `[\"a\",\"b\"]`)\n // rather than colliding under a naive comma-join.\n const sorted = [...(domains as string[])].map(d => d.toLowerCase()).sort();\n return `${JSON.stringify(sorted)}::${sel}`;\n }\n return undefined;\n }\n );\n if (overlaid !== undefined) out.publisher_properties = overlaid;\n }\n\n return merged;\n}\n\n/**\n * Merge a `seed_pricing_option` fixture onto a baseline pricing option. The\n * spec's `PricingOption` is a discriminated union; the generic signature\n * preserves whichever variant the base declares. No nested id-keyed arrays\n * to overlay — a pricing option is a leaf-ish record.\n */\nexport function mergeSeedPricingOption<TBase extends Partial<PricingOption> = Partial<PricingOption>>(\n base: TBase,\n seed: Partial<PricingOption> | null | undefined\n): TBase {\n return mergeSeed(base, seed as Partial<TBase>);\n}\n\n/**\n * Merge a `seed_creative` fixture onto a baseline creative. The SDK does not\n * ship a canonical `Creative` type (the spec models creatives as a union of\n * several assignment/manifest shapes), so the base is generic — sellers pass\n * whichever domain shape they store internally.\n *\n * **By-id overlay** is applied to `assets[]` when present, keyed by\n * `asset_id` — matches the creative manifest shape where assets are an\n * id-keyed list and sellers often seed a single asset override.\n */\nexport function mergeSeedCreative<TBase extends Record<string, unknown> = Record<string, unknown>>(\n base: TBase,\n seed: Partial<TBase> | null | undefined\n): TBase {\n const merged = mergeSeed(base, seed);\n if (!isPlainObject(merged) || !seed) return merged;\n\n const seedObj = seed as Record<string, unknown>;\n const baseObj = base as Record<string, unknown>;\n const out = merged as Record<string, unknown>;\n\n if (Array.isArray(seedObj.assets)) {\n const overlaid = overlayById(\n Array.isArray(baseObj.assets) ? (baseObj.assets as unknown[]) : undefined,\n seedObj.assets,\n 'asset_id'\n );\n if (overlaid !== undefined) out.assets = overlaid;\n }\n\n return merged;\n}\n\n/**\n * Merge a `seed_plan` fixture onto a baseline plan. Like creatives, the spec\n * splits plans across several tool-response shapes, so the base type stays\n * generic.\n *\n * **By-id overlay** is applied to any of these known id-keyed arrays when\n * present on the seed:\n * - `member_plan_ids[]` — string array, no overlay (replaces).\n * - `accounts[]` — string array, no overlay (replaces).\n * - `findings[]` — keyed by `policy_id`.\n * - `checks[]` — keyed by `check_id` when present.\n *\n * Other arrays replace wholesale per {@link mergeSeed}.\n */\nexport function mergeSeedPlan<TBase extends Record<string, unknown> = Record<string, unknown>>(\n base: TBase,\n seed: Partial<TBase> | null | undefined\n): TBase {\n const merged = mergeSeed(base, seed);\n if (!isPlainObject(merged) || !seed) return merged;\n\n const seedObj = seed as Record<string, unknown>;\n const baseObj = base as Record<string, unknown>;\n const out = merged as Record<string, unknown>;\n\n const overlay = (field: string, idField: string) => {\n if (!Array.isArray(seedObj[field])) return;\n const overlaid = overlayById(\n Array.isArray(baseObj[field]) ? (baseObj[field] as unknown[]) : undefined,\n seedObj[field] as unknown[],\n idField as never\n );\n if (overlaid !== undefined) out[field] = overlaid;\n };\n\n overlay('findings', 'policy_id');\n overlay('checks', 'check_id');\n\n return merged;\n}\n\n/**\n * Merge a `seed_media_buy` fixture onto a baseline `MediaBuy`.\n *\n * **By-id overlay** is applied to `packages[]` keyed by `package_id` — the\n * common storyboard pattern is \"seed one package's `delivery` or `status`\n * without rewriting the whole package list\", which a naive array replace\n * would break.\n */\nexport function mergeSeedMediaBuy<TBase extends Partial<MediaBuy> = Partial<MediaBuy>>(\n base: TBase,\n seed: Partial<MediaBuy> | null | undefined\n): TBase {\n const merged = mergeSeed(base, seed as Partial<TBase>);\n if (!isPlainObject(merged) || !seed) return merged;\n\n const seedObj = seed as Partial<MediaBuy>;\n const out = merged as Record<string, unknown>;\n\n if (Array.isArray(seedObj.packages)) {\n const overlaid = overlayById((base as Partial<MediaBuy>).packages, seedObj.packages, 'package_id');\n if (overlaid !== undefined) out.packages = overlaid;\n }\n\n return merged;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/testing/seed-merge.ts"],"sourcesContent":["/**\n * Seed fixture merge helpers.\n *\n * Every seller that implements a `seed_*` scenario hits the same pattern:\n * take a baseline object that fills in defaults (channels, delivery_type,\n * pricing skeleton, reporting capabilities, ...), overlay whatever sparse\n * fields the storyboard's fixture declares, and ignore `undefined`/`null`\n * entries so an empty fixture leaves the defaults intact. These helpers\n * centralize that permissive merge so sellers don't reinvent it per seed kind.\n *\n * The five seed kinds map 1:1 with the `seed_*` scenarios dispatched by\n * `comply_test_controller`:\n *\n * - `seed_product` → {@link mergeSeedProduct}\n * - `seed_pricing_option` → {@link mergeSeedPricingOption}\n * - `seed_creative` → {@link mergeSeedCreative}\n * - `seed_plan` → {@link mergeSeedPlan}\n * - `seed_media_buy` → {@link mergeSeedMediaBuy}\n *\n * The generic {@link mergeSeed} replaces arrays wholesale — safe default\n * for unknown shapes. Typed wrappers layer **by-id overlay** on top for\n * well-known id-keyed arrays so sellers can seed a single `pricing_options`\n * entry and have it overlay the matching base entry without dropping the\n * rest (see {@link overlayById}).\n *\n * @example\n * ```ts\n * import { mergeSeedProduct } from '@adcp/sdk/testing';\n *\n * const baseline: Partial<Product> = {\n * delivery_type: 'guaranteed',\n * channels: ['display'],\n * pricing_options: [\n * { pricing_option_id: 'default', pricing_model: 'cpm', currency: 'USD', rate: 10 },\n * ],\n * };\n *\n * // Fixture carries only the fields the storyboard wants to override.\n * const merged = mergeSeedProduct(baseline, { product_id: 'prd-1', name: 'Homepage Takeover' });\n * // merged.delivery_type === 'guaranteed' (from baseline)\n * // merged.product_id === 'prd-1' (from fixture)\n * ```\n */\n\nimport type { Product, PricingOption } from '../types/tools.generated';\nimport type { MediaBuy } from '../types/core.generated';\n\n/**\n * Plain-object guard. Class instances, `Date`, `Map`, `Set`, and arrays fail\n * this check — they're treated as opaque leaves that replace their target\n * rather than merge. Matches the capability-overrides predicate in\n * `create-adcp-server.ts` so both paths agree on what counts as \"mergeable\".\n */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Reject Map/Set payloads loudly so silent stringification (→ `{}` via\n * `JSON.stringify`) can't ship. These types aren't expected in seed fixtures\n * — storyboards serialize over JSON — and allowing them would let a caller\n * pass a Map and never notice the merge dropped it on the floor.\n */\nfunction rejectUnsupportedCollection(value: unknown, path: string): void {\n if (value instanceof Map) {\n throw new TypeError(\n `mergeSeed: Map is not supported in seed fixtures at ${path}. Convert to a plain object before seeding.`\n );\n }\n if (value instanceof Set) {\n throw new TypeError(\n `mergeSeed: Set is not supported in seed fixtures at ${path}. Convert to an array before seeding.`\n );\n }\n}\n\n/**\n * Deep-merge `seed` onto `base`.\n *\n * Merge rules:\n * - `undefined` or `null` in `seed` → keep the `base` value untouched.\n * Every other falsy leaf (`0`, `false`, `\"\"`, `[]`) DOES override base.\n * - Plain-object values recurse (deep merge per key).\n * - Arrays REPLACE rather than concat — storyboards that seed arrays\n * expect to define the full list; concat would silently inflate\n * `pricing_options`, `publisher_properties`, and similar fields past\n * what the fixture declared. Typed wrappers layer per-array by-id\n * overlay on top for known id-keyed fields (see {@link overlayById}).\n * - `Map` / `Set` throw — not expected in seed payloads (see\n * {@link rejectUnsupportedCollection}).\n * - Other leaves (strings, numbers, booleans, Dates, class instances)\n * replace the base value.\n *\n * Neither input is mutated; a fresh object tree is returned.\n */\nexport function mergeSeed<T>(base: T, seed: Partial<T> | null | undefined): T {\n if (seed === null || seed === undefined) return base;\n rejectUnsupportedCollection(seed, '$');\n\n if (!isPlainObject(base) || !isPlainObject(seed)) {\n // One side is a leaf — a caller passing a non-object seed wants to\n // override with whatever leaf/array it carries.\n return (seed as T) ?? base;\n }\n\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(seed as Record<string, unknown>)) {\n if (value === undefined || value === null) continue;\n rejectUnsupportedCollection(value, `$.${key}`);\n\n const existing = out[key];\n if (isPlainObject(existing) && isPlainObject(value)) {\n out[key] = mergeSeed(existing, value);\n continue;\n }\n // Array replaces (documented above). Leaves replace.\n out[key] = value;\n }\n return out as T;\n}\n\n/**\n * Identity predicate for by-id array overlay. Returns a key that uniquely\n * identifies an item for matching, or `undefined` if the item can't be\n * identified (in which case the overlay falls through to append).\n */\ntype IdentityFn<T> = (item: T) => string | undefined;\n\n/**\n * Overlay a seed array onto a base array by a well-known id field.\n *\n * Semantics:\n * - Seed entries whose identity matches a base entry deep-merge onto\n * that base entry (via {@link mergeSeed}).\n * - Seed entries with no matching base entry append to the result.\n * - Base entries not referenced by any seed entry stay untouched.\n * - Seed entries missing an identity (e.g., no `pricing_option_id`)\n * append unconditionally — the fallback matches \"array replaces\" for\n * the un-identifiable tail but preserves the matched overlays.\n *\n * Neither input is mutated.\n *\n * @param base Base array (may be `undefined`).\n * @param seed Seed array (may be `undefined`).\n * @param identity Returns the id for matching; either a property name or a fn.\n */\nexport function overlayById<T>(\n base: readonly T[] | undefined,\n seed: readonly T[] | undefined,\n identity: IdentityFn<T> | keyof T\n): T[] | undefined {\n if (seed === undefined) return base ? [...base] : undefined;\n if (base === undefined || base.length === 0) return [...seed];\n\n const idOf: IdentityFn<T> =\n typeof identity === 'function'\n ? identity\n : (item: T) => {\n const v = (item as Record<string, unknown>)[identity as string];\n return typeof v === 'string' ? v : undefined;\n };\n\n const out: T[] = [];\n const seedById = new Map<string, T>();\n const seedUnkeyed: T[] = [];\n const consumed = new Set<string>();\n\n for (const item of seed) {\n const id = idOf(item);\n if (id !== undefined) seedById.set(id, item);\n else seedUnkeyed.push(item);\n }\n\n for (const baseItem of base) {\n const id = idOf(baseItem);\n if (id !== undefined && seedById.has(id)) {\n const seedItem = seedById.get(id)!;\n consumed.add(id);\n out.push(mergeSeed(baseItem, seedItem as Partial<T>));\n } else {\n out.push(baseItem);\n }\n }\n\n for (const [id, item] of seedById) {\n if (!consumed.has(id)) out.push(item);\n }\n for (const item of seedUnkeyed) out.push(item);\n\n return out;\n}\n\n// ────────────────────────────────────────────────────────────\n// Typed wrappers — one per seed kind.\n// ────────────────────────────────────────────────────────────\n//\n// Each wrapper delegates to `mergeSeed` for the top-level object merge,\n// then layers by-id overlay on known id-keyed arrays so sellers can seed\n// a single entry without replacing the rest.\n\n/**\n * Merge a `seed_product` fixture onto a baseline `Product` (or a partial\n * defaults object).\n *\n * **By-id overlay** is applied to:\n * - `pricing_options[]` — keyed by `pricing_option_id`. Seeding one\n * `{ pricing_option_id: 'premium', rate: 25 }` overlays the matching\n * base entry; other base pricing options stay put.\n * - `publisher_properties[]` — keyed by `publisher_domain` + `selection_type`\n * composite (PublisherPropertySelector is a discriminated union, no\n * single id field). Compact-form entries that carry `publisher_domains[]`\n * instead are keyed by the sorted, lowercased domain list joined with\n * `,` + `selection_type` so a re-seeded compact selector overlays its\n * counterpart instead of duplicating.\n *\n * Other arrays (`channels`, `format_ids`, `placements`, ...) still replace\n * wholesale per the {@link mergeSeed} default.\n */\nexport function mergeSeedProduct<TBase extends Partial<Product> = Partial<Product>>(\n base: TBase,\n seed: Partial<Product> | null | undefined\n): TBase {\n const merged = mergeSeed(base, seed as Partial<TBase>);\n if (!isPlainObject(merged) || !seed) return merged;\n\n const seedObj = seed as Partial<Product>;\n const out = merged as Record<string, unknown>;\n\n if (Array.isArray(seedObj.pricing_options)) {\n const overlaid = overlayById(\n (base as Partial<Product>).pricing_options as readonly PricingOption[] | undefined,\n seedObj.pricing_options,\n 'pricing_option_id'\n );\n if (overlaid !== undefined) out.pricing_options = overlaid;\n }\n\n if (Array.isArray(seedObj.publisher_properties)) {\n const overlaid = overlayById(\n (base as Partial<Product>).publisher_properties,\n seedObj.publisher_properties,\n item => {\n const domain = (item as { publisher_domain?: unknown }).publisher_domain;\n const domains = (item as { publisher_domains?: unknown }).publisher_domains;\n const sel = (item as { selection_type?: unknown }).selection_type;\n if (typeof sel !== 'string') return undefined;\n if (typeof domain === 'string') return `${domain.toLowerCase()}::${sel}`;\n if (Array.isArray(domains) && domains.length > 0 && domains.every(d => typeof d === 'string')) {\n // JSON.stringify the sorted-lowercased list — guarantees `['a,b']`\n // and `['a','b']` produce distinct keys (`[\"a,b\"]` vs `[\"a\",\"b\"]`)\n // rather than colliding under a naive comma-join.\n const sorted = [...(domains as string[])].map(d => d.toLowerCase()).sort();\n return `${JSON.stringify(sorted)}::${sel}`;\n }\n return undefined;\n }\n );\n if (overlaid !== undefined) out.publisher_properties = overlaid;\n }\n\n return merged;\n}\n\n/**\n * Merge a `seed_pricing_option` fixture onto a baseline pricing option. The\n * spec's `PricingOption` is a discriminated union; the generic signature\n * preserves whichever variant the base declares. No nested id-keyed arrays\n * to overlay — a pricing option is a leaf-ish record.\n */\nexport function mergeSeedPricingOption<TBase extends Partial<PricingOption> = Partial<PricingOption>>(\n base: TBase,\n seed: Partial<PricingOption> | null | undefined\n): TBase {\n return mergeSeed(base, seed as Partial<TBase>);\n}\n\n/**\n * Merge a `seed_creative` fixture onto a baseline creative. The SDK does not\n * ship a canonical `Creative` type (the spec models creatives as a union of\n * several assignment/manifest shapes), so the base is generic — sellers pass\n * whichever domain shape they store internally.\n *\n * **By-id overlay** is applied to `assets[]` when present, keyed by\n * `asset_id` — matches the creative manifest shape where assets are an\n * id-keyed list and sellers often seed a single asset override.\n */\nexport function mergeSeedCreative<TBase extends Record<string, unknown> = Record<string, unknown>>(\n base: TBase,\n seed: Partial<TBase> | null | undefined\n): TBase {\n const merged = mergeSeed(base, seed);\n if (!isPlainObject(merged) || !seed) return merged;\n\n const seedObj = seed as Record<string, unknown>;\n const baseObj = base as Record<string, unknown>;\n const out = merged as Record<string, unknown>;\n\n if (Array.isArray(seedObj.assets)) {\n const overlaid = overlayById(\n Array.isArray(baseObj.assets) ? (baseObj.assets as unknown[]) : undefined,\n seedObj.assets,\n 'asset_id'\n );\n if (overlaid !== undefined) out.assets = overlaid;\n }\n\n return merged;\n}\n\n/**\n * Merge a `seed_plan` fixture onto a baseline plan. Like creatives, the spec\n * splits plans across several tool-response shapes, so the base type stays\n * generic.\n *\n * **By-id overlay** is applied to any of these known id-keyed arrays when\n * present on the seed:\n * - `member_plan_ids[]` — string array, no overlay (replaces).\n * - `accounts[]` — string array, no overlay (replaces).\n * - `findings[]` — keyed by `policy_id`.\n * - `checks[]` — keyed by `check_id` when present.\n *\n * Other arrays replace wholesale per {@link mergeSeed}.\n */\nexport function mergeSeedPlan<TBase extends Record<string, unknown> = Record<string, unknown>>(\n base: TBase,\n seed: Partial<TBase> | null | undefined\n): TBase {\n const merged = mergeSeed(base, seed);\n if (!isPlainObject(merged) || !seed) return merged;\n\n const seedObj = seed as Record<string, unknown>;\n const baseObj = base as Record<string, unknown>;\n const out = merged as Record<string, unknown>;\n\n const overlay = (field: string, idField: string) => {\n if (!Array.isArray(seedObj[field])) return;\n const overlaid = overlayById(\n Array.isArray(baseObj[field]) ? (baseObj[field] as unknown[]) : undefined,\n seedObj[field] as unknown[],\n idField as never\n );\n if (overlaid !== undefined) out[field] = overlaid;\n };\n\n overlay('findings', 'policy_id');\n overlay('checks', 'check_id');\n\n return merged;\n}\n\n/**\n * Merge a `seed_media_buy` fixture onto a baseline `MediaBuy`.\n *\n * **By-id overlay** is applied to `packages[]` keyed by `package_id` — the\n * common storyboard pattern is \"seed one package's `delivery` or `status`\n * without rewriting the whole package list\", which a naive array replace\n * would break.\n */\nexport function mergeSeedMediaBuy<TBase extends Partial<MediaBuy> = Partial<MediaBuy>>(\n base: TBase,\n seed: Partial<MediaBuy> | null | undefined\n): TBase {\n const merged = mergeSeed(base, seed as Partial<TBase>);\n if (!isPlainObject(merged) || !seed) return merged;\n\n const seedObj = seed as Partial<MediaBuy>;\n const out = merged as Record<string, unknown>;\n\n if (Array.isArray(seedObj.packages)) {\n const overlaid = overlayById((base as Partial<MediaBuy>).packages, seedObj.packages, 'package_id');\n if (overlaid !== undefined) out.packages = overlaid;\n }\n\n return merged;\n}\n"],"mappings":"AAqDA,SAAS,cAAc,OAAkD;AACvE,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,QAAM,QAAiB,OAAO,eAAe,KAAK;AAClD,SAAO,UAAU,OAAO,aAAa,UAAU;AACjD;AAQA,SAAS,4BAA4B,OAAgB,MAAoB;AACvE,MAAI,iBAAiB,KAAK;AACxB,UAAM,IAAI;AAAA,MACR,uDAAuD,IAAI;AAAA,IAC7D;AAAA,EACF;AACA,MAAI,iBAAiB,KAAK;AACxB,UAAM,IAAI;AAAA,MACR,uDAAuD,IAAI;AAAA,IAC7D;AAAA,EACF;AACF;AAqBO,SAAS,UAAa,MAAS,MAAwC;AAC5E,MAAI,SAAS,QAAQ,SAAS,OAAW,QAAO;AAChD,8BAA4B,MAAM,GAAG;AAErC,MAAI,CAAC,cAAc,IAAI,KAAK,CAAC,cAAc,IAAI,GAAG;AAGhD,WAAQ,QAAc;AAAA,EACxB;AAEA,QAAM,MAA+B,EAAE,GAAG,KAAK;AAC/C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAA+B,GAAG;AAC1E,QAAI,UAAU,UAAa,UAAU,KAAM;AAC3C,gCAA4B,OAAO,KAAK,GAAG,EAAE;AAE7C,UAAM,WAAW,IAAI,GAAG;AACxB,QAAI,cAAc,QAAQ,KAAK,cAAc,KAAK,GAAG;AACnD,UAAI,GAAG,IAAI,UAAU,UAAU,KAAK;AACpC;AAAA,IACF;AAEA,QAAI,GAAG,IAAI;AAAA,EACb;AACA,SAAO;AACT;AA2BO,SAAS,YACd,MACA,MACA,UACiB;AACjB,MAAI,SAAS,OAAW,QAAO,OAAO,CAAC,GAAG,IAAI,IAAI;AAClD,MAAI,SAAS,UAAa,KAAK,WAAW,EAAG,QAAO,CAAC,GAAG,IAAI;AAE5D,QAAM,OACJ,OAAO,aAAa,aAChB,WACA,CAAC,SAAY;AACX,UAAM,IAAK,KAAiC,QAAkB;AAC9D,WAAO,OAAO,MAAM,WAAW,IAAI;AAAA,EACrC;AAEN,QAAM,MAAW,CAAC;AAClB,QAAM,WAAW,oBAAI,IAAe;AACpC,QAAM,cAAmB,CAAC;AAC1B,QAAM,WAAW,oBAAI,IAAY;AAEjC,aAAW,QAAQ,MAAM;AACvB,UAAM,KAAK,KAAK,IAAI;AACpB,QAAI,OAAO,OAAW,UAAS,IAAI,IAAI,IAAI;AAAA,QACtC,aAAY,KAAK,IAAI;AAAA,EAC5B;AAEA,aAAW,YAAY,MAAM;AAC3B,UAAM,KAAK,KAAK,QAAQ;AACxB,QAAI,OAAO,UAAa,SAAS,IAAI,EAAE,GAAG;AACxC,YAAM,WAAW,SAAS,IAAI,EAAE;AAChC,eAAS,IAAI,EAAE;AACf,UAAI,KAAK,UAAU,UAAU,QAAsB,CAAC;AAAA,IACtD,OAAO;AACL,UAAI,KAAK,QAAQ;AAAA,IACnB;AAAA,EACF;AAEA,aAAW,CAAC,IAAI,IAAI,KAAK,UAAU;AACjC,QAAI,CAAC,SAAS,IAAI,EAAE,EAAG,KAAI,KAAK,IAAI;AAAA,EACtC;AACA,aAAW,QAAQ,YAAa,KAAI,KAAK,IAAI;AAE7C,SAAO;AACT;AA4BO,SAAS,iBACd,MACA,MACO;AACP,QAAM,SAAS,UAAU,MAAM,IAAsB;AACrD,MAAI,CAAC,cAAc,MAAM,KAAK,CAAC,KAAM,QAAO;AAE5C,QAAM,UAAU;AAChB,QAAM,MAAM;AAEZ,MAAI,MAAM,QAAQ,QAAQ,eAAe,GAAG;AAC1C,UAAM,WAAW;AAAA,MACd,KAA0B;AAAA,MAC3B,QAAQ;AAAA,MACR;AAAA,IACF;AACA,QAAI,aAAa,OAAW,KAAI,kBAAkB;AAAA,EACpD;AAEA,MAAI,MAAM,QAAQ,QAAQ,oBAAoB,GAAG;AAC/C,UAAM,WAAW;AAAA,MACd,KAA0B;AAAA,MAC3B,QAAQ;AAAA,MACR,UAAQ;AACN,cAAM,SAAU,KAAwC;AACxD,cAAM,UAAW,KAAyC;AAC1D,cAAM,MAAO,KAAsC;AACnD,YAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,YAAI,OAAO,WAAW,SAAU,QAAO,GAAG,OAAO,YAAY,CAAC,KAAK,GAAG;AACtE,YAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,KAAK,QAAQ,MAAM,OAAK,OAAO,MAAM,QAAQ,GAAG;AAI7F,gBAAM,SAAS,CAAC,GAAI,OAAoB,EAAE,IAAI,OAAK,EAAE,YAAY,CAAC,EAAE,KAAK;AACzE,iBAAO,GAAG,KAAK,UAAU,MAAM,CAAC,KAAK,GAAG;AAAA,QAC1C;AACA,eAAO;AAAA,MACT;AAAA,IACF;AACA,QAAI,aAAa,OAAW,KAAI,uBAAuB;AAAA,EACzD;AAEA,SAAO;AACT;AAQO,SAAS,uBACd,MACA,MACO;AACP,SAAO,UAAU,MAAM,IAAsB;AAC/C;AAYO,SAAS,kBACd,MACA,MACO;AACP,QAAM,SAAS,UAAU,MAAM,IAAI;AACnC,MAAI,CAAC,cAAc,MAAM,KAAK,CAAC,KAAM,QAAO;AAE5C,QAAM,UAAU;AAChB,QAAM,UAAU;AAChB,QAAM,MAAM;AAEZ,MAAI,MAAM,QAAQ,QAAQ,MAAM,GAAG;AACjC,UAAM,WAAW;AAAA,MACf,MAAM,QAAQ,QAAQ,MAAM,IAAK,QAAQ,SAAuB;AAAA,MAChE,QAAQ;AAAA,MACR;AAAA,IACF;AACA,QAAI,aAAa,OAAW,KAAI,SAAS;AAAA,EAC3C;AAEA,SAAO;AACT;AAgBO,SAAS,cACd,MACA,MACO;AACP,QAAM,SAAS,UAAU,MAAM,IAAI;AACnC,MAAI,CAAC,cAAc,MAAM,KAAK,CAAC,KAAM,QAAO;AAE5C,QAAM,UAAU;AAChB,QAAM,UAAU;AAChB,QAAM,MAAM;AAEZ,QAAM,UAAU,CAAC,OAAe,YAAoB;AAClD,QAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,CAAC,EAAG;AACpC,UAAM,WAAW;AAAA,MACf,MAAM,QAAQ,QAAQ,KAAK,CAAC,IAAK,QAAQ,KAAK,IAAkB;AAAA,MAChE,QAAQ,KAAK;AAAA,MACb;AAAA,IACF;AACA,QAAI,aAAa,OAAW,KAAI,KAAK,IAAI;AAAA,EAC3C;AAEA,UAAQ,YAAY,WAAW;AAC/B,UAAQ,UAAU,UAAU;AAE5B,SAAO;AACT;AAUO,SAAS,kBACd,MACA,MACO;AACP,QAAM,SAAS,UAAU,MAAM,IAAsB;AACrD,MAAI,CAAC,cAAc,MAAM,KAAK,CAAC,KAAM,QAAO;AAE5C,QAAM,UAAU;AAChB,QAAM,MAAM;AAEZ,MAAI,MAAM,QAAQ,QAAQ,QAAQ,GAAG;AACnC,UAAM,WAAW,YAAa,KAA2B,UAAU,QAAQ,UAAU,YAAY;AACjG,QAAI,aAAa,OAAW,KAAI,WAAW;AAAA,EAC7C;AAEA,SAAO;AACT;","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 { getOrCreateClient, getOrDiscoverProfile } from "../client.mjs";
|
|
8
2
|
import { TASK_FEATURE_MAP } from "../../utils/capabilities.mjs";
|
|
9
3
|
const KNOWN_PROTOCOLS = /* @__PURE__ */ new Set([
|