agents 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-routing-B2XLNMxq.d.ts → agent-routing-0DR0Tk2v.d.ts} +205 -132
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-routing.js.map +1 -1
- package/dist/agent-tool-types.d.ts +28 -22
- package/dist/agent-tool-types.js +23 -1
- package/dist/agent-tool-types.js.map +1 -1
- package/dist/{agent-tools-y7zLfw4Q.js → agent-tools-CdJC-8Dc.js} +72 -9
- package/dist/agent-tools-CdJC-8Dc.js.map +1 -0
- package/dist/{agent-tools-Dj5Mzlw7.d.ts → agent-tools-YrATZJu2.d.ts} +34 -20
- package/dist/agent-tools.d.ts +20 -18
- package/dist/agent-tools.js.map +1 -1
- package/dist/ai-fm7xx1BK.js +312 -0
- package/dist/ai-fm7xx1BK.js.map +1 -0
- package/dist/base64-redaction-C1Uu29t5.js +59 -0
- package/dist/base64-redaction-C1Uu29t5.js.map +1 -0
- package/dist/browser/ai-sdk.d.ts +90 -0
- package/dist/browser/ai-sdk.js +51 -0
- package/dist/browser/ai-sdk.js.map +1 -0
- package/dist/browser/ai.d.ts +4 -4
- package/dist/browser/ai.js +1 -347
- package/dist/browser/index.d.ts +81 -79
- package/dist/browser/index.js +361 -2
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/tanstack-ai.d.ts +96 -1
- package/dist/browser/tanstack-ai.js +62 -2
- package/dist/browser/tanstack-ai.js.map +1 -1
- package/dist/browser-DE3d-RLk.d.ts +275 -0
- package/dist/browser-tool-CQ10e6Kj.js +480 -0
- package/dist/browser-tool-CQ10e6Kj.js.map +1 -0
- package/dist/browser-tool-DuNdlwZ9.d.ts +73 -0
- package/dist/capability-B4WbF81e.js.map +1 -1
- package/dist/{capability-runner-BUBa6Ake.d.ts → capability-runner-DBAnGr6L.d.ts} +7 -2
- package/dist/chat/index.d.ts +340 -234
- package/dist/chat/index.js +592 -66
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +42 -2
- package/dist/chat/react.js +191 -35
- package/dist/chat/react.js.map +1 -1
- package/dist/chat/transport.d.ts +1 -1
- package/dist/chat/transport.js +1 -1
- package/dist/chat-sdk/index.d.ts +17 -3
- package/dist/chat-sdk/index.js +28 -2
- package/dist/chat-sdk/index.js.map +1 -1
- package/dist/{client-C9DAjZIY.js → client-4OlMIJx-.js} +102 -29
- package/dist/client-4OlMIJx-.js.map +1 -0
- package/dist/{client-BxdkCuVy.d.ts → client-je3koD9Z.d.ts} +45 -10
- package/dist/client.d.ts +7 -5
- package/dist/client.js +2 -2
- package/dist/{connector-CptFKzRh.js → connector-58XDGvc3.js} +251 -120
- package/dist/connector-58XDGvc3.js.map +1 -0
- package/dist/{connector-CkQD4MK3.d.ts → connector-Cl-VqPmA.d.ts} +244 -146
- package/dist/context/index.d.ts +29 -0
- package/dist/context/index.js +64 -17
- package/dist/context/index.js.map +1 -1
- package/dist/current-agent-DhoDkSnH.js.map +1 -1
- package/dist/{current-agent-C4w86kcN.d.ts → current-agent-vAk_5JMt.d.ts} +4 -4
- package/dist/{durable-object-lifecycle-ei7M7lqB.d.ts → durable-object-lifecycle-HhgOMWq9.d.ts} +15 -7
- package/dist/harnesses/pi/index.d.ts +348 -0
- package/dist/harnesses/pi/index.js +754 -0
- package/dist/harnesses/pi/index.js.map +1 -0
- package/dist/images-iiTDSyRu.js +1631 -0
- package/dist/images-iiTDSyRu.js.map +1 -0
- package/dist/{index-Dlgtd3Mj.d.ts → index-BreL0YrQ.d.ts} +2 -2
- package/dist/index-kbSUIer3.d.ts +343 -0
- package/dist/index.d.ts +46 -44
- package/dist/index.js +1 -1
- package/dist/internal_context.d.ts +1 -1
- package/dist/lifecycle/index.d.ts +3 -3
- package/dist/lifecycle/index.js +1 -1
- package/dist/{lifecycle-Mm_jQh7r.js → lifecycle-CFu6OV03.js} +39 -10
- package/dist/{lifecycle-Mm_jQh7r.js.map → lifecycle-CFu6OV03.js.map} +1 -1
- package/dist/mcp/client/index.d.ts +20 -20
- package/dist/mcp/client/x402.js +21 -19
- package/dist/mcp/client/x402.js.map +1 -1
- package/dist/mcp/index.d.ts +35 -35
- package/dist/mcp/index.js +1 -1
- package/dist/{message-builder-BymO4N_D.js → message-builder-DAl9AhHH.js} +89 -4
- package/dist/message-builder-DAl9AhHH.js.map +1 -0
- package/dist/models/ai-sdk/index.d.ts +353 -0
- package/dist/models/ai-sdk/index.js +2443 -0
- package/dist/models/ai-sdk/index.js.map +1 -0
- package/dist/models/pi-ai/index.d.ts +313 -0
- package/dist/models/pi-ai/index.js +1795 -0
- package/dist/models/pi-ai/index.js.map +1 -0
- package/dist/observability/ai/index.js +20 -4
- package/dist/observability/ai/index.js.map +1 -1
- package/dist/{protocol-B0nh6KNf.js → protocol-kHsr-f0X.js} +26 -12
- package/dist/{protocol-B0nh6KNf.js.map → protocol-kHsr-f0X.js.map} +1 -1
- package/dist/queue/index.d.ts +3 -3
- package/dist/queue/index.js +1 -1
- package/dist/{queue-BC9F5cUo.js → queue-BB-zfIYF.js} +2 -2
- package/dist/{queue-BC9F5cUo.js.map → queue-BB-zfIYF.js.map} +1 -1
- package/dist/react.d.ts +6 -6
- package/dist/react.js +160 -64
- package/dist/react.js.map +1 -1
- package/dist/{retries-D9B2UCq3.d.ts → retries-CV6AkXmQ.d.ts} +18 -9
- package/dist/retries.d.ts +11 -9
- package/dist/retries.js +11 -1
- package/dist/retries.js.map +1 -1
- package/dist/routing/index.d.ts +2 -2
- package/dist/routing/index.js +1 -1
- package/dist/{scheduler-D_KHqxBa.js → scheduler-DZ3xQfeK.js} +2 -2
- package/dist/{scheduler-D_KHqxBa.js.map → scheduler-DZ3xQfeK.js.map} +1 -1
- package/dist/{scheduler-BGq6M5Kd.d.ts → scheduler-RdACNXDP.d.ts} +3 -3
- package/dist/schedules/index.d.ts +1 -1
- package/dist/schedules/index.js +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/sessions/index.d.ts +70 -3
- package/dist/sessions/index.js +276 -67
- package/dist/sessions/index.js.map +1 -1
- package/dist/skills/index.d.ts +29 -314
- package/dist/socket-address.d.ts +16 -0
- package/dist/socket-address.js +19 -0
- package/dist/socket-address.js.map +1 -0
- package/dist/{src-BNU3ZiJM.js → src-BZeu-SCD.js} +423 -115
- package/dist/src-BZeu-SCD.js.map +1 -0
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.js +1 -1
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.js +1 -1
- package/dist/{streams-BcE8JP2X.d.ts → streams-Cmkj9QfW.d.ts} +4 -2
- package/dist/{streams-CCPRV6dt.js → streams-DW-UCOUc.js} +9 -2
- package/dist/streams-DW-UCOUc.js.map +1 -0
- package/dist/sub-routing.d.ts +12 -12
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.js +1 -1
- package/dist/{tasks-D4nLqVSI.js → tasks-68DESxf0.js} +2 -2
- package/dist/{tasks-D4nLqVSI.js.map → tasks-68DESxf0.js.map} +1 -1
- package/dist/{tasks-V2lCT8ZV.d.ts → tasks-9YxYtByh.d.ts} +2 -2
- package/dist/transport-PfFnt-Ld.d.ts +525 -0
- package/dist/{types-DCD6BNZH.d.ts → types-BA4anrjI.d.ts} +2 -2
- package/dist/voice/index.d.ts +2 -2
- package/dist/websockets/index.d.ts +23 -6
- package/dist/websockets/index.js +1 -1
- package/dist/{websockets-D7IzWbZb.js → websockets-Ci-LZFHH.js} +45 -20
- package/dist/{websockets-D7IzWbZb.js.map → websockets-Ci-LZFHH.js.map} +1 -1
- package/dist/wire-types-CnMt6_HR.js.map +1 -1
- package/dist/wire-types-CrjKvDyi.d.ts +300 -0
- package/dist/workflow-types.d.ts +25 -25
- package/dist/workflows.d.ts +21 -21
- package/dist/workflows.js +1 -1
- package/dist/{ws-chat-transport-UNRIS2xl.d.ts → ws-chat-transport-BbT1A5Lc.d.ts} +51 -2
- package/dist/{ws-chat-transport-rWwta645.js → ws-chat-transport-cqMKq3IY.js} +143 -16
- package/dist/ws-chat-transport-cqMKq3IY.js.map +1 -0
- package/docs/agent-tools.md +29 -4
- package/docs/browse-the-web.md +87 -5
- package/docs/chat-agents.md +124 -16
- package/docs/context.md +27 -0
- package/docs/durable-execution.md +2 -0
- package/docs/harnesses/pi.md +91 -0
- package/docs/human-in-the-loop.md +4 -0
- package/docs/index.md +3 -0
- package/docs/lifecycle.md +20 -4
- package/docs/models-pi-ai.md +325 -0
- package/docs/models.md +504 -0
- package/docs/resumable-streaming.md +2 -0
- package/docs/routing.md +13 -13
- package/docs/sessions.md +36 -1
- package/docs/state.md +1 -0
- package/docs/sub-agents.md +9 -0
- package/package.json +40 -2
- package/dist/agent-tools-y7zLfw4Q.js.map +0 -1
- package/dist/browser/ai.js.map +0 -1
- package/dist/client-C9DAjZIY.js.map +0 -1
- package/dist/client-tools-aIBO0Fk7.d.ts +0 -53
- package/dist/connector-CptFKzRh.js.map +0 -1
- package/dist/message-builder-BymO4N_D.js.map +0 -1
- package/dist/src-BNU3ZiJM.js.map +0 -1
- package/dist/streams-CCPRV6dt.js.map +0 -1
- package/dist/ws-chat-transport-rWwta645.js.map +0 -1
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import { camelCaseToKebabCase, isInternalJsStubProp } from "./utils.js";
|
|
2
2
|
import { getAgentByName } from "./agent-routing.js";
|
|
3
|
-
import { AGENT_TOOL_MILESTONE_PART } from "./agent-tool-types.js";
|
|
3
|
+
import { AGENT_TOOL_MILESTONE_PART, isAgentToolLifecycleChunk } from "./agent-tool-types.js";
|
|
4
4
|
import { n as getCurrentAgent$1, t as __DO_NOT_USE_WILL_BREAK__agentContext } from "./current-agent-DhoDkSnH.js";
|
|
5
5
|
import "./internal_context.js";
|
|
6
6
|
import { copyCallableMetadata, decoratedMethods, getCallableMetadata, isCallableMethod } from "./callable-decorator.js";
|
|
7
7
|
import "./types.js";
|
|
8
8
|
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
|
|
9
|
+
import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
|
|
9
10
|
import { signAgentHeaders } from "./email.js";
|
|
10
11
|
import { sendAgentEmail } from "./email-send.js";
|
|
11
12
|
import { n as withInvocationScope, r as writeSpanAttributes, t as tracer } from "./cloudflare-Dzvc7V2N.js";
|
|
12
13
|
import { parseSubAgentPath } from "./sub-routing.js";
|
|
13
|
-
import { a as getConnectionFlag, c as isConnectionReadonly, d as setConnectionProtocolEnabled, f as setConnectionReadonly, i as ensureConnectionWrapped, l as registerInternalConnectionKeys, o as getConnectionRawState, s as isConnectionProtocolEnabled, t as WebSockets, u as setConnectionFlag } from "./websockets-
|
|
14
|
+
import { a as getConnectionFlag, c as isConnectionReadonly, d as setConnectionProtocolEnabled, f as setConnectionReadonly, i as ensureConnectionWrapped, l as registerInternalConnectionKeys, o as getConnectionRawState, s as isConnectionProtocolEnabled, t as WebSockets, u as setConnectionFlag } from "./websockets-Ci-LZFHH.js";
|
|
14
15
|
import { t as LifecycleCapability } from "./capability-B4WbF81e.js";
|
|
15
|
-
import { t as
|
|
16
|
-
import { a as abortWithoutAlarmRetry, i as setLifecycleRouteTransport, n as setLifecycleEventSink, r as setLifecycleHostInvoker, t as Lifecycle } from "./lifecycle-Mm_jQh7r.js";
|
|
16
|
+
import { a as abortWithoutAlarmRetry, i as setLifecycleRouteTransport, n as setLifecycleEventSink, r as setLifecycleHostInvoker, t as Lifecycle } from "./lifecycle-CFu6OV03.js";
|
|
17
17
|
import { isErrorRetryable, tryN, validateRetryOptions } from "./retries.js";
|
|
18
18
|
import { SqlError } from "./sql-error.js";
|
|
19
19
|
import { a as ensureMcpServerTable, d as DisposableStore, i as normalizeServerId, l as RPC_DO_PREFIX, o as MCPConnectionState, t as MCPClientManager } from "./client-fyQrLGkD.js";
|
|
20
20
|
import { DurableObjectOAuthClientProvider } from "./mcp/client/do-oauth-client-provider.js";
|
|
21
21
|
import { genericObservability } from "./observability/index.js";
|
|
22
|
-
import { n as setSchedulerCallbackResolver, t as Scheduler } from "./scheduler-
|
|
23
|
-
import { n as setQueueCallbackResolver, t as Queue } from "./queue-
|
|
24
|
-
import { n as setTaskDefinitionResolver, r as setTaskRoutedMemoryLimitHandler, t as Tasks } from "./tasks-
|
|
22
|
+
import { n as setSchedulerCallbackResolver, t as Scheduler } from "./scheduler-DZ3xQfeK.js";
|
|
23
|
+
import { n as setQueueCallbackResolver, t as Queue } from "./queue-BB-zfIYF.js";
|
|
24
|
+
import { n as setTaskDefinitionResolver, r as setTaskRoutedMemoryLimitHandler, t as Tasks } from "./tasks-68DESxf0.js";
|
|
25
25
|
import { State } from "./state/index.js";
|
|
26
26
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
27
27
|
import { DurableObject, RpcTarget, exports } from "cloudflare:workers";
|
|
@@ -296,12 +296,47 @@ function _addColumnIfNotExists(sql) {
|
|
|
296
296
|
*/
|
|
297
297
|
const CF_SUB_AGENT_OUTER_URL_KEY = "_cf_subAgentOuterUrl";
|
|
298
298
|
const CF_SUB_AGENT_TAGS_KEY = "_cf_subAgentTags";
|
|
299
|
+
/**
|
|
300
|
+
* Set on a socket closed because its sub-agent was deleted. Its late
|
|
301
|
+
* message/close events are dropped, so they can't reach a same-name
|
|
302
|
+
* replacement created after the delete. Storage-frozen — never rename.
|
|
303
|
+
*/
|
|
304
|
+
const CF_SUB_AGENT_DELETED_KEY = "_cf_subAgentDeleted";
|
|
299
305
|
/** Wire-frozen internal header carrying the outer URL on WS upgrades. */
|
|
300
306
|
const SUB_AGENT_OUTER_URL_HEADER = "x-cf-agents-subagent-url";
|
|
307
|
+
/**
|
|
308
|
+
* The close frame a rejected sub-agent WebSocket receives in place of the
|
|
309
|
+
* `onBeforeSubAgent` response, which a browser cannot read from a failed
|
|
310
|
+
* handshake. A 4xx closes with `4000 + status`, which clients treat as
|
|
311
|
+
* final; anything else closes with 1011 so the client retries.
|
|
312
|
+
*/
|
|
313
|
+
function subAgentRejectionClose(response) {
|
|
314
|
+
const { status } = response;
|
|
315
|
+
return {
|
|
316
|
+
code: status >= 400 && status < 500 ? 4e3 + status : 1011,
|
|
317
|
+
reason: `Sub-agent connection rejected (${status})`
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Upgrade a rejected sub-agent WebSocket only to close it, so the client
|
|
322
|
+
* sees a close frame instead of a failed handshake that reconnects forever.
|
|
323
|
+
*/
|
|
324
|
+
function rejectSubAgentWebSocket(response) {
|
|
325
|
+
const { code, reason } = subAgentRejectionClose(response);
|
|
326
|
+
const [client, server] = Object.values(new WebSocketPair());
|
|
327
|
+
server.accept();
|
|
328
|
+
server.close(code, reason);
|
|
329
|
+
return new Response(null, {
|
|
330
|
+
status: 101,
|
|
331
|
+
webSocket: client
|
|
332
|
+
});
|
|
333
|
+
}
|
|
301
334
|
var _host = /* @__PURE__ */ new WeakMap();
|
|
302
335
|
var _facetKeepAliveTokens = /* @__PURE__ */ new WeakMap();
|
|
303
336
|
var _bridgeContext = /* @__PURE__ */ new WeakMap();
|
|
304
337
|
var _virtualConnections = /* @__PURE__ */ new WeakMap();
|
|
338
|
+
var _virtualConnectionsHydrated = /* @__PURE__ */ new WeakMap();
|
|
339
|
+
var _virtualConnectionsHydration = /* @__PURE__ */ new WeakMap();
|
|
305
340
|
var _connectionOperationTails = /* @__PURE__ */ new WeakMap();
|
|
306
341
|
var _broadcastOperationTail = /* @__PURE__ */ new WeakMap();
|
|
307
342
|
var _DynamicAgentsInternal_brand = /* @__PURE__ */ new WeakSet();
|
|
@@ -335,6 +370,8 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
335
370
|
_classPrivateFieldInitSpec(this, _facetKeepAliveTokens, /* @__PURE__ */ new Set());
|
|
336
371
|
_classPrivateFieldInitSpec(this, _bridgeContext, new AsyncLocalStorage());
|
|
337
372
|
_classPrivateFieldInitSpec(this, _virtualConnections, /* @__PURE__ */ new Map());
|
|
373
|
+
_classPrivateFieldInitSpec(this, _virtualConnectionsHydrated, false);
|
|
374
|
+
_classPrivateFieldInitSpec(this, _virtualConnectionsHydration, void 0);
|
|
338
375
|
_classPrivateFieldInitSpec(this, _connectionOperationTails, /* @__PURE__ */ new Map());
|
|
339
376
|
_classPrivateFieldInitSpec(this, _broadcastOperationTail, void 0);
|
|
340
377
|
_classPrivateFieldSet2(_host, this, host);
|
|
@@ -389,7 +426,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
389
426
|
if (!_classPrivateFieldGet2(_host, this).hasSubAgent(next.className, next.name)) {
|
|
390
427
|
const stalePath = targetPath.slice(0, selfPath.length + 1);
|
|
391
428
|
if (_classPrivateFieldGet2(_host, this)._isFacet) await (await this.rootAlarmOwner())._cf_cleanupFacetPrefix(stalePath);
|
|
392
|
-
else await
|
|
429
|
+
else await this.cleanupPrefix(stalePath);
|
|
393
430
|
return false;
|
|
394
431
|
}
|
|
395
432
|
return (await _classPrivateFieldGet2(_host, this)._cf_resolveSubAgent(next.className, next.name))._cf_routeLifecycle(target, envelope);
|
|
@@ -403,7 +440,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
403
440
|
if (!root) throw new Error("Facet routing requires a root parent.");
|
|
404
441
|
const binding = _classPrivateFieldGet2(_host, this).ctx.exports?.[root.className];
|
|
405
442
|
if (!binding) throw new Error(`Unable to resolve root "${root.className}" for facet routing.`);
|
|
406
|
-
return
|
|
443
|
+
return binding.get(binding.idFromName(root.name));
|
|
407
444
|
}
|
|
408
445
|
rootResolvesToSelf() {
|
|
409
446
|
const root = _classPrivateFieldGet2(_host, this)._parentPath[0];
|
|
@@ -505,6 +542,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
505
542
|
* rows on the target facet after recovery.
|
|
506
543
|
*/
|
|
507
544
|
async checkRunFibersAtPath(ownerPath) {
|
|
545
|
+
await _classPrivateFieldGet2(_host, this).__unsafe_ensureInitialized();
|
|
508
546
|
const selfPath = _classPrivateFieldGet2(_host, this).selfPath;
|
|
509
547
|
if (!_classPrivateFieldGet2(_host, this)._isSameAgentPathPrefix(selfPath, ownerPath)) throw new Error(`Facet fiber owner path does not descend from ${JSON.stringify(selfPath)}.`);
|
|
510
548
|
if (selfPath.length === ownerPath.length) {
|
|
@@ -548,11 +586,12 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
548
586
|
if (targetPath.length === 0) throw new Error("_cf_destroyDescendantFacet: target path must not be empty.");
|
|
549
587
|
if (selfPath.length >= targetPath.length) throw new Error("_cf_destroyDescendantFacet: target must be a strict descendant.");
|
|
550
588
|
if (!_classPrivateFieldGet2(_host, this)._isSameAgentPathPrefix(selfPath, targetPath)) throw new Error("_cf_destroyDescendantFacet: target path does not descend from this agent.");
|
|
551
|
-
if (_classPrivateFieldGet2(_host, this)._parentPath.length === 0) await
|
|
589
|
+
if (_classPrivateFieldGet2(_host, this)._parentPath.length === 0) await this.cleanupPrefix(targetPath);
|
|
552
590
|
if (selfPath.length === targetPath.length - 1) {
|
|
553
591
|
const target = targetPath[targetPath.length - 1];
|
|
554
592
|
const ctx = _classPrivateFieldGet2(_host, this).ctx;
|
|
555
593
|
if (!ctx.facets) throw new Error("destroy() (delegated from facet) is not supported in this runtime — `ctx.facets` is unavailable. Update to the latest `compatibility_date` in your wrangler.jsonc.");
|
|
594
|
+
await _assertClassBrand(_DynamicAgentsInternal_brand, this, _closeConnectionsForDeletedPath).call(this, targetPath);
|
|
556
595
|
try {
|
|
557
596
|
ctx.facets.delete(`${target.className}\0${target.name}`);
|
|
558
597
|
} catch {}
|
|
@@ -628,16 +667,31 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
628
667
|
className,
|
|
629
668
|
name
|
|
630
669
|
}];
|
|
631
|
-
|
|
632
|
-
|
|
670
|
+
const root = _classPrivateFieldGet2(_host, this)._isFacet ? await this.rootAlarmOwner() : void 0;
|
|
671
|
+
await _assertClassBrand(_DynamicAgentsInternal_brand, this, _closeConnectionsForDeletedPath).call(this, childPath, root);
|
|
633
672
|
try {
|
|
634
673
|
ctx.facets.delete(facetKey);
|
|
635
674
|
} catch {}
|
|
636
675
|
this.registry.forget(className, name);
|
|
676
|
+
if (root) await root._cf_cleanupFacetPrefix(childPath);
|
|
677
|
+
else await this.cleanupPrefix(childPath);
|
|
678
|
+
}
|
|
679
|
+
/** Root-side: close sockets whose `/sub/...` target is under `prefix`. */
|
|
680
|
+
closeConnectionsForPrefix(prefix, code, reason) {
|
|
681
|
+
for (const connection of _classPrivateFieldGet2(_host, this)._webSockets.getConnections()) {
|
|
682
|
+
const targetPath = this.connectionTargetPath(connection);
|
|
683
|
+
if (!targetPath) continue;
|
|
684
|
+
if (!_classPrivateFieldGet2(_host, this)._isSameAgentPathPrefix(prefix, targetPath)) continue;
|
|
685
|
+
_classPrivateFieldGet2(_host, this)._unsafe_setConnectionFlag(connection, CF_SUB_AGENT_DELETED_KEY, true);
|
|
686
|
+
try {
|
|
687
|
+
connection.close(code, reason);
|
|
688
|
+
} catch {}
|
|
689
|
+
}
|
|
637
690
|
}
|
|
638
691
|
/** Drop all facet-side virtual connections (test/rehydration hook). */
|
|
639
692
|
clearVirtualConnections() {
|
|
640
693
|
_classPrivateFieldGet2(_virtualConnections, this).clear();
|
|
694
|
+
_classPrivateFieldSet2(_virtualConnectionsHydrated, this, false);
|
|
641
695
|
}
|
|
642
696
|
/** Facet-side lookup of a virtual connection by id. */
|
|
643
697
|
getVirtualConnection(id) {
|
|
@@ -715,6 +769,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
715
769
|
await completion;
|
|
716
770
|
}
|
|
717
771
|
async broadcastToParent(message, without) {
|
|
772
|
+
if (_assertClassBrand(_DynamicAgentsInternal_brand, this, _broadcastHasNoRecipients).call(this, without)) return;
|
|
718
773
|
await this.routeBroadcast(_classPrivateFieldGet2(_host, this).selfPath, message, without);
|
|
719
774
|
}
|
|
720
775
|
async broadcastToPath(ownerPath, message, without) {
|
|
@@ -779,21 +834,27 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
779
834
|
return parseSubAgentPath(request.url, { knownClasses: ctx.exports ? Object.keys(ctx.exports) : void 0 }) !== null;
|
|
780
835
|
}
|
|
781
836
|
async forwardWebSocketConnect(connection, request, options) {
|
|
782
|
-
const routed = await _assertClassBrand(_DynamicAgentsInternal_brand, this, _resolveConnection).call(this, connection,
|
|
783
|
-
|
|
837
|
+
const routed = await _assertClassBrand(_DynamicAgentsInternal_brand, this, _resolveConnection).call(this, connection, {
|
|
838
|
+
create: true,
|
|
839
|
+
request,
|
|
840
|
+
gate: options.gate
|
|
841
|
+
});
|
|
842
|
+
if (routed.status !== "ok") return false;
|
|
784
843
|
await routed.child._cf_handleSubAgentWebSocketConnect(_assertClassBrand(_DynamicAgentsInternal_brand, this, _createConnectionBridge).call(this, connection), routed.meta);
|
|
785
844
|
return true;
|
|
786
845
|
}
|
|
787
846
|
async forwardWebSocketMessage(connection, message, replyBridge) {
|
|
788
|
-
const routed = await _assertClassBrand(_DynamicAgentsInternal_brand, this, _resolveConnection).call(this, connection);
|
|
789
|
-
if (
|
|
847
|
+
const routed = await _assertClassBrand(_DynamicAgentsInternal_brand, this, _resolveConnection).call(this, connection, { create: false });
|
|
848
|
+
if (routed.status === "no-match") return false;
|
|
849
|
+
if (routed.status === "dropped") return true;
|
|
790
850
|
const bridge = _assertClassBrand(_DynamicAgentsInternal_brand, this, _createConnectionBridge).call(this, connection);
|
|
791
851
|
await routed.child._cf_handleSubAgentWebSocketMessage(message, bridge, routed.meta, replyBridge ?? bridge);
|
|
792
852
|
return true;
|
|
793
853
|
}
|
|
794
854
|
async forwardWebSocketClose(connection, code, reason, wasClean) {
|
|
795
|
-
const routed = await _assertClassBrand(_DynamicAgentsInternal_brand, this, _resolveConnection).call(this, connection);
|
|
796
|
-
if (
|
|
855
|
+
const routed = await _assertClassBrand(_DynamicAgentsInternal_brand, this, _resolveConnection).call(this, connection, { create: false });
|
|
856
|
+
if (routed.status === "no-match") return false;
|
|
857
|
+
if (routed.status === "dropped") return true;
|
|
797
858
|
await routed.child._cf_handleSubAgentWebSocketClose(code, reason, wasClean, _assertClassBrand(_DynamicAgentsInternal_brand, this, _createConnectionBridge).call(this, connection), routed.meta);
|
|
798
859
|
return true;
|
|
799
860
|
}
|
|
@@ -922,7 +983,8 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
922
983
|
if (!_classPrivateFieldGet2(_host, this)._isFacet || _classPrivateFieldGet2(_host, this)._parentPath.length === 0) return;
|
|
923
984
|
if (this.rootResolvesToSelf()) return;
|
|
924
985
|
const metas = await (await this.rootAlarmOwner())._cf_subAgentConnectionMetas(_classPrivateFieldGet2(_host, this).selfPath);
|
|
925
|
-
for (const meta of metas) _classPrivateFieldGet2(_virtualConnections, this).set(meta.id, { meta });
|
|
986
|
+
for (const meta of metas) if (!_classPrivateFieldGet2(_virtualConnections, this).has(meta.id)) _classPrivateFieldGet2(_virtualConnections, this).set(meta.id, { meta });
|
|
987
|
+
_classPrivateFieldSet2(_virtualConnectionsHydrated, this, true);
|
|
926
988
|
}
|
|
927
989
|
getRawConnectionState(connection) {
|
|
928
990
|
return getConnectionRawState(connection);
|
|
@@ -964,6 +1026,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
964
1026
|
* one RPC method. Stateless — no cached references.
|
|
965
1027
|
*/
|
|
966
1028
|
async invoke(className, name, method, args) {
|
|
1029
|
+
await _classPrivateFieldGet2(_host, this).__unsafe_ensureInitialized();
|
|
967
1030
|
const stub = await this.resolve(className, name);
|
|
968
1031
|
return await this.invokeStubMethod(stub, className, method, args);
|
|
969
1032
|
}
|
|
@@ -974,6 +1037,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
974
1037
|
* to the next facet using that facet's own `ctx.facets`.
|
|
975
1038
|
*/
|
|
976
1039
|
async invokePath(path, method, args) {
|
|
1040
|
+
await _classPrivateFieldGet2(_host, this).__unsafe_ensureInitialized();
|
|
977
1041
|
const [self, next, ...rest] = path;
|
|
978
1042
|
if (!self) throw new Error(`Sub-agent path invocation requires a non-empty path.`);
|
|
979
1043
|
const ownClassName = _classPrivateFieldGet2(_host, this).constructor.name;
|
|
@@ -1017,6 +1081,46 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
1017
1081
|
await _classPrivateFieldGet2(_host, this)._syncHostJobs();
|
|
1018
1082
|
}
|
|
1019
1083
|
};
|
|
1084
|
+
/**
|
|
1085
|
+
* Non-creating counterpart to {@link resolve} for WebSocket message/close
|
|
1086
|
+
* forwarding. Returns `null` when the child has no registry row, and never
|
|
1087
|
+
* writes one. The connection's initial connect already went through
|
|
1088
|
+
* {@link resolve} on this hop, so the runtime/export checks there hold.
|
|
1089
|
+
*/
|
|
1090
|
+
async function _resolveExisting(className, name) {
|
|
1091
|
+
const row = this.registry.row(className, name);
|
|
1092
|
+
if (!row) return null;
|
|
1093
|
+
const ctx = _classPrivateFieldGet2(_host, this).ctx;
|
|
1094
|
+
const identityName = row.identity_version === "path-v2" && typeof row.identity_name === "string" ? row.identity_name : name;
|
|
1095
|
+
const rootClassName = _classPrivateFieldGet2(_host, this)._parentPath[0]?.className ?? _classPrivateFieldGet2(_host, this).constructor.name;
|
|
1096
|
+
const rootNs = ctx.exports[rootClassName];
|
|
1097
|
+
const stub = ctx.facets.get(`${className}\0${name}`, () => ({
|
|
1098
|
+
class: ctx.exports[className],
|
|
1099
|
+
id: rootNs.idFromName(identityName)
|
|
1100
|
+
}));
|
|
1101
|
+
const childParentPath = _classPrivateFieldGet2(_host, this).selfPath;
|
|
1102
|
+
try {
|
|
1103
|
+
await _classPrivateFieldGet2(_host, this)._runFacetInitInvocation(async () => {
|
|
1104
|
+
await stub._cf_initAsFacet(name, childParentPath, identityName);
|
|
1105
|
+
});
|
|
1106
|
+
} catch (error) {
|
|
1107
|
+
if (!this.registry.row(className, name)) return null;
|
|
1108
|
+
throw error;
|
|
1109
|
+
}
|
|
1110
|
+
return stub;
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Close every client socket targeting `path` or a descendant, so a client
|
|
1114
|
+
* attached to a deleted facet gets an explicit close instead of a socket
|
|
1115
|
+
* that goes nowhere (#2003). Only the root owns real sockets.
|
|
1116
|
+
*/
|
|
1117
|
+
async function _closeConnectionsForDeletedPath(path, root) {
|
|
1118
|
+
if (!_classPrivateFieldGet2(_host, this)._isFacet) {
|
|
1119
|
+
this.closeConnectionsForPrefix(path, 1001, "Sub-agent deleted");
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
await (root ?? await this.rootAlarmOwner())._cf_closeSubAgentConnectionsForPrefix(path, 1001, "Sub-agent deleted");
|
|
1123
|
+
}
|
|
1020
1124
|
function _reportConnectionOperationFailure(connectionId, operation, error) {
|
|
1021
1125
|
console.error("[Agent] Sub-agent connection operation failed:", {
|
|
1022
1126
|
connectionId,
|
|
@@ -1024,6 +1128,29 @@ function _reportConnectionOperationFailure(connectionId, operation, error) {
|
|
|
1024
1128
|
error
|
|
1025
1129
|
});
|
|
1026
1130
|
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Whether a hydrated mirror proves no root socket targets this facet
|
|
1133
|
+
* outside `without`. Stale mirror entries only cost a root call; a socket
|
|
1134
|
+
* missing from a hydrated mirror has not had its connect forwarded here
|
|
1135
|
+
* yet, so it has not been through `onConnect`. Synchronous so a skipped
|
|
1136
|
+
* broadcast never reorders later operations.
|
|
1137
|
+
*/
|
|
1138
|
+
function _broadcastHasNoRecipients(without) {
|
|
1139
|
+
if (!_classPrivateFieldGet2(_virtualConnectionsHydrated, this)) {
|
|
1140
|
+
_assertClassBrand(_DynamicAgentsInternal_brand, this, _hydrateVirtualConnectionsInBackground).call(this);
|
|
1141
|
+
return false;
|
|
1142
|
+
}
|
|
1143
|
+
for (const id of _classPrivateFieldGet2(_virtualConnections, this).keys()) if (!without?.includes(id)) return false;
|
|
1144
|
+
return true;
|
|
1145
|
+
}
|
|
1146
|
+
function _hydrateVirtualConnectionsInBackground() {
|
|
1147
|
+
if (_classPrivateFieldGet2(_virtualConnectionsHydration, this)) return;
|
|
1148
|
+
const hydration = this.hydrateConnectionsFromRoot().catch(() => {}).finally(() => {
|
|
1149
|
+
_classPrivateFieldSet2(_virtualConnectionsHydration, this, void 0);
|
|
1150
|
+
});
|
|
1151
|
+
_classPrivateFieldSet2(_virtualConnectionsHydration, this, hydration);
|
|
1152
|
+
_classPrivateFieldGet2(_host, this).ctx.waitUntil(hydration);
|
|
1153
|
+
}
|
|
1027
1154
|
function _connectionMetaForPath(connection, ownerPath) {
|
|
1028
1155
|
ensureConnectionWrapped(connection);
|
|
1029
1156
|
const outerUri = _classPrivateFieldGet2(_host, this)._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY);
|
|
@@ -1074,20 +1201,31 @@ function _createConnectionBridge(connection) {
|
|
|
1074
1201
|
return _classPrivateFieldGet2(_host, this)._cf_broadcastToSubAgent(ownerPath, message, without);
|
|
1075
1202
|
});
|
|
1076
1203
|
}
|
|
1077
|
-
|
|
1204
|
+
/**
|
|
1205
|
+
* Resolve a connection's `/sub/{class}/{name}` target.
|
|
1206
|
+
*
|
|
1207
|
+
* `create: true` (the initial connect) may wake or create the child, like
|
|
1208
|
+
* `subAgent()`. `create: false` (message/close on an already-forwarded
|
|
1209
|
+
* connection) only attaches to a child that still has a registry row; a
|
|
1210
|
+
* deleted child resolves to `"dropped"`, which the caller must treat as
|
|
1211
|
+
* consumed so a stale frame can't recreate it (#2003).
|
|
1212
|
+
*/
|
|
1213
|
+
async function _resolveConnection(connection, options) {
|
|
1078
1214
|
ensureConnectionWrapped(connection);
|
|
1079
1215
|
const outerUri = _classPrivateFieldGet2(_host, this)._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY);
|
|
1080
1216
|
const uri = typeof outerUri === "string" ? outerUri : connection.uri;
|
|
1081
|
-
if (!uri) return
|
|
1217
|
+
if (!uri) return { status: "no-match" };
|
|
1218
|
+
if (_classPrivateFieldGet2(_host, this)._unsafe_getConnectionFlag(connection, "_cf_subAgentDeleted")) return { status: "dropped" };
|
|
1082
1219
|
const ctx = _classPrivateFieldGet2(_host, this).ctx;
|
|
1083
1220
|
let match = parseSubAgentPath(uri, { knownClasses: ctx.exports ? Object.keys(ctx.exports) : void 0 });
|
|
1084
|
-
if (!match) return
|
|
1221
|
+
if (!match) return { status: "no-match" };
|
|
1085
1222
|
if (_classPrivateFieldGet2(_host, this)._ParentClass.name === match.childClass && _classPrivateFieldGet2(_host, this).name === match.childName) {
|
|
1086
1223
|
const tailUri = new URL(uri);
|
|
1087
1224
|
tailUri.pathname = match.remainingPath;
|
|
1088
1225
|
match = parseSubAgentPath(tailUri.toString(), { knownClasses: ctx.exports ? Object.keys(ctx.exports) : void 0 });
|
|
1089
|
-
if (!match) return
|
|
1226
|
+
if (!match) return { status: "no-match" };
|
|
1090
1227
|
}
|
|
1228
|
+
const { request } = options;
|
|
1091
1229
|
let forwardReq = request;
|
|
1092
1230
|
if (request && options.gate) {
|
|
1093
1231
|
const decision = await _classPrivateFieldGet2(_host, this).onBeforeSubAgent(request, {
|
|
@@ -1095,25 +1233,28 @@ async function _resolveConnection(connection, request, options = { gate: false }
|
|
|
1095
1233
|
name: match.childName
|
|
1096
1234
|
});
|
|
1097
1235
|
if (decision instanceof Response) {
|
|
1098
|
-
|
|
1099
|
-
|
|
1236
|
+
const { code, reason } = subAgentRejectionClose(decision);
|
|
1237
|
+
connection.close(code, reason);
|
|
1238
|
+
return { status: "dropped" };
|
|
1100
1239
|
}
|
|
1101
1240
|
forwardReq = decision instanceof Request ? decision : request;
|
|
1102
1241
|
}
|
|
1103
|
-
const child = await this.resolve(match.childClass, match.childName);
|
|
1242
|
+
const child = options.create ? await this.resolve(match.childClass, match.childName) : await _assertClassBrand(_DynamicAgentsInternal_brand, this, _resolveExisting).call(this, match.childClass, match.childName);
|
|
1243
|
+
if (!child) return { status: "dropped" };
|
|
1104
1244
|
const childUri = new URL(forwardReq?.url ?? uri);
|
|
1105
1245
|
childUri.pathname = match.remainingPath;
|
|
1106
1246
|
const raw = this.getRawConnectionState(connection);
|
|
1107
1247
|
const rawTags = raw != null && typeof raw === "object" ? raw[CF_SUB_AGENT_TAGS_KEY] : void 0;
|
|
1108
1248
|
const tags = Array.isArray(rawTags) ? rawTags.filter((tag) => typeof tag === "string") : [...connection.tags];
|
|
1109
1249
|
return {
|
|
1250
|
+
status: "ok",
|
|
1110
1251
|
child,
|
|
1111
1252
|
meta: {
|
|
1112
1253
|
id: connection.id,
|
|
1113
1254
|
uri: childUri.toString(),
|
|
1114
1255
|
tags,
|
|
1115
1256
|
state: this.getForwardedState(connection),
|
|
1116
|
-
requestHeaders: forwardReq ? [...forwardReq.headers] : void 0
|
|
1257
|
+
requestHeaders: forwardReq ? [...forwardReq.headers].filter(([name]) => name !== SUB_AGENT_OUTER_URL_HEADER) : void 0
|
|
1117
1258
|
}
|
|
1118
1259
|
};
|
|
1119
1260
|
}
|
|
@@ -1248,7 +1389,7 @@ const DETACHED_NOTIFY_CALLBACK = "_cfDetachedNotifyFinish";
|
|
|
1248
1389
|
* every capability uses for its own schema version) and checks it on wake to
|
|
1249
1390
|
* skip DDL on established DOs.
|
|
1250
1391
|
*/
|
|
1251
|
-
const CURRENT_SCHEMA_VERSION =
|
|
1392
|
+
const CURRENT_SCHEMA_VERSION = 14;
|
|
1252
1393
|
const SCHEMA_VERSION_KEY = "cf_agents:schema_version";
|
|
1253
1394
|
const LEGACY_SCHEMA_VERSION_ROW_ID = "cf_schema_version";
|
|
1254
1395
|
const DEFAULT_STATE = {};
|
|
@@ -1323,9 +1464,9 @@ const DEFAULT_AGENT_STATIC_OPTIONS = {
|
|
|
1323
1464
|
/**
|
|
1324
1465
|
* Optional hard wall-clock ceiling (ms) on a single agent-tool re-attach
|
|
1325
1466
|
* (#1630). Caps the total wait even as the no-progress budget re-arms across
|
|
1326
|
-
* stream-closes. Defaults to `Infinity` (no implicit cap),
|
|
1327
|
-
*
|
|
1328
|
-
*
|
|
1467
|
+
* stream-closes. Defaults to `Infinity` (no implicit cap, #1672): a healthy,
|
|
1468
|
+
* still-advancing child is followed for as long as it makes progress — a
|
|
1469
|
+
* hung child is bounded by
|
|
1329
1470
|
* the no-progress budget, and a content-runaway by the child's own
|
|
1330
1471
|
* `maxRecoveryWork` / `shouldKeepRecovering`. Set a finite value to impose a
|
|
1331
1472
|
* wall-clock cap (which also tears the child down on `window-exceeded`).
|
|
@@ -1345,13 +1486,21 @@ const DEFAULT_AGENT_STATIC_OPTIONS = {
|
|
|
1345
1486
|
};
|
|
1346
1487
|
/** Compatibility alias for the lifecycle-owned current Agent accessor. */
|
|
1347
1488
|
const getCurrentAgent = getCurrentAgent$1;
|
|
1489
|
+
const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor;
|
|
1490
|
+
/** Functions produced by {@link withAgentContext}, so they are wrapped once. */
|
|
1491
|
+
const agentContextWrappers = /* @__PURE__ */ new WeakSet();
|
|
1348
1492
|
/**
|
|
1349
1493
|
* Restore Agent context when a public method is entered outside a Lifecycle
|
|
1350
1494
|
* hook, notably through native Durable Object RPC or cross-Agent re-entry.
|
|
1351
1495
|
* Lifecycle already owns context for its capability and semantic user hooks.
|
|
1496
|
+
*
|
|
1497
|
+
* Native RPC bypasses the lifecycle's runtime handlers, so an `async` method
|
|
1498
|
+
* entered from outside this Agent's context first starts the lifecycle when
|
|
1499
|
+
* the call is the one that wakes a cold instance. Synchronous methods are
|
|
1500
|
+
* never deferred, so they keep their synchronous return type.
|
|
1352
1501
|
*/
|
|
1353
1502
|
function withAgentContext(method) {
|
|
1354
|
-
|
|
1503
|
+
const enter = function(...args) {
|
|
1355
1504
|
const { agent } = getCurrentAgent();
|
|
1356
1505
|
if (agent === this) return method.apply(this, args);
|
|
1357
1506
|
return runInInvocation({
|
|
@@ -1363,6 +1512,16 @@ function withAgentContext(method) {
|
|
|
1363
1512
|
return method.apply(this, args);
|
|
1364
1513
|
});
|
|
1365
1514
|
};
|
|
1515
|
+
if (!(method instanceof AsyncFunction)) {
|
|
1516
|
+
agentContextWrappers.add(enter);
|
|
1517
|
+
return enter;
|
|
1518
|
+
}
|
|
1519
|
+
const enterStarted = async function(...args) {
|
|
1520
|
+
if (getCurrentAgent().agent !== this && !this.lifecycle.isStarted()) await this.lifecycle.start();
|
|
1521
|
+
return enter.apply(this, args);
|
|
1522
|
+
};
|
|
1523
|
+
agentContextWrappers.add(enterStarted);
|
|
1524
|
+
return enterStarted;
|
|
1366
1525
|
}
|
|
1367
1526
|
/**
|
|
1368
1527
|
* Base class for creating Agent implementations
|
|
@@ -1573,7 +1732,10 @@ var Agent = class Agent extends DurableObject {
|
|
|
1573
1732
|
id TEXT PRIMARY KEY NOT NULL,
|
|
1574
1733
|
name TEXT NOT NULL,
|
|
1575
1734
|
snapshot TEXT,
|
|
1576
|
-
created_at INTEGER NOT NULL
|
|
1735
|
+
created_at INTEGER NOT NULL,
|
|
1736
|
+
completed_at INTEGER,
|
|
1737
|
+
outcome TEXT,
|
|
1738
|
+
error_message TEXT
|
|
1577
1739
|
)
|
|
1578
1740
|
`;
|
|
1579
1741
|
this.sql`
|
|
@@ -1652,6 +1814,10 @@ var Agent = class Agent extends DurableObject {
|
|
|
1652
1814
|
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN detached_no_progress_budget_ms INTEGER");
|
|
1653
1815
|
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN last_progress_at INTEGER");
|
|
1654
1816
|
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN detached_on_milestones TEXT");
|
|
1817
|
+
addColumnIfNotExists("ALTER TABLE cf_agents_runs ADD COLUMN completed_at INTEGER");
|
|
1818
|
+
addColumnIfNotExists("ALTER TABLE cf_agents_runs ADD COLUMN outcome TEXT");
|
|
1819
|
+
addColumnIfNotExists("ALTER TABLE cf_agents_runs ADD COLUMN error_message TEXT");
|
|
1820
|
+
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN event_delivery TEXT");
|
|
1655
1821
|
this.ctx.storage.kv.put(SCHEMA_VERSION_KEY, CURRENT_SCHEMA_VERSION);
|
|
1656
1822
|
}
|
|
1657
1823
|
this._schemaInitialization = {
|
|
@@ -1928,6 +2094,14 @@ var Agent = class Agent extends DurableObject {
|
|
|
1928
2094
|
}, async () => {
|
|
1929
2095
|
if (this.shouldConnectionBeReadonly(connection, ctx)) this.setConnectionReadonly(connection, true);
|
|
1930
2096
|
if (this.shouldSendProtocolMessages(connection, ctx)) {
|
|
2097
|
+
const wasExcludedFromStateInitBroadcast = this._protocolBroadcastExcludeIds.has(connection.id);
|
|
2098
|
+
let currentState;
|
|
2099
|
+
this._protocolBroadcastExcludeIds.add(connection.id);
|
|
2100
|
+
try {
|
|
2101
|
+
currentState = this.state;
|
|
2102
|
+
} finally {
|
|
2103
|
+
if (!wasExcludedFromStateInitBroadcast) this._protocolBroadcastExcludeIds.delete(connection.id);
|
|
2104
|
+
}
|
|
1931
2105
|
if (this._resolvedOptions.sendIdentityOnConnect) {
|
|
1932
2106
|
const ctor = this.constructor;
|
|
1933
2107
|
if (ctor.options?.sendIdentityOnConnect === void 0 && !_sendIdentityWarnedClasses.has(ctor) && !this._isFacet) {
|
|
@@ -1936,20 +2110,11 @@ var Agent = class Agent extends DurableObject {
|
|
|
1936
2110
|
console.warn(`[Agent] ${ctor.name}: sending instance name "${this.name}" to clients via sendIdentityOnConnect (the name is not visible in the URL with custom routing). If this name is sensitive, add \`static options = { sendIdentityOnConnect: false }\` to opt out. Set it to true to silence this message.`);
|
|
1937
2111
|
}
|
|
1938
2112
|
}
|
|
1939
|
-
this._webSockets.
|
|
2113
|
+
this._webSockets.sendConnectFrames(connection, {
|
|
1940
2114
|
name: this.name,
|
|
1941
2115
|
agent: camelCaseToKebabCase(this._ParentClass.name)
|
|
1942
2116
|
});
|
|
1943
|
-
}
|
|
1944
|
-
const wasExcludedFromStateInitBroadcast = this._protocolBroadcastExcludeIds.has(connection.id);
|
|
1945
|
-
let currentState;
|
|
1946
|
-
this._protocolBroadcastExcludeIds.add(connection.id);
|
|
1947
|
-
try {
|
|
1948
|
-
currentState = this.state;
|
|
1949
|
-
} finally {
|
|
1950
|
-
if (!wasExcludedFromStateInitBroadcast) this._protocolBroadcastExcludeIds.delete(connection.id);
|
|
1951
|
-
}
|
|
1952
|
-
if (currentState !== void 0) this._webSockets.sendState(connection);
|
|
2117
|
+
} else if (currentState !== void 0) this._webSockets.sendState(connection);
|
|
1953
2118
|
connection.send(JSON.stringify({
|
|
1954
2119
|
mcp: this.getMcpServers(),
|
|
1955
2120
|
type: "cf_agent_mcp_servers"
|
|
@@ -2366,19 +2531,21 @@ var Agent = class Agent extends DurableObject {
|
|
|
2366
2531
|
proto = Object.getPrototypeOf(proto);
|
|
2367
2532
|
}
|
|
2368
2533
|
}
|
|
2534
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2369
2535
|
let proto = Object.getPrototypeOf(this);
|
|
2370
|
-
|
|
2371
|
-
while (proto && proto !== Object.prototype && depth < 10) {
|
|
2536
|
+
while (proto && proto !== Agent.prototype && proto !== Object.prototype) {
|
|
2372
2537
|
const methodNames = Object.getOwnPropertyNames(proto);
|
|
2373
2538
|
for (const methodName of methodNames) {
|
|
2539
|
+
if (seen.has(methodName)) continue;
|
|
2540
|
+
seen.add(methodName);
|
|
2374
2541
|
const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
|
|
2375
|
-
if (baseMethods.has(methodName) || methodName.startsWith("_") || !descriptor || !!descriptor.get || typeof descriptor.value !== "function") continue;
|
|
2376
|
-
const
|
|
2377
|
-
|
|
2542
|
+
if (baseMethods.has(methodName) || methodName.startsWith("_") || !descriptor || !!descriptor.get || typeof descriptor.value !== "function" || agentContextWrappers.has(descriptor.value)) continue;
|
|
2543
|
+
const method = descriptor.value;
|
|
2544
|
+
const wrappedFunction = withAgentContext(method);
|
|
2545
|
+
if (this._isCallable(methodName)) copyCallableMetadata(method, wrappedFunction);
|
|
2378
2546
|
this.constructor.prototype[methodName] = wrappedFunction;
|
|
2379
2547
|
}
|
|
2380
2548
|
proto = Object.getPrototypeOf(proto);
|
|
2381
|
-
depth++;
|
|
2382
2549
|
}
|
|
2383
2550
|
}
|
|
2384
2551
|
onError(connectionOrError, error) {
|
|
@@ -2487,7 +2654,8 @@ var Agent = class Agent extends DurableObject {
|
|
|
2487
2654
|
return this._dynamicAgents.routeLifecycleToTarget(target, envelope);
|
|
2488
2655
|
}
|
|
2489
2656
|
/** Single native-RPC aperture for routed Lifecycle capabilities. */
|
|
2490
|
-
_cf_routeLifecycle(target, envelope) {
|
|
2657
|
+
async _cf_routeLifecycle(target, envelope) {
|
|
2658
|
+
await this.__unsafe_ensureInitialized();
|
|
2491
2659
|
return this._dynamicAgents.routeLifecycle(target, envelope);
|
|
2492
2660
|
}
|
|
2493
2661
|
_rootAlarmOwner() {
|
|
@@ -2504,6 +2672,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
2504
2672
|
* @internal
|
|
2505
2673
|
*/
|
|
2506
2674
|
async _cf_cleanupFacetPrefix(ownerPath) {
|
|
2675
|
+
await this.__unsafe_ensureInitialized();
|
|
2507
2676
|
await this._dynamicAgents.cleanupPrefix(ownerPath);
|
|
2508
2677
|
}
|
|
2509
2678
|
/**
|
|
@@ -2512,7 +2681,8 @@ var Agent = class Agent extends DurableObject {
|
|
|
2512
2681
|
* physical alarm, so this lets facet work use the root alarm heartbeat.
|
|
2513
2682
|
* @internal
|
|
2514
2683
|
*/
|
|
2515
|
-
_cf_acquireFacetKeepAlive(ownerPath) {
|
|
2684
|
+
async _cf_acquireFacetKeepAlive(ownerPath) {
|
|
2685
|
+
await this.__unsafe_ensureInitialized();
|
|
2516
2686
|
return this._dynamicAgents.acquireKeepAlive(ownerPath);
|
|
2517
2687
|
}
|
|
2518
2688
|
/**
|
|
@@ -2520,8 +2690,9 @@ var Agent = class Agent extends DurableObject {
|
|
|
2520
2690
|
* Idempotent so disposer calls can safely race or run twice.
|
|
2521
2691
|
* @internal
|
|
2522
2692
|
*/
|
|
2523
|
-
_cf_releaseFacetKeepAlive(token) {
|
|
2524
|
-
|
|
2693
|
+
async _cf_releaseFacetKeepAlive(token) {
|
|
2694
|
+
await this.__unsafe_ensureInitialized();
|
|
2695
|
+
await this._dynamicAgents.releaseKeepAlive(token);
|
|
2525
2696
|
}
|
|
2526
2697
|
/**
|
|
2527
2698
|
* Register a facet's durable run row in the root-side index so root
|
|
@@ -2529,15 +2700,17 @@ var Agent = class Agent extends DurableObject {
|
|
|
2529
2700
|
* The facet remains authoritative for snapshots and recovery hooks.
|
|
2530
2701
|
* @internal
|
|
2531
2702
|
*/
|
|
2532
|
-
_cf_registerFacetRun(ownerPath, runId) {
|
|
2533
|
-
|
|
2703
|
+
async _cf_registerFacetRun(ownerPath, runId) {
|
|
2704
|
+
await this.__unsafe_ensureInitialized();
|
|
2705
|
+
await this._dynamicAgents.registerRun(ownerPath, runId);
|
|
2534
2706
|
}
|
|
2535
2707
|
/**
|
|
2536
2708
|
* Remove a completed facet fiber from the root-side index.
|
|
2537
2709
|
* @internal
|
|
2538
2710
|
*/
|
|
2539
|
-
_cf_unregisterFacetRun(ownerPath, runId) {
|
|
2540
|
-
|
|
2711
|
+
async _cf_unregisterFacetRun(ownerPath, runId) {
|
|
2712
|
+
await this.__unsafe_ensureInitialized();
|
|
2713
|
+
await this._dynamicAgents.unregisterRun(ownerPath, runId);
|
|
2541
2714
|
}
|
|
2542
2715
|
/**
|
|
2543
2716
|
* Schedule a task to be executed in the future
|
|
@@ -3222,6 +3395,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
3222
3395
|
};
|
|
3223
3396
|
let root;
|
|
3224
3397
|
let registeredFacetRun = false;
|
|
3398
|
+
let bodyOutcome;
|
|
3225
3399
|
let dispose = () => {};
|
|
3226
3400
|
try {
|
|
3227
3401
|
if ("initialSnapshot" in (options ?? {})) writeSnapshot(options?.initialSnapshot);
|
|
@@ -3235,16 +3409,29 @@ var Agent = class Agent extends DurableObject {
|
|
|
3235
3409
|
writeSnapshot(options?.wrapStash ? options.wrapStash(data) : data);
|
|
3236
3410
|
};
|
|
3237
3411
|
try {
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3412
|
+
let result;
|
|
3413
|
+
try {
|
|
3414
|
+
result = await _fiberALS.run({
|
|
3415
|
+
id,
|
|
3416
|
+
signal,
|
|
3417
|
+
stash
|
|
3418
|
+
}, () => fn({
|
|
3419
|
+
id,
|
|
3420
|
+
signal,
|
|
3421
|
+
stash,
|
|
3422
|
+
snapshot: null
|
|
3423
|
+
}));
|
|
3424
|
+
} catch (error) {
|
|
3425
|
+
bodyOutcome = {
|
|
3426
|
+
status: signal.aborted ? "aborted" : "error",
|
|
3427
|
+
error: this._fiberErrorMessage(error)
|
|
3428
|
+
};
|
|
3429
|
+
throw error;
|
|
3430
|
+
}
|
|
3431
|
+
bodyOutcome = {
|
|
3432
|
+
status: "completed",
|
|
3433
|
+
error: null
|
|
3434
|
+
};
|
|
3248
3435
|
options?.beforeRunCleanup?.({ ok: true });
|
|
3249
3436
|
this._emit("fiber:run:completed", {
|
|
3250
3437
|
fiberId: id,
|
|
@@ -3269,18 +3456,29 @@ var Agent = class Agent extends DurableObject {
|
|
|
3269
3456
|
}
|
|
3270
3457
|
} finally {
|
|
3271
3458
|
this._runFiberActiveFibers.delete(id);
|
|
3459
|
+
let rowDeleted = false;
|
|
3272
3460
|
try {
|
|
3273
3461
|
this._withAgentSpan("finalize_fiber", "fiber", {
|
|
3274
3462
|
"cloudflare.agents.fiber.id": id,
|
|
3275
3463
|
"cloudflare.agents.fiber.name": name
|
|
3276
3464
|
}, () => {
|
|
3465
|
+
if (bodyOutcome) try {
|
|
3466
|
+
this.sql`
|
|
3467
|
+
UPDATE cf_agents_runs
|
|
3468
|
+
SET completed_at = ${Date.now()},
|
|
3469
|
+
outcome = ${bodyOutcome.status},
|
|
3470
|
+
error_message = ${bodyOutcome.error}
|
|
3471
|
+
WHERE id = ${id}
|
|
3472
|
+
`;
|
|
3473
|
+
} catch {}
|
|
3277
3474
|
this.sql`DELETE FROM cf_agents_runs WHERE id = ${id}`;
|
|
3278
3475
|
});
|
|
3476
|
+
rowDeleted = true;
|
|
3279
3477
|
} catch (error) {
|
|
3280
3478
|
console.error(`[Agent] Failed to finalize fiber "${name}" (${id}); leaving run row for recovery:`, error);
|
|
3281
3479
|
}
|
|
3282
3480
|
dispose();
|
|
3283
|
-
if (root && registeredFacetRun) try {
|
|
3481
|
+
if (root && registeredFacetRun && rowDeleted) try {
|
|
3284
3482
|
await root._cf_unregisterFacetRun(this.selfPath, id);
|
|
3285
3483
|
} catch (e) {
|
|
3286
3484
|
console.error("[Agent] Failed to unregister facet fiber:", e);
|
|
@@ -3337,7 +3535,11 @@ var Agent = class Agent extends DurableObject {
|
|
|
3337
3535
|
const fiberRecoveryMaxAgeMs = this._resolvedOptions.fiberRecoveryMaxAgeMs;
|
|
3338
3536
|
let madeProgress = false;
|
|
3339
3537
|
try {
|
|
3340
|
-
const rows = this.sql`
|
|
3538
|
+
const rows = this.sql`
|
|
3539
|
+
SELECT id, name, snapshot, created_at, completed_at, outcome,
|
|
3540
|
+
error_message
|
|
3541
|
+
FROM cf_agents_runs
|
|
3542
|
+
`;
|
|
3341
3543
|
for (const row of rows) {
|
|
3342
3544
|
if (scanDeadlineMs > 0 && Date.now() - scanStartedAt > scanDeadlineMs) {
|
|
3343
3545
|
this._emit("fiber:recovery:skipped", {
|
|
@@ -3349,6 +3551,27 @@ var Agent = class Agent extends DurableObject {
|
|
|
3349
3551
|
break;
|
|
3350
3552
|
}
|
|
3351
3553
|
if (this._runFiberActiveFibers.has(row.id)) continue;
|
|
3554
|
+
const managedRow = this._readFiber(row.id);
|
|
3555
|
+
if (row.completed_at !== null && (!managedRow || row.outcome !== null)) {
|
|
3556
|
+
if (managedRow) this.sql`
|
|
3557
|
+
UPDATE cf_agents_fibers
|
|
3558
|
+
SET status = ${row.outcome},
|
|
3559
|
+
error_message = ${row.error_message},
|
|
3560
|
+
completed_at = ${row.completed_at}
|
|
3561
|
+
WHERE fiber_id = ${row.id}
|
|
3562
|
+
AND status IN ('pending', 'running')
|
|
3563
|
+
`;
|
|
3564
|
+
this.sql`DELETE FROM cf_agents_runs WHERE id = ${row.id}`;
|
|
3565
|
+
madeProgress = true;
|
|
3566
|
+
if (managedRow) this._notifyManagedFiberTerminal(row.id);
|
|
3567
|
+
continue;
|
|
3568
|
+
}
|
|
3569
|
+
if (managedRow && this._isTerminalFiberStatus(managedRow.status)) {
|
|
3570
|
+
this.sql`DELETE FROM cf_agents_runs WHERE id = ${row.id}`;
|
|
3571
|
+
madeProgress = true;
|
|
3572
|
+
this._notifyManagedFiberTerminal(row.id);
|
|
3573
|
+
continue;
|
|
3574
|
+
}
|
|
3352
3575
|
const snapshot = this._parseFiberRecoverySnapshot(row.id, row.snapshot);
|
|
3353
3576
|
const ctx = {
|
|
3354
3577
|
id: row.id,
|
|
@@ -3357,7 +3580,6 @@ var Agent = class Agent extends DurableObject {
|
|
|
3357
3580
|
createdAt: row.created_at,
|
|
3358
3581
|
recoveryReason: "interrupted"
|
|
3359
3582
|
};
|
|
3360
|
-
const managedRow = this._readFiber(row.id);
|
|
3361
3583
|
this._emit("fiber:recovery:detected", {
|
|
3362
3584
|
...this._fiberRecoveryPayload(ctx, managedRow),
|
|
3363
3585
|
elapsedMs: Date.now() - row.created_at
|
|
@@ -3370,12 +3592,6 @@ var Agent = class Agent extends DurableObject {
|
|
|
3370
3592
|
elapsedMs: Date.now() - row.created_at
|
|
3371
3593
|
});
|
|
3372
3594
|
if (managedRow) {
|
|
3373
|
-
if (this._isTerminalFiberStatus(managedRow.status)) {
|
|
3374
|
-
this.sql`DELETE FROM cf_agents_runs WHERE id = ${row.id}`;
|
|
3375
|
-
madeProgress = true;
|
|
3376
|
-
this._notifyManagedFiberTerminal(row.id);
|
|
3377
|
-
continue;
|
|
3378
|
-
}
|
|
3379
3595
|
const completedAt = Date.now();
|
|
3380
3596
|
this.sql`
|
|
3381
3597
|
UPDATE cf_agents_fibers
|
|
@@ -3513,8 +3729,9 @@ var Agent = class Agent extends DurableObject {
|
|
|
3513
3729
|
* cleanup as `parent.deleteSubAgent(Cls, name)` from the parent.
|
|
3514
3730
|
* @internal
|
|
3515
3731
|
*/
|
|
3516
|
-
_cf_destroyDescendantFacet(targetPath) {
|
|
3517
|
-
|
|
3732
|
+
async _cf_destroyDescendantFacet(targetPath) {
|
|
3733
|
+
await this.__unsafe_ensureInitialized();
|
|
3734
|
+
await this._dynamicAgents.destroyDescendant(targetPath);
|
|
3518
3735
|
}
|
|
3519
3736
|
/**
|
|
3520
3737
|
* Whether any runFiber recovery work is still outstanding: orphaned
|
|
@@ -3552,6 +3769,15 @@ var Agent = class Agent extends DurableObject {
|
|
|
3552
3769
|
*/
|
|
3553
3770
|
async _syncHostJobs() {
|
|
3554
3771
|
if (this._destroyed) return;
|
|
3772
|
+
if (this._isFacet) {
|
|
3773
|
+
const work = this.lifecycle.jobs;
|
|
3774
|
+
for (const id of [
|
|
3775
|
+
HOST_JOB_DESTROY_ID,
|
|
3776
|
+
HOST_JOB_KEEP_ALIVE_ID,
|
|
3777
|
+
HOST_JOB_HOUSEKEEPING_ID
|
|
3778
|
+
]) if (work.get(id)) await work.cancel(id);
|
|
3779
|
+
return;
|
|
3780
|
+
}
|
|
3555
3781
|
await this._withAgentSpan("schedule_agent_alarm", "alarm", {}, async () => {
|
|
3556
3782
|
const work = this.lifecycle.jobs;
|
|
3557
3783
|
const nowMs = Date.now();
|
|
@@ -3683,9 +3909,10 @@ var Agent = class Agent extends DurableObject {
|
|
|
3683
3909
|
className: match.childClass,
|
|
3684
3910
|
name: match.childName
|
|
3685
3911
|
});
|
|
3686
|
-
|
|
3912
|
+
const isWebSocketUpgrade = request.headers.get("Upgrade")?.toLowerCase() === "websocket";
|
|
3913
|
+
if (decision instanceof Response) return isWebSocketUpgrade && !decision.webSocket ? rejectSubAgentWebSocket(decision) : decision;
|
|
3687
3914
|
const forwardReq = decision instanceof Request ? decision : request;
|
|
3688
|
-
if (
|
|
3915
|
+
if (isWebSocketUpgrade) {
|
|
3689
3916
|
const acceptHeaders = new Headers(forwardReq.headers);
|
|
3690
3917
|
const routedUrl = new URL(forwardReq.url);
|
|
3691
3918
|
routedUrl.pathname = new URL(request.url).pathname;
|
|
@@ -3722,18 +3949,27 @@ var Agent = class Agent extends DurableObject {
|
|
|
3722
3949
|
}
|
|
3723
3950
|
}
|
|
3724
3951
|
async _cf_broadcastToSubAgent(ownerPath, message, without) {
|
|
3952
|
+
await this.__unsafe_ensureInitialized();
|
|
3725
3953
|
await this._dynamicAgents.broadcastToPath(ownerPath, message, without);
|
|
3726
3954
|
}
|
|
3727
|
-
_cf_subAgentConnectionMetas(ownerPath) {
|
|
3955
|
+
async _cf_subAgentConnectionMetas(ownerPath) {
|
|
3956
|
+
await this.__unsafe_ensureInitialized();
|
|
3728
3957
|
return this._dynamicAgents.connectionMetas(ownerPath);
|
|
3729
3958
|
}
|
|
3730
|
-
_cf_sendToSubAgentConnection(connectionId, message) {
|
|
3731
|
-
|
|
3959
|
+
async _cf_sendToSubAgentConnection(connectionId, message) {
|
|
3960
|
+
await this.__unsafe_ensureInitialized();
|
|
3961
|
+
await this._dynamicAgents.sendToConnection(connectionId, message);
|
|
3962
|
+
}
|
|
3963
|
+
async _cf_closeSubAgentConnection(connectionId, code, reason) {
|
|
3964
|
+
await this.__unsafe_ensureInitialized();
|
|
3965
|
+
await this._dynamicAgents.closeConnection(connectionId, code, reason);
|
|
3732
3966
|
}
|
|
3733
|
-
|
|
3734
|
-
|
|
3967
|
+
async _cf_closeSubAgentConnectionsForPrefix(prefix, code, reason) {
|
|
3968
|
+
await this.__unsafe_ensureInitialized();
|
|
3969
|
+
this._dynamicAgents.closeConnectionsForPrefix(prefix, code, reason);
|
|
3735
3970
|
}
|
|
3736
|
-
_cf_setSubAgentConnectionState(connectionId, state) {
|
|
3971
|
+
async _cf_setSubAgentConnectionState(connectionId, state) {
|
|
3972
|
+
await this.__unsafe_ensureInitialized();
|
|
3737
3973
|
return this._dynamicAgents.setConnectionState(connectionId, state);
|
|
3738
3974
|
}
|
|
3739
3975
|
_cf_connectionTargetsSubAgent(connection) {
|
|
@@ -4049,6 +4285,9 @@ var Agent = class Agent extends DurableObject {
|
|
|
4049
4285
|
const runId = options.runId ?? nanoid(12);
|
|
4050
4286
|
const agentType = cls.name;
|
|
4051
4287
|
const detached = this._parseDetachedOption(options.detached);
|
|
4288
|
+
const eventDelivery = options.eventDelivery ?? "full";
|
|
4289
|
+
if (eventDelivery !== "full" && eventDelivery !== "terminal") throw new Error(`runAgentTool: eventDelivery must be "full" or "terminal", got ${JSON.stringify(eventDelivery)}.`);
|
|
4290
|
+
if (detached && eventDelivery === "terminal") throw new Error("runAgentTool: eventDelivery \"terminal\" is not supported for detached runs.");
|
|
4052
4291
|
const existing = this._readAgentToolRun(runId);
|
|
4053
4292
|
if (existing) {
|
|
4054
4293
|
if (detached) {
|
|
@@ -4139,13 +4378,14 @@ var Agent = class Agent extends DurableObject {
|
|
|
4139
4378
|
input_redacted, status, display_metadata, display_order, started_at,
|
|
4140
4379
|
detached, detached_on_finish, detached_notify_source,
|
|
4141
4380
|
detached_max_budget_at, detached_no_progress_budget_ms,
|
|
4142
|
-
detached_on_milestones
|
|
4381
|
+
detached_on_milestones, event_delivery
|
|
4143
4382
|
) VALUES (
|
|
4144
4383
|
${runId}, ${options.parentToolCallId ?? null}, ${agentType},
|
|
4145
4384
|
${inputPreviewJson}, 1, 'starting', ${displayJson}, ${displayOrder},
|
|
4146
4385
|
${startedAt}, ${detached ? 1 : 0}, ${detached?.onFinishName ?? null},
|
|
4147
4386
|
${detached?.notifySource ?? null}, ${detachedMaxBudgetAt},
|
|
4148
|
-
${detachedNoProgressBudgetMs}, ${detachedOnMilestonesJson}
|
|
4387
|
+
${detachedNoProgressBudgetMs}, ${detachedOnMilestonesJson},
|
|
4388
|
+
${eventDelivery === "terminal" ? "terminal" : null}
|
|
4149
4389
|
)
|
|
4150
4390
|
`;
|
|
4151
4391
|
const runInfo = {
|
|
@@ -4170,7 +4410,10 @@ var Agent = class Agent extends DurableObject {
|
|
|
4170
4410
|
});
|
|
4171
4411
|
const child = await this.subAgent(cls, runId);
|
|
4172
4412
|
const adapter = this._asAgentToolChildAdapter(child);
|
|
4173
|
-
const childStart = await adapter.startAgentToolRun(options.input, {
|
|
4413
|
+
const childStart = await adapter.startAgentToolRun(options.input, {
|
|
4414
|
+
runId,
|
|
4415
|
+
...eventDelivery === "terminal" ? { eventDelivery } : {}
|
|
4416
|
+
});
|
|
4174
4417
|
this._markAgentToolRunning(runId);
|
|
4175
4418
|
if (detached) {
|
|
4176
4419
|
if (options.signal) console.warn(`[agents] runAgentTool: \`signal\` is ignored for a detached run (${runId}); a detached child must outlive the spawning turn. Use cancelAgentTool(runId) to cancel it.`);
|
|
@@ -4781,29 +5024,79 @@ var Agent = class Agent extends DurableObject {
|
|
|
4781
5024
|
else this.broadcast(body);
|
|
4782
5025
|
}
|
|
4783
5026
|
_broadcastAgentToolChunks(parentToolCallId, runId, chunks, sequence, replay, connection) {
|
|
5027
|
+
const terminalOnly = this._isTerminalOnlyAgentToolRun(runId);
|
|
4784
5028
|
let next = sequence;
|
|
4785
|
-
for (const chunk of chunks)
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
5029
|
+
for (const chunk of chunks) {
|
|
5030
|
+
const chunkSequence = next++;
|
|
5031
|
+
if (terminalOnly && !isAgentToolLifecycleChunk(chunk.body)) continue;
|
|
5032
|
+
this._broadcastAgentToolEvent(parentToolCallId, chunkSequence, {
|
|
5033
|
+
kind: "chunk",
|
|
5034
|
+
runId,
|
|
5035
|
+
body: chunk.body
|
|
5036
|
+
}, replay, connection);
|
|
5037
|
+
}
|
|
4790
5038
|
return next;
|
|
4791
5039
|
}
|
|
4792
|
-
|
|
4793
|
-
|
|
5040
|
+
_isTerminalOnlyAgentToolRun(runId) {
|
|
5041
|
+
return this.sql`
|
|
5042
|
+
SELECT event_delivery FROM cf_agent_tool_runs WHERE run_id = ${runId}
|
|
5043
|
+
`[0]?.event_delivery === "terminal";
|
|
5044
|
+
}
|
|
5045
|
+
async _broadcastAgentToolStoredChunks(row, sequence, replay, connection, timeoutMs) {
|
|
5046
|
+
const deadline = this._agentToolRecoveryDeadline(timeoutMs);
|
|
5047
|
+
const resolving = this._cf_resolveSubAgent(row.agent_type, row.run_id);
|
|
5048
|
+
const child = deadline === void 0 ? await resolving : await this._settleWithinRecoveryTimeout(resolving, deadline());
|
|
5049
|
+
if (child === void 0) return sequence;
|
|
4794
5050
|
const adapter = this._asAgentToolChildAdapter(child);
|
|
4795
|
-
return this._broadcastAgentToolStoredChunksFromAdapter(adapter, row, sequence, replay, connection);
|
|
5051
|
+
return this._broadcastAgentToolStoredChunksFromAdapter(adapter, row, sequence, replay, connection, deadline?.());
|
|
5052
|
+
}
|
|
5053
|
+
/**
|
|
5054
|
+
* One budget shared by every step of a bounded recovery read, so a run's
|
|
5055
|
+
* total time stays within `timeoutMs`. Returns the remaining milliseconds,
|
|
5056
|
+
* never below 1 because a non-positive timeout means "unbounded".
|
|
5057
|
+
*/
|
|
5058
|
+
_agentToolRecoveryDeadline(timeoutMs) {
|
|
5059
|
+
if (timeoutMs === void 0 || timeoutMs <= 0) return void 0;
|
|
5060
|
+
const deadline = Date.now() + timeoutMs;
|
|
5061
|
+
return () => Math.max(1, deadline - Date.now());
|
|
4796
5062
|
}
|
|
4797
5063
|
async _broadcastAgentToolStoredChunksFromAdapter(adapter, row, sequence, replay, connection, timeoutMs) {
|
|
4798
|
-
const
|
|
4799
|
-
|
|
4800
|
-
|
|
5064
|
+
const deadline = this._agentToolRecoveryDeadline(timeoutMs);
|
|
5065
|
+
const chunks = await this._getAgentToolChunksForRecovery(adapter, row.run_id, deadline?.());
|
|
5066
|
+
const next = chunks ? this._broadcastAgentToolChunks(row.parent_tool_call_id ?? void 0, row.run_id, chunks, sequence, replay, connection) : sequence;
|
|
5067
|
+
return this._broadcastAgentToolMilestones(adapter, row, next, replay, connection, deadline?.());
|
|
5068
|
+
}
|
|
5069
|
+
/**
|
|
5070
|
+
* Milestones are persisted on the child run rather than in its chunk log, so
|
|
5071
|
+
* replay re-emits them from the child's inspection. The client dedupes them
|
|
5072
|
+
* on the milestone's own sequence, so a milestone already seen live is a no-op.
|
|
5073
|
+
* They carry the next stored-chunk sequence without consuming it, matching
|
|
5074
|
+
* the live path.
|
|
5075
|
+
*/
|
|
5076
|
+
async _broadcastAgentToolMilestones(adapter, row, sequence, replay, connection, timeoutMs) {
|
|
5077
|
+
const milestones = (await this._settleWithinRecoveryTimeout(adapter.inspectAgentToolRun(row.run_id, { reconcile: false }), timeoutMs))?.milestones ?? [];
|
|
5078
|
+
for (const milestone of milestones) this._broadcastAgentToolEvent(row.parent_tool_call_id ?? void 0, sequence, {
|
|
5079
|
+
kind: "chunk",
|
|
5080
|
+
runId: row.run_id,
|
|
5081
|
+
body: JSON.stringify({
|
|
5082
|
+
type: AGENT_TOOL_MILESTONE_PART,
|
|
5083
|
+
data: {
|
|
5084
|
+
name: milestone.name,
|
|
5085
|
+
sequence: milestone.sequence,
|
|
5086
|
+
at: milestone.at,
|
|
5087
|
+
...milestone.data !== void 0 ? { data: milestone.data } : {}
|
|
5088
|
+
}
|
|
5089
|
+
})
|
|
5090
|
+
}, replay, connection);
|
|
5091
|
+
return sequence;
|
|
4801
5092
|
}
|
|
4802
5093
|
async _forwardAgentToolStream(stream, parentToolCallId, runId, sequence, signal, idleTimeoutMs) {
|
|
4803
5094
|
let next = sequence;
|
|
5095
|
+
let forwarded = false;
|
|
4804
5096
|
if (signal?.aborted) return {
|
|
4805
5097
|
next,
|
|
4806
|
-
ended: "aborted"
|
|
5098
|
+
ended: "aborted",
|
|
5099
|
+
forwarded
|
|
4807
5100
|
};
|
|
4808
5101
|
let ended = "done";
|
|
4809
5102
|
const reader = stream.getReader();
|
|
@@ -4831,12 +5124,18 @@ var Agent = class Agent extends DurableObject {
|
|
|
4831
5124
|
idleTimer = setTimeout(() => resolveIdle?.(), idleTimeoutMs);
|
|
4832
5125
|
};
|
|
4833
5126
|
let forwardedSinceProgress = false;
|
|
5127
|
+
const terminalOnly = this._isTerminalOnlyAgentToolRun(runId);
|
|
4834
5128
|
try {
|
|
4835
5129
|
const forwardChunk = (chunk) => {
|
|
4836
|
-
|
|
5130
|
+
const lifecycle = isAgentToolLifecycleChunk(chunk.body);
|
|
5131
|
+
const unstoredId = typeof chunk.unstoredId === "string" ? chunk.unstoredId : void 0;
|
|
5132
|
+
const chunkSequence = lifecycle || unstoredId !== void 0 ? next : next++;
|
|
5133
|
+
forwarded = true;
|
|
5134
|
+
if (!terminalOnly || lifecycle) this._broadcastAgentToolEvent(parentToolCallId, chunkSequence, {
|
|
4837
5135
|
kind: "chunk",
|
|
4838
5136
|
runId,
|
|
4839
|
-
body: chunk.body
|
|
5137
|
+
body: chunk.body,
|
|
5138
|
+
...unstoredId !== void 0 ? { unstoredId } : {}
|
|
4840
5139
|
});
|
|
4841
5140
|
this._observeForwardedProgress(runId, chunk.body);
|
|
4842
5141
|
forwardedSinceProgress = true;
|
|
@@ -4904,7 +5203,8 @@ var Agent = class Agent extends DurableObject {
|
|
|
4904
5203
|
}
|
|
4905
5204
|
return {
|
|
4906
5205
|
next,
|
|
4907
|
-
ended
|
|
5206
|
+
ended,
|
|
5207
|
+
forwarded
|
|
4908
5208
|
};
|
|
4909
5209
|
}
|
|
4910
5210
|
/**
|
|
@@ -5105,9 +5405,9 @@ var Agent = class Agent extends DurableObject {
|
|
|
5105
5405
|
* dies and recovers again during deploy churn is still collected. A genuinely
|
|
5106
5406
|
* silent/hung child can never block recovery forever: it seals `interrupted`
|
|
5107
5407
|
* after one `noProgressTimeoutMs` window. `maxWindowMs` is an OPTIONAL hard
|
|
5108
|
-
* wall-clock ceiling (default `Infinity` — uncapped,
|
|
5109
|
-
*
|
|
5110
|
-
*
|
|
5408
|
+
* wall-clock ceiling (default `Infinity` — uncapped, #1672); set it finite
|
|
5409
|
+
* to also bound a child that keeps progressing, which seals
|
|
5410
|
+
* `window-exceeded` and tears the child down.
|
|
5111
5411
|
*
|
|
5112
5412
|
* Returns the terminal `result` (and `completedAt`) when the child reaches a
|
|
5113
5413
|
* terminal status, plus the advanced broadcast `sequence`. Returns
|
|
@@ -5152,18 +5452,22 @@ var Agent = class Agent extends DurableObject {
|
|
|
5152
5452
|
try {
|
|
5153
5453
|
while (!ceilingController.signal.aborted) {
|
|
5154
5454
|
let afterSequence = -1;
|
|
5455
|
+
let storedCount = 0;
|
|
5155
5456
|
try {
|
|
5156
5457
|
const existing = await adapter.getAgentToolChunks(row.run_id);
|
|
5157
5458
|
const last = existing[existing.length - 1];
|
|
5158
5459
|
if (last) afterSequence = last.sequence;
|
|
5460
|
+
storedCount = existing.length;
|
|
5159
5461
|
} catch {}
|
|
5160
|
-
|
|
5462
|
+
nextSequence = storedCount + 1;
|
|
5161
5463
|
let streamEnded = "idle";
|
|
5464
|
+
let forwardedAny = false;
|
|
5162
5465
|
try {
|
|
5163
5466
|
const stream = await adapter.tailAgentToolRun(row.run_id, { afterSequence });
|
|
5164
5467
|
const forwarded = await this._forwardAgentToolStream(stream, row.parent_tool_call_id ?? void 0, row.run_id, nextSequence, ceilingController.signal, noProgressTimeoutMs);
|
|
5165
5468
|
nextSequence = forwarded.next;
|
|
5166
5469
|
streamEnded = forwarded.ended;
|
|
5470
|
+
forwardedAny = forwarded.forwarded;
|
|
5167
5471
|
} catch {}
|
|
5168
5472
|
const terminal = await collectTerminal(nextSequence);
|
|
5169
5473
|
if (terminal) return terminal;
|
|
@@ -5172,7 +5476,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
5172
5476
|
break;
|
|
5173
5477
|
}
|
|
5174
5478
|
if (streamEnded !== "done") break;
|
|
5175
|
-
if (
|
|
5479
|
+
if (!forwardedAny) break;
|
|
5176
5480
|
}
|
|
5177
5481
|
} finally {
|
|
5178
5482
|
if (ceilingTimer !== void 0) clearTimeout(ceilingTimer);
|
|
@@ -5202,7 +5506,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
5202
5506
|
display: this._parseAgentToolJson(row.display_metadata)
|
|
5203
5507
|
}, true, connection);
|
|
5204
5508
|
try {
|
|
5205
|
-
sequence = await this._broadcastAgentToolStoredChunks(row, sequence, true, connection);
|
|
5509
|
+
sequence = await this._broadcastAgentToolStoredChunks(row, sequence, true, connection, DEFAULT_AGENT_TOOL_RECOVERY_TIMEOUT_MS);
|
|
5206
5510
|
} catch {}
|
|
5207
5511
|
if (this._isAgentToolTerminal(row.status)) this._broadcastAgentToolTerminal(parentToolCallId, sequence, {
|
|
5208
5512
|
runId: row.run_id,
|
|
@@ -5389,13 +5693,17 @@ var Agent = class Agent extends DurableObject {
|
|
|
5389
5693
|
`.map((row) => row.run_id);
|
|
5390
5694
|
}
|
|
5391
5695
|
async _getAgentToolChunksForRecovery(adapter, runId, timeoutMs) {
|
|
5392
|
-
|
|
5393
|
-
|
|
5696
|
+
return this._settleWithinRecoveryTimeout(adapter.getAgentToolChunks(runId), timeoutMs);
|
|
5697
|
+
}
|
|
5698
|
+
/** Resolve to `undefined` when `promise` rejects or outlasts `timeoutMs`. */
|
|
5699
|
+
async _settleWithinRecoveryTimeout(promise, timeoutMs) {
|
|
5700
|
+
const settled = promise.catch(() => void 0);
|
|
5701
|
+
if (timeoutMs === void 0 || timeoutMs <= 0) return settled;
|
|
5394
5702
|
let timeoutId;
|
|
5395
5703
|
const timeout = new Promise((resolve) => {
|
|
5396
5704
|
timeoutId = setTimeout(() => resolve(void 0), timeoutMs);
|
|
5397
5705
|
});
|
|
5398
|
-
const result = await Promise.race([
|
|
5706
|
+
const result = await Promise.race([settled, timeout]);
|
|
5399
5707
|
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
5400
5708
|
return result;
|
|
5401
5709
|
}
|
|
@@ -6693,4 +7001,4 @@ var StreamingResponse = class {
|
|
|
6693
7001
|
//#endregion
|
|
6694
7002
|
export { routeAgentEmail as a, getCurrentAgent as i, DEFAULT_AGENT_STATIC_OPTIONS as n, StreamingResponse as r, Agent as t };
|
|
6695
7003
|
|
|
6696
|
-
//# sourceMappingURL=src-
|
|
7004
|
+
//# sourceMappingURL=src-BZeu-SCD.js.map
|