@adcp/sdk 14.0.0-beta.5 → 14.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/AgentClient.js +26 -10
- package/dist/lib/core/AgentClient.js.map +1 -1
- package/dist/lib/core/AgentClient.mjs +26 -10
- package/dist/lib/core/AgentClient.mjs.map +1 -1
- package/dist/lib/core/AsyncHandler.d.mts +4 -2
- package/dist/lib/core/AsyncHandler.d.ts +4 -2
- package/dist/lib/core/AsyncHandler.d.ts.map +1 -1
- package/dist/lib/core/AsyncHandler.js +15 -1
- package/dist/lib/core/AsyncHandler.js.map +1 -1
- package/dist/lib/core/AsyncHandler.mjs +15 -1
- package/dist/lib/core/AsyncHandler.mjs.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.mts +3 -1
- package/dist/lib/core/SingleAgentClient.d.ts +3 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +158 -39
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +167 -40
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.d.mts +57 -2
- package/dist/lib/core/TaskExecutor.d.ts +57 -2
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +382 -44
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +382 -45
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/core/request-proposals-guard.d.mts +11 -0
- package/dist/lib/core/request-proposals-guard.d.ts +12 -0
- package/dist/lib/core/request-proposals-guard.d.ts.map +1 -0
- package/dist/lib/core/request-proposals-guard.js +65 -0
- package/dist/lib/core/request-proposals-guard.js.map +1 -0
- package/dist/lib/core/request-proposals-guard.mjs +39 -0
- package/dist/lib/core/request-proposals-guard.mjs.map +1 -0
- package/dist/lib/core/webhook-registration.d.mts +5 -0
- package/dist/lib/core/webhook-registration.d.ts +5 -0
- package/dist/lib/core/webhook-registration.d.ts.map +1 -1
- package/dist/lib/core/webhook-registration.js +13 -0
- package/dist/lib/core/webhook-registration.js.map +1 -1
- package/dist/lib/core/webhook-registration.mjs +13 -0
- package/dist/lib/core/webhook-registration.mjs.map +1 -1
- package/dist/lib/media-buy/compatibility.d.mts +45 -10
- package/dist/lib/media-buy/compatibility.d.ts +45 -10
- package/dist/lib/media-buy/compatibility.d.ts.map +1 -1
- package/dist/lib/media-buy/compatibility.js +295 -113
- package/dist/lib/media-buy/compatibility.js.map +1 -1
- package/dist/lib/media-buy/compatibility.mjs +295 -113
- package/dist/lib/media-buy/compatibility.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/core.generated.d.mts +334 -85
- package/dist/lib/types/core.generated.d.ts +334 -85
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js.map +1 -1
- package/dist/lib/types/decline-proposals.d.ts +0 -5
- package/dist/lib/types/index.d.mts +2 -0
- package/dist/lib/types/index.d.ts +2 -0
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/request-proposals.d.ts +254 -36
- package/dist/lib/types/schemas.generated.d.ts +3123 -835
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +192 -85
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +192 -85
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/tools.generated.d.mts +1 -121
- package/dist/lib/types/tools.generated.d.ts +1 -121
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- 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.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/guides/MEDIA-BUY-3.2-COMPATIBILITY.md +28 -14
- package/docs/llms.txt +1 -1
- package/package.json +1 -1
|
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var TaskExecutor_exports = {};
|
|
20
20
|
__export(TaskExecutor_exports, {
|
|
21
|
+
AfterProtocolDispatchHookError: () => AfterProtocolDispatchHookError,
|
|
21
22
|
BeforeProtocolDispatchHookError: () => BeforeProtocolDispatchHookError,
|
|
22
23
|
DeferredTaskError: () => DeferredTaskError,
|
|
23
24
|
InputRequiredError: () => InputRequiredError,
|
|
@@ -80,6 +81,14 @@ class BeforeProtocolDispatchHookError extends Error {
|
|
|
80
81
|
}
|
|
81
82
|
original;
|
|
82
83
|
}
|
|
84
|
+
class AfterProtocolDispatchHookError extends Error {
|
|
85
|
+
constructor(original) {
|
|
86
|
+
super("An SDK post-dispatch settlement hook failed.", { cause: original });
|
|
87
|
+
this.original = original;
|
|
88
|
+
this.name = "AfterProtocolDispatchHookError";
|
|
89
|
+
}
|
|
90
|
+
original;
|
|
91
|
+
}
|
|
83
92
|
const GOVERNED_CREDENTIAL_SCAN_MAX_NODES = 1e4;
|
|
84
93
|
const GOVERNED_CREDENTIAL_SCAN_MAX_DEPTH = 64;
|
|
85
94
|
const GOVERNED_CALLBACK_FIELDS = /* @__PURE__ */ new Set(["push_notification_config", "reporting_webhook", "artifact_webhook"]);
|
|
@@ -245,6 +254,8 @@ function resolveIdempotencyKey(taskName, params, serverVersion) {
|
|
|
245
254
|
return void 0;
|
|
246
255
|
}
|
|
247
256
|
const COMPACTED_TASK_STATE_LIMIT = 1e4;
|
|
257
|
+
const DEFAULT_EXTERNAL_TASK_SETTLEMENT_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
258
|
+
const MAX_TIMER_DELAY_MS = 2147483647;
|
|
248
259
|
const TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set([
|
|
249
260
|
"completed",
|
|
250
261
|
"failed",
|
|
@@ -253,9 +264,14 @@ const TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set([
|
|
|
253
264
|
"governance-denied",
|
|
254
265
|
"aborted"
|
|
255
266
|
]);
|
|
267
|
+
const MAX_PENDING_EXTERNAL_TASK_OBSERVATIONS = 8;
|
|
268
|
+
const MAX_RETAINED_EXTERNAL_TASK_ERROR_CHARS = 1024;
|
|
256
269
|
class TaskExecutor {
|
|
257
270
|
constructor(config = {}) {
|
|
258
271
|
this.config = config;
|
|
272
|
+
if (config.externalTaskSettlementRetentionMs !== void 0 && (!Number.isSafeInteger(config.externalTaskSettlementRetentionMs) || config.externalTaskSettlementRetentionMs < 1)) {
|
|
273
|
+
throw new import_errors.ConfigurationError("externalTaskSettlementRetentionMs must be a positive safe integer.");
|
|
274
|
+
}
|
|
259
275
|
this.responseParser = new import_ProtocolResponseParser.ProtocolResponseParser();
|
|
260
276
|
if (config.enableConversationStorage) {
|
|
261
277
|
this.conversationStorage = /* @__PURE__ */ new Map();
|
|
@@ -280,6 +296,14 @@ class TaskExecutor {
|
|
|
280
296
|
}
|
|
281
297
|
}
|
|
282
298
|
config;
|
|
299
|
+
deferredTerminalPublicationTaskIds = /* @__PURE__ */ new Set();
|
|
300
|
+
settlementCapacityReservations = /* @__PURE__ */ new Set();
|
|
301
|
+
closedExternalTaskSettlementTaskIds = /* @__PURE__ */ new Set();
|
|
302
|
+
externalTaskSettlementHandlers = /* @__PURE__ */ new Map();
|
|
303
|
+
externalTaskSettlementInFlight = /* @__PURE__ */ new Map();
|
|
304
|
+
settledExternalTaskObservationKeys = /* @__PURE__ */ new Map();
|
|
305
|
+
externalTaskSettlementExpiry = /* @__PURE__ */ new Map();
|
|
306
|
+
pendingExternalTaskObservations = /* @__PURE__ */ new Map();
|
|
283
307
|
responseParser;
|
|
284
308
|
activeTasks = /* @__PURE__ */ new Map();
|
|
285
309
|
compactedTaskIds = /* @__PURE__ */ new Map();
|
|
@@ -305,9 +329,43 @@ class TaskExecutor {
|
|
|
305
329
|
*
|
|
306
330
|
* @internal
|
|
307
331
|
*/
|
|
308
|
-
observeExternalTaskStatus(taskId, status, result) {
|
|
309
|
-
if (!["completed", "failed", "rejected", "canceled"].includes(status))
|
|
332
|
+
async observeExternalTaskStatus(taskId, status, result, identity = {}) {
|
|
333
|
+
if (!["completed", "failed", "rejected", "canceled", "governance-denied", "aborted"].includes(status)) {
|
|
334
|
+
return { settled: false, result };
|
|
335
|
+
}
|
|
336
|
+
const observation = { status, result, ...identity };
|
|
337
|
+
const observationKey = this.externalTaskObservationKey(observation);
|
|
338
|
+
if (this.closedExternalTaskSettlementTaskIds.has(taskId)) {
|
|
339
|
+
const accepted = this.settledExternalTaskObservationKeys.get(taskId);
|
|
340
|
+
if (accepted?.key === observationKey) {
|
|
341
|
+
return {
|
|
342
|
+
settled: true,
|
|
343
|
+
duplicate: true,
|
|
344
|
+
status: accepted.status,
|
|
345
|
+
...accepted.error !== void 0 && { error: accepted.error }
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
throw new Error("This task already completed durable settlement; the pushed result was not accepted.");
|
|
349
|
+
}
|
|
350
|
+
if (this.deferredTerminalPublicationTaskIds.has(taskId)) {
|
|
351
|
+
const handler = this.externalTaskSettlementHandlers.get(taskId);
|
|
352
|
+
if (handler) return this.settleExternalTaskStatus(taskId, handler, observation);
|
|
353
|
+
return new Promise((resolve, reject) => {
|
|
354
|
+
const pending = this.pendingExternalTaskObservations.get(taskId) ?? [];
|
|
355
|
+
if (pending.length >= MAX_PENDING_EXTERNAL_TASK_OBSERVATIONS) {
|
|
356
|
+
reject(new Error("Too many terminal push notifications are awaiting durable task settlement."));
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
pending.push({ observation, resolve, reject });
|
|
360
|
+
this.pendingExternalTaskObservations.set(taskId, pending);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
310
363
|
this.updateTaskStatus(taskId, status, result);
|
|
364
|
+
return { settled: false, result };
|
|
365
|
+
}
|
|
366
|
+
/** Whether this process can safely settle or reject a durable callback for the operation. */
|
|
367
|
+
hasExternalTaskSettlementRoute(taskId) {
|
|
368
|
+
return this.deferredTerminalPublicationTaskIds.has(taskId) || this.closedExternalTaskSettlementTaskIds.has(taskId) || this.externalTaskSettlementHandlers.has(taskId);
|
|
311
369
|
}
|
|
312
370
|
/**
|
|
313
371
|
* Run the configured pre-send schema check against the user-facing request
|
|
@@ -404,6 +462,7 @@ class TaskExecutor {
|
|
|
404
462
|
}
|
|
405
463
|
async executeTaskWithinDeadline(agent, taskName, params, inputHandler, options = {}, serverVersion, targetCapabilities, beforeProtocolDispatch) {
|
|
406
464
|
if (serverVersion) this.lastKnownServerVersion = serverVersion;
|
|
465
|
+
params = structuredClone(params);
|
|
407
466
|
const taskId = (0, import_task_deadline.getTaskOperationId)(options) ?? (0, import_crypto.randomUUID)();
|
|
408
467
|
const startTime = Date.now();
|
|
409
468
|
const workingTimeout = this.config.workingTimeout || 12e4;
|
|
@@ -426,9 +485,14 @@ class TaskExecutor {
|
|
|
426
485
|
idempotencyKey
|
|
427
486
|
};
|
|
428
487
|
this.activeTasks.set(taskId, taskState);
|
|
488
|
+
let dispatchBoundaryOwnsTerminalState = false;
|
|
429
489
|
const taskAbortListener = options.signal ? () => {
|
|
430
490
|
const currentStatus = this.activeTasks.get(taskId)?.status;
|
|
431
491
|
if (currentStatus && !TERMINAL_TASK_STATUSES.has(currentStatus)) {
|
|
492
|
+
if (dispatchBoundaryOwnsTerminalState) {
|
|
493
|
+
this.compactAbandonedObserverTaskState(taskId);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
432
496
|
const reason = options.signal?.reason;
|
|
433
497
|
this.updateTaskStatus(
|
|
434
498
|
taskId,
|
|
@@ -455,6 +519,9 @@ class TaskExecutor {
|
|
|
455
519
|
let governanceResult;
|
|
456
520
|
let effectiveParams = params;
|
|
457
521
|
let governanceAdjusted = false;
|
|
522
|
+
let dispatchCommitted = false;
|
|
523
|
+
let dispatchSettlement;
|
|
524
|
+
let dispatchSettlementStarted = false;
|
|
458
525
|
try {
|
|
459
526
|
await this.config.onActivity?.({
|
|
460
527
|
type: "protocol_request",
|
|
@@ -513,14 +580,15 @@ class TaskExecutor {
|
|
|
513
580
|
effectiveParams = adjustedParams;
|
|
514
581
|
}
|
|
515
582
|
}
|
|
583
|
+
const dispatchParams = structuredClone(effectiveParams);
|
|
516
584
|
const initialMessage = {
|
|
517
585
|
id: (0, import_crypto.randomUUID)(),
|
|
518
586
|
role: "user",
|
|
519
|
-
content: { tool: taskName, params:
|
|
587
|
+
content: { tool: taskName, params: dispatchParams },
|
|
520
588
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
521
589
|
metadata: { toolName: taskName, type: "request" }
|
|
522
590
|
};
|
|
523
|
-
const preparedCall = (0, import_protocols.prepareProtocolToolCall)(agent,
|
|
591
|
+
const preparedCall = (0, import_protocols.prepareProtocolToolCall)(agent, dispatchParams, {
|
|
524
592
|
toolName: taskName,
|
|
525
593
|
webhookUrl,
|
|
526
594
|
webhookSecret: this.config.webhookSecret,
|
|
@@ -529,6 +597,7 @@ class TaskExecutor {
|
|
|
529
597
|
wireAdcpVersion: this.config.wireAdcpVersion,
|
|
530
598
|
versionEnvelope: this.config.versionEnvelope
|
|
531
599
|
});
|
|
600
|
+
let webhookRegistrationPersisted = false;
|
|
532
601
|
if (webhookUrl && this.config.onWebhookRegistration) {
|
|
533
602
|
const registration = webhookRegistrationFromPreparedCall(agent, preparedCall);
|
|
534
603
|
if (registration) {
|
|
@@ -538,16 +607,35 @@ class TaskExecutor {
|
|
|
538
607
|
operationId: taskId,
|
|
539
608
|
...registration
|
|
540
609
|
});
|
|
610
|
+
webhookRegistrationPersisted = true;
|
|
541
611
|
}
|
|
542
612
|
}
|
|
543
613
|
(0, import_abort.throwIfAborted)(options.signal);
|
|
544
|
-
let dispatchCommitted = false;
|
|
545
614
|
if (beforeProtocolDispatch) {
|
|
546
615
|
let decision;
|
|
616
|
+
dispatchBoundaryOwnsTerminalState = true;
|
|
547
617
|
try {
|
|
548
|
-
|
|
618
|
+
if (this.deferredTerminalPublicationTaskIds.size + this.settlementCapacityReservations.size >= COMPACTED_TASK_STATE_LIMIT) {
|
|
619
|
+
throw new Error("The durable task-settlement capacity is exhausted; no mutation claim was attempted.");
|
|
620
|
+
}
|
|
621
|
+
this.settlementCapacityReservations.add(taskId);
|
|
622
|
+
if (webhookRegistrationPersisted) {
|
|
623
|
+
await this.config.onDurableSettlementRequired?.(taskId);
|
|
624
|
+
(0, import_abort.throwIfAborted)(options.signal);
|
|
625
|
+
}
|
|
626
|
+
decision = await beforeProtocolDispatch(dispatchParams, {
|
|
627
|
+
governanceAdjusted,
|
|
628
|
+
publishSettledTaskStatus: (status, data, error) => this.publishSettledTaskStatus(taskId, status, data, error),
|
|
629
|
+
registerExternalTaskSettlement: (handler) => this.registerExternalTaskSettlement(taskId, handler)
|
|
630
|
+
});
|
|
631
|
+
if (decision.action === "dispatch_committed") {
|
|
632
|
+
this.deferredTerminalPublicationTaskIds.add(taskId);
|
|
633
|
+
this.retainExternalTaskSettlementState(taskId);
|
|
634
|
+
}
|
|
549
635
|
} catch (error) {
|
|
550
636
|
throw new BeforeProtocolDispatchHookError(error);
|
|
637
|
+
} finally {
|
|
638
|
+
this.settlementCapacityReservations.delete(taskId);
|
|
551
639
|
}
|
|
552
640
|
if (decision.action === "return") {
|
|
553
641
|
const earlyResult = decision.result;
|
|
@@ -557,7 +645,10 @@ class TaskExecutor {
|
|
|
557
645
|
return (0, import_match.attachMatch)(earlyResult);
|
|
558
646
|
}
|
|
559
647
|
dispatchCommitted = true;
|
|
648
|
+
dispatchSettlement = decision;
|
|
560
649
|
}
|
|
650
|
+
(0, import_abort.throwIfAborted)(options.signal);
|
|
651
|
+
const postDispatchOptions = dispatchCommitted ? { ...options, signal: void 0 } : options;
|
|
561
652
|
const callOptions = {
|
|
562
653
|
debugLogs,
|
|
563
654
|
webhookUrl,
|
|
@@ -568,12 +659,9 @@ class TaskExecutor {
|
|
|
568
659
|
...this.config.wireAdcpVersion !== void 0 && { wireAdcpVersion: this.config.wireAdcpVersion },
|
|
569
660
|
...this.config.versionEnvelope !== void 0 && { versionEnvelope: this.config.versionEnvelope },
|
|
570
661
|
transport: options.transport ?? this.config.transport,
|
|
571
|
-
// Once a
|
|
572
|
-
//
|
|
573
|
-
|
|
574
|
-
// still rejects promptly and post-call handling marks the outcome
|
|
575
|
-
// ambiguous for reconciliation.
|
|
576
|
-
signal: dispatchCommitted ? void 0 : options.signal,
|
|
662
|
+
// Once dispatch begins for a live committed claim, post-call handling
|
|
663
|
+
// owns durable settlement even if the caller's deadline fires later.
|
|
664
|
+
signal: postDispatchOptions.signal,
|
|
577
665
|
onTransportActivity: this.config.onTransportActivity,
|
|
578
666
|
transportActivityContext: {
|
|
579
667
|
operationId: taskId,
|
|
@@ -583,10 +671,10 @@ class TaskExecutor {
|
|
|
583
671
|
}
|
|
584
672
|
};
|
|
585
673
|
const response = await (0, import_prepared_call_context.withPreparedProtocolToolCall)(
|
|
586
|
-
{ agent, toolName: taskName, args:
|
|
587
|
-
() => import_protocols.ProtocolClient.callTool(agent, taskName,
|
|
674
|
+
{ agent, toolName: taskName, args: dispatchParams, preparedCall },
|
|
675
|
+
() => import_protocols.ProtocolClient.callTool(agent, taskName, dispatchParams, callOptions)
|
|
588
676
|
);
|
|
589
|
-
(0, import_abort.throwIfAborted)(
|
|
677
|
+
(0, import_abort.throwIfAborted)(postDispatchOptions.signal);
|
|
590
678
|
const respStatus = this.responseParser.getStatus(response);
|
|
591
679
|
await this.config.onActivity?.({
|
|
592
680
|
type: "protocol_response",
|
|
@@ -599,7 +687,7 @@ class TaskExecutor {
|
|
|
599
687
|
payload: response,
|
|
600
688
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
601
689
|
});
|
|
602
|
-
(0, import_abort.throwIfAborted)(
|
|
690
|
+
(0, import_abort.throwIfAborted)(postDispatchOptions.signal);
|
|
603
691
|
const responseMessage = {
|
|
604
692
|
id: (0, import_crypto.randomUUID)(),
|
|
605
693
|
role: "agent",
|
|
@@ -608,22 +696,33 @@ class TaskExecutor {
|
|
|
608
696
|
metadata: { toolName: taskName, type: "response" }
|
|
609
697
|
};
|
|
610
698
|
const messages = [initialMessage, responseMessage];
|
|
611
|
-
|
|
699
|
+
let result = await this.handleAsyncResponse(
|
|
612
700
|
agent,
|
|
613
701
|
taskId,
|
|
614
702
|
taskName,
|
|
615
|
-
|
|
703
|
+
dispatchParams,
|
|
616
704
|
response,
|
|
617
705
|
messages,
|
|
618
706
|
inputHandler,
|
|
619
|
-
|
|
707
|
+
postDispatchOptions,
|
|
620
708
|
debugLogs,
|
|
621
|
-
startTime
|
|
709
|
+
startTime,
|
|
710
|
+
dispatchCommitted
|
|
622
711
|
);
|
|
623
|
-
(0, import_abort.throwIfAborted)(
|
|
712
|
+
(0, import_abort.throwIfAborted)(postDispatchOptions.signal);
|
|
624
713
|
if (governanceResult) {
|
|
625
714
|
result.governance = governanceResult;
|
|
626
715
|
}
|
|
716
|
+
if (dispatchSettlement?.onResult) {
|
|
717
|
+
dispatchSettlementStarted = true;
|
|
718
|
+
try {
|
|
719
|
+
result = await dispatchSettlement.onResult((0, import_match.attachMatch)(result));
|
|
720
|
+
} catch (error) {
|
|
721
|
+
this.closeExternalTaskSettlement(taskId, error);
|
|
722
|
+
this.updateTaskStatus(taskId, "failed", void 0, error instanceof Error ? error.message : String(error));
|
|
723
|
+
throw new AfterProtocolDispatchHookError(error);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
627
726
|
if (governanceCheckId && this.governanceMiddleware) {
|
|
628
727
|
const govCtx = governanceResult?.governanceContext;
|
|
629
728
|
if (result.status === "completed" && govCtx) {
|
|
@@ -643,10 +742,10 @@ class TaskExecutor {
|
|
|
643
742
|
void 0,
|
|
644
743
|
debugLogs,
|
|
645
744
|
govCtx,
|
|
646
|
-
|
|
745
|
+
postDispatchOptions.signal,
|
|
647
746
|
outcomeIdempotencyKey
|
|
648
747
|
);
|
|
649
|
-
(0, import_abort.throwIfAborted)(
|
|
748
|
+
(0, import_abort.throwIfAborted)(postDispatchOptions.signal);
|
|
650
749
|
if (!result.governanceOutcome) {
|
|
651
750
|
result.governanceOutcomeError = "Outcome reporting to governance agent failed";
|
|
652
751
|
}
|
|
@@ -664,10 +763,10 @@ class TaskExecutor {
|
|
|
664
763
|
{ message: result.error },
|
|
665
764
|
debugLogs,
|
|
666
765
|
govCtx,
|
|
667
|
-
|
|
766
|
+
postDispatchOptions.signal,
|
|
668
767
|
outcomeIdempotencyKey
|
|
669
768
|
);
|
|
670
|
-
(0, import_abort.throwIfAborted)(
|
|
769
|
+
(0, import_abort.throwIfAborted)(postDispatchOptions.signal);
|
|
671
770
|
if (!result.governanceOutcome) {
|
|
672
771
|
result.governanceOutcomeError = "Outcome reporting to governance agent failed";
|
|
673
772
|
}
|
|
@@ -675,6 +774,12 @@ class TaskExecutor {
|
|
|
675
774
|
result.governance = { ...result.governance ?? {}, checkId: governanceCheckId };
|
|
676
775
|
}
|
|
677
776
|
}
|
|
777
|
+
if (dispatchCommitted) {
|
|
778
|
+
result = this.attachSettledContinuationTaskStatus(taskId, result);
|
|
779
|
+
if (TERMINAL_TASK_STATUSES.has(result.status)) {
|
|
780
|
+
this.publishSettledTaskStatus(taskId, result.status, result.data, result.error);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
678
783
|
if (["completed", "failed", "rejected", "canceled", "governance-denied", "aborted"].includes(result.status) && this.activeTasks.get(taskId)?.status !== result.status) {
|
|
679
784
|
this.updateTaskStatus(taskId, result.status, result.data, result.error);
|
|
680
785
|
}
|
|
@@ -684,6 +789,22 @@ class TaskExecutor {
|
|
|
684
789
|
this.updateTaskStatus(taskId, "failed", void 0, error.message);
|
|
685
790
|
throw error;
|
|
686
791
|
}
|
|
792
|
+
if (error instanceof AfterProtocolDispatchHookError) throw error;
|
|
793
|
+
if (dispatchCommitted && dispatchSettlement?.onError && !dispatchSettlementStarted) {
|
|
794
|
+
try {
|
|
795
|
+
await dispatchSettlement.onError(error);
|
|
796
|
+
} catch (settlementError) {
|
|
797
|
+
this.closeExternalTaskSettlement(taskId, settlementError);
|
|
798
|
+
this.updateTaskStatus(
|
|
799
|
+
taskId,
|
|
800
|
+
"failed",
|
|
801
|
+
void 0,
|
|
802
|
+
settlementError instanceof Error ? settlementError.message : String(settlementError)
|
|
803
|
+
);
|
|
804
|
+
throw new AfterProtocolDispatchHookError(settlementError);
|
|
805
|
+
}
|
|
806
|
+
this.closeExternalTaskSettlement(taskId, error);
|
|
807
|
+
}
|
|
687
808
|
if ((0, import_abort.isAbortOrTimeoutError)(error)) {
|
|
688
809
|
if (idempotencyKey && error && typeof error === "object") {
|
|
689
810
|
error.idempotency_key = idempotencyKey;
|
|
@@ -734,12 +855,12 @@ class TaskExecutor {
|
|
|
734
855
|
debug_logs: debugLogs
|
|
735
856
|
};
|
|
736
857
|
}
|
|
737
|
-
async handleAsyncResponse(agent, taskId, taskName, params, response, messages, inputHandler, options = {}, debugLogs = [], startTime = Date.now()) {
|
|
858
|
+
async handleAsyncResponse(agent, taskId, taskName, params, response, messages, inputHandler, options = {}, debugLogs = [], startTime = Date.now(), deferTerminalTaskStatus = false) {
|
|
738
859
|
const status = this.responseParser.getStatus(response);
|
|
739
860
|
switch (status) {
|
|
740
861
|
case import_ProtocolResponseParser.ADCP_STATUS.COMPLETED:
|
|
741
862
|
const completedData = this.extractResponseData(response, debugLogs, taskName);
|
|
742
|
-
this.updateTaskStatus(taskId, "completed", completedData);
|
|
863
|
+
if (!deferTerminalTaskStatus) this.updateTaskStatus(taskId, "completed", completedData);
|
|
743
864
|
const operationSuccess = this.isOperationSuccess(completedData, taskName);
|
|
744
865
|
const validationResult = this.validateResponseSchema(completedData, taskName, debugLogs);
|
|
745
866
|
const finalSuccess = operationSuccess && validationResult.valid;
|
|
@@ -795,7 +916,17 @@ class TaskExecutor {
|
|
|
795
916
|
startTime
|
|
796
917
|
);
|
|
797
918
|
case import_ProtocolResponseParser.ADCP_STATUS.SUBMITTED:
|
|
798
|
-
return this.setupSubmittedTask(
|
|
919
|
+
return this.setupSubmittedTask(
|
|
920
|
+
agent,
|
|
921
|
+
taskId,
|
|
922
|
+
taskName,
|
|
923
|
+
response,
|
|
924
|
+
messages,
|
|
925
|
+
options,
|
|
926
|
+
debugLogs,
|
|
927
|
+
startTime,
|
|
928
|
+
deferTerminalTaskStatus
|
|
929
|
+
);
|
|
799
930
|
case import_ProtocolResponseParser.ADCP_STATUS.INPUT_REQUIRED:
|
|
800
931
|
return this.handleInputRequired(
|
|
801
932
|
agent,
|
|
@@ -807,7 +938,8 @@ class TaskExecutor {
|
|
|
807
938
|
inputHandler,
|
|
808
939
|
options,
|
|
809
940
|
debugLogs,
|
|
810
|
-
startTime
|
|
941
|
+
startTime,
|
|
942
|
+
deferTerminalTaskStatus
|
|
811
943
|
);
|
|
812
944
|
case import_ProtocolResponseParser.ADCP_STATUS.FAILED:
|
|
813
945
|
case import_ProtocolResponseParser.ADCP_STATUS.REJECTED:
|
|
@@ -1009,7 +1141,7 @@ class TaskExecutor {
|
|
|
1009
1141
|
/**
|
|
1010
1142
|
* Set up submitted task with webhook
|
|
1011
1143
|
*/
|
|
1012
|
-
async setupSubmittedTask(agent, taskId, taskName, response, messages, options = {}, debugLogs = [], startTime = Date.now()) {
|
|
1144
|
+
async setupSubmittedTask(agent, taskId, taskName, response, messages, options = {}, debugLogs = [], startTime = Date.now(), deferTerminalTaskStatus = false) {
|
|
1013
1145
|
const partialData = this.extractResponseData(response, debugLogs, taskName);
|
|
1014
1146
|
let webhookUrl = response.webhookUrl;
|
|
1015
1147
|
if (!webhookUrl && this.config.webhookManager) {
|
|
@@ -1033,14 +1165,16 @@ class TaskExecutor {
|
|
|
1033
1165
|
webhookUrl,
|
|
1034
1166
|
track: async (transport) => {
|
|
1035
1167
|
const task = await this.getTaskStatus(agent, serverTaskId, transport ?? pollingTransport);
|
|
1036
|
-
if (["completed", "failed", "rejected", "canceled"].includes(task.status)) {
|
|
1168
|
+
if (!deferTerminalTaskStatus && ["completed", "failed", "rejected", "canceled"].includes(task.status)) {
|
|
1037
1169
|
this.updateTaskStatus(taskId, task.status, task.result, task.error);
|
|
1038
1170
|
}
|
|
1039
1171
|
return task;
|
|
1040
1172
|
},
|
|
1041
1173
|
waitForCompletion: async (pollInterval = 6e4, signal) => {
|
|
1042
1174
|
const completed = await this.pollTaskCompletion(agent, serverTaskId, pollInterval, pollingTransport, signal);
|
|
1043
|
-
|
|
1175
|
+
if (!deferTerminalTaskStatus || !TERMINAL_TASK_STATUSES.has(completed.status)) {
|
|
1176
|
+
this.updateTaskStatus(taskId, completed.status, completed.data, completed.error);
|
|
1177
|
+
}
|
|
1044
1178
|
return completed;
|
|
1045
1179
|
}
|
|
1046
1180
|
};
|
|
@@ -1064,6 +1198,193 @@ class TaskExecutor {
|
|
|
1064
1198
|
debug_logs: debugLogs
|
|
1065
1199
|
};
|
|
1066
1200
|
}
|
|
1201
|
+
/**
|
|
1202
|
+
* A committed compatibility hook may replace resumable continuations with
|
|
1203
|
+
* wrappers that validate and durably persist their terminal result. Attach
|
|
1204
|
+
* local task publication only after those final wrappers return.
|
|
1205
|
+
*/
|
|
1206
|
+
attachSettledContinuationTaskStatus(taskId, result) {
|
|
1207
|
+
const publish = (status, data, error) => {
|
|
1208
|
+
this.publishSettledTaskStatus(taskId, status, data, error);
|
|
1209
|
+
};
|
|
1210
|
+
if (result.submitted) {
|
|
1211
|
+
const submitted = result.submitted;
|
|
1212
|
+
result.submitted = {
|
|
1213
|
+
...submitted,
|
|
1214
|
+
track: async (transport) => {
|
|
1215
|
+
const task = await submitted.track(transport);
|
|
1216
|
+
publish(task.status, task.result, task.error);
|
|
1217
|
+
return task;
|
|
1218
|
+
},
|
|
1219
|
+
waitForCompletion: async (pollInterval, signal) => {
|
|
1220
|
+
const completion = this.attachSettledContinuationTaskStatus(
|
|
1221
|
+
taskId,
|
|
1222
|
+
await submitted.waitForCompletion(pollInterval, signal)
|
|
1223
|
+
);
|
|
1224
|
+
publish(completion.status, completion.data, completion.error);
|
|
1225
|
+
return completion;
|
|
1226
|
+
}
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
if (result.deferred) {
|
|
1230
|
+
const deferred = result.deferred;
|
|
1231
|
+
result.deferred = {
|
|
1232
|
+
...deferred,
|
|
1233
|
+
resume: async (input) => {
|
|
1234
|
+
const completion = this.attachSettledContinuationTaskStatus(taskId, await deferred.resume(input));
|
|
1235
|
+
publish(completion.status, completion.data, completion.error);
|
|
1236
|
+
return completion;
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
return result;
|
|
1241
|
+
}
|
|
1242
|
+
publishSettledTaskStatus(taskId, status, data, error, fromExternalObservation = false) {
|
|
1243
|
+
if (!TERMINAL_TASK_STATUSES.has(status)) return;
|
|
1244
|
+
const task = this.activeTasks.get(taskId);
|
|
1245
|
+
if (!task) return;
|
|
1246
|
+
if (!fromExternalObservation) {
|
|
1247
|
+
this.closeExternalTaskSettlement(
|
|
1248
|
+
taskId,
|
|
1249
|
+
new Error("The task settled through its direct response; a racing pushed result was not accepted.")
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
if (task.status !== status) this.updateTaskStatus(taskId, status, data, error);
|
|
1253
|
+
}
|
|
1254
|
+
rejectPendingExternalTaskObservations(taskId, error) {
|
|
1255
|
+
const pending = this.pendingExternalTaskObservations.get(taskId);
|
|
1256
|
+
this.pendingExternalTaskObservations.delete(taskId);
|
|
1257
|
+
for (const waiter of pending ?? []) waiter.reject(error);
|
|
1258
|
+
}
|
|
1259
|
+
closeExternalTaskSettlement(taskId, error) {
|
|
1260
|
+
this.externalTaskSettlementHandlers.delete(taskId);
|
|
1261
|
+
this.externalTaskSettlementInFlight.delete(taskId);
|
|
1262
|
+
this.closedExternalTaskSettlementTaskIds.add(taskId);
|
|
1263
|
+
this.rejectPendingExternalTaskObservations(taskId, error);
|
|
1264
|
+
}
|
|
1265
|
+
clearExternalTaskSettlementState(taskId) {
|
|
1266
|
+
this.deferredTerminalPublicationTaskIds.delete(taskId);
|
|
1267
|
+
this.closedExternalTaskSettlementTaskIds.delete(taskId);
|
|
1268
|
+
this.externalTaskSettlementHandlers.delete(taskId);
|
|
1269
|
+
this.externalTaskSettlementInFlight.delete(taskId);
|
|
1270
|
+
this.settledExternalTaskObservationKeys.delete(taskId);
|
|
1271
|
+
this.externalTaskSettlementExpiry.delete(taskId);
|
|
1272
|
+
this.rejectPendingExternalTaskObservations(
|
|
1273
|
+
taskId,
|
|
1274
|
+
new Error("The durable push-settlement retention window expired before the observation was accepted.")
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1277
|
+
retainExternalTaskSettlementState(taskId) {
|
|
1278
|
+
const retentionMs = this.config.externalTaskSettlementRetentionMs ?? DEFAULT_EXTERNAL_TASK_SETTLEMENT_RETENTION_MS;
|
|
1279
|
+
const expiry = Date.now() + retentionMs;
|
|
1280
|
+
if ((this.externalTaskSettlementExpiry.get(taskId) ?? 0) >= expiry) return;
|
|
1281
|
+
this.externalTaskSettlementExpiry.set(taskId, expiry);
|
|
1282
|
+
const expire = () => {
|
|
1283
|
+
if (this.externalTaskSettlementExpiry.get(taskId) !== expiry) return;
|
|
1284
|
+
const remaining = expiry - Date.now();
|
|
1285
|
+
if (remaining > 0) {
|
|
1286
|
+
const timer2 = setTimeout(expire, Math.min(remaining, MAX_TIMER_DELAY_MS));
|
|
1287
|
+
timer2.unref?.();
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
this.clearExternalTaskSettlementState(taskId);
|
|
1291
|
+
};
|
|
1292
|
+
const timer = setTimeout(expire, Math.min(retentionMs, MAX_TIMER_DELAY_MS));
|
|
1293
|
+
timer.unref?.();
|
|
1294
|
+
}
|
|
1295
|
+
/** Release short-lived task inspection state without dropping a live durable push fence. */
|
|
1296
|
+
cleanupTerminalTaskInspectionState(taskId) {
|
|
1297
|
+
this.activeTasks.delete(taskId);
|
|
1298
|
+
this.compactedTaskIds.delete(taskId);
|
|
1299
|
+
if (this.deferredTerminalPublicationTaskIds.has(taskId) || this.closedExternalTaskSettlementTaskIds.has(taskId) || this.externalTaskSettlementHandlers.has(taskId)) {
|
|
1300
|
+
if (this.externalTaskSettlementExpiry.has(taskId)) return;
|
|
1301
|
+
}
|
|
1302
|
+
this.clearExternalTaskSettlementState(taskId);
|
|
1303
|
+
}
|
|
1304
|
+
registerExternalTaskSettlement(taskId, handler) {
|
|
1305
|
+
this.externalTaskSettlementHandlers.set(taskId, handler);
|
|
1306
|
+
const pending = this.pendingExternalTaskObservations.get(taskId);
|
|
1307
|
+
if (!pending) return;
|
|
1308
|
+
this.pendingExternalTaskObservations.delete(taskId);
|
|
1309
|
+
for (const waiter of pending) {
|
|
1310
|
+
void this.settleExternalTaskStatus(taskId, handler, waiter.observation).then(waiter.resolve, waiter.reject);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
externalTaskObservationKey(observation) {
|
|
1314
|
+
return (0, import_crypto.createHash)("sha256").update(
|
|
1315
|
+
(0, import_jcs.canonicalize)({
|
|
1316
|
+
status: observation.status,
|
|
1317
|
+
serverTaskId: observation.serverTaskId ?? null,
|
|
1318
|
+
taskType: observation.taskType ?? null,
|
|
1319
|
+
result: observation.result ?? null
|
|
1320
|
+
})
|
|
1321
|
+
).digest("base64url");
|
|
1322
|
+
}
|
|
1323
|
+
async settleExternalTaskStatus(taskId, handler, observation) {
|
|
1324
|
+
const observationKey = this.externalTaskObservationKey(observation);
|
|
1325
|
+
const existing = this.externalTaskSettlementInFlight.get(taskId);
|
|
1326
|
+
if (existing) {
|
|
1327
|
+
if (existing.waiterCount >= MAX_PENDING_EXTERNAL_TASK_OBSERVATIONS) {
|
|
1328
|
+
throw new Error("Too many terminal push notifications are undergoing durable task settlement.");
|
|
1329
|
+
}
|
|
1330
|
+
existing.waiterCount += 1;
|
|
1331
|
+
try {
|
|
1332
|
+
const accepted = await existing.settlement;
|
|
1333
|
+
if (existing.observationKey !== observationKey) {
|
|
1334
|
+
throw new Error("This task already completed durable settlement; the pushed result was not accepted.");
|
|
1335
|
+
}
|
|
1336
|
+
return { ...accepted, duplicate: true };
|
|
1337
|
+
} finally {
|
|
1338
|
+
existing.waiterCount -= 1;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
const settlement = (async () => {
|
|
1342
|
+
const settled = await handler(observation);
|
|
1343
|
+
const settledStatus = settled.status;
|
|
1344
|
+
if (this.closedExternalTaskSettlementTaskIds.has(taskId)) {
|
|
1345
|
+
throw new Error("The task settled through its direct response; the racing pushed result was not accepted.");
|
|
1346
|
+
}
|
|
1347
|
+
if (this.settledExternalTaskObservationKeys.has(taskId)) {
|
|
1348
|
+
throw new Error("This task already completed durable settlement; the pushed result was not accepted.");
|
|
1349
|
+
}
|
|
1350
|
+
this.publishSettledTaskStatus(taskId, settledStatus, settled.data, settled.error, true);
|
|
1351
|
+
this.settledExternalTaskObservationKeys.set(taskId, {
|
|
1352
|
+
key: observationKey,
|
|
1353
|
+
status: settledStatus,
|
|
1354
|
+
...settled.error !== void 0 && {
|
|
1355
|
+
error: settled.error.slice(0, MAX_RETAINED_EXTERNAL_TASK_ERROR_CHARS)
|
|
1356
|
+
}
|
|
1357
|
+
});
|
|
1358
|
+
this.closeExternalTaskSettlement(
|
|
1359
|
+
taskId,
|
|
1360
|
+
new Error("The task already completed durable external settlement; a later pushed result was not accepted.")
|
|
1361
|
+
);
|
|
1362
|
+
return {
|
|
1363
|
+
settled: true,
|
|
1364
|
+
result: settled.data,
|
|
1365
|
+
status: settled.status,
|
|
1366
|
+
...settled.error !== void 0 && { error: settled.error }
|
|
1367
|
+
};
|
|
1368
|
+
})();
|
|
1369
|
+
const inFlight = { observationKey, settlement, waiterCount: 1 };
|
|
1370
|
+
this.externalTaskSettlementInFlight.set(taskId, inFlight);
|
|
1371
|
+
try {
|
|
1372
|
+
return await settlement;
|
|
1373
|
+
} finally {
|
|
1374
|
+
if (this.externalTaskSettlementInFlight.get(taskId) === inFlight) {
|
|
1375
|
+
this.externalTaskSettlementInFlight.delete(taskId);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
/** Release abandoned caller data without publishing a premature terminal state. */
|
|
1380
|
+
compactAbandonedObserverTaskState(taskId) {
|
|
1381
|
+
const task = this.activeTasks.get(taskId);
|
|
1382
|
+
if (!task) return;
|
|
1383
|
+
task.params = void 0;
|
|
1384
|
+
task.messages = [];
|
|
1385
|
+
task.options = {};
|
|
1386
|
+
delete task.pendingInput;
|
|
1387
|
+
}
|
|
1067
1388
|
/**
|
|
1068
1389
|
* A working/submitted response carries everything needed to poll externally.
|
|
1069
1390
|
* Keeping the original request in activeTasks after dispatch would pin
|
|
@@ -1082,10 +1403,14 @@ class TaskExecutor {
|
|
|
1082
1403
|
this.compactedTaskIds.delete(taskId);
|
|
1083
1404
|
this.compactedTaskIds.set(taskId, true);
|
|
1084
1405
|
while (this.compactedTaskIds.size > COMPACTED_TASK_STATE_LIMIT) {
|
|
1085
|
-
const oldest = this.compactedTaskIds.keys().
|
|
1406
|
+
const oldest = [...this.compactedTaskIds.keys()].find(
|
|
1407
|
+
(candidate) => !this.deferredTerminalPublicationTaskIds.has(candidate) && !this.externalTaskSettlementHandlers.has(candidate) && !this.externalTaskSettlementInFlight.has(candidate)
|
|
1408
|
+
);
|
|
1086
1409
|
if (oldest === void 0) break;
|
|
1087
1410
|
this.compactedTaskIds.delete(oldest);
|
|
1088
1411
|
this.activeTasks.delete(oldest);
|
|
1412
|
+
this.closeExternalTaskSettlement(oldest, new Error("The compacted task was evicted before push settlement."));
|
|
1413
|
+
this.closedExternalTaskSettlementTaskIds.delete(oldest);
|
|
1089
1414
|
}
|
|
1090
1415
|
}
|
|
1091
1416
|
/**
|
|
@@ -1096,7 +1421,7 @@ class TaskExecutor {
|
|
|
1096
1421
|
* This is common for HITL (human-in-the-loop) workflows where the agent has already processed
|
|
1097
1422
|
* the request and is just signaling that async approval may be needed.
|
|
1098
1423
|
*/
|
|
1099
|
-
async handleInputRequired(agent, taskId, taskName, params, response, messages, inputHandler, options = {}, debugLogs = [], startTime = Date.now()) {
|
|
1424
|
+
async handleInputRequired(agent, taskId, taskName, params, response, messages, inputHandler, options = {}, debugLogs = [], startTime = Date.now(), deferTerminalTaskStatus = false) {
|
|
1100
1425
|
const inputRequest = this.responseParser.parseInputRequest(response);
|
|
1101
1426
|
if (!inputHandler) {
|
|
1102
1427
|
const partialData = this.extractResponseData(response, debugLogs, taskName);
|
|
@@ -1174,7 +1499,7 @@ class TaskExecutor {
|
|
|
1174
1499
|
const deferred = {
|
|
1175
1500
|
token,
|
|
1176
1501
|
question: inputRequest.question,
|
|
1177
|
-
resume: (input) => this.resumeDeferredTask(token, input)
|
|
1502
|
+
resume: (input) => this.resumeDeferredTask(token, input, !deferTerminalTaskStatus)
|
|
1178
1503
|
};
|
|
1179
1504
|
return {
|
|
1180
1505
|
success: true,
|
|
@@ -1207,7 +1532,8 @@ class TaskExecutor {
|
|
|
1207
1532
|
// Pass handler for multi-round clarification
|
|
1208
1533
|
options,
|
|
1209
1534
|
debugLogs,
|
|
1210
|
-
startTime
|
|
1535
|
+
startTime,
|
|
1536
|
+
deferTerminalTaskStatus
|
|
1211
1537
|
);
|
|
1212
1538
|
}
|
|
1213
1539
|
/**
|
|
@@ -1426,7 +1752,7 @@ class TaskExecutor {
|
|
|
1426
1752
|
/**
|
|
1427
1753
|
* Resume a deferred task (client deferral)
|
|
1428
1754
|
*/
|
|
1429
|
-
async resumeDeferredTask(token, input) {
|
|
1755
|
+
async resumeDeferredTask(token, input, publishTerminalTaskStatus = true) {
|
|
1430
1756
|
if (!this.config.deferredStorage) {
|
|
1431
1757
|
throw new Error("Deferred storage not configured");
|
|
1432
1758
|
}
|
|
@@ -1443,11 +1769,15 @@ class TaskExecutor {
|
|
|
1443
1769
|
state.contextId,
|
|
1444
1770
|
input,
|
|
1445
1771
|
state.messages,
|
|
1446
|
-
void 0
|
|
1772
|
+
void 0,
|
|
1447
1773
|
// No handler for deferred tasks - input was provided by human
|
|
1774
|
+
{},
|
|
1775
|
+
[],
|
|
1776
|
+
Date.now(),
|
|
1777
|
+
!publishTerminalTaskStatus
|
|
1448
1778
|
);
|
|
1449
1779
|
const remainsPaused = ["input-required", "auth-required", "deferred"].includes(resumed.status);
|
|
1450
|
-
if (["completed", "failed", "rejected", "canceled", "governance-denied", "aborted"].includes(resumed.status) && this.activeTasks.get(state.taskId)?.status !== resumed.status) {
|
|
1780
|
+
if (publishTerminalTaskStatus && ["completed", "failed", "rejected", "canceled", "governance-denied", "aborted"].includes(resumed.status) && this.activeTasks.get(state.taskId)?.status !== resumed.status) {
|
|
1451
1781
|
this.updateTaskStatus(state.taskId, resumed.status, resumed.data, resumed.error);
|
|
1452
1782
|
}
|
|
1453
1783
|
if (!remainsPaused) {
|
|
@@ -1455,7 +1785,14 @@ class TaskExecutor {
|
|
|
1455
1785
|
}
|
|
1456
1786
|
return (0, import_match.attachMatch)(resumed);
|
|
1457
1787
|
} catch (error) {
|
|
1458
|
-
|
|
1788
|
+
if (publishTerminalTaskStatus) {
|
|
1789
|
+
this.updateTaskStatus(
|
|
1790
|
+
state.taskId,
|
|
1791
|
+
"failed",
|
|
1792
|
+
void 0,
|
|
1793
|
+
error instanceof Error ? error.message : String(error)
|
|
1794
|
+
);
|
|
1795
|
+
}
|
|
1459
1796
|
try {
|
|
1460
1797
|
await this.config.deferredStorage.delete(token);
|
|
1461
1798
|
} catch {
|
|
@@ -1466,7 +1803,7 @@ class TaskExecutor {
|
|
|
1466
1803
|
/**
|
|
1467
1804
|
* Continue a task after receiving input
|
|
1468
1805
|
*/
|
|
1469
|
-
async continueTaskWithInput(agent, taskId, taskName, params, contextId, input, messages, inputHandler, options = {}, debugLogs = [], startTime = Date.now()) {
|
|
1806
|
+
async continueTaskWithInput(agent, taskId, taskName, params, contextId, input, messages, inputHandler, options = {}, debugLogs = [], startTime = Date.now(), deferTerminalTaskStatus = false) {
|
|
1470
1807
|
const inputMessage = {
|
|
1471
1808
|
id: (0, import_crypto.randomUUID)(),
|
|
1472
1809
|
role: "user",
|
|
@@ -1516,7 +1853,8 @@ class TaskExecutor {
|
|
|
1516
1853
|
inputHandler,
|
|
1517
1854
|
options,
|
|
1518
1855
|
debugLogs,
|
|
1519
|
-
startTime
|
|
1856
|
+
startTime,
|
|
1857
|
+
deferTerminalTaskStatus
|
|
1520
1858
|
);
|
|
1521
1859
|
}
|
|
1522
1860
|
/**
|
|
@@ -1801,8 +2139,7 @@ class TaskExecutor {
|
|
|
1801
2139
|
task.options = {};
|
|
1802
2140
|
delete task.pendingInput;
|
|
1803
2141
|
setTimeout(() => {
|
|
1804
|
-
this.
|
|
1805
|
-
this.compactedTaskIds.delete(taskId);
|
|
2142
|
+
this.cleanupTerminalTaskInspectionState(taskId);
|
|
1806
2143
|
}, 3e4).unref();
|
|
1807
2144
|
}
|
|
1808
2145
|
}
|
|
@@ -1816,6 +2153,7 @@ class TaskExecutor {
|
|
|
1816
2153
|
}
|
|
1817
2154
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1818
2155
|
0 && (module.exports = {
|
|
2156
|
+
AfterProtocolDispatchHookError,
|
|
1819
2157
|
BeforeProtocolDispatchHookError,
|
|
1820
2158
|
DeferredTaskError,
|
|
1821
2159
|
InputRequiredError,
|