@adcp/sdk 9.1.2 → 9.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +8 -8
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +9 -5
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +2 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/test-controller.d.ts +4 -1
- package/dist/lib/server/test-controller.d.ts.map +1 -1
- package/dist/lib/server/test-controller.js +18 -0
- package/dist/lib/server/test-controller.js.map +1 -1
- package/dist/lib/testing/comply-controller.d.ts +8 -0
- package/dist/lib/testing/comply-controller.d.ts.map +1 -1
- package/dist/lib/testing/comply-controller.js +7 -0
- package/dist/lib/testing/comply-controller.js.map +1 -1
- package/dist/lib/testing/index.d.ts +1 -1
- package/dist/lib/testing/index.d.ts.map +1 -1
- package/dist/lib/testing/index.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts +8 -5
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +106 -17
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/seeding.d.ts +1 -1
- package/dist/lib/testing/storyboard/seeding.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/seeding.js +20 -0
- package/dist/lib/testing/storyboard/seeding.js.map +1 -1
- package/dist/lib/testing/storyboard/types.d.ts +24 -10
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/types.js +1 -0
- package/dist/lib/testing/storyboard/types.js.map +1 -1
- package/dist/lib/v2/projection/augment-response.d.ts +67 -1
- package/dist/lib/v2/projection/augment-response.d.ts.map +1 -1
- package/dist/lib/v2/projection/augment-response.js +151 -1
- package/dist/lib/v2/projection/augment-response.js.map +1 -1
- package/dist/lib/v2/projection/index.d.ts +14 -4
- package/dist/lib/v2/projection/index.d.ts.map +1 -1
- package/dist/lib/v2/projection/index.js +16 -2
- package/dist/lib/v2/projection/index.js.map +1 -1
- package/dist/lib/v2/projection/types.d.ts +36 -0
- package/dist/lib/v2/projection/types.d.ts.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.d.ts +104 -1
- package/dist/lib/v2/projection/v1-to-v2.d.ts.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.js +107 -0
- package/dist/lib/v2/projection/v1-to-v2.js.map +1 -1
- package/dist/lib/validation/schema-loader.js +57 -0
- package/dist/lib/validation/schema-loader.js.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/package.json +1 -1
|
@@ -169,10 +169,44 @@ function resolveCapabilityPath(raw, dottedPath) {
|
|
|
169
169
|
for (const key of keys) {
|
|
170
170
|
if (current === null || typeof current !== 'object')
|
|
171
171
|
return undefined;
|
|
172
|
+
if (!Object.prototype.hasOwnProperty.call(current, key))
|
|
173
|
+
return undefined;
|
|
172
174
|
current = current[key];
|
|
173
175
|
}
|
|
174
176
|
return current;
|
|
175
177
|
}
|
|
178
|
+
const GET_ADCP_CAPABILITIES_RESPONSE_SCHEMA_REF = 'protocol/get-adcp-capabilities-response.json';
|
|
179
|
+
function resolveCapabilityPathForGate(raw, predicate, adcpVersion) {
|
|
180
|
+
const actual = resolveCapabilityPath(raw, predicate.path);
|
|
181
|
+
if (actual !== undefined)
|
|
182
|
+
return actual;
|
|
183
|
+
// `present:` is an absence-detection matcher — an absent field IS the
|
|
184
|
+
// load-bearing signal. Materializing a schema default would make a defaulted
|
|
185
|
+
// field never read as absent, silently flipping the gate (e.g. a signals
|
|
186
|
+
// seller that omits `signals.discovery_modes`, default `["brief"]`, would run
|
|
187
|
+
// a `present: true`-gated scenario that should skip). Defaults are resolved
|
|
188
|
+
// only for the value matchers (`equals` / `contains`), where the default's
|
|
189
|
+
// VALUE is what the gate tests.
|
|
190
|
+
if ('present' in predicate)
|
|
191
|
+
return undefined;
|
|
192
|
+
if (!schemaDefaultShouldApply(raw, predicate.path))
|
|
193
|
+
return undefined;
|
|
194
|
+
return (0, schema_loader_1.getSchemaDefaultByPath)(GET_ADCP_CAPABILITIES_RESPONSE_SCHEMA_REF, predicate.path, adcpVersion);
|
|
195
|
+
}
|
|
196
|
+
function schemaDefaultShouldApply(raw, dottedPath) {
|
|
197
|
+
const keys = dottedPath.split('.');
|
|
198
|
+
if (keys.length <= 1)
|
|
199
|
+
return raw !== null && typeof raw === 'object';
|
|
200
|
+
let current = raw;
|
|
201
|
+
for (const key of keys.slice(0, -1)) {
|
|
202
|
+
if (current === null || typeof current !== 'object')
|
|
203
|
+
return false;
|
|
204
|
+
if (!Object.prototype.hasOwnProperty.call(current, key))
|
|
205
|
+
return false;
|
|
206
|
+
current = current[key];
|
|
207
|
+
}
|
|
208
|
+
return current !== null && typeof current === 'object';
|
|
209
|
+
}
|
|
176
210
|
/**
|
|
177
211
|
* Evaluate a `requires_capability` predicate against the value already
|
|
178
212
|
* resolved from the agent's raw capabilities. Returns `null` when the
|
|
@@ -182,8 +216,8 @@ function resolveCapabilityPath(raw, dottedPath) {
|
|
|
182
216
|
* Three matcher forms — see `Storyboard.requires_capability` for full semantics:
|
|
183
217
|
*
|
|
184
218
|
* - `equals: V` — scalar equality. `actual` must be declared and must equal
|
|
185
|
-
* `V`. Absent fields (`undefined`) skip
|
|
186
|
-
*
|
|
219
|
+
* `V`. Absent fields (`undefined`) skip unless the capabilities schema
|
|
220
|
+
* declares a default that the gate materialized before predicate evaluation.
|
|
187
221
|
*
|
|
188
222
|
* - `present: B` — presence is the load-bearing signal. `present: true`
|
|
189
223
|
* skips when the field is absent (treats `undefined` and `null` as absent).
|
|
@@ -193,12 +227,15 @@ function resolveCapabilityPath(raw, dottedPath) {
|
|
|
193
227
|
* non-conformant for object-typed capabilities (`"type": "object"` rejects
|
|
194
228
|
* null in JSON Schema), but is coalesced with absent here in the spirit of
|
|
195
229
|
* Postel — agents that misdeclare a not-supported capability as `null`
|
|
196
|
-
* get the same not_applicable skip as agents that omit the field.
|
|
230
|
+
* get the same not_applicable skip as agents that omit the field. Schema
|
|
231
|
+
* defaults are deliberately NOT materialized for this matcher: presence is
|
|
232
|
+
* the signal, so a default would defeat the gate (see
|
|
233
|
+
* `resolveCapabilityPathForGate`).
|
|
197
234
|
*
|
|
198
235
|
* - `contains: V` — array-membership. `actual` must be an array that
|
|
199
236
|
* includes `V` (strict equality, no coercion). Empty arrays, non-arrays,
|
|
200
|
-
* and absent fields all skip
|
|
201
|
-
* the
|
|
237
|
+
* and absent fields all skip unless the capabilities schema declares a
|
|
238
|
+
* default that the gate materialized before predicate evaluation.
|
|
202
239
|
*
|
|
203
240
|
* Exported for direct testing so the predicate semantics are pinned without
|
|
204
241
|
* needing a full runStoryboard() roundtrip.
|
|
@@ -237,10 +274,10 @@ function evaluateCapabilityPredicate(predicate, actual) {
|
|
|
237
274
|
}
|
|
238
275
|
return null;
|
|
239
276
|
}
|
|
240
|
-
function evaluateRequiresCapabilityGate(predicate, profile, agentTools) {
|
|
277
|
+
function evaluateRequiresCapabilityGate(predicate, profile, agentTools, adcpVersion) {
|
|
241
278
|
const rawCaps = profile?.raw_capabilities;
|
|
242
279
|
if (rawCaps !== undefined) {
|
|
243
|
-
const actual =
|
|
280
|
+
const actual = resolveCapabilityPathForGate(rawCaps, predicate, adcpVersion);
|
|
244
281
|
return evaluateCapabilityPredicate(predicate, actual);
|
|
245
282
|
}
|
|
246
283
|
const tools = agentTools ?? profile?.tools;
|
|
@@ -249,12 +286,12 @@ function evaluateRequiresCapabilityGate(predicate, profile, agentTools) {
|
|
|
249
286
|
}
|
|
250
287
|
return null;
|
|
251
288
|
}
|
|
252
|
-
function collectPhaseCapabilitySkipDetails(storyboard, profile, agentTools) {
|
|
289
|
+
function collectPhaseCapabilitySkipDetails(storyboard, profile, agentTools, adcpVersion) {
|
|
253
290
|
const skipDetails = new Map();
|
|
254
291
|
for (const phase of storyboard.phases) {
|
|
255
292
|
if (!phase.requires_capability)
|
|
256
293
|
continue;
|
|
257
|
-
const unmetDetail = evaluateRequiresCapabilityGate(phase.requires_capability, profile, agentTools);
|
|
294
|
+
const unmetDetail = evaluateRequiresCapabilityGate(phase.requires_capability, profile, agentTools, adcpVersion);
|
|
258
295
|
if (unmetDetail !== null) {
|
|
259
296
|
skipDetails.set(phase.id, unmetDetail);
|
|
260
297
|
}
|
|
@@ -825,6 +862,17 @@ async function runStoryboardBody(agentUrlOrUrls, storyboard, options) {
|
|
|
825
862
|
}
|
|
826
863
|
return runMultiPass(agentUrls, storyboard, options);
|
|
827
864
|
}
|
|
865
|
+
const allRequires = resolveStoryboardRequires(storyboard, options);
|
|
866
|
+
if (allRequires.length) {
|
|
867
|
+
const unmet = checkRequires(allRequires, storyboard, options, options._profile);
|
|
868
|
+
if (unmet) {
|
|
869
|
+
const resultAgentUrls = options.agents ? Object.values(options.agents).map(e => e.url) : agentUrls;
|
|
870
|
+
return {
|
|
871
|
+
...buildRequirementUnmetResult(resultAgentUrls, storyboard, unmet.requirement, unmet.detail),
|
|
872
|
+
notices: collectCapabilityNotices(storyboard, options._profile?.raw_capabilities),
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
}
|
|
828
876
|
if (options.agents) {
|
|
829
877
|
// Project the agents map's URLs into the legacy `agentUrls` array so
|
|
830
878
|
// downstream signatures (per-step `agent_url:` records, etc.) keep
|
|
@@ -1008,6 +1056,7 @@ const REQUIREMENT_TO_SKIP_REASON = {
|
|
|
1008
1056
|
real_wire: 'requirement_unmet',
|
|
1009
1057
|
webhook_receiver: 'requirement_unmet',
|
|
1010
1058
|
request_signer: 'not_applicable',
|
|
1059
|
+
multi_agent: 'requirement_unmet',
|
|
1011
1060
|
};
|
|
1012
1061
|
function isKnownRequirement(requirement) {
|
|
1013
1062
|
return types_1.KNOWN_REQUIREMENTS.has(requirement);
|
|
@@ -1167,8 +1216,14 @@ function normalizeAgentToolNames(tools) {
|
|
|
1167
1216
|
* threaded through), the gate is a no-op — the caller accepted
|
|
1168
1217
|
* responsibility for capability compatibility by reusing an external
|
|
1169
1218
|
* client. Spec: adcp-client#1702.
|
|
1219
|
+
* - `multi_agent` — `options.agents` is set and the storyboard's
|
|
1220
|
+
* declared route keys (`default_agent` and step-level `agent:` overrides)
|
|
1221
|
+
* resolve to at least two distinct entries in that map. Raw
|
|
1222
|
+
* `options.agents` cardinality is not enough; the requirement describes
|
|
1223
|
+
* the topology this storyboard actually routes through.
|
|
1224
|
+
* Spec: adcp-client#2281.
|
|
1170
1225
|
*/
|
|
1171
|
-
function checkRequires(requires, options, profile) {
|
|
1226
|
+
function checkRequires(requires, storyboard, options, profile) {
|
|
1172
1227
|
for (const requirement of requires) {
|
|
1173
1228
|
if (!isKnownRequirement(requirement)) {
|
|
1174
1229
|
return {
|
|
@@ -1243,10 +1298,46 @@ function checkRequires(requires, options, profile) {
|
|
|
1243
1298
|
'register the test keypair before the 4.0 cut to avoid a hard compliance failure then.',
|
|
1244
1299
|
};
|
|
1245
1300
|
}
|
|
1301
|
+
case 'multi_agent': {
|
|
1302
|
+
const routeKeys = collectMultiAgentRequirementRouteKeys(storyboard, options);
|
|
1303
|
+
if (routeKeys.length >= 2)
|
|
1304
|
+
break;
|
|
1305
|
+
const availableKeys = options.agents ? Object.keys(options.agents) : [];
|
|
1306
|
+
const routed = routeKeys.length ? routeKeys.join(', ') : '(none)';
|
|
1307
|
+
const available = availableKeys.length ? availableKeys.join(', ') : '(none)';
|
|
1308
|
+
return {
|
|
1309
|
+
requirement,
|
|
1310
|
+
detail: "Storyboard requires 'multi_agent'; configure `agents` and route this storyboard " +
|
|
1311
|
+
'to at least two distinct agent keys via `default_agent` and/or step-level `agent:` overrides. ' +
|
|
1312
|
+
`Resolved route keys: [${routed}]. Available agents: [${available}].`,
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1246
1315
|
}
|
|
1247
1316
|
}
|
|
1248
1317
|
return null;
|
|
1249
1318
|
}
|
|
1319
|
+
function collectMultiAgentRequirementRouteKeys(storyboard, options) {
|
|
1320
|
+
const agents = options.agents;
|
|
1321
|
+
if (!agents)
|
|
1322
|
+
return [];
|
|
1323
|
+
const routeKeys = new Set();
|
|
1324
|
+
if (options.default_agent !== undefined && options.default_agent in agents) {
|
|
1325
|
+
routeKeys.add(options.default_agent);
|
|
1326
|
+
}
|
|
1327
|
+
for (const phase of storyboard.phases ?? []) {
|
|
1328
|
+
for (const step of phase.steps ?? []) {
|
|
1329
|
+
if (step.agent !== undefined && step.agent in agents) {
|
|
1330
|
+
routeKeys.add(step.agent);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
return [...routeKeys];
|
|
1335
|
+
}
|
|
1336
|
+
function resolveStoryboardRequires(storyboard, options) {
|
|
1337
|
+
const declared = storyboard.requires ?? [];
|
|
1338
|
+
const implicit = detectImplicitRequires(storyboard, options);
|
|
1339
|
+
return [...declared, ...implicit.filter(r => !declared.includes(r))];
|
|
1340
|
+
}
|
|
1250
1341
|
/**
|
|
1251
1342
|
* Webhook-token regex used to autodetect the implicit `webhook_receiver`
|
|
1252
1343
|
* requirement. Matches `{{runner.webhook_url:<step_id>}}` and the bare
|
|
@@ -1739,11 +1830,9 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1739
1830
|
// standalone runner path options._profile may be undefined; notices will be
|
|
1740
1831
|
// collected again from the fully-fetched profile at result-build time.
|
|
1741
1832
|
const preflightNotices = collectCapabilityNotices(storyboard, options._profile?.raw_capabilities);
|
|
1742
|
-
const
|
|
1743
|
-
const implicit = detectImplicitRequires(storyboard, options);
|
|
1744
|
-
const allRequires = [...declared, ...implicit.filter(r => !declared.includes(r))];
|
|
1833
|
+
const allRequires = resolveStoryboardRequires(storyboard, options);
|
|
1745
1834
|
if (allRequires.length) {
|
|
1746
|
-
const unmet = checkRequires(allRequires, options, profile);
|
|
1835
|
+
const unmet = checkRequires(allRequires, storyboard, options, profile);
|
|
1747
1836
|
if (unmet) {
|
|
1748
1837
|
if (!callerOwnsClients)
|
|
1749
1838
|
await (0, protocols_1.closeConnections)(options.protocol);
|
|
@@ -1772,7 +1861,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1772
1861
|
// tests (e.g. `adcp.idempotency.supported: false`), skip the whole storyboard
|
|
1773
1862
|
// rather than producing a cascade of misleading per-phase failures.
|
|
1774
1863
|
if (storyboard.requires_capability) {
|
|
1775
|
-
const unmetDetail = evaluateRequiresCapabilityGate(storyboard.requires_capability, profile, options.agentTools);
|
|
1864
|
+
const unmetDetail = evaluateRequiresCapabilityGate(storyboard.requires_capability, profile, options.agentTools, options.adcpVersion);
|
|
1776
1865
|
if (unmetDetail !== null) {
|
|
1777
1866
|
if (!callerOwnsClients)
|
|
1778
1867
|
await (0, protocols_1.closeConnections)(options.protocol);
|
|
@@ -1913,7 +2002,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
|
|
|
1913
2002
|
// an implementor reading the report can't tell "nothing tested" from
|
|
1914
2003
|
// "everything passed".
|
|
1915
2004
|
const hasExecutableSteps = storyboard.phases.some(p => p.steps.length > 0);
|
|
1916
|
-
const phaseCapabilitySkipDetails = collectPhaseCapabilitySkipDetails(storyboard, profile, options.agentTools);
|
|
2005
|
+
const phaseCapabilitySkipDetails = collectPhaseCapabilitySkipDetails(storyboard, profile, options.agentTools, options.adcpVersion);
|
|
1917
2006
|
const skipControllerSeedingForPhaseGates = allExecutablePhasesCapabilitySkipped(storyboard, phaseCapabilitySkipDetails);
|
|
1918
2007
|
if (!hasExecutableSteps) {
|
|
1919
2008
|
const isScenarioComposed = (storyboard.requires_scenarios?.length ?? 0) > 0;
|
|
@@ -2854,7 +2943,7 @@ async function runMultiPass(agentUrls, storyboard, options) {
|
|
|
2854
2943
|
...(options.agentTools ? {} : { agentTools: normalizeAgentToolNames(preSeedProfile.tools) }),
|
|
2855
2944
|
};
|
|
2856
2945
|
}
|
|
2857
|
-
const phaseCapabilitySkipDetails = collectPhaseCapabilitySkipDetails(storyboard, preSeedProfile, options.agentTools);
|
|
2946
|
+
const phaseCapabilitySkipDetails = collectPhaseCapabilitySkipDetails(storyboard, preSeedProfile, options.agentTools, options.adcpVersion);
|
|
2858
2947
|
const preSeededResult = allExecutablePhasesCapabilitySkipped(storyboard, phaseCapabilitySkipDetails)
|
|
2859
2948
|
? null
|
|
2860
2949
|
: await (0, seeding_1.runControllerSeeding)(preSeedClients[0], storyboard, options, preSeedContext);
|