@adcp/sdk 14.0.0-rc.41 → 14.0.0-rc.42

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.
Files changed (104) hide show
  1. package/bin/adcp-grade.js +4 -3
  2. package/bin/adcp-storyboard-summary.js +1 -1
  3. package/bin/adcp.js +4 -6
  4. package/dist/lib/conformance/index.d.mts +2 -0
  5. package/dist/lib/conformance/index.d.ts +2 -0
  6. package/dist/lib/conformance/index.js +7 -0
  7. package/dist/lib/conformance/index.mjs +8 -0
  8. package/dist/lib/conformance/targeting.d.mts +72 -0
  9. package/dist/lib/conformance/targeting.d.ts +72 -0
  10. package/dist/lib/conformance/targeting.js +163 -0
  11. package/dist/lib/conformance/targeting.mjs +137 -0
  12. package/dist/lib/core/AgentClient.d.mts +27 -1
  13. package/dist/lib/core/AgentClient.d.ts +27 -1
  14. package/dist/lib/core/AgentClient.js +41 -2
  15. package/dist/lib/core/AgentClient.mjs +39 -1
  16. package/dist/lib/errors/index.d.mts +4 -1
  17. package/dist/lib/errors/index.d.ts +4 -1
  18. package/dist/lib/errors/index.js +6 -1
  19. package/dist/lib/errors/index.mjs +6 -1
  20. package/dist/lib/index.d.mts +1 -1
  21. package/dist/lib/index.d.ts +1 -1
  22. package/dist/lib/index.js +2 -0
  23. package/dist/lib/index.mjs +3 -1
  24. package/dist/lib/media-buy/action-assessment.js +7 -0
  25. package/dist/lib/media-buy/action-assessment.mjs +7 -0
  26. package/dist/lib/media-buy/available-actions.d.mts +8 -1
  27. package/dist/lib/media-buy/available-actions.d.ts +8 -1
  28. package/dist/lib/media-buy/available-actions.js +18 -3
  29. package/dist/lib/media-buy/available-actions.mjs +15 -2
  30. package/dist/lib/media-buy/index.d.mts +1 -0
  31. package/dist/lib/media-buy/index.d.ts +1 -0
  32. package/dist/lib/media-buy/preflight.js +23 -12
  33. package/dist/lib/media-buy/preflight.mjs +25 -13
  34. package/dist/lib/protocols/transportDiagnostics.d.mts +2 -0
  35. package/dist/lib/protocols/transportDiagnostics.d.ts +2 -0
  36. package/dist/lib/protocols/transportDiagnostics.js +60 -20
  37. package/dist/lib/protocols/transportDiagnostics.mjs +61 -21
  38. package/dist/lib/reporting/ledger/handler.js +67 -11
  39. package/dist/lib/reporting/ledger/handler.mjs +69 -12
  40. package/dist/lib/reporting/ledger/producer.js +4 -9
  41. package/dist/lib/reporting/ledger/producer.mjs +4 -9
  42. package/dist/lib/reporting/ledger/status-ingest.js +1 -1
  43. package/dist/lib/reporting/ledger/status-ingest.mjs +1 -1
  44. package/dist/lib/reporting/reconciliation.d.mts +4 -9
  45. package/dist/lib/reporting/reconciliation.d.ts +4 -9
  46. package/dist/lib/reporting/reconciliation.js +5 -5
  47. package/dist/lib/reporting/reconciliation.mjs +5 -5
  48. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  49. package/dist/lib/server/decisioning/runtime/from-platform.js +16 -3
  50. package/dist/lib/server/decisioning/runtime/from-platform.mjs +16 -3
  51. package/dist/lib/server/index.d.mts +1 -0
  52. package/dist/lib/server/index.d.ts +1 -0
  53. package/dist/lib/server/media-buy-actions.js +3 -1
  54. package/dist/lib/server/media-buy-actions.mjs +3 -1
  55. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.mts +118 -0
  56. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.ts +118 -0
  57. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.js +180 -0
  58. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.mjs +144 -0
  59. package/dist/lib/testing/storyboard/request-signing/builder.d.mts +21 -1
  60. package/dist/lib/testing/storyboard/request-signing/builder.d.ts +21 -1
  61. package/dist/lib/testing/storyboard/request-signing/builder.js +22 -0
  62. package/dist/lib/testing/storyboard/request-signing/builder.mjs +22 -0
  63. package/dist/lib/testing/storyboard/request-signing/grader.d.mts +5 -6
  64. package/dist/lib/testing/storyboard/request-signing/grader.d.ts +5 -6
  65. package/dist/lib/testing/storyboard/request-signing/grader.js +79 -8
  66. package/dist/lib/testing/storyboard/request-signing/grader.mjs +79 -8
  67. package/dist/lib/testing/storyboard/request-signing/index.d.mts +1 -0
  68. package/dist/lib/testing/storyboard/request-signing/index.d.ts +1 -0
  69. package/dist/lib/testing/storyboard/request-signing/index.js +7 -0
  70. package/dist/lib/testing/storyboard/request-signing/index.mjs +8 -0
  71. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.mts +10 -29
  72. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.ts +10 -29
  73. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.js +49 -5
  74. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +39 -5
  75. package/dist/lib/testing/storyboard/runner.js +28 -2
  76. package/dist/lib/testing/storyboard/runner.mjs +18 -2
  77. package/dist/lib/testing/storyboard/types.d.mts +8 -19
  78. package/dist/lib/testing/storyboard/types.d.ts +8 -19
  79. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  80. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  81. package/dist/lib/types/index.d.mts +11 -2
  82. package/dist/lib/types/index.d.ts +11 -2
  83. package/dist/lib/types/schemas.generated.js +17 -0
  84. package/dist/lib/types/schemas.generated.mjs +17 -0
  85. package/dist/lib/utils/reporting-status-response.js +2 -2
  86. package/dist/lib/utils/reporting-status-response.mjs +2 -2
  87. package/dist/lib/validation/schema-loader.js +13 -6
  88. package/dist/lib/validation/schema-loader.mjs +13 -6
  89. package/dist/lib/version.d.mts +3 -3
  90. package/dist/lib/version.d.ts +3 -3
  91. package/dist/lib/version.js +3 -3
  92. package/dist/lib/version.mjs +3 -3
  93. package/docs/TYPE-SUMMARY.md +9 -1
  94. package/docs/guides/EXISTING-PLATFORM.md +61 -33
  95. package/docs/guides/MEDIA-BUY-3.2-COMPATIBILITY.md +27 -1
  96. package/docs/guides/REPORTING-LEDGER.md +3 -1
  97. package/docs/guides/REPORTING-RECONCILIATION.md +1 -1
  98. package/docs/guides/VALIDATE-YOUR-AGENT.md +4 -4
  99. package/docs/llms.txt +2 -2
  100. package/docs/migration-14.x-rc-worksheet.md +4 -4
  101. package/examples/existing-platform-thin.ts +29 -1
  102. package/examples/targeting-input-existing-platform.ts +2 -8
  103. package/package.json +1 -1
  104. package/skills/build-seller-agent/specialisms/signed-requests.md +1 -1
