@adcp/sdk 15.9.1 → 15.9.3
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/core/TaskExecutor.js +5 -1
- package/dist/lib/core/TaskExecutor.mjs +5 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/testing/client.js +2 -1
- package/dist/lib/testing/client.mjs +2 -1
- package/dist/lib/testing/scenarios/capabilities.js +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +1 -1
- package/dist/lib/testing/storyboard/junit.js +16 -3
- package/dist/lib/testing/storyboard/junit.mjs +16 -3
- package/dist/lib/testing/storyboard/runner.js +94 -25
- package/dist/lib/testing/storyboard/runner.mjs +94 -25
- package/dist/lib/testing/storyboard/types.d.mts +6 -0
- package/dist/lib/testing/storyboard/types.d.ts +6 -0
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/validation/schema-loader.js +25 -0
- package/dist/lib/validation/schema-loader.mjs +24 -0
- 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.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/llms.txt +2 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/package.json +1 -1
|
@@ -47,6 +47,7 @@ var import_signedRequestRejection = require('../protocols/signedRequestRejection
|
|
|
47
47
|
var import_errors = require('../errors/index.js');
|
|
48
48
|
var import_client_hooks = require('../validation/client-hooks.js');
|
|
49
49
|
var import_schema_validator = require('../validation/schema-validator.js');
|
|
50
|
+
var import_schema_loader = require('../validation/schema-loader.js');
|
|
50
51
|
var import_version = require('../version.js');
|
|
51
52
|
var import_response_unwrapper = require('../utils/response-unwrapper.js');
|
|
52
53
|
var import_error_extraction = require('../utils/error-extraction.js');
|
|
@@ -4397,7 +4398,10 @@ class TaskExecutor {
|
|
|
4397
4398
|
const mode = this.responseValidationMode;
|
|
4398
4399
|
const logViolations = this.config.logSchemaViolations !== false;
|
|
4399
4400
|
try {
|
|
4400
|
-
|
|
4401
|
+
let validationVersion = (serverVersion ?? this.lastKnownServerVersion) === "v2" ? "v2.5" : this.responseAdcpVersionForValidation() ?? this.config.adcpVersion ?? import_version.ADCP_VERSION;
|
|
4402
|
+
if (taskName === "get_adcp_capabilities" && validationVersion !== "v2.5") {
|
|
4403
|
+
validationVersion = (0, import_schema_loader.resolveServedValidationVersion)(response, validationVersion);
|
|
4404
|
+
}
|
|
4401
4405
|
const normalizedResponse = this.normalizeResponseForValidation(response, taskName, validationVersion === "v2.5");
|
|
4402
4406
|
const outcome = (0, import_client_hooks.validateIncomingResponse)(taskName, normalizedResponse, mode, void 0, validationVersion);
|
|
4403
4407
|
if (outcome.valid) return { valid: true, errors: [] };
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
resolveValidationModes
|
|
16
16
|
} from "../validation/client-hooks.mjs";
|
|
17
17
|
import { formatIssues } from "../validation/schema-validator.mjs";
|
|
18
|
+
import { resolveServedValidationVersion } from "../validation/schema-loader.mjs";
|
|
18
19
|
import { ADCP_VERSION } from "../version.mjs";
|
|
19
20
|
import { unwrapProtocolResponse, isAdcpOperationSuccess } from "../utils/response-unwrapper.mjs";
|
|
20
21
|
import { extractAdcpErrorInfo, extractCorrelationId } from "../utils/error-extraction.mjs";
|
|
@@ -4370,7 +4371,10 @@ class TaskExecutor {
|
|
|
4370
4371
|
const mode = this.responseValidationMode;
|
|
4371
4372
|
const logViolations = this.config.logSchemaViolations !== false;
|
|
4372
4373
|
try {
|
|
4373
|
-
|
|
4374
|
+
let validationVersion = (serverVersion ?? this.lastKnownServerVersion) === "v2" ? "v2.5" : this.responseAdcpVersionForValidation() ?? this.config.adcpVersion ?? ADCP_VERSION;
|
|
4375
|
+
if (taskName === "get_adcp_capabilities" && validationVersion !== "v2.5") {
|
|
4376
|
+
validationVersion = resolveServedValidationVersion(response, validationVersion);
|
|
4377
|
+
}
|
|
4374
4378
|
const normalizedResponse = this.normalizeResponseForValidation(response, taskName, validationVersion === "v2.5");
|
|
4375
4379
|
const outcome = validateIncomingResponse(taskName, normalizedResponse, mode, void 0, validationVersion);
|
|
4376
4380
|
if (outcome.valid) return { valid: true, errors: [] };
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
"source_sha": "4e553ad955f83b49c7d221ab5c3ff78237ad02e3",
|
|
5
5
|
"source_tarball_sha256": "580656d6466ef9f0d1119985e6726c2efea718dc671e2ad30957fcb2fd54af0f",
|
|
6
6
|
"upstream_adcp_version": "2.5.3",
|
|
7
|
-
"synced_at": "2026-10-
|
|
7
|
+
"synced_at": "2026-10-16T14:52:19.557Z"
|
|
8
8
|
}
|
|
@@ -50,6 +50,7 @@ var import_ssrf_fetch = require('../net/ssrf-fetch.js');
|
|
|
50
50
|
var import_version = require('../version.js');
|
|
51
51
|
var import_node_crypto = require("node:crypto");
|
|
52
52
|
var import_client_hooks = require('../validation/client-hooks.js');
|
|
53
|
+
var import_schema_loader = require('../validation/schema-loader.js');
|
|
53
54
|
var import_error_extraction = require('../utils/error-extraction.js');
|
|
54
55
|
var import_client = require('../signing/client.js');
|
|
55
56
|
var import_storage_registry = require('../auth/oauth/storage-registry.js');
|
|
@@ -418,7 +419,7 @@ async function discoverAgentProfile(client, signal, schemaAdcpVersion) {
|
|
|
418
419
|
caps.data,
|
|
419
420
|
"strict",
|
|
420
421
|
void 0,
|
|
421
|
-
schemaAdcpVersion ?? client.getAdcpVersion()
|
|
422
|
+
(0, import_schema_loader.resolveServedValidationVersion)(caps.data, schemaAdcpVersion ?? client.getAdcpVersion())
|
|
422
423
|
);
|
|
423
424
|
if (!validation.valid) {
|
|
424
425
|
profile.capabilities_schema_issues = validation.issues.map((issue) => ({
|
|
@@ -10,6 +10,7 @@ import { SsrfRefusedError } from "../net/ssrf-fetch.mjs";
|
|
|
10
10
|
import { ADCP_VERSION, toReleasePrecisionVersion } from "../version.mjs";
|
|
11
11
|
import { createHmac, hkdfSync, randomBytes } from "node:crypto";
|
|
12
12
|
import { validateIncomingResponse } from "../validation/client-hooks.mjs";
|
|
13
|
+
import { resolveServedValidationVersion } from "../validation/schema-loader.mjs";
|
|
13
14
|
import { extractVersionUnsupportedDetails } from "../utils/error-extraction.mjs";
|
|
14
15
|
import { buildAgentSigningContext } from "../signing/client.mjs";
|
|
15
16
|
import { bindAgentStorage } from "../auth/oauth/storage-registry.mjs";
|
|
@@ -378,7 +379,7 @@ async function discoverAgentProfile(client, signal, schemaAdcpVersion) {
|
|
|
378
379
|
caps.data,
|
|
379
380
|
"strict",
|
|
380
381
|
void 0,
|
|
381
|
-
schemaAdcpVersion ?? client.getAdcpVersion()
|
|
382
|
+
resolveServedValidationVersion(caps.data, schemaAdcpVersion ?? client.getAdcpVersion())
|
|
382
383
|
);
|
|
383
384
|
if (!validation.valid) {
|
|
384
385
|
profile.capabilities_schema_issues = validation.issues.map((issue) => ({
|
|
@@ -239,7 +239,7 @@ function crossValidateProtocolsAndTools(capabilities, tools) {
|
|
|
239
239
|
creative: import_capabilities.CREATIVE_TOOLS,
|
|
240
240
|
sponsored_intelligence: import_capabilities.SPONSORED_INTELLIGENCE_TOOLS,
|
|
241
241
|
trusted_match: import_capabilities.TRUSTED_MATCH_TOOLS,
|
|
242
|
-
|
|
242
|
+
compliance_testing: import_capabilities.COMPLIANCE_TOOLS
|
|
243
243
|
};
|
|
244
244
|
const perProtocolDiffs = {};
|
|
245
245
|
for (const protocol of capabilities.protocols) {
|
|
@@ -225,7 +225,7 @@ function crossValidateProtocolsAndTools(capabilities, tools) {
|
|
|
225
225
|
creative: CREATIVE_TOOLS,
|
|
226
226
|
sponsored_intelligence: SPONSORED_INTELLIGENCE_TOOLS,
|
|
227
227
|
trusted_match: TRUSTED_MATCH_TOOLS,
|
|
228
|
-
|
|
228
|
+
compliance_testing: COMPLIANCE_TOOLS
|
|
229
229
|
};
|
|
230
230
|
const perProtocolDiffs = {};
|
|
231
231
|
for (const protocol of capabilities.protocols) {
|
|
@@ -82,8 +82,9 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
82
82
|
const suiteGroup = options.suite_groups?.[sb.storyboard_id];
|
|
83
83
|
const suiteClassname = suiteGroup ? `${suiteGroup}.${sb.storyboard_id}` : sb.storyboard_id;
|
|
84
84
|
const suiteCases = [];
|
|
85
|
-
let suiteFailures =
|
|
85
|
+
let suiteFailures = 0;
|
|
86
86
|
let representedSkipped = 0;
|
|
87
|
+
let suiteSkipped = 0;
|
|
87
88
|
const passPhases = sb.passes?.length ? sb.passes.map((pass) => ({ label: `Pass ${pass.pass_index} \u203A `, phases: pass.phases })) : [{ label: "", phases: sb.phases }];
|
|
88
89
|
for (const pass of passPhases) {
|
|
89
90
|
for (const phase of pass.phases) {
|
|
@@ -93,6 +94,7 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
93
94
|
const time = ((step.duration_ms || 0) / 1e3).toFixed(3);
|
|
94
95
|
if (step.skipped) {
|
|
95
96
|
representedSkipped += 1;
|
|
97
|
+
suiteSkipped += 1;
|
|
96
98
|
totalSkipped += 1;
|
|
97
99
|
suiteCases.push(
|
|
98
100
|
` <testcase classname="${xmlEscape(suiteClassname)}" name="${xmlEscape(name)}" time="${time}">
|
|
@@ -102,7 +104,6 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
102
104
|
continue;
|
|
103
105
|
}
|
|
104
106
|
if (!step.passed) {
|
|
105
|
-
totalFailures += 1;
|
|
106
107
|
const failureDetails = [
|
|
107
108
|
step.error,
|
|
108
109
|
...step.validations.filter((v) => !v.passed).map(
|
|
@@ -114,6 +115,17 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
114
115
|
// report body.
|
|
115
116
|
...hintLines(step.hints)
|
|
116
117
|
].filter(Boolean).join("\n");
|
|
118
|
+
if (step.counts_toward_failure === false) {
|
|
119
|
+
suiteCases.push(
|
|
120
|
+
` <testcase classname="${xmlEscape(suiteClassname)}" name="${xmlEscape(name)}" time="${time}">
|
|
121
|
+
<system-out>${xmlEscape(`Optional phase failure; excluded from storyboard verdict.
|
|
122
|
+
${failureDetails}`)}</system-out>
|
|
123
|
+
</testcase>`
|
|
124
|
+
);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
totalFailures += 1;
|
|
128
|
+
suiteFailures += 1;
|
|
117
129
|
const message = step.error || firstHintMessage(step) || "validation failed";
|
|
118
130
|
suiteCases.push(
|
|
119
131
|
` <testcase classname="${xmlEscape(suiteClassname)}" name="${xmlEscape(name)}" time="${time}">
|
|
@@ -136,6 +148,7 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
136
148
|
if (hasStoryboardFixtureSkip) {
|
|
137
149
|
totalTests += 1;
|
|
138
150
|
totalSkipped += 1;
|
|
151
|
+
suiteSkipped += 1;
|
|
139
152
|
suiteCases.push(
|
|
140
153
|
` <testcase classname="${xmlEscape(suiteClassname)}" name="Fixture resolution" time="0.000">
|
|
141
154
|
<skipped message="${xmlEscape(fixtureGap.detail)}"/>
|
|
@@ -159,7 +172,7 @@ ${assertion.error}` : ""}`;
|
|
|
159
172
|
totalDuration += sb.total_duration_ms || 0;
|
|
160
173
|
const suiteTests = suiteCases.length;
|
|
161
174
|
suites.push(
|
|
162
|
-
` <testsuite name="${xmlEscape(suiteGroup ? `${suiteGroup} \u203A ${sb.storyboard_title}` : sb.storyboard_title)}"${suiteGroup ? ` package="${xmlEscape(`adcp.${suiteGroup}`)}"` : ""} tests="${suiteTests}" failures="${suiteFailures}" skipped="${
|
|
175
|
+
` <testsuite name="${xmlEscape(suiteGroup ? `${suiteGroup} \u203A ${sb.storyboard_title}` : sb.storyboard_title)}"${suiteGroup ? ` package="${xmlEscape(`adcp.${suiteGroup}`)}"` : ""} tests="${suiteTests}" failures="${suiteFailures}" skipped="${suiteSkipped}" time="${((sb.total_duration_ms || 0) / 1e3).toFixed(3)}" timestamp="${sb.tested_at || (/* @__PURE__ */ new Date()).toISOString()}">
|
|
163
176
|
` + suiteCases.join("\n") + `
|
|
164
177
|
</testsuite>`
|
|
165
178
|
);
|
|
@@ -58,8 +58,9 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
58
58
|
const suiteGroup = options.suite_groups?.[sb.storyboard_id];
|
|
59
59
|
const suiteClassname = suiteGroup ? `${suiteGroup}.${sb.storyboard_id}` : sb.storyboard_id;
|
|
60
60
|
const suiteCases = [];
|
|
61
|
-
let suiteFailures =
|
|
61
|
+
let suiteFailures = 0;
|
|
62
62
|
let representedSkipped = 0;
|
|
63
|
+
let suiteSkipped = 0;
|
|
63
64
|
const passPhases = sb.passes?.length ? sb.passes.map((pass) => ({ label: `Pass ${pass.pass_index} \u203A `, phases: pass.phases })) : [{ label: "", phases: sb.phases }];
|
|
64
65
|
for (const pass of passPhases) {
|
|
65
66
|
for (const phase of pass.phases) {
|
|
@@ -69,6 +70,7 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
69
70
|
const time = ((step.duration_ms || 0) / 1e3).toFixed(3);
|
|
70
71
|
if (step.skipped) {
|
|
71
72
|
representedSkipped += 1;
|
|
73
|
+
suiteSkipped += 1;
|
|
72
74
|
totalSkipped += 1;
|
|
73
75
|
suiteCases.push(
|
|
74
76
|
` <testcase classname="${xmlEscape(suiteClassname)}" name="${xmlEscape(name)}" time="${time}">
|
|
@@ -78,7 +80,6 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
78
80
|
continue;
|
|
79
81
|
}
|
|
80
82
|
if (!step.passed) {
|
|
81
|
-
totalFailures += 1;
|
|
82
83
|
const failureDetails = [
|
|
83
84
|
step.error,
|
|
84
85
|
...step.validations.filter((v) => !v.passed).map(
|
|
@@ -90,6 +91,17 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
90
91
|
// report body.
|
|
91
92
|
...hintLines(step.hints)
|
|
92
93
|
].filter(Boolean).join("\n");
|
|
94
|
+
if (step.counts_toward_failure === false) {
|
|
95
|
+
suiteCases.push(
|
|
96
|
+
` <testcase classname="${xmlEscape(suiteClassname)}" name="${xmlEscape(name)}" time="${time}">
|
|
97
|
+
<system-out>${xmlEscape(`Optional phase failure; excluded from storyboard verdict.
|
|
98
|
+
${failureDetails}`)}</system-out>
|
|
99
|
+
</testcase>`
|
|
100
|
+
);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
totalFailures += 1;
|
|
104
|
+
suiteFailures += 1;
|
|
93
105
|
const message = step.error || firstHintMessage(step) || "validation failed";
|
|
94
106
|
suiteCases.push(
|
|
95
107
|
` <testcase classname="${xmlEscape(suiteClassname)}" name="${xmlEscape(name)}" time="${time}">
|
|
@@ -112,6 +124,7 @@ function formatStoryboardResultsAsJUnit(results, options = {}) {
|
|
|
112
124
|
if (hasStoryboardFixtureSkip) {
|
|
113
125
|
totalTests += 1;
|
|
114
126
|
totalSkipped += 1;
|
|
127
|
+
suiteSkipped += 1;
|
|
115
128
|
suiteCases.push(
|
|
116
129
|
` <testcase classname="${xmlEscape(suiteClassname)}" name="Fixture resolution" time="0.000">
|
|
117
130
|
<skipped message="${xmlEscape(fixtureGap.detail)}"/>
|
|
@@ -135,7 +148,7 @@ ${assertion.error}` : ""}`;
|
|
|
135
148
|
totalDuration += sb.total_duration_ms || 0;
|
|
136
149
|
const suiteTests = suiteCases.length;
|
|
137
150
|
suites.push(
|
|
138
|
-
` <testsuite name="${xmlEscape(suiteGroup ? `${suiteGroup} \u203A ${sb.storyboard_title}` : sb.storyboard_title)}"${suiteGroup ? ` package="${xmlEscape(`adcp.${suiteGroup}`)}"` : ""} tests="${suiteTests}" failures="${suiteFailures}" skipped="${
|
|
151
|
+
` <testsuite name="${xmlEscape(suiteGroup ? `${suiteGroup} \u203A ${sb.storyboard_title}` : sb.storyboard_title)}"${suiteGroup ? ` package="${xmlEscape(`adcp.${suiteGroup}`)}"` : ""} tests="${suiteTests}" failures="${suiteFailures}" skipped="${suiteSkipped}" time="${((sb.total_duration_ms || 0) / 1e3).toFixed(3)}" timestamp="${sb.tested_at || (/* @__PURE__ */ new Date()).toISOString()}">
|
|
139
152
|
` + suiteCases.join("\n") + `
|
|
140
153
|
</testsuite>`
|
|
141
154
|
);
|
|
@@ -548,6 +548,7 @@ function applyBranchSetGrading(phases, phaseResults, branchSetByPhaseId, contrib
|
|
|
548
548
|
step.skip = { reason: "peer_branch_taken", detail };
|
|
549
549
|
delete step.error;
|
|
550
550
|
delete step.adcp_error;
|
|
551
|
+
delete step.counts_toward_failure;
|
|
551
552
|
skippedDelta++;
|
|
552
553
|
regraded = true;
|
|
553
554
|
}
|
|
@@ -2646,6 +2647,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2646
2647
|
if (!phase.optional || (routingContext ? routedOauthPresent.has(assignment.instanceIndex) : presenceDetected)) {
|
|
2647
2648
|
failedCount++;
|
|
2648
2649
|
countedAsFailed.add(result2);
|
|
2650
|
+
} else if (!result2.validations.some((validation) => validation.check === "assertion" && !validation.passed)) {
|
|
2651
|
+
result2.counts_toward_failure = false;
|
|
2649
2652
|
}
|
|
2650
2653
|
if (step.stateful) {
|
|
2651
2654
|
phaseStatefulCascades.set(phase.id, null);
|
|
@@ -3657,9 +3660,20 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3657
3660
|
const testsIdempotencyKeyOmission = (step.omit_idempotency_key === true || governedRequest && (typeof request.idempotency_key !== "string" || request.idempotency_key.length === 0)) && (0, import_idempotency.requestUsesIdempotency)(effectiveStep.task, request);
|
|
3658
3661
|
const testsMissingAccount = effectiveStep.task === "create_media_buy" && (step.omit_account === true || governedRequest && !Object.prototype.hasOwnProperty.call(request, "account"));
|
|
3659
3662
|
const testsSchemaInvalidRequest = step.expect_error === true && step.negative_path !== "payload_well_formed";
|
|
3663
|
+
const useSdkAuthOverride = typeof step.auth === "object" && step.auth.type === "api_key" && step.auth.from_test_kit === true && step.auth.value_strategy === void 0 && step.expect_error !== true && !(step.validations ?? []).some((validation) => HTTP_PROBE_ONLY_CHECKS.has(validation.check));
|
|
3660
3664
|
let rawProbeHeaders;
|
|
3665
|
+
let authOverrideClient;
|
|
3661
3666
|
try {
|
|
3662
3667
|
rawProbeHeaders = step.auth !== void 0 ? authHeadersForStep(step.auth, options) : void 0;
|
|
3668
|
+
if (useSdkAuthOverride) {
|
|
3669
|
+
if (rawProbeHeaders === void 0) throw new Error("Step auth override credentials were not resolved");
|
|
3670
|
+
authOverrideClient = createAuthOverrideClient(
|
|
3671
|
+
runState.agentUrl,
|
|
3672
|
+
options.protocol ?? "mcp",
|
|
3673
|
+
options,
|
|
3674
|
+
rawProbeHeaders
|
|
3675
|
+
);
|
|
3676
|
+
}
|
|
3663
3677
|
} catch (err) {
|
|
3664
3678
|
return {
|
|
3665
3679
|
step_id: step.id,
|
|
@@ -3674,7 +3688,8 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3674
3688
|
extraction: { path: "none" }
|
|
3675
3689
|
};
|
|
3676
3690
|
}
|
|
3677
|
-
const useRawProbe = rawProbeHeaders !== void 0;
|
|
3691
|
+
const useRawProbe = rawProbeHeaders !== void 0 && !useSdkAuthOverride;
|
|
3692
|
+
const stepClient = () => authOverrideClient ?? client;
|
|
3678
3693
|
let taskResult;
|
|
3679
3694
|
let stepResult;
|
|
3680
3695
|
let caughtError;
|
|
@@ -3758,7 +3773,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3758
3773
|
const started = Date.now();
|
|
3759
3774
|
try {
|
|
3760
3775
|
if (options.protocol === "a2a") {
|
|
3761
|
-
const probeClient =
|
|
3776
|
+
const probeClient = createAuthOverrideClient(runState.agentUrl, "a2a", options, rawProbeHeaders ?? {});
|
|
3762
3777
|
const captured = await (0, import_rawResponseCapture.withRawResponseCapture)(
|
|
3763
3778
|
() => (0, import_client.runStep)(
|
|
3764
3779
|
step.title,
|
|
@@ -3853,7 +3868,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3853
3868
|
let a2aCaptures;
|
|
3854
3869
|
if (step.parallel_dispatch) {
|
|
3855
3870
|
const started = Date.now();
|
|
3856
|
-
crossResponses = await (0, import_parallel_dispatch.runParallelDispatches)(
|
|
3871
|
+
crossResponses = await (0, import_parallel_dispatch.runParallelDispatches)(stepClient(), effectiveStep.task, request, {
|
|
3857
3872
|
spec: step.parallel_dispatch,
|
|
3858
3873
|
keyMinter: import_idempotency.generateIdempotencyKey,
|
|
3859
3874
|
correlationPrefix: step.id,
|
|
@@ -3890,7 +3905,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3890
3905
|
};
|
|
3891
3906
|
}
|
|
3892
3907
|
} else {
|
|
3893
|
-
const dispatch = () => (0, import_task_map.executeStoryboardTask)(
|
|
3908
|
+
const dispatch = () => (0, import_task_map.executeStoryboardTask)(stepClient(), effectiveStep.task, request, {
|
|
3894
3909
|
skipIdempotencyAutoInject: testsIdempotencyKeyOmission,
|
|
3895
3910
|
skipAccountValidation: testsMissingAccount,
|
|
3896
3911
|
skipRequestValidation: testsSchemaInvalidRequest,
|
|
@@ -5699,8 +5714,10 @@ function defaultAuthHeadersForRawProbe(options) {
|
|
|
5699
5714
|
}
|
|
5700
5715
|
function sessionProbeRoutingHeaders(options) {
|
|
5701
5716
|
const headers = {};
|
|
5717
|
+
const runSecrets = runCredentialValues(options);
|
|
5702
5718
|
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5703
5719
|
if (!SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase())) continue;
|
|
5720
|
+
if (runSecrets.some((secret) => value.includes(secret))) continue;
|
|
5704
5721
|
try {
|
|
5705
5722
|
assertSafeAuthHeaderPart(value, `options.headers.${name}`);
|
|
5706
5723
|
} catch {
|
|
@@ -5725,35 +5742,62 @@ function setHeaderIfAbsent(headers, name, value, label) {
|
|
|
5725
5742
|
}
|
|
5726
5743
|
function runCredentialValues(options) {
|
|
5727
5744
|
const values = [];
|
|
5745
|
+
const pushHeaderToken = (value) => {
|
|
5746
|
+
values.push(value, value.replace(/^[\t ]+|[\t ]+$/g, ""));
|
|
5747
|
+
};
|
|
5748
|
+
const pushUserPass = (userpass) => {
|
|
5749
|
+
values.push(userpass, Buffer.from(userpass).toString("base64"));
|
|
5750
|
+
const separator = userpass.indexOf(":");
|
|
5751
|
+
if (separator >= 0) values.push(userpass.slice(separator + 1));
|
|
5752
|
+
};
|
|
5728
5753
|
const auth = options.auth;
|
|
5729
|
-
if (auth?.type === "bearer" && typeof auth.token === "string")
|
|
5754
|
+
if (auth?.type === "bearer" && typeof auth.token === "string") pushHeaderToken(auth.token);
|
|
5730
5755
|
if (auth?.type === "basic") {
|
|
5731
5756
|
if (typeof auth.password === "string") values.push(auth.password);
|
|
5732
5757
|
if (typeof auth.username === "string" && typeof auth.password === "string") {
|
|
5733
|
-
|
|
5758
|
+
pushUserPass(`${auth.username}:${auth.password}`);
|
|
5734
5759
|
}
|
|
5735
5760
|
}
|
|
5736
5761
|
if (auth?.type === "oauth" || auth?.type === "oauth_client_credentials") {
|
|
5737
5762
|
const token = auth.tokens?.access_token;
|
|
5738
|
-
if (typeof token === "string")
|
|
5763
|
+
if (typeof token === "string") pushHeaderToken(token);
|
|
5739
5764
|
}
|
|
5740
5765
|
const kit = options.test_kit?.auth;
|
|
5741
|
-
if (typeof kit?.api_key === "string")
|
|
5766
|
+
if (typeof kit?.api_key === "string") pushHeaderToken(kit.api_key);
|
|
5742
5767
|
const basic = kit?.basic;
|
|
5743
5768
|
if (typeof basic?.password === "string") values.push(basic.password);
|
|
5744
5769
|
if (typeof basic?.username === "string" && typeof basic?.password === "string") {
|
|
5745
|
-
|
|
5770
|
+
pushUserPass(`${basic.username}:${basic.password}`);
|
|
5746
5771
|
}
|
|
5747
|
-
if (typeof basic?.credentials === "string")
|
|
5772
|
+
if (typeof basic?.credentials === "string") pushUserPass(basic.credentials);
|
|
5748
5773
|
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5749
5774
|
if (typeof value !== "string" || value.length === 0) continue;
|
|
5750
|
-
if (AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase())
|
|
5775
|
+
if (!AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase()) && !isCredentialHeaderName(name)) continue;
|
|
5776
|
+
pushHeaderToken(value);
|
|
5777
|
+
const scheme = /^(Bearer|Basic|Token|ApiKey)\s+(.+)$/i.exec(value.trim());
|
|
5778
|
+
if (scheme?.[1] !== void 0 && scheme[2] !== void 0) {
|
|
5779
|
+
const payload = scheme[2].trim();
|
|
5780
|
+
values.push(payload);
|
|
5781
|
+
if (/^Basic$/i.test(scheme[1]) && /^[A-Za-z0-9+/]+={0,2}$/.test(payload)) {
|
|
5782
|
+
const bytes = Buffer.from(payload, "base64");
|
|
5783
|
+
const decoded = bytes.toString("utf8");
|
|
5784
|
+
if (bytes.toString("base64").replace(/=+$/, "") === payload.replace(/=+$/, "") && Buffer.from(decoded, "utf8").equals(bytes) && !/[\x00-\x1f\x7f]/.test(decoded) && decoded.includes(":")) {
|
|
5785
|
+
pushUserPass(decoded);
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5788
|
+
}
|
|
5751
5789
|
}
|
|
5752
5790
|
return values.filter((value) => value.trim().length > 0);
|
|
5753
5791
|
}
|
|
5754
5792
|
const SESSION_PROBE_ROUTING_HEADERS = /* @__PURE__ */ new Set([
|
|
5755
5793
|
"x-tenant-id",
|
|
5756
5794
|
"x-tenant",
|
|
5795
|
+
// AdCP's own tenant-routing header (`src/lib/testing/types.ts` names it as
|
|
5796
|
+
// the canonical example). Omitting it meant a run that routes on it had the
|
|
5797
|
+
// header classified as unknown: dropped from session probes, and — once the
|
|
5798
|
+
// isolated-client value test landed — silently strippable on a credential
|
|
5799
|
+
// collision, which reroutes the step to another tenant.
|
|
5800
|
+
"x-adcp-tenant",
|
|
5757
5801
|
"x-account",
|
|
5758
5802
|
"x-account-id",
|
|
5759
5803
|
"x-routing-key",
|
|
@@ -5772,16 +5816,17 @@ function unroutableProbeHeader(options) {
|
|
|
5772
5816
|
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5773
5817
|
const lower = name.toLowerCase();
|
|
5774
5818
|
if (SESSION_PROBE_ROUTING_HEADERS.has(lower)) {
|
|
5819
|
+
if (runSecrets.some((secret) => value.includes(secret))) return { name, reason: "credential_collision" };
|
|
5775
5820
|
try {
|
|
5776
5821
|
assertSafeAuthHeaderPart(value, `options.headers.${name}`);
|
|
5777
5822
|
} catch {
|
|
5778
|
-
return name;
|
|
5823
|
+
return { name, reason: "malformed" };
|
|
5779
5824
|
}
|
|
5780
5825
|
continue;
|
|
5781
5826
|
}
|
|
5782
5827
|
if (AUTH_OVERRIDE_HEADER_NAMES.has(lower)) continue;
|
|
5783
5828
|
if (runSecrets.some((secret) => value.includes(secret))) continue;
|
|
5784
|
-
return name;
|
|
5829
|
+
return { name, reason: "unknown" };
|
|
5785
5830
|
}
|
|
5786
5831
|
return void 0;
|
|
5787
5832
|
}
|
|
@@ -6015,11 +6060,9 @@ function planMcpSessionSentinel(step, options, client, agentUrl) {
|
|
|
6015
6060
|
}
|
|
6016
6061
|
const unroutable = unroutableProbeHeader(options);
|
|
6017
6062
|
if (unroutable !== void 0) {
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
detail: `The runner cannot classify run header "${escapeControlChars(unroutable.slice(0, 64))}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`
|
|
6022
|
-
};
|
|
6063
|
+
const name = escapeControlChars(unroutable.name.slice(0, 64));
|
|
6064
|
+
const detail = unroutable.reason === "credential_collision" ? `Routing header "${name}" has a value containing a credential this run holds. Nothing was graded: forwarding it could authenticate the unauthenticated probe, and dropping it could change tenants. Choose a routing value or suite credential that does not collide.` : unroutable.reason === "malformed" ? `Routing header "${name}" contains invalid header characters. Nothing was graded because dropping it could change tenants. Correct this run header before retrying the probe.` : `The runner cannot classify run header "${name}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`;
|
|
6065
|
+
return { kind: "skip", reason: "session_probe_ungradable", detail };
|
|
6023
6066
|
}
|
|
6024
6067
|
const routing = sessionProbeRoutingHeaders(options);
|
|
6025
6068
|
let headers;
|
|
@@ -6052,6 +6095,11 @@ function authHeadersForStep(directive, options) {
|
|
|
6052
6095
|
if ("value" in directive && directive.value) {
|
|
6053
6096
|
value = directive.value;
|
|
6054
6097
|
} else if ("from_test_kit" in directive && directive.from_test_kit) {
|
|
6098
|
+
if (typeof directive.from_test_kit === "string") {
|
|
6099
|
+
throw new Error(
|
|
6100
|
+
"Named test-kit API-key paths are not supported; use from_test_kit: true only for the primary key."
|
|
6101
|
+
);
|
|
6102
|
+
}
|
|
6055
6103
|
value = options.test_kit?.auth?.api_key;
|
|
6056
6104
|
if (!value) {
|
|
6057
6105
|
throw new Error(
|
|
@@ -6068,6 +6116,13 @@ function authHeadersForStep(directive, options) {
|
|
|
6068
6116
|
}
|
|
6069
6117
|
return { authorization: `Bearer ${value}` };
|
|
6070
6118
|
}
|
|
6119
|
+
const HTTP_PROBE_ONLY_CHECKS = /* @__PURE__ */ new Set([
|
|
6120
|
+
"http_status",
|
|
6121
|
+
"http_status_in",
|
|
6122
|
+
"probe_passed",
|
|
6123
|
+
"on_401_require_header",
|
|
6124
|
+
"resource_equals_agent_url"
|
|
6125
|
+
]);
|
|
6071
6126
|
const AUTH_OVERRIDE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
6072
6127
|
"authorization",
|
|
6073
6128
|
"proxy-authorization",
|
|
@@ -6076,14 +6131,28 @@ const AUTH_OVERRIDE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
6076
6131
|
"x-api-key"
|
|
6077
6132
|
]);
|
|
6078
6133
|
const AUTH_OVERRIDE_CREDENTIAL_HEADER_RE = /(^|[-_])(auth(?:entication|orization)?|credentials?|secrets?|tokens?|keys?|api[-_]?keys?|access[-_]?keys?|private[-_]?keys?|password|passwd|signatures?|cert(?:ificate)?s?)([-_]|$)/i;
|
|
6134
|
+
const AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE = /(auth(?:entication|orization)?|credentials?|secrets?|tokens?|passwords?|passwd|signatures?|certificates?|bearer|(?:api|access|private|session|auth|secret|client|app|master|signing|shared|subscription)keys?|(?:client|tls|ssl)certs?)$/i;
|
|
6079
6135
|
function isCredentialHeaderName(name) {
|
|
6080
6136
|
const normalized = name.toLowerCase();
|
|
6081
|
-
|
|
6137
|
+
if (SESSION_PROBE_ROUTING_HEADERS.has(normalized)) return false;
|
|
6138
|
+
return AUTH_OVERRIDE_HEADER_NAMES.has(normalized) || AUTH_OVERRIDE_CREDENTIAL_HEADER_RE.test(normalized) || AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE.test(normalized.replace(/[-_]/g, ""));
|
|
6082
6139
|
}
|
|
6083
|
-
function
|
|
6084
|
-
const
|
|
6085
|
-
|
|
6086
|
-
)
|
|
6140
|
+
function createAuthOverrideClient(agentUrl, protocol, options, authHeaders) {
|
|
6141
|
+
const runSecrets = runCredentialValues(options);
|
|
6142
|
+
const headers = {};
|
|
6143
|
+
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
6144
|
+
const isRouting = SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase());
|
|
6145
|
+
if (!isRouting && isCredentialHeaderName(name)) continue;
|
|
6146
|
+
if (typeof value === "string" && runSecrets.some((secret) => value.includes(secret))) {
|
|
6147
|
+
if (isRouting) {
|
|
6148
|
+
throw new Error(
|
|
6149
|
+
`options.headers.${name} is a routing header but its value contains a credential this run holds; an isolated step cannot both route correctly and withhold the suite principal. Choose a routing value or suite credential that does not collide.`
|
|
6150
|
+
);
|
|
6151
|
+
}
|
|
6152
|
+
continue;
|
|
6153
|
+
}
|
|
6154
|
+
headers[name] = value;
|
|
6155
|
+
}
|
|
6087
6156
|
let auth;
|
|
6088
6157
|
for (const [name, value] of Object.entries(authHeaders)) {
|
|
6089
6158
|
if (name.toLowerCase() === "authorization" && value.startsWith("Bearer ")) {
|
|
@@ -6092,9 +6161,9 @@ function createA2AAuthOverrideClient(agentUrl, options, authHeaders) {
|
|
|
6092
6161
|
headers[name] = value;
|
|
6093
6162
|
}
|
|
6094
6163
|
}
|
|
6095
|
-
return (0, import_client.createTestClient)(agentUrl,
|
|
6164
|
+
return (0, import_client.createTestClient)(agentUrl, protocol, {
|
|
6096
6165
|
...options,
|
|
6097
|
-
protocol
|
|
6166
|
+
protocol,
|
|
6098
6167
|
auth,
|
|
6099
6168
|
test_kit: void 0,
|
|
6100
6169
|
_client: void 0,
|
|
@@ -570,6 +570,7 @@ function applyBranchSetGrading(phases, phaseResults, branchSetByPhaseId, contrib
|
|
|
570
570
|
step.skip = { reason: "peer_branch_taken", detail };
|
|
571
571
|
delete step.error;
|
|
572
572
|
delete step.adcp_error;
|
|
573
|
+
delete step.counts_toward_failure;
|
|
573
574
|
skippedDelta++;
|
|
574
575
|
regraded = true;
|
|
575
576
|
}
|
|
@@ -2668,6 +2669,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
2668
2669
|
if (!phase.optional || (routingContext ? routedOauthPresent.has(assignment.instanceIndex) : presenceDetected)) {
|
|
2669
2670
|
failedCount++;
|
|
2670
2671
|
countedAsFailed.add(result2);
|
|
2672
|
+
} else if (!result2.validations.some((validation) => validation.check === "assertion" && !validation.passed)) {
|
|
2673
|
+
result2.counts_toward_failure = false;
|
|
2671
2674
|
}
|
|
2672
2675
|
if (step.stateful) {
|
|
2673
2676
|
phaseStatefulCascades.set(phase.id, null);
|
|
@@ -3679,9 +3682,20 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3679
3682
|
const testsIdempotencyKeyOmission = (step.omit_idempotency_key === true || governedRequest && (typeof request.idempotency_key !== "string" || request.idempotency_key.length === 0)) && requestUsesIdempotency(effectiveStep.task, request);
|
|
3680
3683
|
const testsMissingAccount = effectiveStep.task === "create_media_buy" && (step.omit_account === true || governedRequest && !Object.prototype.hasOwnProperty.call(request, "account"));
|
|
3681
3684
|
const testsSchemaInvalidRequest = step.expect_error === true && step.negative_path !== "payload_well_formed";
|
|
3685
|
+
const useSdkAuthOverride = typeof step.auth === "object" && step.auth.type === "api_key" && step.auth.from_test_kit === true && step.auth.value_strategy === void 0 && step.expect_error !== true && !(step.validations ?? []).some((validation) => HTTP_PROBE_ONLY_CHECKS.has(validation.check));
|
|
3682
3686
|
let rawProbeHeaders;
|
|
3687
|
+
let authOverrideClient;
|
|
3683
3688
|
try {
|
|
3684
3689
|
rawProbeHeaders = step.auth !== void 0 ? authHeadersForStep(step.auth, options) : void 0;
|
|
3690
|
+
if (useSdkAuthOverride) {
|
|
3691
|
+
if (rawProbeHeaders === void 0) throw new Error("Step auth override credentials were not resolved");
|
|
3692
|
+
authOverrideClient = createAuthOverrideClient(
|
|
3693
|
+
runState.agentUrl,
|
|
3694
|
+
options.protocol ?? "mcp",
|
|
3695
|
+
options,
|
|
3696
|
+
rawProbeHeaders
|
|
3697
|
+
);
|
|
3698
|
+
}
|
|
3685
3699
|
} catch (err) {
|
|
3686
3700
|
return {
|
|
3687
3701
|
step_id: step.id,
|
|
@@ -3696,7 +3710,8 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3696
3710
|
extraction: { path: "none" }
|
|
3697
3711
|
};
|
|
3698
3712
|
}
|
|
3699
|
-
const useRawProbe = rawProbeHeaders !== void 0;
|
|
3713
|
+
const useRawProbe = rawProbeHeaders !== void 0 && !useSdkAuthOverride;
|
|
3714
|
+
const stepClient = () => authOverrideClient ?? client;
|
|
3700
3715
|
let taskResult;
|
|
3701
3716
|
let stepResult;
|
|
3702
3717
|
let caughtError;
|
|
@@ -3780,7 +3795,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3780
3795
|
const started = Date.now();
|
|
3781
3796
|
try {
|
|
3782
3797
|
if (options.protocol === "a2a") {
|
|
3783
|
-
const probeClient =
|
|
3798
|
+
const probeClient = createAuthOverrideClient(runState.agentUrl, "a2a", options, rawProbeHeaders ?? {});
|
|
3784
3799
|
const captured = await withRawResponseCapture(
|
|
3785
3800
|
() => runStep(
|
|
3786
3801
|
step.title,
|
|
@@ -3875,7 +3890,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3875
3890
|
let a2aCaptures;
|
|
3876
3891
|
if (step.parallel_dispatch) {
|
|
3877
3892
|
const started = Date.now();
|
|
3878
|
-
crossResponses = await runParallelDispatches(
|
|
3893
|
+
crossResponses = await runParallelDispatches(stepClient(), effectiveStep.task, request, {
|
|
3879
3894
|
spec: step.parallel_dispatch,
|
|
3880
3895
|
keyMinter: generateIdempotencyKey,
|
|
3881
3896
|
correlationPrefix: step.id,
|
|
@@ -3912,7 +3927,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
|
|
|
3912
3927
|
};
|
|
3913
3928
|
}
|
|
3914
3929
|
} else {
|
|
3915
|
-
const dispatch = () => executeStoryboardTask(
|
|
3930
|
+
const dispatch = () => executeStoryboardTask(stepClient(), effectiveStep.task, request, {
|
|
3916
3931
|
skipIdempotencyAutoInject: testsIdempotencyKeyOmission,
|
|
3917
3932
|
skipAccountValidation: testsMissingAccount,
|
|
3918
3933
|
skipRequestValidation: testsSchemaInvalidRequest,
|
|
@@ -5721,8 +5736,10 @@ function defaultAuthHeadersForRawProbe(options) {
|
|
|
5721
5736
|
}
|
|
5722
5737
|
function sessionProbeRoutingHeaders(options) {
|
|
5723
5738
|
const headers = {};
|
|
5739
|
+
const runSecrets = runCredentialValues(options);
|
|
5724
5740
|
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5725
5741
|
if (!SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase())) continue;
|
|
5742
|
+
if (runSecrets.some((secret) => value.includes(secret))) continue;
|
|
5726
5743
|
try {
|
|
5727
5744
|
assertSafeAuthHeaderPart(value, `options.headers.${name}`);
|
|
5728
5745
|
} catch {
|
|
@@ -5747,35 +5764,62 @@ function setHeaderIfAbsent(headers, name, value, label) {
|
|
|
5747
5764
|
}
|
|
5748
5765
|
function runCredentialValues(options) {
|
|
5749
5766
|
const values = [];
|
|
5767
|
+
const pushHeaderToken = (value) => {
|
|
5768
|
+
values.push(value, value.replace(/^[\t ]+|[\t ]+$/g, ""));
|
|
5769
|
+
};
|
|
5770
|
+
const pushUserPass = (userpass) => {
|
|
5771
|
+
values.push(userpass, Buffer.from(userpass).toString("base64"));
|
|
5772
|
+
const separator = userpass.indexOf(":");
|
|
5773
|
+
if (separator >= 0) values.push(userpass.slice(separator + 1));
|
|
5774
|
+
};
|
|
5750
5775
|
const auth = options.auth;
|
|
5751
|
-
if (auth?.type === "bearer" && typeof auth.token === "string")
|
|
5776
|
+
if (auth?.type === "bearer" && typeof auth.token === "string") pushHeaderToken(auth.token);
|
|
5752
5777
|
if (auth?.type === "basic") {
|
|
5753
5778
|
if (typeof auth.password === "string") values.push(auth.password);
|
|
5754
5779
|
if (typeof auth.username === "string" && typeof auth.password === "string") {
|
|
5755
|
-
|
|
5780
|
+
pushUserPass(`${auth.username}:${auth.password}`);
|
|
5756
5781
|
}
|
|
5757
5782
|
}
|
|
5758
5783
|
if (auth?.type === "oauth" || auth?.type === "oauth_client_credentials") {
|
|
5759
5784
|
const token = auth.tokens?.access_token;
|
|
5760
|
-
if (typeof token === "string")
|
|
5785
|
+
if (typeof token === "string") pushHeaderToken(token);
|
|
5761
5786
|
}
|
|
5762
5787
|
const kit = options.test_kit?.auth;
|
|
5763
|
-
if (typeof kit?.api_key === "string")
|
|
5788
|
+
if (typeof kit?.api_key === "string") pushHeaderToken(kit.api_key);
|
|
5764
5789
|
const basic = kit?.basic;
|
|
5765
5790
|
if (typeof basic?.password === "string") values.push(basic.password);
|
|
5766
5791
|
if (typeof basic?.username === "string" && typeof basic?.password === "string") {
|
|
5767
|
-
|
|
5792
|
+
pushUserPass(`${basic.username}:${basic.password}`);
|
|
5768
5793
|
}
|
|
5769
|
-
if (typeof basic?.credentials === "string")
|
|
5794
|
+
if (typeof basic?.credentials === "string") pushUserPass(basic.credentials);
|
|
5770
5795
|
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5771
5796
|
if (typeof value !== "string" || value.length === 0) continue;
|
|
5772
|
-
if (AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase())
|
|
5797
|
+
if (!AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase()) && !isCredentialHeaderName(name)) continue;
|
|
5798
|
+
pushHeaderToken(value);
|
|
5799
|
+
const scheme = /^(Bearer|Basic|Token|ApiKey)\s+(.+)$/i.exec(value.trim());
|
|
5800
|
+
if (scheme?.[1] !== void 0 && scheme[2] !== void 0) {
|
|
5801
|
+
const payload = scheme[2].trim();
|
|
5802
|
+
values.push(payload);
|
|
5803
|
+
if (/^Basic$/i.test(scheme[1]) && /^[A-Za-z0-9+/]+={0,2}$/.test(payload)) {
|
|
5804
|
+
const bytes = Buffer.from(payload, "base64");
|
|
5805
|
+
const decoded = bytes.toString("utf8");
|
|
5806
|
+
if (bytes.toString("base64").replace(/=+$/, "") === payload.replace(/=+$/, "") && Buffer.from(decoded, "utf8").equals(bytes) && !/[\x00-\x1f\x7f]/.test(decoded) && decoded.includes(":")) {
|
|
5807
|
+
pushUserPass(decoded);
|
|
5808
|
+
}
|
|
5809
|
+
}
|
|
5810
|
+
}
|
|
5773
5811
|
}
|
|
5774
5812
|
return values.filter((value) => value.trim().length > 0);
|
|
5775
5813
|
}
|
|
5776
5814
|
const SESSION_PROBE_ROUTING_HEADERS = /* @__PURE__ */ new Set([
|
|
5777
5815
|
"x-tenant-id",
|
|
5778
5816
|
"x-tenant",
|
|
5817
|
+
// AdCP's own tenant-routing header (`src/lib/testing/types.ts` names it as
|
|
5818
|
+
// the canonical example). Omitting it meant a run that routes on it had the
|
|
5819
|
+
// header classified as unknown: dropped from session probes, and — once the
|
|
5820
|
+
// isolated-client value test landed — silently strippable on a credential
|
|
5821
|
+
// collision, which reroutes the step to another tenant.
|
|
5822
|
+
"x-adcp-tenant",
|
|
5779
5823
|
"x-account",
|
|
5780
5824
|
"x-account-id",
|
|
5781
5825
|
"x-routing-key",
|
|
@@ -5794,16 +5838,17 @@ function unroutableProbeHeader(options) {
|
|
|
5794
5838
|
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
5795
5839
|
const lower = name.toLowerCase();
|
|
5796
5840
|
if (SESSION_PROBE_ROUTING_HEADERS.has(lower)) {
|
|
5841
|
+
if (runSecrets.some((secret) => value.includes(secret))) return { name, reason: "credential_collision" };
|
|
5797
5842
|
try {
|
|
5798
5843
|
assertSafeAuthHeaderPart(value, `options.headers.${name}`);
|
|
5799
5844
|
} catch {
|
|
5800
|
-
return name;
|
|
5845
|
+
return { name, reason: "malformed" };
|
|
5801
5846
|
}
|
|
5802
5847
|
continue;
|
|
5803
5848
|
}
|
|
5804
5849
|
if (AUTH_OVERRIDE_HEADER_NAMES.has(lower)) continue;
|
|
5805
5850
|
if (runSecrets.some((secret) => value.includes(secret))) continue;
|
|
5806
|
-
return name;
|
|
5851
|
+
return { name, reason: "unknown" };
|
|
5807
5852
|
}
|
|
5808
5853
|
return void 0;
|
|
5809
5854
|
}
|
|
@@ -6037,11 +6082,9 @@ function planMcpSessionSentinel(step, options, client, agentUrl) {
|
|
|
6037
6082
|
}
|
|
6038
6083
|
const unroutable = unroutableProbeHeader(options);
|
|
6039
6084
|
if (unroutable !== void 0) {
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
detail: `The runner cannot classify run header "${escapeControlChars(unroutable.slice(0, 64))}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`
|
|
6044
|
-
};
|
|
6085
|
+
const name = escapeControlChars(unroutable.name.slice(0, 64));
|
|
6086
|
+
const detail = unroutable.reason === "credential_collision" ? `Routing header "${name}" has a value containing a credential this run holds. Nothing was graded: forwarding it could authenticate the unauthenticated probe, and dropping it could change tenants. Choose a routing value or suite credential that does not collide.` : unroutable.reason === "malformed" ? `Routing header "${name}" contains invalid header characters. Nothing was graded because dropping it could change tenants. Correct this run header before retrying the probe.` : `The runner cannot classify run header "${name}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`;
|
|
6087
|
+
return { kind: "skip", reason: "session_probe_ungradable", detail };
|
|
6045
6088
|
}
|
|
6046
6089
|
const routing = sessionProbeRoutingHeaders(options);
|
|
6047
6090
|
let headers;
|
|
@@ -6074,6 +6117,11 @@ function authHeadersForStep(directive, options) {
|
|
|
6074
6117
|
if ("value" in directive && directive.value) {
|
|
6075
6118
|
value = directive.value;
|
|
6076
6119
|
} else if ("from_test_kit" in directive && directive.from_test_kit) {
|
|
6120
|
+
if (typeof directive.from_test_kit === "string") {
|
|
6121
|
+
throw new Error(
|
|
6122
|
+
"Named test-kit API-key paths are not supported; use from_test_kit: true only for the primary key."
|
|
6123
|
+
);
|
|
6124
|
+
}
|
|
6077
6125
|
value = options.test_kit?.auth?.api_key;
|
|
6078
6126
|
if (!value) {
|
|
6079
6127
|
throw new Error(
|
|
@@ -6090,6 +6138,13 @@ function authHeadersForStep(directive, options) {
|
|
|
6090
6138
|
}
|
|
6091
6139
|
return { authorization: `Bearer ${value}` };
|
|
6092
6140
|
}
|
|
6141
|
+
const HTTP_PROBE_ONLY_CHECKS = /* @__PURE__ */ new Set([
|
|
6142
|
+
"http_status",
|
|
6143
|
+
"http_status_in",
|
|
6144
|
+
"probe_passed",
|
|
6145
|
+
"on_401_require_header",
|
|
6146
|
+
"resource_equals_agent_url"
|
|
6147
|
+
]);
|
|
6093
6148
|
const AUTH_OVERRIDE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
6094
6149
|
"authorization",
|
|
6095
6150
|
"proxy-authorization",
|
|
@@ -6098,14 +6153,28 @@ const AUTH_OVERRIDE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
|
6098
6153
|
"x-api-key"
|
|
6099
6154
|
]);
|
|
6100
6155
|
const AUTH_OVERRIDE_CREDENTIAL_HEADER_RE = /(^|[-_])(auth(?:entication|orization)?|credentials?|secrets?|tokens?|keys?|api[-_]?keys?|access[-_]?keys?|private[-_]?keys?|password|passwd|signatures?|cert(?:ificate)?s?)([-_]|$)/i;
|
|
6156
|
+
const AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE = /(auth(?:entication|orization)?|credentials?|secrets?|tokens?|passwords?|passwd|signatures?|certificates?|bearer|(?:api|access|private|session|auth|secret|client|app|master|signing|shared|subscription)keys?|(?:client|tls|ssl)certs?)$/i;
|
|
6101
6157
|
function isCredentialHeaderName(name) {
|
|
6102
6158
|
const normalized = name.toLowerCase();
|
|
6103
|
-
|
|
6159
|
+
if (SESSION_PROBE_ROUTING_HEADERS.has(normalized)) return false;
|
|
6160
|
+
return AUTH_OVERRIDE_HEADER_NAMES.has(normalized) || AUTH_OVERRIDE_CREDENTIAL_HEADER_RE.test(normalized) || AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE.test(normalized.replace(/[-_]/g, ""));
|
|
6104
6161
|
}
|
|
6105
|
-
function
|
|
6106
|
-
const
|
|
6107
|
-
|
|
6108
|
-
)
|
|
6162
|
+
function createAuthOverrideClient(agentUrl, protocol, options, authHeaders) {
|
|
6163
|
+
const runSecrets = runCredentialValues(options);
|
|
6164
|
+
const headers = {};
|
|
6165
|
+
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
6166
|
+
const isRouting = SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase());
|
|
6167
|
+
if (!isRouting && isCredentialHeaderName(name)) continue;
|
|
6168
|
+
if (typeof value === "string" && runSecrets.some((secret) => value.includes(secret))) {
|
|
6169
|
+
if (isRouting) {
|
|
6170
|
+
throw new Error(
|
|
6171
|
+
`options.headers.${name} is a routing header but its value contains a credential this run holds; an isolated step cannot both route correctly and withhold the suite principal. Choose a routing value or suite credential that does not collide.`
|
|
6172
|
+
);
|
|
6173
|
+
}
|
|
6174
|
+
continue;
|
|
6175
|
+
}
|
|
6176
|
+
headers[name] = value;
|
|
6177
|
+
}
|
|
6109
6178
|
let auth;
|
|
6110
6179
|
for (const [name, value] of Object.entries(authHeaders)) {
|
|
6111
6180
|
if (name.toLowerCase() === "authorization" && value.startsWith("Bearer ")) {
|
|
@@ -6114,9 +6183,9 @@ function createA2AAuthOverrideClient(agentUrl, options, authHeaders) {
|
|
|
6114
6183
|
headers[name] = value;
|
|
6115
6184
|
}
|
|
6116
6185
|
}
|
|
6117
|
-
return createTestClient(agentUrl,
|
|
6186
|
+
return createTestClient(agentUrl, protocol, {
|
|
6118
6187
|
...options,
|
|
6119
|
-
protocol
|
|
6188
|
+
protocol,
|
|
6120
6189
|
auth,
|
|
6121
6190
|
test_kit: void 0,
|
|
6122
6191
|
_client: void 0,
|
|
@@ -2395,6 +2395,12 @@ export interface StoryboardStepResult {
|
|
|
2395
2395
|
title: string;
|
|
2396
2396
|
task: string;
|
|
2397
2397
|
passed: boolean;
|
|
2398
|
+
/**
|
|
2399
|
+
* False when a failed step is diagnostic only and does not count toward
|
|
2400
|
+
* the storyboard verdict (for example, an optional discovery phase).
|
|
2401
|
+
* Absent on ordinary failures, including mandatory OAuth and invariant checks.
|
|
2402
|
+
*/
|
|
2403
|
+
counts_toward_failure?: boolean;
|
|
2398
2404
|
/** True when the step was not executed */
|
|
2399
2405
|
skipped?: boolean;
|
|
2400
2406
|
/**
|
|
@@ -2395,6 +2395,12 @@ export interface StoryboardStepResult {
|
|
|
2395
2395
|
title: string;
|
|
2396
2396
|
task: string;
|
|
2397
2397
|
passed: boolean;
|
|
2398
|
+
/**
|
|
2399
|
+
* False when a failed step is diagnostic only and does not count toward
|
|
2400
|
+
* the storyboard verdict (for example, an optional discovery phase).
|
|
2401
|
+
* Absent on ordinary failures, including mandatory OAuth and invariant checks.
|
|
2402
|
+
*/
|
|
2403
|
+
counts_toward_failure?: boolean;
|
|
2398
2404
|
/** True when the step was not executed */
|
|
2399
2405
|
skipped?: boolean;
|
|
2400
2406
|
/**
|
|
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
|
|
|
197
197
|
*/
|
|
198
198
|
export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
|
|
199
199
|
/** Capability semver emitted in run summaries and used for advisory expiry. */
|
|
200
|
-
export declare const RUNNER_CAPABILITY_VERSION = "15.9.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "15.9.3";
|
|
201
201
|
/** True when a failed validation contributes to the owning step's grade. */
|
|
202
202
|
export declare function validationFailsStep(result: ValidationResult): boolean;
|
|
203
203
|
/**
|
|
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
|
|
|
197
197
|
*/
|
|
198
198
|
export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
|
|
199
199
|
/** Capability semver emitted in run summaries and used for advisory expiry. */
|
|
200
|
-
export declare const RUNNER_CAPABILITY_VERSION = "15.9.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "15.9.3";
|
|
201
201
|
/** True when a failed validation contributes to the owning step's grade. */
|
|
202
202
|
export declare function validationFailsStep(result: ValidationResult): boolean;
|
|
203
203
|
/**
|
|
@@ -46,6 +46,7 @@ __export(schema_loader_exports, {
|
|
|
46
46
|
listValidatorKeys: () => listValidatorKeys,
|
|
47
47
|
registerExternalSchemaRoot: () => registerExternalSchemaRoot,
|
|
48
48
|
resolveBundleKey: () => resolveBundleKey,
|
|
49
|
+
resolveServedValidationVersion: () => resolveServedValidationVersion,
|
|
49
50
|
schemaAllowsTopLevelField: () => schemaAllowsTopLevelField,
|
|
50
51
|
toReleasePrecisionWire: () => toReleasePrecisionWire,
|
|
51
52
|
unregisterExternalSchemaRoot: () => unregisterExternalSchemaRoot,
|
|
@@ -718,6 +719,29 @@ function hasSchemaBundle(version) {
|
|
|
718
719
|
return false;
|
|
719
720
|
}
|
|
720
721
|
}
|
|
722
|
+
const SERVED_RELEASE_MAJOR = /^(\d+)\.\d+(?:-[a-zA-Z0-9.-]+)?$/;
|
|
723
|
+
const NUMERIC_PIN_MAJOR = /^(\d+)\.\d+/;
|
|
724
|
+
function resolveServedValidationVersion(response, pinnedVersion) {
|
|
725
|
+
const pinMajor = NUMERIC_PIN_MAJOR.exec(pinnedVersion)?.[1];
|
|
726
|
+
if (pinMajor === void 0) return pinnedVersion;
|
|
727
|
+
try {
|
|
728
|
+
if (isExternalSchemaRootActive(pinnedVersion)) return pinnedVersion;
|
|
729
|
+
} catch {
|
|
730
|
+
return pinnedVersion;
|
|
731
|
+
}
|
|
732
|
+
const echoed = response !== null && typeof response === "object" ? response.adcp_version : void 0;
|
|
733
|
+
if (typeof echoed !== "string") return pinnedVersion;
|
|
734
|
+
const echoMajor = SERVED_RELEASE_MAJOR.exec(echoed)?.[1];
|
|
735
|
+
if (echoMajor === void 0 || echoMajor !== pinMajor) return pinnedVersion;
|
|
736
|
+
let pinnedRelease;
|
|
737
|
+
try {
|
|
738
|
+
pinnedRelease = toReleasePrecisionWire(pinnedVersion);
|
|
739
|
+
} catch {
|
|
740
|
+
return pinnedVersion;
|
|
741
|
+
}
|
|
742
|
+
if (echoed === pinnedRelease) return pinnedVersion;
|
|
743
|
+
return hasSchemaBundle(echoed) ? echoed : pinnedVersion;
|
|
744
|
+
}
|
|
721
745
|
const mcpToolSchemaCache = /* @__PURE__ */ new Map();
|
|
722
746
|
const mcpToolSummaryCache = /* @__PURE__ */ new Map();
|
|
723
747
|
function boundedMcpToolSummary(value) {
|
|
@@ -981,6 +1005,7 @@ function cloneJsonValue(value) {
|
|
|
981
1005
|
listValidatorKeys,
|
|
982
1006
|
registerExternalSchemaRoot,
|
|
983
1007
|
resolveBundleKey,
|
|
1008
|
+
resolveServedValidationVersion,
|
|
984
1009
|
schemaAllowsTopLevelField,
|
|
985
1010
|
toReleasePrecisionWire,
|
|
986
1011
|
unregisterExternalSchemaRoot,
|
|
@@ -668,6 +668,29 @@ function hasSchemaBundle(version) {
|
|
|
668
668
|
return false;
|
|
669
669
|
}
|
|
670
670
|
}
|
|
671
|
+
const SERVED_RELEASE_MAJOR = /^(\d+)\.\d+(?:-[a-zA-Z0-9.-]+)?$/;
|
|
672
|
+
const NUMERIC_PIN_MAJOR = /^(\d+)\.\d+/;
|
|
673
|
+
function resolveServedValidationVersion(response, pinnedVersion) {
|
|
674
|
+
const pinMajor = NUMERIC_PIN_MAJOR.exec(pinnedVersion)?.[1];
|
|
675
|
+
if (pinMajor === void 0) return pinnedVersion;
|
|
676
|
+
try {
|
|
677
|
+
if (isExternalSchemaRootActive(pinnedVersion)) return pinnedVersion;
|
|
678
|
+
} catch {
|
|
679
|
+
return pinnedVersion;
|
|
680
|
+
}
|
|
681
|
+
const echoed = response !== null && typeof response === "object" ? response.adcp_version : void 0;
|
|
682
|
+
if (typeof echoed !== "string") return pinnedVersion;
|
|
683
|
+
const echoMajor = SERVED_RELEASE_MAJOR.exec(echoed)?.[1];
|
|
684
|
+
if (echoMajor === void 0 || echoMajor !== pinMajor) return pinnedVersion;
|
|
685
|
+
let pinnedRelease;
|
|
686
|
+
try {
|
|
687
|
+
pinnedRelease = toReleasePrecisionWire(pinnedVersion);
|
|
688
|
+
} catch {
|
|
689
|
+
return pinnedVersion;
|
|
690
|
+
}
|
|
691
|
+
if (echoed === pinnedRelease) return pinnedVersion;
|
|
692
|
+
return hasSchemaBundle(echoed) ? echoed : pinnedVersion;
|
|
693
|
+
}
|
|
671
694
|
const mcpToolSchemaCache = /* @__PURE__ */ new Map();
|
|
672
695
|
const mcpToolSummaryCache = /* @__PURE__ */ new Map();
|
|
673
696
|
function boundedMcpToolSummary(value) {
|
|
@@ -930,6 +953,7 @@ export {
|
|
|
930
953
|
listValidatorKeys,
|
|
931
954
|
registerExternalSchemaRoot,
|
|
932
955
|
resolveBundleKey,
|
|
956
|
+
resolveServedValidationVersion,
|
|
933
957
|
schemaAllowsTopLevelField,
|
|
934
958
|
toReleasePrecisionWire,
|
|
935
959
|
unregisterExternalSchemaRoot,
|
package/dist/lib/version.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AdCP SDK library version
|
|
3
3
|
*/
|
|
4
|
-
export declare const LIBRARY_VERSION = "15.9.
|
|
4
|
+
export declare const LIBRARY_VERSION = "15.9.3";
|
|
5
5
|
/**
|
|
6
6
|
* AdCP specification version this library is built for
|
|
7
7
|
*/
|
|
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
|
|
|
33
33
|
* Full version information
|
|
34
34
|
*/
|
|
35
35
|
export declare const VERSION_INFO: {
|
|
36
|
-
readonly library: "15.9.
|
|
36
|
+
readonly library: "15.9.3";
|
|
37
37
|
readonly adcp: "3.2.4";
|
|
38
38
|
readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4"];
|
|
39
|
-
readonly generatedAt: "2026-10-
|
|
39
|
+
readonly generatedAt: "2026-10-16T14:25:50.306Z";
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Get the AdCP specification version this library is built for
|
package/dist/lib/version.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AdCP SDK library version
|
|
3
3
|
*/
|
|
4
|
-
export declare const LIBRARY_VERSION = "15.9.
|
|
4
|
+
export declare const LIBRARY_VERSION = "15.9.3";
|
|
5
5
|
/**
|
|
6
6
|
* AdCP specification version this library is built for
|
|
7
7
|
*/
|
|
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
|
|
|
33
33
|
* Full version information
|
|
34
34
|
*/
|
|
35
35
|
export declare const VERSION_INFO: {
|
|
36
|
-
readonly library: "15.9.
|
|
36
|
+
readonly library: "15.9.3";
|
|
37
37
|
readonly adcp: "3.2.4";
|
|
38
38
|
readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4"];
|
|
39
|
-
readonly generatedAt: "2026-10-
|
|
39
|
+
readonly generatedAt: "2026-10-16T14:25:50.306Z";
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Get the AdCP specification version this library is built for
|
package/dist/lib/version.js
CHANGED
|
@@ -31,7 +31,7 @@ __export(version_exports, {
|
|
|
31
31
|
toReleasePrecisionVersion: () => toReleasePrecisionVersion
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(version_exports);
|
|
34
|
-
const LIBRARY_VERSION = "15.9.
|
|
34
|
+
const LIBRARY_VERSION = "15.9.3";
|
|
35
35
|
const ADCP_VERSION = "3.2.4";
|
|
36
36
|
const ADCP_MAJOR_VERSION = 3;
|
|
37
37
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -98,10 +98,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
98
98
|
"3.2.4"
|
|
99
99
|
];
|
|
100
100
|
const VERSION_INFO = {
|
|
101
|
-
library: "15.9.
|
|
101
|
+
library: "15.9.3",
|
|
102
102
|
adcp: "3.2.4",
|
|
103
103
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
104
|
-
generatedAt: "2026-10-
|
|
104
|
+
generatedAt: "2026-10-16T14:25:50.306Z"
|
|
105
105
|
};
|
|
106
106
|
function getAdcpVersion() {
|
|
107
107
|
return ADCP_VERSION;
|
package/dist/lib/version.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const LIBRARY_VERSION = "15.9.
|
|
1
|
+
const LIBRARY_VERSION = "15.9.3";
|
|
2
2
|
const ADCP_VERSION = "3.2.4";
|
|
3
3
|
const ADCP_MAJOR_VERSION = 3;
|
|
4
4
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -65,10 +65,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
65
65
|
"3.2.4"
|
|
66
66
|
];
|
|
67
67
|
const VERSION_INFO = {
|
|
68
|
-
library: "15.9.
|
|
68
|
+
library: "15.9.3",
|
|
69
69
|
adcp: "3.2.4",
|
|
70
70
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
71
|
-
generatedAt: "2026-10-
|
|
71
|
+
generatedAt: "2026-10-16T14:25:50.306Z"
|
|
72
72
|
};
|
|
73
73
|
function getAdcpVersion() {
|
|
74
74
|
return ADCP_VERSION;
|
package/docs/TYPE-SUMMARY.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AdCP Type Summary
|
|
2
2
|
|
|
3
|
-
> Generated at: 2026-10-
|
|
4
|
-
> @adcp/sdk v15.9.
|
|
3
|
+
> Generated at: 2026-10-16
|
|
4
|
+
> @adcp/sdk v15.9.3
|
|
5
5
|
|
|
6
6
|
Curated reference of the types that matter for using the AdCP client. For full generated types see `src/lib/types/tools.generated.ts` and `src/lib/types/core.generated.ts`.
|
|
7
7
|
|
package/docs/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Ad Context Protocol (AdCP)
|
|
2
2
|
|
|
3
|
-
> Generated at: 2026-10-
|
|
4
|
-
> Library: @adcp/sdk v15.9.
|
|
3
|
+
> Generated at: 2026-10-16
|
|
4
|
+
> Library: @adcp/sdk v15.9.3
|
|
5
5
|
> AdCP major version: 3
|
|
6
6
|
> Canonical URL: https://adcontextprotocol.github.io/adcp-client/llms.txt
|
|
7
7
|
> Note: the `Library` stamp reflects the package.json version at doc-generation time. The narrative below describes the surface that lands on the next-published minor — including any 6.7 helpers documented here ahead of the release tag.
|
|
@@ -11,8 +11,8 @@ below as the publication/deployment gate.
|
|
|
11
11
|
|
|
12
12
|
| Fact | Value |
|
|
13
13
|
| --- | --- |
|
|
14
|
-
| Exact npm package | `@adcp/sdk@15.9.
|
|
15
|
-
| npm integrity | registry-derived after publication; run `npm view @adcp/sdk@15.9.
|
|
14
|
+
| Exact npm package | `@adcp/sdk@15.9.3` |
|
|
15
|
+
| npm integrity | registry-derived after publication; run `npm view @adcp/sdk@15.9.3 dist.integrity` |
|
|
16
16
|
| Node.js runtime | `^20.19.0 || >=22.12.0` |
|
|
17
17
|
| Default AdCP wire release | `3.2.4` |
|
|
18
18
|
| Maintained wire releases | `v2.5`, `v2.6`, `v3`, `3.0.0`, `3.0`, `3.0.1`, `3.0.2`, `3.0.3`, `3.0.4`, `3.0.5`, `3.0.6`, `3.0.7`, `3.0.8`, `3.0.9`, `3.0.10`, `3.0.11`, `3.0.12`, `3.0.13`, `3.0.14`, `3.0.15`, `3.0.16`, `3.0.17`, `3.0.18`, `3.0.19`, `3.0.20`, `3.0.21`, `3.0.22`, `3.0.23`, `3.0.24`, `3.0.25`, `3.1.0`, `3.1`, `3.1.1`, `3.1.2`, `3.1.3`, `3.1.4`, `3.1.5`, `3.1.6`, `3.1.7`, `3.1.8`, `3.1.9`, `3.1.10`, `3.1.11`, `3.1.12`, `3.1.13`, `3.1.14`, `3.1.15`, `3.1.16`, `3.1.17`, `3.1.18`, `3.1.19`, `3.1.20`, `3.1.21`, `3.1.22`, `3.1.23`, `3.1.24`, `3.2.1`, `3.2`, `3.2.2`, `3.2.3`, `3.2.4` |
|
|
@@ -21,8 +21,8 @@ below as the publication/deployment gate.
|
|
|
21
21
|
Install exact production inputs rather than a moving range or dist-tag:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
npm install --save-exact '@adcp/sdk@15.9.
|
|
25
|
-
npm view '@adcp/sdk@15.9.
|
|
24
|
+
npm install --save-exact '@adcp/sdk@15.9.3'
|
|
25
|
+
npm view '@adcp/sdk@15.9.3' dist.integrity
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
### Required and optional peers
|