@adcp/sdk 16.0.0 → 16.2.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.
Files changed (85) hide show
  1. package/README.md +52 -0
  2. package/bin/adcp-identity.js +3 -2
  3. package/dist/lib/client/core.d.mts +1 -1
  4. package/dist/lib/client/core.d.ts +1 -1
  5. package/dist/lib/core/AgentClient.d.mts +8 -1
  6. package/dist/lib/core/AgentClient.d.ts +8 -1
  7. package/dist/lib/core/AgentClient.js +10 -0
  8. package/dist/lib/core/AgentClient.mjs +10 -0
  9. package/dist/lib/core/AsyncHandler.d.mts +2 -0
  10. package/dist/lib/core/AsyncHandler.d.ts +2 -0
  11. package/dist/lib/core/AsyncHandler.js +1 -1
  12. package/dist/lib/core/AsyncHandler.mjs +1 -1
  13. package/dist/lib/core/ConversationTypes.d.mts +32 -0
  14. package/dist/lib/core/ConversationTypes.d.ts +32 -0
  15. package/dist/lib/core/SingleAgentClient.d.mts +11 -1
  16. package/dist/lib/core/SingleAgentClient.d.ts +11 -1
  17. package/dist/lib/core/SingleAgentClient.js +25 -6
  18. package/dist/lib/core/SingleAgentClient.mjs +26 -7
  19. package/dist/lib/core/TaskExecutor.d.mts +3 -1
  20. package/dist/lib/core/TaskExecutor.d.ts +3 -1
  21. package/dist/lib/core/TaskExecutor.js +127 -34
  22. package/dist/lib/core/TaskExecutor.mjs +127 -34
  23. package/dist/lib/core/task-deadline.d.mts +2 -0
  24. package/dist/lib/core/task-deadline.d.ts +2 -0
  25. package/dist/lib/core/task-deadline.js +20 -2
  26. package/dist/lib/core/task-deadline.mjs +19 -2
  27. package/dist/lib/governance/authorization.d.mts +66 -0
  28. package/dist/lib/governance/authorization.d.ts +66 -0
  29. package/dist/lib/governance/authorization.js +181 -37
  30. package/dist/lib/governance/authorization.mjs +183 -36
  31. package/dist/lib/governance/index.d.mts +2 -2
  32. package/dist/lib/governance/index.d.ts +2 -2
  33. package/dist/lib/governance/index.js +4 -2
  34. package/dist/lib/governance/index.mjs +3 -1
  35. package/dist/lib/identity-3.3/index.d.mts +1 -0
  36. package/dist/lib/identity-3.3/index.d.ts +1 -0
  37. package/dist/lib/identity-3.3/index.js +3 -1
  38. package/dist/lib/identity-3.3/index.mjs +1 -0
  39. package/dist/lib/identity-3.3/jws-artifacts.d.mts +147 -0
  40. package/dist/lib/identity-3.3/jws-artifacts.d.ts +147 -0
  41. package/dist/lib/identity-3.3/jws-artifacts.js +258 -0
  42. package/dist/lib/identity-3.3/jws-artifacts.mjs +234 -0
  43. package/dist/lib/identity-3.3/revocation.d.mts +7 -0
  44. package/dist/lib/identity-3.3/revocation.d.ts +7 -0
  45. package/dist/lib/identity-3.3/revocation.js +13 -0
  46. package/dist/lib/identity-3.3/revocation.mjs +13 -0
  47. package/dist/lib/identity-3.3/schemas.draft.js +1 -1
  48. package/dist/lib/identity-3.3/schemas.draft.mjs +1 -1
  49. package/dist/lib/identity-3.3/trust.d.mts +8 -0
  50. package/dist/lib/identity-3.3/trust.d.ts +8 -0
  51. package/dist/lib/identity-3.3/trust.js +41 -12
  52. package/dist/lib/identity-3.3/trust.mjs +40 -12
  53. package/dist/lib/index.d.mts +3 -3
  54. package/dist/lib/index.d.ts +3 -3
  55. package/dist/lib/index.js +2 -0
  56. package/dist/lib/index.mjs +2 -0
  57. package/dist/lib/registry/types.generated.d.mts +24 -1
  58. package/dist/lib/registry/types.generated.d.ts +24 -1
  59. package/dist/lib/server/account-sync-contract.js +4 -1
  60. package/dist/lib/server/account-sync-contract.mjs +4 -1
  61. package/dist/lib/server/decisioning/runtime/from-platform.js +22 -17
  62. package/dist/lib/server/decisioning/runtime/from-platform.mjs +22 -17
  63. package/dist/lib/server/index.d.mts +2 -2
  64. package/dist/lib/server/index.d.ts +2 -2
  65. package/dist/lib/server/index.js +2 -0
  66. package/dist/lib/server/index.mjs +2 -0
  67. package/dist/lib/signing/web-bot-auth.js +25 -5
  68. package/dist/lib/signing/web-bot-auth.mjs +25 -6
  69. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  70. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  71. package/dist/lib/v2/projection/catalog.d.mts +6 -0
  72. package/dist/lib/v2/projection/catalog.d.ts +6 -0
  73. package/dist/lib/v2/projection/catalog.js +5 -0
  74. package/dist/lib/v2/projection/catalog.mjs +4 -0
  75. package/dist/lib/v2/projection/v1-to-v2.js +3 -2
  76. package/dist/lib/v2/projection/v1-to-v2.mjs +4 -3
  77. package/dist/lib/version.d.mts +3 -3
  78. package/dist/lib/version.d.ts +3 -3
  79. package/dist/lib/version.js +3 -3
  80. package/dist/lib/version.mjs +3 -3
  81. package/docs/TYPE-SUMMARY.md +12 -2
  82. package/docs/llms.txt +3 -3
  83. package/docs/migration-14.x-rc-worksheet.md +4 -4
  84. package/docs/migration-agent-identity-3.3.md +72 -19
  85. package/package.json +6 -4