package/bin/adcp-grade.js CHANGED
@@ -43,7 +43,8 @@ Options:
43
43
  --transport <mode> \`mcp\` (default) wraps each vector body in a
44
44
  JSON-RPC tools/call envelope and posts to the
45
45
  agent's MCP mount (see #612); \`raw\` posts to
46
- per-operation AdCP endpoints (REST-binding agents).
46
+ per-operation AdCP endpoints (REST-binding agents);
47
+ \`a2a\` signs the official A2A client's request.
47
48
  --timeout <ms> Per-probe timeout (default 10000)
48
49
  --json Emit the full GradeReport as JSON
49
50
  -h, --help Show this help
@@ -199,8 +200,8 @@ async function runRequestSigningGrader(args) {
199
200
  break;
200
201
  case '--transport': {
201
202
  const mode = args[++i];
202
- if (mode !== 'raw' && mode !== 'mcp') {
203
- console.error(`ERROR: --transport must be \"raw\" or \"mcp\", got \"${mode}\"\n`);
203
+ if (mode !== 'raw' && mode !== 'mcp' && mode !== 'a2a') {
204
+ console.error(`ERROR: --transport must be \"raw\", \"mcp\", or \"a2a\", got \"${mode}\"\n`);
204
205
  process.exit(2);
205
206
  }
206
207
  options.transport = mode;
@@ -350,7 +350,7 @@ function formatStepVerdictLines(step, options = {}) {
350
350
  return [`${step?.passed ? '✅ Passed' : '❌ Failed'}${suffix}`];
351
351
  }
352
352
 
353
- const SIGNING_TRANSPORTS = ['raw', 'mcp'];
353
+ const SIGNING_TRANSPORTS = ['raw', 'mcp', 'a2a'];
354
354
 
355
355
  // Tokens only ever passed as a (rejected) value for a boolean flag — no
356
356
  // storyboard id or agent URL looks like these, so treating them as a misuse
package/bin/adcp.js CHANGED
@@ -2180,17 +2180,15 @@ WEBHOOK OPTIONS:
2180
2180
  HTTP-on-the-wire — spec-compliant.
2181
2181
 
2182
2182
  REQUEST-SIGNING VECTOR OPTIONS (signed_requests storyboard):
2183
- --signing-transport raw|mcp How the RFC 9421 conformance vectors are
2183
+ --signing-transport raw|mcp|a2a How the RFC 9421 conformance vectors are
2184
2184
  framed on the wire. NOT the same as
2185
2185
  --transport/--protocol, which selects how the
2186
2186
  storyboard itself talks to the agent. Default:
2187
2187
  inferred from the resolved protocol — an MCP
2188
2188
  run wraps each vector in a tools/call envelope
2189
- (mcp); an A2A run reports the vectors
2190
- signing_transport_unavailable (COVERAGE
2191
- UNAVAILABLE; the track cannot pass) because
2192
- the fixtures have no A2A framing. Pass raw for
2193
- agents that
2189
+ (mcp); an A2A run signs the exact request the
2190
+ official A2A client emits after Agent Card
2191
+ discovery. Pass raw for agents that
2194
2192
  expose AdCP tools as per-operation HTTP
2195
2193
  endpoints. Mirrors
