agents 0.14.0 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-tool-types-LInzZfLo.d.ts → agent-tool-types-V25Z_HcX.d.ts} +275 -122
- package/dist/agent-tool-types.d.ts +13 -11
- package/dist/{agent-tools-BAdX1vdI.js → agent-tools-3zLG7MgA.js} +49 -7
- package/dist/agent-tools-3zLG7MgA.js.map +1 -0
- package/dist/{agent-tools-BE9xosUG.d.ts → agent-tools-C-9s151X.d.ts} +2 -2
- package/dist/agent-tools.d.ts +13 -11
- package/dist/agent-tools.js +8 -3
- package/dist/agent-tools.js.map +1 -1
- package/dist/browser/ai.d.ts +1 -1
- package/dist/browser/ai.js +1 -1
- package/dist/browser/ai.js.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/tanstack-ai.d.ts +1 -1
- package/dist/browser/tanstack-ai.js +1 -1
- package/dist/browser/tanstack-ai.js.map +1 -1
- package/dist/chat/index.d.ts +115 -8
- package/dist/chat/index.js +10 -6
- package/dist/chat/index.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +5 -5
- package/dist/chat-sdk/index.js +2 -2
- package/dist/chat-sdk/index.js.map +1 -1
- package/dist/{classPrivateFieldGet2-Evpt0SEr.js → classPrivateFieldGet2-Beqsfu2Z.js} +5 -5
- package/dist/{classPrivateMethodInitSpec-bG0tD96O.js → classPrivateMethodInitSpec-B5ko1s2R.js} +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/{client-NradHZZz.js → client-FUizKzj2.js} +94 -21
- package/dist/client-FUizKzj2.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/{compaction-helpers-DpP_XP9J.d.ts → compaction-helpers-BEUILPss.d.ts} +1 -1
- package/dist/{compaction-helpers-BjT2NKRZ.js → compaction-helpers-iiKMr2TQ.js} +1 -1
- package/dist/{compaction-helpers-BjT2NKRZ.js.map → compaction-helpers-iiKMr2TQ.js.map} +1 -1
- package/dist/{do-oauth-client-provider-CPm9rK5I.d.ts → do-oauth-client-provider-D4ZwyBDu.d.ts} +21 -1
- package/dist/{email-1fTSJwPm.d.ts → email-CL27preh.d.ts} +1 -1
- package/dist/email.d.ts +2 -2
- package/dist/email.js.map +1 -1
- package/dist/experimental/memory/session/index.d.ts +1 -1
- package/dist/experimental/memory/session/index.js +1 -1
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/experimental/memory/utils/index.d.ts +1 -1
- package/dist/experimental/memory/utils/index.js +2 -2
- package/dist/experimental/webmcp.js.map +1 -1
- package/dist/{index-Brdu5nMI.d.ts → index-CPe1OtI0.d.ts} +17 -1
- package/dist/index.d.ts +71 -69
- package/dist/index.js +288 -84
- package/dist/index.js.map +1 -1
- package/dist/{internal_context-CcZy2Em7.d.ts → internal_context-Dg4Cgjcu.d.ts} +1 -1
- package/dist/internal_context.d.ts +1 -1
- package/dist/mcp/client.d.ts +14 -14
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
- package/dist/mcp/do-oauth-client-provider.js +143 -17
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +30 -30
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.js.map +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.js.map +1 -1
- package/dist/react.d.ts +3 -3
- package/dist/react.js +1 -1
- package/dist/react.js.map +1 -1
- package/dist/{retries-ClWwxADl.d.ts → retries-CF_HKSlJ.d.ts} +1 -1
- package/dist/retries.d.ts +1 -1
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/{shared-CpY1FLvm.d.ts → shared-4CAYLCTO.d.ts} +1 -1
- package/dist/{shared-DdOn6sp4.js → shared-wyII629d.js} +3 -3
- package/dist/{shared-DdOn6sp4.js.map → shared-wyII629d.js.map} +1 -1
- package/dist/skills/index.js +4 -4
- package/dist/skills/index.js.map +1 -1
- package/dist/sub-routing.d.ts +6 -6
- package/dist/sub-routing.js.map +1 -1
- package/dist/{tool-output-truncation-BF4AZQlw.js → tool-output-truncation-CNnnGZQ3.js} +1 -1
- package/dist/{tool-output-truncation-BF4AZQlw.js.map → tool-output-truncation-CNnnGZQ3.js.map} +1 -1
- package/dist/{types-B0GymtN_.d.ts → types-6Zo2zfoO.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/vite.d.ts +15 -4
- package/dist/vite.js +37 -7
- package/dist/vite.js.map +1 -1
- package/dist/{workflow-types-DPkuBi--.d.ts → workflow-types-SrZK_o9p.d.ts} +1 -1
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflows.d.ts +11 -3
- package/dist/workflows.js +48 -22
- package/dist/workflows.js.map +1 -1
- package/package.json +14 -23
- package/dist/agent-tools-BAdX1vdI.js.map +0 -1
- package/dist/client-NradHZZz.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -2,10 +2,10 @@ import { __DO_NOT_USE_WILL_BREAK__agentContext } from "./internal_context.js";
|
|
|
2
2
|
import { MessageType } from "./types.js";
|
|
3
3
|
import { camelCaseToKebabCase, isInternalJsStubProp } from "./utils.js";
|
|
4
4
|
import { createHeaderBasedEmailResolver, signAgentHeaders } from "./email.js";
|
|
5
|
-
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-
|
|
5
|
+
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-Beqsfu2Z.js";
|
|
6
6
|
import { SUB_PREFIX, getSubAgentByName, parseSubAgentPath, routeSubAgentRequest } from "./sub-routing.js";
|
|
7
7
|
import { isErrorRetryable, tryN, validateRetryOptions } from "./retries.js";
|
|
8
|
-
import { a as MCPConnectionState, c as RPC_DO_PREFIX, i as normalizeServerId, l as DisposableStore, n as MCP_SERVER_ID_MAX_LENGTH, t as MCPClientManager } from "./client-
|
|
8
|
+
import { a as MCPConnectionState, c as RPC_DO_PREFIX, i as normalizeServerId, l as DisposableStore, n as MCP_SERVER_ID_MAX_LENGTH, t as MCPClientManager } from "./client-FUizKzj2.js";
|
|
9
9
|
import { DurableObjectOAuthClientProvider } from "./mcp/do-oauth-client-provider.js";
|
|
10
10
|
import { genericObservability } from "./observability/index.js";
|
|
11
11
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -116,7 +116,8 @@ function getNextCronTime(cron) {
|
|
|
116
116
|
const DEFAULT_KEEP_ALIVE_INTERVAL_MS = 3e4;
|
|
117
117
|
const DEFAULT_AGENT_TOOL_RECOVERY_TIMEOUT_MS = 2e3;
|
|
118
118
|
const DEFAULT_AGENT_TOOL_RECOVERY_TOTAL_TIMEOUT_MS = 5e3;
|
|
119
|
-
const
|
|
119
|
+
const DEFAULT_AGENT_TOOL_REATTACH_NO_PROGRESS_TIMEOUT_MS = 12e4;
|
|
120
|
+
const DEFAULT_AGENT_TOOL_REATTACH_MAX_WINDOW_MS = Number.POSITIVE_INFINITY;
|
|
120
121
|
const SUB_AGENT_IDENTITY_VERSION_LEGACY = "legacy";
|
|
121
122
|
const SUB_AGENT_IDENTITY_VERSION_PATH_V2 = "path-v2";
|
|
122
123
|
const SUB_AGENT_IDENTITY_PATH_V2_PREFIX = "cf-agents:v2:";
|
|
@@ -126,7 +127,7 @@ const SUB_AGENT_IDENTITY_PATH_V2_PREFIX = "cf-agents:v2:";
|
|
|
126
127
|
* The constructor stores this as a row in cf_agents_state and checks it
|
|
127
128
|
* on wake to skip DDL on established DOs.
|
|
128
129
|
*/
|
|
129
|
-
const CURRENT_SCHEMA_VERSION =
|
|
130
|
+
const CURRENT_SCHEMA_VERSION = 9;
|
|
130
131
|
const SCHEMA_VERSION_ROW_ID = "cf_schema_version";
|
|
131
132
|
const STATE_ROW_ID = "cf_state_row_id";
|
|
132
133
|
const STATE_WAS_CHANGED = "cf_state_was_changed";
|
|
@@ -275,7 +276,27 @@ const DEFAULT_AGENT_STATIC_OPTIONS = {
|
|
|
275
276
|
* up. Bounds repeated retries of a `onFiberRecovered()` hook that keeps
|
|
276
277
|
* throwing so a poison row cannot re-trigger forever across boots.
|
|
277
278
|
*/
|
|
278
|
-
fiberRecoveryMaxAgeMs: 1440 * 60 * 1e3
|
|
279
|
+
fiberRecoveryMaxAgeMs: 1440 * 60 * 1e3,
|
|
280
|
+
/**
|
|
281
|
+
* No-progress budget (ms) for re-attaching to a still-running agent-tool
|
|
282
|
+
* child after a deploy / parent recovery (#1630). Bounds how long the parent
|
|
283
|
+
* waits with NO forward progress from the child; it resets on every forwarded
|
|
284
|
+
* chunk, so a child that keeps streaming is never abandoned mid-flight. Only a
|
|
285
|
+
* genuinely silent/hung child seals `interrupted` after a full window. Raise
|
|
286
|
+
* for children with long quiet stretches between outputs.
|
|
287
|
+
*/
|
|
288
|
+
agentToolReattachNoProgressTimeoutMs: DEFAULT_AGENT_TOOL_REATTACH_NO_PROGRESS_TIMEOUT_MS,
|
|
289
|
+
/**
|
|
290
|
+
* Optional hard wall-clock ceiling (ms) on a single agent-tool re-attach
|
|
291
|
+
* (#1630). Caps the total wait even as the no-progress budget re-arms across
|
|
292
|
+
* stream-closes. Defaults to `Infinity` (no implicit cap), mirroring
|
|
293
|
+
* chat-recovery's `maxRecoveryWork` (#1672): a healthy, still-advancing child
|
|
294
|
+
* is followed for as long as it makes progress — a hung child is bounded by
|
|
295
|
+
* the no-progress budget, and a content-runaway by the child's own
|
|
296
|
+
* `maxRecoveryWork` / `shouldKeepRecovering`. Set a finite value to impose a
|
|
297
|
+
* wall-clock cap (which also tears the child down on `window-exceeded`).
|
|
298
|
+
*/
|
|
299
|
+
agentToolReattachMaxWindowMs: DEFAULT_AGENT_TOOL_REATTACH_MAX_WINDOW_MS
|
|
279
300
|
};
|
|
280
301
|
/**
|
|
281
302
|
* Parse the raw `retry_options` TEXT column from a SQLite row into a
|
|
@@ -299,17 +320,34 @@ function resolveRetryConfig(taskRetry, defaults) {
|
|
|
299
320
|
};
|
|
300
321
|
}
|
|
301
322
|
/**
|
|
302
|
-
* Whether an error is a
|
|
323
|
+
* Whether an error is a transient "superseded isolate" failure — the invocation
|
|
324
|
+
* is running on an isolate the platform has replaced with a new version (a
|
|
325
|
+
* deploy / code update). For the rest of that invocation every operation throws
|
|
326
|
+
* the same error (code never reloads mid-invocation), so in-process retries are
|
|
327
|
+
* futile; but the next fresh invocation runs the new code and succeeds.
|
|
328
|
+
*
|
|
329
|
+
* workerd surfaces this as a plain `Error` with one of a few messages, all the
|
|
330
|
+
* same failure class — a message match is the only signal:
|
|
331
|
+
* - "Durable Object reset because its code was updated." (DO storage op on a
|
|
332
|
+
* superseded isolate / deploy bounce)
|
|
333
|
+
* - "This script has been upgraded. Please send a new request to connect to
|
|
334
|
+
* the new version." (a stub/connection to a superseded script; the message
|
|
335
|
+
* literally instructs the caller to retry on the new version)
|
|
303
336
|
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
337
|
+
* The match stays close to the verbatim platform strings (rather than a loose
|
|
338
|
+
* "upgraded"/"reset" substring) so an ordinary application error that happens
|
|
339
|
+
* to mention those words is NOT misclassified as a supersede — a false positive
|
|
340
|
+
* would defer + re-run a genuinely-failing callback on the platform's alarm
|
|
341
|
+
* retries instead of abandoning it.
|
|
342
|
+
*
|
|
343
|
+
* NOTE: "Network connection lost." is deliberately NOT included — it is a
|
|
344
|
+
* connection error, not an isolate replacement, and may succeed on in-process
|
|
345
|
+
* retry (it is gated by the CF `retryable` property via `isErrorRetryable`),
|
|
346
|
+
* so it stays on the normal retry path rather than the immediate-defer path.
|
|
309
347
|
*/
|
|
310
348
|
function isDurableObjectCodeUpdateReset(error) {
|
|
311
349
|
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
|
|
312
|
-
return /reset because its code was updated/i.test(message);
|
|
350
|
+
return /reset because its code was updated|this script has been upgraded/i.test(message);
|
|
313
351
|
}
|
|
314
352
|
function getCurrentAgent() {
|
|
315
353
|
const store = __DO_NOT_USE_WILL_BREAK__agentContext.getStore();
|
|
@@ -411,7 +449,9 @@ var Agent = class Agent extends Server {
|
|
|
411
449
|
},
|
|
412
450
|
fiberRecoveryHookTimeoutMs: ctor.options?.fiberRecoveryHookTimeoutMs ?? DEFAULT_AGENT_STATIC_OPTIONS.fiberRecoveryHookTimeoutMs,
|
|
413
451
|
fiberRecoveryScanDeadlineMs: ctor.options?.fiberRecoveryScanDeadlineMs ?? DEFAULT_AGENT_STATIC_OPTIONS.fiberRecoveryScanDeadlineMs,
|
|
414
|
-
fiberRecoveryMaxAgeMs: ctor.options?.fiberRecoveryMaxAgeMs ?? DEFAULT_AGENT_STATIC_OPTIONS.fiberRecoveryMaxAgeMs
|
|
452
|
+
fiberRecoveryMaxAgeMs: ctor.options?.fiberRecoveryMaxAgeMs ?? DEFAULT_AGENT_STATIC_OPTIONS.fiberRecoveryMaxAgeMs,
|
|
453
|
+
agentToolReattachNoProgressTimeoutMs: ctor.options?.agentToolReattachNoProgressTimeoutMs ?? DEFAULT_AGENT_STATIC_OPTIONS.agentToolReattachNoProgressTimeoutMs,
|
|
454
|
+
agentToolReattachMaxWindowMs: ctor.options?.agentToolReattachMaxWindowMs ?? DEFAULT_AGENT_STATIC_OPTIONS.agentToolReattachMaxWindowMs
|
|
415
455
|
};
|
|
416
456
|
return this._cachedOptions;
|
|
417
457
|
}
|
|
@@ -638,6 +678,8 @@ var Agent = class Agent extends Server {
|
|
|
638
678
|
summary TEXT,
|
|
639
679
|
output_json TEXT,
|
|
640
680
|
error_message TEXT,
|
|
681
|
+
interrupted_reason TEXT,
|
|
682
|
+
child_still_running INTEGER,
|
|
641
683
|
display_metadata TEXT,
|
|
642
684
|
display_order INTEGER NOT NULL DEFAULT 0,
|
|
643
685
|
started_at INTEGER NOT NULL,
|
|
@@ -649,6 +691,8 @@ var Agent = class Agent extends Server {
|
|
|
649
691
|
ON cf_agent_tool_runs(parent_tool_call_id, display_order)
|
|
650
692
|
`;
|
|
651
693
|
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN output_json TEXT");
|
|
694
|
+
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN interrupted_reason TEXT");
|
|
695
|
+
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN child_still_running INTEGER");
|
|
652
696
|
this.sql`
|
|
653
697
|
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
654
698
|
VALUES (${SCHEMA_VERSION_ROW_ID}, ${String(CURRENT_SCHEMA_VERSION)})
|
|
@@ -663,12 +707,12 @@ var Agent = class Agent extends Server {
|
|
|
663
707
|
this._rawStateAccessors = /* @__PURE__ */ new WeakMap();
|
|
664
708
|
this._persistenceHookMode = "none";
|
|
665
709
|
this._isFacet = false;
|
|
666
|
-
this._suppressProtocolBroadcasts = false;
|
|
667
710
|
this._protocolBroadcastExcludeIds = /* @__PURE__ */ new Set();
|
|
668
711
|
this._cf_virtualSubAgentConnections = /* @__PURE__ */ new Map();
|
|
669
712
|
this._parentPath = [];
|
|
670
713
|
this._insideOnStart = false;
|
|
671
714
|
this._warnedScheduleInOnStart = /* @__PURE__ */ new Set();
|
|
715
|
+
this._warnedChatRecoveryInOnStart = false;
|
|
672
716
|
this._keepAliveRefs = 0;
|
|
673
717
|
this._facetKeepAliveTokens = /* @__PURE__ */ new Set();
|
|
674
718
|
this._runFiberActiveFibers = /* @__PURE__ */ new Set();
|
|
@@ -915,6 +959,7 @@ var Agent = class Agent extends Server {
|
|
|
915
959
|
this._checkOrphanedWorkflows();
|
|
916
960
|
await this._checkRunFibers();
|
|
917
961
|
const startupAgentToolRunIds = this._agentToolRunRecoveryRunIds();
|
|
962
|
+
const chatRecoveryBefore = this.chatRecovery;
|
|
918
963
|
this._insideOnStart = true;
|
|
919
964
|
this._warnedScheduleInOnStart.clear();
|
|
920
965
|
let result;
|
|
@@ -923,6 +968,12 @@ var Agent = class Agent extends Server {
|
|
|
923
968
|
} finally {
|
|
924
969
|
this._insideOnStart = false;
|
|
925
970
|
}
|
|
971
|
+
const chatRecoveryAfter = this.chatRecovery;
|
|
972
|
+
const chatRecoveryAfterMatters = typeof chatRecoveryAfter === "object" && chatRecoveryAfter !== null || chatRecoveryAfter === true;
|
|
973
|
+
if (!this._warnedChatRecoveryInOnStart && chatRecoveryBefore !== chatRecoveryAfter && chatRecoveryAfterMatters) {
|
|
974
|
+
this._warnedChatRecoveryInOnStart = true;
|
|
975
|
+
console.warn("[Agent] `chatRecovery` was assigned during onStart(). Chat recovery evaluates its budgets (and may seal an interrupted turn, firing onExhausted) on wake BEFORE onStart() runs, so a config set here is applied too late and the built-in defaults are used for the recovery that matters. Assign `chatRecovery` as a class field or in the constructor instead.");
|
|
976
|
+
}
|
|
926
977
|
this._scheduleAgentToolRunRecovery({ runIds: startupAgentToolRunIds });
|
|
927
978
|
return result;
|
|
928
979
|
});
|
|
@@ -959,7 +1010,6 @@ var Agent = class Agent extends Server {
|
|
|
959
1010
|
* @param excludeIds Additional connection IDs to exclude (e.g. the source)
|
|
960
1011
|
*/
|
|
961
1012
|
_broadcastProtocol(msg, excludeIds = []) {
|
|
962
|
-
if (this._suppressProtocolBroadcasts) return;
|
|
963
1013
|
const exclude = [...excludeIds, ...this._protocolBroadcastExcludeIds];
|
|
964
1014
|
for (const conn of this.getConnections()) if (!this.isConnectionProtocolEnabled(conn)) exclude.push(conn.id);
|
|
965
1015
|
this.broadcast(msg, exclude);
|
|
@@ -3370,6 +3420,7 @@ var Agent = class Agent extends Server {
|
|
|
3370
3420
|
if (this._isFacet) {
|
|
3371
3421
|
const stored = this._cf_virtualSubAgentConnections.get(id);
|
|
3372
3422
|
if (stored) return this._cf_createSubAgentBridgeConnection(stored.bridge, stored.meta);
|
|
3423
|
+
return;
|
|
3373
3424
|
}
|
|
3374
3425
|
const connection = super.getConnection(id);
|
|
3375
3426
|
if (!connection || this._cf_connectionHasSubAgentTarget(connection)) return;
|
|
@@ -3378,6 +3429,7 @@ var Agent = class Agent extends Server {
|
|
|
3378
3429
|
*getConnections(tag) {
|
|
3379
3430
|
if (this._isFacet) {
|
|
3380
3431
|
for (const stored of this._cf_virtualSubAgentConnections.values()) if (!tag || stored.meta.tags.includes(tag)) yield this._cf_createSubAgentBridgeConnection(stored.bridge, stored.meta);
|
|
3432
|
+
return;
|
|
3381
3433
|
}
|
|
3382
3434
|
for (const connection of super.getConnections(tag)) {
|
|
3383
3435
|
if (this._cf_connectionHasSubAgentTarget(connection)) continue;
|
|
@@ -3830,12 +3882,7 @@ var Agent = class Agent extends Server {
|
|
|
3830
3882
|
this.ctx.storage.put("cf_agents_facet_name", name),
|
|
3831
3883
|
this.ctx.storage.put("cf_agents_parent_path", parentPath)
|
|
3832
3884
|
]);
|
|
3833
|
-
this.
|
|
3834
|
-
try {
|
|
3835
|
-
await this.__unsafe_ensureInitialized();
|
|
3836
|
-
} finally {
|
|
3837
|
-
this._suppressProtocolBroadcasts = false;
|
|
3838
|
-
}
|
|
3885
|
+
await this.__unsafe_ensureInitialized();
|
|
3839
3886
|
}
|
|
3840
3887
|
get name() {
|
|
3841
3888
|
return this._facetName ?? logicalNameFromPathV2Identity(super.name) ?? super.name;
|
|
@@ -4005,10 +4052,12 @@ var Agent = class Agent extends Server {
|
|
|
4005
4052
|
} catch {}
|
|
4006
4053
|
return this._resultFromAgentToolRow(existing);
|
|
4007
4054
|
}
|
|
4055
|
+
let reattachReason;
|
|
4056
|
+
let childTornDown = false;
|
|
4008
4057
|
try {
|
|
4009
4058
|
const child = await this.subAgent(cls, runId);
|
|
4010
4059
|
const adapter = this._asAgentToolChildAdapter(child);
|
|
4011
|
-
const reattach = await this._reattachAgentToolRunToTerminal(adapter, existing, 1);
|
|
4060
|
+
const reattach = await this._reattachAgentToolRunToTerminal(adapter, existing, 1, this._resolvedOptions.agentToolReattachNoProgressTimeoutMs, this._resolvedOptions.agentToolReattachMaxWindowMs);
|
|
4012
4061
|
if (reattach.result) {
|
|
4013
4062
|
await this._finishAgentToolRun(this._agentToolRunInfoFromRow(existing), reattach.result, {
|
|
4014
4063
|
sequence: reattach.sequence,
|
|
@@ -4016,8 +4065,13 @@ var Agent = class Agent extends Server {
|
|
|
4016
4065
|
});
|
|
4017
4066
|
return reattach.result;
|
|
4018
4067
|
}
|
|
4068
|
+
reattachReason = reattach.reason;
|
|
4069
|
+
childTornDown = await this._teardownGivenUpAgentToolChild(adapter, runId, reattach.reason);
|
|
4019
4070
|
} catch {}
|
|
4020
|
-
return await this._replayAndInterruptAgentToolRun(existing,
|
|
4071
|
+
return await this._replayAndInterruptAgentToolRun(existing, this._interruptedMessageForReason(reattachReason), {
|
|
4072
|
+
reason: reattachReason,
|
|
4073
|
+
childStillRunning: !childTornDown
|
|
4074
|
+
});
|
|
4021
4075
|
}
|
|
4022
4076
|
const displayOrder = options.displayOrder ?? 0;
|
|
4023
4077
|
const inputPreview = options.inputPreview ?? this._defaultAgentToolPreview(options.input);
|
|
@@ -4111,7 +4165,7 @@ var Agent = class Agent extends Server {
|
|
|
4111
4165
|
try {
|
|
4112
4166
|
if (adapter.tailAgentToolRun) {
|
|
4113
4167
|
const stream = await adapter.tailAgentToolRun(runId, { afterSequence: -1 });
|
|
4114
|
-
sequence = await this._forwardAgentToolStream(stream, options.parentToolCallId, runId, sequence, options.signal);
|
|
4168
|
+
sequence = (await this._forwardAgentToolStream(stream, options.parentToolCallId, runId, sequence, options.signal)).next;
|
|
4115
4169
|
} else {
|
|
4116
4170
|
const chunks = await adapter.getAgentToolChunks(runId);
|
|
4117
4171
|
sequence = this._broadcastAgentToolChunks(options.parentToolCallId, runId, chunks, sequence);
|
|
@@ -4215,13 +4269,28 @@ var Agent = class Agent extends Server {
|
|
|
4215
4269
|
_readAgentToolRun(runId) {
|
|
4216
4270
|
return this.sql`
|
|
4217
4271
|
SELECT run_id, parent_tool_call_id, agent_type, input_preview, status,
|
|
4218
|
-
summary, output_json, error_message,
|
|
4272
|
+
summary, output_json, error_message, interrupted_reason,
|
|
4273
|
+
child_still_running, display_metadata, display_order,
|
|
4219
4274
|
started_at, completed_at
|
|
4220
4275
|
FROM cf_agent_tool_runs
|
|
4221
4276
|
WHERE run_id = ${runId}
|
|
4222
4277
|
LIMIT 1
|
|
4223
4278
|
`[0] ?? null;
|
|
4224
4279
|
}
|
|
4280
|
+
/**
|
|
4281
|
+
* Reconstruct the typed interrupted cause (`reason` / `childStillRunning`,
|
|
4282
|
+
* #1630 follow-up) from a stored row so a row→result/event rebuild — e.g. a
|
|
4283
|
+
* reconnect replay — carries the same fields a live client saw. Only
|
|
4284
|
+
* `interrupted` rows store a cause; everything else yields `{}` (the columns
|
|
4285
|
+
* are cleared whenever a row settles to a hard terminal).
|
|
4286
|
+
*/
|
|
4287
|
+
_agentToolInterruptedExtrasFromRow(row) {
|
|
4288
|
+
if (row.status !== "interrupted") return {};
|
|
4289
|
+
return {
|
|
4290
|
+
...row.interrupted_reason !== null ? { reason: row.interrupted_reason } : {},
|
|
4291
|
+
...row.child_still_running !== null ? { childStillRunning: row.child_still_running !== 0 } : {}
|
|
4292
|
+
};
|
|
4293
|
+
}
|
|
4225
4294
|
_resultFromAgentToolRow(row) {
|
|
4226
4295
|
const output = this._parseAgentToolJson(row.output_json);
|
|
4227
4296
|
return {
|
|
@@ -4230,7 +4299,8 @@ var Agent = class Agent extends Server {
|
|
|
4230
4299
|
status: row.status,
|
|
4231
4300
|
...output !== void 0 ? { output } : {},
|
|
4232
4301
|
...row.summary !== null ? { summary: row.summary } : {},
|
|
4233
|
-
...row.error_message !== null ? { error: row.error_message } : {}
|
|
4302
|
+
...row.error_message !== null ? { error: row.error_message } : {},
|
|
4303
|
+
...this._agentToolInterruptedExtrasFromRow(row)
|
|
4234
4304
|
};
|
|
4235
4305
|
}
|
|
4236
4306
|
_agentToolRunInfoFromRow(row, status = row.status, completedAt = row.completed_at ?? void 0) {
|
|
@@ -4289,12 +4359,15 @@ var Agent = class Agent extends Server {
|
|
|
4289
4359
|
}
|
|
4290
4360
|
}
|
|
4291
4361
|
_updateAgentToolTerminal(runId, result, completedAt = Date.now()) {
|
|
4362
|
+
const childStillRunning = result.childStillRunning === void 0 ? null : result.childStillRunning ? 1 : 0;
|
|
4292
4363
|
this.sql`
|
|
4293
4364
|
UPDATE cf_agent_tool_runs
|
|
4294
4365
|
SET status = ${result.status},
|
|
4295
4366
|
summary = ${result.summary ?? null},
|
|
4296
4367
|
output_json = ${this._stringifyAgentToolOutput(result.output)},
|
|
4297
4368
|
error_message = ${result.error ?? null},
|
|
4369
|
+
interrupted_reason = ${result.reason ?? null},
|
|
4370
|
+
child_still_running = ${childStillRunning},
|
|
4298
4371
|
completed_at = ${completedAt}
|
|
4299
4372
|
WHERE run_id = ${runId}
|
|
4300
4373
|
AND status NOT IN ('completed', 'error', 'aborted')
|
|
@@ -4357,9 +4430,13 @@ var Agent = class Agent extends Server {
|
|
|
4357
4430
|
if (!chunks) return sequence;
|
|
4358
4431
|
return this._broadcastAgentToolChunks(row.parent_tool_call_id ?? void 0, row.run_id, chunks, sequence, replay, connection);
|
|
4359
4432
|
}
|
|
4360
|
-
async _forwardAgentToolStream(stream, parentToolCallId, runId, sequence, signal) {
|
|
4433
|
+
async _forwardAgentToolStream(stream, parentToolCallId, runId, sequence, signal, idleTimeoutMs) {
|
|
4361
4434
|
let next = sequence;
|
|
4362
|
-
if (signal?.aborted) return
|
|
4435
|
+
if (signal?.aborted) return {
|
|
4436
|
+
next,
|
|
4437
|
+
ended: "aborted"
|
|
4438
|
+
};
|
|
4439
|
+
let ended = "done";
|
|
4363
4440
|
const reader = stream.getReader();
|
|
4364
4441
|
const decoder = new TextDecoder();
|
|
4365
4442
|
let bufferedBytes = "";
|
|
@@ -4373,6 +4450,17 @@ var Agent = class Agent extends Server {
|
|
|
4373
4450
|
abortListener = () => resolveAbort?.();
|
|
4374
4451
|
signal.addEventListener("abort", abortListener, { once: true });
|
|
4375
4452
|
}
|
|
4453
|
+
const idleEnabled = typeof idleTimeoutMs === "number" && idleTimeoutMs > 0 && Number.isFinite(idleTimeoutMs);
|
|
4454
|
+
let resolveIdle;
|
|
4455
|
+
let idleTimer;
|
|
4456
|
+
const idlePromise = new Promise((resolve) => {
|
|
4457
|
+
resolveIdle = resolve;
|
|
4458
|
+
});
|
|
4459
|
+
const armIdle = () => {
|
|
4460
|
+
if (!idleEnabled) return;
|
|
4461
|
+
if (idleTimer !== void 0) clearTimeout(idleTimer);
|
|
4462
|
+
idleTimer = setTimeout(() => resolveIdle?.(), idleTimeoutMs);
|
|
4463
|
+
};
|
|
4376
4464
|
let forwardedSinceProgress = false;
|
|
4377
4465
|
try {
|
|
4378
4466
|
const forwardChunk = (chunk) => {
|
|
@@ -4382,6 +4470,7 @@ var Agent = class Agent extends Server {
|
|
|
4382
4470
|
body: chunk.body
|
|
4383
4471
|
});
|
|
4384
4472
|
forwardedSinceProgress = true;
|
|
4473
|
+
armIdle();
|
|
4385
4474
|
};
|
|
4386
4475
|
const forwardLine = (line) => {
|
|
4387
4476
|
try {
|
|
@@ -4402,15 +4491,21 @@ var Agent = class Agent extends Server {
|
|
|
4402
4491
|
bufferedBytes = "";
|
|
4403
4492
|
}
|
|
4404
4493
|
};
|
|
4494
|
+
armIdle();
|
|
4405
4495
|
while (true) {
|
|
4406
4496
|
const readPromise = reader.read();
|
|
4407
4497
|
readPromise.catch(() => {});
|
|
4408
|
-
const raced = await Promise.race([
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4498
|
+
const raced = await Promise.race([
|
|
4499
|
+
readPromise.then((result) => ({
|
|
4500
|
+
kind: "read",
|
|
4501
|
+
result
|
|
4502
|
+
})),
|
|
4503
|
+
abortPromise.then(() => ({ kind: "abort" })),
|
|
4504
|
+
idlePromise.then(() => ({ kind: "idle" }))
|
|
4505
|
+
]);
|
|
4506
|
+
if (raced.kind === "abort" || raced.kind === "idle") {
|
|
4413
4507
|
aborted = true;
|
|
4508
|
+
ended = raced.kind === "idle" ? "idle" : "aborted";
|
|
4414
4509
|
break;
|
|
4415
4510
|
}
|
|
4416
4511
|
const { done, value } = raced.result;
|
|
@@ -4431,12 +4526,16 @@ var Agent = class Agent extends Server {
|
|
|
4431
4526
|
}
|
|
4432
4527
|
}
|
|
4433
4528
|
} finally {
|
|
4529
|
+
if (idleTimer !== void 0) clearTimeout(idleTimer);
|
|
4434
4530
|
if (abortListener && signal) signal.removeEventListener("abort", abortListener);
|
|
4435
4531
|
if (!aborted) try {
|
|
4436
4532
|
reader.releaseLock();
|
|
4437
4533
|
} catch {}
|
|
4438
4534
|
}
|
|
4439
|
-
return
|
|
4535
|
+
return {
|
|
4536
|
+
next,
|
|
4537
|
+
ended
|
|
4538
|
+
};
|
|
4440
4539
|
}
|
|
4441
4540
|
/**
|
|
4442
4541
|
* Hook invoked by `_forwardAgentToolStream` after a child produces output that
|
|
@@ -4473,7 +4572,9 @@ var Agent = class Agent extends Server {
|
|
|
4473
4572
|
else if (result.status === "interrupted") this._broadcastAgentToolEvent(parentToolCallId, sequence, {
|
|
4474
4573
|
kind: "interrupted",
|
|
4475
4574
|
runId: result.runId,
|
|
4476
|
-
error: result.error ?? "Agent tool run was interrupted"
|
|
4575
|
+
error: result.error ?? "Agent tool run was interrupted",
|
|
4576
|
+
...result.reason !== void 0 ? { reason: result.reason } : {},
|
|
4577
|
+
...result.childStillRunning !== void 0 ? { childStillRunning: result.childStillRunning } : {}
|
|
4477
4578
|
}, replay, connection);
|
|
4478
4579
|
else this._broadcastAgentToolEvent(parentToolCallId, sequence, {
|
|
4479
4580
|
kind: "error",
|
|
@@ -4491,7 +4592,7 @@ var Agent = class Agent extends Server {
|
|
|
4491
4592
|
if (!cls) throw new Error(`Agent tool class "${className}" is not exported.`);
|
|
4492
4593
|
return cls;
|
|
4493
4594
|
}
|
|
4494
|
-
async _replayAndInterruptAgentToolRun(row, message) {
|
|
4595
|
+
async _replayAndInterruptAgentToolRun(row, message, extra) {
|
|
4495
4596
|
let sequence = 1;
|
|
4496
4597
|
try {
|
|
4497
4598
|
sequence = await this._broadcastAgentToolStoredChunks(row, sequence);
|
|
@@ -4500,12 +4601,53 @@ var Agent = class Agent extends Server {
|
|
|
4500
4601
|
runId: row.run_id,
|
|
4501
4602
|
agentType: row.agent_type,
|
|
4502
4603
|
status: "interrupted",
|
|
4503
|
-
error: message
|
|
4604
|
+
error: message,
|
|
4605
|
+
...extra?.reason !== void 0 ? { reason: extra.reason } : {},
|
|
4606
|
+
...extra?.childStillRunning !== void 0 ? { childStillRunning: extra.childStillRunning } : {}
|
|
4504
4607
|
};
|
|
4505
4608
|
await this._finishAgentToolRun(this._agentToolRunInfoFromRow(row), result, { sequence });
|
|
4506
4609
|
return result;
|
|
4507
4610
|
}
|
|
4508
4611
|
/**
|
|
4612
|
+
* Human-readable prose for an `interrupted` seal. Kept in sync with
|
|
4613
|
+
* {@link AgentToolInterruptedReason}; callers branch on the typed `reason`
|
|
4614
|
+
* field, not this string.
|
|
4615
|
+
*/
|
|
4616
|
+
_interruptedMessageForReason(reason) {
|
|
4617
|
+
switch (reason) {
|
|
4618
|
+
case "no-progress": return "Agent tool run was still running but made no forward progress within the re-attach no-progress budget; the parent gave up.";
|
|
4619
|
+
case "window-exceeded": return "Agent tool run did not reach a terminal result within the maximum re-attach window; the parent gave up.";
|
|
4620
|
+
case "not-tailable": return "Agent tool run was still running, but live-tail reattachment is not supported in this runtime.";
|
|
4621
|
+
case "inspect-timeout": return "Agent tool run inspection timed out during parent recovery.";
|
|
4622
|
+
case "inspect-failed": return "Agent tool run could not be inspected during parent recovery.";
|
|
4623
|
+
case "recovery-deadline": return "Agent tool run recovery deadline exceeded.";
|
|
4624
|
+
default: return "Agent tool run was still running and did not reach a terminal result.";
|
|
4625
|
+
}
|
|
4626
|
+
}
|
|
4627
|
+
/**
|
|
4628
|
+
* Tear down a child agent-tool run the parent has genuinely given up on
|
|
4629
|
+
* (#1630 follow-up). Teardown is scoped to `window-exceeded` ONLY — the hard
|
|
4630
|
+
* ceiling, where the child has had its full recovery window and is therefore
|
|
4631
|
+
* truly exhausted, so cancelling it reclaims its fiber / keep-alive. Every
|
|
4632
|
+
* other give-up is deliberately left repairable: `no-progress` seals stay
|
|
4633
|
+
* SOFT (`interrupted`, `childStillRunning: true`) so a re-issue can still
|
|
4634
|
+
* re-attach and collect the child if it self-heals — tearing those down would
|
|
4635
|
+
* defeat the repair-on-re-issue path and convert a retryable interrupt into a
|
|
4636
|
+
* non-retryable `aborted`. Reasons where the child's state is unknown
|
|
4637
|
+
* (`inspect-*`, `recovery-deadline`, `not-tailable`) are also left alone.
|
|
4638
|
+
* Returns whether the child was torn down (so the caller reports
|
|
4639
|
+
* `childStillRunning: false`).
|
|
4640
|
+
*/
|
|
4641
|
+
async _teardownGivenUpAgentToolChild(adapter, runId, reason) {
|
|
4642
|
+
if (reason !== "window-exceeded") return false;
|
|
4643
|
+
try {
|
|
4644
|
+
await adapter.cancelAgentToolRun(runId, `agent tool run given up by parent recovery: ${reason}`);
|
|
4645
|
+
return true;
|
|
4646
|
+
} catch {
|
|
4647
|
+
return false;
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
/**
|
|
4509
4651
|
* Re-attach to a still-running child agent-tool run and tail it to its real
|
|
4510
4652
|
* terminal result, instead of abandoning it as `interrupted` (#1630). The
|
|
4511
4653
|
* child is a separate facet with its own `chatRecovery`, so resolving it via
|
|
@@ -4513,54 +4655,98 @@ var Agent = class Agent extends Server {
|
|
|
4513
4655
|
* its live stream (forwarding chunks to the parent's connections) until it
|
|
4514
4656
|
* reaches terminal, then inspect for the collected result.
|
|
4515
4657
|
*
|
|
4516
|
-
*
|
|
4517
|
-
* advancing
|
|
4518
|
-
*
|
|
4519
|
-
*
|
|
4658
|
+
* The wait is PROGRESS-KEYED, not a flat wall clock (which previously abandoned
|
|
4659
|
+
* healthy, still-advancing children whose recovery simply outran a fixed
|
|
4660
|
+
* budget). `noProgressTimeoutMs` bounds how long the parent waits with NO
|
|
4661
|
+
* forward progress; it is reset on every forwarded chunk. As long as the child
|
|
4662
|
+
* keeps streaming it is followed through to terminal. The loop also RE-ARMS
|
|
4663
|
+
* across stream-closes (a child re-evicted mid-recovery, or a tail that ends
|
|
4664
|
+
* before terminal) as long as the prior attempt made progress, so a child that
|
|
4665
|
+
* dies and recovers again during deploy churn is still collected. A genuinely
|
|
4666
|
+
* silent/hung child can never block recovery forever: it seals `interrupted`
|
|
4667
|
+
* after one `noProgressTimeoutMs` window. `maxWindowMs` is an OPTIONAL hard
|
|
4668
|
+
* wall-clock ceiling (default `Infinity` — uncapped, mirroring #1672's
|
|
4669
|
+
* `maxRecoveryWork`); set it finite to also bound a child that keeps
|
|
4670
|
+
* progressing, which seals `window-exceeded` and tears the child down.
|
|
4520
4671
|
*
|
|
4521
4672
|
* Returns the terminal `result` (and `completedAt`) when the child reaches a
|
|
4522
|
-
* terminal status
|
|
4523
|
-
*
|
|
4524
|
-
*
|
|
4673
|
+
* terminal status, plus the advanced broadcast `sequence`. Returns
|
|
4674
|
+
* `{ result: undefined }` when there is no `tailAgentToolRun` adapter, the
|
|
4675
|
+
* child makes no progress within a full no-progress window, or the ceiling is
|
|
4676
|
+
* reached while the child is still non-terminal — the caller then seals
|
|
4677
|
+
* `interrupted`.
|
|
4525
4678
|
*/
|
|
4526
|
-
async _reattachAgentToolRunToTerminal(adapter, row, sequence,
|
|
4527
|
-
if (typeof adapter.tailAgentToolRun !== "function") return {
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
else if (budgetMs <= 0) controller.abort();
|
|
4679
|
+
async _reattachAgentToolRunToTerminal(adapter, row, sequence, noProgressTimeoutMs = DEFAULT_AGENT_TOOL_REATTACH_NO_PROGRESS_TIMEOUT_MS, maxWindowMs = DEFAULT_AGENT_TOOL_REATTACH_MAX_WINDOW_MS) {
|
|
4680
|
+
if (typeof adapter.tailAgentToolRun !== "function") return {
|
|
4681
|
+
sequence,
|
|
4682
|
+
reason: "not-tailable"
|
|
4683
|
+
};
|
|
4532
4684
|
this._emit("agent_tool:recovery:reattach", {
|
|
4533
4685
|
runId: row.run_id,
|
|
4534
4686
|
agentType: row.agent_type,
|
|
4535
|
-
budgetMs
|
|
4687
|
+
budgetMs: noProgressTimeoutMs
|
|
4536
4688
|
});
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
let afterSequence = -1;
|
|
4689
|
+
const collectTerminal = async (seq) => {
|
|
4690
|
+
let inspection = null;
|
|
4540
4691
|
try {
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
}
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4692
|
+
inspection = await adapter.inspectAgentToolRun(row.run_id);
|
|
4693
|
+
} catch {
|
|
4694
|
+
return null;
|
|
4695
|
+
}
|
|
4696
|
+
if (inspection && inspection.status !== "running" && inspection.status !== "starting") return {
|
|
4697
|
+
sequence: seq,
|
|
4698
|
+
result: this._terminalResultFromInspection(row.agent_type, inspection),
|
|
4699
|
+
completedAt: inspection.completedAt
|
|
4700
|
+
};
|
|
4701
|
+
return null;
|
|
4702
|
+
};
|
|
4703
|
+
let nextSequence = sequence;
|
|
4704
|
+
if (!(noProgressTimeoutMs > 0)) return await collectTerminal(nextSequence) ?? {
|
|
4705
|
+
sequence: nextSequence,
|
|
4706
|
+
reason: "no-progress"
|
|
4707
|
+
};
|
|
4708
|
+
const ceilingController = new AbortController();
|
|
4709
|
+
let ceilingTimer;
|
|
4710
|
+
if (maxWindowMs > 0 && Number.isFinite(maxWindowMs)) ceilingTimer = setTimeout(() => ceilingController.abort(), maxWindowMs);
|
|
4711
|
+
let reason = "no-progress";
|
|
4550
4712
|
try {
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4713
|
+
while (!ceilingController.signal.aborted) {
|
|
4714
|
+
let afterSequence = -1;
|
|
4715
|
+
try {
|
|
4716
|
+
const existing = await adapter.getAgentToolChunks(row.run_id);
|
|
4717
|
+
const last = existing[existing.length - 1];
|
|
4718
|
+
if (last) afterSequence = last.sequence;
|
|
4719
|
+
} catch {}
|
|
4720
|
+
const beforeSequence = nextSequence;
|
|
4721
|
+
let streamEnded = "idle";
|
|
4722
|
+
try {
|
|
4723
|
+
const stream = await adapter.tailAgentToolRun(row.run_id, { afterSequence });
|
|
4724
|
+
const forwarded = await this._forwardAgentToolStream(stream, row.parent_tool_call_id ?? void 0, row.run_id, nextSequence, ceilingController.signal, noProgressTimeoutMs);
|
|
4725
|
+
nextSequence = forwarded.next;
|
|
4726
|
+
streamEnded = forwarded.ended;
|
|
4727
|
+
} catch {}
|
|
4728
|
+
const terminal = await collectTerminal(nextSequence);
|
|
4729
|
+
if (terminal) return terminal;
|
|
4730
|
+
if (ceilingController.signal.aborted) {
|
|
4731
|
+
reason = "window-exceeded";
|
|
4732
|
+
break;
|
|
4733
|
+
}
|
|
4734
|
+
if (streamEnded !== "done") break;
|
|
4735
|
+
if (nextSequence <= beforeSequence) break;
|
|
4736
|
+
}
|
|
4737
|
+
} finally {
|
|
4738
|
+
if (ceilingTimer !== void 0) clearTimeout(ceilingTimer);
|
|
4739
|
+
}
|
|
4740
|
+
return {
|
|
4554
4741
|
sequence: nextSequence,
|
|
4555
|
-
|
|
4556
|
-
completedAt: inspection.completedAt
|
|
4742
|
+
reason
|
|
4557
4743
|
};
|
|
4558
|
-
return { sequence: nextSequence };
|
|
4559
4744
|
}
|
|
4560
4745
|
async _replayAgentToolRuns(connection) {
|
|
4561
4746
|
const rows = this.sql`
|
|
4562
4747
|
SELECT run_id, parent_tool_call_id, agent_type, input_preview, status,
|
|
4563
|
-
summary, output_json, error_message,
|
|
4748
|
+
summary, output_json, error_message, interrupted_reason,
|
|
4749
|
+
child_still_running, display_metadata, display_order
|
|
4564
4750
|
FROM cf_agent_tool_runs
|
|
4565
4751
|
ORDER BY started_at ASC
|
|
4566
4752
|
`;
|
|
@@ -4584,19 +4770,22 @@ var Agent = class Agent extends Server {
|
|
|
4584
4770
|
status: row.status,
|
|
4585
4771
|
output: this._parseAgentToolJson(row.output_json),
|
|
4586
4772
|
summary: row.summary ?? void 0,
|
|
4587
|
-
error: row.error_message ?? void 0
|
|
4773
|
+
error: row.error_message ?? void 0,
|
|
4774
|
+
...this._agentToolInterruptedExtrasFromRow(row)
|
|
4588
4775
|
}, true, connection);
|
|
4589
4776
|
}
|
|
4590
4777
|
}
|
|
4591
4778
|
async _reconcileAgentToolRuns(options) {
|
|
4592
|
-
const reattachTimeoutMs = options?.reattachTimeoutMs ??
|
|
4779
|
+
const reattachTimeoutMs = options?.reattachTimeoutMs ?? this._resolvedOptions.agentToolReattachNoProgressTimeoutMs;
|
|
4780
|
+
const reattachMaxWindowMs = options?.reattachMaxWindowMs ?? this._resolvedOptions.agentToolReattachMaxWindowMs;
|
|
4593
4781
|
const startedAt = Date.now();
|
|
4594
4782
|
const totalTimeoutMs = options?.totalRecoveryTimeoutMs ?? DEFAULT_AGENT_TOOL_RECOVERY_TOTAL_TIMEOUT_MS;
|
|
4595
4783
|
const deadlineAt = totalTimeoutMs > 0 ? startedAt + totalTimeoutMs : Number.POSITIVE_INFINITY;
|
|
4596
4784
|
const deferredFinishes = [];
|
|
4597
4785
|
const rows = this.sql`
|
|
4598
4786
|
SELECT run_id, parent_tool_call_id, agent_type, input_preview, status,
|
|
4599
|
-
summary, output_json, error_message,
|
|
4787
|
+
summary, output_json, error_message, interrupted_reason,
|
|
4788
|
+
child_still_running, display_metadata, display_order,
|
|
4600
4789
|
started_at, completed_at
|
|
4601
4790
|
FROM cf_agent_tool_runs
|
|
4602
4791
|
WHERE status IN ('starting', 'running')
|
|
@@ -4637,7 +4826,8 @@ var Agent = class Agent extends Server {
|
|
|
4637
4826
|
runId: row.run_id,
|
|
4638
4827
|
agentType: row.agent_type,
|
|
4639
4828
|
status: "interrupted",
|
|
4640
|
-
|
|
4829
|
+
reason: "recovery-deadline",
|
|
4830
|
+
error: this._interruptedMessageForReason("recovery-deadline")
|
|
4641
4831
|
}, sequence, void 0);
|
|
4642
4832
|
continue;
|
|
4643
4833
|
}
|
|
@@ -4645,12 +4835,16 @@ var Agent = class Agent extends Server {
|
|
|
4645
4835
|
const boundedChildTimeout = childTimeout > 0 ? Math.min(childTimeout, remainingMs) : remainingMs;
|
|
4646
4836
|
const recovery = await this._inspectAgentToolRunForRecovery(row, sequence, boundedChildTimeout);
|
|
4647
4837
|
if (recovery.status !== "inspected") {
|
|
4648
|
-
await finalizeRow(row, {
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4838
|
+
await finalizeRow(row, (() => {
|
|
4839
|
+
const reason = recovery.status === "timed-out" ? "inspect-timeout" : "inspect-failed";
|
|
4840
|
+
return {
|
|
4841
|
+
runId: row.run_id,
|
|
4842
|
+
agentType: row.agent_type,
|
|
4843
|
+
status: "interrupted",
|
|
4844
|
+
reason,
|
|
4845
|
+
error: this._interruptedMessageForReason(reason)
|
|
4846
|
+
};
|
|
4847
|
+
})(), sequence, void 0);
|
|
4654
4848
|
continue;
|
|
4655
4849
|
}
|
|
4656
4850
|
const inspection = recovery.inspection;
|
|
@@ -4670,17 +4864,26 @@ var Agent = class Agent extends Server {
|
|
|
4670
4864
|
runId: row.run_id,
|
|
4671
4865
|
agentType: row.agent_type,
|
|
4672
4866
|
status: "interrupted",
|
|
4673
|
-
|
|
4867
|
+
reason: "not-tailable",
|
|
4868
|
+
childStillRunning: true,
|
|
4869
|
+
error: this._interruptedMessageForReason("not-tailable")
|
|
4674
4870
|
}, sequenceAfterReplay, void 0);
|
|
4675
4871
|
else await finalizeRow(row, this._terminalResultFromInspection(row.agent_type, inspection), sequenceAfterReplay, inspection.completedAt);
|
|
4676
4872
|
}
|
|
4677
4873
|
await Promise.all(reattachQueue.map(async ({ row, adapter }) => {
|
|
4678
|
-
const reattach = await this._reattachAgentToolRunToTerminal(adapter, row, 1, reattachTimeoutMs);
|
|
4679
|
-
|
|
4874
|
+
const reattach = await this._reattachAgentToolRunToTerminal(adapter, row, 1, reattachTimeoutMs, reattachMaxWindowMs);
|
|
4875
|
+
if (reattach.result) {
|
|
4876
|
+
await finalizeRow(row, reattach.result, reattach.sequence, reattach.completedAt);
|
|
4877
|
+
return;
|
|
4878
|
+
}
|
|
4879
|
+
const tornDown = await this._teardownGivenUpAgentToolChild(adapter, row.run_id, reattach.reason);
|
|
4880
|
+
await finalizeRow(row, {
|
|
4680
4881
|
runId: row.run_id,
|
|
4681
4882
|
agentType: row.agent_type,
|
|
4682
4883
|
status: "interrupted",
|
|
4683
|
-
|
|
4884
|
+
reason: reattach.reason,
|
|
4885
|
+
childStillRunning: !tornDown,
|
|
4886
|
+
error: this._interruptedMessageForReason(reattach.reason)
|
|
4684
4887
|
}, reattach.sequence, reattach.completedAt);
|
|
4685
4888
|
}));
|
|
4686
4889
|
this._emit("agent_tool:recovery:complete", {
|
|
@@ -4720,6 +4923,7 @@ var Agent = class Agent extends Server {
|
|
|
4720
4923
|
childInspectionTimeoutMs: options?.childInspectionTimeoutMs,
|
|
4721
4924
|
totalRecoveryTimeoutMs: options?.totalRecoveryTimeoutMs,
|
|
4722
4925
|
reattachTimeoutMs: options?.reattachTimeoutMs,
|
|
4926
|
+
reattachMaxWindowMs: options?.reattachMaxWindowMs,
|
|
4723
4927
|
runIds: options?.runIds
|
|
4724
4928
|
});
|
|
4725
4929
|
await this._runDeferredAgentToolFinishHooks(recoveredAgentToolFinishes);
|