@adcp/sdk 16.0.0 → 16.1.0
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/README.md +52 -0
- package/bin/adcp-identity.js +3 -2
- package/dist/lib/client/core.d.mts +1 -1
- package/dist/lib/client/core.d.ts +1 -1
- package/dist/lib/core/AgentClient.d.mts +8 -1
- package/dist/lib/core/AgentClient.d.ts +8 -1
- package/dist/lib/core/AgentClient.js +10 -0
- package/dist/lib/core/AgentClient.mjs +10 -0
- package/dist/lib/core/AsyncHandler.d.mts +2 -0
- package/dist/lib/core/AsyncHandler.d.ts +2 -0
- package/dist/lib/core/AsyncHandler.js +1 -1
- package/dist/lib/core/AsyncHandler.mjs +1 -1
- package/dist/lib/core/ConversationTypes.d.mts +32 -0
- package/dist/lib/core/ConversationTypes.d.ts +32 -0
- package/dist/lib/core/SingleAgentClient.d.mts +11 -1
- package/dist/lib/core/SingleAgentClient.d.ts +11 -1
- package/dist/lib/core/SingleAgentClient.js +25 -6
- package/dist/lib/core/SingleAgentClient.mjs +26 -7
- package/dist/lib/core/TaskExecutor.d.mts +3 -1
- package/dist/lib/core/TaskExecutor.d.ts +3 -1
- package/dist/lib/core/TaskExecutor.js +127 -34
- package/dist/lib/core/TaskExecutor.mjs +127 -34
- package/dist/lib/core/task-deadline.d.mts +2 -0
- package/dist/lib/core/task-deadline.d.ts +2 -0
- package/dist/lib/core/task-deadline.js +20 -2
- package/dist/lib/core/task-deadline.mjs +19 -2
- package/dist/lib/identity-3.3/schemas.draft.js +1 -1
- package/dist/lib/identity-3.3/schemas.draft.mjs +1 -1
- package/dist/lib/identity-3.3/trust.d.mts +8 -0
- package/dist/lib/identity-3.3/trust.d.ts +8 -0
- package/dist/lib/identity-3.3/trust.js +41 -12
- package/dist/lib/identity-3.3/trust.mjs +40 -12
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/server/account-sync-contract.js +4 -1
- package/dist/lib/server/account-sync-contract.mjs +4 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +22 -17
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +22 -17
- package/dist/lib/signing/web-bot-auth.js +20 -5
- package/dist/lib/signing/web-bot-auth.mjs +21 -6
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/v2/projection/catalog.d.mts +6 -0
- package/dist/lib/v2/projection/catalog.d.ts +6 -0
- package/dist/lib/v2/projection/catalog.js +5 -0
- package/dist/lib/v2/projection/catalog.mjs +4 -0
- package/dist/lib/v2/projection/v1-to-v2.js +3 -2
- package/dist/lib/v2/projection/v1-to-v2.mjs +4 -3
- 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 +12 -2
- package/docs/llms.txt +3 -3
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/migration-agent-identity-3.3.md +21 -13
- package/package.json +1 -1
|
@@ -70,8 +70,34 @@ function validateTrustRecord(value) {
|
|
|
70
70
|
origins.add(origin);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
function
|
|
73
|
+
function registrableGrantee(grantee) {
|
|
74
|
+
try {
|
|
75
|
+
return eTldPlusOne(grantee) === grantee ? grantee : void 0;
|
|
76
|
+
} catch {
|
|
77
|
+
return void 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function grantAgentOrigin(url) {
|
|
81
|
+
try {
|
|
82
|
+
return canonicalAgentOrigin(url);
|
|
83
|
+
} catch {
|
|
84
|
+
return void 0;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function assertPublishableTrustRecord(record) {
|
|
74
88
|
validateTrustRecord(record);
|
|
89
|
+
for (const grant of record.grants ?? []) {
|
|
90
|
+
if (registrableGrantee(grant.grantee) === void 0)
|
|
91
|
+
throw new TypeError(
|
|
92
|
+
`Grant grantee "${grant.grantee}" is not a registrable domain; name the organization's registrable domain and narrow with agents[]`
|
|
93
|
+
);
|
|
94
|
+
for (const agent of grant.agents ?? [])
|
|
95
|
+
if (grantAgentOrigin(agent.url) === void 0)
|
|
96
|
+
throw new TypeError(`Grant agents[] URL "${agent.url}" is not a valid agent origin`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function createTrustRecord(record) {
|
|
100
|
+
assertPublishableTrustRecord(record);
|
|
75
101
|
return structuredClone(record);
|
|
76
102
|
}
|
|
77
103
|
class TrustEvaluator {
|
|
@@ -268,13 +294,15 @@ function authorityGroup(operator) {
|
|
|
268
294
|
const provider = parseDomain(operator).domain;
|
|
269
295
|
return `private:${provider ?? operator}`;
|
|
270
296
|
}
|
|
297
|
+
function grantsScope(grant, scope) {
|
|
298
|
+
return grant.scopes.some(
|
|
299
|
+
(granted) => granted === "*" || granted === scope || granted === "adcp:all" && scope.startsWith("adcp:")
|
|
300
|
+
);
|
|
301
|
+
}
|
|
271
302
|
function grantMatches(grant, target, claim, now) {
|
|
272
|
-
if (
|
|
273
|
-
if (!grant.
|
|
274
|
-
|
|
275
|
-
))
|
|
276
|
-
return false;
|
|
277
|
-
if (grant.agents && !grant.agents.some((agent) => canonicalAgentOrigin(agent.url) === canonicalAgentOrigin(claim.signerOrigin)))
|
|
303
|
+
if (registrableGrantee(grant.grantee) !== target) return false;
|
|
304
|
+
if (!grantsScope(grant, claim.scope)) return false;
|
|
305
|
+
if (grant.agents && !grant.agents.some((agent) => grantAgentOrigin(agent.url) === canonicalAgentOrigin(claim.signerOrigin)))
|
|
278
306
|
return false;
|
|
279
307
|
const brands = grant.profiles?.adcp?.brands;
|
|
280
308
|
if (brands && !brands.includes("*") && (!claim.brand.brand_id || !brands.includes(claim.brand.brand_id)))
|
|
@@ -321,11 +349,10 @@ async function authorizeDemandGrant(claim, options) {
|
|
|
321
349
|
if (second) return result("trust", [brand, account, operator], [first[0], second]);
|
|
322
350
|
}
|
|
323
351
|
}
|
|
324
|
-
const covered = (record.record.grants ?? []).some(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
);
|
|
352
|
+
const covered = (record.record.grants ?? []).some((g) => {
|
|
353
|
+
const grantee = registrableGrantee(g.grantee);
|
|
354
|
+
return grantee !== void 0 && (grantee === account || selfOperated && grantee === operator) && grantsScope(g, claim.scope);
|
|
355
|
+
});
|
|
329
356
|
if (!covered && !record.record.exclusive_grants && await options.sellerAuthorization?.(claim))
|
|
330
357
|
return result("seller", [brand, account, operator]);
|
|
331
358
|
throw new IdentityAuthorizationError("grant_absent");
|
|
@@ -335,6 +362,7 @@ export {
|
|
|
335
362
|
TrustEvaluator,
|
|
336
363
|
TrustMembershipError,
|
|
337
364
|
TrustRecordUnavailableError,
|
|
365
|
+
assertPublishableTrustRecord,
|
|
338
366
|
authorizeDemandGrant,
|
|
339
367
|
createTrustRecord,
|
|
340
368
|
validateIdentity33Schema,
|
package/dist/lib/index.d.mts
CHANGED
|
@@ -36,7 +36,7 @@ export { match, attachMatch } from './core/match.mjs';
|
|
|
36
36
|
export type { MatchHandlers, PartialMatchHandlers } from './core/match.mjs';
|
|
37
37
|
export { ProtocolResponseParser, responseParser, ADCP_STATUS, type ADCPStatus } from './core/ProtocolResponseParser.mjs';
|
|
38
38
|
export { ResponseValidator, responseValidator, type ValidationResult, type ValidationOptions, } from './core/ResponseValidator.mjs';
|
|
39
|
-
export type { Message, InputRequest, InputHandler, InputHandlerResponse, ConversationContext, TaskOptions, WebhookToolPredicate, WebhookUrlTemplate, TaskResult, TaskResultCompleted, TaskResultIntermediate, TaskResultFailure, TaskResultMetadata, DeferredContinuation, DirectPauseRecoveryRequest, TaskState, TaskStatus, ConversationConfig, AdcpErrorInfo, AdcpValidationIssue, } from './core/ConversationTypes.mjs';
|
|
39
|
+
export type { Message, InputRequest, InputHandler, InputHandlerResponse, ConversationContext, TaskOptions, TrackTaskRequest, TrackedTask, SubmittedContinuation, TaskInfo, WebhookToolPredicate, WebhookUrlTemplate, TaskResult, TaskResultCompleted, TaskResultIntermediate, TaskResultFailure, TaskResultMetadata, DeferredContinuation, DirectPauseRecoveryRequest, TaskState, TaskStatus, ConversationConfig, AdcpErrorInfo, AdcpValidationIssue, } from './core/ConversationTypes.mjs';
|
|
40
40
|
export type { GovernanceConfig, CampaignGovernanceConfig, GovernanceCheckResult, GovernanceOutcome, GovernanceFinding, GovernanceIntentDetails, GovernanceCondition, GovernanceEscalation, NormalizedGovernanceApproved, NormalizedGovernanceConditions, NormalizedGovernanceDenied, NormalizedGovernanceVerdict, } from './core/GovernanceTypes.mjs';
|
|
41
41
|
export { GovernanceMiddleware } from './core/GovernanceMiddleware.mjs';
|
|
42
42
|
export { isGovernanceApproved, isGovernanceConditions, isGovernanceDenied, normalizeGovernanceVerdict, } from './core/GovernanceTypes.mjs';
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export { match, attachMatch } from './core/match';
|
|
|
36
36
|
export type { MatchHandlers, PartialMatchHandlers } from './core/match';
|
|
37
37
|
export { ProtocolResponseParser, responseParser, ADCP_STATUS, type ADCPStatus } from './core/ProtocolResponseParser';
|
|
38
38
|
export { ResponseValidator, responseValidator, type ValidationResult, type ValidationOptions, } from './core/ResponseValidator';
|
|
39
|
-
export type { Message, InputRequest, InputHandler, InputHandlerResponse, ConversationContext, TaskOptions, WebhookToolPredicate, WebhookUrlTemplate, TaskResult, TaskResultCompleted, TaskResultIntermediate, TaskResultFailure, TaskResultMetadata, DeferredContinuation, DirectPauseRecoveryRequest, TaskState, TaskStatus, ConversationConfig, AdcpErrorInfo, AdcpValidationIssue, } from './core/ConversationTypes';
|
|
39
|
+
export type { Message, InputRequest, InputHandler, InputHandlerResponse, ConversationContext, TaskOptions, TrackTaskRequest, TrackedTask, SubmittedContinuation, TaskInfo, WebhookToolPredicate, WebhookUrlTemplate, TaskResult, TaskResultCompleted, TaskResultIntermediate, TaskResultFailure, TaskResultMetadata, DeferredContinuation, DirectPauseRecoveryRequest, TaskState, TaskStatus, ConversationConfig, AdcpErrorInfo, AdcpValidationIssue, } from './core/ConversationTypes';
|
|
40
40
|
export type { GovernanceConfig, CampaignGovernanceConfig, GovernanceCheckResult, GovernanceOutcome, GovernanceFinding, GovernanceIntentDetails, GovernanceCondition, GovernanceEscalation, NormalizedGovernanceApproved, NormalizedGovernanceConditions, NormalizedGovernanceDenied, NormalizedGovernanceVerdict, } from './core/GovernanceTypes';
|
|
41
41
|
export { GovernanceMiddleware } from './core/GovernanceMiddleware';
|
|
42
42
|
export { isGovernanceApproved, isGovernanceConditions, isGovernanceDenied, normalizeGovernanceVerdict, } from './core/GovernanceTypes';
|
|
@@ -28,6 +28,7 @@ module.exports = __toCommonJS(account_sync_contract_exports);
|
|
|
28
28
|
var import_account_key = require('../core/account-key.js');
|
|
29
29
|
var import_account = require('./decisioning/account.js');
|
|
30
30
|
var import_async_outcome = require('./decisioning/async-outcome.js');
|
|
31
|
+
const NATURAL_KEY_FIELDS = ["brand", "operator", "operator_unit", "currency", "timezone", "sandbox"];
|
|
31
32
|
function isolateAccountCallbackInput(ctx) {
|
|
32
33
|
const descriptors = Object.getOwnPropertyDescriptors(ctx);
|
|
33
34
|
delete descriptors.input;
|
|
@@ -58,7 +59,9 @@ function naturalRef(entry) {
|
|
|
58
59
|
const ref = entry.account ?? entry;
|
|
59
60
|
if (!ref || "account_id" in ref || !("brand" in ref) || !ref.brand || typeof ref.operator !== "string")
|
|
60
61
|
return void 0;
|
|
61
|
-
return
|
|
62
|
+
return Object.fromEntries(
|
|
63
|
+
NATURAL_KEY_FIELDS.filter((field) => ref[field] !== void 0).map((field) => [field, ref[field]])
|
|
64
|
+
);
|
|
62
65
|
}
|
|
63
66
|
async function lookup(accounts, ref, ctx, onUnsupported) {
|
|
64
67
|
try {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { accountReferenceKey } from "../core/account-key.mjs";
|
|
2
2
|
import { AccountNotFoundError, toWireAccount } from "./decisioning/account.mjs";
|
|
3
3
|
import { AdcpError } from "./decisioning/async-outcome.mjs";
|
|
4
|
+
const NATURAL_KEY_FIELDS = ["brand", "operator", "operator_unit", "currency", "timezone", "sandbox"];
|
|
4
5
|
function isolateAccountCallbackInput(ctx) {
|
|
5
6
|
const descriptors = Object.getOwnPropertyDescriptors(ctx);
|
|
6
7
|
delete descriptors.input;
|
|
@@ -31,7 +32,9 @@ function naturalRef(entry) {
|
|
|
31
32
|
const ref = entry.account ?? entry;
|
|
32
33
|
if (!ref || "account_id" in ref || !("brand" in ref) || !ref.brand || typeof ref.operator !== "string")
|
|
33
34
|
return void 0;
|
|
34
|
-
return
|
|
35
|
+
return Object.fromEntries(
|
|
36
|
+
NATURAL_KEY_FIELDS.filter((field) => ref[field] !== void 0).map((field) => [field, ref[field]])
|
|
37
|
+
);
|
|
35
38
|
}
|
|
36
39
|
async function lookup(accounts, ref, ctx, onUnsupported) {
|
|
37
40
|
try {
|
|
@@ -1009,23 +1009,28 @@ function jsonValuesEqual(left, right) {
|
|
|
1009
1009
|
return leftKeys.length === rightKeys.length && leftKeys.every((key) => Object.hasOwn(rightRecord, key) && jsonValuesEqual(leftRecord[key], rightRecord[key]));
|
|
1010
1010
|
}
|
|
1011
1011
|
function matchLegacyRefToDeclaration(declaration, ref, ownerId, legacyFormatConverter) {
|
|
1012
|
-
const
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1012
|
+
const compare = (authoritativeOnly) => {
|
|
1013
|
+
const projected = (0, import_v1_to_v2.projectV1ProductToV2)(
|
|
1014
|
+
{
|
|
1015
|
+
product_id: ownerId,
|
|
1016
|
+
name: ownerId,
|
|
1017
|
+
description: ownerId,
|
|
1018
|
+
format_ids: [ref]
|
|
1019
|
+
},
|
|
1020
|
+
{ legacyFormatConverter, _authoritativeOnly: authoritativeOnly }
|
|
1021
|
+
);
|
|
1022
|
+
if (projected.diagnostics.length > 0 || projected.v2.format_options.length !== 1) return "unresolved";
|
|
1023
|
+
const expected = projected.v2.format_options[0];
|
|
1024
|
+
if (declaration.format_kind !== expected.format_kind) return "kind_mismatch";
|
|
1025
|
+
const params = declaration.params !== null && typeof declaration.params === "object" && !Array.isArray(declaration.params) ? declaration.params : {};
|
|
1026
|
+
for (const [key, expectedValue] of Object.entries(expected.params)) {
|
|
1027
|
+
if (!Object.hasOwn(params, key) || !jsonValuesEqual(params[key], expectedValue)) return "params_mismatch";
|
|
1028
|
+
}
|
|
1029
|
+
return "match";
|
|
1030
|
+
};
|
|
1031
|
+
const authoritative = compare(true);
|
|
1032
|
+
if (authoritative !== "unresolved") return authoritative;
|
|
1033
|
+
return compare(false) === "match" ? "match" : "unresolved";
|
|
1029
1034
|
}
|
|
1030
1035
|
function validateLegacyRefNarrowing(declaration, ref, ownerId, field, legacyFormatConverter) {
|
|
1031
1036
|
const match = matchLegacyRefToDeclaration(declaration, ref, ownerId, legacyFormatConverter);
|
|
@@ -1041,23 +1041,28 @@ function jsonValuesEqual(left, right) {
|
|
|
1041
1041
|
return leftKeys.length === rightKeys.length && leftKeys.every((key) => Object.hasOwn(rightRecord, key) && jsonValuesEqual(leftRecord[key], rightRecord[key]));
|
|
1042
1042
|
}
|
|
1043
1043
|
function matchLegacyRefToDeclaration(declaration, ref, ownerId, legacyFormatConverter) {
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1044
|
+
const compare = (authoritativeOnly) => {
|
|
1045
|
+
const projected = projectV1ProductToV2(
|
|
1046
|
+
{
|
|
1047
|
+
product_id: ownerId,
|
|
1048
|
+
name: ownerId,
|
|
1049
|
+
description: ownerId,
|
|
1050
|
+
format_ids: [ref]
|
|
1051
|
+
},
|
|
1052
|
+
{ legacyFormatConverter, _authoritativeOnly: authoritativeOnly }
|
|
1053
|
+
);
|
|
1054
|
+
if (projected.diagnostics.length > 0 || projected.v2.format_options.length !== 1) return "unresolved";
|
|
1055
|
+
const expected = projected.v2.format_options[0];
|
|
1056
|
+
if (declaration.format_kind !== expected.format_kind) return "kind_mismatch";
|
|
1057
|
+
const params = declaration.params !== null && typeof declaration.params === "object" && !Array.isArray(declaration.params) ? declaration.params : {};
|
|
1058
|
+
for (const [key, expectedValue] of Object.entries(expected.params)) {
|
|
1059
|
+
if (!Object.hasOwn(params, key) || !jsonValuesEqual(params[key], expectedValue)) return "params_mismatch";
|
|
1060
|
+
}
|
|
1061
|
+
return "match";
|
|
1062
|
+
};
|
|
1063
|
+
const authoritative = compare(true);
|
|
1064
|
+
if (authoritative !== "unresolved") return authoritative;
|
|
1065
|
+
return compare(false) === "match" ? "match" : "unresolved";
|
|
1061
1066
|
}
|
|
1062
1067
|
function validateLegacyRefNarrowing(declaration, ref, ownerId, field, legacyFormatConverter) {
|
|
1063
1068
|
const match = matchLegacyRefToDeclaration(declaration, ref, ownerId, legacyFormatConverter);
|
|
@@ -186,6 +186,14 @@ function jwkThumbprint(jwk) {
|
|
|
186
186
|
function keyAlgorithm(jwk) {
|
|
187
187
|
return jwk.kty === "OKP" && jwk.crv === "Ed25519" ? "ed25519" : void 0;
|
|
188
188
|
}
|
|
189
|
+
function importable(jwk) {
|
|
190
|
+
try {
|
|
191
|
+
(0, import_crypto2.jwkToPublicKey)(jwk);
|
|
192
|
+
return true;
|
|
193
|
+
} catch {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
189
197
|
function algorithm(jwk) {
|
|
190
198
|
return keyAlgorithm(jwk) ?? denied("unsupported_key");
|
|
191
199
|
}
|
|
@@ -590,25 +598,24 @@ async function verifyKeyDirectory(response, now = Date.now() / 1e3, options = {}
|
|
|
590
598
|
if (!raw || typeof raw !== "object") denied("directory_key");
|
|
591
599
|
if (Object.keys(raw).some((k) => PRIVATE_JWK_MEMBERS.has(k.toLowerCase()) || k.startsWith("_private")))
|
|
592
600
|
denied("directory_key");
|
|
593
|
-
if (!keyAlgorithm(raw)) continue;
|
|
601
|
+
if (!keyAlgorithm(raw) || !importable(raw)) continue;
|
|
594
602
|
const thumbprint = jwkThumbprint(raw);
|
|
595
603
|
const key = { ...raw, kid: raw.kid ?? thumbprint };
|
|
596
604
|
if (key.kid !== thumbprint || kids.has(key.kid) || key.adcp_use !== void 0 || !testKeysAllowed(options.allowTestKeys) && TEST_KIDS.has(key.kid))
|
|
597
605
|
denied("directory_key");
|
|
598
606
|
kids.add(key.kid);
|
|
599
|
-
keys.push(key);
|
|
600
607
|
const proof = signatures.find((input) => input.params.keyid === key.kid && input.params.tag === DIRECTORY_TAG);
|
|
601
608
|
if (!proof || !proof.components.includes("@authority;req") || !proof.components.includes("content-digest") || !Number.isSafeInteger(proof.params.created) || !Number.isSafeInteger(proof.params.expires) || proof.params.expires <= now || proof.params.expires <= proof.params.created)
|
|
602
|
-
|
|
609
|
+
continue;
|
|
603
610
|
const proofComponents = [(0, import_http_message_sig.component)("@authority", { req: true }), (0, import_http_message_sig.component)("content-digest")];
|
|
604
611
|
let covered;
|
|
605
612
|
try {
|
|
606
613
|
covered = proof.components.map(componentDescriptor);
|
|
607
614
|
} catch {
|
|
608
|
-
|
|
615
|
+
continue;
|
|
609
616
|
}
|
|
610
617
|
const requestHeaders = response.request.headers ?? {};
|
|
611
|
-
await verifyWithLibrary(
|
|
618
|
+
const proven = await verifyWithLibrary(
|
|
612
619
|
{
|
|
613
620
|
kind: "response",
|
|
614
621
|
status: response.status,
|
|
@@ -634,7 +641,15 @@ async function verifyKeyDirectory(response, now = Date.now() / 1e3, options = {}
|
|
|
634
641
|
// The library rejects a proof whose `created` is in the future (beyond skew).
|
|
635
642
|
{ requiredComponents: proofComponents, requiredParameters: ["created", "expires", "keyid", "tag"], now },
|
|
636
643
|
async () => keyVerifier(key)
|
|
644
|
+
).then(
|
|
645
|
+
() => true,
|
|
646
|
+
(error) => {
|
|
647
|
+
if (error instanceof WebBotAuthError) return false;
|
|
648
|
+
throw error;
|
|
649
|
+
}
|
|
637
650
|
);
|
|
651
|
+
if (!proven) continue;
|
|
652
|
+
keys.push(key);
|
|
638
653
|
expires = Math.min(expires, proof.params.expires);
|
|
639
654
|
}
|
|
640
655
|
if (!keys.length) denied("directory_keys");
|
|
@@ -16,7 +16,7 @@ import { canonicalAgentUrl } from "./agent-resolver/select-agent.mjs";
|
|
|
16
16
|
import { parseStrictJson } from "./agent-resolver/strict-json.mjs";
|
|
17
17
|
import { getHeaderValue } from "./canonicalize.mjs";
|
|
18
18
|
import { computeContentDigest, contentDigestMatches, contentDigestUsesEncoding } from "./content-digest.mjs";
|
|
19
|
-
import { signWithPrivateJwkAsync, verifySignatureAsync } from "./crypto.mjs";
|
|
19
|
+
import { jwkToPublicKey, signWithPrivateJwkAsync, verifySignatureAsync } from "./crypto.mjs";
|
|
20
20
|
import {
|
|
21
21
|
parseSignature,
|
|
22
22
|
parseSignatureInputMember,
|
|
@@ -142,6 +142,14 @@ function jwkThumbprint(jwk) {
|
|
|
142
142
|
function keyAlgorithm(jwk) {
|
|
143
143
|
return jwk.kty === "OKP" && jwk.crv === "Ed25519" ? "ed25519" : void 0;
|
|
144
144
|
}
|
|
145
|
+
function importable(jwk) {
|
|
146
|
+
try {
|
|
147
|
+
jwkToPublicKey(jwk);
|
|
148
|
+
return true;
|
|
149
|
+
} catch {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
145
153
|
function algorithm(jwk) {
|
|
146
154
|
return keyAlgorithm(jwk) ?? denied("unsupported_key");
|
|
147
155
|
}
|
|
@@ -546,25 +554,24 @@ async function verifyKeyDirectory(response, now = Date.now() / 1e3, options = {}
|
|
|
546
554
|
if (!raw || typeof raw !== "object") denied("directory_key");
|
|
547
555
|
if (Object.keys(raw).some((k) => PRIVATE_JWK_MEMBERS.has(k.toLowerCase()) || k.startsWith("_private")))
|
|
548
556
|
denied("directory_key");
|
|
549
|
-
if (!keyAlgorithm(raw)) continue;
|
|
557
|
+
if (!keyAlgorithm(raw) || !importable(raw)) continue;
|
|
550
558
|
const thumbprint = jwkThumbprint(raw);
|
|
551
559
|
const key = { ...raw, kid: raw.kid ?? thumbprint };
|
|
552
560
|
if (key.kid !== thumbprint || kids.has(key.kid) || key.adcp_use !== void 0 || !testKeysAllowed(options.allowTestKeys) && TEST_KIDS.has(key.kid))
|
|
553
561
|
denied("directory_key");
|
|
554
562
|
kids.add(key.kid);
|
|
555
|
-
keys.push(key);
|
|
556
563
|
const proof = signatures.find((input) => input.params.keyid === key.kid && input.params.tag === DIRECTORY_TAG);
|
|
557
564
|
if (!proof || !proof.components.includes("@authority;req") || !proof.components.includes("content-digest") || !Number.isSafeInteger(proof.params.created) || !Number.isSafeInteger(proof.params.expires) || proof.params.expires <= now || proof.params.expires <= proof.params.created)
|
|
558
|
-
|
|
565
|
+
continue;
|
|
559
566
|
const proofComponents = [component("@authority", { req: true }), component("content-digest")];
|
|
560
567
|
let covered;
|
|
561
568
|
try {
|
|
562
569
|
covered = proof.components.map(componentDescriptor);
|
|
563
570
|
} catch {
|
|
564
|
-
|
|
571
|
+
continue;
|
|
565
572
|
}
|
|
566
573
|
const requestHeaders = response.request.headers ?? {};
|
|
567
|
-
await verifyWithLibrary(
|
|
574
|
+
const proven = await verifyWithLibrary(
|
|
568
575
|
{
|
|
569
576
|
kind: "response",
|
|
570
577
|
status: response.status,
|
|
@@ -590,7 +597,15 @@ async function verifyKeyDirectory(response, now = Date.now() / 1e3, options = {}
|
|
|
590
597
|
// The library rejects a proof whose `created` is in the future (beyond skew).
|
|
591
598
|
{ requiredComponents: proofComponents, requiredParameters: ["created", "expires", "keyid", "tag"], now },
|
|
592
599
|
async () => keyVerifier(key)
|
|
600
|
+
).then(
|
|
601
|
+
() => true,
|
|
602
|
+
(error) => {
|
|
603
|
+
if (error instanceof WebBotAuthError) return false;
|
|
604
|
+
throw error;
|
|
605
|
+
}
|
|
593
606
|
);
|
|
607
|
+
if (!proven) continue;
|
|
608
|
+
keys.push(key);
|
|
594
609
|
expires = Math.min(expires, proof.params.expires);
|
|
595
610
|
}
|
|
596
611
|
if (!keys.length) denied("directory_keys");
|
|
@@ -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 = "16.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "16.1.0";
|
|
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 = "16.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "16.1.0";
|
|
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
|
/**
|
|
@@ -91,6 +91,12 @@ interface CatalogIndex {
|
|
|
91
91
|
byUniqueId: Map<string, V1FormatDefinition | null>;
|
|
92
92
|
entries: V1FormatDefinition[];
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* True when `agentUrl` names the AAO reference format agent (including its
|
|
96
|
+
* folded historical hosts). Ids under any other agent URL belong to that
|
|
97
|
+
* agent, so AAO naming conventions say nothing about what they mean.
|
|
98
|
+
*/
|
|
99
|
+
export declare function isAaoAgentUrl(agentUrl: string): boolean;
|
|
94
100
|
/**
|
|
95
101
|
* Load the catalog from a known path. Resolution order:
|
|
96
102
|
*
|
|
@@ -91,6 +91,12 @@ interface CatalogIndex {
|
|
|
91
91
|
byUniqueId: Map<string, V1FormatDefinition | null>;
|
|
92
92
|
entries: V1FormatDefinition[];
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* True when `agentUrl` names the AAO reference format agent (including its
|
|
96
|
+
* folded historical hosts). Ids under any other agent URL belong to that
|
|
97
|
+
* agent, so AAO naming conventions say nothing about what they mean.
|
|
98
|
+
*/
|
|
99
|
+
export declare function isAaoAgentUrl(agentUrl: string): boolean;
|
|
94
100
|
/**
|
|
95
101
|
* Load the catalog from a known path. Resolution order:
|
|
96
102
|
*
|
|
@@ -30,6 +30,7 @@ var catalog_exports = {};
|
|
|
30
30
|
__export(catalog_exports, {
|
|
31
31
|
_resetCatalogCache: () => _resetCatalogCache,
|
|
32
32
|
findCatalogEntryByCanonicalAndSize: () => findCatalogEntryByCanonicalAndSize,
|
|
33
|
+
isAaoAgentUrl: () => isAaoAgentUrl,
|
|
33
34
|
loadCatalog: () => loadCatalog,
|
|
34
35
|
lookupUniqueV1FormatById: () => lookupUniqueV1FormatById,
|
|
35
36
|
lookupV1Format: () => lookupV1Format,
|
|
@@ -52,6 +53,9 @@ function normalizeAgentUrl(u) {
|
|
|
52
53
|
if (canonical === null) return void 0;
|
|
53
54
|
return AAO_LEGACY_AGENT_URL_ALIASES.has(canonical) ? import_constants.AAO_CANONICAL_AGENT_URL : canonical;
|
|
54
55
|
}
|
|
56
|
+
function isAaoAgentUrl(agentUrl) {
|
|
57
|
+
return normalizeAgentUrl(agentUrl) === import_constants.AAO_CANONICAL_AGENT_URL;
|
|
58
|
+
}
|
|
55
59
|
function indexKey(agentUrl, id) {
|
|
56
60
|
const normalized = normalizeAgentUrl(agentUrl);
|
|
57
61
|
return normalized === void 0 ? void 0 : `${normalized}::${id}`;
|
|
@@ -136,6 +140,7 @@ function findCatalogEntryByCanonicalAndSize(canonical, width, height, agentUrl,
|
|
|
136
140
|
0 && (module.exports = {
|
|
137
141
|
_resetCatalogCache,
|
|
138
142
|
findCatalogEntryByCanonicalAndSize,
|
|
143
|
+
isAaoAgentUrl,
|
|
139
144
|
loadCatalog,
|
|
140
145
|
lookupUniqueV1FormatById,
|
|
141
146
|
lookupV1Format,
|
|
@@ -19,6 +19,9 @@ function normalizeAgentUrl(u) {
|
|
|
19
19
|
if (canonical === null) return void 0;
|
|
20
20
|
return AAO_LEGACY_AGENT_URL_ALIASES.has(canonical) ? AAO_CANONICAL_AGENT_URL : canonical;
|
|
21
21
|
}
|
|
22
|
+
function isAaoAgentUrl(agentUrl) {
|
|
23
|
+
return normalizeAgentUrl(agentUrl) === AAO_CANONICAL_AGENT_URL;
|
|
24
|
+
}
|
|
22
25
|
function indexKey(agentUrl, id) {
|
|
23
26
|
const normalized = normalizeAgentUrl(agentUrl);
|
|
24
27
|
return normalized === void 0 ? void 0 : `${normalized}::${id}`;
|
|
@@ -102,6 +105,7 @@ function findCatalogEntryByCanonicalAndSize(canonical, width, height, agentUrl,
|
|
|
102
105
|
export {
|
|
103
106
|
_resetCatalogCache,
|
|
104
107
|
findCatalogEntryByCanonicalAndSize,
|
|
108
|
+
isAaoAgentUrl,
|
|
105
109
|
loadCatalog,
|
|
106
110
|
lookupUniqueV1FormatById,
|
|
107
111
|
lookupV1Format,
|
|
@@ -219,7 +219,8 @@ function projectFormatId(fid, productId, field, options) {
|
|
|
219
219
|
const exactCatalogEntry = (0, import_catalog.lookupV1Format)(fid, options?._catalogPath);
|
|
220
220
|
const canonicalAgentUrl = (0, import_resolve_agent_properties.canonicalizeAgentUrl)(fid.agent_url);
|
|
221
221
|
const mayUseUniqueAlias = canonicalAgentUrl !== null && new URL(canonicalAgentUrl).protocol === "https:" && !(0, import_address_guards.isLikelyPrivateUrl)(canonicalAgentUrl);
|
|
222
|
-
const
|
|
222
|
+
const aaoGuessesApply = options?._authoritativeOnly !== true || (0, import_catalog.isAaoAgentUrl)(fid.agent_url);
|
|
223
|
+
const uniqueAliasEntry = exactCatalogEntry === void 0 && mayUseUniqueAlias && aaoGuessesApply ? (0, import_catalog.lookupUniqueV1FormatById)(fid.id, options?._catalogPath) : void 0;
|
|
223
224
|
if (uniqueAliasEntry) {
|
|
224
225
|
const explicit = projectWithLegacyConverter(fid, productId, field, options?.legacyFormatConverter);
|
|
225
226
|
if (explicit) return explicit;
|
|
@@ -277,7 +278,7 @@ function projectFormatId(fid, productId, field, options) {
|
|
|
277
278
|
}
|
|
278
279
|
};
|
|
279
280
|
}
|
|
280
|
-
const globMatch = (0, import_registry.forwardLookupByGlob)(fid.id);
|
|
281
|
+
const globMatch = aaoGuessesApply ? (0, import_registry.forwardLookupByGlob)(fid.id) : void 0;
|
|
281
282
|
if (globMatch) {
|
|
282
283
|
return {
|
|
283
284
|
decl: {
|
|
@@ -4,7 +4,7 @@ import { createRequire as __adcpCreateRequire } from "node:module";
|
|
|
4
4
|
const __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));
|
|
5
5
|
const require2 = __adcpCreateRequire(import.meta.url);
|
|
6
6
|
import { forwardLookupByGlob, forwardLookupByStructural } from "./registry.mjs";
|
|
7
|
-
import { lookupUniqueV1FormatById, lookupV1Format } from "./catalog.mjs";
|
|
7
|
+
import { isAaoAgentUrl, lookupUniqueV1FormatById, lookupV1Format } from "./catalog.mjs";
|
|
8
8
|
import { AAO_CANONICAL_AGENT_URL } from "./constants.mjs";
|
|
9
9
|
import { LIBRARY_VERSION } from "../../version.mjs";
|
|
10
10
|
import { legacyFormatConverterFromCatalogSnapshots } from "./catalog-snapshot.mjs";
|
|
@@ -202,7 +202,8 @@ function projectFormatId(fid, productId, field, options) {
|
|
|
202
202
|
const exactCatalogEntry = lookupV1Format(fid, options?._catalogPath);
|
|
203
203
|
const canonicalAgentUrl = canonicalizeAgentUrl(fid.agent_url);
|
|
204
204
|
const mayUseUniqueAlias = canonicalAgentUrl !== null && new URL(canonicalAgentUrl).protocol === "https:" && !isLikelyPrivateUrl(canonicalAgentUrl);
|
|
205
|
-
const
|
|
205
|
+
const aaoGuessesApply = options?._authoritativeOnly !== true || isAaoAgentUrl(fid.agent_url);
|
|
206
|
+
const uniqueAliasEntry = exactCatalogEntry === void 0 && mayUseUniqueAlias && aaoGuessesApply ? lookupUniqueV1FormatById(fid.id, options?._catalogPath) : void 0;
|
|
206
207
|
if (uniqueAliasEntry) {
|
|
207
208
|
const explicit = projectWithLegacyConverter(fid, productId, field, options?.legacyFormatConverter);
|
|
208
209
|
if (explicit) return explicit;
|
|
@@ -260,7 +261,7 @@ function projectFormatId(fid, productId, field, options) {
|
|
|
260
261
|
}
|
|
261
262
|
};
|
|
262
263
|
}
|
|
263
|
-
const globMatch = forwardLookupByGlob(fid.id);
|
|
264
|
+
const globMatch = aaoGuessesApply ? forwardLookupByGlob(fid.id) : void 0;
|
|
264
265
|
if (globMatch) {
|
|
265
266
|
return {
|
|
266
267
|
decl: {
|
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 = "16.
|
|
4
|
+
export declare const LIBRARY_VERSION = "16.1.0";
|
|
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: "16.
|
|
36
|
+
readonly library: "16.1.0";
|
|
37
37
|
readonly adcp: "3.2.5";
|
|
38
38
|
readonly compatibleVersions: readonly ["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.1.25", "3.1.26", "3.1.27", "3.1.28", "3.1.29", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4", "3.2.5"];
|
|
39
|
-
readonly generatedAt: "2026-10-
|
|
39
|
+
readonly generatedAt: "2026-10-20T17:31:57.242Z";
|
|
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 = "16.
|
|
4
|
+
export declare const LIBRARY_VERSION = "16.1.0";
|
|
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: "16.
|
|
36
|
+
readonly library: "16.1.0";
|
|
37
37
|
readonly adcp: "3.2.5";
|
|
38
38
|
readonly compatibleVersions: readonly ["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.1.25", "3.1.26", "3.1.27", "3.1.28", "3.1.29", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4", "3.2.5"];
|
|
39
|
-
readonly generatedAt: "2026-10-
|
|
39
|
+
readonly generatedAt: "2026-10-20T17:31:57.242Z";
|
|
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 = "16.
|
|
34
|
+
const LIBRARY_VERSION = "16.1.0";
|
|
35
35
|
const ADCP_VERSION = "3.2.5";
|
|
36
36
|
const ADCP_MAJOR_VERSION = 3;
|
|
37
37
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -102,10 +102,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
102
102
|
"3.2.5"
|
|
103
103
|
];
|
|
104
104
|
const VERSION_INFO = {
|
|
105
|
-
library: "16.
|
|
105
|
+
library: "16.1.0",
|
|
106
106
|
adcp: "3.2.5",
|
|
107
107
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
108
|
-
generatedAt: "2026-10-
|
|
108
|
+
generatedAt: "2026-10-20T17:31:57.242Z"
|
|
109
109
|
};
|
|
110
110
|
function getAdcpVersion() {
|
|
111
111
|
return ADCP_VERSION;
|
package/dist/lib/version.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const LIBRARY_VERSION = "16.
|
|
1
|
+
const LIBRARY_VERSION = "16.1.0";
|
|
2
2
|
const ADCP_VERSION = "3.2.5";
|
|
3
3
|
const ADCP_MAJOR_VERSION = 3;
|
|
4
4
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -69,10 +69,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
69
69
|
"3.2.5"
|
|
70
70
|
];
|
|
71
71
|
const VERSION_INFO = {
|
|
72
|
-
library: "16.
|
|
72
|
+
library: "16.1.0",
|
|
73
73
|
adcp: "3.2.5",
|
|
74
74
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
75
|
-
generatedAt: "2026-10-
|
|
75
|
+
generatedAt: "2026-10-20T17:31:57.242Z"
|
|
76
76
|
};
|
|
77
77
|
function getAdcpVersion() {
|
|
78
78
|
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 v16.
|
|
3
|
+
> Generated at: 2026-10-20
|
|
4
|
+
> @adcp/sdk v16.1.0
|
|
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
|
|
|
@@ -95,6 +95,7 @@ interface AgentDiscoverySeed {
|
|
|
95
95
|
// client.invalidateDiscoveryCache(): Promise<void>; refresh after a seller change.
|
|
96
96
|
|
|
97
97
|
interface TaskOptions {
|
|
98
|
+
operationId?: string; // Stable caller correlation id (otherwise a UUID); not an idempotency key
|
|
98
99
|
skipStatusHandlers?: boolean; // Skip inline completion handlers, including continuations
|
|
99
100
|
timeout?: number; // Absolute whole-task deadline
|
|
100
101
|
signal?: AbortSignal; // Caller cancellation
|
|
@@ -106,6 +107,15 @@ interface TaskOptions {
|
|
|
106
107
|
// ...deadline, cancellation, transport, and conversation options...
|
|
107
108
|
}
|
|
108
109
|
|
|
110
|
+
// Resume observation of persisted seller work (SingleAgentClient or AgentClient).
|
|
111
|
+
// Save metadata.serverTaskId, metadata.taskName as taskType, and metadata.taskId as operationId.
|
|
112
|
+
const tracked = await agent.trackTask({ taskId: saved.serverTaskId, taskType: saved.taskType, operationId: saved.operationId });
|
|
113
|
+
await tracked.track(); // One status read; TaskInfo includes operationId and serverTaskId
|
|
114
|
+
await tracked.waitForCompletion(1000, signal); // Same polling path as submitted continuations
|
|
115
|
+
// No per-poll protocol activity. Terminal status_change carries operation_id and server_task_id.
|
|
116
|
+
// Local observation errors do not terminalize seller work. Matching identities can reattach on the same client.
|
|
117
|
+
// Results retain seller tool response shapes; tracking does not restore prior request context or handlers.
|
|
118
|
+
|
|
109
119
|
interface DeferredContinuation<T> {
|
|
110
120
|
token: string;
|
|
111
121
|
question?: string;
|