2196
2194
  \`adcp grade request-signing --transport\`.
@@ -21,6 +21,8 @@
21
21
  export { runConformance } from './runConformance.mjs';
22
22
  export { runWebhookConformance } from './webhook.mjs';
23
23
  export { seedFixtures } from './seeder.mjs';
24
+ export { TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS, buildTargetingInputConformanceVectors, runTargetingInputConformance, } from './targeting.mjs';
25
+ export type { TargetingConformanceOutcome, TargetingConformanceOperation, TargetingDimensionSample, TargetingDimensionSamples, TargetingInputConformanceAdapter, TargetingInputConformanceCaseResult, TargetingInputConformanceObservation, TargetingInputConformanceOptions, TargetingInputConformanceReport, TargetingInputConformanceVector, } from './targeting.mjs';
24
26
  export type { SeedOptions, SeedResult, SeederName, SeedWarning } from './seeder.mjs';
25
27
  export type { ConformanceSchemaOptions } from './schemaLoader.mjs';
26
28
  export { STATELESS_TIER_TOOLS, REFERENTIAL_STATELESS_TOOLS, UPDATE_TIER_TOOLS, COMPACT_STATELESS_TIER_TOOLS, COMPACT_UPDATE_TIER_TOOLS, COMPACT_LIFECYCLE_TOOLS, DEFAULT_TOOLS, DEFAULT_TOOLS_WITH_UPDATES, } from './types.mjs';
@@ -21,6 +21,8 @@
21
21
  export { runConformance } from './runConformance';
22
22
  export { runWebhookConformance } from './webhook';
23
23
  export { seedFixtures } from './seeder';
24
+ export { TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS, buildTargetingInputConformanceVectors, runTargetingInputConformance, } from './targeting';
25
+ export type { TargetingConformanceOutcome, TargetingConformanceOperation, TargetingDimensionSample, TargetingDimensionSamples, TargetingInputConformanceAdapter, TargetingInputConformanceCaseResult, TargetingInputConformanceObservation, TargetingInputConformanceOptions, TargetingInputConformanceReport, TargetingInputConformanceVector, } from './targeting';
24
26
  export type { SeedOptions, SeedResult, SeederName, SeedWarning } from './seeder';
25
27
  export type { ConformanceSchemaOptions } from './schemaLoader';
26
28
  export { STATELESS_TIER_TOOLS, REFERENTIAL_STATELESS_TOOLS, UPDATE_TIER_TOOLS, COMPACT_STATELESS_TIER_TOOLS, COMPACT_UPDATE_TIER_TOOLS, COMPACT_LIFECYCLE_TOOLS, DEFAULT_TOOLS, DEFAULT_TOOLS_WITH_UPDATES, } from './types';
@@ -25,8 +25,11 @@ __export(conformance_exports, {
25
25
  DEFAULT_TOOLS_WITH_UPDATES: () => import_types.DEFAULT_TOOLS_WITH_UPDATES,
26
26
  REFERENTIAL_STATELESS_TOOLS: () => import_types.REFERENTIAL_STATELESS_TOOLS,
27
27
  STATELESS_TIER_TOOLS: () => import_types.STATELESS_TIER_TOOLS,
28
+ TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS: () => import_targeting.TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS,
28
29
  UPDATE_TIER_TOOLS: () => import_types.UPDATE_TIER_TOOLS,
30
+ buildTargetingInputConformanceVectors: () => import_targeting.buildTargetingInputConformanceVectors,
29
31
  runConformance: () => import_runConformance.runConformance,
32
+ runTargetingInputConformance: () => import_targeting.runTargetingInputConformance,
30
33
  runWebhookConformance: () => import_webhook.runWebhookConformance,
31
34
  seedFixtures: () => import_seeder.seedFixtures
32
35
  });
@@ -34,6 +37,7 @@ module.exports = __toCommonJS(conformance_exports);
34
37
  var import_runConformance = require('./runConformance.js');
35
38
  var import_webhook = require('./webhook.js');
36
39
  var import_seeder = require('./seeder.js');
40
+ var import_targeting = require('./targeting.js');
37
41
  var import_types = require('./types.js');
38
42
  // Annotate the CommonJS export names for ESM import in node:
39
43
  0 && (module.exports = {
@@ -44,8 +48,11 @@ var import_types = require('./types.js');
44
48
  DEFAULT_TOOLS_WITH_UPDATES,
45
49
  REFERENTIAL_STATELESS_TOOLS,
46
50
  STATELESS_TIER_TOOLS,
51
+ TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS,
47
52
  UPDATE_TIER_TOOLS,
53
+ buildTargetingInputConformanceVectors,
48
54
  runConformance,
55
+ runTargetingInputConformance,
49
56
  runWebhookConformance,
50
57
  seedFixtures
51
58
  });
@@ -1,6 +1,11 @@
1
1
  import { runConformance } from "./runConformance.mjs";
2
2
  import { runWebhookConformance } from "./webhook.mjs";
3
3
  import { seedFixtures } from "./seeder.mjs";
4
+ import {
5
+ TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS,
6
+ buildTargetingInputConformanceVectors,
7
+ runTargetingInputConformance
8
+ } from "./targeting.mjs";
4
9
  import {
5
10
  STATELESS_TIER_TOOLS,
6
11
  REFERENTIAL_STATELESS_TOOLS,
@@ -19,8 +24,11 @@ export {
19
24
  DEFAULT_TOOLS_WITH_UPDATES,
20
25
  REFERENTIAL_STATELESS_TOOLS,
21
26
  STATELESS_TIER_TOOLS,
27
+ TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS,
22
28
  UPDATE_TIER_TOOLS,
29
+ buildTargetingInputConformanceVectors,
23
30
  runConformance,
31
+ runTargetingInputConformance,
24
32
  runWebhookConformance,
25
33
  seedFixtures
26
34
  };
@@ -0,0 +1,72 @@
1
+ import type { TargetingOverlayInput } from '../types/core.generated.mjs';
2
+ export type TargetingConformanceOperation = 'create' | 'update';
3
+ export type TargetingConformanceOutcome = 'accepted' | 'rejected';
4
+ export interface TargetingDimensionSample<T> {
5
+ /** Strict configured/stored value used as the vector baseline. */
6
+ initialValue: NonNullable<T>;
7
+ /** Distinct valid request value used to prove complete replacement. */
8
+ replacementValue: NonNullable<T>;
9
+ /** Canonical readback value when it differs from the request value. */
10
+ expectedReplacementValue?: NonNullable<T>;
11
+ /** Whole canonical readback state for cross-dimension materialization. */
12
+ expectedReplacementState?: Record<string, unknown>;
13
+ /** Override for products that cannot execute a clear against inherent scope. */
14
+ expectedNullOutcome?: TargetingConformanceOutcome;
15
+ /** Override for replacements that require renegotiation in the selected fixture. */
16
+ expectedReplacementOutcome?: TargetingConformanceOutcome;
17
+ }
18
+ export type TargetingDimensionSamples = {
19
+ [K in keyof TargetingOverlayInput]?: TargetingDimensionSample<TargetingOverlayInput[K]>;
20
+ };
21
+ export interface TargetingInputConformanceVector {
22
+ id: string;
23
+ operation: TargetingConformanceOperation;
24
+ dimension?: keyof TargetingOverlayInput & string;
25
+ baseline?: Record<string, unknown>;
26
+ /** Present request overlay; `{}` means this dimension was omitted. */
27
+ input?: Record<string, unknown>;
28
+ expectedOutcome: TargetingConformanceOutcome;
29
+ /** Accepted strict state, unchanged update state, or absent state after a rejected create. */
30
+ expectedState: Record<string, unknown> | undefined;
31
+ description: string;
32
+ }
33
+ export interface TargetingInputConformanceObservation {
34
+ outcome: TargetingConformanceOutcome;
35
+ /** Strict durable/readback state after the attempted operation. */
36
+ state?: Record<string, unknown>;
37
+ /** Exact request-only overlay observed at the seller/provider dispatch seam. */
38
+ dispatchedInput?: Record<string, unknown>;
39
+ }
40
+ export interface TargetingInputConformanceAdapter {
41
+ create(vector: TargetingInputConformanceVector): Promise<TargetingInputConformanceObservation>;
42
+ update(vector: TargetingInputConformanceVector): Promise<TargetingInputConformanceObservation>;
43
+ }
44
+ export interface TargetingInputConformanceOptions {
45
+ /** Override when a seller has a documented canonical ordering/materialization policy. */
46
+ compareState?: (observed: Record<string, unknown> | undefined, expected: Record<string, unknown> | undefined, vector: TargetingInputConformanceVector) => boolean;
47
+ }
48
+ export interface TargetingInputConformanceCaseResult {
49
+ id: string;
50
+ passed: boolean;
51
+ failures: string[];
52
+ vector: TargetingInputConformanceVector;
53
+ observation?: TargetingInputConformanceObservation;
54
+ }
55
+ export interface TargetingInputConformanceReport {
56
+ passed: boolean;
57
+ cases: TargetingInputConformanceCaseResult[];
58
+ }
59
+ /**
60
+ * Generate create/update omit, null, and value vectors for every supplied
61
+ * targeting dimension. Samples are schema-typed and share one multi-dimension
62
+ * baseline so the corpus catches adapters that clear unrelated omitted axes.
63
+ */
64
+ export declare function buildTargetingInputConformanceVectors(samples: TargetingDimensionSamples): TargetingInputConformanceVector[];
65
+ /**
66
+ * Cross-dimension vectors requested by the targeting command-state contract:
67
+ * an omitted region axis is preserved, and an invalid combined projection is
68
+ * rejected without mutating either stored axis.
69
+ */
70
+ export declare const TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS: readonly TargetingInputConformanceVector[];
71
+ /** Run vectors through distinct create and update adapter seams. */
72
+ export declare function runTargetingInputConformance(vectors: readonly TargetingInputConformanceVector[], adapter: TargetingInputConformanceAdapter, options?: TargetingInputConformanceOptions): Promise<TargetingInputConformanceReport>;
@@ -0,0 +1,72 @@
1
+ import type { TargetingOverlayInput } from '../types/core.generated';
2
+ export type TargetingConformanceOperation = 'create' | 'update';
3
+ export type TargetingConformanceOutcome = 'accepted' | 'rejected';
4
+ export interface TargetingDimensionSample<T> {
5
+ /** Strict configured/stored value used as the vector baseline. */
6
+ initialValue: NonNullable<T>;
7
+ /** Distinct valid request value used to prove complete replacement. */
8
+ replacementValue: NonNullable<T>;
9
+ /** Canonical readback value when it differs from the request value. */
10
+ expectedReplacementValue?: NonNullable<T>;
11
+ /** Whole canonical readback state for cross-dimension materialization. */
12
+ expectedReplacementState?: Record<string, unknown>;
13
+ /** Override for products that cannot execute a clear against inherent scope. */
14
+ expectedNullOutcome?: TargetingConformanceOutcome;
15
+ /** Override for replacements that require renegotiation in the selected fixture. */
16
+ expectedReplacementOutcome?: TargetingConformanceOutcome;
17
+ }
18
+ export type TargetingDimensionSamples = {
19
+ [K in keyof TargetingOverlayInput]?: TargetingDimensionSample<TargetingOverlayInput[K]>;
20
+ };
21
+ export interface TargetingInputConformanceVector {
22
+ id: string;
23
+ operation: TargetingConformanceOperation;
24
+ dimension?: keyof TargetingOverlayInput & string;
25
+ baseline?: Record<string, unknown>;
26
+ /** Present request overlay; `{}` means this dimension was omitted. */
27
+ input?: Record<string, unknown>;
28
+ expectedOutcome: TargetingConformanceOutcome;
29
+ /** Accepted strict state, unchanged update state, or absent state after a rejected create. */
30
+ expectedState: Record<string, unknown> | undefined;
31
+ description: string;
32
+ }
33
+ export interface TargetingInputConformanceObservation {
34
+ outcome: TargetingConformanceOutcome;
35
+ /** Strict durable/readback state after the attempted operation. */
36
+ state?: Record<string, unknown>;
37
+ /** Exact request-only overlay observed at the seller/provider dispatch seam. */
38
+ dispatchedInput?: Record<string, unknown>;
39
+ }
40
+ export interface TargetingInputConformanceAdapter {
41
+ create(vector: TargetingInputConformanceVector): Promise<TargetingInputConformanceObservation>;
42
+ update(vector: TargetingInputConformanceVector): Promise<TargetingInputConformanceObservation>;
43
+ }
44
+ export interface TargetingInputConformanceOptions {
45
+ /** Override when a seller has a documented canonical ordering/materialization policy. */
46
+ compareState?: (observed: Record<string, unknown> | undefined, expected: Record<string, unknown> | undefined, vector: TargetingInputConformanceVector) => boolean;
47
+ }
48
+ export interface TargetingInputConformanceCaseResult {
49
+ id: string;
50
+ passed: boolean;
51
+ failures: string[];
52
+ vector: TargetingInputConformanceVector;
53
+ observation?: TargetingInputConformanceObservation;
54
+ }
55
+ export interface TargetingInputConformanceReport {
56
+ passed: boolean;
57
+ cases: TargetingInputConformanceCaseResult[];
58
+ }
59
+ /**
60
+ * Generate create/update omit, null, and value vectors for every supplied
61
+ * targeting dimension. Samples are schema-typed and share one multi-dimension
62
+ * baseline so the corpus catches adapters that clear unrelated omitted axes.
63
+ */
64
+ export declare function buildTargetingInputConformanceVectors(samples: TargetingDimensionSamples): TargetingInputConformanceVector[];
65
+ /**
66
+ * Cross-dimension vectors requested by the targeting command-state contract:
67
+ * an omitted region axis is preserved, and an invalid combined projection is
68
+ * rejected without mutating either stored axis.
69
+ */
70
+ export declare const TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS: readonly TargetingInputConformanceVector[];
71
+ /** Run vectors through distinct create and update adapter seams. */
72
+ export declare function runTargetingInputConformance(vectors: readonly TargetingInputConformanceVector[], adapter: TargetingInputConformanceAdapter, options?: TargetingInputConformanceOptions): Promise<TargetingInputConformanceReport>;
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var targeting_exports = {};
20
+ __export(targeting_exports, {
21
+ TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS: () => TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS,
22
+ buildTargetingInputConformanceVectors: () => buildTargetingInputConformanceVectors,
23
+ runTargetingInputConformance: () => runTargetingInputConformance
24
+ });
25
+ module.exports = __toCommonJS(targeting_exports);
26
+ var import_node_util = require("node:util");
27
+ function buildTargetingInputConformanceVectors(samples) {
28
+ const entries = Object.entries(samples).filter(([, sample]) => sample !== void 0);
29
+ const baseline = Object.fromEntries(entries.map(([dimension, sample]) => [dimension, clone(sample.initialValue)]));
30
+ const vectors = [];
31
+ for (const [dimension, sample] of entries) {
32
+ const clearedState = withoutKey(baseline, dimension);
33
+ const replacementState = sample.expectedReplacementState ? clone(sample.expectedReplacementState) : {
34
+ ...clone(baseline),
35
+ [dimension]: clone(sample.expectedReplacementValue ?? sample.replacementValue)
36
+ };
37
+ for (const operation of ["create", "update"]) {
38
+ const omittedMeaning = operation === "create" ? "inherits configured/product defaults" : "preserves stored state";
39
+ const nullOutcome = sample.expectedNullOutcome ?? "accepted";
40
+ const replacementOutcome = sample.expectedReplacementOutcome ?? "accepted";
41
+ const rejectedState = operation === "create" ? void 0 : baseline;
42
+ vectors.push(
43
+ {
44
+ id: `${operation}/${dimension}/omitted`,
45
+ operation,
46
+ dimension,
47
+ baseline: clone(baseline),
48
+ input: {},
49
+ expectedOutcome: "accepted",
50
+ expectedState: clone(baseline),
51
+ description: `${operation}: omitted ${dimension} ${omittedMeaning}`
52
+ },
53
+ {
54
+ id: `${operation}/${dimension}/null`,
55
+ operation,
56
+ dimension,
57
+ baseline: clone(baseline),
58
+ input: { [dimension]: null },
59
+ expectedOutcome: nullOutcome,
60
+ expectedState: clone(nullOutcome === "accepted" ? clearedState : rejectedState),
61
+ description: `${operation}: null ${dimension} clears/suppresses only that effective dimension`
62
+ },
63
+ {
64
+ id: `${operation}/${dimension}/value`,
65
+ operation,
66
+ dimension,
67
+ baseline: clone(baseline),
68
+ input: { [dimension]: clone(sample.replacementValue) },
69
+ expectedOutcome: replacementOutcome,
70
+ expectedState: clone(replacementOutcome === "accepted" ? replacementState : rejectedState),
71
+ description: `${operation}: a non-null ${dimension} value replaces only that complete dimension`
72
+ }
73
+ );
74
+ }
75
+ }
76
+ return vectors;
77
+ }
78
+ const TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS = deepFreeze([
79
+ {
80
+ id: "update/geo_countries/preserve-compatible-regions",
81
+ operation: "update",
82
+ baseline: { geo_countries: ["US"], geo_regions: ["US-NY"] },
83
+ input: { geo_countries: ["US", "CA"] },
84
+ expectedOutcome: "accepted",
85
+ expectedState: { geo_countries: ["US", "CA"], geo_regions: ["US-NY"] },
86
+ description: "Changing countries preserves an omitted compatible geo_regions dimension."
87
+ },
88
+ {
89
+ id: "update/geo_countries/reject-incompatible-preserved-regions",
90
+ operation: "update",
91
+ baseline: { geo_countries: ["US"], geo_regions: ["US-NY"] },
92
+ input: { geo_countries: ["CA"] },
93
+ expectedOutcome: "rejected",
94
+ expectedState: { geo_countries: ["US"], geo_regions: ["US-NY"] },
95
+ description: "An invalid country/region result is rejected atomically instead of clearing the omitted region axis."
96
+ }
97
+ ]);
98
+ async function runTargetingInputConformance(vectors, adapter, options = {}) {
99
+ if (vectors.length === 0) throw new TypeError("Targeting conformance requires at least one vector.");
100
+ const compareState = options.compareState ?? defaultStateComparison;
101
+ const cases = [];
102
+ for (const sourceVector of vectors) {
103
+ const vector = clone(sourceVector);
104
+ const failures = [];
105
+ try {
106
+ const observation = await adapter[vector.operation](clone(vector));
107
+ if (observation.outcome !== vector.expectedOutcome) {
108
+ failures.push(`expected ${vector.expectedOutcome}, observed ${observation.outcome}`);
109
+ }
110
+ if (!compareState(observation.state, vector.expectedState, vector)) {
111
+ failures.push(
112
+ `strict state mismatch: expected ${formatDiagnosticValue(vector.expectedState)}, observed ${formatDiagnosticValue(observation.state)}`
113
+ );
114
+ }
115
+ if (containsNull(observation.state)) {
116
+ failures.push("durable/readback state retained a request-only null command");
117
+ }
118
+ if (observation.outcome === "accepted" && !(0, import_node_util.isDeepStrictEqual)(observation.dispatchedInput, vector.input)) {
119
+ failures.push(
120
+ `dispatch changed the request overlay: expected ${formatDiagnosticValue(vector.input)}, observed ${formatDiagnosticValue(observation.dispatchedInput)}`
121
+ );
122
+ }
123
+ cases.push({ id: vector.id, passed: failures.length === 0, failures, vector, observation });
124
+ } catch (error) {
125
+ const name = error instanceof Error ? error.name : typeof error;
126
+ failures.push(`adapter execution failed (${name}); inspect adapter logs for details`);
127
+ cases.push({ id: vector.id, passed: false, failures, vector });
128
+ }
129
+ }
130
+ return { passed: cases.every((result) => result.passed), cases };
131
+ }
132
+ function defaultStateComparison(observed, expected) {
133
+ return (0, import_node_util.isDeepStrictEqual)(normalizeEmptyState(observed), normalizeEmptyState(expected));
134
+ }
135
+ function normalizeEmptyState(state) {
136
+ return state && Object.keys(state).length === 0 ? void 0 : state;
137
+ }
138
+ function containsNull(value) {
139
+ if (value === null) return true;
140
+ if (Array.isArray(value)) return value.some(containsNull);
141
+ return typeof value === "object" && Object.values(value).some(containsNull);
142
+ }
143
+ function withoutKey(state, key) {
144
+ const result = Object.fromEntries(Object.entries(state).filter(([candidate]) => candidate !== key));
145
+ return Object.keys(result).length === 0 ? void 0 : result;
146
+ }
147
+ function clone(value) {
148
+ return structuredClone(value);
149
+ }
150
+ function formatDiagnosticValue(value) {
151
+ return value === void 0 ? "undefined" : JSON.stringify(value);
152
+ }
153
+ function deepFreeze(value) {
154
+ if (typeof value !== "object" || value === null || Object.isFrozen(value)) return value;
155
+ for (const child of Object.values(value)) deepFreeze(child);
156
+ return Object.freeze(value);
157
+ }
158
+ // Annotate the CommonJS export names for ESM import in node:
159
+ 0 && (module.exports = {
160
+ TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS,
161
+ buildTargetingInputConformanceVectors,
162
+ runTargetingInputConformance
163
+ });
@@ -0,0 +1,137 @@
1
+ import { isDeepStrictEqual } from "node:util";
2
+ function buildTargetingInputConformanceVectors(samples) {
3
+ const entries = Object.entries(samples).filter(([, sample]) => sample !== void 0);
4
+ const baseline = Object.fromEntries(entries.map(([dimension, sample]) => [dimension, clone(sample.initialValue)]));
5
+ const vectors = [];
6
+ for (const [dimension, sample] of entries) {
7
+ const clearedState = withoutKey(baseline, dimension);
8
+ const replacementState = sample.expectedReplacementState ? clone(sample.expectedReplacementState) : {
9
+ ...clone(baseline),
10
+ [dimension]: clone(sample.expectedReplacementValue ?? sample.replacementValue)
11
+ };
12
+ for (const operation of ["create", "update"]) {
13
+ const omittedMeaning = operation === "create" ? "inherits configured/product defaults" : "preserves stored state";
14
+ const nullOutcome = sample.expectedNullOutcome ?? "accepted";
15
+ const replacementOutcome = sample.expectedReplacementOutcome ?? "accepted";
16
+ const rejectedState = operation === "create" ? void 0 : baseline;
17
+ vectors.push(
18
+ {
19
+ id: `${operation}/${dimension}/omitted`,
20
+ operation,
21
+ dimension,
22
+ baseline: clone(baseline),
23
+ input: {},
24
+ expectedOutcome: "accepted",
25
+ expectedState: clone(baseline),
26
+ description: `${operation}: omitted ${dimension} ${omittedMeaning}`
27
+ },
28
+ {
29
+ id: `${operation}/${dimension}/null`,
30
+ operation,
31
+ dimension,
32
+ baseline: clone(baseline),
33
+ input: { [dimension]: null },
34
+ expectedOutcome: nullOutcome,
35
+ expectedState: clone(nullOutcome === "accepted" ? clearedState : rejectedState),
36
+ description: `${operation}: null ${dimension} clears/suppresses only that effective dimension`
37
+ },
38
+ {
39
+ id: `${operation}/${dimension}/value`,
40
+ operation,
41
+ dimension,
42
+ baseline: clone(baseline),
43
+ input: { [dimension]: clone(sample.replacementValue) },
44
+ expectedOutcome: replacementOutcome,
45
+ expectedState: clone(replacementOutcome === "accepted" ? replacementState : rejectedState),
46
+ description: `${operation}: a non-null ${dimension} value replaces only that complete dimension`
47
+ }
48
+ );
49
+ }
50
+ }
51
+ return vectors;
52
+ }
53
+ const TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS = deepFreeze([
54
+ {
55
+ id: "update/geo_countries/preserve-compatible-regions",
56
+ operation: "update",
57
+ baseline: { geo_countries: ["US"], geo_regions: ["US-NY"] },
58
+ input: { geo_countries: ["US", "CA"] },
59
+ expectedOutcome: "accepted",
60
+ expectedState: { geo_countries: ["US", "CA"], geo_regions: ["US-NY"] },
61
+ description: "Changing countries preserves an omitted compatible geo_regions dimension."
62
+ },
63
+ {
64
+ id: "update/geo_countries/reject-incompatible-preserved-regions",
65
+ operation: "update",
66
+ baseline: { geo_countries: ["US"], geo_regions: ["US-NY"] },
67
+ input: { geo_countries: ["CA"] },
68
+ expectedOutcome: "rejected",
69
+ expectedState: { geo_countries: ["US"], geo_regions: ["US-NY"] },
70
+ description: "An invalid country/region result is rejected atomically instead of clearing the omitted region axis."
71
+ }
72
+ ]);
73
+ async function runTargetingInputConformance(vectors, adapter, options = {}) {
74
+ if (vectors.length === 0) throw new TypeError("Targeting conformance requires at least one vector.");
75
+ const compareState = options.compareState ?? defaultStateComparison;
76
+ const cases = [];
77
+ for (const sourceVector of vectors) {
78
+ const vector = clone(sourceVector);
79
+ const failures = [];
80
+ try {
81
+ const observation = await adapter[vector.operation](clone(vector));
82
+ if (observation.outcome !== vector.expectedOutcome) {
83
+ failures.push(`expected ${vector.expectedOutcome}, observed ${observation.outcome}`);
84
+ }
85
+ if (!compareState(observation.state, vector.expectedState, vector)) {
86
+ failures.push(
87
+ `strict state mismatch: expected ${formatDiagnosticValue(vector.expectedState)}, observed ${formatDiagnosticValue(observation.state)}`
88
+ );
89
+ }
90
+ if (containsNull(observation.state)) {
91
+ failures.push("durable/readback state retained a request-only null command");
92
+ }
93
+ if (observation.outcome === "accepted" && !isDeepStrictEqual(observation.dispatchedInput, vector.input)) {
94
+ failures.push(
95
+ `dispatch changed the request overlay: expected ${formatDiagnosticValue(vector.input)}, observed ${formatDiagnosticValue(observation.dispatchedInput)}`
96
+ );
97
+ }
98
+ cases.push({ id: vector.id, passed: failures.length === 0, failures, vector, observation });
99
+ } catch (error) {
100
+ const name = error instanceof Error ? error.name : typeof error;
101
+ failures.push(`adapter execution failed (${name}); inspect adapter logs for details`);
102
+ cases.push({ id: vector.id, passed: false, failures, vector });
103
+ }
104
+ }
105
+ return { passed: cases.every((result) => result.passed), cases };
106
+ }
107
+ function defaultStateComparison(observed, expected) {
108
+ return isDeepStrictEqual(normalizeEmptyState(observed), normalizeEmptyState(expected));
109
+ }
110
+ function normalizeEmptyState(state) {
111
+ return state && Object.keys(state).length === 0 ? void 0 : state;
112
+ }
113
+ function containsNull(value) {
114
+ if (value === null) return true;
115
+ if (Array.isArray(value)) return value.some(containsNull);
116
+ return typeof value === "object" && Object.values(value).some(containsNull);
117
+ }
118
+ function withoutKey(state, key) {
119
+ const result = Object.fromEntries(Object.entries(state).filter(([candidate]) => candidate !== key));
120
+ return Object.keys(result).length === 0 ? void 0 : result;
121
+ }
122
+ function clone(value) {
123
+ return structuredClone(value);
124
+ }
125
+ function formatDiagnosticValue(value) {
126
+ return value === void 0 ? "undefined" : JSON.stringify(value);
127
+ }
128
+ function deepFreeze(value) {
129
+ if (typeof value !== "object" || value === null || Object.isFrozen(value)) return value;
130
+ for (const child of Object.values(value)) deepFreeze(child);
131
+ return Object.freeze(value);
132
+ }
133
+ export {
134
+ TARGETING_GEOGRAPHY_CONFORMANCE_VECTORS,
135
+ buildTargetingInputConformanceVectors,
136
+ runTargetingInputConformance
137
+ };
@@ -2,7 +2,7 @@ import type { Client as MCPClient } from '@modelcontextprotocol/sdk/client/index
2
2
  import type { AgentConfig } from '../types/index.mjs';
3
3
  import type { MCPWebhookPayload, GetBrandIdentityRequest, GetBrandIdentityResponse, ContextMatchRequest, ContextMatchResponse, IdentityMatchRequest, IdentityMatchResponseRouterPublisher } from '../types/core.generated.mjs';
4
4
  import type { Task as A2ATask, TaskStatusUpdateEvent } from '@a2a-js/sdk';
5
- import { type CanonicalReadTaskOptions, type CreativeDeliveryTaskOptions, type SingleAgentClientConfig, type SyncCreativesTaskOptions, type VerifyAndParseWebhookOptions, type WebhookHandlerAdapter, type WebhookParseResult, type WebhookRequestContext } from './SingleAgentClient.mjs';
5
+ import { type CapabilityEvidenceScope, type CapabilityEvidenceSnapshot, type CanonicalReadTaskOptions, type CreativeDeliveryTaskOptions, type SingleAgentClientConfig, type SyncCreativesTaskOptions, type VerifyAndParseWebhookOptions, type WebhookHandlerAdapter, type WebhookParseResult, type WebhookRequestContext } from './SingleAgentClient.mjs';
6
6
  import type { InputHandler, TaskOptions, TaskResult, TaskInfo, Message, DirectPauseRecoveryRequest } from './ConversationTypes.mjs';
7
7
  import type { AdcpCapabilities } from '../utils/capabilities.mjs';
8
8
  import type { WebhookHeaderValue } from '../webhooks/index.mjs';
@@ -167,6 +167,22 @@ export type InProcessAgentClientConfig = Pick<SingleAgentClientConfig, 'adcpVers
167
167
  */
168
168
  agentId?: string;
169
169
  };
170
+ /** Context passed to {@link AgentClient.createWithCapabilityPreflight}. */
171
+ export interface CapabilityPreflightContext {
172
+ /** The exact client instance that will be returned by the factory. */
173
+ client: AgentClient;
174
+ /** Opaque authorization/transport scope the returned snapshot must carry. */
175
+ scope: CapabilityEvidenceScope;
176
+ }
177
+ /** Load or perform capability discovery for one newly constructed client. */
178
+ export type CapabilityPreflightLoader = (context: CapabilityPreflightContext) => CapabilityEvidenceSnapshot | Promise<CapabilityEvidenceSnapshot>;
179
+ export type CapabilityPreflightErrorCode = 'scoped_transport' | 'scope_rotated' | 'invalid_evidence';
180
+ /** Actionable factory failure without weakening the same-instance invariant. */
181
+ export declare class CapabilityPreflightError extends Error {
182
+ readonly code: CapabilityPreflightErrorCode;
183
+ readonly name = "CapabilityPreflightError";
184
+ constructor(code: CapabilityPreflightErrorCode, message: string);
185
+ }
170
186
  export declare class AgentClient {
171
187
  private agent;
172
188
  private config;
@@ -176,6 +192,16 @@ export declare class AgentClient {
176
192
  private readonly sessionTrackedDeferredContinuations;
177
193
  private readonly _isInProcess;
178
194
  constructor(agent: AgentConfig, config?: SingleAgentClientConfig);
195
+ /**
196
+ * Construct and prime one client before exposing it for task dispatch.
197
+ *
198
+ * Capability evidence is intentionally bound to a client instance. This
199
+ * factory gives application factories the instance and its opaque scope
200
+ * before the first task can be sent, then installs the callback's snapshot
201
+ * on that same instance. Evidence from an otherwise identical client is
202
+ * rejected rather than silently falling back to redundant discovery.
203
+ */
204
+ static createWithCapabilityPreflight(agent: AgentConfig, loadEvidence: CapabilityPreflightLoader, config?: SingleAgentClientConfig): Promise<AgentClient>;
179
205
  /**
180
206
  * Recover the current A2A pause generation for a direct mutation that opted
181
207
  * into `TaskOptions.durableContinuationRecovery`.