@adcp/sdk 9.3.0 → 9.5.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/dist/lib/core/AgentClient.d.ts +2 -2
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/AgentClient.js +4 -4
- package/dist/lib/core/AgentClient.js.map +1 -1
- package/dist/lib/core/ConversationTypes.d.ts +7 -0
- package/dist/lib/core/ConversationTypes.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.ts +9 -5
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +117 -52
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/TaskExecutor.d.ts +1 -1
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +15 -4
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/discovery/inline-publisher-properties.js +10 -3
- package/dist/lib/discovery/inline-publisher-properties.js.map +1 -1
- package/dist/lib/discovery/resolve-agent-properties.d.ts +39 -11
- package/dist/lib/discovery/resolve-agent-properties.d.ts.map +1 -1
- package/dist/lib/discovery/resolve-agent-properties.js +136 -16
- package/dist/lib/discovery/resolve-agent-properties.js.map +1 -1
- package/dist/lib/discovery/types.d.ts +9 -2
- package/dist/lib/discovery/types.d.ts.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 +14 -12
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/protocols/a2a.d.ts +1 -1
- package/dist/lib/protocols/a2a.d.ts.map +1 -1
- package/dist/lib/protocols/a2a.js +66 -35
- package/dist/lib/protocols/a2a.js.map +1 -1
- package/dist/lib/protocols/abort.d.ts +10 -0
- package/dist/lib/protocols/abort.d.ts.map +1 -0
- package/dist/lib/protocols/abort.js +107 -0
- package/dist/lib/protocols/abort.js.map +1 -0
- package/dist/lib/protocols/index.d.ts +10 -0
- package/dist/lib/protocols/index.d.ts.map +1 -1
- package/dist/lib/protocols/index.js +33 -9
- package/dist/lib/protocols/index.js.map +1 -1
- package/dist/lib/protocols/mcp-tasks.d.ts +4 -0
- package/dist/lib/protocols/mcp-tasks.d.ts.map +1 -1
- package/dist/lib/protocols/mcp-tasks.js +27 -11
- package/dist/lib/protocols/mcp-tasks.js.map +1 -1
- package/dist/lib/protocols/mcp.d.ts +14 -2
- package/dist/lib/protocols/mcp.d.ts.map +1 -1
- package/dist/lib/protocols/mcp.js +116 -43
- package/dist/lib/protocols/mcp.js.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/signing/agent-fetch.d.ts +5 -4
- package/dist/lib/signing/agent-fetch.d.ts.map +1 -1
- package/dist/lib/signing/agent-fetch.js +31 -4
- package/dist/lib/signing/agent-fetch.js.map +1 -1
- package/dist/lib/signing/capability-priming.d.ts.map +1 -1
- package/dist/lib/signing/capability-priming.js +5 -1
- package/dist/lib/signing/capability-priming.js.map +1 -1
- package/dist/lib/signing/verifier.d.ts.map +1 -1
- package/dist/lib/signing/verifier.js +10 -37
- package/dist/lib/signing/verifier.js.map +1 -1
- package/dist/lib/signing/webhook-auth-detection.d.ts +10 -0
- package/dist/lib/signing/webhook-auth-detection.d.ts.map +1 -0
- package/dist/lib/signing/webhook-auth-detection.js +37 -0
- package/dist/lib/signing/webhook-auth-detection.js.map +1 -0
- package/dist/lib/testing/client.js +3 -3
- package/dist/lib/testing/client.js.map +1 -1
- package/dist/lib/testing/types.d.ts +2 -0
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/package.json +1 -1
|
@@ -46,6 +46,7 @@ const idempotency_1 = require("../utils/idempotency");
|
|
|
46
46
|
const TaskExecutor_1 = require("./TaskExecutor");
|
|
47
47
|
const match_1 = require("./match");
|
|
48
48
|
const auth_1 = require("../auth");
|
|
49
|
+
const abort_1 = require("../protocols/abort");
|
|
49
50
|
const errors_1 = require("../errors");
|
|
50
51
|
const net_1 = require("../net");
|
|
51
52
|
const authorization_required_1 = require("../auth/oauth/authorization-required");
|
|
@@ -55,6 +56,7 @@ const webhooks_1 = require("../webhooks");
|
|
|
55
56
|
const response_unwrapper_1 = require("../utils/response-unwrapper");
|
|
56
57
|
const a2a_discovery_1 = require("../utils/a2a-discovery");
|
|
57
58
|
const crypto = __importStar(require("crypto"));
|
|
59
|
+
const abort_2 = require("../protocols/abort");
|
|
58
60
|
const capabilities_1 = require("../utils/capabilities");
|
|
59
61
|
const request_normalizer_1 = require("../utils/request-normalizer");
|
|
60
62
|
const validate_user_agent_1 = require("../utils/validate-user-agent");
|
|
@@ -313,7 +315,8 @@ class SingleAgentClient {
|
|
|
313
315
|
* Returns the agent config with the discovered endpoint.
|
|
314
316
|
* Also computes the canonical base URL by stripping /mcp suffix.
|
|
315
317
|
*/
|
|
316
|
-
async ensureEndpointDiscovered() {
|
|
318
|
+
async ensureEndpointDiscovered(options) {
|
|
319
|
+
(0, abort_2.throwIfAborted)(options?.signal);
|
|
317
320
|
const needsDiscovery = this.normalizedAgent._needsDiscovery;
|
|
318
321
|
if (!needsDiscovery) {
|
|
319
322
|
return this.normalizedAgent;
|
|
@@ -330,7 +333,7 @@ class SingleAgentClient {
|
|
|
330
333
|
return this.discoveredAgent;
|
|
331
334
|
}
|
|
332
335
|
// Perform discovery
|
|
333
|
-
this.discoveredEndpoint = await this.discoverMCPEndpoint(this.normalizedAgent.agent_uri);
|
|
336
|
+
this.discoveredEndpoint = await this.discoverMCPEndpoint(this.normalizedAgent.agent_uri, options);
|
|
334
337
|
// Compute canonical base URL by stripping /mcp suffix
|
|
335
338
|
this.canonicalBaseUrl = this.computeBaseUrl(this.discoveredEndpoint);
|
|
336
339
|
this.discoveredAgent = {
|
|
@@ -345,7 +348,8 @@ class SingleAgentClient {
|
|
|
345
348
|
* Fetches the agent card and extracts the canonical URL.
|
|
346
349
|
* Returns the agent config with the canonical URL.
|
|
347
350
|
*/
|
|
348
|
-
async ensureCanonicalUrlResolved() {
|
|
351
|
+
async ensureCanonicalUrlResolved(options) {
|
|
352
|
+
(0, abort_2.throwIfAborted)(options?.signal);
|
|
349
353
|
const needsCanonicalUrl = this.normalizedAgent._needsCanonicalUrl;
|
|
350
354
|
if (!needsCanonicalUrl) {
|
|
351
355
|
return this.normalizedAgent;
|
|
@@ -358,7 +362,7 @@ class SingleAgentClient {
|
|
|
358
362
|
};
|
|
359
363
|
}
|
|
360
364
|
// Fetch agent card to get canonical URL
|
|
361
|
-
const canonicalUrl = await this.fetchA2ACanonicalUrl(this.normalizedAgent.agent_uri);
|
|
365
|
+
const canonicalUrl = await this.fetchA2ACanonicalUrl(this.normalizedAgent.agent_uri, options);
|
|
362
366
|
this.canonicalBaseUrl = canonicalUrl;
|
|
363
367
|
return {
|
|
364
368
|
...this.normalizedAgent,
|
|
@@ -372,7 +376,7 @@ class SingleAgentClient {
|
|
|
372
376
|
* - If the agent card fetch returns 401, throw AuthenticationRequiredError
|
|
373
377
|
* - Check for OAuth metadata to provide helpful guidance
|
|
374
378
|
*/
|
|
375
|
-
async fetchA2ACanonicalUrl(agentUri) {
|
|
379
|
+
async fetchA2ACanonicalUrl(agentUri, readOptions) {
|
|
376
380
|
const clientModule = require('@a2a-js/sdk/client');
|
|
377
381
|
const A2AClient = clientModule.A2AClient;
|
|
378
382
|
// adcp-client#1804 — wrap A2A card discovery in withResponseSizeLimit so
|
|
@@ -381,20 +385,22 @@ class SingleAgentClient {
|
|
|
381
385
|
// active ALS slot enforces the cap on the wire call. Matches the same
|
|
382
386
|
// pattern in `getAgentInfo` (closed #1799 via PR #1802).
|
|
383
387
|
const { withResponseSizeLimit, wrapFetchWithSizeLimit } = await Promise.resolve().then(() => __importStar(require('../protocols/responseSizeLimit')));
|
|
384
|
-
const
|
|
388
|
+
const transport = readOptions?.transport ?? this.config.transport;
|
|
389
|
+
const maxResponseBytes = transport?.maxResponseBytes;
|
|
390
|
+
const requestTimeoutMs = (0, abort_2.resolveRequestTimeoutMs)(transport?.requestTimeoutMs, abort_2.DEFAULT_REQUEST_TIMEOUT_MS);
|
|
385
391
|
const sizeLimitedFetch = wrapFetchWithSizeLimit((input, init) => fetch(input, init));
|
|
386
392
|
const authToken = this.normalizedAgent.auth_token;
|
|
387
393
|
let got401 = false;
|
|
388
|
-
const fetchImpl = async (url,
|
|
394
|
+
const fetchImpl = async (url, requestInit) => {
|
|
389
395
|
const headers = {
|
|
390
|
-
...
|
|
396
|
+
...requestInit?.headers,
|
|
391
397
|
...this.normalizedAgent.headers,
|
|
392
398
|
...(authToken && {
|
|
393
399
|
Authorization: `Bearer ${authToken}`,
|
|
394
400
|
'x-adcp-auth': authToken,
|
|
395
401
|
}),
|
|
396
402
|
};
|
|
397
|
-
const response = await sizeLimitedFetch(url, { ...
|
|
403
|
+
const response = await (0, abort_2.withAbortSignal)([readOptions?.signal, requestInit?.signal], requestTimeoutMs, signal => sizeLimitedFetch(url, { ...requestInit, headers, signal }));
|
|
398
404
|
// Track 401 errors for later handling
|
|
399
405
|
if (response.status === 401) {
|
|
400
406
|
got401 = true;
|
|
@@ -481,18 +487,25 @@ class SingleAgentClient {
|
|
|
481
487
|
*
|
|
482
488
|
* Note: This is async and called lazily on first agent interaction
|
|
483
489
|
*/
|
|
484
|
-
async discoverMCPEndpoint(providedUri) {
|
|
490
|
+
async discoverMCPEndpoint(providedUri, options) {
|
|
491
|
+
(0, abort_2.throwIfAborted)(options?.signal);
|
|
485
492
|
const { connectMCPWithFallback } = await Promise.resolve().then(() => __importStar(require('../protocols/mcp')));
|
|
486
493
|
const authToken = this.agent.auth_token;
|
|
487
494
|
const agentHeaders = this.agent.headers;
|
|
488
495
|
const authHeaders = { ...agentHeaders, ...(0, auth_1.createMCPAuthHeaders)(authToken) };
|
|
489
496
|
const testEndpoint = async (url) => {
|
|
490
497
|
try {
|
|
491
|
-
const client = await connectMCPWithFallback(new URL(url), authHeaders
|
|
498
|
+
const client = await connectMCPWithFallback(new URL(url), authHeaders, [], 'endpoint discovery', undefined, {
|
|
499
|
+
signal: options?.signal,
|
|
500
|
+
requestTimeoutMs: options?.transport?.requestTimeoutMs ?? this.config.transport?.requestTimeoutMs,
|
|
501
|
+
});
|
|
492
502
|
await client.close();
|
|
493
503
|
return { success: true };
|
|
494
504
|
}
|
|
495
505
|
catch (error) {
|
|
506
|
+
if ((0, abort_1.isAbortOrTimeoutError)(error)) {
|
|
507
|
+
throw error;
|
|
508
|
+
}
|
|
496
509
|
if ((0, errors_1.is401Error)(error)) {
|
|
497
510
|
return { success: false, status: 401, error };
|
|
498
511
|
}
|
|
@@ -1041,6 +1054,7 @@ class SingleAgentClient {
|
|
|
1041
1054
|
* Automatically adapts requests for v2 servers and normalizes responses.
|
|
1042
1055
|
*/
|
|
1043
1056
|
async executeAndHandle(taskType, handlerName, params, inputHandler, options) {
|
|
1057
|
+
(0, abort_2.throwIfAborted)(options?.signal);
|
|
1044
1058
|
// Normalize params for backwards compatibility before validation
|
|
1045
1059
|
let normalizedParams = (0, request_normalizer_1.normalizeRequestParams)(taskType, params, {
|
|
1046
1060
|
skipIdempotencyAutoInject: options?.skipIdempotencyAutoInject,
|
|
@@ -1075,17 +1089,17 @@ class SingleAgentClient {
|
|
|
1075
1089
|
this.validateRequest(taskType, normalizedParams);
|
|
1076
1090
|
}
|
|
1077
1091
|
// Validate required features before sending request
|
|
1078
|
-
await this.validateTaskFeatures(taskType);
|
|
1092
|
+
await this.validateTaskFeatures(taskType, options);
|
|
1079
1093
|
// Guard mutating calls against pre-v3 sellers when opted in.
|
|
1080
1094
|
if (this.config.requireV3ForMutations && (0, idempotency_1.isMutatingTask)(taskType)) {
|
|
1081
|
-
await this.requireSupportedMajor(taskType);
|
|
1095
|
+
await this.requireSupportedMajor(taskType, options);
|
|
1082
1096
|
}
|
|
1083
1097
|
// Check for v3 features used against v2 servers - return empty result if unsupported
|
|
1084
|
-
const earlyResult = await this.getEarlyResultForUnsupportedFeatures(taskType, normalizedParams);
|
|
1098
|
+
const earlyResult = await this.getEarlyResultForUnsupportedFeatures(taskType, normalizedParams, options);
|
|
1085
1099
|
if (earlyResult) {
|
|
1086
1100
|
return (0, match_1.attachMatch)(earlyResult);
|
|
1087
1101
|
}
|
|
1088
|
-
const agent = await this.ensureEndpointDiscovered();
|
|
1102
|
+
const agent = await this.ensureEndpointDiscovered(options);
|
|
1089
1103
|
// Schema-driven pre-send validation runs on the unadapted v3 shape so
|
|
1090
1104
|
// wire-format adapters (e.g. adaptGetProductsRequestForV2) don't strip
|
|
1091
1105
|
// v3-only fields out from under the v3 bundled schema. Skip the entire
|
|
@@ -1095,7 +1109,7 @@ class SingleAgentClient {
|
|
|
1095
1109
|
this.executor.validateRequest(taskType, normalizedParams);
|
|
1096
1110
|
}
|
|
1097
1111
|
// Adapt request for the detected server and AdCP protocol versions.
|
|
1098
|
-
const serverVersion = await this.detectServerVersion();
|
|
1112
|
+
const serverVersion = await this.detectServerVersion(options);
|
|
1099
1113
|
const inputSchemaStripLogs = [];
|
|
1100
1114
|
const { params: adaptedParams, driftLogs: adaptDriftLogs } = this.adaptRequest(taskType, normalizedParams, serverVersion, inputSchemaStripLogs);
|
|
1101
1115
|
// Symmetric to the pre-adapter v3 pass above: when the adapter
|
|
@@ -1584,13 +1598,13 @@ class SingleAgentClient {
|
|
|
1584
1598
|
*
|
|
1585
1599
|
* @returns TaskResult with empty data if v3 features are unsupported, null to proceed normally
|
|
1586
1600
|
*/
|
|
1587
|
-
async getEarlyResultForUnsupportedFeatures(taskType, params) {
|
|
1601
|
+
async getEarlyResultForUnsupportedFeatures(taskType, params, options) {
|
|
1588
1602
|
// Only check for tasks that have v3-specific features
|
|
1589
1603
|
if (taskType !== 'get_products') {
|
|
1590
1604
|
return null;
|
|
1591
1605
|
}
|
|
1592
1606
|
// Get capabilities to check what the server supports
|
|
1593
|
-
const capabilities = await this.getCapabilities();
|
|
1607
|
+
const capabilities = await this.getCapabilities(options);
|
|
1594
1608
|
// If server is v3, all features are supported - proceed normally
|
|
1595
1609
|
if (capabilities.version === 'v3') {
|
|
1596
1610
|
return null;
|
|
@@ -1867,7 +1881,7 @@ class SingleAgentClient {
|
|
|
1867
1881
|
* @param options - Task execution options
|
|
1868
1882
|
*/
|
|
1869
1883
|
async getAdcpCapabilities(params, inputHandler, options) {
|
|
1870
|
-
const agent = await this.ensureEndpointDiscovered();
|
|
1884
|
+
const agent = await this.ensureEndpointDiscovered(options);
|
|
1871
1885
|
this.executor.validateRequest('get_adcp_capabilities', params);
|
|
1872
1886
|
return this.executor.executeTask(agent, 'get_adcp_capabilities', params, inputHandler, options);
|
|
1873
1887
|
}
|
|
@@ -1996,6 +2010,7 @@ class SingleAgentClient {
|
|
|
1996
2010
|
* ```
|
|
1997
2011
|
*/
|
|
1998
2012
|
async executeTask(taskName, params, inputHandler, options) {
|
|
2013
|
+
(0, abort_2.throwIfAborted)(options?.signal);
|
|
1999
2014
|
const startTime = Date.now();
|
|
2000
2015
|
try {
|
|
2001
2016
|
const normalizedParams = (0, request_normalizer_1.normalizeRequestParams)(taskName, params, {
|
|
@@ -2007,11 +2022,11 @@ class SingleAgentClient {
|
|
|
2007
2022
|
// (get_products / get_signals). `effectiveOptions` carries disableWebhook
|
|
2008
2023
|
// so no push_notification_config reaches a seller that can't accept it.
|
|
2009
2024
|
const { options: effectiveOptions, driftLog: webhookDriftLog } = this.suppressPre31DiscoveryWebhook(taskName, options);
|
|
2010
|
-
await this.validateTaskFeatures(taskName);
|
|
2025
|
+
await this.validateTaskFeatures(taskName, options);
|
|
2011
2026
|
if (this.config.requireV3ForMutations && (0, idempotency_1.isMutatingTask)(taskName)) {
|
|
2012
|
-
await this.requireSupportedMajor(taskName);
|
|
2027
|
+
await this.requireSupportedMajor(taskName, options);
|
|
2013
2028
|
}
|
|
2014
|
-
const agent = await this.ensureEndpointDiscovered();
|
|
2029
|
+
const agent = await this.ensureEndpointDiscovered(options);
|
|
2015
2030
|
// Schema-driven pre-send validation runs on the unadapted v3 shape so
|
|
2016
2031
|
// wire-format adapters (e.g. adaptGetProductsRequestForV2) don't strip
|
|
2017
2032
|
// v3-only fields out from under the v3 bundled schema. Skip the entire
|
|
@@ -2021,7 +2036,7 @@ class SingleAgentClient {
|
|
|
2021
2036
|
this.executor.validateRequest(taskName, normalizedParams);
|
|
2022
2037
|
}
|
|
2023
2038
|
// Adapt request for the detected server and AdCP protocol versions.
|
|
2024
|
-
const serverVersion = await this.detectServerVersion();
|
|
2039
|
+
const serverVersion = await this.detectServerVersion(options);
|
|
2025
2040
|
const inputSchemaStripLogs = [];
|
|
2026
2041
|
const { params: adaptedParams, driftLogs: adaptDriftLogs } = this.adaptRequest(taskName, normalizedParams, serverVersion, inputSchemaStripLogs);
|
|
2027
2042
|
// Symmetric warn-only post-adapter pass against the v2.5 schema bundle.
|
|
@@ -2055,7 +2070,8 @@ class SingleAgentClient {
|
|
|
2055
2070
|
if (error instanceof errors_1.AuthenticationRequiredError ||
|
|
2056
2071
|
error instanceof errors_1.TaskTimeoutError ||
|
|
2057
2072
|
error instanceof errors_1.VersionUnsupportedError ||
|
|
2058
|
-
error instanceof errors_1.FeatureUnsupportedError
|
|
2073
|
+
error instanceof errors_1.FeatureUnsupportedError ||
|
|
2074
|
+
(0, abort_1.isAbortOrTimeoutError)(error)) {
|
|
2059
2075
|
throw error;
|
|
2060
2076
|
}
|
|
2061
2077
|
// Unexpected pre-flight errors (e.g. a TypeError from response parsing
|
|
@@ -2408,17 +2424,25 @@ class SingleAgentClient {
|
|
|
2408
2424
|
* });
|
|
2409
2425
|
* ```
|
|
2410
2426
|
*/
|
|
2411
|
-
async getAgentInfo() {
|
|
2427
|
+
async getAgentInfo(options) {
|
|
2412
2428
|
// adcp-client#1799 — wrap every wire call in the response-size cap so
|
|
2413
2429
|
// `transport.maxResponseBytes` extends to discovery / tools-list bodies.
|
|
2414
2430
|
// `withResponseSizeLimit` is a no-op when no cap is configured.
|
|
2415
2431
|
const { withResponseSizeLimit } = await Promise.resolve().then(() => __importStar(require('../protocols/responseSizeLimit')));
|
|
2416
|
-
|
|
2432
|
+
(0, abort_2.throwIfAborted)(options?.signal);
|
|
2433
|
+
const transport = options?.transport ?? this.config.transport;
|
|
2434
|
+
const maxResponseBytes = transport?.maxResponseBytes;
|
|
2435
|
+
const requestTimeoutMs = (0, abort_2.resolveRequestTimeoutMs)(transport?.requestTimeoutMs, abort_2.DEFAULT_REQUEST_TIMEOUT_MS);
|
|
2436
|
+
const clientRequestTimeoutMs = (0, abort_2.resolveClientRequestTimeoutMs)(transport?.requestTimeoutMs);
|
|
2437
|
+
const mcpRequestOptions = {
|
|
2438
|
+
...(options?.signal && { signal: options.signal }),
|
|
2439
|
+
...(clientRequestTimeoutMs !== undefined && { timeout: clientRequestTimeoutMs }),
|
|
2440
|
+
};
|
|
2417
2441
|
if (this.normalizedAgent.protocol === 'mcp') {
|
|
2418
2442
|
// In-process: use the pre-connected client instead of opening a new HTTP connection
|
|
2419
2443
|
if (this.normalizedAgent._inProcessMcpClient) {
|
|
2420
2444
|
const mcpClient = this.normalizedAgent._inProcessMcpClient;
|
|
2421
|
-
const toolsList = await withResponseSizeLimit(maxResponseBytes, () => mcpClient.listTools());
|
|
2445
|
+
const toolsList = await withResponseSizeLimit(maxResponseBytes, () => mcpClient.listTools(undefined, mcpRequestOptions));
|
|
2422
2446
|
const tools = toolsList.tools.map(tool => ({
|
|
2423
2447
|
name: tool.name,
|
|
2424
2448
|
description: tool.description,
|
|
@@ -2434,7 +2458,7 @@ class SingleAgentClient {
|
|
|
2434
2458
|
};
|
|
2435
2459
|
}
|
|
2436
2460
|
// Discover endpoint if needed
|
|
2437
|
-
const agent = await this.ensureEndpointDiscovered();
|
|
2461
|
+
const agent = await this.ensureEndpointDiscovered(options);
|
|
2438
2462
|
// Use the shared connectMCP path so both static bearer AND saved OAuth
|
|
2439
2463
|
// tokens work. OAuth takes the refresh-capable authProvider branch.
|
|
2440
2464
|
// Header-only auth (basic, x-api-key, custom routing) lives on
|
|
@@ -2443,6 +2467,12 @@ class SingleAgentClient {
|
|
|
2443
2467
|
// SDK doesn't emit a competing `Authorization: Bearer …`.
|
|
2444
2468
|
const { connectMCP } = await Promise.resolve().then(() => __importStar(require('../protocols/mcp')));
|
|
2445
2469
|
const connectOptions = { agentUrl: agent.agent_uri };
|
|
2470
|
+
if (options?.signal) {
|
|
2471
|
+
connectOptions.signal = options.signal;
|
|
2472
|
+
}
|
|
2473
|
+
if (transport?.requestTimeoutMs !== undefined) {
|
|
2474
|
+
connectOptions.requestTimeoutMs = transport.requestTimeoutMs;
|
|
2475
|
+
}
|
|
2446
2476
|
if (this.normalizedAgent.headers && Object.keys(this.normalizedAgent.headers).length > 0) {
|
|
2447
2477
|
connectOptions.customHeaders = this.normalizedAgent.headers;
|
|
2448
2478
|
}
|
|
@@ -2457,7 +2487,7 @@ class SingleAgentClient {
|
|
|
2457
2487
|
}
|
|
2458
2488
|
const { client: mcpClient } = await connectMCP(connectOptions);
|
|
2459
2489
|
try {
|
|
2460
|
-
const toolsList = await withResponseSizeLimit(maxResponseBytes, () => mcpClient.listTools());
|
|
2490
|
+
const toolsList = await withResponseSizeLimit(maxResponseBytes, () => mcpClient.listTools(undefined, mcpRequestOptions));
|
|
2461
2491
|
const tools = toolsList.tools.map(tool => ({
|
|
2462
2492
|
name: tool.name,
|
|
2463
2493
|
description: tool.description,
|
|
@@ -2491,17 +2521,39 @@ class SingleAgentClient {
|
|
|
2491
2521
|
// calls native `fetch` directly and ignores `transport.maxResponseBytes`.
|
|
2492
2522
|
const { wrapFetchWithSizeLimit } = await Promise.resolve().then(() => __importStar(require('../protocols/responseSizeLimit')));
|
|
2493
2523
|
const authToken = this.normalizedAgent.auth_token;
|
|
2524
|
+
const agentHeaders = this.normalizedAgent.headers ?? {};
|
|
2494
2525
|
const sizeLimitedFetch = wrapFetchWithSizeLimit((input, init) => fetch(input, init));
|
|
2495
|
-
const
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2526
|
+
const normalizeHeaders = (headers) => {
|
|
2527
|
+
const normalized = {};
|
|
2528
|
+
if (!headers)
|
|
2529
|
+
return normalized;
|
|
2530
|
+
if (headers instanceof Headers) {
|
|
2531
|
+
headers.forEach((value, key) => {
|
|
2532
|
+
normalized[key] = value;
|
|
2533
|
+
});
|
|
2534
|
+
}
|
|
2535
|
+
else if (Array.isArray(headers)) {
|
|
2536
|
+
for (const [key, value] of headers) {
|
|
2537
|
+
normalized[key] = value;
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
else {
|
|
2541
|
+
Object.assign(normalized, headers);
|
|
2503
2542
|
}
|
|
2504
|
-
|
|
2543
|
+
return normalized;
|
|
2544
|
+
};
|
|
2545
|
+
const buildHeaders = (requestInit) => ({
|
|
2546
|
+
...normalizeHeaders(requestInit?.headers),
|
|
2547
|
+
...agentHeaders,
|
|
2548
|
+
...(authToken && {
|
|
2549
|
+
Authorization: `Bearer ${authToken}`,
|
|
2550
|
+
'x-adcp-auth': authToken,
|
|
2551
|
+
}),
|
|
2552
|
+
});
|
|
2553
|
+
const fetchImpl = async (url, requestInit) => {
|
|
2554
|
+
const headers = buildHeaders(requestInit);
|
|
2555
|
+
return (0, abort_2.withAbortSignal)([options?.signal, requestInit?.signal], requestTimeoutMs, signal => sizeLimitedFetch(url, { ...requestInit, headers, signal }));
|
|
2556
|
+
};
|
|
2505
2557
|
const cardUrls = (0, a2a_discovery_1.buildCardUrls)(this.normalizedAgent.agent_uri);
|
|
2506
2558
|
let client;
|
|
2507
2559
|
let lastCardError = new Error(`A2A agent card not found at ${cardUrls.join(', ')}`);
|
|
@@ -2559,14 +2611,15 @@ class SingleAgentClient {
|
|
|
2559
2611
|
* }
|
|
2560
2612
|
* ```
|
|
2561
2613
|
*/
|
|
2562
|
-
async getCapabilities() {
|
|
2614
|
+
async getCapabilities(options) {
|
|
2615
|
+
(0, abort_2.throwIfAborted)(options?.signal);
|
|
2563
2616
|
// Return cached if available
|
|
2564
2617
|
if (this.cachedCapabilities) {
|
|
2565
2618
|
this.maybeWarnV2Sunset(this.cachedCapabilities);
|
|
2566
2619
|
return this.cachedCapabilities;
|
|
2567
2620
|
}
|
|
2568
2621
|
// First get tool list to support both detection methods
|
|
2569
|
-
const agentInfo = await this.getAgentInfo();
|
|
2622
|
+
const agentInfo = await this.getAgentInfo(options);
|
|
2570
2623
|
const tools = agentInfo.tools.map(t => ({
|
|
2571
2624
|
name: t.name,
|
|
2572
2625
|
description: t.description,
|
|
@@ -2585,8 +2638,15 @@ class SingleAgentClient {
|
|
|
2585
2638
|
// because normalizeAgentConfig returns early when _inProcessMcpClient is set). The
|
|
2586
2639
|
// executor then hits ProtocolClient.callTool which reads _inProcessMcpClient directly,
|
|
2587
2640
|
// so the sentinel adcp-in-process:// URI never reaches validateAgentUrl.
|
|
2588
|
-
const agent = await this.ensureEndpointDiscovered();
|
|
2589
|
-
const result = await this.executor.executeTask(agent, 'get_adcp_capabilities', {}, undefined);
|
|
2641
|
+
const agent = await this.ensureEndpointDiscovered(options);
|
|
2642
|
+
const result = await this.executor.executeTask(agent, 'get_adcp_capabilities', {}, undefined, options);
|
|
2643
|
+
(0, abort_2.throwIfAborted)(options?.signal);
|
|
2644
|
+
const requestTimeoutMs = (0, abort_2.resolveRequestTimeoutMs)(options?.transport?.requestTimeoutMs ?? this.config.transport?.requestTimeoutMs);
|
|
2645
|
+
if (!result.success &&
|
|
2646
|
+
requestTimeoutMs !== undefined &&
|
|
2647
|
+
/\b(requesttimeout|timeout|timed out)\b/i.test(result.error ?? '')) {
|
|
2648
|
+
throw (0, abort_2.createTimeoutError)(requestTimeoutMs);
|
|
2649
|
+
}
|
|
2590
2650
|
if (result.success && result.data) {
|
|
2591
2651
|
this.cachedCapabilities = (0, capabilities_1.augmentCapabilitiesFromTools)((0, capabilities_1.parseCapabilitiesResponse)(result.data), tools);
|
|
2592
2652
|
this.maybeWarnV2Sunset(this.cachedCapabilities);
|
|
@@ -2641,7 +2701,7 @@ class SingleAgentClient {
|
|
|
2641
2701
|
`since the agent has the v3-only discovery tool. ` +
|
|
2642
2702
|
`This client routes to v3 adapters, but calls reading capability details ` +
|
|
2643
2703
|
`(idempotency TTL, supported_versions, feature flags) will fail until the agent ` +
|
|
2644
|
-
`operator fixes the capabilities endpoint
|
|
2704
|
+
`operator fixes the capabilities endpoint.`, {
|
|
2645
2705
|
success: result.success,
|
|
2646
2706
|
hasError: !!result.error,
|
|
2647
2707
|
hasData: !!result.data,
|
|
@@ -2651,15 +2711,16 @@ class SingleAgentClient {
|
|
|
2651
2711
|
// Re-throw errors that indicate real infrastructure problems —
|
|
2652
2712
|
// only fall through for tool-execution failures (the agent
|
|
2653
2713
|
// advertises get_adcp_capabilities but can't actually serve it).
|
|
2654
|
-
if (error instanceof errors_1.AuthenticationRequiredError ||
|
|
2714
|
+
if (error instanceof errors_1.AuthenticationRequiredError ||
|
|
2715
|
+
error instanceof errors_1.TaskTimeoutError ||
|
|
2716
|
+
(0, abort_1.isAbortOrTimeoutError)(error)) {
|
|
2655
2717
|
throw error;
|
|
2656
2718
|
}
|
|
2657
2719
|
console.warn(`[AdCP] Agent "${this.agent.id}" advertises get_adcp_capabilities but the call ` +
|
|
2658
2720
|
`threw — treating as v3 (synthetic) since the agent has the v3-only discovery tool. ` +
|
|
2659
2721
|
`This client routes to v3 adapters, but calls reading capability details ` +
|
|
2660
2722
|
`(idempotency TTL, supported_versions, feature flags) will fail until the agent ` +
|
|
2661
|
-
`operator fixes the capabilities endpoint
|
|
2662
|
-
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
2723
|
+
`operator fixes the capabilities endpoint.`);
|
|
2663
2724
|
}
|
|
2664
2725
|
// Synthesize v3 capabilities from the tool list. Reached only when
|
|
2665
2726
|
// the executor returned non-v3-shaped data, OR threw a non-auth
|
|
@@ -2750,8 +2811,8 @@ class SingleAgentClient {
|
|
|
2750
2811
|
*
|
|
2751
2812
|
* @returns 'v2' or 'v3' based on server capabilities
|
|
2752
2813
|
*/
|
|
2753
|
-
async detectServerVersion() {
|
|
2754
|
-
const capabilities = await this.getCapabilities();
|
|
2814
|
+
async detectServerVersion(options) {
|
|
2815
|
+
const capabilities = await this.getCapabilities(options);
|
|
2755
2816
|
return capabilities.version;
|
|
2756
2817
|
}
|
|
2757
2818
|
/**
|
|
@@ -2848,13 +2909,17 @@ class SingleAgentClient {
|
|
|
2848
2909
|
*
|
|
2849
2910
|
* Skipped when validateFeatures is false or the task has no feature requirements.
|
|
2850
2911
|
*/
|
|
2851
|
-
async validateTaskFeatures(taskName) {
|
|
2912
|
+
async validateTaskFeatures(taskName, options) {
|
|
2852
2913
|
if (this.config.validateFeatures === false)
|
|
2853
2914
|
return;
|
|
2854
2915
|
const requiredFeatures = capabilities_1.TASK_FEATURE_MAP[taskName];
|
|
2855
2916
|
if (!requiredFeatures || requiredFeatures.length === 0)
|
|
2856
2917
|
return;
|
|
2857
|
-
await this.
|
|
2918
|
+
const capabilities = await this.getCapabilities(options);
|
|
2919
|
+
const missing = requiredFeatures.filter(f => !(0, capabilities_1.resolveFeature)(capabilities, f));
|
|
2920
|
+
if (missing.length > 0) {
|
|
2921
|
+
throw new errors_1.FeatureUnsupportedError(missing, (0, capabilities_1.listDeclaredFeatures)(capabilities), this.agent.agent_uri);
|
|
2922
|
+
}
|
|
2858
2923
|
}
|
|
2859
2924
|
/**
|
|
2860
2925
|
* Fail version-incompatible request shapes before schema validation.
|
|
@@ -2968,10 +3033,10 @@ class SingleAgentClient {
|
|
|
2968
3033
|
*
|
|
2969
3034
|
* Throws `VersionUnsupportedError` with the specific reason on failure.
|
|
2970
3035
|
*/
|
|
2971
|
-
async requireSupportedMajor(taskType = 'request') {
|
|
3036
|
+
async requireSupportedMajor(taskType = 'request', options) {
|
|
2972
3037
|
if (this.isV2Allowed())
|
|
2973
3038
|
return;
|
|
2974
|
-
const capabilities = await this.getCapabilities();
|
|
3039
|
+
const capabilities = await this.getCapabilities(options);
|
|
2975
3040
|
// Synthetic capabilities — no authoritative `get_adcp_capabilities`
|
|
2976
3041
|
// response, so the version + idempotency-TTL fields couldn't be read.
|
|
2977
3042
|
// Route as the synthesized version (v2 when the v3 discovery tool is
|