package/README.md CHANGED
@@ -204,6 +204,58 @@ if (result.status === 'submitted') {
204
204
  }
205
205
  ```
206
206
 
207
+ ### Tracking a seller task after a restart
208
+
209
+ Persist `result.metadata.serverTaskId`, the original tool name, and
210
+ `result.metadata.taskId` (the buyer's operation ID) when a seller returns
211
+ `submitted` or `working`. A new client can reconstruct the polling handle:
212
+
213
+ ```typescript
214
+ const tracked = await agent.trackTask({
215
+ taskId: saved.serverTaskId,
216
+ taskType: saved.taskType,
217
+ operationId: saved.operationId,
218
+ });
219
+
220
+ const status = await tracked.track(); // One status check
221
+ const completed = await tracked.waitForCompletion(1000, AbortSignal.timeout(60_000));
222
+ ```
223
+
224
+ Each poll uses AdCP `tasks_get` (MCP) or `tasks/get` (A2A) with
225
+ `{ task_id, include_result: true }`. Polls do not create separate
226
+ `protocol_request` / `protocol_response` activity records. Terminal
227
+ `status_change` activity carries the stable `operation_id` and the seller's
228
+ `server_task_id`; existing `task_id` fields retain their current meaning.
229
+ `TaskInfo` from the handle also carries `operationId` and `serverTaskId`.
230
+ The SDK checks the returned task ID and tool name before exposing a result.
231
+
232
+ Omitting `operationId` generates a UUID, available as `tracked.operationId`.
233
+ Reuse the handle within a client, or call `trackTask` again with the same
234
+ operation ID, seller task ID, and tool name to rebuild it. You can pin the ID before submitting work
235
+ with `TaskOptions.operationId`, for example
236
+ `agent.executeCustomTask('extension_task', params, undefined, { operationId })`.
237
+ Use a globally unique, opaque operation ID per dispatch (UUID recommended),
238
+ including across clients and tenants sharing persistence or webhook receivers.
239
+ Reuse it for tracking. To retry a dispatch after a crash, use a new operation ID
240
+ and the same `idempotency_key`. Operation IDs correlate observations;
241
+ `idempotency_key` provides retry safety. The SDK rejects local collisions;
242
+ uniqueness across processes is the caller's responsibility. Avoid sensitive
243
+ information in these IDs because webhook registration sends them to the seller.
244
+ They accept 1–255 letters, digits, underscores, periods, colons, or hyphens.
245
+ Dot-only IDs and the `delivery_route:` prefix are reserved.
246
+
247
+ Tracking returns the seller's original tool response shape and emits lifecycle
248
+ activity. It does not restore the original request's policy/projection context
249
+ or invoke inline tool completion handlers. Handle the returned result in the
250
+ caller. Pass `transport` or `signal` in the tracking request to configure the
251
+ polling lifetime; `track(transport)` overrides transport options for one poll.
252
+ Local cancellation, identity mismatches, missing tasks, and malformed poll
253
+ responses return or throw observation errors without publishing seller failure
254
+ events. Rebuild the handle with a fresh signal to resume after cancellation.
255
+ For A2A, stopping observation leaves seller work running by default. Set both
256
+ `cancelOnAbort: true` and `a2aTaskId` to request cancellation of seller work
257
+ when polling aborts; `a2aTaskId` must be the separate A2A transport task ID.
258
+
207
259
  ### Handling Clarifications (input-required)
208
260
 
209
261
  When an agent needs more information, you can continue the conversation:
@@ -4,7 +4,7 @@ const { parseStrictJson } = require('../dist/lib/signing/agent-resolver/strict-j
4
4
  const {
5
5
  createSignedSignatureDirectory,
6
6
  createSignedOriginRevocationList,
7
- validateTrustRecord,
7
+ assertPublishableTrustRecord,
8
8
  } = require('../dist/lib/identity-3.3/index.js');
9
9
 
10
10
  async function handleIdentityCommand(args) {
@@ -17,7 +17,8 @@ async function handleIdentityCommand(args) {
17
17
  if (!args[1]) throw new Error('Usage: adcp identity trust-validate trust.json');
18
18
  const bytes = readFileSync(args[1]);
19
19
  if (bytes.length > 2 * 1024 * 1024) throw new Error('trust.json exceeds 2 MiB');
20
- validateTrustRecord(parseStrictJson(new TextDecoder('utf-8', { fatal: true }).decode(bytes), 32));
20
+ // Publication rules, not only the schema: a non-registrable grantee grants nothing.
21
+ assertPublishableTrustRecord(parseStrictJson(new TextDecoder('utf-8', { fatal: true }).decode(bytes), 32));
21
22
  process.stdout.write('Valid experimental trust v1 record\n');
22
23
  return;
23
24
  }
@@ -4,7 +4,7 @@ export { ADCPMultiAgentClient, createADCPMultiAgentClient, type MultiAgentWebhoo
4
4
  export { CreativeAgentClient, createCreativeAgentClient, STANDARD_CREATIVE_AGENTS, type CreativeAgentClientConfig, type CreativeAgentListTaskOptions, type LegacyCreativeFormat, } from '../core/CreativeAgentClient.mjs';
5
5
  export { ConfigurationManager } from '../core/ConfigurationManager.mjs';
6
6
  export { InMemoryWebhookRegistrationStore, type InMemoryWebhookRegistrationStoreOptions, type WebhookAuthenticationMode, type WebhookRegistration, type WebhookRegistrationStore, } from '../core/webhook-registration.mjs';
7
- export type { ConversationConfig, ConversationContext, InputHandler, InputHandlerResponse, InputRequest, Message, TaskInfo, TaskOptions, TaskResult, TaskResultCompleted, TaskResultFailure, TaskResultIntermediate, TaskResultMetadata, } from '../core/ConversationTypes.mjs';
7
+ export type { ConversationConfig, ConversationContext, InputHandler, InputHandlerResponse, InputRequest, Message, TaskInfo, TaskOptions, TrackTaskRequest, TrackedTask, SubmittedContinuation, TaskResult, TaskResultCompleted, TaskResultFailure, TaskResultIntermediate, TaskResultMetadata, } from '../core/ConversationTypes.mjs';
8
8
  export type { AgentConfig } from '../types/adcp.mjs';
9
9
  export type { ResolveAccountOptions, ResolveAccountResult, ListedAccount } from '../core/account-resolution.mjs';
10
10
  export type { CreativeFormatWireMode } from '../v2/projection/creative-delivery.mjs';
@@ -4,7 +4,7 @@ export { ADCPMultiAgentClient, createADCPMultiAgentClient, type MultiAgentWebhoo
4
4
  export { CreativeAgentClient, createCreativeAgentClient, STANDARD_CREATIVE_AGENTS, type CreativeAgentClientConfig, type CreativeAgentListTaskOptions, type LegacyCreativeFormat, } from '../core/CreativeAgentClient';
5
5
  export { ConfigurationManager } from '../core/ConfigurationManager';
6
6
  export { InMemoryWebhookRegistrationStore, type InMemoryWebhookRegistrationStoreOptions, type WebhookAuthenticationMode, type WebhookRegistration, type WebhookRegistrationStore, } from '../core/webhook-registration';
7
- export type { ConversationConfig, ConversationContext, InputHandler, InputHandlerResponse, InputRequest, Message, TaskInfo, TaskOptions, TaskResult, TaskResultCompleted, TaskResultFailure, TaskResultIntermediate, TaskResultMetadata, } from '../core/ConversationTypes';
7
+ export type { ConversationConfig, ConversationContext, InputHandler, InputHandlerResponse, InputRequest, Message, TaskInfo, TaskOptions, TrackTaskRequest, TrackedTask, SubmittedContinuation, TaskResult, TaskResultCompleted, TaskResultFailure, TaskResultIntermediate, TaskResultMetadata, } from '../core/ConversationTypes';
8
8
  export type { AgentConfig } from '../types/adcp';
9
9
  export type { ResolveAccountOptions, ResolveAccountResult, ListedAccount } from '../core/account-resolution';
10
10
  export type { CreativeFormatWireMode } from '../v2/projection/creative-delivery';
@@ -4,7 +4,7 @@ import type { ResolveAccountOptions, ResolveAccountResult } from './account-reso
4
4
  import type { MCPWebhookPayload, GetBrandIdentityRequest, GetBrandIdentityResponse, ContextMatchRequest, ContextMatchResponse, IdentityMatchRequest, IdentityMatchResponseRouterPublisher } from '../types/core.generated.mjs';
5
5
  import type { Task as A2ATask, TaskStatusUpdateEvent } from '@a2a-js/sdk';
6
6
  import { type CapabilityEvidenceScope, type CapabilityEvidenceSnapshot, type CanonicalReadTaskOptions, type CreativeDeliveryTaskOptions, type SingleAgentClientConfig, type SyncCreativesTaskOptions, type VerifyAndParseWebhookOptions, type WebhookHandlerAdapter, type WebhookParseResult, type WebhookRequestContext } from './SingleAgentClient.mjs';
7
- import type { InputHandler, TaskOptions, TaskResult, TaskInfo, Message, DirectPauseRecoveryRequest } from './ConversationTypes.mjs';
7
+ import type { InputHandler, TaskOptions, TaskResult, TaskInfo, Message, DirectPauseRecoveryRequest, TrackTaskRequest, TrackedTask } from './ConversationTypes.mjs';
8
8
  import type { AdcpCapabilities } from '../utils/capabilities.mjs';
9
9
  import type { WebhookHeaderValue } from '../webhooks/index.mjs';
10
10
  import type { ListProductsResponseWithSupplyPath } from '../supply-path/index.mjs';
@@ -794,6 +794,13 @@ export declare class AgentClient {
794
794
  * Get active tasks for this agent
795
795
  */
796
796
  getActiveTasks(): import("./ConversationTypes.mjs").TaskState[];
797
+ /**
798
+ * Rebuild a polling handle for a persisted seller task. Reuse operationId
799
+ * from the original TaskResult.metadata.taskId to correlate its lifecycle.
800
+ * The handle provides track() and waitForCompletion(); polling itself does
801
+ * not create new protocol activity records. Results retain seller tool shapes.
802
+ */
803
+ trackTask<T = unknown>(request: TrackTaskRequest): Promise<TrackedTask<T>>;
797
804
  /**
798
805
  * Execute any ADCP task by name with full type safety
799
806
  *
@@ -4,7 +4,7 @@ import type { ResolveAccountOptions, ResolveAccountResult } from './account-reso
4
4
  import type { MCPWebhookPayload, GetBrandIdentityRequest, GetBrandIdentityResponse, ContextMatchRequest, ContextMatchResponse, IdentityMatchRequest, IdentityMatchResponseRouterPublisher } from '../types/core.generated';
5
5
  import type { Task as A2ATask, TaskStatusUpdateEvent } from '@a2a-js/sdk';
6
6
  import { type CapabilityEvidenceScope, type CapabilityEvidenceSnapshot, type CanonicalReadTaskOptions, type CreativeDeliveryTaskOptions, type SingleAgentClientConfig, type SyncCreativesTaskOptions, type VerifyAndParseWebhookOptions, type WebhookHandlerAdapter, type WebhookParseResult, type WebhookRequestContext } from './SingleAgentClient';
7
- import type { InputHandler, TaskOptions, TaskResult, TaskInfo, Message, DirectPauseRecoveryRequest } from './ConversationTypes';
7
+ import type { InputHandler, TaskOptions, TaskResult, TaskInfo, Message, DirectPauseRecoveryRequest, TrackTaskRequest, TrackedTask } from './ConversationTypes';
8
8
  import type { AdcpCapabilities } from '../utils/capabilities';
9
9
  import type { WebhookHeaderValue } from '../webhooks';
10
10
  import type { ListProductsResponseWithSupplyPath } from '../supply-path';
@@ -794,6 +794,13 @@ export declare class AgentClient {
794
794
  * Get active tasks for this agent
795
795
  */
796
796
  getActiveTasks(): import("./ConversationTypes").TaskState[];
797
+ /**
798
+ * Rebuild a polling handle for a persisted seller task. Reuse operationId
799
+ * from the original TaskResult.metadata.taskId to correlate its lifecycle.
800
+ * The handle provides track() and waitForCompletion(); polling itself does
801
+ * not create new protocol activity records. Results retain seller tool shapes.
802
+ */
803
+ trackTask<T = unknown>(request: TrackTaskRequest): Promise<TrackedTask<T>>;
797
804
  /**
798
805
  * Execute any ADCP task by name with full type safety
799
806
  *
@@ -1254,6 +1254,16 @@ class AgentClient {
1254
1254
  getActiveTasks() {
1255
1255
  return this.client.getActiveTasks().map(import_request_proposals_guard.assertNativeRequestProposalsTask);
1256
1256
  }
1257
+ // ====== GENERIC TASK EXECUTION ======
1258
+ /**
1259
+ * Rebuild a polling handle for a persisted seller task. Reuse operationId
1260
+ * from the original TaskResult.metadata.taskId to correlate its lifecycle.
1261
+ * The handle provides track() and waitForCompletion(); polling itself does
1262
+ * not create new protocol activity records. Results retain seller tool shapes.
1263
+ */
1264
+ trackTask(request) {
1265
+ return this.client.trackTask(request);
1266
+ }
1257
1267
  async executeTask(taskName, params, inputHandler, options) {
1258
1268
  switch (taskName) {
1259
1269
  case "get_products":
@@ -1222,6 +1222,16 @@ class AgentClient {
1222
1222
  getActiveTasks() {
1223
1223
  return this.client.getActiveTasks().map(assertNativeRequestProposalsTask);
1224
1224
  }
1225
+ // ====== GENERIC TASK EXECUTION ======
1226
+ /**
1227
+ * Rebuild a polling handle for a persisted seller task. Reuse operationId
1228
+ * from the original TaskResult.metadata.taskId to correlate its lifecycle.
1229
+ * The handle provides track() and waitForCompletion(); polling itself does
1230
+ * not create new protocol activity records. Results retain seller tool shapes.
1231
+ */
1232
+ trackTask(request) {
1233
+ return this.client.trackTask(request);
1234
+ }
1225
1235
  async executeTask(taskName, params, inputHandler, options) {
1226
1236
  switch (taskName) {
1227
1237
  case "get_products":
@@ -118,6 +118,8 @@ export interface Activity {
118
118
  agent_id: string;
119
119
  context_id?: string;
120
120
  task_id?: string;
121
+ /** Seller's AdCP work handle; operation_id remains the runner correlation id. */
122
+ server_task_id?: string;
121
123
  task_type: string;
122
124
  status?: string;
123
125
  /**
@@ -118,6 +118,8 @@ export interface Activity {
118
118
  agent_id: string;
119
119
  context_id?: string;
120
120
  task_id?: string;
121
+ /** Seller's AdCP work handle; operation_id remains the runner correlation id. */
122
+ server_task_id?: string;
121
123
  task_type: string;
122
124
  status?: string;
123
125
  /**
@@ -403,7 +403,7 @@ class AsyncHandler {
403
403
  * Emit activity event
404
404
  */
405
405
  async emitActivity(activity) {
406
- await this.config.onActivity?.(activity);
406
+ await this.config.onActivity?.({ ...activity, server_task_id: activity.server_task_id ?? activity.task_id });
407
407
  }
408
408
  /**
409
409
  * Claim the webhook for processing. A failed dispatch rolls this claim
@@ -376,7 +376,7 @@ class AsyncHandler {
376
376
  * Emit activity event
377
377
  */
378
378
  async emitActivity(activity) {
379
- await this.config.onActivity?.(activity);
379
+ await this.config.onActivity?.({ ...activity, server_task_id: activity.server_task_id ?? activity.task_id });
380
380
  }
381
381
  /**
382
382
  * Claim the webhook for processing. A failed dispatch rolls this claim
@@ -121,6 +121,16 @@ export type WebhookUrlTemplate = string | {
121
121
  * Options for task execution
122
122
  */
123
123
  export interface TaskOptions {
124
+ /**
125
+ * Caller-supplied operation correlation id. Defaults to a generated UUID.
126
+ * Persist it with metadata.serverTaskId to resume tracking after a restart.
127
+ * Use a globally unique opaque id per dispatch (UUID recommended), including
128
+ * across tenants sharing persistence or webhook receivers. Reuse it for tracking,
129
+ * not resubmission; retry dispatches use a new id and the same idempotency_key.
130
+ * Accepts 1–255 letters, digits, underscores, periods, colons, or hyphens.
131
+ * Dot-only IDs and the delivery_route: prefix are reserved.
132
+ */
133
+ operationId?: string;
124
134
  /**
125
135
  * Skip inline completion status handlers for this call and its continuations.
126
136
  * Defaults to false. Independently delivered webhook handlers are unaffected.
@@ -202,6 +212,8 @@ export interface TaskOptions {
202
212
  export interface TaskState {
203
213
  /** Unique task identifier */
204
214
  taskId: string;
215
+ /** Seller work handle, distinct from the local operation id. */
216
+ serverTaskId?: string;
205
217
  /** Task name (tool name) */
206
218
  taskName: string;
207
219
  /**
@@ -247,6 +259,10 @@ export interface TaskState {
247
259
  export interface TaskInfo {
248
260
  /** Task ID */
249
261
  taskId: string;
262
+ /** Local operation id when observed through an SDK continuation or lifecycle event. */
263
+ operationId?: string;
264
+ /** Seller work handle when known. Existing taskId semantics are preserved. */
265
+ serverTaskId?: string;
250
266
  /** Current status */
251
267
  status: string;
252
268
  /** Task type/name */
@@ -292,6 +308,22 @@ export interface DirectPauseRecoveryRequest {
292
308
  recoveryKey: string;
293
309
  ownerScope: string;
294
310
  }
311
+ /** Persisted seller work to observe without submitting a new task. */
312
+ export interface TrackTaskRequest extends Pick<TaskOptions, 'operationId' | 'transport' | 'signal'> {
313
+ /** Seller's AdCP task_id (TaskResult.metadata.serverTaskId). */
314
+ taskId: string;
315
+ /** Original tool name, used to verify the seller's task identity. */
316
+ taskType: string;
317
+ /** Actual A2A transport Task.id, if known. Distinct from the AdCP taskId. */
318
+ a2aTaskId?: string;
319
+ /** Request cancellation of seller work on polling abort. Requires a2aTaskId; defaults to false. */
320
+ cancelOnAbort?: boolean;
321
+ }
322
+ /** Polling handle for persisted seller work. */
323
+ export interface TrackedTask<T = unknown> extends SubmittedContinuation<T> {
324
+ /** Stable runner operation id. Save this when the SDK generates it. */
325
+ operationId: string;
326
+ }
295
327
  /**
296
328
  * Continuation for submitted server tasks (server needs time).
297
329
  *
@@ -121,6 +121,16 @@ export type WebhookUrlTemplate = string | {
121
121
  * Options for task execution
122
122
  */
123
123
  export interface TaskOptions {
124
+ /**
125
+ * Caller-supplied operation correlation id. Defaults to a generated UUID.
126
+ * Persist it with metadata.serverTaskId to resume tracking after a restart.
127
+ * Use a globally unique opaque id per dispatch (UUID recommended), including
128
+ * across tenants sharing persistence or webhook receivers. Reuse it for tracking,
129
+ * not resubmission; retry dispatches use a new id and the same idempotency_key.
130
+ * Accepts 1–255 letters, digits, underscores, periods, colons, or hyphens.
131
+ * Dot-only IDs and the delivery_route: prefix are reserved.
132
+ */
133
+ operationId?: string;
124
134
  /**
125
135
  * Skip inline completion status handlers for this call and its continuations.
126
136
  * Defaults to false. Independently delivered webhook handlers are unaffected.
@@ -202,6 +212,8 @@ export interface TaskOptions {
202
212
  export interface TaskState {
203
213
  /** Unique task identifier */
204
214
  taskId: string;
215
+ /** Seller work handle, distinct from the local operation id. */
216
+ serverTaskId?: string;
205
217
  /** Task name (tool name) */
206
218
  taskName: string;
207
219
  /**
@@ -247,6 +259,10 @@ export interface TaskState {
247
259
  export interface TaskInfo {
248
260
  /** Task ID */
249
261
  taskId: string;
262
+ /** Local operation id when observed through an SDK continuation or lifecycle event. */
263
+ operationId?: string;
264
+ /** Seller work handle when known. Existing taskId semantics are preserved. */
265
+ serverTaskId?: string;
250
266
  /** Current status */
251
267
  status: string;
252
268
  /** Task type/name */
@@ -292,6 +308,22 @@ export interface DirectPauseRecoveryRequest {
292
308
  recoveryKey: string;
293
309
  ownerScope: string;
294
310
  }
311
+ /** Persisted seller work to observe without submitting a new task. */
312
+ export interface TrackTaskRequest extends Pick<TaskOptions, 'operationId' | 'transport' | 'signal'> {
313
+ /** Seller's AdCP task_id (TaskResult.metadata.serverTaskId). */
314
+ taskId: string;
315
+ /** Original tool name, used to verify the seller's task identity. */
316
+ taskType: string;
317
+ /** Actual A2A transport Task.id, if known. Distinct from the AdCP taskId. */
318
+ a2aTaskId?: string;
319
+ /** Request cancellation of seller work on polling abort. Requires a2aTaskId; defaults to false. */
320
+ cancelOnAbort?: boolean;
321
+ }
322
+ /** Polling handle for persisted seller work. */
323
+ export interface TrackedTask<T = unknown> extends SubmittedContinuation<T> {
324
+ /** Stable runner operation id. Save this when the SDK generates it. */
325
+ operationId: string;
326
+ }
295
327
  /**
296
328
  * Continuation for submitted server tasks (server needs time).
297
329
  *
@@ -6,7 +6,7 @@ import { type MutatingRequestInput } from '../utils/idempotency.mjs';
6
6
  import type { MCPWebhookPayload, TaskStatus } from '../types/core.generated.mjs';
7
7
  type A2ATask = Record<string, any>;
8
8
  type TaskStatusUpdateEvent = Record<string, any>;
9
- import type { InputHandler, Message, TaskOptions, TaskResult, ConversationConfig, TaskInfo, TaskState, WebhookUrlTemplate, DirectPauseRecoveryRequest } from './ConversationTypes.mjs';
9
+ import type { InputHandler, Message, TaskOptions, TaskResult, ConversationConfig, TaskInfo, TaskState, WebhookUrlTemplate, DirectPauseRecoveryRequest, TrackTaskRequest, TrackedTask } from './ConversationTypes.mjs';
10
10
  import type { AdcpTaskName, TaskRequestFor, TaskResponseTypeMap } from './AgentClient.mjs';
11
11
  import type { DeferredTaskStorage } from '../storage/interfaces.mjs';
12
12
  import type { Activity, AsyncHandlerConfig, WebhookMetadata } from './AsyncHandler.mjs';
@@ -638,6 +638,16 @@ export declare class SingleAgentClient {
638
638
  * version. Wire-shape adapters key off this method in subsequent stages.
639
639
  */
640
640
  getAdcpVersion(): string;
641
+ /**
642
+ * Observe a persisted seller task using the continuation polling path.
643
+ * Does not submit work or emit protocol_request/protocol_response activity
644
+ * for each poll. Terminal status_change activity carries operation_id and
645
+ * server_task_id. Results use the seller's original tool response shape.
646
+ * Persist the returned operationId if none was supplied. Polling handles
647
+ * are local to this client; matching identities can reattach to existing work.
648
+ * Local observation failures do not publish seller terminal lifecycle events.
649
+ */
650
+ trackTask<T = unknown>(request: TrackTaskRequest): Promise<TrackedTask<T>>;
641
651
  /** Recover the current generation of an opt-in direct mutation pause. */
642
652
  recoverDirectPauseContinuation<T>(request: DirectPauseRecoveryRequest): Promise<TaskResult<T>>;
643
653
  private recoverDurableSettlement;
@@ -6,7 +6,7 @@ import { type MutatingRequestInput } from '../utils/idempotency';
6
6
  import type { MCPWebhookPayload, TaskStatus } from '../types/core.generated';
7
7
  type A2ATask = Record<string, any>;
8
8
  type TaskStatusUpdateEvent = Record<string, any>;
9
- import type { InputHandler, Message, TaskOptions, TaskResult, ConversationConfig, TaskInfo, TaskState, WebhookUrlTemplate, DirectPauseRecoveryRequest } from './ConversationTypes';
9
+ import type { InputHandler, Message, TaskOptions, TaskResult, ConversationConfig, TaskInfo, TaskState, WebhookUrlTemplate, DirectPauseRecoveryRequest, TrackTaskRequest, TrackedTask } from './ConversationTypes';
10
10
  import type { AdcpTaskName, TaskRequestFor, TaskResponseTypeMap } from './AgentClient';
11
11
  import type { DeferredTaskStorage } from '../storage/interfaces';
12
12
  import type { Activity, AsyncHandlerConfig, WebhookMetadata } from './AsyncHandler';
@@ -638,6 +638,16 @@ export declare class SingleAgentClient {
638
638
  * version. Wire-shape adapters key off this method in subsequent stages.
639
639
  */
640
640
  getAdcpVersion(): string;
641
+ /**
642
+ * Observe a persisted seller task using the continuation polling path.
643
+ * Does not submit work or emit protocol_request/protocol_response activity
644
+ * for each poll. Terminal status_change activity carries operation_id and
645
+ * server_task_id. Results use the seller's original tool response shape.
646
+ * Persist the returned operationId if none was supplied. Polling handles
647
+ * are local to this client; matching identities can reattach to existing work.
648
+ * Local observation failures do not publish seller terminal lifecycle events.
649
+ */
650
+ trackTask<T = unknown>(request: TrackTaskRequest): Promise<TrackedTask<T>>;
641
651
  /** Recover the current generation of an opt-in direct mutation pause. */
642
652
  recoverDirectPauseContinuation<T>(request: DirectPauseRecoveryRequest): Promise<TaskResult<T>>;
643
653
  private recoverDurableSettlement;
@@ -992,7 +992,7 @@ class SingleAgentClient {
992
992
  const result = await this.listAccounts(
993
993
  { account: { account_id: accountId }, ...cursor && { pagination: { cursor } } },
994
994
  void 0,
995
- { ...options, [SKIP_ACCOUNT_REGISTRY_OBSERVATION]: true }
995
+ { ...(0, import_task_deadline.childTaskOptions)(options), [SKIP_ACCOUNT_REGISTRY_OBSERVATION]: true }
996
996
  );
997
997
  if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data))
998
998
  throw new Error("Account status reconciliation failed.");
@@ -1693,6 +1693,22 @@ class SingleAgentClient {
1693
1693
  getAdcpVersion() {
1694
1694
  return this.resolvedAdcpVersion;
1695
1695
  }
1696
+ /**
1697
+ * Observe a persisted seller task using the continuation polling path.
1698
+ * Does not submit work or emit protocol_request/protocol_response activity
1699
+ * for each poll. Terminal status_change activity carries operation_id and
1700
+ * server_task_id. Results use the seller's original tool response shape.
1701
+ * Persist the returned operationId if none was supplied. Polling handles
1702
+ * are local to this client; matching identities can reattach to existing work.
1703
+ * Local observation failures do not publish seller terminal lifecycle events.
1704
+ */
1705
+ async trackTask(request) {
1706
+ const snapshot = { ...request, transport: request.transport && { ...request.transport } };
1707
+ (0, import_task_deadline.getTaskOperationId)(snapshot);
1708
+ (0, import_abort2.throwIfAborted)(snapshot.signal);
1709
+ const agent = this.normalizedAgent.protocol === "a2a" ? await this.ensureCanonicalUrlResolved(snapshot) : await this.ensureEndpointDiscovered(snapshot);
1710
+ return this.executor.trackTask(agent, snapshot);
1711
+ }
1696
1712
  /** Poll through the same discovered/canonical protocol endpoint used for dispatch. @internal */
1697
1713
  async getTaskStatus(taskId, transport, signal, wireOptions) {
1698
1714
  const transportSnapshot = transport === void 0 ? void 0 : { ...transport };
@@ -1759,6 +1775,7 @@ class SingleAgentClient {
1759
1775
  operation_id: metadata.operation_id,
1760
1776
  agent_id: metadata.agent_id,
1761
1777
  task_id: metadata.task_id,
1778
+ server_task_id: metadata.task_id,
1762
1779
  task_type: metadata.task_type,
1763
1780
  status: metadata.status,
1764
1781
  payload: args.result,
@@ -2987,6 +3004,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2987
3004
  agent_id: metadata.agent_id,
2988
3005
  context_id: metadata.context_id,
2989
3006
  task_id: metadata.task_id,
3007
+ server_task_id: metadata.task_id,
2990
3008
  task_type: metadata.task_type,
2991
3009
  status: metadata.status,
2992
3010
  idempotency_key: metadata.idempotency_key,
@@ -3013,6 +3031,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
3013
3031
  agent_id: metadata.agent_id,
3014
3032
  context_id: metadata.context_id,
3015
3033
  task_id: metadata.task_id,
3034
+ server_task_id: metadata.task_id,
3016
3035
  task_type: metadata.task_type,
3017
3036
  status: metadata.status,
3018
3037
  payload: webhookResult,
@@ -3101,6 +3120,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
3101
3120
  agent_id: metadata.agent_id,
3102
3121
  context_id: metadata.context_id,
3103
3122
  task_id: metadata.task_id,
3123
+ server_task_id: metadata.task_id,
3104
3124
  task_type: metadata.task_type,
3105
3125
  status: metadata.status,
3106
3126
  idempotency_key: metadata.idempotency_key,
@@ -4806,8 +4826,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4806
4826
  if (cachedResult.success && cachedResult.status === "completed") {
4807
4827
  if (!skipCacheRead && cacheParams.if_wholesale_feed_version === void 0 && cacheParams.if_pricing_version === void 0 && cachedResult.data.unchanged === true) {
4808
4828
  return this.getProducts(params, inputHandler, {
4809
- ...options,
4810
- ...effectiveOptions,
4829
+ ...(0, import_task_deadline.childTaskOptions)({ ...options, ...effectiveOptions }),
4811
4830
  [SKIP_PRODUCT_CACHE]: true
4812
4831
  });
4813
4832
  }
@@ -5773,7 +5792,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
5773
5792
  ...cursor !== void 0 && { pagination: { cursor } }
5774
5793
  },
5775
5794
  void 0,
5776
- effectiveOptions
5795
+ (0, import_task_deadline.childTaskOptions)(effectiveOptions)
5777
5796
  );
5778
5797
  onTaskResult?.(result);
5779
5798
  if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data) || !Array.isArray(result.data.accounts)) {
@@ -5867,7 +5886,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
5867
5886
  ]
5868
5887
  },
5869
5888
  void 0,
5870
- effectiveOptions
5889
+ (0, import_task_deadline.childTaskOptions)(effectiveOptions)
5871
5890
  );
5872
5891
  onTaskResult?.(result);
5873
5892
  if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data) || !Array.isArray(result.data.accounts)) {
@@ -5939,7 +5958,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
5939
5958
  paymentTerms: hints.paymentTerms,
5940
5959
  billingEntity: hints.billingEntity
5941
5960
  },
5942
- effectiveOptions,
5961
+ (0, import_task_deadline.childTaskOptions)(effectiveOptions),
5943
5962
  onTaskResult
5944
5963
  );
5945
5964
  } catch (error) {
@@ -51,7 +51,7 @@ import {
51
51
  assertNativeRequestProposalsTask,
52
52
  guardNativeRequestProposalsCompletion
53
53
  } from "./request-proposals-guard.mjs";
54
- import { withTaskDeadline } from "./task-deadline.mjs";
54
+ import { childTaskOptions, getTaskOperationId, withTaskDeadline } from "./task-deadline.mjs";
55
55
  import { createMCPRequestHeaders } from "../auth/index.mjs";
56
56
  import { isAbortOrTimeoutError } from "../protocols/abort.mjs";
57
57
  import { getSignedRequestRejection } from "../protocols/signedRequestRejection.mjs";
@@ -1089,7 +1089,7 @@ class SingleAgentClient {
1089
1089
  const result = await this.listAccounts(
1090
1090
  { account: { account_id: accountId }, ...cursor && { pagination: { cursor } } },
1091
1091
  void 0,
1092
- { ...options, [SKIP_ACCOUNT_REGISTRY_OBSERVATION]: true }
1092
+ { ...childTaskOptions(options), [SKIP_ACCOUNT_REGISTRY_OBSERVATION]: true }
1093
1093
  );
1094
1094
  if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data))
1095
1095
  throw new Error("Account status reconciliation failed.");
@@ -1790,6 +1790,22 @@ class SingleAgentClient {
1790
1790
  getAdcpVersion() {
1791
1791
  return this.resolvedAdcpVersion;
1792
1792
  }
1793
+ /**
1794
+ * Observe a persisted seller task using the continuation polling path.
1795
+ * Does not submit work or emit protocol_request/protocol_response activity
1796
+ * for each poll. Terminal status_change activity carries operation_id and
1797
+ * server_task_id. Results use the seller's original tool response shape.
1798
+ * Persist the returned operationId if none was supplied. Polling handles
1799
+ * are local to this client; matching identities can reattach to existing work.
1800
+ * Local observation failures do not publish seller terminal lifecycle events.
1801
+ */
1802
+ async trackTask(request) {
1803
+ const snapshot = { ...request, transport: request.transport && { ...request.transport } };
1804
+ getTaskOperationId(snapshot);
1805
+ throwIfAborted(snapshot.signal);
1806
+ const agent = this.normalizedAgent.protocol === "a2a" ? await this.ensureCanonicalUrlResolved(snapshot) : await this.ensureEndpointDiscovered(snapshot);
1807
+ return this.executor.trackTask(agent, snapshot);
1808
+ }
1793
1809
  /** Poll through the same discovered/canonical protocol endpoint used for dispatch. @internal */
1794
1810
  async getTaskStatus(taskId, transport, signal, wireOptions) {
1795
1811
  const transportSnapshot = transport === void 0 ? void 0 : { ...transport };
@@ -1856,6 +1872,7 @@ class SingleAgentClient {
1856
1872
  operation_id: metadata.operation_id,
1857
1873
  agent_id: metadata.agent_id,
1858
1874
  task_id: metadata.task_id,
1875
+ server_task_id: metadata.task_id,
1859
1876
  task_type: metadata.task_type,
1860
1877
  status: metadata.status,
1861
1878
  payload: args.result,
@@ -3084,6 +3101,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
3084
3101
  agent_id: metadata.agent_id,
3085
3102
  context_id: metadata.context_id,
3086
3103
  task_id: metadata.task_id,
3104
+ server_task_id: metadata.task_id,
3087
3105
  task_type: metadata.task_type,
3088
3106
  status: metadata.status,
3089
3107
  idempotency_key: metadata.idempotency_key,
@@ -3110,6 +3128,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
3110
3128
  agent_id: metadata.agent_id,
3111
3129
  context_id: metadata.context_id,
3112
3130
  task_id: metadata.task_id,
3131
+ server_task_id: metadata.task_id,
3113
3132
  task_type: metadata.task_type,
3114
3133
  status: metadata.status,
3115
3134
  payload: webhookResult,
@@ -3198,6 +3217,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
3198
3217
  agent_id: metadata.agent_id,
3199
3218
  context_id: metadata.context_id,
3200
3219
  task_id: metadata.task_id,
3220
+ server_task_id: metadata.task_id,
3201
3221
  task_type: metadata.task_type,
3202
3222
  status: metadata.status,
3203
3223
  idempotency_key: metadata.idempotency_key,
@@ -4903,8 +4923,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4903
4923
  if (cachedResult.success && cachedResult.status === "completed") {
4904
4924
  if (!skipCacheRead && cacheParams.if_wholesale_feed_version === void 0 && cacheParams.if_pricing_version === void 0 && cachedResult.data.unchanged === true) {
4905
4925
  return this.getProducts(params, inputHandler, {
4906
- ...options,
4907
- ...effectiveOptions,
4926
+ ...childTaskOptions({ ...options, ...effectiveOptions }),
4908
4927
  [SKIP_PRODUCT_CACHE]: true
4909
4928
  });
4910
4929
  }
@@ -5870,7 +5889,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
5870
5889
  ...cursor !== void 0 && { pagination: { cursor } }
5871
5890
  },
5872
5891
  void 0,
5873
- effectiveOptions
5892
+ childTaskOptions(effectiveOptions)
5874
5893
  );
5875
5894
  onTaskResult?.(result);
5876
5895
  if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data) || !Array.isArray(result.data.accounts)) {
@@ -5964,7 +5983,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
5964
5983
  ]
5965
5984
  },
5966
5985
  void 0,
5967
- effectiveOptions
5986
+ childTaskOptions(effectiveOptions)
5968
5987
  );
5969
5988
  onTaskResult?.(result);
5970
5989
  if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data) || !Array.isArray(result.data.accounts)) {
@@ -6036,7 +6055,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
6036
6055
  paymentTerms: hints.paymentTerms,
6037
6056
  billingEntity: hints.billingEntity
6038
6057
  },
6039
- effectiveOptions,
6058
+ childTaskOptions(effectiveOptions),
6040
6059
  onTaskResult
6041
6060
  );
6042
6061
  } catch (error) {
@@ -2,7 +2,7 @@ import type { AgentConfig } from '../types/index.mjs';
2
2
  import type { DeferredTaskStorage } from '../storage/interfaces.mjs';
3
3
  import { type ValidationHookConfig } from '../validation/client-hooks.mjs';
4
4
  import type { AdcpCapabilities } from '../utils/capabilities.mjs';
5
- import type { Message, InputHandler, TaskOptions, TaskResult, TaskState, TaskStatus, TaskInfo, DirectPauseRecoveryRequest, WebhookUrlTemplate } from './ConversationTypes.mjs';
5
+ import type { Message, InputHandler, TaskOptions, TaskResult, TaskState, TaskStatus, TaskInfo, DirectPauseRecoveryRequest, TrackTaskRequest, TrackedTask, WebhookUrlTemplate } from './ConversationTypes.mjs';
6
6
  import type { Activity } from './AsyncHandler.mjs';
7
7
  import { GovernanceMiddleware } from './GovernanceMiddleware.mjs';
8
8
  import type { GovernanceConfig } from './GovernanceTypes.mjs';
@@ -279,6 +279,8 @@ export declare class TaskExecutor {
279
279
  * Set up submitted task with webhook
280
280
  */
281
281
  private setupSubmittedTask;
282
+ /** Rebuild the polling continuation for seller work persisted by the caller. */
283
+ trackTask<T = unknown>(agent: AgentConfig, request: TrackTaskRequest): TrackedTask<T>;
282
284
  /** Build polling closures around one authoritative seller work handle. */
283
285
  private createSubmittedContinuation;
284
286
  /**
@@ -2,7 +2,7 @@ import type { AgentConfig } from '../types';
2
2
  import type { DeferredTaskStorage } from '../storage/interfaces';
3
3
  import { type ValidationHookConfig } from '../validation/client-hooks';
4
4
  import type { AdcpCapabilities } from '../utils/capabilities';
5
- import type { Message, InputHandler, TaskOptions, TaskResult, TaskState, TaskStatus, TaskInfo, DirectPauseRecoveryRequest, WebhookUrlTemplate } from './ConversationTypes';
5
+ import type { Message, InputHandler, TaskOptions, TaskResult, TaskState, TaskStatus, TaskInfo, DirectPauseRecoveryRequest, TrackTaskRequest, TrackedTask, WebhookUrlTemplate } from './ConversationTypes';
6
6
  import type { Activity } from './AsyncHandler';
7
7
  import { GovernanceMiddleware } from './GovernanceMiddleware';
8
8
  import type { GovernanceConfig } from './GovernanceTypes';
@@ -279,6 +279,8 @@ export declare class TaskExecutor {
279
279
  * Set up submitted task with webhook
280
280
  */
281
281
  private setupSubmittedTask;
282
+ /** Rebuild the polling continuation for seller work persisted by the caller. */
283
+ trackTask<T = unknown>(agent: AgentConfig, request: TrackTaskRequest): TrackedTask<T>;
282
284
  /** Build polling closures around one authoritative seller work handle. */
283
285
  private createSubmittedContinuation;
284
286
  /**