@adcp/sdk 12.0.0 → 12.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/adapters/content-standards-adapter.mjs +0 -6
- package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
- package/dist/lib/adapters/derived-account-store.mjs +0 -6
- package/dist/lib/adapters/derived-account-store.mjs.map +1 -1
- package/dist/lib/adapters/governance-adapter.mjs +0 -6
- package/dist/lib/adapters/governance-adapter.mjs.map +1 -1
- package/dist/lib/adapters/implicit-account-store.mjs +0 -6
- package/dist/lib/adapters/implicit-account-store.mjs.map +1 -1
- package/dist/lib/adapters/index.mjs +0 -6
- package/dist/lib/adapters/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/index.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/types.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs +0 -6
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs.map +1 -1
- package/dist/lib/adapters/property-list-adapter.mjs +0 -6
- package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
- package/dist/lib/adapters/roster-account-store.mjs +0 -6
- package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
- package/dist/lib/adapters/si-session-manager.mjs +0 -6
- package/dist/lib/adapters/si-session-manager.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/brand-fields.mjs +0 -6
- package/dist/lib/adapters/version/3.0/brand-fields.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/get-products.mjs +0 -6
- package/dist/lib/adapters/version/3.0/get-products.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/index.mjs +0 -6
- package/dist/lib/adapters/version/3.0/index.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs +0 -6
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs.map +1 -1
- package/dist/lib/adapters/version/index.mjs +0 -6
- package/dist/lib/adapters/version/index.mjs.map +1 -1
- package/dist/lib/adapters/version/types.mjs +0 -6
- package/dist/lib/advanced.mjs +0 -6
- package/dist/lib/advanced.mjs.map +1 -1
- package/dist/lib/agents/index.generated.mjs +0 -6
- package/dist/lib/agents/index.generated.mjs.map +1 -1
- package/dist/lib/auth/index.mjs +0 -6
- package/dist/lib/auth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +0 -6
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs.map +1 -1
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +0 -6
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs.map +1 -1
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/authorization-required.mjs +0 -6
- package/dist/lib/auth/oauth/authorization-required.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnose.mjs +0 -6
- package/dist/lib/auth/oauth/diagnose.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnostics.mjs +0 -6
- package/dist/lib/auth/oauth/diagnostics.mjs.map +1 -1
- package/dist/lib/auth/oauth/discovery.mjs +0 -6
- package/dist/lib/auth/oauth/discovery.mjs.map +1 -1
- package/dist/lib/auth/oauth/file-storage.mjs +0 -6
- package/dist/lib/auth/oauth/file-storage.mjs.map +1 -1
- package/dist/lib/auth/oauth/index.mjs +0 -6
- package/dist/lib/auth/oauth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/secret-resolver.mjs +0 -6
- package/dist/lib/auth/oauth/secret-resolver.mjs.map +1 -1
- package/dist/lib/auth/oauth/storage-registry.mjs +0 -6
- package/dist/lib/auth/oauth/storage-registry.mjs.map +1 -1
- package/dist/lib/auth/oauth/types.mjs +0 -6
- package/dist/lib/auth/oauth/types.mjs.map +1 -1
- package/dist/lib/auth/oauth/web-flow.mjs +0 -6
- package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
- package/dist/lib/brand/index.mjs +0 -6
- package/dist/lib/brand/index.mjs.map +1 -1
- package/dist/lib/canonical-references/index.mjs +6 -7
- package/dist/lib/canonical-references/index.mjs.map +1 -1
- package/dist/lib/client/index.mjs +0 -6
- package/dist/lib/client/index.mjs.map +1 -1
- package/dist/lib/compliance/index.mjs +0 -6
- package/dist/lib/compliance/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/index.mjs +0 -6
- package/dist/lib/compliance-fixtures/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs +0 -6
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs.map +1 -1
- package/dist/lib/conformance/index.mjs +0 -6
- package/dist/lib/conformance/index.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformError.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs.map +1 -1
- package/dist/lib/conformance/oracle.mjs +0 -6
- package/dist/lib/conformance/oracle.mjs.map +1 -1
- package/dist/lib/conformance/runConformance.mjs +0 -6
- package/dist/lib/conformance/runConformance.mjs.map +1 -1
- package/dist/lib/conformance/runners.mjs +0 -6
- package/dist/lib/conformance/runners.mjs.map +1 -1
- package/dist/lib/conformance/schemaArbitrary.mjs +0 -6
- package/dist/lib/conformance/schemaArbitrary.mjs.map +1 -1
- package/dist/lib/conformance/schemaLoader.mjs +5 -6
- package/dist/lib/conformance/schemaLoader.mjs.map +1 -1
- package/dist/lib/conformance/seeder.mjs +0 -6
- package/dist/lib/conformance/seeder.mjs.map +1 -1
- package/dist/lib/conformance/types.mjs +0 -6
- package/dist/lib/conformance/types.mjs.map +1 -1
- package/dist/lib/conformance/webhook.mjs +0 -6
- package/dist/lib/conformance/webhook.mjs.map +1 -1
- package/dist/lib/core/ADCPMultiAgentClient.mjs +0 -6
- package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
- package/dist/lib/core/AgentClient.mjs +0 -6
- package/dist/lib/core/AgentClient.mjs.map +1 -1
- package/dist/lib/core/AsyncHandler.mjs +0 -6
- package/dist/lib/core/AsyncHandler.mjs.map +1 -1
- package/dist/lib/core/ConfigurationManager.mjs +0 -6
- package/dist/lib/core/ConfigurationManager.mjs.map +1 -1
- package/dist/lib/core/ConversationTypes.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
- package/dist/lib/core/GovernanceMiddleware.mjs +0 -6
- package/dist/lib/core/GovernanceMiddleware.mjs.map +1 -1
- package/dist/lib/core/GovernanceTypes.mjs +0 -6
- package/dist/lib/core/GovernanceTypes.mjs.map +1 -1
- package/dist/lib/core/ProtocolResponseParser.mjs +0 -6
- package/dist/lib/core/ProtocolResponseParser.mjs.map +1 -1
- package/dist/lib/core/ResponseValidator.mjs +0 -6
- package/dist/lib/core/ResponseValidator.mjs.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +0 -6
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskEventTypes.mjs +0 -6
- package/dist/lib/core/TaskEventTypes.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +0 -6
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/core/match.mjs +0 -6
- package/dist/lib/core/match.mjs.map +1 -1
- package/dist/lib/core/task-status.mjs +0 -6
- package/dist/lib/core/task-status.mjs.map +1 -1
- package/dist/lib/core/webhook-url.mjs +0 -6
- package/dist/lib/core/webhook-url.mjs.map +1 -1
- package/dist/lib/discovery/adagents-redirects.mjs +0 -6
- package/dist/lib/discovery/adagents-redirects.mjs.map +1 -1
- package/dist/lib/discovery/agent-directory.mjs +0 -6
- package/dist/lib/discovery/agent-directory.mjs.map +1 -1
- package/dist/lib/discovery/inline-publisher-properties.mjs +0 -6
- package/dist/lib/discovery/inline-publisher-properties.mjs.map +1 -1
- package/dist/lib/discovery/network-consistency-checker.mjs +0 -6
- package/dist/lib/discovery/network-consistency-checker.mjs.map +1 -1
- package/dist/lib/discovery/property-crawler.mjs +0 -6
- package/dist/lib/discovery/property-crawler.mjs.map +1 -1
- package/dist/lib/discovery/property-index.mjs +0 -6
- package/dist/lib/discovery/property-index.mjs.map +1 -1
- package/dist/lib/discovery/publisher-property-selector.mjs +0 -6
- package/dist/lib/discovery/publisher-property-selector.mjs.map +1 -1
- package/dist/lib/discovery/resolve-agent-properties.mjs +0 -6
- package/dist/lib/discovery/resolve-agent-properties.mjs.map +1 -1
- package/dist/lib/discovery/types.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs.map +1 -1
- package/dist/lib/enums.mjs +0 -6
- package/dist/lib/enums.mjs.map +1 -1
- package/dist/lib/errors/index.mjs +0 -6
- package/dist/lib/errors/index.mjs.map +1 -1
- package/dist/lib/express-mcp/index.mjs +0 -6
- package/dist/lib/express-mcp/index.mjs.map +1 -1
- package/dist/lib/governance/index.mjs +0 -6
- package/dist/lib/governance/index.mjs.map +1 -1
- package/dist/lib/handlers/types.mjs +0 -6
- package/dist/lib/handlers/types.mjs.map +1 -1
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +0 -6
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/media-buy/available-actions.mjs +0 -6
- package/dist/lib/media-buy/available-actions.mjs.map +1 -1
- package/dist/lib/media-buy/index.mjs +0 -6
- package/dist/lib/media-buy/index.mjs.map +1 -1
- package/dist/lib/media-buy/preflight.mjs +0 -6
- package/dist/lib/media-buy/preflight.mjs.map +1 -1
- package/dist/lib/media-buy/property-policy.mjs +0 -6
- package/dist/lib/media-buy/property-policy.mjs.map +1 -1
- package/dist/lib/media-buy/types.mjs +0 -6
- package/dist/lib/media-buy/types.mjs.map +1 -1
- package/dist/lib/media-buy/update-fields.generated.mjs +0 -6
- package/dist/lib/media-buy/update-fields.generated.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/server.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/server.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-template/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/server.mjs +0 -6
- package/dist/lib/mock-server/creative-template/server.mjs.map +1 -1
- package/dist/lib/mock-server/index.mjs +0 -6
- package/dist/lib/mock-server/index.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-social/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/server.mjs +0 -6
- package/dist/lib/mock-server/sales-social/server.mjs.map +1 -1
- package/dist/lib/mock-server/scenario.mjs +0 -6
- package/dist/lib/mock-server/scenario.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/server.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/server.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs.map +1 -1
- package/dist/lib/net/address-guards.mjs +0 -6
- package/dist/lib/net/address-guards.mjs.map +1 -1
- package/dist/lib/net/index.mjs +0 -6
- package/dist/lib/net/index.mjs.map +1 -1
- package/dist/lib/net/ssrf-fetch.mjs +0 -6
- package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
- package/dist/lib/observability/index.mjs +0 -6
- package/dist/lib/observability/index.mjs.map +1 -1
- package/dist/lib/observability/tracing.mjs +6 -7
- package/dist/lib/observability/tracing.mjs.map +1 -1
- package/dist/lib/protocols/a2a.mjs +0 -6
- package/dist/lib/protocols/a2a.mjs.map +1 -1
- package/dist/lib/protocols/abort.mjs +0 -6
- package/dist/lib/protocols/abort.mjs.map +1 -1
- package/dist/lib/protocols/index.mjs +0 -6
- package/dist/lib/protocols/index.mjs.map +1 -1
- package/dist/lib/protocols/mcp-modern.mjs +0 -6
- package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
- package/dist/lib/protocols/mcp-tasks.mjs +0 -6
- package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
- package/dist/lib/protocols/mcp.mjs +0 -6
- package/dist/lib/protocols/mcp.mjs.map +1 -1
- package/dist/lib/protocols/rawResponseCapture.mjs +0 -6
- package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
- package/dist/lib/protocols/responseSizeLimit.mjs +0 -6
- package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
- package/dist/lib/protocols/transportDiagnostics.mjs +0 -6
- package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
- package/dist/lib/registry/cursor-store.mjs +0 -6
- package/dist/lib/registry/cursor-store.mjs.map +1 -1
- package/dist/lib/registry/feed-stream.mjs +0 -6
- package/dist/lib/registry/feed-stream.mjs.map +1 -1
- package/dist/lib/registry/index.mjs +0 -6
- package/dist/lib/registry/index.mjs.map +1 -1
- package/dist/lib/registry/property-registry.mjs +0 -6
- package/dist/lib/registry/property-registry.mjs.map +1 -1
- package/dist/lib/registry/sync.mjs +0 -6
- package/dist/lib/registry/sync.mjs.map +1 -1
- package/dist/lib/registry/types.generated.mjs +0 -6
- package/dist/lib/registry/types.mjs +0 -6
- package/dist/lib/schemas/index.mjs +0 -6
- package/dist/lib/schemas/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/a2a-adapter.mjs +0 -6
- package/dist/lib/server/a2a-adapter.mjs.map +1 -1
- package/dist/lib/server/account-mode.mjs +0 -6
- package/dist/lib/server/account-mode.mjs.map +1 -1
- package/dist/lib/server/adcp-server.mjs +0 -6
- package/dist/lib/server/adcp-server.mjs.map +1 -1
- package/dist/lib/server/auth-introspection.mjs +0 -6
- package/dist/lib/server/auth-introspection.mjs.map +1 -1
- package/dist/lib/server/auth-signature.mjs +0 -6
- package/dist/lib/server/auth-signature.mjs.map +1 -1
- package/dist/lib/server/auth.mjs +0 -6
- package/dist/lib/server/auth.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +13 -0
- package/dist/lib/server/create-adcp-server.d.ts +13 -0
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +3 -2
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +3 -8
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/credential-policy.mjs +0 -6
- package/dist/lib/server/credential-policy.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/memory.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/memory.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/pg.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/pg.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/redis.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/redis.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/index.mjs +0 -6
- package/dist/lib/server/ctx-metadata/index.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/store.mjs +0 -6
- package/dist/lib/server/ctx-metadata/store.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/wire-shape.mjs +0 -6
- package/dist/lib/server/ctx-metadata/wire-shape.mjs.map +1 -1
- package/dist/lib/server/decisioning/account.mjs +0 -6
- package/dist/lib/server/decisioning/account.mjs.map +1 -1
- package/dist/lib/server/decisioning/admin-router.mjs +0 -6
- package/dist/lib/server/decisioning/admin-router.mjs.map +1 -1
- package/dist/lib/server/decisioning/assembly-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/async-outcome.mjs +0 -6
- package/dist/lib/server/decisioning/async-outcome.mjs.map +1 -1
- package/dist/lib/server/decisioning/buyer-agent.mjs +0 -6
- package/dist/lib/server/decisioning/buyer-agent.mjs.map +1 -1
- package/dist/lib/server/decisioning/capabilities.mjs +0 -6
- package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
- package/dist/lib/server/decisioning/compose.mjs +0 -6
- package/dist/lib/server/decisioning/compose.mjs.map +1 -1
- package/dist/lib/server/decisioning/context.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs.map +1 -1
- package/dist/lib/server/decisioning/helpers.mjs +0 -6
- package/dist/lib/server/decisioning/helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +0 -6
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/list-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/pagination.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/platform.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/index.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/store.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/store.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
- package/dist/lib/server/decisioning/resolve-presets.mjs +0 -6
- package/dist/lib/server/decisioning/resolve-presets.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/audiences.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/brand-rights.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/campaign-governance.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/content-standards.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/lists.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sales.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/signals.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-changes.mjs +0 -6
- package/dist/lib/server/decisioning/status-changes.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-mappers.mjs +0 -6
- package/dist/lib/server/decisioning/status-mappers.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-registry.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-store.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
- package/dist/lib/server/decisioning/validate-specialisms.mjs +0 -6
- package/dist/lib/server/decisioning/validate-specialisms.mjs.map +1 -1
- package/dist/lib/server/dynamic-registry.mjs +0 -6
- package/dist/lib/server/dynamic-registry.mjs.map +1 -1
- package/dist/lib/server/envelope-allowlist.mjs +0 -6
- package/dist/lib/server/envelope-allowlist.mjs.map +1 -1
- package/dist/lib/server/error-arm-tools.mjs +5 -6
- package/dist/lib/server/error-arm-tools.mjs.map +1 -1
- package/dist/lib/server/errors.mjs +0 -6
- package/dist/lib/server/errors.mjs.map +1 -1
- package/dist/lib/server/example-tld-guard.mjs +0 -6
- package/dist/lib/server/example-tld-guard.mjs.map +1 -1
- package/dist/lib/server/express-adapter.mjs +0 -6
- package/dist/lib/server/express-adapter.mjs.map +1 -1
- package/dist/lib/server/governance.mjs +0 -6
- package/dist/lib/server/governance.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/lazy.mjs +0 -6
- package/dist/lib/server/idempotency/backends/lazy.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/memory.mjs +0 -6
- package/dist/lib/server/idempotency/backends/memory.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/pg.mjs +0 -6
- package/dist/lib/server/idempotency/backends/pg.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/redis.mjs +0 -6
- package/dist/lib/server/idempotency/backends/redis.mjs.map +1 -1
- package/dist/lib/server/idempotency/index.mjs +0 -6
- package/dist/lib/server/idempotency/index.mjs.map +1 -1
- package/dist/lib/server/idempotency/store.mjs +0 -6
- package/dist/lib/server/idempotency/store.mjs.map +1 -1
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs +0 -6
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/legacy/v5/index.d.mts +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
- package/dist/lib/server/legacy/v5/index.js.map +1 -1
- package/dist/lib/server/legacy/v5/index.mjs +0 -6
- package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
- package/dist/lib/server/mcp-modern-server.mjs +0 -6
- package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
- package/dist/lib/server/media-buy-actions.mjs +0 -6
- package/dist/lib/server/media-buy-actions.mjs.map +1 -1
- package/dist/lib/server/media-buy-helpers.mjs +0 -6
- package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
- package/dist/lib/server/media-buy-store.mjs +0 -6
- package/dist/lib/server/media-buy-store.mjs.map +1 -1
- package/dist/lib/server/normalize-errors.mjs +0 -6
- package/dist/lib/server/normalize-errors.mjs.map +1 -1
- package/dist/lib/server/operational-platform.mjs +0 -6
- package/dist/lib/server/operational-platform.mjs.map +1 -1
- package/dist/lib/server/pick-safe-details.mjs +0 -6
- package/dist/lib/server/pick-safe-details.mjs.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
- package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
- package/dist/lib/server/postgres-state-store.mjs +0 -6
- package/dist/lib/server/postgres-state-store.mjs.map +1 -1
- package/dist/lib/server/postgres-task-store.mjs +0 -6
- package/dist/lib/server/postgres-task-store.mjs.map +1 -1
- package/dist/lib/server/product-defaults.mjs +0 -6
- package/dist/lib/server/product-defaults.mjs.map +1 -1
- package/dist/lib/server/redact.mjs +0 -6
- package/dist/lib/server/redact.mjs.map +1 -1
- package/dist/lib/server/responses.mjs +0 -6
- package/dist/lib/server/responses.mjs.map +1 -1
- package/dist/lib/server/serve.mjs +0 -6
- package/dist/lib/server/serve.mjs.map +1 -1
- package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
- package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
- package/dist/lib/server/socket-mode/index.mjs +0 -6
- package/dist/lib/server/socket-mode/index.mjs.map +1 -1
- package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
- package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
- package/dist/lib/server/state-machine.mjs +0 -6
- package/dist/lib/server/state-machine.mjs.map +1 -1
- package/dist/lib/server/state-store.mjs +0 -6
- package/dist/lib/server/state-store.mjs.map +1 -1
- package/dist/lib/server/structured-serialize.mjs +0 -6
- package/dist/lib/server/structured-serialize.mjs.map +1 -1
- package/dist/lib/server/targeting-helpers.mjs +0 -6
- package/dist/lib/server/targeting-helpers.mjs.map +1 -1
- package/dist/lib/server/tasks.mjs +0 -6
- package/dist/lib/server/tasks.mjs.map +1 -1
- package/dist/lib/server/test-controller-bridge.mjs +0 -6
- package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
- package/dist/lib/server/test-controller.mjs +0 -6
- package/dist/lib/server/test-controller.mjs.map +1 -1
- package/dist/lib/server/upstream-helpers.mjs +0 -6
- package/dist/lib/server/upstream-helpers.mjs.map +1 -1
- package/dist/lib/server/webhook-emitter.mjs +0 -6
- package/dist/lib/server/webhook-emitter.mjs.map +1 -1
- package/dist/lib/server/wire-safe.mjs +0 -6
- package/dist/lib/server/wire-safe.mjs.map +1 -1
- package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
- package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
- package/dist/lib/server/wrap-envelope.mjs +0 -6
- package/dist/lib/server/wrap-envelope.mjs.map +1 -1
- package/dist/lib/signing/agent-context.mjs +0 -6
- package/dist/lib/signing/agent-context.mjs.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +0 -6
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
- package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
- package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
- package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
- package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/index.mjs +0 -6
- package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
- package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
- package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
- package/dist/lib/signing/brand-jwks.mjs +0 -6
- package/dist/lib/signing/brand-jwks.mjs.map +1 -1
- package/dist/lib/signing/canonicalize.mjs +0 -6
- package/dist/lib/signing/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/capability-cache.mjs +0 -6
- package/dist/lib/signing/capability-cache.mjs.map +1 -1
- package/dist/lib/signing/capability-priming.mjs +0 -6
- package/dist/lib/signing/capability-priming.mjs.map +1 -1
- package/dist/lib/signing/client.mjs +0 -6
- package/dist/lib/signing/client.mjs.map +1 -1
- package/dist/lib/signing/content-digest.mjs +0 -6
- package/dist/lib/signing/content-digest.mjs.map +1 -1
- package/dist/lib/signing/crypto.mjs +0 -6
- package/dist/lib/signing/crypto.mjs.map +1 -1
- package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
- package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
- package/dist/lib/signing/errors.mjs +0 -6
- package/dist/lib/signing/errors.mjs.map +1 -1
- package/dist/lib/signing/fetch-async.mjs +0 -6
- package/dist/lib/signing/fetch-async.mjs.map +1 -1
- package/dist/lib/signing/fetch.mjs +0 -6
- package/dist/lib/signing/fetch.mjs.map +1 -1
- package/dist/lib/signing/index.mjs +0 -6
- package/dist/lib/signing/index.mjs.map +1 -1
- package/dist/lib/signing/jwks-helpers.mjs +0 -6
- package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
- package/dist/lib/signing/jwks-https.mjs +0 -6
- package/dist/lib/signing/jwks-https.mjs.map +1 -1
- package/dist/lib/signing/jwks.mjs +0 -6
- package/dist/lib/signing/jwks.mjs.map +1 -1
- package/dist/lib/signing/middleware.mjs +0 -6
- package/dist/lib/signing/middleware.mjs.map +1 -1
- package/dist/lib/signing/parser.mjs +0 -6
- package/dist/lib/signing/parser.mjs.map +1 -1
- package/dist/lib/signing/postgres-replay-store.mjs +0 -6
- package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
- package/dist/lib/signing/protocol-response.mjs +0 -6
- package/dist/lib/signing/protocol-response.mjs.map +1 -1
- package/dist/lib/signing/provider.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
- package/dist/lib/signing/replay.mjs +0 -6
- package/dist/lib/signing/replay.mjs.map +1 -1
- package/dist/lib/signing/request-context.mjs +0 -6
- package/dist/lib/signing/request-context.mjs.map +1 -1
- package/dist/lib/signing/revocation-https.mjs +0 -6
- package/dist/lib/signing/revocation-https.mjs.map +1 -1
- package/dist/lib/signing/revocation.mjs +0 -6
- package/dist/lib/signing/revocation.mjs.map +1 -1
- package/dist/lib/signing/server.mjs +0 -6
- package/dist/lib/signing/server.mjs.map +1 -1
- package/dist/lib/signing/signer-async.mjs +0 -6
- package/dist/lib/signing/signer-async.mjs.map +1 -1
- package/dist/lib/signing/signer.mjs +0 -6
- package/dist/lib/signing/signer.mjs.map +1 -1
- package/dist/lib/signing/testing.mjs +0 -6
- package/dist/lib/signing/testing.mjs.map +1 -1
- package/dist/lib/signing/types.mjs +0 -6
- package/dist/lib/signing/types.mjs.map +1 -1
- package/dist/lib/signing/verifier.mjs +0 -6
- package/dist/lib/signing/verifier.mjs.map +1 -1
- package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
- package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
- package/dist/lib/signing/webhook-verifier.mjs +0 -6
- package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
- package/dist/lib/storage/MemoryStorage.mjs +0 -6
- package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
- package/dist/lib/storage/interfaces.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
- package/dist/lib/substitution/encoder/index.mjs +0 -6
- package/dist/lib/substitution/encoder/index.mjs.map +1 -1
- package/dist/lib/substitution/index.mjs +0 -6
- package/dist/lib/substitution/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
- package/dist/lib/substitution/observer/alignment.mjs +0 -6
- package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
- package/dist/lib/substitution/observer/assertions.mjs +0 -6
- package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
- package/dist/lib/substitution/observer/html-parser.mjs +0 -6
- package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
- package/dist/lib/substitution/observer/index.mjs +0 -6
- package/dist/lib/substitution/observer/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/ssrf.mjs +0 -6
- package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
- package/dist/lib/substitution/rfc3986.mjs +0 -6
- package/dist/lib/substitution/rfc3986.mjs.map +1 -1
- package/dist/lib/substitution/translate.mjs +0 -6
- package/dist/lib/substitution/translate.mjs.map +1 -1
- package/dist/lib/substitution/types.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs.map +1 -1
- package/dist/lib/testing/agent-tester.mjs +0 -6
- package/dist/lib/testing/agent-tester.mjs.map +1 -1
- package/dist/lib/testing/client.mjs +0 -6
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/compliance/briefs.mjs +0 -6
- package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +0 -6
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.mjs +0 -6
- package/dist/lib/testing/compliance/index.mjs.map +1 -1
- package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
- package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
- package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
- package/dist/lib/testing/compliance/summary.mjs +0 -6
- package/dist/lib/testing/compliance/summary.mjs.map +1 -1
- package/dist/lib/testing/compliance/types.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs.map +1 -1
- package/dist/lib/testing/controller-assertions.mjs +0 -6
- package/dist/lib/testing/controller-assertions.mjs.map +1 -1
- package/dist/lib/testing/formatter.mjs +0 -6
- package/dist/lib/testing/formatter.mjs.map +1 -1
- package/dist/lib/testing/index.mjs +0 -6
- package/dist/lib/testing/index.mjs.map +1 -1
- package/dist/lib/testing/local-agent-runner.mjs +0 -6
- package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
- package/dist/lib/testing/orchestrator.mjs +0 -6
- package/dist/lib/testing/orchestrator.mjs.map +1 -1
- package/dist/lib/testing/personas/index.mjs +0 -6
- package/dist/lib/testing/personas/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
- package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
- package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
- package/dist/lib/testing/scenarios/creative.mjs +0 -6
- package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
- package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
- package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
- package/dist/lib/testing/scenarios/discovery.mjs +0 -6
- package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
- package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
- package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/governance.mjs +0 -6
- package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/health.mjs +0 -6
- package/dist/lib/testing/scenarios/health.mjs.map +1 -1
- package/dist/lib/testing/scenarios/index.mjs +0 -6
- package/dist/lib/testing/scenarios/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
- package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/signals.mjs +0 -6
- package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
- package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
- package/dist/lib/testing/seed-merge.mjs +0 -6
- package/dist/lib/testing/seed-merge.mjs.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
- package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
- package/dist/lib/testing/storyboard/assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
- package/dist/lib/testing/storyboard/compliance.mjs +5 -6
- package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
- package/dist/lib/testing/storyboard/context.mjs +0 -6
- package/dist/lib/testing/storyboard/context.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs +0 -6
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/junit.mjs +0 -6
- package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +0 -6
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/path.mjs +0 -6
- package/dist/lib/testing/storyboard/path.mjs.map +1 -1
- package/dist/lib/testing/storyboard/probes.mjs +0 -6
- package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +0 -6
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
- package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
- package/dist/lib/testing/storyboard/seeding.mjs +0 -6
- package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +0 -6
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs +0 -6
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +0 -6
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
- package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
- package/dist/lib/testing/stubs/index.mjs +0 -6
- package/dist/lib/testing/stubs/index.mjs.map +1 -1
- package/dist/lib/testing/test-controller.mjs +0 -6
- package/dist/lib/testing/test-controller.mjs.map +1 -1
- package/dist/lib/testing/test-helpers.mjs +0 -6
- package/dist/lib/testing/test-helpers.mjs.map +1 -1
- package/dist/lib/testing/types.mjs +0 -6
- package/dist/lib/types/adcp.mjs +0 -6
- package/dist/lib/types/adcp.mjs.map +1 -1
- package/dist/lib/types/asset-instances.mjs +0 -6
- package/dist/lib/types/compat.mjs +0 -6
- package/dist/lib/types/compat.mjs.map +1 -1
- package/dist/lib/types/core.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs.map +1 -1
- package/dist/lib/types/error-codes.mjs +0 -6
- package/dist/lib/types/error-codes.mjs.map +1 -1
- package/dist/lib/types/error-details.aliases.mjs +0 -6
- package/dist/lib/types/error-details.aliases.mjs.map +1 -1
- package/dist/lib/types/format-asset-slots.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
- package/dist/lib/types/index.mjs +0 -6
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/inline-enums.aliases.mjs +0 -6
- package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
- package/dist/lib/types/inline-enums.generated.mjs +0 -6
- package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
- package/dist/lib/types/manifest.generated.mjs +0 -6
- package/dist/lib/types/manifest.generated.mjs.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +0 -6
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.mjs +0 -6
- package/dist/lib/types/server-payload.mjs +0 -6
- package/dist/lib/types/sync-rows.mjs +0 -6
- package/dist/lib/types/tools.generated.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs.map +1 -1
- package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
- package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
- package/dist/lib/upstream-recorder/constants.mjs +0 -6
- package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
- package/dist/lib/upstream-recorder/index.mjs +0 -6
- package/dist/lib/upstream-recorder/index.mjs.map +1 -1
- package/dist/lib/upstream-recorder/recorder.mjs +0 -6
- package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
- package/dist/lib/upstream-recorder/types.mjs +0 -6
- package/dist/lib/upstream-recorder/types.mjs.map +1 -1
- package/dist/lib/utils/a2a-artifacts.mjs +0 -6
- package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
- package/dist/lib/utils/a2a-discovery.mjs +0 -6
- package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
- package/dist/lib/utils/activation-key-builders.mjs +0 -6
- package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
- package/dist/lib/utils/adcp-version-config.mjs +0 -6
- package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
- package/dist/lib/utils/asset-builders.mjs +0 -6
- package/dist/lib/utils/asset-builders.mjs.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
- package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
- package/dist/lib/utils/capabilities.mjs +0 -6
- package/dist/lib/utils/capabilities.mjs.map +1 -1
- package/dist/lib/utils/capability-rollups.mjs +0 -6
- package/dist/lib/utils/capability-rollups.mjs.map +1 -1
- package/dist/lib/utils/creative-adapter.mjs +0 -6
- package/dist/lib/utils/creative-adapter.mjs.map +1 -1
- package/dist/lib/utils/creative-delivery.mjs +0 -6
- package/dist/lib/utils/creative-delivery.mjs.map +1 -1
- package/dist/lib/utils/deprecation.mjs +0 -6
- package/dist/lib/utils/deprecation.mjs.map +1 -1
- package/dist/lib/utils/envelope-status-compat.mjs +0 -6
- package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
- package/dist/lib/utils/error-extraction.mjs +0 -6
- package/dist/lib/utils/error-extraction.mjs.map +1 -1
- package/dist/lib/utils/extract-result.mjs +0 -6
- package/dist/lib/utils/extract-result.mjs.map +1 -1
- package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
- package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
- package/dist/lib/utils/format-assets.mjs +0 -6
- package/dist/lib/utils/format-assets.mjs.map +1 -1
- package/dist/lib/utils/format-render-builders.mjs +0 -6
- package/dist/lib/utils/format-render-builders.mjs.map +1 -1
- package/dist/lib/utils/format-renders.mjs +0 -6
- package/dist/lib/utils/format-renders.mjs.map +1 -1
- package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
- package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
- package/dist/lib/utils/glob.mjs +0 -6
- package/dist/lib/utils/glob.mjs.map +1 -1
- package/dist/lib/utils/global-async-local-storage.mjs +0 -6
- package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
- package/dist/lib/utils/idempotency.mjs +0 -6
- package/dist/lib/utils/idempotency.mjs.map +1 -1
- package/dist/lib/utils/index.mjs +0 -6
- package/dist/lib/utils/index.mjs.map +1 -1
- package/dist/lib/utils/jcs.mjs +0 -6
- package/dist/lib/utils/jcs.mjs.map +1 -1
- package/dist/lib/utils/json-depth.mjs +0 -6
- package/dist/lib/utils/json-depth.mjs.map +1 -1
- package/dist/lib/utils/logger.mjs +0 -6
- package/dist/lib/utils/logger.mjs.map +1 -1
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
- package/dist/lib/utils/media-buy-status.mjs +0 -6
- package/dist/lib/utils/media-buy-status.mjs.map +1 -1
- package/dist/lib/utils/pagination.mjs +0 -6
- package/dist/lib/utils/pagination.mjs.map +1 -1
- package/dist/lib/utils/preview-creative-builders.mjs +0 -6
- package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
- package/dist/lib/utils/preview-normalizer.mjs +0 -6
- package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
- package/dist/lib/utils/preview-utils.mjs +0 -6
- package/dist/lib/utils/preview-utils.mjs.map +1 -1
- package/dist/lib/utils/pricing-adapter.mjs +0 -6
- package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
- package/dist/lib/utils/probe-policy.mjs +0 -6
- package/dist/lib/utils/probe-policy.mjs.map +1 -1
- package/dist/lib/utils/protocol-detection.mjs +0 -6
- package/dist/lib/utils/protocol-detection.mjs.map +1 -1
- package/dist/lib/utils/redact-secrets.mjs +0 -6
- package/dist/lib/utils/redact-secrets.mjs.map +1 -1
- package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
- package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
- package/dist/lib/utils/render-builders.mjs +0 -6
- package/dist/lib/utils/render-builders.mjs.map +1 -1
- package/dist/lib/utils/request-normalizer.mjs +0 -6
- package/dist/lib/utils/request-normalizer.mjs.map +1 -1
- package/dist/lib/utils/response-schemas.mjs +0 -6
- package/dist/lib/utils/response-schemas.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +0 -6
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/utils/retry.mjs +0 -6
- package/dist/lib/utils/retry.mjs.map +1 -1
- package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
- package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
- package/dist/lib/utils/signal-id-builders.mjs +0 -6
- package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
- package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
- package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
- package/dist/lib/utils/task-state.mjs +0 -6
- package/dist/lib/utils/task-state.mjs.map +1 -1
- package/dist/lib/utils/tool-request-schemas.mjs +0 -6
- package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
- package/dist/lib/utils/typeGuards.mjs +0 -6
- package/dist/lib/utils/typeGuards.mjs.map +1 -1
- package/dist/lib/utils/union-errors.mjs +0 -6
- package/dist/lib/utils/union-errors.mjs.map +1 -1
- package/dist/lib/utils/validate-user-agent.mjs +0 -6
- package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
- package/dist/lib/v2/format-schema/fetch.mjs +0 -6
- package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
- package/dist/lib/v2/format-schema/index.mjs +0 -6
- package/dist/lib/v2/format-schema/index.mjs.map +1 -1
- package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
- package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
- package/dist/lib/v2/format-schema/resolver.mjs +7 -8
- package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
- package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
- package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
- package/dist/lib/v2/projection/augment-response.mjs +0 -6
- package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
- package/dist/lib/v2/projection/builders.mjs +0 -6
- package/dist/lib/v2/projection/builders.mjs.map +1 -1
- package/dist/lib/v2/projection/cache-versions.mjs +0 -6
- package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
- package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
- package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
- package/dist/lib/v2/projection/catalog.mjs +5 -6
- package/dist/lib/v2/projection/catalog.mjs.map +1 -1
- package/dist/lib/v2/projection/constants.mjs +0 -6
- package/dist/lib/v2/projection/constants.mjs.map +1 -1
- package/dist/lib/v2/projection/index.mjs +0 -6
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/registry.mjs +5 -6
- package/dist/lib/v2/projection/registry.mjs.map +1 -1
- package/dist/lib/v2/projection/types.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
- package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
- package/dist/lib/v2/projection/write-side.mjs +0 -6
- package/dist/lib/v2/projection/write-side.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
- package/dist/lib/validation/client-hooks.mjs +0 -6
- package/dist/lib/validation/client-hooks.mjs.map +1 -1
- package/dist/lib/validation/hints.mjs +0 -6
- package/dist/lib/validation/hints.mjs.map +1 -1
- package/dist/lib/validation/index.mjs +0 -6
- package/dist/lib/validation/index.mjs.map +1 -1
- package/dist/lib/validation/schema-errors.mjs +0 -6
- package/dist/lib/validation/schema-errors.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +5 -6
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/validation/schema-validator.mjs +0 -6
- package/dist/lib/validation/schema-validator.mjs.map +1 -1
- package/dist/lib/validation/sync-creatives.mjs +0 -6
- package/dist/lib/validation/sync-creatives.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -9
- package/dist/lib/version.mjs.map +1 -1
- package/dist/lib/webhooks/index.mjs +0 -6
- package/dist/lib/webhooks/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/core/AsyncHandler.ts"],"sourcesContent":["/**\n * Structured async handler for AdCP webhook responses\n * Provides type-safe callbacks for each AdCP tool completion\n */\n\nimport type { IdempotencyBackend } from '../server/idempotency/store';\nimport type {\n ListCreativeFormatsResponse,\n ListCreativesResponse,\n PreviewCreativeResponse,\n BuildCreativeResponse,\n GetMediaBuysResponse,\n GetMediaBuyDeliveryResponse,\n ProvidePerformanceFeedbackResponse,\n GetSignalsResponse,\n ActivateSignalResponse,\n ListAccountsResponse,\n SyncAccountsResponse,\n SyncAudiencesResponse,\n CreatePropertyListResponse,\n GetPropertyListResponse,\n UpdatePropertyListResponse,\n ListPropertyListsResponse,\n DeletePropertyListResponse,\n ListContentStandardsResponse,\n GetContentStandardsResponse,\n CalibrateContentResponse,\n ValidateContentDeliveryResponse,\n SIGetOfferingResponse,\n SIInitiateSessionResponse,\n SISendMessageResponse,\n SITerminateSessionResponse,\n} from '../types/tools.generated';\n\nimport type {\n AdCPAsyncResponseData,\n CreateMediaBuyAsyncInputRequired,\n CreateMediaBuyAsyncSubmitted,\n CreateMediaBuyAsyncWorking,\n CreateMediaBuyResponse,\n GetProductsAsyncInputRequired,\n GetProductsAsyncSubmitted,\n GetProductsAsyncWorking,\n GetProductsResponse,\n SyncCreativesAsyncInputRequired,\n SyncCreativesAsyncSubmitted,\n SyncCreativesAsyncWorking,\n SyncCreativesResponse,\n TaskStatus,\n TaskType,\n UpdateMediaBuyAsyncInputRequired,\n UpdateMediaBuyAsyncSubmitted,\n UpdateMediaBuyAsyncWorking,\n UpdateMediaBuyResponse,\n} from '../types/core.generated';\nimport type { TaskResultMetadata } from './ConversationTypes';\nimport {\n CreateMediaBuyAsyncResponseData,\n GetProductsAsyncResponseData,\n SyncCreativesAsyncResponseData,\n UpdateMediaBuyAsyncResponseData,\n} from '../types';\n\n/**\n * Metadata provided with webhook responses\n */\nexport interface WebhookMetadata {\n /** Client-provided operation ID */\n operation_id: string;\n /** Server's task ID */\n task_id: string;\n /** Agent ID */\n agent_id: string;\n /** Task type/tool name */\n task_type: string;\n /** Task status (completed, failed, needs_input, working, etc) */\n status: TaskStatus;\n /** Server's context ID */\n context_id?: string;\n /** Human-readable context about the status change */\n message?: string;\n /** Timestamp */\n timestamp: string;\n /** raw HTTP payload */\n rawHTTPPayload?: any;\n /**\n * Wire protocol that delivered this webhook. Useful for handler code\n * that needs to treat MCP and A2A transports differently (e.g.,\n * `idempotency_key` is only present on MCP payloads).\n */\n protocol?: 'mcp' | 'a2a';\n /**\n * Sender-generated key stable across retries of the same webhook event\n * (MCP envelope only — A2A webhooks do not carry this field). Use this\n * as the canonical dedup key; see `AsyncHandlerConfig.webhookDedup`.\n */\n idempotency_key?: string;\n /**\n * Buyer-side product property policy evaluation for completed get_products\n * webhooks. Present when the client filters, audits, or rejects a webhook\n * result before dispatching it to handlers.\n */\n productPropertyPolicy?: TaskResultMetadata['productPropertyPolicy'];\n /**\n * Buyer-side pricing-options enforcement summary for completed get_products\n * webhooks. Present when the client drops products that arrived without a\n * usable `pricing_options[]` array before dispatching to handlers.\n */\n productPricingPolicy?: TaskResultMetadata['productPricingPolicy'];\n}\n\n/**\n * Metadata for agent-initiated notifications\n * Same as WebhookMetadata but includes notification-specific fields\n */\nexport interface NotificationMetadata extends WebhookMetadata {\n /** Notification type */\n notification_type: 'scheduled' | 'final' | 'delayed';\n /** Sequence number of this notification */\n sequence_number?: number;\n /** When next notification is expected (not present for 'final') */\n next_expected_at?: string;\n}\n\n// Simple union-typed handlers for webhook status changes\nexport type GetProductsStatusChangeHandler = (\n response: GetProductsResponse | GetProductsAsyncSubmitted | GetProductsAsyncWorking | GetProductsAsyncInputRequired,\n metadata: WebhookMetadata\n) => void | Promise<void>;\n\nexport type CreateMediaBuyStatusChangeHandler = (\n response:\n | CreateMediaBuyResponse\n | CreateMediaBuyAsyncSubmitted\n | CreateMediaBuyAsyncWorking\n | CreateMediaBuyAsyncInputRequired,\n metadata: WebhookMetadata\n) => void | Promise<void>;\n\nexport type UpdateMediaBuyStatusChangeHandler = (\n response:\n | UpdateMediaBuyResponse\n | UpdateMediaBuyAsyncSubmitted\n | UpdateMediaBuyAsyncWorking\n | UpdateMediaBuyAsyncInputRequired,\n metadata: WebhookMetadata\n) => void | Promise<void>;\n\nexport type SyncCreativesStatusChangeHandler = (\n response:\n | SyncCreativesResponse\n | SyncCreativesAsyncSubmitted\n | SyncCreativesAsyncWorking\n | SyncCreativesAsyncInputRequired,\n metadata: WebhookMetadata\n) => void | Promise<void>;\n\n/**\n * Media buy delivery notification payload (PR #81)\n * Agent-initiated periodic reporting, not tied to any client operation\n */\nexport interface MediaBuyDeliveryNotification {\n /** Type of notification */\n notification_type: 'scheduled' | 'final' | 'delayed';\n /** Sequential notification number (starts at 1) */\n sequence_number?: number;\n /** When next notification is expected (omitted for 'final') */\n next_expected_at?: string;\n /** Reporting period for this notification */\n reporting_period?: {\n start: string;\n end: string;\n };\n /** Currency used for financial metrics */\n currency?: string;\n /** Array of media buy deliveries being reported */\n media_buy_deliveries?: Array<{\n media_buy_id: string;\n impressions?: number;\n clicks?: number;\n spend?: number;\n conversions?: number;\n [key: string]: any;\n }>;\n}\n\n/**\n * Activity event for logging/observability\n */\nexport interface Activity {\n type:\n | 'protocol_request'\n | 'protocol_response'\n | 'status_change'\n | 'webhook_received'\n | 'webhook_duplicate'\n | 'governance_check'\n | 'governance_outcome';\n operation_id: string;\n agent_id: string;\n context_id?: string;\n task_id?: string;\n task_type: string;\n status?: string;\n /**\n * Full AdCP response payload. Populated on `webhook_received` and\n * protocol/status events. INTENTIONALLY omitted on `webhook_duplicate`\n * to avoid re-logging potentially-sensitive data on every retry — the\n * originating `webhook_received` event already carries it. Correlate\n * the two via `idempotency_key`.\n */\n payload?: any;\n /**\n * Webhook idempotency key when available. Present on `webhook_received`\n * and `webhook_duplicate` events from MCP envelopes, enabling\n * correlation between a first delivery and its retry echoes.\n */\n idempotency_key?: string;\n timestamp: string;\n}\n\n/**\n * Configuration for async handler with typed callbacks\n */\nexport interface AsyncHandlerConfig {\n // AdCP tool status change handlers - called for ALL status changes (completed, failed, working, input-required, submitted)\n onGetProductsStatusChange?: GetProductsStatusChangeHandler;\n onListCreativeFormatsStatusChange?: (\n data: ListCreativeFormatsResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onCreateMediaBuyStatusChange?: CreateMediaBuyStatusChangeHandler;\n onUpdateMediaBuyStatusChange?: UpdateMediaBuyStatusChangeHandler;\n onSyncCreativesStatusChange?: SyncCreativesStatusChangeHandler;\n onListCreativesStatusChange?: (response: ListCreativesResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onPreviewCreativeStatusChange?: (\n response: PreviewCreativeResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onGetMediaBuysStatusChange?: (response: GetMediaBuysResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onGetMediaBuyDeliveryStatusChange?: (\n response: GetMediaBuyDeliveryResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onProvidePerformanceFeedbackStatusChange?: (\n response: ProvidePerformanceFeedbackResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onGetSignalsStatusChange?: (response: GetSignalsResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onActivateSignalStatusChange?: (response: ActivateSignalResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onBuildCreativeStatusChange?: (response: BuildCreativeResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onListAccountsStatusChange?: (response: ListAccountsResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onSyncAccountsStatusChange?: (response: SyncAccountsResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onSyncAudiencesStatusChange?: (response: SyncAudiencesResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onCreatePropertyListStatusChange?: (\n response: CreatePropertyListResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onGetPropertyListStatusChange?: (\n response: GetPropertyListResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onUpdatePropertyListStatusChange?: (\n response: UpdatePropertyListResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onListPropertyListsStatusChange?: (\n response: ListPropertyListsResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onDeletePropertyListStatusChange?: (\n response: DeletePropertyListResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onListContentStandardsStatusChange?: (\n response: ListContentStandardsResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onGetContentStandardsStatusChange?: (\n response: GetContentStandardsResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onCalibrateContentStatusChange?: (\n response: CalibrateContentResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onValidateContentDeliveryStatusChange?: (\n response: ValidateContentDeliveryResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onSIGetOfferingStatusChange?: (response: SIGetOfferingResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onSIInitiateSessionStatusChange?: (\n response: SIInitiateSessionResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onSISendMessageStatusChange?: (response: SISendMessageResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onSITerminateSessionStatusChange?: (\n response: SITerminateSessionResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n\n // Fallback handler for any task status change\n onTaskStatusChange?: (response: any, metadata: WebhookMetadata) => void | Promise<void>;\n\n // Activity logging (low-level protocol events)\n onActivity?: (activity: Activity) => void | Promise<void>;\n\n /**\n * Receiver-side deduplication of webhook payloads by `idempotency_key`.\n *\n * AdCP webhooks use at-least-once delivery — publishers retry until they\n * see a 2xx, so the same event may arrive more than once. When configured,\n * the first delivery for a given `(agent_id, idempotency_key)` tuple\n * dispatches to handlers; subsequent deliveries are dropped and surface\n * as a `webhook_duplicate` activity.\n *\n * Reuses `IdempotencyBackend` from `@adcp/sdk/server` — you can share\n * the same backend across request-side and webhook-side dedup, or use a\n * dedicated one. Scope is per-agent so keys from different senders are\n * independent, matching the spec's \"scoped to authenticated sender\n * identity\" rule.\n *\n * If a payload arrives without `idempotency_key` (non-conforming sender,\n * or A2A transport which does not carry the field), dispatch proceeds\n * without dedup and a warning is logged.\n */\n webhookDedup?: {\n backend: IdempotencyBackend;\n /** Retention for dedup keys. Defaults to 86_400 (24h). */\n ttlSeconds?: number;\n };\n\n // Notification handlers (agent-initiated, no operation_id)\n onMediaBuyDeliveryNotification?: (\n notification: MediaBuyDeliveryNotification,\n metadata: NotificationMetadata\n ) => void | Promise<void>;\n}\n\n/**\n * Async handler class\n */\nexport class AsyncHandler {\n constructor(private config: AsyncHandlerConfig) {}\n\n /**\n * Handle incoming webhook payload (both task completions and notifications)\n */\n async handleWebhook({\n result,\n metadata,\n }: {\n result: AdCPAsyncResponseData | undefined;\n metadata: WebhookMetadata;\n }): Promise<void> {\n if (await this.isDuplicate(metadata)) {\n await this.emitActivity({\n type: 'webhook_duplicate',\n operation_id: metadata.operation_id,\n agent_id: metadata.agent_id,\n context_id: metadata.context_id,\n task_id: metadata.task_id,\n task_type: metadata.task_type,\n status: metadata.status,\n idempotency_key: metadata.idempotency_key,\n timestamp: metadata.timestamp,\n });\n return;\n }\n\n // Emit activity\n await this.emitActivity({\n type: 'webhook_received',\n idempotency_key: metadata.idempotency_key,\n operation_id: metadata.operation_id,\n agent_id: metadata.agent_id,\n context_id: metadata.context_id,\n task_id: metadata.task_id,\n task_type: metadata.task_type,\n status: metadata.status,\n payload: metadata.rawHTTPPayload?.result ?? result,\n timestamp: metadata.timestamp,\n });\n\n // Check if this is a notification (media_buy_delivery with notification_type)\n // Notifications are treated like status updates for an ongoing \"get delivery report\" operation\n // The operation_id (from URL) groups all reports for the same agent + month\n if (\n metadata.task_type === 'media_buy_delivery' &&\n result &&\n typeof result === 'object' &&\n 'notification_type' in result\n ) {\n const notificationPayload = result as unknown as MediaBuyDeliveryNotification;\n\n // Build notification metadata\n // operation_id comes from webhook URL and was lazily generated from agent + month\n const notificationMetadata: NotificationMetadata = {\n ...metadata,\n notification_type: notificationPayload.notification_type,\n sequence_number: notificationPayload.sequence_number,\n next_expected_at: notificationPayload.next_expected_at,\n };\n\n await this.config.onMediaBuyDeliveryNotification?.(notificationPayload, notificationMetadata);\n return;\n }\n\n // All status changes go through the specific handler\n // The handler receives metadata with status and can act accordingly\n await this.handleCompletion(metadata.task_type, result, metadata);\n }\n\n /**\n * Handle task completion - route to specific handler\n */\n private async handleCompletion(\n taskType: string,\n result: AdCPAsyncResponseData | undefined,\n metadata: WebhookMetadata\n ): Promise<void> {\n let handler: ((result: any, metadata: any) => void | Promise<void>) | undefined;\n\n // Route to specific handler based on task type\n switch (taskType) {\n case 'get_products':\n handler = this.config.onGetProductsStatusChange;\n break;\n\n case 'list_creative_formats':\n handler = this.config.onListCreativeFormatsStatusChange;\n break;\n\n case 'create_media_buy':\n handler = this.config.onCreateMediaBuyStatusChange;\n break;\n\n case 'update_media_buy':\n handler = this.config.onUpdateMediaBuyStatusChange;\n break;\n\n case 'sync_creatives':\n handler = this.config.onSyncCreativesStatusChange;\n break;\n\n case 'list_creatives':\n handler = this.config.onListCreativesStatusChange;\n break;\n\n case 'get_media_buys':\n handler = this.config.onGetMediaBuysStatusChange;\n break;\n\n case 'get_media_buy_delivery':\n handler = this.config.onGetMediaBuyDeliveryStatusChange;\n break;\n\n case 'provide_performance_feedback':\n handler = this.config.onProvidePerformanceFeedbackStatusChange;\n break;\n\n case 'get_signals':\n handler = this.config.onGetSignalsStatusChange;\n break;\n\n case 'activate_signal':\n handler = this.config.onActivateSignalStatusChange;\n break;\n }\n\n // Call specific handler if configured, otherwise fallback to generic handler\n const handlerToCall = handler || this.config.onTaskStatusChange;\n\n if (handlerToCall) {\n try {\n await handlerToCall(result, metadata);\n } catch (error) {\n // Log error but don't crash webhook processing\n console.error(\n `Error in handler for task ${taskType}:`,\n error instanceof Error ? error.message : 'unknown error'\n );\n }\n }\n }\n\n /**\n * Emit activity event\n */\n private async emitActivity(activity: Activity): Promise<void> {\n await this.config.onActivity?.(activity);\n }\n\n /**\n * Claim the webhook for processing, returning true if the event has\n * already been delivered for this `(agent_id, idempotency_key)` tuple.\n *\n * Uses `IdempotencyBackend.putIfAbsent` so concurrent retries race on a\n * single claim: exactly one caller gets `true` and proceeds, the rest\n * observe the existing entry and return.\n */\n private async isDuplicate(metadata: WebhookMetadata): Promise<boolean> {\n const dedup = this.config.webhookDedup;\n if (!dedup) return false;\n\n const key = metadata.idempotency_key;\n if (!key || !IDEMPOTENCY_KEY_PATTERN.test(key)) {\n // No valid key. MCP senders MUST emit one per AdCP 3.0; A2A\n // transport doesn't carry the field at all. Warn MCP (so\n // integrators notice non-conforming publishers) and stay quiet\n // for A2A (expected and unactionable).\n if (metadata.protocol !== 'a2a') {\n console.warn(\n `[AdCP] webhookDedup enabled but webhook from agent=${metadata.agent_id} task=${metadata.task_id} has ${\n key ? 'an invalid' : 'no'\n } idempotency_key. Expected format: ${IDEMPOTENCY_KEY_PATTERN.source}. ` +\n 'Dispatching without dedup — duplicate deliveries from this sender will re-trigger handlers. ' +\n 'See docs/guides/PUSH-NOTIFICATION-CONFIG.md#deduplication'\n );\n }\n return false;\n }\n\n const ttlSeconds = dedup.ttlSeconds ?? 86_400;\n // Reserved prefix `adcp\\u001fwebhook\\u001fv1\\u001f...` namespaces the\n // claim so webhook dedup entries can coexist with request-side\n // idempotency entries in a shared backend — a request-side principal\n // can never produce a scoped key with this prefix because the\n // principal regex excludes U+001F.\n const scopedKey = `adcp\\u001fwebhook\\u001fv1\\u001f${metadata.agent_id}\\u001f${key}`;\n const expiresAt = Math.floor(Date.now() / 1000) + ttlSeconds;\n\n const claimed = await dedup.backend.putIfAbsent(scopedKey, {\n payloadHash: '',\n response: null,\n expiresAt,\n });\n return !claimed;\n }\n}\n\n// AdCP spec: `^[A-Za-z0-9_.:-]{16,255}$`. Any key not matching this\n// pattern is malformed — treat as missing rather than forming a scoped\n// key from arbitrary sender-supplied bytes.\nconst IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9_.:-]{16,255}$/;\n\n/**\n * Factory function to create async handler\n */\nexport function createAsyncHandler(config: AsyncHandlerConfig): AsyncHandler {\n return new AsyncHandler(config);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/core/AsyncHandler.ts"],"sourcesContent":["/**\n * Structured async handler for AdCP webhook responses\n * Provides type-safe callbacks for each AdCP tool completion\n */\n\nimport type { IdempotencyBackend } from '../server/idempotency/store';\nimport type {\n ListCreativeFormatsResponse,\n ListCreativesResponse,\n PreviewCreativeResponse,\n BuildCreativeResponse,\n GetMediaBuysResponse,\n GetMediaBuyDeliveryResponse,\n ProvidePerformanceFeedbackResponse,\n GetSignalsResponse,\n ActivateSignalResponse,\n ListAccountsResponse,\n SyncAccountsResponse,\n SyncAudiencesResponse,\n CreatePropertyListResponse,\n GetPropertyListResponse,\n UpdatePropertyListResponse,\n ListPropertyListsResponse,\n DeletePropertyListResponse,\n ListContentStandardsResponse,\n GetContentStandardsResponse,\n CalibrateContentResponse,\n ValidateContentDeliveryResponse,\n SIGetOfferingResponse,\n SIInitiateSessionResponse,\n SISendMessageResponse,\n SITerminateSessionResponse,\n} from '../types/tools.generated';\n\nimport type {\n AdCPAsyncResponseData,\n CreateMediaBuyAsyncInputRequired,\n CreateMediaBuyAsyncSubmitted,\n CreateMediaBuyAsyncWorking,\n CreateMediaBuyResponse,\n GetProductsAsyncInputRequired,\n GetProductsAsyncSubmitted,\n GetProductsAsyncWorking,\n GetProductsResponse,\n SyncCreativesAsyncInputRequired,\n SyncCreativesAsyncSubmitted,\n SyncCreativesAsyncWorking,\n SyncCreativesResponse,\n TaskStatus,\n TaskType,\n UpdateMediaBuyAsyncInputRequired,\n UpdateMediaBuyAsyncSubmitted,\n UpdateMediaBuyAsyncWorking,\n UpdateMediaBuyResponse,\n} from '../types/core.generated';\nimport type { TaskResultMetadata } from './ConversationTypes';\nimport {\n CreateMediaBuyAsyncResponseData,\n GetProductsAsyncResponseData,\n SyncCreativesAsyncResponseData,\n UpdateMediaBuyAsyncResponseData,\n} from '../types';\n\n/**\n * Metadata provided with webhook responses\n */\nexport interface WebhookMetadata {\n /** Client-provided operation ID */\n operation_id: string;\n /** Server's task ID */\n task_id: string;\n /** Agent ID */\n agent_id: string;\n /** Task type/tool name */\n task_type: string;\n /** Task status (completed, failed, needs_input, working, etc) */\n status: TaskStatus;\n /** Server's context ID */\n context_id?: string;\n /** Human-readable context about the status change */\n message?: string;\n /** Timestamp */\n timestamp: string;\n /** raw HTTP payload */\n rawHTTPPayload?: any;\n /**\n * Wire protocol that delivered this webhook. Useful for handler code\n * that needs to treat MCP and A2A transports differently (e.g.,\n * `idempotency_key` is only present on MCP payloads).\n */\n protocol?: 'mcp' | 'a2a';\n /**\n * Sender-generated key stable across retries of the same webhook event\n * (MCP envelope only — A2A webhooks do not carry this field). Use this\n * as the canonical dedup key; see `AsyncHandlerConfig.webhookDedup`.\n */\n idempotency_key?: string;\n /**\n * Buyer-side product property policy evaluation for completed get_products\n * webhooks. Present when the client filters, audits, or rejects a webhook\n * result before dispatching it to handlers.\n */\n productPropertyPolicy?: TaskResultMetadata['productPropertyPolicy'];\n /**\n * Buyer-side pricing-options enforcement summary for completed get_products\n * webhooks. Present when the client drops products that arrived without a\n * usable `pricing_options[]` array before dispatching to handlers.\n */\n productPricingPolicy?: TaskResultMetadata['productPricingPolicy'];\n}\n\n/**\n * Metadata for agent-initiated notifications\n * Same as WebhookMetadata but includes notification-specific fields\n */\nexport interface NotificationMetadata extends WebhookMetadata {\n /** Notification type */\n notification_type: 'scheduled' | 'final' | 'delayed';\n /** Sequence number of this notification */\n sequence_number?: number;\n /** When next notification is expected (not present for 'final') */\n next_expected_at?: string;\n}\n\n// Simple union-typed handlers for webhook status changes\nexport type GetProductsStatusChangeHandler = (\n response: GetProductsResponse | GetProductsAsyncSubmitted | GetProductsAsyncWorking | GetProductsAsyncInputRequired,\n metadata: WebhookMetadata\n) => void | Promise<void>;\n\nexport type CreateMediaBuyStatusChangeHandler = (\n response:\n | CreateMediaBuyResponse\n | CreateMediaBuyAsyncSubmitted\n | CreateMediaBuyAsyncWorking\n | CreateMediaBuyAsyncInputRequired,\n metadata: WebhookMetadata\n) => void | Promise<void>;\n\nexport type UpdateMediaBuyStatusChangeHandler = (\n response:\n | UpdateMediaBuyResponse\n | UpdateMediaBuyAsyncSubmitted\n | UpdateMediaBuyAsyncWorking\n | UpdateMediaBuyAsyncInputRequired,\n metadata: WebhookMetadata\n) => void | Promise<void>;\n\nexport type SyncCreativesStatusChangeHandler = (\n response:\n | SyncCreativesResponse\n | SyncCreativesAsyncSubmitted\n | SyncCreativesAsyncWorking\n | SyncCreativesAsyncInputRequired,\n metadata: WebhookMetadata\n) => void | Promise<void>;\n\n/**\n * Media buy delivery notification payload (PR #81)\n * Agent-initiated periodic reporting, not tied to any client operation\n */\nexport interface MediaBuyDeliveryNotification {\n /** Type of notification */\n notification_type: 'scheduled' | 'final' | 'delayed';\n /** Sequential notification number (starts at 1) */\n sequence_number?: number;\n /** When next notification is expected (omitted for 'final') */\n next_expected_at?: string;\n /** Reporting period for this notification */\n reporting_period?: {\n start: string;\n end: string;\n };\n /** Currency used for financial metrics */\n currency?: string;\n /** Array of media buy deliveries being reported */\n media_buy_deliveries?: Array<{\n media_buy_id: string;\n impressions?: number;\n clicks?: number;\n spend?: number;\n conversions?: number;\n [key: string]: any;\n }>;\n}\n\n/**\n * Activity event for logging/observability\n */\nexport interface Activity {\n type:\n | 'protocol_request'\n | 'protocol_response'\n | 'status_change'\n | 'webhook_received'\n | 'webhook_duplicate'\n | 'governance_check'\n | 'governance_outcome';\n operation_id: string;\n agent_id: string;\n context_id?: string;\n task_id?: string;\n task_type: string;\n status?: string;\n /**\n * Full AdCP response payload. Populated on `webhook_received` and\n * protocol/status events. INTENTIONALLY omitted on `webhook_duplicate`\n * to avoid re-logging potentially-sensitive data on every retry — the\n * originating `webhook_received` event already carries it. Correlate\n * the two via `idempotency_key`.\n */\n payload?: any;\n /**\n * Webhook idempotency key when available. Present on `webhook_received`\n * and `webhook_duplicate` events from MCP envelopes, enabling\n * correlation between a first delivery and its retry echoes.\n */\n idempotency_key?: string;\n timestamp: string;\n}\n\n/**\n * Configuration for async handler with typed callbacks\n */\nexport interface AsyncHandlerConfig {\n // AdCP tool status change handlers - called for ALL status changes (completed, failed, working, input-required, submitted)\n onGetProductsStatusChange?: GetProductsStatusChangeHandler;\n onListCreativeFormatsStatusChange?: (\n data: ListCreativeFormatsResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onCreateMediaBuyStatusChange?: CreateMediaBuyStatusChangeHandler;\n onUpdateMediaBuyStatusChange?: UpdateMediaBuyStatusChangeHandler;\n onSyncCreativesStatusChange?: SyncCreativesStatusChangeHandler;\n onListCreativesStatusChange?: (response: ListCreativesResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onPreviewCreativeStatusChange?: (\n response: PreviewCreativeResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onGetMediaBuysStatusChange?: (response: GetMediaBuysResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onGetMediaBuyDeliveryStatusChange?: (\n response: GetMediaBuyDeliveryResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onProvidePerformanceFeedbackStatusChange?: (\n response: ProvidePerformanceFeedbackResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onGetSignalsStatusChange?: (response: GetSignalsResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onActivateSignalStatusChange?: (response: ActivateSignalResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onBuildCreativeStatusChange?: (response: BuildCreativeResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onListAccountsStatusChange?: (response: ListAccountsResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onSyncAccountsStatusChange?: (response: SyncAccountsResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onSyncAudiencesStatusChange?: (response: SyncAudiencesResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onCreatePropertyListStatusChange?: (\n response: CreatePropertyListResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onGetPropertyListStatusChange?: (\n response: GetPropertyListResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onUpdatePropertyListStatusChange?: (\n response: UpdatePropertyListResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onListPropertyListsStatusChange?: (\n response: ListPropertyListsResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onDeletePropertyListStatusChange?: (\n response: DeletePropertyListResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onListContentStandardsStatusChange?: (\n response: ListContentStandardsResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onGetContentStandardsStatusChange?: (\n response: GetContentStandardsResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onCalibrateContentStatusChange?: (\n response: CalibrateContentResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onValidateContentDeliveryStatusChange?: (\n response: ValidateContentDeliveryResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onSIGetOfferingStatusChange?: (response: SIGetOfferingResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onSIInitiateSessionStatusChange?: (\n response: SIInitiateSessionResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n onSISendMessageStatusChange?: (response: SISendMessageResponse, metadata: WebhookMetadata) => void | Promise<void>;\n onSITerminateSessionStatusChange?: (\n response: SITerminateSessionResponse,\n metadata: WebhookMetadata\n ) => void | Promise<void>;\n\n // Fallback handler for any task status change\n onTaskStatusChange?: (response: any, metadata: WebhookMetadata) => void | Promise<void>;\n\n // Activity logging (low-level protocol events)\n onActivity?: (activity: Activity) => void | Promise<void>;\n\n /**\n * Receiver-side deduplication of webhook payloads by `idempotency_key`.\n *\n * AdCP webhooks use at-least-once delivery — publishers retry until they\n * see a 2xx, so the same event may arrive more than once. When configured,\n * the first delivery for a given `(agent_id, idempotency_key)` tuple\n * dispatches to handlers; subsequent deliveries are dropped and surface\n * as a `webhook_duplicate` activity.\n *\n * Reuses `IdempotencyBackend` from `@adcp/sdk/server` — you can share\n * the same backend across request-side and webhook-side dedup, or use a\n * dedicated one. Scope is per-agent so keys from different senders are\n * independent, matching the spec's \"scoped to authenticated sender\n * identity\" rule.\n *\n * If a payload arrives without `idempotency_key` (non-conforming sender,\n * or A2A transport which does not carry the field), dispatch proceeds\n * without dedup and a warning is logged.\n */\n webhookDedup?: {\n backend: IdempotencyBackend;\n /** Retention for dedup keys. Defaults to 86_400 (24h). */\n ttlSeconds?: number;\n };\n\n // Notification handlers (agent-initiated, no operation_id)\n onMediaBuyDeliveryNotification?: (\n notification: MediaBuyDeliveryNotification,\n metadata: NotificationMetadata\n ) => void | Promise<void>;\n}\n\n/**\n * Async handler class\n */\nexport class AsyncHandler {\n constructor(private config: AsyncHandlerConfig) {}\n\n /**\n * Handle incoming webhook payload (both task completions and notifications)\n */\n async handleWebhook({\n result,\n metadata,\n }: {\n result: AdCPAsyncResponseData | undefined;\n metadata: WebhookMetadata;\n }): Promise<void> {\n if (await this.isDuplicate(metadata)) {\n await this.emitActivity({\n type: 'webhook_duplicate',\n operation_id: metadata.operation_id,\n agent_id: metadata.agent_id,\n context_id: metadata.context_id,\n task_id: metadata.task_id,\n task_type: metadata.task_type,\n status: metadata.status,\n idempotency_key: metadata.idempotency_key,\n timestamp: metadata.timestamp,\n });\n return;\n }\n\n // Emit activity\n await this.emitActivity({\n type: 'webhook_received',\n idempotency_key: metadata.idempotency_key,\n operation_id: metadata.operation_id,\n agent_id: metadata.agent_id,\n context_id: metadata.context_id,\n task_id: metadata.task_id,\n task_type: metadata.task_type,\n status: metadata.status,\n payload: metadata.rawHTTPPayload?.result ?? result,\n timestamp: metadata.timestamp,\n });\n\n // Check if this is a notification (media_buy_delivery with notification_type)\n // Notifications are treated like status updates for an ongoing \"get delivery report\" operation\n // The operation_id (from URL) groups all reports for the same agent + month\n if (\n metadata.task_type === 'media_buy_delivery' &&\n result &&\n typeof result === 'object' &&\n 'notification_type' in result\n ) {\n const notificationPayload = result as unknown as MediaBuyDeliveryNotification;\n\n // Build notification metadata\n // operation_id comes from webhook URL and was lazily generated from agent + month\n const notificationMetadata: NotificationMetadata = {\n ...metadata,\n notification_type: notificationPayload.notification_type,\n sequence_number: notificationPayload.sequence_number,\n next_expected_at: notificationPayload.next_expected_at,\n };\n\n await this.config.onMediaBuyDeliveryNotification?.(notificationPayload, notificationMetadata);\n return;\n }\n\n // All status changes go through the specific handler\n // The handler receives metadata with status and can act accordingly\n await this.handleCompletion(metadata.task_type, result, metadata);\n }\n\n /**\n * Handle task completion - route to specific handler\n */\n private async handleCompletion(\n taskType: string,\n result: AdCPAsyncResponseData | undefined,\n metadata: WebhookMetadata\n ): Promise<void> {\n let handler: ((result: any, metadata: any) => void | Promise<void>) | undefined;\n\n // Route to specific handler based on task type\n switch (taskType) {\n case 'get_products':\n handler = this.config.onGetProductsStatusChange;\n break;\n\n case 'list_creative_formats':\n handler = this.config.onListCreativeFormatsStatusChange;\n break;\n\n case 'create_media_buy':\n handler = this.config.onCreateMediaBuyStatusChange;\n break;\n\n case 'update_media_buy':\n handler = this.config.onUpdateMediaBuyStatusChange;\n break;\n\n case 'sync_creatives':\n handler = this.config.onSyncCreativesStatusChange;\n break;\n\n case 'list_creatives':\n handler = this.config.onListCreativesStatusChange;\n break;\n\n case 'get_media_buys':\n handler = this.config.onGetMediaBuysStatusChange;\n break;\n\n case 'get_media_buy_delivery':\n handler = this.config.onGetMediaBuyDeliveryStatusChange;\n break;\n\n case 'provide_performance_feedback':\n handler = this.config.onProvidePerformanceFeedbackStatusChange;\n break;\n\n case 'get_signals':\n handler = this.config.onGetSignalsStatusChange;\n break;\n\n case 'activate_signal':\n handler = this.config.onActivateSignalStatusChange;\n break;\n }\n\n // Call specific handler if configured, otherwise fallback to generic handler\n const handlerToCall = handler || this.config.onTaskStatusChange;\n\n if (handlerToCall) {\n try {\n await handlerToCall(result, metadata);\n } catch (error) {\n // Log error but don't crash webhook processing\n console.error(\n `Error in handler for task ${taskType}:`,\n error instanceof Error ? error.message : 'unknown error'\n );\n }\n }\n }\n\n /**\n * Emit activity event\n */\n private async emitActivity(activity: Activity): Promise<void> {\n await this.config.onActivity?.(activity);\n }\n\n /**\n * Claim the webhook for processing, returning true if the event has\n * already been delivered for this `(agent_id, idempotency_key)` tuple.\n *\n * Uses `IdempotencyBackend.putIfAbsent` so concurrent retries race on a\n * single claim: exactly one caller gets `true` and proceeds, the rest\n * observe the existing entry and return.\n */\n private async isDuplicate(metadata: WebhookMetadata): Promise<boolean> {\n const dedup = this.config.webhookDedup;\n if (!dedup) return false;\n\n const key = metadata.idempotency_key;\n if (!key || !IDEMPOTENCY_KEY_PATTERN.test(key)) {\n // No valid key. MCP senders MUST emit one per AdCP 3.0; A2A\n // transport doesn't carry the field at all. Warn MCP (so\n // integrators notice non-conforming publishers) and stay quiet\n // for A2A (expected and unactionable).\n if (metadata.protocol !== 'a2a') {\n console.warn(\n `[AdCP] webhookDedup enabled but webhook from agent=${metadata.agent_id} task=${metadata.task_id} has ${\n key ? 'an invalid' : 'no'\n } idempotency_key. Expected format: ${IDEMPOTENCY_KEY_PATTERN.source}. ` +\n 'Dispatching without dedup — duplicate deliveries from this sender will re-trigger handlers. ' +\n 'See docs/guides/PUSH-NOTIFICATION-CONFIG.md#deduplication'\n );\n }\n return false;\n }\n\n const ttlSeconds = dedup.ttlSeconds ?? 86_400;\n // Reserved prefix `adcp\\u001fwebhook\\u001fv1\\u001f...` namespaces the\n // claim so webhook dedup entries can coexist with request-side\n // idempotency entries in a shared backend — a request-side principal\n // can never produce a scoped key with this prefix because the\n // principal regex excludes U+001F.\n const scopedKey = `adcp\\u001fwebhook\\u001fv1\\u001f${metadata.agent_id}\\u001f${key}`;\n const expiresAt = Math.floor(Date.now() / 1000) + ttlSeconds;\n\n const claimed = await dedup.backend.putIfAbsent(scopedKey, {\n payloadHash: '',\n response: null,\n expiresAt,\n });\n return !claimed;\n }\n}\n\n// AdCP spec: `^[A-Za-z0-9_.:-]{16,255}$`. Any key not matching this\n// pattern is malformed — treat as missing rather than forming a scoped\n// key from arbitrary sender-supplied bytes.\nconst IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9_.:-]{16,255}$/;\n\n/**\n * Factory function to create async handler\n */\nexport function createAsyncHandler(config: AsyncHandlerConfig): AsyncHandler {\n return new AsyncHandler(config);\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 { readFileSync, existsSync } from "fs";
|
|
8
2
|
import { resolve } from "path";
|
|
9
3
|
import { ConfigurationError } from "../errors/index.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/core/ConfigurationManager.ts"],"sourcesContent":["// Enhanced configuration manager for easy ADCP client setup\n\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, join } from 'path';\nimport type { AgentConfig } from '../types';\nimport { ConfigurationError } from '../errors';\n\n/**\n * Configuration structure for ADCP agents\n */\nexport interface ADCPConfig {\n /** Array of agent configurations */\n agents: AgentConfig[];\n /** Default configuration options */\n defaults?: {\n /** Default protocol for agents */\n protocol?: 'mcp' | 'a2a';\n /** Default timeout for all operations */\n timeout?: number;\n /** Default max clarifications */\n maxClarifications?: number;\n /** Enable debug mode by default */\n debug?: boolean;\n };\n /** Environment-specific overrides */\n environments?: {\n [envName: string]: Partial<ADCPConfig>;\n };\n}\n\n/**\n * Enhanced configuration manager with multiple loading strategies\n */\nexport class ConfigurationManager {\n private static readonly CONFIG_FILES = ['adcp.config.json', 'adcp.json', '.adcp.json', 'agents.json'];\n\n private static readonly ENV_VARS = ['SALES_AGENTS_CONFIG', 'ADCP_AGENTS_CONFIG', 'ADCP_CONFIG'];\n\n /**\n * Load agent configurations using auto-discovery\n * Tries multiple sources in order:\n * 1. Environment variables\n * 2. Config files in current directory\n * 3. Config files in project root\n */\n static loadAgents(): AgentConfig[] {\n // Try environment variables first\n const envAgents = this.loadAgentsFromEnv();\n if (envAgents.length > 0) {\n return envAgents;\n }\n\n // Try config files\n const configAgents = this.loadAgentsFromConfig();\n if (configAgents.length > 0) {\n return configAgents;\n }\n\n // No configuration found\n console.warn('⚠️ No ADCP agent configuration found');\n console.log('💡 To configure agents, you can:');\n console.log(' 1. Set SALES_AGENTS_CONFIG environment variable');\n console.log(' 2. Create an adcp.config.json file');\n console.log(' 3. Pass agents directly to the constructor');\n console.log('\\n📖 See documentation for configuration examples');\n\n return [];\n }\n\n /**\n * Load agents from environment variables\n */\n static loadAgentsFromEnv(): AgentConfig[] {\n for (const envVar of this.ENV_VARS) {\n const configEnv = process.env[envVar];\n if (configEnv) {\n try {\n const config = JSON.parse(configEnv);\n const agents = this.extractAgents(config);\n\n if (agents.length > 0) {\n console.log(`📡 Loaded ${agents.length} agents from ${envVar}`);\n this.logAgents(agents);\n return agents;\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`❌ Failed to parse ${envVar}:`, errorMessage);\n throw new ConfigurationError(`Invalid JSON in ${envVar}: ${errorMessage}`, envVar);\n }\n }\n }\n\n return [];\n }\n\n /**\n * Load agents from config file\n */\n static loadAgentsFromConfig(configPath?: string): AgentConfig[] {\n const filesToTry = configPath ? [configPath] : this.CONFIG_FILES;\n\n for (const file of filesToTry) {\n const fullPath = resolve(file);\n\n if (existsSync(fullPath)) {\n try {\n const content = readFileSync(fullPath, 'utf8');\n const config = JSON.parse(content);\n const agents = this.extractAgents(config);\n\n if (agents.length > 0) {\n console.log(`📁 Loaded ${agents.length} agents from ${file}`);\n this.logAgents(agents);\n return agents;\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`❌ Failed to load config from ${file}:`, errorMessage);\n throw new ConfigurationError(`Invalid config file ${file}: ${errorMessage}`, 'configFile');\n }\n }\n }\n\n return [];\n }\n\n /**\n * Extract agents array from various config formats\n */\n private static extractAgents(config: any): AgentConfig[] {\n // Handle different config formats\n if (Array.isArray(config)) {\n return config; // Direct agent array\n }\n\n if (config.agents && Array.isArray(config.agents)) {\n return config.agents; // Standard format: { agents: [...] }\n }\n\n if (config.data?.agents && Array.isArray(config.data.agents)) {\n return config.data.agents; // Nested format: { data: { agents: [...] } }\n }\n\n return [];\n }\n\n /**\n * Log configured agents in a user-friendly way\n */\n private static logAgents(agents: AgentConfig[]): void {\n agents.forEach(agent => {\n const protocolIcon = agent.protocol === 'mcp' ? '🔗' : '⚡';\n const authIcon = agent.auth_token ? '🔐' : '🌐';\n console.log(` ${protocolIcon}${authIcon} ${agent.name} (${agent.protocol.toUpperCase()}) at ${agent.agent_uri}`);\n });\n\n const useRealAgents = process.env.USE_REAL_AGENTS === 'true';\n console.log(`🔧 Real agents mode: ${useRealAgents ? 'ENABLED' : 'DISABLED'}`);\n }\n\n /**\n * Validate agent configuration\n */\n static validateAgentConfig(agent: AgentConfig): void {\n const required = ['id', 'name', 'agent_uri', 'protocol'];\n\n for (const field of required) {\n if (!agent[field as keyof AgentConfig]) {\n throw new ConfigurationError(`Agent configuration missing required field: ${field}`, field);\n }\n }\n\n if (!['mcp', 'a2a'].includes(agent.protocol)) {\n throw new ConfigurationError(`Invalid protocol \"${agent.protocol}\". Must be \"mcp\" or \"a2a\"`, 'protocol');\n }\n\n // Basic URL validation\n try {\n new URL(agent.agent_uri);\n } catch {\n throw new ConfigurationError(`Invalid agent_uri \"${agent.agent_uri}\". Must be a valid URL`, 'agent_uri');\n }\n }\n\n /**\n * Validate multiple agent configurations\n */\n static validateAgentsConfig(agents: AgentConfig[]): void {\n if (!Array.isArray(agents)) {\n throw new ConfigurationError('Agents configuration must be an array');\n }\n\n if (agents.length === 0) {\n throw new ConfigurationError('At least one agent must be configured');\n }\n\n // Check for duplicate IDs\n const ids = agents.map(a => a.id);\n const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);\n if (duplicates.length > 0) {\n throw new ConfigurationError(`Duplicate agent IDs found: ${duplicates.join(', ')}`, 'duplicateIds');\n }\n\n // Validate each agent\n agents.forEach(agent => this.validateAgentConfig(agent));\n }\n\n /**\n * Create a sample configuration file\n */\n static createSampleConfig(): ADCPConfig {\n return {\n agents: [\n {\n id: 'premium-network',\n name: 'Premium Ad Network',\n agent_uri: 'https://premium-ads.example.com/mcp/',\n protocol: 'mcp',\n auth_token: process.env.PREMIUM_AGENT_TOKEN,\n },\n {\n id: 'budget-network',\n name: 'Budget Ad Network',\n agent_uri: 'https://budget-ads.example.com/a2a/',\n protocol: 'a2a',\n },\n ],\n defaults: {\n protocol: 'mcp',\n timeout: 30000,\n maxClarifications: 3,\n debug: false,\n },\n };\n }\n\n /**\n * Get configuration file paths that would be checked\n */\n static getConfigPaths(): string[] {\n return this.CONFIG_FILES.map(file => resolve(file));\n }\n\n /**\n * Get environment variables that would be checked\n */\n static getEnvVars(): string[] {\n return this.ENV_VARS;\n }\n\n /**\n * Generate configuration help text\n */\n static getConfigurationHelp(): string {\n return `\n🔧 ADCP Agent Configuration\n\nThe ADCP client can load agents from multiple sources:\n\n1️⃣ Environment Variables:\n Set any of: ${this.ENV_VARS.join(', ')}\n \n Example:\n export SALES_AGENTS_CONFIG='{\"agents\":[{\"id\":\"my-agent\",\"name\":\"My Agent\",\"agent_uri\":\"https://agent.example.com\",\"protocol\":\"mcp\"}]}'\n\n2️⃣ Configuration Files:\n Create any of: ${this.CONFIG_FILES.join(', ')}\n \n Example adcp.config.json:\n {\n \"agents\": [\n {\n \"id\": \"premium-agent\",\n \"name\": \"Premium Ad Network\",\n \"agent_uri\": \"https://premium.example.com\",\n \"protocol\": \"mcp\",\n \"auth_token\": \"your-token-here\"\n },\n {\n \"id\": \"dev-agent\",\n \"name\": \"Development Agent\",\n \"agent_uri\": \"https://dev.example.com\",\n \"protocol\": \"a2a\"\n }\n ]\n }\n\n3️⃣ Programmatic Configuration:\n const client = new ADCPMultiAgentClient([\n { id: 'agent', agent_uri: 'https://...', protocol: 'mcp',\n auth_token: process.env.MY_TOKEN }\n ]);\n\n📖 For more examples, see the documentation.\n`;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/core/ConfigurationManager.ts"],"sourcesContent":["// Enhanced configuration manager for easy ADCP client setup\n\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, join } from 'path';\nimport type { AgentConfig } from '../types';\nimport { ConfigurationError } from '../errors';\n\n/**\n * Configuration structure for ADCP agents\n */\nexport interface ADCPConfig {\n /** Array of agent configurations */\n agents: AgentConfig[];\n /** Default configuration options */\n defaults?: {\n /** Default protocol for agents */\n protocol?: 'mcp' | 'a2a';\n /** Default timeout for all operations */\n timeout?: number;\n /** Default max clarifications */\n maxClarifications?: number;\n /** Enable debug mode by default */\n debug?: boolean;\n };\n /** Environment-specific overrides */\n environments?: {\n [envName: string]: Partial<ADCPConfig>;\n };\n}\n\n/**\n * Enhanced configuration manager with multiple loading strategies\n */\nexport class ConfigurationManager {\n private static readonly CONFIG_FILES = ['adcp.config.json', 'adcp.json', '.adcp.json', 'agents.json'];\n\n private static readonly ENV_VARS = ['SALES_AGENTS_CONFIG', 'ADCP_AGENTS_CONFIG', 'ADCP_CONFIG'];\n\n /**\n * Load agent configurations using auto-discovery\n * Tries multiple sources in order:\n * 1. Environment variables\n * 2. Config files in current directory\n * 3. Config files in project root\n */\n static loadAgents(): AgentConfig[] {\n // Try environment variables first\n const envAgents = this.loadAgentsFromEnv();\n if (envAgents.length > 0) {\n return envAgents;\n }\n\n // Try config files\n const configAgents = this.loadAgentsFromConfig();\n if (configAgents.length > 0) {\n return configAgents;\n }\n\n // No configuration found\n console.warn('⚠️ No ADCP agent configuration found');\n console.log('💡 To configure agents, you can:');\n console.log(' 1. Set SALES_AGENTS_CONFIG environment variable');\n console.log(' 2. Create an adcp.config.json file');\n console.log(' 3. Pass agents directly to the constructor');\n console.log('\\n📖 See documentation for configuration examples');\n\n return [];\n }\n\n /**\n * Load agents from environment variables\n */\n static loadAgentsFromEnv(): AgentConfig[] {\n for (const envVar of this.ENV_VARS) {\n const configEnv = process.env[envVar];\n if (configEnv) {\n try {\n const config = JSON.parse(configEnv);\n const agents = this.extractAgents(config);\n\n if (agents.length > 0) {\n console.log(`📡 Loaded ${agents.length} agents from ${envVar}`);\n this.logAgents(agents);\n return agents;\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`❌ Failed to parse ${envVar}:`, errorMessage);\n throw new ConfigurationError(`Invalid JSON in ${envVar}: ${errorMessage}`, envVar);\n }\n }\n }\n\n return [];\n }\n\n /**\n * Load agents from config file\n */\n static loadAgentsFromConfig(configPath?: string): AgentConfig[] {\n const filesToTry = configPath ? [configPath] : this.CONFIG_FILES;\n\n for (const file of filesToTry) {\n const fullPath = resolve(file);\n\n if (existsSync(fullPath)) {\n try {\n const content = readFileSync(fullPath, 'utf8');\n const config = JSON.parse(content);\n const agents = this.extractAgents(config);\n\n if (agents.length > 0) {\n console.log(`📁 Loaded ${agents.length} agents from ${file}`);\n this.logAgents(agents);\n return agents;\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`❌ Failed to load config from ${file}:`, errorMessage);\n throw new ConfigurationError(`Invalid config file ${file}: ${errorMessage}`, 'configFile');\n }\n }\n }\n\n return [];\n }\n\n /**\n * Extract agents array from various config formats\n */\n private static extractAgents(config: any): AgentConfig[] {\n // Handle different config formats\n if (Array.isArray(config)) {\n return config; // Direct agent array\n }\n\n if (config.agents && Array.isArray(config.agents)) {\n return config.agents; // Standard format: { agents: [...] }\n }\n\n if (config.data?.agents && Array.isArray(config.data.agents)) {\n return config.data.agents; // Nested format: { data: { agents: [...] } }\n }\n\n return [];\n }\n\n /**\n * Log configured agents in a user-friendly way\n */\n private static logAgents(agents: AgentConfig[]): void {\n agents.forEach(agent => {\n const protocolIcon = agent.protocol === 'mcp' ? '🔗' : '⚡';\n const authIcon = agent.auth_token ? '🔐' : '🌐';\n console.log(` ${protocolIcon}${authIcon} ${agent.name} (${agent.protocol.toUpperCase()}) at ${agent.agent_uri}`);\n });\n\n const useRealAgents = process.env.USE_REAL_AGENTS === 'true';\n console.log(`🔧 Real agents mode: ${useRealAgents ? 'ENABLED' : 'DISABLED'}`);\n }\n\n /**\n * Validate agent configuration\n */\n static validateAgentConfig(agent: AgentConfig): void {\n const required = ['id', 'name', 'agent_uri', 'protocol'];\n\n for (const field of required) {\n if (!agent[field as keyof AgentConfig]) {\n throw new ConfigurationError(`Agent configuration missing required field: ${field}`, field);\n }\n }\n\n if (!['mcp', 'a2a'].includes(agent.protocol)) {\n throw new ConfigurationError(`Invalid protocol \"${agent.protocol}\". Must be \"mcp\" or \"a2a\"`, 'protocol');\n }\n\n // Basic URL validation\n try {\n new URL(agent.agent_uri);\n } catch {\n throw new ConfigurationError(`Invalid agent_uri \"${agent.agent_uri}\". Must be a valid URL`, 'agent_uri');\n }\n }\n\n /**\n * Validate multiple agent configurations\n */\n static validateAgentsConfig(agents: AgentConfig[]): void {\n if (!Array.isArray(agents)) {\n throw new ConfigurationError('Agents configuration must be an array');\n }\n\n if (agents.length === 0) {\n throw new ConfigurationError('At least one agent must be configured');\n }\n\n // Check for duplicate IDs\n const ids = agents.map(a => a.id);\n const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);\n if (duplicates.length > 0) {\n throw new ConfigurationError(`Duplicate agent IDs found: ${duplicates.join(', ')}`, 'duplicateIds');\n }\n\n // Validate each agent\n agents.forEach(agent => this.validateAgentConfig(agent));\n }\n\n /**\n * Create a sample configuration file\n */\n static createSampleConfig(): ADCPConfig {\n return {\n agents: [\n {\n id: 'premium-network',\n name: 'Premium Ad Network',\n agent_uri: 'https://premium-ads.example.com/mcp/',\n protocol: 'mcp',\n auth_token: process.env.PREMIUM_AGENT_TOKEN,\n },\n {\n id: 'budget-network',\n name: 'Budget Ad Network',\n agent_uri: 'https://budget-ads.example.com/a2a/',\n protocol: 'a2a',\n },\n ],\n defaults: {\n protocol: 'mcp',\n timeout: 30000,\n maxClarifications: 3,\n debug: false,\n },\n };\n }\n\n /**\n * Get configuration file paths that would be checked\n */\n static getConfigPaths(): string[] {\n return this.CONFIG_FILES.map(file => resolve(file));\n }\n\n /**\n * Get environment variables that would be checked\n */\n static getEnvVars(): string[] {\n return this.ENV_VARS;\n }\n\n /**\n * Generate configuration help text\n */\n static getConfigurationHelp(): string {\n return `\n🔧 ADCP Agent Configuration\n\nThe ADCP client can load agents from multiple sources:\n\n1️⃣ Environment Variables:\n Set any of: ${this.ENV_VARS.join(', ')}\n \n Example:\n export SALES_AGENTS_CONFIG='{\"agents\":[{\"id\":\"my-agent\",\"name\":\"My Agent\",\"agent_uri\":\"https://agent.example.com\",\"protocol\":\"mcp\"}]}'\n\n2️⃣ Configuration Files:\n Create any of: ${this.CONFIG_FILES.join(', ')}\n \n Example adcp.config.json:\n {\n \"agents\": [\n {\n \"id\": \"premium-agent\",\n \"name\": \"Premium Ad Network\",\n \"agent_uri\": \"https://premium.example.com\",\n \"protocol\": \"mcp\",\n \"auth_token\": \"your-token-here\"\n },\n {\n \"id\": \"dev-agent\",\n \"name\": \"Development Agent\",\n \"agent_uri\": \"https://dev.example.com\",\n \"protocol\": \"a2a\"\n }\n ]\n }\n\n3️⃣ Programmatic Configuration:\n const client = new ADCPMultiAgentClient([\n { id: 'agent', agent_uri: 'https://...', protocol: 'mcp',\n auth_token: process.env.MY_TOKEN }\n ]);\n\n📖 For more examples, see the documentation.\n`;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1 @@
|
|
|
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
|
//# sourceMappingURL=ConversationTypes.mjs.map
|
|
@@ -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 { SingleAgentClient } from "./SingleAgentClient.mjs";
|
|
8
2
|
class CreativeAgentClient {
|
|
9
3
|
client;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/core/CreativeAgentClient.ts"],"sourcesContent":["// Creative Agent Client - First-class support for creative agents\n\nimport { SingleAgentClient } from './SingleAgentClient';\nimport type { SingleAgentClientConfig } from './SingleAgentClient';\nimport type { InputHandler, TaskOptions } from './ConversationTypes';\nimport type { AgentConfig } from '../types';\nimport type { FormatReferenceStructuredObject as FormatID } from '../types/core.generated';\nimport type {\n ListCreativeFormatsRequest,\n ListCreativeFormatsResponse,\n ListCreativesRequest,\n ListCreativesResponse,\n Format,\n} from '../types/tools.generated';\n\n/**\n * Configuration for CreativeAgentClient\n */\nexport interface CreativeAgentClientConfig extends SingleAgentClientConfig {\n /** Creative agent URL */\n agentUrl: string;\n /** Protocol to use (defaults to 'mcp') */\n protocol?: 'mcp' | 'a2a';\n /** Authentication token if required */\n authToken?: string;\n}\n\n/**\n * Creative Agent Client - Specialized client for interacting with creative agents\n *\n * Creative agents provide creative format catalogs and creative assembly services.\n * This client provides a simplified interface for common creative agent operations.\n *\n * @example\n * ```typescript\n * // Standard creative agent\n * const creativeAgent = new CreativeAgentClient({\n * agentUrl: 'https://creative.adcontextprotocol.org/mcp'\n * });\n *\n * // List available formats\n * const formats = await creativeAgent.listFormats();\n *\n * // Find specific format\n * const banner = formats.find(f => f.format_id.id === 'display_300x250_image');\n * ```\n */\nexport class CreativeAgentClient {\n private client: SingleAgentClient;\n private agentUrl: string;\n\n constructor(config: CreativeAgentClientConfig) {\n const agentConfig: AgentConfig = {\n id: config.agentUrl.replace(/https?:\\/\\//, '').replace(/\\//g, '_'),\n name: 'Creative Agent',\n agent_uri: config.agentUrl,\n protocol: config.protocol || 'mcp',\n ...(config.authToken && { auth_token: config.authToken }),\n };\n\n this.client = new SingleAgentClient(agentConfig, config);\n this.agentUrl = config.agentUrl;\n }\n\n /**\n * List all available creative formats\n *\n * @param params - Optional filtering parameters\n * @returns Promise resolving to array of creative formats\n *\n * @example\n * ```typescript\n * const formats = await creativeAgent.listFormats();\n *\n * // Find by dimensions\n * const banners = formats.filter(f =>\n * f.renders?.[0]?.dimensions?.width === 300 &&\n * f.renders?.[0]?.dimensions?.height === 250\n * );\n * ```\n */\n async listFormats(params: ListCreativeFormatsRequest = {}): Promise<CreativeFormat[]> {\n const result = await this.client.listCreativeFormats(params);\n\n if (!result.success || !result.data) {\n throw new Error(`Failed to list creative formats: ${result.error || 'Unknown error'}`);\n }\n\n // Enrich formats with agent_url for convenience\n return (result.data.formats || []).map(format => ({\n ...format,\n agent_url: this.agentUrl,\n }));\n }\n\n /**\n * Find formats by dimensions\n *\n * @param width - Width in pixels\n * @param height - Height in pixels\n * @returns Promise resolving to matching formats\n *\n * @example\n * ```typescript\n * // Find all 300x250 formats\n * const mediumRectangles = await creativeAgent.findByDimensions(300, 250);\n * ```\n */\n async findByDimensions(width: number, height: number): Promise<CreativeFormat[]> {\n const allFormats = await this.listFormats();\n return allFormats.filter(f =>\n f.renders?.some(r => {\n if (!('dimensions' in r) || !r.dimensions) return false;\n const dims = r.dimensions as { width?: number; height?: number };\n return dims.width === width && dims.height === height;\n })\n );\n }\n\n /**\n * Find format by ID\n *\n * @param formatId - Format ID to search for\n * @returns Promise resolving to matching format or undefined\n *\n * @example\n * ```typescript\n * const format = await creativeAgent.findById('display_300x250_image');\n * if (format) {\n * console.log(`Found: ${format.name}`);\n * }\n * ```\n */\n async findById(formatId: string): Promise<CreativeFormat | undefined> {\n const allFormats = await this.listFormats();\n return allFormats.find(f => f.format_id.id === formatId);\n }\n\n /**\n * List creatives in the agent's library\n *\n * @param params - Optional filtering, sorting, and pagination parameters\n * @returns Promise resolving to the list creatives response\n *\n * @example\n * ```typescript\n * const result = await creativeAgent.listCreatives({\n * filters: { statuses: ['approved'], has_variables: true },\n * include_variables: true\n * });\n * ```\n */\n async listCreatives(\n params: ListCreativesRequest = {},\n inputHandler?: InputHandler,\n options?: TaskOptions\n ): Promise<ListCreativesResponse> {\n const result = await this.client.listCreatives(params, inputHandler, options);\n\n if (!result.success || !result.data) {\n throw new Error(`Failed to list creatives: ${result.error || 'Unknown error'}`);\n }\n\n return result.data;\n }\n\n /**\n * Get the agent URL\n */\n getAgentUrl(): string {\n return this.agentUrl;\n }\n\n /**\n * Get the underlying single-agent client for advanced operations\n */\n getClient(): SingleAgentClient {\n return this.client;\n }\n}\n\n/**\n * Creative format definition.\n *\n * Extends the official Format type from the schema with an additional\n * agent_url field for convenience when working with creative agents.\n */\nexport interface CreativeFormat extends Format {\n /** Base URL of the creative agent that provides this format */\n agent_url: string;\n}\n\n/**\n * Factory function to create a creative agent client\n *\n * @param config - Creative agent configuration\n * @returns Configured CreativeAgentClient instance\n *\n * @example\n * ```typescript\n * const creativeAgent = createCreativeAgentClient({\n * agentUrl: 'https://creative.adcontextprotocol.org/mcp'\n * });\n * ```\n */\nexport function createCreativeAgentClient(config: CreativeAgentClientConfig): CreativeAgentClient {\n return new CreativeAgentClient(config);\n}\n\n/**\n * Standard creative agent URLs\n */\nexport const STANDARD_CREATIVE_AGENTS = {\n /** Official AdCP reference creative agent */\n ADCP_REFERENCE: 'https://creative.adcontextprotocol.org/mcp',\n /** Official AdCP reference creative agent (A2A) */\n ADCP_REFERENCE_A2A: 'https://creative.adcontextprotocol.org/a2a',\n} as const;\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/core/CreativeAgentClient.ts"],"sourcesContent":["// Creative Agent Client - First-class support for creative agents\n\nimport { SingleAgentClient } from './SingleAgentClient';\nimport type { SingleAgentClientConfig } from './SingleAgentClient';\nimport type { InputHandler, TaskOptions } from './ConversationTypes';\nimport type { AgentConfig } from '../types';\nimport type { FormatReferenceStructuredObject as FormatID } from '../types/core.generated';\nimport type {\n ListCreativeFormatsRequest,\n ListCreativeFormatsResponse,\n ListCreativesRequest,\n ListCreativesResponse,\n Format,\n} from '../types/tools.generated';\n\n/**\n * Configuration for CreativeAgentClient\n */\nexport interface CreativeAgentClientConfig extends SingleAgentClientConfig {\n /** Creative agent URL */\n agentUrl: string;\n /** Protocol to use (defaults to 'mcp') */\n protocol?: 'mcp' | 'a2a';\n /** Authentication token if required */\n authToken?: string;\n}\n\n/**\n * Creative Agent Client - Specialized client for interacting with creative agents\n *\n * Creative agents provide creative format catalogs and creative assembly services.\n * This client provides a simplified interface for common creative agent operations.\n *\n * @example\n * ```typescript\n * // Standard creative agent\n * const creativeAgent = new CreativeAgentClient({\n * agentUrl: 'https://creative.adcontextprotocol.org/mcp'\n * });\n *\n * // List available formats\n * const formats = await creativeAgent.listFormats();\n *\n * // Find specific format\n * const banner = formats.find(f => f.format_id.id === 'display_300x250_image');\n * ```\n */\nexport class CreativeAgentClient {\n private client: SingleAgentClient;\n private agentUrl: string;\n\n constructor(config: CreativeAgentClientConfig) {\n const agentConfig: AgentConfig = {\n id: config.agentUrl.replace(/https?:\\/\\//, '').replace(/\\//g, '_'),\n name: 'Creative Agent',\n agent_uri: config.agentUrl,\n protocol: config.protocol || 'mcp',\n ...(config.authToken && { auth_token: config.authToken }),\n };\n\n this.client = new SingleAgentClient(agentConfig, config);\n this.agentUrl = config.agentUrl;\n }\n\n /**\n * List all available creative formats\n *\n * @param params - Optional filtering parameters\n * @returns Promise resolving to array of creative formats\n *\n * @example\n * ```typescript\n * const formats = await creativeAgent.listFormats();\n *\n * // Find by dimensions\n * const banners = formats.filter(f =>\n * f.renders?.[0]?.dimensions?.width === 300 &&\n * f.renders?.[0]?.dimensions?.height === 250\n * );\n * ```\n */\n async listFormats(params: ListCreativeFormatsRequest = {}): Promise<CreativeFormat[]> {\n const result = await this.client.listCreativeFormats(params);\n\n if (!result.success || !result.data) {\n throw new Error(`Failed to list creative formats: ${result.error || 'Unknown error'}`);\n }\n\n // Enrich formats with agent_url for convenience\n return (result.data.formats || []).map(format => ({\n ...format,\n agent_url: this.agentUrl,\n }));\n }\n\n /**\n * Find formats by dimensions\n *\n * @param width - Width in pixels\n * @param height - Height in pixels\n * @returns Promise resolving to matching formats\n *\n * @example\n * ```typescript\n * // Find all 300x250 formats\n * const mediumRectangles = await creativeAgent.findByDimensions(300, 250);\n * ```\n */\n async findByDimensions(width: number, height: number): Promise<CreativeFormat[]> {\n const allFormats = await this.listFormats();\n return allFormats.filter(f =>\n f.renders?.some(r => {\n if (!('dimensions' in r) || !r.dimensions) return false;\n const dims = r.dimensions as { width?: number; height?: number };\n return dims.width === width && dims.height === height;\n })\n );\n }\n\n /**\n * Find format by ID\n *\n * @param formatId - Format ID to search for\n * @returns Promise resolving to matching format or undefined\n *\n * @example\n * ```typescript\n * const format = await creativeAgent.findById('display_300x250_image');\n * if (format) {\n * console.log(`Found: ${format.name}`);\n * }\n * ```\n */\n async findById(formatId: string): Promise<CreativeFormat | undefined> {\n const allFormats = await this.listFormats();\n return allFormats.find(f => f.format_id.id === formatId);\n }\n\n /**\n * List creatives in the agent's library\n *\n * @param params - Optional filtering, sorting, and pagination parameters\n * @returns Promise resolving to the list creatives response\n *\n * @example\n * ```typescript\n * const result = await creativeAgent.listCreatives({\n * filters: { statuses: ['approved'], has_variables: true },\n * include_variables: true\n * });\n * ```\n */\n async listCreatives(\n params: ListCreativesRequest = {},\n inputHandler?: InputHandler,\n options?: TaskOptions\n ): Promise<ListCreativesResponse> {\n const result = await this.client.listCreatives(params, inputHandler, options);\n\n if (!result.success || !result.data) {\n throw new Error(`Failed to list creatives: ${result.error || 'Unknown error'}`);\n }\n\n return result.data;\n }\n\n /**\n * Get the agent URL\n */\n getAgentUrl(): string {\n return this.agentUrl;\n }\n\n /**\n * Get the underlying single-agent client for advanced operations\n */\n getClient(): SingleAgentClient {\n return this.client;\n }\n}\n\n/**\n * Creative format definition.\n *\n * Extends the official Format type from the schema with an additional\n * agent_url field for convenience when working with creative agents.\n */\nexport interface CreativeFormat extends Format {\n /** Base URL of the creative agent that provides this format */\n agent_url: string;\n}\n\n/**\n * Factory function to create a creative agent client\n *\n * @param config - Creative agent configuration\n * @returns Configured CreativeAgentClient instance\n *\n * @example\n * ```typescript\n * const creativeAgent = createCreativeAgentClient({\n * agentUrl: 'https://creative.adcontextprotocol.org/mcp'\n * });\n * ```\n */\nexport function createCreativeAgentClient(config: CreativeAgentClientConfig): CreativeAgentClient {\n return new CreativeAgentClient(config);\n}\n\n/**\n * Standard creative agent URLs\n */\nexport const STANDARD_CREATIVE_AGENTS = {\n /** Official AdCP reference creative agent */\n ADCP_REFERENCE: 'https://creative.adcontextprotocol.org/mcp',\n /** Official AdCP reference creative agent (A2A) */\n ADCP_REFERENCE_A2A: 'https://creative.adcontextprotocol.org/a2a',\n} as const;\n"],"mappings":"AAEA,SAAS,yBAAyB;AA6C3B,MAAM,oBAAoB;AAAA,EACvB;AAAA,EACA;AAAA,EAER,YAAY,QAAmC;AAC7C,UAAM,cAA2B;AAAA,MAC/B,IAAI,OAAO,SAAS,QAAQ,eAAe,EAAE,EAAE,QAAQ,OAAO,GAAG;AAAA,MACjE,MAAM;AAAA,MACN,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO,YAAY;AAAA,MAC7B,GAAI,OAAO,aAAa,EAAE,YAAY,OAAO,UAAU;AAAA,IACzD;AAEA,SAAK,SAAS,IAAI,kBAAkB,aAAa,MAAM;AACvD,SAAK,WAAW,OAAO;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,YAAY,SAAqC,CAAC,GAA8B;AACpF,UAAM,SAAS,MAAM,KAAK,OAAO,oBAAoB,MAAM;AAE3D,QAAI,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;AACnC,YAAM,IAAI,MAAM,oCAAoC,OAAO,SAAS,eAAe,EAAE;AAAA,IACvF;AAGA,YAAQ,OAAO,KAAK,WAAW,CAAC,GAAG,IAAI,aAAW;AAAA,MAChD,GAAG;AAAA,MACH,WAAW,KAAK;AAAA,IAClB,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,iBAAiB,OAAe,QAA2C;AAC/E,UAAM,aAAa,MAAM,KAAK,YAAY;AAC1C,WAAO,WAAW;AAAA,MAAO,OACvB,EAAE,SAAS,KAAK,OAAK;AACnB,YAAI,EAAE,gBAAgB,MAAM,CAAC,EAAE,WAAY,QAAO;AAClD,cAAM,OAAO,EAAE;AACf,eAAO,KAAK,UAAU,SAAS,KAAK,WAAW;AAAA,MACjD,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,SAAS,UAAuD;AACpE,UAAM,aAAa,MAAM,KAAK,YAAY;AAC1C,WAAO,WAAW,KAAK,OAAK,EAAE,UAAU,OAAO,QAAQ;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,cACJ,SAA+B,CAAC,GAChC,cACA,SACgC;AAChC,UAAM,SAAS,MAAM,KAAK,OAAO,cAAc,QAAQ,cAAc,OAAO;AAE5E,QAAI,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;AACnC,YAAM,IAAI,MAAM,6BAA6B,OAAO,SAAS,eAAe,EAAE;AAAA,IAChF;AAEA,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,YAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AA0BO,SAAS,0BAA0B,QAAwD;AAChG,SAAO,IAAI,oBAAoB,MAAM;AACvC;AAKO,MAAM,2BAA2B;AAAA;AAAA,EAEtC,gBAAgB;AAAA;AAAA,EAEhB,oBAAoB;AACtB;","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 { ProtocolClient } from "../protocols/index.mjs";
|
|
8
2
|
import { toolRequiresGovernance, parseCheckResponse } from "./GovernanceTypes.mjs";
|
|
9
3
|
import { unwrapProtocolResponse } from "../utils/response-unwrapper.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/core/GovernanceMiddleware.ts"],"sourcesContent":["/**\n * Buyer-side governance middleware.\n *\n * Intercepts tool calls in the execution path and checks them against\n * a campaign governance agent before allowing execution. Handles:\n * - approved: proceed with execution\n * - denied: return denial to caller\n * - conditions: auto-apply machine-actionable conditions and re-check\n *\n * After execution, reports the outcome back to the governance agent.\n */\n\nimport { randomUUID } from 'crypto';\n\nimport type { AgentConfig } from '../types';\nimport type {\n CheckGovernanceRequest,\n CheckGovernanceResponse,\n ReportPlanOutcomeRequest,\n ReportPlanOutcomeResponse,\n OutcomeType,\n} from '../types/tools.generated';\nimport { ProtocolClient } from '../protocols';\nimport type { Activity } from './AsyncHandler';\nimport type {\n GovernanceConfig,\n CampaignGovernanceConfig,\n GovernanceCheckResult,\n GovernanceOutcome,\n GovernanceFinding,\n GovernanceCondition,\n} from './GovernanceTypes';\nimport { toolRequiresGovernance, parseCheckResponse } from './GovernanceTypes';\nimport { unwrapProtocolResponse } from '../utils/response-unwrapper';\nimport { generateIdempotencyKey } from '../utils/idempotency';\n\n/**\n * Typed debug log entries for governance operations.\n */\nexport type GovernanceDebugEntry =\n | { type: 'governance_check'; iteration: number; tool: string; plan_id: string }\n | { type: 'governance_conditions_applied'; iteration: number; conditions: GovernanceCondition[] }\n | { type: 'governance_outcome_error'; check_id: string; error: string };\n\n/** Safe pattern for path segments: identifiers or numeric indices */\nconst SAFE_PATH_SEGMENT = /^[a-zA-Z_$][a-zA-Z0-9_$]*$|^\\d+$/;\n\n/** Path segments that would cause prototype pollution even though they match the safe pattern. */\nconst FORBIDDEN_PATH_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Set a value at a dot-path in an object. Creates intermediate objects as needed.\n * e.g., setAtPath(obj, 'packages.0.budget', 25000)\n *\n * Path segments are validated against a safe allowlist pattern and a forbidden\n * set to prevent prototype pollution from external governance agent responses.\n */\nexport function setAtPath(obj: Record<string, any>, path: string, value: unknown): void {\n if (!path || path.trim() === '') {\n throw new Error('Empty path is not allowed');\n }\n const parts = path.split('.');\n for (const part of parts) {\n // Explicit inline block for prototype-pollution vectors. The\n // FORBIDDEN_PATH_SEGMENTS set covers the same cases but CodeQL's\n // `js/prototype-pollution-utility` pattern matcher only recognizes\n // inline string comparisons as a valid guard.\n if (part === '__proto__' || part === 'constructor' || part === 'prototype') {\n throw new Error(`Invalid path segment: ${part}`);\n }\n if (FORBIDDEN_PATH_SEGMENTS.has(part)) {\n throw new Error(`Invalid path segment: ${part}`);\n }\n if (!SAFE_PATH_SEGMENT.test(part)) {\n throw new Error(`Invalid path segment: ${part}`);\n }\n }\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i]!;\n const nextKey = parts[i + 1]!;\n // Belt-and-suspenders: even with the segment allowlist, traverse only\n // own properties so a malicious prototype-chained value can't be\n // followed.\n const hasOwn = Object.prototype.hasOwnProperty.call(current, key);\n if (!hasOwn || current[key] == null || typeof current[key] !== 'object') {\n // Create array if next key is numeric, else object\n current[key] = /^\\d+$/.test(nextKey) ? [] : {};\n }\n current = current[key];\n }\n const finalKey = parts[parts.length - 1]!;\n if (finalKey === '__proto__' || finalKey === 'constructor' || finalKey === 'prototype') {\n throw new Error(`Invalid path segment: ${finalKey}`);\n }\n current[finalKey] = value;\n}\n\n/**\n * Upper bound on cached `(checkId, outcome)` idempotency keys. Chosen to\n * cover a full day of outcome reporting at ~100/minute without unbounded\n * growth for long-lived buyers. Each entry is ~100 bytes, so the cap\n * caps memory at ~1MB.\n */\nconst OUTCOME_KEY_CACHE_MAX = 10_000;\n\nexport class GovernanceMiddleware {\n /**\n * Cache of idempotency keys per `(checkId, outcome)` tuple. The\n * governance agent dedups on this tuple already, but the SDK keeps its\n * own cache so retries of `reportOutcome` with the same logical intent\n * reuse the same idempotency_key — re-generating on each call defeats\n * the whole retry-safety point of the envelope. Bounded LRU: once full,\n * inserting a new key evicts the oldest. Retries of evicted\n * (checkId, outcome) tuples will mint a fresh key — still functional\n * because the governance agent's own dedup takes over — but won't get\n * the SDK-level retry guarantee.\n */\n private outcomeKeys = new Map<string, string>();\n\n constructor(\n private governanceConfig: GovernanceConfig,\n private onActivity?: (activity: Activity) => void | Promise<void>,\n /**\n * Buyer's per-instance AdCP version pin. Forwarded to the governance\n * agent's `ProtocolClient.callTool` so a buyer pinned to e.g.\n * `'4.0.0-beta.1'` doesn't silently fall back to the SDK default\n * `ADCP_MAJOR_VERSION` constant when calling the governance agent.\n * Defaults to `undefined`, which `ProtocolClient.callTool` resolves\n * to the SDK constant — same shape as a no-pin call.\n */\n private adcpVersion?: string,\n private versionEnvelope?: import('../protocols').VersionEnvelopeMode,\n private onTransportActivity?: import('../protocols').TransportActivityHandler\n ) {}\n\n /**\n * Get or mint the idempotency key for a `(checkId, outcome)` tuple.\n * Uses the Map's insertion-order semantics for LRU eviction.\n */\n private getOrMintOutcomeKey(checkId: string, outcome: OutcomeType): string {\n const tupleKey = `${checkId}\\u001f${outcome}`;\n const cached = this.outcomeKeys.get(tupleKey);\n if (cached !== undefined) {\n // Touch: move to end so it becomes most-recently-used.\n this.outcomeKeys.delete(tupleKey);\n this.outcomeKeys.set(tupleKey, cached);\n return cached;\n }\n const fresh = generateIdempotencyKey();\n if (this.outcomeKeys.size >= OUTCOME_KEY_CACHE_MAX) {\n // Evict oldest (first inserted) entry.\n const oldest = this.outcomeKeys.keys().next().value;\n if (oldest !== undefined) this.outcomeKeys.delete(oldest);\n }\n this.outcomeKeys.set(tupleKey, fresh);\n return fresh;\n }\n\n /**\n * Check whether this tool requires a governance check.\n */\n requiresCheck(tool: string): boolean {\n return toolRequiresGovernance(tool, this.governanceConfig);\n }\n\n /**\n * Get the campaign governance config. Returns undefined if not configured.\n */\n get campaign(): CampaignGovernanceConfig | undefined {\n return this.governanceConfig.campaign;\n }\n\n /**\n * Run a proposed governance check before sending a tool call to a seller.\n *\n * Returns the governance result. The caller decides how to handle each status:\n * - approved: proceed with execution (params may be modified by conditions)\n * - denied: do not execute\n *\n * When conditions are returned with required_value, this method auto-applies\n * them and re-checks, up to maxConditionsIterations.\n */\n async checkProposed(\n tool: string,\n params: Record<string, unknown>,\n debugLogs: GovernanceDebugEntry[] = []\n ): Promise<{ result: GovernanceCheckResult; params: Record<string, unknown> }> {\n const config = this.governanceConfig.campaign;\n if (!config) {\n throw new Error('Campaign governance not configured');\n }\n\n const maxReChecks = config.maxConditionsIterations ?? 0;\n let currentParams = structuredClone(params);\n let iteration = 0;\n\n // Always make the initial governance check. maxConditionsIterations only\n // controls how many times we re-apply conditions and re-check.\n do {\n const request: CheckGovernanceRequest = {\n plan_id: config.planId,\n caller: config.callerUrl ?? '',\n tool,\n payload: currentParams,\n governance_context: config.governanceContext,\n };\n\n debugLogs.push({\n type: 'governance_check',\n iteration,\n tool,\n plan_id: config.planId,\n });\n\n const response = await ProtocolClient.callTool(config.agent, 'check_governance', request as Record<string, any>, {\n debugLogs,\n adcpVersion: this.adcpVersion,\n ...(this.versionEnvelope !== undefined && { versionEnvelope: this.versionEnvelope }),\n onTransportActivity: this.onTransportActivity,\n });\n\n // Unwrap protocol response (MCP text content, structuredContent, A2A artifacts)\n const responseData = unwrapProtocolResponse(response);\n\n await this.emitGovernanceActivity('governance_check', {\n tool,\n binding: 'proposed',\n iteration,\n response: responseData,\n });\n\n const checkResult = parseCheckResponse(responseData as unknown as CheckGovernanceResponse);\n\n // Thread governance_context from response to subsequent checks\n if (checkResult.governanceContext) {\n config.governanceContext = checkResult.governanceContext;\n }\n\n if (checkResult.status === 'approved') {\n return { result: checkResult, params: currentParams };\n }\n\n if (checkResult.status === 'denied') {\n return { result: checkResult, params: currentParams };\n }\n\n // status === 'conditions'\n if (!checkResult.conditions || checkResult.conditions.length === 0) {\n // Conditions status with no conditions — treat as advisory denial\n return { result: checkResult, params: currentParams };\n }\n\n // Try to auto-apply machine-actionable conditions\n const allApplicable = checkResult.conditions.every(c => c.requiredValue !== undefined);\n if (!allApplicable) {\n // Some conditions are advisory-only (no required_value) — can't auto-apply\n return { result: checkResult, params: currentParams };\n }\n\n // If we've exhausted re-check iterations, return conditions to caller\n if (iteration >= maxReChecks) {\n return { result: checkResult, params: currentParams };\n }\n\n // Apply conditions and re-check\n for (const condition of checkResult.conditions) {\n setAtPath(currentParams, condition.field, condition.requiredValue);\n }\n\n checkResult.conditionsApplied = true;\n checkResult.modifiedParams = currentParams;\n\n debugLogs.push({\n type: 'governance_conditions_applied',\n iteration,\n conditions: checkResult.conditions,\n });\n\n iteration++;\n } while (iteration <= maxReChecks);\n\n // Defensive: the early return at `iteration >= maxReChecks` inside the loop\n // should always fire before this point. If we somehow reach here, treat it\n // as an unresolvable condition so we fail closed.\n return {\n result: {\n checkId: '',\n status: 'denied',\n explanation: `Governance conditions could not be resolved after ${maxReChecks} iterations`,\n },\n params: currentParams,\n };\n }\n\n /**\n * Report the outcome of a tool execution to the governance agent.\n * Called after the seller responds (success or failure).\n */\n async reportOutcome(\n checkId: string,\n outcome: OutcomeType,\n sellerResponse?: Record<string, unknown>,\n error?: { code?: string; message: string },\n debugLogs: GovernanceDebugEntry[] = [],\n governanceContext?: string\n ): Promise<GovernanceOutcome | undefined> {\n const config = this.governanceConfig.campaign;\n if (!config) return undefined;\n\n const gc = governanceContext ?? config.governanceContext ?? '';\n\n // Reuse the same idempotency_key for retries of the same\n // (checkId, outcome) intent so the governance agent treats them as\n // one logical outcome report rather than distinct submissions.\n const idempotencyKey = this.getOrMintOutcomeKey(checkId, outcome);\n\n const request: ReportPlanOutcomeRequest = {\n idempotency_key: idempotencyKey,\n plan_id: config.planId,\n check_id: checkId,\n outcome,\n governance_context: gc,\n };\n\n if (outcome === 'completed' && sellerResponse) {\n request.seller_response = sellerResponse as ReportPlanOutcomeRequest['seller_response'];\n }\n\n if (outcome === 'failed' && error) {\n request.error = error;\n }\n\n try {\n const response = await ProtocolClient.callTool(\n config.agent,\n 'report_plan_outcome',\n request as Record<string, any>,\n {\n debugLogs,\n adcpVersion: this.adcpVersion,\n ...(this.versionEnvelope !== undefined && { versionEnvelope: this.versionEnvelope }),\n onTransportActivity: this.onTransportActivity,\n transportActivityContext: {\n operationId: checkId,\n taskId: checkId,\n idempotencyKey,\n },\n }\n );\n\n const responseData = unwrapProtocolResponse(response) as unknown as ReportPlanOutcomeResponse;\n\n await this.emitGovernanceActivity('governance_outcome', {\n check_id: checkId,\n outcome,\n });\n\n return {\n outcomeId: responseData.outcome_id,\n status: responseData.outcome_state as GovernanceOutcome['status'],\n committedBudget: responseData.committed_budget ?? undefined,\n findings: responseData.findings?.map(f => ({\n categoryId: f.category_id,\n severity: f.severity,\n explanation: f.explanation,\n details: f.details ?? undefined,\n })),\n planSummary:\n responseData.plan_summary?.total_committed != null && responseData.plan_summary?.budget_remaining != null\n ? {\n totalCommitted: responseData.plan_summary.total_committed,\n budgetRemaining: responseData.plan_summary.budget_remaining,\n }\n : undefined,\n };\n } catch (err) {\n // Outcome reporting failure shouldn't fail the task\n debugLogs.push({\n type: 'governance_outcome_error',\n check_id: checkId,\n error: (err as Error).message,\n });\n await this.emitGovernanceActivity(\n 'governance_outcome',\n {\n check_id: checkId,\n outcome,\n error: (err as Error).message,\n warning: 'Outcome reporting failed — governance agent may have stale state',\n },\n 'failed'\n );\n return undefined;\n }\n }\n\n private async emitGovernanceActivity(\n type: Activity['type'],\n payload: Record<string, unknown>,\n status: string = 'completed'\n ): Promise<void> {\n await this.onActivity?.({\n type,\n operation_id: '',\n agent_id: this.governanceConfig.campaign?.agent.id ?? '',\n task_type: 'governance',\n status,\n payload,\n timestamp: new Date().toISOString(),\n });\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/core/GovernanceMiddleware.ts"],"sourcesContent":["/**\n * Buyer-side governance middleware.\n *\n * Intercepts tool calls in the execution path and checks them against\n * a campaign governance agent before allowing execution. Handles:\n * - approved: proceed with execution\n * - denied: return denial to caller\n * - conditions: auto-apply machine-actionable conditions and re-check\n *\n * After execution, reports the outcome back to the governance agent.\n */\n\nimport { randomUUID } from 'crypto';\n\nimport type { AgentConfig } from '../types';\nimport type {\n CheckGovernanceRequest,\n CheckGovernanceResponse,\n ReportPlanOutcomeRequest,\n ReportPlanOutcomeResponse,\n OutcomeType,\n} from '../types/tools.generated';\nimport { ProtocolClient } from '../protocols';\nimport type { Activity } from './AsyncHandler';\nimport type {\n GovernanceConfig,\n CampaignGovernanceConfig,\n GovernanceCheckResult,\n GovernanceOutcome,\n GovernanceFinding,\n GovernanceCondition,\n} from './GovernanceTypes';\nimport { toolRequiresGovernance, parseCheckResponse } from './GovernanceTypes';\nimport { unwrapProtocolResponse } from '../utils/response-unwrapper';\nimport { generateIdempotencyKey } from '../utils/idempotency';\n\n/**\n * Typed debug log entries for governance operations.\n */\nexport type GovernanceDebugEntry =\n | { type: 'governance_check'; iteration: number; tool: string; plan_id: string }\n | { type: 'governance_conditions_applied'; iteration: number; conditions: GovernanceCondition[] }\n | { type: 'governance_outcome_error'; check_id: string; error: string };\n\n/** Safe pattern for path segments: identifiers or numeric indices */\nconst SAFE_PATH_SEGMENT = /^[a-zA-Z_$][a-zA-Z0-9_$]*$|^\\d+$/;\n\n/** Path segments that would cause prototype pollution even though they match the safe pattern. */\nconst FORBIDDEN_PATH_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Set a value at a dot-path in an object. Creates intermediate objects as needed.\n * e.g., setAtPath(obj, 'packages.0.budget', 25000)\n *\n * Path segments are validated against a safe allowlist pattern and a forbidden\n * set to prevent prototype pollution from external governance agent responses.\n */\nexport function setAtPath(obj: Record<string, any>, path: string, value: unknown): void {\n if (!path || path.trim() === '') {\n throw new Error('Empty path is not allowed');\n }\n const parts = path.split('.');\n for (const part of parts) {\n // Explicit inline block for prototype-pollution vectors. The\n // FORBIDDEN_PATH_SEGMENTS set covers the same cases but CodeQL's\n // `js/prototype-pollution-utility` pattern matcher only recognizes\n // inline string comparisons as a valid guard.\n if (part === '__proto__' || part === 'constructor' || part === 'prototype') {\n throw new Error(`Invalid path segment: ${part}`);\n }\n if (FORBIDDEN_PATH_SEGMENTS.has(part)) {\n throw new Error(`Invalid path segment: ${part}`);\n }\n if (!SAFE_PATH_SEGMENT.test(part)) {\n throw new Error(`Invalid path segment: ${part}`);\n }\n }\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i]!;\n const nextKey = parts[i + 1]!;\n // Belt-and-suspenders: even with the segment allowlist, traverse only\n // own properties so a malicious prototype-chained value can't be\n // followed.\n const hasOwn = Object.prototype.hasOwnProperty.call(current, key);\n if (!hasOwn || current[key] == null || typeof current[key] !== 'object') {\n // Create array if next key is numeric, else object\n current[key] = /^\\d+$/.test(nextKey) ? [] : {};\n }\n current = current[key];\n }\n const finalKey = parts[parts.length - 1]!;\n if (finalKey === '__proto__' || finalKey === 'constructor' || finalKey === 'prototype') {\n throw new Error(`Invalid path segment: ${finalKey}`);\n }\n current[finalKey] = value;\n}\n\n/**\n * Upper bound on cached `(checkId, outcome)` idempotency keys. Chosen to\n * cover a full day of outcome reporting at ~100/minute without unbounded\n * growth for long-lived buyers. Each entry is ~100 bytes, so the cap\n * caps memory at ~1MB.\n */\nconst OUTCOME_KEY_CACHE_MAX = 10_000;\n\nexport class GovernanceMiddleware {\n /**\n * Cache of idempotency keys per `(checkId, outcome)` tuple. The\n * governance agent dedups on this tuple already, but the SDK keeps its\n * own cache so retries of `reportOutcome` with the same logical intent\n * reuse the same idempotency_key — re-generating on each call defeats\n * the whole retry-safety point of the envelope. Bounded LRU: once full,\n * inserting a new key evicts the oldest. Retries of evicted\n * (checkId, outcome) tuples will mint a fresh key — still functional\n * because the governance agent's own dedup takes over — but won't get\n * the SDK-level retry guarantee.\n */\n private outcomeKeys = new Map<string, string>();\n\n constructor(\n private governanceConfig: GovernanceConfig,\n private onActivity?: (activity: Activity) => void | Promise<void>,\n /**\n * Buyer's per-instance AdCP version pin. Forwarded to the governance\n * agent's `ProtocolClient.callTool` so a buyer pinned to e.g.\n * `'4.0.0-beta.1'` doesn't silently fall back to the SDK default\n * `ADCP_MAJOR_VERSION` constant when calling the governance agent.\n * Defaults to `undefined`, which `ProtocolClient.callTool` resolves\n * to the SDK constant — same shape as a no-pin call.\n */\n private adcpVersion?: string,\n private versionEnvelope?: import('../protocols').VersionEnvelopeMode,\n private onTransportActivity?: import('../protocols').TransportActivityHandler\n ) {}\n\n /**\n * Get or mint the idempotency key for a `(checkId, outcome)` tuple.\n * Uses the Map's insertion-order semantics for LRU eviction.\n */\n private getOrMintOutcomeKey(checkId: string, outcome: OutcomeType): string {\n const tupleKey = `${checkId}\\u001f${outcome}`;\n const cached = this.outcomeKeys.get(tupleKey);\n if (cached !== undefined) {\n // Touch: move to end so it becomes most-recently-used.\n this.outcomeKeys.delete(tupleKey);\n this.outcomeKeys.set(tupleKey, cached);\n return cached;\n }\n const fresh = generateIdempotencyKey();\n if (this.outcomeKeys.size >= OUTCOME_KEY_CACHE_MAX) {\n // Evict oldest (first inserted) entry.\n const oldest = this.outcomeKeys.keys().next().value;\n if (oldest !== undefined) this.outcomeKeys.delete(oldest);\n }\n this.outcomeKeys.set(tupleKey, fresh);\n return fresh;\n }\n\n /**\n * Check whether this tool requires a governance check.\n */\n requiresCheck(tool: string): boolean {\n return toolRequiresGovernance(tool, this.governanceConfig);\n }\n\n /**\n * Get the campaign governance config. Returns undefined if not configured.\n */\n get campaign(): CampaignGovernanceConfig | undefined {\n return this.governanceConfig.campaign;\n }\n\n /**\n * Run a proposed governance check before sending a tool call to a seller.\n *\n * Returns the governance result. The caller decides how to handle each status:\n * - approved: proceed with execution (params may be modified by conditions)\n * - denied: do not execute\n *\n * When conditions are returned with required_value, this method auto-applies\n * them and re-checks, up to maxConditionsIterations.\n */\n async checkProposed(\n tool: string,\n params: Record<string, unknown>,\n debugLogs: GovernanceDebugEntry[] = []\n ): Promise<{ result: GovernanceCheckResult; params: Record<string, unknown> }> {\n const config = this.governanceConfig.campaign;\n if (!config) {\n throw new Error('Campaign governance not configured');\n }\n\n const maxReChecks = config.maxConditionsIterations ?? 0;\n let currentParams = structuredClone(params);\n let iteration = 0;\n\n // Always make the initial governance check. maxConditionsIterations only\n // controls how many times we re-apply conditions and re-check.\n do {\n const request: CheckGovernanceRequest = {\n plan_id: config.planId,\n caller: config.callerUrl ?? '',\n tool,\n payload: currentParams,\n governance_context: config.governanceContext,\n };\n\n debugLogs.push({\n type: 'governance_check',\n iteration,\n tool,\n plan_id: config.planId,\n });\n\n const response = await ProtocolClient.callTool(config.agent, 'check_governance', request as Record<string, any>, {\n debugLogs,\n adcpVersion: this.adcpVersion,\n ...(this.versionEnvelope !== undefined && { versionEnvelope: this.versionEnvelope }),\n onTransportActivity: this.onTransportActivity,\n });\n\n // Unwrap protocol response (MCP text content, structuredContent, A2A artifacts)\n const responseData = unwrapProtocolResponse(response);\n\n await this.emitGovernanceActivity('governance_check', {\n tool,\n binding: 'proposed',\n iteration,\n response: responseData,\n });\n\n const checkResult = parseCheckResponse(responseData as unknown as CheckGovernanceResponse);\n\n // Thread governance_context from response to subsequent checks\n if (checkResult.governanceContext) {\n config.governanceContext = checkResult.governanceContext;\n }\n\n if (checkResult.status === 'approved') {\n return { result: checkResult, params: currentParams };\n }\n\n if (checkResult.status === 'denied') {\n return { result: checkResult, params: currentParams };\n }\n\n // status === 'conditions'\n if (!checkResult.conditions || checkResult.conditions.length === 0) {\n // Conditions status with no conditions — treat as advisory denial\n return { result: checkResult, params: currentParams };\n }\n\n // Try to auto-apply machine-actionable conditions\n const allApplicable = checkResult.conditions.every(c => c.requiredValue !== undefined);\n if (!allApplicable) {\n // Some conditions are advisory-only (no required_value) — can't auto-apply\n return { result: checkResult, params: currentParams };\n }\n\n // If we've exhausted re-check iterations, return conditions to caller\n if (iteration >= maxReChecks) {\n return { result: checkResult, params: currentParams };\n }\n\n // Apply conditions and re-check\n for (const condition of checkResult.conditions) {\n setAtPath(currentParams, condition.field, condition.requiredValue);\n }\n\n checkResult.conditionsApplied = true;\n checkResult.modifiedParams = currentParams;\n\n debugLogs.push({\n type: 'governance_conditions_applied',\n iteration,\n conditions: checkResult.conditions,\n });\n\n iteration++;\n } while (iteration <= maxReChecks);\n\n // Defensive: the early return at `iteration >= maxReChecks` inside the loop\n // should always fire before this point. If we somehow reach here, treat it\n // as an unresolvable condition so we fail closed.\n return {\n result: {\n checkId: '',\n status: 'denied',\n explanation: `Governance conditions could not be resolved after ${maxReChecks} iterations`,\n },\n params: currentParams,\n };\n }\n\n /**\n * Report the outcome of a tool execution to the governance agent.\n * Called after the seller responds (success or failure).\n */\n async reportOutcome(\n checkId: string,\n outcome: OutcomeType,\n sellerResponse?: Record<string, unknown>,\n error?: { code?: string; message: string },\n debugLogs: GovernanceDebugEntry[] = [],\n governanceContext?: string\n ): Promise<GovernanceOutcome | undefined> {\n const config = this.governanceConfig.campaign;\n if (!config) return undefined;\n\n const gc = governanceContext ?? config.governanceContext ?? '';\n\n // Reuse the same idempotency_key for retries of the same\n // (checkId, outcome) intent so the governance agent treats them as\n // one logical outcome report rather than distinct submissions.\n const idempotencyKey = this.getOrMintOutcomeKey(checkId, outcome);\n\n const request: ReportPlanOutcomeRequest = {\n idempotency_key: idempotencyKey,\n plan_id: config.planId,\n check_id: checkId,\n outcome,\n governance_context: gc,\n };\n\n if (outcome === 'completed' && sellerResponse) {\n request.seller_response = sellerResponse as ReportPlanOutcomeRequest['seller_response'];\n }\n\n if (outcome === 'failed' && error) {\n request.error = error;\n }\n\n try {\n const response = await ProtocolClient.callTool(\n config.agent,\n 'report_plan_outcome',\n request as Record<string, any>,\n {\n debugLogs,\n adcpVersion: this.adcpVersion,\n ...(this.versionEnvelope !== undefined && { versionEnvelope: this.versionEnvelope }),\n onTransportActivity: this.onTransportActivity,\n transportActivityContext: {\n operationId: checkId,\n taskId: checkId,\n idempotencyKey,\n },\n }\n );\n\n const responseData = unwrapProtocolResponse(response) as unknown as ReportPlanOutcomeResponse;\n\n await this.emitGovernanceActivity('governance_outcome', {\n check_id: checkId,\n outcome,\n });\n\n return {\n outcomeId: responseData.outcome_id,\n status: responseData.outcome_state as GovernanceOutcome['status'],\n committedBudget: responseData.committed_budget ?? undefined,\n findings: responseData.findings?.map(f => ({\n categoryId: f.category_id,\n severity: f.severity,\n explanation: f.explanation,\n details: f.details ?? undefined,\n })),\n planSummary:\n responseData.plan_summary?.total_committed != null && responseData.plan_summary?.budget_remaining != null\n ? {\n totalCommitted: responseData.plan_summary.total_committed,\n budgetRemaining: responseData.plan_summary.budget_remaining,\n }\n : undefined,\n };\n } catch (err) {\n // Outcome reporting failure shouldn't fail the task\n debugLogs.push({\n type: 'governance_outcome_error',\n check_id: checkId,\n error: (err as Error).message,\n });\n await this.emitGovernanceActivity(\n 'governance_outcome',\n {\n check_id: checkId,\n outcome,\n error: (err as Error).message,\n warning: 'Outcome reporting failed — governance agent may have stale state',\n },\n 'failed'\n );\n return undefined;\n }\n }\n\n private async emitGovernanceActivity(\n type: Activity['type'],\n payload: Record<string, unknown>,\n status: string = 'completed'\n ): Promise<void> {\n await this.onActivity?.({\n type,\n operation_id: '',\n agent_id: this.governanceConfig.campaign?.agent.id ?? '',\n task_type: 'governance',\n status,\n payload,\n timestamp: new Date().toISOString(),\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
|
const GOVERNANCE_SELF_TOOLS = /* @__PURE__ */ new Set(["sync_plans", "check_governance", "report_plan_outcome", "get_plan_audit_logs"]);
|
|
8
2
|
const DEFAULT_EXCLUDED_TOOLS = /* @__PURE__ */ new Set([...GOVERNANCE_SELF_TOOLS, "get_adcp_capabilities"]);
|
|
9
3
|
function toolRequiresGovernance(tool, config) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/core/GovernanceTypes.ts"],"sourcesContent":["/**\n * Governance middleware types for buyer-side campaign governance.\n *\n * The governance middleware intercepts tool calls and checks them against\n * a campaign governance agent before execution. It handles the full lifecycle:\n * check → execute → report outcome.\n */\n\nimport type { AgentConfig } from '../types';\nimport type { CheckGovernanceResponse, EscalationSeverity } from '../types/tools.generated';\n\n/**\n * Campaign governance agent configuration.\n * The campaign governance agent handles check_governance, sync_plans,\n * report_plan_outcome, and get_plan_audit_logs.\n */\nexport interface CampaignGovernanceConfig {\n /** The governance agent to call */\n agent: AgentConfig;\n /** Plan ID for this advertiser's campaign */\n planId: string;\n /** Caller URL for the check_governance request */\n callerUrl?: string;\n /** Max re-check iterations after auto-applying conditions. Default: 0 (return conditions to caller without re-checking). The initial governance check always fires. */\n maxConditionsIterations?: number;\n /** Opaque governance context string from a prior check_governance response. The middleware passes this through on subsequent checks and outcome reports. */\n governanceContext?: string;\n}\n\n/**\n * Governance configuration.\n *\n * Campaign governance handles: check_governance, sync_plans,\n * report_plan_outcome, get_plan_audit_logs.\n */\nexport interface GovernanceConfig {\n /** Campaign governance agent */\n campaign?: CampaignGovernanceConfig;\n /**\n * Which tools require governance checks.\n * - 'all': every tool including get_adcp_capabilities (governance tools themselves still excluded)\n * - string[]: only listed tools\n * - function: custom predicate\n * - undefined (default): all tools except get_adcp_capabilities and governance tools\n */\n scope?: 'all' | string[] | ((tool: string) => boolean);\n}\n\n/** Governance tools that are always excluded (infinite recursion otherwise) */\nconst GOVERNANCE_SELF_TOOLS = new Set(['sync_plans', 'check_governance', 'report_plan_outcome', 'get_plan_audit_logs']);\n\n/** Tools excluded by default (governance tools + capabilities) */\nconst DEFAULT_EXCLUDED_TOOLS = new Set([...GOVERNANCE_SELF_TOOLS, 'get_adcp_capabilities']);\n\n/**\n * Determine whether a tool requires a governance check given the config.\n */\nexport function toolRequiresGovernance(tool: string, config: GovernanceConfig): boolean {\n if (!config.campaign) return false;\n\n // Governance tools are always excluded to prevent infinite recursion\n if (GOVERNANCE_SELF_TOOLS.has(tool)) return false;\n\n if (config.scope === 'all') return true;\n\n if (Array.isArray(config.scope)) return config.scope.includes(tool);\n\n if (typeof config.scope === 'function') return config.scope(tool);\n\n // Default: all tools except excluded set\n return !DEFAULT_EXCLUDED_TOOLS.has(tool);\n}\n\n/**\n * A single finding from a governance check.\n */\nexport interface GovernanceFinding {\n categoryId: string;\n policyId?: string;\n severity: EscalationSeverity;\n explanation: string;\n confidence?: number;\n uncertaintyReason?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * A condition that must be met before the action can proceed.\n */\nexport interface GovernanceCondition {\n /** Dot-path to the field that needs adjustment */\n field: string;\n /** The value the field must have for approval. When present, condition is machine-actionable. */\n requiredValue?: unknown;\n /** Why this condition is required */\n reason: string;\n}\n\n/**\n * Escalation details when a governance check requires human review.\n */\nexport interface GovernanceEscalation {\n reason: string;\n severity: EscalationSeverity;\n requiresHuman: boolean;\n approvalTier?: string;\n}\n\n/**\n * Governance check result attached to TaskResult.\n */\nexport interface GovernanceCheckResult {\n checkId: string;\n status: 'approved' | 'denied' | 'conditions';\n explanation: string;\n findings?: GovernanceFinding[];\n conditions?: GovernanceCondition[];\n escalation?: GovernanceEscalation;\n expiresAt?: string;\n /** Opaque governance context issued by the governance agent. Callers must thread this to subsequent checks and outcome reports. */\n governanceContext?: string;\n /** Whether conditions were auto-applied by the middleware */\n conditionsApplied?: boolean;\n /** The modified params after conditions were applied */\n modifiedParams?: Record<string, unknown>;\n}\n\n/**\n * Outcome metadata from report_plan_outcome, attached to TaskResult after completion.\n */\nexport interface GovernanceOutcome {\n outcomeId: string;\n status: 'accepted' | 'findings';\n committedBudget?: number;\n findings?: GovernanceFinding[];\n planSummary?: {\n totalCommitted: number;\n budgetRemaining: number;\n };\n}\n\n/**\n * Parse a CheckGovernanceResponse into GovernanceCheckResult.\n */\nexport function parseCheckResponse(response: CheckGovernanceResponse): GovernanceCheckResult {\n return {\n checkId: response.check_id,\n status: response.verdict,\n explanation: response.explanation,\n findings: response.findings?.map(f => ({\n categoryId: f.category_id,\n policyId: f.policy_id ?? undefined,\n severity: f.severity,\n explanation: f.explanation,\n confidence: f.confidence ?? undefined,\n uncertaintyReason: f.uncertainty_reason ?? undefined,\n details: f.details ?? undefined,\n })),\n conditions: response.conditions?.map(c => ({\n field: c.field,\n requiredValue: c.required_value,\n reason: c.reason,\n })),\n expiresAt: response.expires_at ?? undefined,\n governanceContext: response.governance_context ?? undefined,\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/core/GovernanceTypes.ts"],"sourcesContent":["/**\n * Governance middleware types for buyer-side campaign governance.\n *\n * The governance middleware intercepts tool calls and checks them against\n * a campaign governance agent before execution. It handles the full lifecycle:\n * check → execute → report outcome.\n */\n\nimport type { AgentConfig } from '../types';\nimport type { CheckGovernanceResponse, EscalationSeverity } from '../types/tools.generated';\n\n/**\n * Campaign governance agent configuration.\n * The campaign governance agent handles check_governance, sync_plans,\n * report_plan_outcome, and get_plan_audit_logs.\n */\nexport interface CampaignGovernanceConfig {\n /** The governance agent to call */\n agent: AgentConfig;\n /** Plan ID for this advertiser's campaign */\n planId: string;\n /** Caller URL for the check_governance request */\n callerUrl?: string;\n /** Max re-check iterations after auto-applying conditions. Default: 0 (return conditions to caller without re-checking). The initial governance check always fires. */\n maxConditionsIterations?: number;\n /** Opaque governance context string from a prior check_governance response. The middleware passes this through on subsequent checks and outcome reports. */\n governanceContext?: string;\n}\n\n/**\n * Governance configuration.\n *\n * Campaign governance handles: check_governance, sync_plans,\n * report_plan_outcome, get_plan_audit_logs.\n */\nexport interface GovernanceConfig {\n /** Campaign governance agent */\n campaign?: CampaignGovernanceConfig;\n /**\n * Which tools require governance checks.\n * - 'all': every tool including get_adcp_capabilities (governance tools themselves still excluded)\n * - string[]: only listed tools\n * - function: custom predicate\n * - undefined (default): all tools except get_adcp_capabilities and governance tools\n */\n scope?: 'all' | string[] | ((tool: string) => boolean);\n}\n\n/** Governance tools that are always excluded (infinite recursion otherwise) */\nconst GOVERNANCE_SELF_TOOLS = new Set(['sync_plans', 'check_governance', 'report_plan_outcome', 'get_plan_audit_logs']);\n\n/** Tools excluded by default (governance tools + capabilities) */\nconst DEFAULT_EXCLUDED_TOOLS = new Set([...GOVERNANCE_SELF_TOOLS, 'get_adcp_capabilities']);\n\n/**\n * Determine whether a tool requires a governance check given the config.\n */\nexport function toolRequiresGovernance(tool: string, config: GovernanceConfig): boolean {\n if (!config.campaign) return false;\n\n // Governance tools are always excluded to prevent infinite recursion\n if (GOVERNANCE_SELF_TOOLS.has(tool)) return false;\n\n if (config.scope === 'all') return true;\n\n if (Array.isArray(config.scope)) return config.scope.includes(tool);\n\n if (typeof config.scope === 'function') return config.scope(tool);\n\n // Default: all tools except excluded set\n return !DEFAULT_EXCLUDED_TOOLS.has(tool);\n}\n\n/**\n * A single finding from a governance check.\n */\nexport interface GovernanceFinding {\n categoryId: string;\n policyId?: string;\n severity: EscalationSeverity;\n explanation: string;\n confidence?: number;\n uncertaintyReason?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * A condition that must be met before the action can proceed.\n */\nexport interface GovernanceCondition {\n /** Dot-path to the field that needs adjustment */\n field: string;\n /** The value the field must have for approval. When present, condition is machine-actionable. */\n requiredValue?: unknown;\n /** Why this condition is required */\n reason: string;\n}\n\n/**\n * Escalation details when a governance check requires human review.\n */\nexport interface GovernanceEscalation {\n reason: string;\n severity: EscalationSeverity;\n requiresHuman: boolean;\n approvalTier?: string;\n}\n\n/**\n * Governance check result attached to TaskResult.\n */\nexport interface GovernanceCheckResult {\n checkId: string;\n status: 'approved' | 'denied' | 'conditions';\n explanation: string;\n findings?: GovernanceFinding[];\n conditions?: GovernanceCondition[];\n escalation?: GovernanceEscalation;\n expiresAt?: string;\n /** Opaque governance context issued by the governance agent. Callers must thread this to subsequent checks and outcome reports. */\n governanceContext?: string;\n /** Whether conditions were auto-applied by the middleware */\n conditionsApplied?: boolean;\n /** The modified params after conditions were applied */\n modifiedParams?: Record<string, unknown>;\n}\n\n/**\n * Outcome metadata from report_plan_outcome, attached to TaskResult after completion.\n */\nexport interface GovernanceOutcome {\n outcomeId: string;\n status: 'accepted' | 'findings';\n committedBudget?: number;\n findings?: GovernanceFinding[];\n planSummary?: {\n totalCommitted: number;\n budgetRemaining: number;\n };\n}\n\n/**\n * Parse a CheckGovernanceResponse into GovernanceCheckResult.\n */\nexport function parseCheckResponse(response: CheckGovernanceResponse): GovernanceCheckResult {\n return {\n checkId: response.check_id,\n status: response.verdict,\n explanation: response.explanation,\n findings: response.findings?.map(f => ({\n categoryId: f.category_id,\n policyId: f.policy_id ?? undefined,\n severity: f.severity,\n explanation: f.explanation,\n confidence: f.confidence ?? undefined,\n uncertaintyReason: f.uncertainty_reason ?? undefined,\n details: f.details ?? undefined,\n })),\n conditions: response.conditions?.map(c => ({\n field: c.field,\n requiredValue: c.required_value,\n reason: c.reason,\n })),\n expiresAt: response.expires_at ?? undefined,\n governanceContext: response.governance_context ?? undefined,\n };\n}\n"],"mappings":"AAiDA,MAAM,wBAAwB,oBAAI,IAAI,CAAC,cAAc,oBAAoB,uBAAuB,qBAAqB,CAAC;AAGtH,MAAM,yBAAyB,oBAAI,IAAI,CAAC,GAAG,uBAAuB,uBAAuB,CAAC;AAKnF,SAAS,uBAAuB,MAAc,QAAmC;AACtF,MAAI,CAAC,OAAO,SAAU,QAAO;AAG7B,MAAI,sBAAsB,IAAI,IAAI,EAAG,QAAO;AAE5C,MAAI,OAAO,UAAU,MAAO,QAAO;AAEnC,MAAI,MAAM,QAAQ,OAAO,KAAK,EAAG,QAAO,OAAO,MAAM,SAAS,IAAI;AAElE,MAAI,OAAO,OAAO,UAAU,WAAY,QAAO,OAAO,MAAM,IAAI;AAGhE,SAAO,CAAC,uBAAuB,IAAI,IAAI;AACzC;AAyEO,SAAS,mBAAmB,UAA0D;AAC3F,SAAO;AAAA,IACL,SAAS,SAAS;AAAA,IAClB,QAAQ,SAAS;AAAA,IACjB,aAAa,SAAS;AAAA,IACtB,UAAU,SAAS,UAAU,IAAI,QAAM;AAAA,MACrC,YAAY,EAAE;AAAA,MACd,UAAU,EAAE,aAAa;AAAA,MACzB,UAAU,EAAE;AAAA,MACZ,aAAa,EAAE;AAAA,MACf,YAAY,EAAE,cAAc;AAAA,MAC5B,mBAAmB,EAAE,sBAAsB;AAAA,MAC3C,SAAS,EAAE,WAAW;AAAA,IACxB,EAAE;AAAA,IACF,YAAY,SAAS,YAAY,IAAI,QAAM;AAAA,MACzC,OAAO,EAAE;AAAA,MACT,eAAe,EAAE;AAAA,MACjB,QAAQ,EAAE;AAAA,IACZ,EAAE;AAAA,IACF,WAAW,SAAS,cAAc;AAAA,IAClC,mBAAmB,SAAS,sBAAsB;AAAA,EACpD;AACF;","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 { getLatestA2ADataPartFromTask } from "../utils/a2a-artifacts.mjs";
|
|
8
2
|
import {
|
|
9
3
|
ADCP_STATUS,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/core/ProtocolResponseParser.ts"],"sourcesContent":["/**\n * Simple ADCP-compliant response parser\n * Implements ADCP spec PR #77 for standardized status field\n */\n\nimport type { InputRequest } from './ConversationTypes';\nimport { getLatestA2ADataPartFromTask } from '../utils/a2a-artifacts';\nimport {\n ADCP_STATUS,\n type ADCPStatus,\n TASK_ENVELOPE_FIELDS,\n extractAdcpStatusFromA2aTaskResult,\n extractAdcpTaskStatusFromPayload,\n isAdcpStatus,\n} from './task-status';\n\nexport { ADCP_STATUS, type ADCPStatus } from './task-status';\n\nconst NESTED_TASK_ENVELOPE_FIELDS: ReadonlySet<string> = new Set([...TASK_ENVELOPE_FIELDS, 'taskId', 'adcp_error']);\n\n/**\n * Max length for a server-issued session id (`contextId` / `taskId`) we\n * will retain on the client. Well above any sane UUID, opaque token, or\n * ADK-style hierarchical id — exceeding it signals a misbehaving seller,\n * not a legitimate identifier.\n */\nconst SESSION_ID_MAX_LENGTH = 256;\n\n/**\n * Printable ASCII only (0x20–0x7E). Rejects control characters (CR, LF,\n * NUL, ANSI sequences) that would be retained verbatim on future sends\n * and echoed into debug logs — a log-injection vector if those logs reach\n * third-party observability stacks. This is stricter than the A2A spec,\n * which treats the id as opaque, but matches every id format we've seen\n * in the wild (UUIDs, KSUIDs, ADK `app/user/session` triples, etc.).\n */\nconst SESSION_ID_PATTERN = /^[\\x20-\\x7E]+$/;\n\nfunction isSafeSessionId(v: unknown): v is string {\n if (typeof v !== 'string') return false;\n if (v.length === 0 || v.length > SESSION_ID_MAX_LENGTH) return false;\n return SESSION_ID_PATTERN.test(v);\n}\n\n/**\n * Extract the AdCP task handle from an A2A wrapped Task result. The\n * handle lives on artifact metadata (`adcp_task_id` per adcp-client#899,\n * with `serverTaskId` accepted as a compatibility alias).\n * Walk artifacts backward so trailing text-only artifacts with metadata still\n * work when the DataPart does not carry a task id. If both metadata and the\n * typed DataPart carry task ids and they disagree, prefer the DataPart.\n */\nfunction extractAdcpTaskIdFromA2aTaskResult(result: any): string | undefined {\n if (result == null || typeof result !== 'object' || Array.isArray(result)) return undefined;\n if (result.kind !== 'task') return undefined;\n\n const latestDataPart = getLatestA2ADataPartFromTask(result);\n const taskIdFromDataPart = firstSafeSessionId(latestDataPart?.data?.task_id, latestDataPart?.data?.taskId);\n\n const resolveMetadataTaskId = (taskId: string | undefined): string | undefined => {\n if (!taskId) return undefined;\n return taskIdFromDataPart && taskIdFromDataPart !== taskId ? taskIdFromDataPart : taskId;\n };\n\n const artifacts = result.artifacts;\n if (Array.isArray(artifacts)) {\n for (let i = artifacts.length - 1; i >= 0; i -= 1) {\n const artifact = artifacts[i];\n if (artifact == null || typeof artifact !== 'object' || Array.isArray(artifact)) continue;\n const metadata = (artifact as { metadata?: unknown }).metadata;\n if (metadata == null || typeof metadata !== 'object' || Array.isArray(metadata)) continue;\n const m = metadata as Record<string, unknown>;\n const taskId = resolveMetadataTaskId(firstSafeSessionId(m.adcp_task_id, m.serverTaskId));\n if (taskId) return taskId;\n }\n }\n\n if (taskIdFromDataPart) return taskIdFromDataPart;\n\n const resultMetadata = result.metadata;\n if (resultMetadata != null && typeof resultMetadata === 'object' && !Array.isArray(resultMetadata)) {\n const m = resultMetadata as Record<string, unknown>;\n const taskId = resolveMetadataTaskId(firstSafeSessionId(m.adcp_task_id, m.serverTaskId));\n if (taskId) return taskId;\n }\n\n return undefined;\n}\n\n/** Return the first argument that passes {@link isSafeSessionId}, else `undefined`. */\nfunction firstSafeSessionId(...candidates: unknown[]): string | undefined {\n for (const c of candidates) {\n if (isSafeSessionId(c)) return c;\n }\n return undefined;\n}\n\nfunction getAdcpVersionFromPayload(payload: unknown): string | undefined {\n if (payload == null || typeof payload !== 'object' || Array.isArray(payload)) return undefined;\n const record = payload as Record<string, unknown>;\n if (typeof record.adcp_version === 'string') return record.adcp_version;\n\n const nested = record.response;\n if (nested != null && typeof nested === 'object' && !Array.isArray(nested)) {\n const envelope = nested as Record<string, unknown>;\n const status = typeof envelope.status === 'string' ? envelope.status : undefined;\n const isAdcpStatus = status !== undefined && (Object.values(ADCP_STATUS) as string[]).includes(status);\n const hasOnlyEnvelopeFields = Object.keys(envelope).every(key => NESTED_TASK_ENVELOPE_FIELDS.has(key));\n const looksLikeEnvelope =\n typeof envelope.task_id === 'string' ||\n typeof envelope.taskId === 'string' ||\n Array.isArray(envelope.errors) ||\n (envelope.adcp_error != null && typeof envelope.adcp_error === 'object') ||\n (isAdcpStatus && hasOnlyEnvelopeFields);\n\n if (looksLikeEnvelope && typeof envelope.adcp_version === 'string') {\n return envelope.adcp_version;\n }\n }\n\n return undefined;\n}\n\nfunction getLatestDataPartFromParts(parts: unknown): Record<string, unknown> | undefined {\n if (!Array.isArray(parts)) return undefined;\n for (let i = parts.length - 1; i >= 0; i -= 1) {\n const part = parts[i];\n if (part == null || typeof part !== 'object' || Array.isArray(part)) continue;\n const record = part as Record<string, unknown>;\n if (record.kind !== 'data') continue;\n const data = record.data;\n if (data == null || typeof data !== 'object' || Array.isArray(data)) continue;\n return data as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction getA2AResultAdcpVersion(result: unknown): string | undefined {\n if (result == null || typeof result !== 'object' || Array.isArray(result)) return undefined;\n\n const taskData = getLatestA2ADataPartFromTask(result)?.data;\n const taskVersion = getAdcpVersionFromPayload(taskData);\n if (taskVersion) return taskVersion;\n\n const resultRecord = result as Record<string, unknown>;\n const messageData = getLatestDataPartFromParts(resultRecord.parts);\n const messageVersion = getAdcpVersionFromPayload(messageData);\n if (messageVersion) return messageVersion;\n\n return getAdcpVersionFromPayload(result);\n}\n\nfunction getMcpTextContentAdcpVersion(content: unknown): string | undefined {\n if (!Array.isArray(content)) return undefined;\n for (const item of content) {\n if (item == null || typeof item !== 'object' || Array.isArray(item)) continue;\n const text = (item as { type?: unknown; text?: unknown }).text;\n if ((item as { type?: unknown }).type !== 'text' || typeof text !== 'string') continue;\n try {\n const parsed = JSON.parse(text);\n const version = getAdcpVersionFromPayload(parsed);\n if (version) return version;\n } catch {\n // Non-JSON text chunks are advisory copy, not AdCP envelopes.\n }\n }\n return undefined;\n}\n\n/**\n * Simple parser that follows ADCP spec exactly\n */\nexport class ProtocolResponseParser {\n /**\n * Check if response indicates input is needed per ADCP spec\n */\n isInputRequest(response: any): boolean {\n // ADCP spec: check A2A JSON-RPC wrapped status first\n if (response?.result?.status?.state === ADCP_STATUS.INPUT_REQUIRED) {\n return true;\n }\n\n // ADCP spec: check top-level status field\n if (response?.status === ADCP_STATUS.INPUT_REQUIRED) {\n return true;\n }\n\n // Legacy fallback for backward compatibility\n return (\n response?.type === 'input_request' ||\n response?.question !== undefined ||\n response?.input_required === true ||\n response?.needs_clarification === true\n );\n }\n\n /**\n * Parse input request from response\n */\n parseInputRequest(response: any): InputRequest {\n const question = response.message || response.question || response.prompt || 'Please provide input';\n const field = response.field || response.parameter;\n const suggestions = response.options || response.choices || response.suggestions;\n\n return {\n question,\n field,\n expectedType: this.parseExpectedType(response.expected_type || response.type),\n suggestions,\n required: response.required !== false,\n validation: response.validation,\n context: response.context || response.description,\n };\n }\n\n /**\n * Get ADCP status from response\n */\n getStatus(response: any): ADCPStatus | null {\n // For A2A wrapped Task responses (`result.kind === 'task'`), the\n // transport-layer `result.status.state` reflects the HTTP-call\n // lifecycle (always `'completed'` for AdCP submitted arms per\n // adcp-client#899), NOT the AdCP work lifecycle. Prefer the AdCP\n // status surfaced on the artifact's DataPart when it's set —\n // that's the layer the buyer cares about for polling decisions.\n // See adcp-client#973 for the regression class this catches.\n const adcpStatusFromArtifact = extractAdcpStatusFromA2aTaskResult(response?.result);\n if (adcpStatusFromArtifact) return adcpStatusFromArtifact;\n\n // Check A2A JSON-RPC wrapped status (result.status.state) — used\n // when the artifact didn't surface an AdCP status (non-AdCP A2A\n // responses, or sync-completed responses where transport state is\n // authoritative).\n if (isAdcpStatus(response?.result?.status?.state)) {\n return response.result.status.state as ADCPStatus;\n }\n\n // Raw/in-process MCP wrappers may have a wrapper-level status plus the\n // actual AdCP task envelope under `data`. The nested task status wins\n // over the wrapper when it is a real task envelope; domain-status\n // collisions still fall through because `extractAdcpTaskStatusFromPayload`\n // rejects domain payloads with non-envelope fields.\n const hasOfficialPayload =\n response?.structuredContent !== undefined || response?.content !== undefined || response?.result !== undefined;\n const data = hasOfficialPayload ? undefined : response?.data;\n const dataTaskStatus =\n data != null && typeof data === 'object' && !Array.isArray(data)\n ? extractAdcpTaskStatusFromPayload(data)\n : undefined;\n if (dataTaskStatus) return dataTaskStatus;\n\n // Check top-level status first (A2A and direct responses)\n if (isAdcpStatus(response?.status)) {\n return response.status as ADCPStatus;\n }\n\n // Check MCP structuredContent.status.\n // Exclusive task-lifecycle statuses (submitted/working/input-required/\n // auth-required) never appear in domain enums and are trusted unconditionally.\n // Shared literals (completed/canceled/failed/rejected) collide with AdCP v3\n // domain status enums like MediaBuyStatus, so we only treat them as task\n // status when the envelope has no keys outside the task-envelope allowlist.\n // Otherwise we fall through to the structuredContent fallback below, so Zod\n // validators parse the domain payload. See issue #646.\n const sc = response?.structuredContent;\n if (sc?.status && isAdcpStatus(sc.status)) {\n const taskStatus = extractAdcpTaskStatusFromPayload(sc);\n if (taskStatus) return taskStatus;\n // Domain payload present alongside a shared-literal status — fall through.\n }\n\n // Check for MCP error responses\n if (response?.isError === true) {\n return ADCP_STATUS.FAILED;\n }\n\n // If response has structuredContent or content, assume it's completed\n if (response?.structuredContent || (response?.content && !response?.isError)) {\n return ADCP_STATUS.COMPLETED;\n }\n\n return null;\n }\n\n /**\n * Extract the `replayed` field from a protocol response envelope.\n *\n * Returns `true` if the seller set `replayed: true` on the envelope,\n * `false` if explicitly set to `false`, `undefined` if not present. Callers\n * with side effects on response (notifications, LLM memory writes, downstream\n * tool calls) MUST treat `undefined` as `false` — the spec says fresh\n * executions MAY omit the field.\n */\n getReplayed(response: any): boolean | undefined {\n if (response == null) return undefined;\n\n // A2A JSON-RPC wrapped\n if (response.result && typeof response.result.replayed === 'boolean') {\n return response.result.replayed;\n }\n\n // MCP structuredContent\n if (response.structuredContent && typeof response.structuredContent.replayed === 'boolean') {\n return response.structuredContent.replayed;\n }\n\n // Top-level envelope (A2A direct, REST)\n if (typeof response.replayed === 'boolean') {\n return response.replayed;\n }\n\n return undefined;\n }\n\n /**\n * Extract the seller-served AdCP release echo from the response envelope.\n *\n * This is the response-side `adcp_version` value, not necessarily the\n * caller's configured pin. Multi-version sellers can downshift within the\n * same major; callers that care should compare this value to their request's\n * release-precision wire version (for example, `wireVersion.normalize(pin)`),\n * not to a raw full-semver configuration value.\n */\n getAdcpVersion(response: any): string | undefined {\n if (response == null) return undefined;\n\n // A2A wrapped Task/Message responses carry AdCP payloads in DataParts.\n const a2aVersion = getA2AResultAdcpVersion(response.result);\n if (a2aVersion) return a2aVersion;\n\n // MCP structuredContent.\n if (typeof response.structuredContent?.adcp_version === 'string') {\n return response.structuredContent.adcp_version;\n }\n\n // MCP text content fallback.\n const textContentVersion = getMcpTextContentAdcpVersion(response.content);\n if (textContentVersion) return textContentVersion;\n\n // Legacy tasks/get wrapper.\n const taskVersion = getAdcpVersionFromPayload(response.task);\n if (taskVersion) return taskVersion;\n\n // Flat AdCP envelope.\n if (typeof response.adcp_version === 'string') {\n return response.adcp_version;\n }\n\n return undefined;\n }\n\n /**\n * Extract the A2A `contextId` / AdCP `context_id` that binds the response\n * to a server-side conversation. Buyers retain this across calls on the\n * same AgentClient so the server can route subsequent sends to the same\n * session. Returns `undefined` when the server did not surface one (e.g.,\n * MCP completed responses that don't need conversation continuity).\n *\n * Values that fail {@link isSafeSessionId} (overlong, control characters,\n * non-string) are rejected and return `undefined` — retention falls back\n * to the previously retained id. The server is the authoritative issuer\n * but a compromised or buggy seller shouldn't be able to exhaust buyer\n * memory or inject control sequences into buyer debug logs.\n */\n getContextId(response: any): string | undefined {\n if (response == null) return undefined;\n\n // A2A sendMessage returns either a Task (has `contextId`) or a Message\n // (may have `contextId`). With the A2AClient SDK these arrive unwrapped\n // on `response.result`; some transports surface them directly on the\n // response envelope, so check both.\n if (response.result) {\n const fromResult = firstSafeSessionId(response.result.contextId, response.result.context_id);\n if (fromResult) return fromResult;\n }\n const fromEnvelope = firstSafeSessionId(response.contextId);\n if (fromEnvelope) return fromEnvelope;\n\n // MCP structuredContent / top-level AdCP envelope.\n const sc = response.structuredContent;\n if (sc) {\n const fromSc = firstSafeSessionId(sc.context_id);\n if (fromSc) return fromSc;\n }\n return firstSafeSessionId(response.context_id);\n }\n\n /**\n * Extract the A2A `taskId` for the task the server is tracking (or just\n * created) for this send. Retained across calls only while the last\n * response was non-terminal (working / input-required / submitted /\n * auth-required) so buyers can resume the same server-side task; cleared\n * by the caller on terminal responses.\n *\n * Same sanitization rules as {@link getContextId}: malformed ids return\n * `undefined`.\n */\n getTaskId(response: any): string | undefined {\n if (response == null) return undefined;\n\n if (response.result) {\n // A2A wrapped Task with AdCP payload — `artifact.metadata.adcp_task_id`\n // is the AdCP work handle (what the buyer polls with via AdCP\n // `tasks/get`). The transport-layer `result.id` is the A2A\n // Task.id (always pinned to one HTTP call per adcp-client#899's\n // two-lifecycle contract); using it as a polling key would\n // address the wrong thing. Prefer the AdCP handle when present;\n // fall back to `result.id` for non-AdCP A2A responses where no\n // artifact metadata was emitted. See adcp-client#973.\n if (response.result.kind === 'task') {\n const adcpHandle = extractAdcpTaskIdFromA2aTaskResult(response.result);\n if (adcpHandle) return adcpHandle;\n const taskKindId = firstSafeSessionId(response.result.id);\n if (taskKindId) return taskKindId;\n }\n const fromResult = firstSafeSessionId(response.result.taskId, response.result.id, response.result.task_id);\n if (fromResult) return fromResult;\n }\n const fromEnvelope = firstSafeSessionId(response.taskId);\n if (fromEnvelope) return fromEnvelope;\n\n const sc = response.structuredContent;\n if (sc) {\n const fromSc = firstSafeSessionId(sc.task_id);\n if (fromSc) return fromSc;\n }\n const fromFlat = firstSafeSessionId(response.task_id);\n if (fromFlat) return fromFlat;\n\n const hasOfficialPayload =\n response.structuredContent !== undefined || response.content !== undefined || response.result !== undefined;\n const data = hasOfficialPayload ? undefined : response.data;\n if (data != null && typeof data === 'object' && !Array.isArray(data)) {\n const fromData = firstSafeSessionId(data.task_id, data.taskId);\n if (fromData) return fromData;\n }\n return undefined;\n }\n\n private parseExpectedType(rawType: unknown): 'string' | 'number' | 'boolean' | 'object' | 'array' | undefined {\n if (typeof rawType === 'string') {\n const allowedTypes: string[] = ['string', 'number', 'boolean', 'object', 'array'];\n return allowedTypes.includes(rawType)\n ? (rawType as 'string' | 'number' | 'boolean' | 'object' | 'array')\n : undefined;\n }\n return undefined;\n }\n}\n\n// Export singleton instance\nexport const responseParser = new ProtocolResponseParser();\n"],"mappings":"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","names":["ADCP_STATUS","isAdcpStatus"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/core/ProtocolResponseParser.ts"],"sourcesContent":["/**\n * Simple ADCP-compliant response parser\n * Implements ADCP spec PR #77 for standardized status field\n */\n\nimport type { InputRequest } from './ConversationTypes';\nimport { getLatestA2ADataPartFromTask } from '../utils/a2a-artifacts';\nimport {\n ADCP_STATUS,\n type ADCPStatus,\n TASK_ENVELOPE_FIELDS,\n extractAdcpStatusFromA2aTaskResult,\n extractAdcpTaskStatusFromPayload,\n isAdcpStatus,\n} from './task-status';\n\nexport { ADCP_STATUS, type ADCPStatus } from './task-status';\n\nconst NESTED_TASK_ENVELOPE_FIELDS: ReadonlySet<string> = new Set([...TASK_ENVELOPE_FIELDS, 'taskId', 'adcp_error']);\n\n/**\n * Max length for a server-issued session id (`contextId` / `taskId`) we\n * will retain on the client. Well above any sane UUID, opaque token, or\n * ADK-style hierarchical id — exceeding it signals a misbehaving seller,\n * not a legitimate identifier.\n */\nconst SESSION_ID_MAX_LENGTH = 256;\n\n/**\n * Printable ASCII only (0x20–0x7E). Rejects control characters (CR, LF,\n * NUL, ANSI sequences) that would be retained verbatim on future sends\n * and echoed into debug logs — a log-injection vector if those logs reach\n * third-party observability stacks. This is stricter than the A2A spec,\n * which treats the id as opaque, but matches every id format we've seen\n * in the wild (UUIDs, KSUIDs, ADK `app/user/session` triples, etc.).\n */\nconst SESSION_ID_PATTERN = /^[\\x20-\\x7E]+$/;\n\nfunction isSafeSessionId(v: unknown): v is string {\n if (typeof v !== 'string') return false;\n if (v.length === 0 || v.length > SESSION_ID_MAX_LENGTH) return false;\n return SESSION_ID_PATTERN.test(v);\n}\n\n/**\n * Extract the AdCP task handle from an A2A wrapped Task result. The\n * handle lives on artifact metadata (`adcp_task_id` per adcp-client#899,\n * with `serverTaskId` accepted as a compatibility alias).\n * Walk artifacts backward so trailing text-only artifacts with metadata still\n * work when the DataPart does not carry a task id. If both metadata and the\n * typed DataPart carry task ids and they disagree, prefer the DataPart.\n */\nfunction extractAdcpTaskIdFromA2aTaskResult(result: any): string | undefined {\n if (result == null || typeof result !== 'object' || Array.isArray(result)) return undefined;\n if (result.kind !== 'task') return undefined;\n\n const latestDataPart = getLatestA2ADataPartFromTask(result);\n const taskIdFromDataPart = firstSafeSessionId(latestDataPart?.data?.task_id, latestDataPart?.data?.taskId);\n\n const resolveMetadataTaskId = (taskId: string | undefined): string | undefined => {\n if (!taskId) return undefined;\n return taskIdFromDataPart && taskIdFromDataPart !== taskId ? taskIdFromDataPart : taskId;\n };\n\n const artifacts = result.artifacts;\n if (Array.isArray(artifacts)) {\n for (let i = artifacts.length - 1; i >= 0; i -= 1) {\n const artifact = artifacts[i];\n if (artifact == null || typeof artifact !== 'object' || Array.isArray(artifact)) continue;\n const metadata = (artifact as { metadata?: unknown }).metadata;\n if (metadata == null || typeof metadata !== 'object' || Array.isArray(metadata)) continue;\n const m = metadata as Record<string, unknown>;\n const taskId = resolveMetadataTaskId(firstSafeSessionId(m.adcp_task_id, m.serverTaskId));\n if (taskId) return taskId;\n }\n }\n\n if (taskIdFromDataPart) return taskIdFromDataPart;\n\n const resultMetadata = result.metadata;\n if (resultMetadata != null && typeof resultMetadata === 'object' && !Array.isArray(resultMetadata)) {\n const m = resultMetadata as Record<string, unknown>;\n const taskId = resolveMetadataTaskId(firstSafeSessionId(m.adcp_task_id, m.serverTaskId));\n if (taskId) return taskId;\n }\n\n return undefined;\n}\n\n/** Return the first argument that passes {@link isSafeSessionId}, else `undefined`. */\nfunction firstSafeSessionId(...candidates: unknown[]): string | undefined {\n for (const c of candidates) {\n if (isSafeSessionId(c)) return c;\n }\n return undefined;\n}\n\nfunction getAdcpVersionFromPayload(payload: unknown): string | undefined {\n if (payload == null || typeof payload !== 'object' || Array.isArray(payload)) return undefined;\n const record = payload as Record<string, unknown>;\n if (typeof record.adcp_version === 'string') return record.adcp_version;\n\n const nested = record.response;\n if (nested != null && typeof nested === 'object' && !Array.isArray(nested)) {\n const envelope = nested as Record<string, unknown>;\n const status = typeof envelope.status === 'string' ? envelope.status : undefined;\n const isAdcpStatus = status !== undefined && (Object.values(ADCP_STATUS) as string[]).includes(status);\n const hasOnlyEnvelopeFields = Object.keys(envelope).every(key => NESTED_TASK_ENVELOPE_FIELDS.has(key));\n const looksLikeEnvelope =\n typeof envelope.task_id === 'string' ||\n typeof envelope.taskId === 'string' ||\n Array.isArray(envelope.errors) ||\n (envelope.adcp_error != null && typeof envelope.adcp_error === 'object') ||\n (isAdcpStatus && hasOnlyEnvelopeFields);\n\n if (looksLikeEnvelope && typeof envelope.adcp_version === 'string') {\n return envelope.adcp_version;\n }\n }\n\n return undefined;\n}\n\nfunction getLatestDataPartFromParts(parts: unknown): Record<string, unknown> | undefined {\n if (!Array.isArray(parts)) return undefined;\n for (let i = parts.length - 1; i >= 0; i -= 1) {\n const part = parts[i];\n if (part == null || typeof part !== 'object' || Array.isArray(part)) continue;\n const record = part as Record<string, unknown>;\n if (record.kind !== 'data') continue;\n const data = record.data;\n if (data == null || typeof data !== 'object' || Array.isArray(data)) continue;\n return data as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction getA2AResultAdcpVersion(result: unknown): string | undefined {\n if (result == null || typeof result !== 'object' || Array.isArray(result)) return undefined;\n\n const taskData = getLatestA2ADataPartFromTask(result)?.data;\n const taskVersion = getAdcpVersionFromPayload(taskData);\n if (taskVersion) return taskVersion;\n\n const resultRecord = result as Record<string, unknown>;\n const messageData = getLatestDataPartFromParts(resultRecord.parts);\n const messageVersion = getAdcpVersionFromPayload(messageData);\n if (messageVersion) return messageVersion;\n\n return getAdcpVersionFromPayload(result);\n}\n\nfunction getMcpTextContentAdcpVersion(content: unknown): string | undefined {\n if (!Array.isArray(content)) return undefined;\n for (const item of content) {\n if (item == null || typeof item !== 'object' || Array.isArray(item)) continue;\n const text = (item as { type?: unknown; text?: unknown }).text;\n if ((item as { type?: unknown }).type !== 'text' || typeof text !== 'string') continue;\n try {\n const parsed = JSON.parse(text);\n const version = getAdcpVersionFromPayload(parsed);\n if (version) return version;\n } catch {\n // Non-JSON text chunks are advisory copy, not AdCP envelopes.\n }\n }\n return undefined;\n}\n\n/**\n * Simple parser that follows ADCP spec exactly\n */\nexport class ProtocolResponseParser {\n /**\n * Check if response indicates input is needed per ADCP spec\n */\n isInputRequest(response: any): boolean {\n // ADCP spec: check A2A JSON-RPC wrapped status first\n if (response?.result?.status?.state === ADCP_STATUS.INPUT_REQUIRED) {\n return true;\n }\n\n // ADCP spec: check top-level status field\n if (response?.status === ADCP_STATUS.INPUT_REQUIRED) {\n return true;\n }\n\n // Legacy fallback for backward compatibility\n return (\n response?.type === 'input_request' ||\n response?.question !== undefined ||\n response?.input_required === true ||\n response?.needs_clarification === true\n );\n }\n\n /**\n * Parse input request from response\n */\n parseInputRequest(response: any): InputRequest {\n const question = response.message || response.question || response.prompt || 'Please provide input';\n const field = response.field || response.parameter;\n const suggestions = response.options || response.choices || response.suggestions;\n\n return {\n question,\n field,\n expectedType: this.parseExpectedType(response.expected_type || response.type),\n suggestions,\n required: response.required !== false,\n validation: response.validation,\n context: response.context || response.description,\n };\n }\n\n /**\n * Get ADCP status from response\n */\n getStatus(response: any): ADCPStatus | null {\n // For A2A wrapped Task responses (`result.kind === 'task'`), the\n // transport-layer `result.status.state` reflects the HTTP-call\n // lifecycle (always `'completed'` for AdCP submitted arms per\n // adcp-client#899), NOT the AdCP work lifecycle. Prefer the AdCP\n // status surfaced on the artifact's DataPart when it's set —\n // that's the layer the buyer cares about for polling decisions.\n // See adcp-client#973 for the regression class this catches.\n const adcpStatusFromArtifact = extractAdcpStatusFromA2aTaskResult(response?.result);\n if (adcpStatusFromArtifact) return adcpStatusFromArtifact;\n\n // Check A2A JSON-RPC wrapped status (result.status.state) — used\n // when the artifact didn't surface an AdCP status (non-AdCP A2A\n // responses, or sync-completed responses where transport state is\n // authoritative).\n if (isAdcpStatus(response?.result?.status?.state)) {\n return response.result.status.state as ADCPStatus;\n }\n\n // Raw/in-process MCP wrappers may have a wrapper-level status plus the\n // actual AdCP task envelope under `data`. The nested task status wins\n // over the wrapper when it is a real task envelope; domain-status\n // collisions still fall through because `extractAdcpTaskStatusFromPayload`\n // rejects domain payloads with non-envelope fields.\n const hasOfficialPayload =\n response?.structuredContent !== undefined || response?.content !== undefined || response?.result !== undefined;\n const data = hasOfficialPayload ? undefined : response?.data;\n const dataTaskStatus =\n data != null && typeof data === 'object' && !Array.isArray(data)\n ? extractAdcpTaskStatusFromPayload(data)\n : undefined;\n if (dataTaskStatus) return dataTaskStatus;\n\n // Check top-level status first (A2A and direct responses)\n if (isAdcpStatus(response?.status)) {\n return response.status as ADCPStatus;\n }\n\n // Check MCP structuredContent.status.\n // Exclusive task-lifecycle statuses (submitted/working/input-required/\n // auth-required) never appear in domain enums and are trusted unconditionally.\n // Shared literals (completed/canceled/failed/rejected) collide with AdCP v3\n // domain status enums like MediaBuyStatus, so we only treat them as task\n // status when the envelope has no keys outside the task-envelope allowlist.\n // Otherwise we fall through to the structuredContent fallback below, so Zod\n // validators parse the domain payload. See issue #646.\n const sc = response?.structuredContent;\n if (sc?.status && isAdcpStatus(sc.status)) {\n const taskStatus = extractAdcpTaskStatusFromPayload(sc);\n if (taskStatus) return taskStatus;\n // Domain payload present alongside a shared-literal status — fall through.\n }\n\n // Check for MCP error responses\n if (response?.isError === true) {\n return ADCP_STATUS.FAILED;\n }\n\n // If response has structuredContent or content, assume it's completed\n if (response?.structuredContent || (response?.content && !response?.isError)) {\n return ADCP_STATUS.COMPLETED;\n }\n\n return null;\n }\n\n /**\n * Extract the `replayed` field from a protocol response envelope.\n *\n * Returns `true` if the seller set `replayed: true` on the envelope,\n * `false` if explicitly set to `false`, `undefined` if not present. Callers\n * with side effects on response (notifications, LLM memory writes, downstream\n * tool calls) MUST treat `undefined` as `false` — the spec says fresh\n * executions MAY omit the field.\n */\n getReplayed(response: any): boolean | undefined {\n if (response == null) return undefined;\n\n // A2A JSON-RPC wrapped\n if (response.result && typeof response.result.replayed === 'boolean') {\n return response.result.replayed;\n }\n\n // MCP structuredContent\n if (response.structuredContent && typeof response.structuredContent.replayed === 'boolean') {\n return response.structuredContent.replayed;\n }\n\n // Top-level envelope (A2A direct, REST)\n if (typeof response.replayed === 'boolean') {\n return response.replayed;\n }\n\n return undefined;\n }\n\n /**\n * Extract the seller-served AdCP release echo from the response envelope.\n *\n * This is the response-side `adcp_version` value, not necessarily the\n * caller's configured pin. Multi-version sellers can downshift within the\n * same major; callers that care should compare this value to their request's\n * release-precision wire version (for example, `wireVersion.normalize(pin)`),\n * not to a raw full-semver configuration value.\n */\n getAdcpVersion(response: any): string | undefined {\n if (response == null) return undefined;\n\n // A2A wrapped Task/Message responses carry AdCP payloads in DataParts.\n const a2aVersion = getA2AResultAdcpVersion(response.result);\n if (a2aVersion) return a2aVersion;\n\n // MCP structuredContent.\n if (typeof response.structuredContent?.adcp_version === 'string') {\n return response.structuredContent.adcp_version;\n }\n\n // MCP text content fallback.\n const textContentVersion = getMcpTextContentAdcpVersion(response.content);\n if (textContentVersion) return textContentVersion;\n\n // Legacy tasks/get wrapper.\n const taskVersion = getAdcpVersionFromPayload(response.task);\n if (taskVersion) return taskVersion;\n\n // Flat AdCP envelope.\n if (typeof response.adcp_version === 'string') {\n return response.adcp_version;\n }\n\n return undefined;\n }\n\n /**\n * Extract the A2A `contextId` / AdCP `context_id` that binds the response\n * to a server-side conversation. Buyers retain this across calls on the\n * same AgentClient so the server can route subsequent sends to the same\n * session. Returns `undefined` when the server did not surface one (e.g.,\n * MCP completed responses that don't need conversation continuity).\n *\n * Values that fail {@link isSafeSessionId} (overlong, control characters,\n * non-string) are rejected and return `undefined` — retention falls back\n * to the previously retained id. The server is the authoritative issuer\n * but a compromised or buggy seller shouldn't be able to exhaust buyer\n * memory or inject control sequences into buyer debug logs.\n */\n getContextId(response: any): string | undefined {\n if (response == null) return undefined;\n\n // A2A sendMessage returns either a Task (has `contextId`) or a Message\n // (may have `contextId`). With the A2AClient SDK these arrive unwrapped\n // on `response.result`; some transports surface them directly on the\n // response envelope, so check both.\n if (response.result) {\n const fromResult = firstSafeSessionId(response.result.contextId, response.result.context_id);\n if (fromResult) return fromResult;\n }\n const fromEnvelope = firstSafeSessionId(response.contextId);\n if (fromEnvelope) return fromEnvelope;\n\n // MCP structuredContent / top-level AdCP envelope.\n const sc = response.structuredContent;\n if (sc) {\n const fromSc = firstSafeSessionId(sc.context_id);\n if (fromSc) return fromSc;\n }\n return firstSafeSessionId(response.context_id);\n }\n\n /**\n * Extract the A2A `taskId` for the task the server is tracking (or just\n * created) for this send. Retained across calls only while the last\n * response was non-terminal (working / input-required / submitted /\n * auth-required) so buyers can resume the same server-side task; cleared\n * by the caller on terminal responses.\n *\n * Same sanitization rules as {@link getContextId}: malformed ids return\n * `undefined`.\n */\n getTaskId(response: any): string | undefined {\n if (response == null) return undefined;\n\n if (response.result) {\n // A2A wrapped Task with AdCP payload — `artifact.metadata.adcp_task_id`\n // is the AdCP work handle (what the buyer polls with via AdCP\n // `tasks/get`). The transport-layer `result.id` is the A2A\n // Task.id (always pinned to one HTTP call per adcp-client#899's\n // two-lifecycle contract); using it as a polling key would\n // address the wrong thing. Prefer the AdCP handle when present;\n // fall back to `result.id` for non-AdCP A2A responses where no\n // artifact metadata was emitted. See adcp-client#973.\n if (response.result.kind === 'task') {\n const adcpHandle = extractAdcpTaskIdFromA2aTaskResult(response.result);\n if (adcpHandle) return adcpHandle;\n const taskKindId = firstSafeSessionId(response.result.id);\n if (taskKindId) return taskKindId;\n }\n const fromResult = firstSafeSessionId(response.result.taskId, response.result.id, response.result.task_id);\n if (fromResult) return fromResult;\n }\n const fromEnvelope = firstSafeSessionId(response.taskId);\n if (fromEnvelope) return fromEnvelope;\n\n const sc = response.structuredContent;\n if (sc) {\n const fromSc = firstSafeSessionId(sc.task_id);\n if (fromSc) return fromSc;\n }\n const fromFlat = firstSafeSessionId(response.task_id);\n if (fromFlat) return fromFlat;\n\n const hasOfficialPayload =\n response.structuredContent !== undefined || response.content !== undefined || response.result !== undefined;\n const data = hasOfficialPayload ? undefined : response.data;\n if (data != null && typeof data === 'object' && !Array.isArray(data)) {\n const fromData = firstSafeSessionId(data.task_id, data.taskId);\n if (fromData) return fromData;\n }\n return undefined;\n }\n\n private parseExpectedType(rawType: unknown): 'string' | 'number' | 'boolean' | 'object' | 'array' | undefined {\n if (typeof rawType === 'string') {\n const allowedTypes: string[] = ['string', 'number', 'boolean', 'object', 'array'];\n return allowedTypes.includes(rawType)\n ? (rawType as 'string' | 'number' | 'boolean' | 'object' | 'array')\n : undefined;\n }\n return undefined;\n }\n}\n\n// Export singleton instance\nexport const responseParser = new ProtocolResponseParser();\n"],"mappings":"AAMA,SAAS,oCAAoC;AAC7C;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,eAAAA,oBAAoC;AAE7C,MAAM,8BAAmD,oBAAI,IAAI,CAAC,GAAG,sBAAsB,UAAU,YAAY,CAAC;AAQlH,MAAM,wBAAwB;AAU9B,MAAM,qBAAqB;AAE3B,SAAS,gBAAgB,GAAyB;AAChD,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,MAAI,EAAE,WAAW,KAAK,EAAE,SAAS,sBAAuB,QAAO;AAC/D,SAAO,mBAAmB,KAAK,CAAC;AAClC;AAUA,SAAS,mCAAmC,QAAiC;AAC3E,MAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,EAAG,QAAO;AAClF,MAAI,OAAO,SAAS,OAAQ,QAAO;AAEnC,QAAM,iBAAiB,6BAA6B,MAAM;AAC1D,QAAM,qBAAqB,mBAAmB,gBAAgB,MAAM,SAAS,gBAAgB,MAAM,MAAM;AAEzG,QAAM,wBAAwB,CAAC,WAAmD;AAChF,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO,sBAAsB,uBAAuB,SAAS,qBAAqB;AAAA,EACpF;AAEA,QAAM,YAAY,OAAO;AACzB,MAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,aAAS,IAAI,UAAU,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACjD,YAAM,WAAW,UAAU,CAAC;AAC5B,UAAI,YAAY,QAAQ,OAAO,aAAa,YAAY,MAAM,QAAQ,QAAQ,EAAG;AACjF,YAAM,WAAY,SAAoC;AACtD,UAAI,YAAY,QAAQ,OAAO,aAAa,YAAY,MAAM,QAAQ,QAAQ,EAAG;AACjF,YAAM,IAAI;AACV,YAAM,SAAS,sBAAsB,mBAAmB,EAAE,cAAc,EAAE,YAAY,CAAC;AACvF,UAAI,OAAQ,QAAO;AAAA,IACrB;AAAA,EACF;AAEA,MAAI,mBAAoB,QAAO;AAE/B,QAAM,iBAAiB,OAAO;AAC9B,MAAI,kBAAkB,QAAQ,OAAO,mBAAmB,YAAY,CAAC,MAAM,QAAQ,cAAc,GAAG;AAClG,UAAM,IAAI;AACV,UAAM,SAAS,sBAAsB,mBAAmB,EAAE,cAAc,EAAE,YAAY,CAAC;AACvF,QAAI,OAAQ,QAAO;AAAA,EACrB;AAEA,SAAO;AACT;AAGA,SAAS,sBAAsB,YAA2C;AACxE,aAAW,KAAK,YAAY;AAC1B,QAAI,gBAAgB,CAAC,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,0BAA0B,SAAsC;AACvE,MAAI,WAAW,QAAQ,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,EAAG,QAAO;AACrF,QAAM,SAAS;AACf,MAAI,OAAO,OAAO,iBAAiB,SAAU,QAAO,OAAO;AAE3D,QAAM,SAAS,OAAO;AACtB,MAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1E,UAAM,WAAW;AACjB,UAAM,SAAS,OAAO,SAAS,WAAW,WAAW,SAAS,SAAS;AACvE,UAAMC,gBAAe,WAAW,UAAc,OAAO,OAAO,WAAW,EAAe,SAAS,MAAM;AACrG,UAAM,wBAAwB,OAAO,KAAK,QAAQ,EAAE,MAAM,SAAO,4BAA4B,IAAI,GAAG,CAAC;AACrG,UAAM,oBACJ,OAAO,SAAS,YAAY,YAC5B,OAAO,SAAS,WAAW,YAC3B,MAAM,QAAQ,SAAS,MAAM,KAC5B,SAAS,cAAc,QAAQ,OAAO,SAAS,eAAe,YAC9DA,iBAAgB;AAEnB,QAAI,qBAAqB,OAAO,SAAS,iBAAiB,UAAU;AAClE,aAAO,SAAS;AAAA,IAClB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,2BAA2B,OAAqD;AACvF,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AAC7C,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,QAAQ,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,EAAG;AACrE,UAAM,SAAS;AACf,QAAI,OAAO,SAAS,OAAQ;AAC5B,UAAM,OAAO,OAAO;AACpB,QAAI,QAAQ,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,EAAG;AACrE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,wBAAwB,QAAqC;AACpE,MAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,EAAG,QAAO;AAElF,QAAM,WAAW,6BAA6B,MAAM,GAAG;AACvD,QAAM,cAAc,0BAA0B,QAAQ;AACtD,MAAI,YAAa,QAAO;AAExB,QAAM,eAAe;AACrB,QAAM,cAAc,2BAA2B,aAAa,KAAK;AACjE,QAAM,iBAAiB,0BAA0B,WAAW;AAC5D,MAAI,eAAgB,QAAO;AAE3B,SAAO,0BAA0B,MAAM;AACzC;AAEA,SAAS,6BAA6B,SAAsC;AAC1E,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AACpC,aAAW,QAAQ,SAAS;AAC1B,QAAI,QAAQ,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,EAAG;AACrE,UAAM,OAAQ,KAA4C;AAC1D,QAAK,KAA4B,SAAS,UAAU,OAAO,SAAS,SAAU;AAC9E,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,YAAM,UAAU,0BAA0B,MAAM;AAChD,UAAI,QAAS,QAAO;AAAA,IACtB,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAKO,MAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA,EAIlC,eAAe,UAAwB;AAErC,QAAI,UAAU,QAAQ,QAAQ,UAAU,YAAY,gBAAgB;AAClE,aAAO;AAAA,IACT;AAGA,QAAI,UAAU,WAAW,YAAY,gBAAgB;AACnD,aAAO;AAAA,IACT;AAGA,WACE,UAAU,SAAS,mBACnB,UAAU,aAAa,UACvB,UAAU,mBAAmB,QAC7B,UAAU,wBAAwB;AAAA,EAEtC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,UAA6B;AAC7C,UAAM,WAAW,SAAS,WAAW,SAAS,YAAY,SAAS,UAAU;AAC7E,UAAM,QAAQ,SAAS,SAAS,SAAS;AACzC,UAAM,cAAc,SAAS,WAAW,SAAS,WAAW,SAAS;AAErE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,cAAc,KAAK,kBAAkB,SAAS,iBAAiB,SAAS,IAAI;AAAA,MAC5E;AAAA,MACA,UAAU,SAAS,aAAa;AAAA,MAChC,YAAY,SAAS;AAAA,MACrB,SAAS,SAAS,WAAW,SAAS;AAAA,IACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,UAAkC;AAQ1C,UAAM,yBAAyB,mCAAmC,UAAU,MAAM;AAClF,QAAI,uBAAwB,QAAO;AAMnC,QAAI,aAAa,UAAU,QAAQ,QAAQ,KAAK,GAAG;AACjD,aAAO,SAAS,OAAO,OAAO;AAAA,IAChC;AAOA,UAAM,qBACJ,UAAU,sBAAsB,UAAa,UAAU,YAAY,UAAa,UAAU,WAAW;AACvG,UAAM,OAAO,qBAAqB,SAAY,UAAU;AACxD,UAAM,iBACJ,QAAQ,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,IAC3D,iCAAiC,IAAI,IACrC;AACN,QAAI,eAAgB,QAAO;AAG3B,QAAI,aAAa,UAAU,MAAM,GAAG;AAClC,aAAO,SAAS;AAAA,IAClB;AAUA,UAAM,KAAK,UAAU;AACrB,QAAI,IAAI,UAAU,aAAa,GAAG,MAAM,GAAG;AACzC,YAAM,aAAa,iCAAiC,EAAE;AACtD,UAAI,WAAY,QAAO;AAAA,IAEzB;AAGA,QAAI,UAAU,YAAY,MAAM;AAC9B,aAAO,YAAY;AAAA,IACrB;AAGA,QAAI,UAAU,qBAAsB,UAAU,WAAW,CAAC,UAAU,SAAU;AAC5E,aAAO,YAAY;AAAA,IACrB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,YAAY,UAAoC;AAC9C,QAAI,YAAY,KAAM,QAAO;AAG7B,QAAI,SAAS,UAAU,OAAO,SAAS,OAAO,aAAa,WAAW;AACpE,aAAO,SAAS,OAAO;AAAA,IACzB;AAGA,QAAI,SAAS,qBAAqB,OAAO,SAAS,kBAAkB,aAAa,WAAW;AAC1F,aAAO,SAAS,kBAAkB;AAAA,IACpC;AAGA,QAAI,OAAO,SAAS,aAAa,WAAW;AAC1C,aAAO,SAAS;AAAA,IAClB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,eAAe,UAAmC;AAChD,QAAI,YAAY,KAAM,QAAO;AAG7B,UAAM,aAAa,wBAAwB,SAAS,MAAM;AAC1D,QAAI,WAAY,QAAO;AAGvB,QAAI,OAAO,SAAS,mBAAmB,iBAAiB,UAAU;AAChE,aAAO,SAAS,kBAAkB;AAAA,IACpC;AAGA,UAAM,qBAAqB,6BAA6B,SAAS,OAAO;AACxE,QAAI,mBAAoB,QAAO;AAG/B,UAAM,cAAc,0BAA0B,SAAS,IAAI;AAC3D,QAAI,YAAa,QAAO;AAGxB,QAAI,OAAO,SAAS,iBAAiB,UAAU;AAC7C,aAAO,SAAS;AAAA,IAClB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,aAAa,UAAmC;AAC9C,QAAI,YAAY,KAAM,QAAO;AAM7B,QAAI,SAAS,QAAQ;AACnB,YAAM,aAAa,mBAAmB,SAAS,OAAO,WAAW,SAAS,OAAO,UAAU;AAC3F,UAAI,WAAY,QAAO;AAAA,IACzB;AACA,UAAM,eAAe,mBAAmB,SAAS,SAAS;AAC1D,QAAI,aAAc,QAAO;AAGzB,UAAM,KAAK,SAAS;AACpB,QAAI,IAAI;AACN,YAAM,SAAS,mBAAmB,GAAG,UAAU;AAC/C,UAAI,OAAQ,QAAO;AAAA,IACrB;AACA,WAAO,mBAAmB,SAAS,UAAU;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,UAAU,UAAmC;AAC3C,QAAI,YAAY,KAAM,QAAO;AAE7B,QAAI,SAAS,QAAQ;AASnB,UAAI,SAAS,OAAO,SAAS,QAAQ;AACnC,cAAM,aAAa,mCAAmC,SAAS,MAAM;AACrE,YAAI,WAAY,QAAO;AACvB,cAAM,aAAa,mBAAmB,SAAS,OAAO,EAAE;AACxD,YAAI,WAAY,QAAO;AAAA,MACzB;AACA,YAAM,aAAa,mBAAmB,SAAS,OAAO,QAAQ,SAAS,OAAO,IAAI,SAAS,OAAO,OAAO;AACzG,UAAI,WAAY,QAAO;AAAA,IACzB;AACA,UAAM,eAAe,mBAAmB,SAAS,MAAM;AACvD,QAAI,aAAc,QAAO;AAEzB,UAAM,KAAK,SAAS;AACpB,QAAI,IAAI;AACN,YAAM,SAAS,mBAAmB,GAAG,OAAO;AAC5C,UAAI,OAAQ,QAAO;AAAA,IACrB;AACA,UAAM,WAAW,mBAAmB,SAAS,OAAO;AACpD,QAAI,SAAU,QAAO;AAErB,UAAM,qBACJ,SAAS,sBAAsB,UAAa,SAAS,YAAY,UAAa,SAAS,WAAW;AACpG,UAAM,OAAO,qBAAqB,SAAY,SAAS;AACvD,QAAI,QAAQ,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AACpE,YAAM,WAAW,mBAAmB,KAAK,SAAS,KAAK,MAAM;AAC7D,UAAI,SAAU,QAAO;AAAA,IACvB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,SAAoF;AAC5G,QAAI,OAAO,YAAY,UAAU;AAC/B,YAAM,eAAyB,CAAC,UAAU,UAAU,WAAW,UAAU,OAAO;AAChF,aAAO,aAAa,SAAS,OAAO,IAC/B,UACD;AAAA,IACN;AACA,WAAO;AAAA,EACT;AACF;AAGO,MAAM,iBAAiB,IAAI,uBAAuB;","names":["ADCP_STATUS","isAdcpStatus"]}
|
|
@@ -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 { getBestUnionErrors } from "../utils/union-errors.mjs";
|
|
8
2
|
import { prepareResponseForSchemaValidation, TOOL_RESPONSE_SCHEMAS } from "../utils/response-schemas.mjs";
|
|
9
3
|
import { injectLegacyEnvelopeStatus } from "../utils/envelope-status-compat.mjs";
|