agents 0.23.0 → 0.24.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-DE5zmCQ8.d.ts → agent-routing-B2XLNMxq.d.ts} +196 -189
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-tool-types.d.ts +26 -26
- package/dist/{agent-tools-DtXMTDGM.d.ts → agent-tools-Dj5Mzlw7.d.ts} +7 -7
- package/dist/agent-tools.d.ts +21 -21
- package/dist/{capability-BjSKYpzg.js → capability-B4WbF81e.js} +2 -1
- package/dist/capability-B4WbF81e.js.map +1 -0
- package/dist/{capability-runner-Be_-PLR1.d.ts → capability-runner-BUBa6Ake.d.ts} +40 -15
- package/dist/chat/index.d.ts +14 -11
- package/dist/chat/index.js +11 -7
- package/dist/chat/index.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +3 -3
- package/dist/chat-sdk/index.js +1 -1
- package/dist/client-BxdkCuVy.d.ts +411 -0
- package/dist/client-C9DAjZIY.js +518 -0
- package/dist/client-C9DAjZIY.js.map +1 -0
- package/dist/{client-jagG8a9_.js → client-fyQrLGkD.js} +2 -2
- package/dist/{client-jagG8a9_.js.map → client-fyQrLGkD.js.map} +1 -1
- package/dist/client.d.ts +27 -283
- package/dist/client.js +2 -274
- package/dist/current-agent-C4w86kcN.d.ts +93 -0
- package/dist/{current-agent-Da_C9a3b.d.ts → durable-object-lifecycle-ei7M7lqB.d.ts} +13 -122
- package/dist/index-Dlgtd3Mj.d.ts +78 -0
- package/dist/index.d.ts +59 -59
- package/dist/index.js +2 -2
- package/dist/internal_context.d.ts +1 -1
- package/dist/lifecycle/index.d.ts +19 -17
- package/dist/lifecycle/index.js +2 -2
- package/dist/{lifecycle-CMRGjZdw.js → lifecycle-Mm_jQh7r.js} +36 -21
- package/dist/lifecycle-Mm_jQh7r.js.map +1 -0
- package/dist/mcp/client/index.d.ts +20 -20
- package/dist/mcp/client/index.js +1 -1
- package/dist/mcp/index.d.ts +35 -35
- package/dist/mcp/index.js +2 -2
- package/dist/queue/index.d.ts +123 -0
- package/dist/queue/index.js +2 -0
- package/dist/queue-BC9F5cUo.js +406 -0
- package/dist/queue-BC9F5cUo.js.map +1 -0
- package/dist/react.d.ts +33 -15
- package/dist/react.js +31 -8
- package/dist/react.js.map +1 -1
- package/dist/{retries-D9Ds-1lz.d.ts → retries-D9B2UCq3.d.ts} +9 -3
- package/dist/retries.d.ts +5 -3
- package/dist/retries.js +9 -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-Dwh85ZGl.d.ts → scheduler-BGq6M5Kd.d.ts} +6 -6
- package/dist/{scheduler-DD9NdYbF.js → scheduler-D_KHqxBa.js} +4 -11
- package/dist/scheduler-D_KHqxBa.js.map +1 -0
- 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 +1 -1
- package/dist/sessions/index.js +1 -1
- package/dist/{src-DlSHshb2.js → src-BNU3ZiJM.js} +126 -393
- package/dist/src-BNU3ZiJM.js.map +1 -0
- package/dist/state/index.d.ts +6 -0
- package/dist/state/index.js +137 -0
- package/dist/state/index.js.map +1 -0
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.js +1 -1
- package/dist/{streams-D6tJ0NN9.d.ts → streams-BcE8JP2X.d.ts} +2 -2
- package/dist/{streams-DZKgAj9b.js → streams-CCPRV6dt.js} +2 -2
- package/dist/{streams-DZKgAj9b.js.map → streams-CCPRV6dt.js.map} +1 -1
- 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-ylZgBjhj.js → tasks-D4nLqVSI.js} +3 -3
- package/dist/{tasks-ylZgBjhj.js.map → tasks-D4nLqVSI.js.map} +1 -1
- package/dist/{tasks-BRJ5zgya.d.ts → tasks-V2lCT8ZV.d.ts} +5 -5
- package/dist/transport-protocol-BxyngQ_R.js +25 -0
- package/dist/transport-protocol-BxyngQ_R.js.map +1 -0
- package/dist/transport-protocol-ZTew5Wso.d.ts +27 -0
- package/dist/types-DCD6BNZH.d.ts +70 -0
- package/dist/voice/index.d.ts +2 -2
- package/dist/websockets/index.d.ts +178 -69
- package/dist/websockets/index.js +3 -2
- package/dist/websockets-D7IzWbZb.js +1005 -0
- package/dist/websockets-D7IzWbZb.js.map +1 -0
- package/dist/workflow-types.d.ts +25 -25
- package/dist/workflows.d.ts +21 -21
- package/dist/workflows.js +1 -1
- package/docs/agent-class.md +2 -2
- package/docs/client-sdk.md +30 -0
- package/docs/index.md +1 -1
- package/docs/lifecycle.md +97 -22
- package/docs/queue.md +135 -241
- package/docs/retries.md +1 -1
- package/docs/sub-agents.md +3 -3
- package/package.json +12 -2
- package/dist/capability-BjSKYpzg.js.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/lifecycle-CMRGjZdw.js.map +0 -1
- package/dist/scheduler-DD9NdYbF.js.map +0 -1
- package/dist/src-DlSHshb2.js.map +0 -1
- package/dist/websockets-DUfRHPRq.js +0 -502
- package/dist/websockets-DUfRHPRq.js.map +0 -1
|
@@ -5,22 +5,24 @@ import { n as getCurrentAgent$1, t as __DO_NOT_USE_WILL_BREAK__agentContext } fr
|
|
|
5
5
|
import "./internal_context.js";
|
|
6
6
|
import { copyCallableMetadata, decoratedMethods, getCallableMetadata, isCallableMethod } from "./callable-decorator.js";
|
|
7
7
|
import "./types.js";
|
|
8
|
+
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
|
|
8
9
|
import { signAgentHeaders } from "./email.js";
|
|
9
10
|
import { sendAgentEmail } from "./email-send.js";
|
|
10
|
-
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
|
|
11
11
|
import { n as withInvocationScope, r as writeSpanAttributes, t as tracer } from "./cloudflare-Dzvc7V2N.js";
|
|
12
12
|
import { parseSubAgentPath } from "./sub-routing.js";
|
|
13
|
-
import { t as
|
|
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-D7IzWbZb.js";
|
|
14
|
+
import { t as LifecycleCapability } from "./capability-B4WbF81e.js";
|
|
14
15
|
import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
|
|
15
|
-
import { a as abortWithoutAlarmRetry, i as setLifecycleRouteTransport, n as setLifecycleEventSink, r as setLifecycleHostInvoker, t as Lifecycle } from "./lifecycle-
|
|
16
|
+
import { a as abortWithoutAlarmRetry, i as setLifecycleRouteTransport, n as setLifecycleEventSink, r as setLifecycleHostInvoker, t as Lifecycle } from "./lifecycle-Mm_jQh7r.js";
|
|
16
17
|
import { isErrorRetryable, tryN, validateRetryOptions } from "./retries.js";
|
|
17
18
|
import { SqlError } from "./sql-error.js";
|
|
18
|
-
import { o as
|
|
19
|
-
import { a as ensureMcpServerTable, d as DisposableStore, i as normalizeServerId, l as RPC_DO_PREFIX, o as MCPConnectionState, t as MCPClientManager } from "./client-jagG8a9_.js";
|
|
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
|
|
22
|
+
import { n as setSchedulerCallbackResolver, t as Scheduler } from "./scheduler-D_KHqxBa.js";
|
|
23
|
+
import { n as setQueueCallbackResolver, t as Queue } from "./queue-BC9F5cUo.js";
|
|
24
|
+
import { n as setTaskDefinitionResolver, r as setTaskRoutedMemoryLimitHandler, t as Tasks } from "./tasks-D4nLqVSI.js";
|
|
25
|
+
import { State } from "./state/index.js";
|
|
24
26
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
25
27
|
import { DurableObject, RpcTarget, exports } from "cloudflare:workers";
|
|
26
28
|
import { nanoid } from "nanoid";
|
|
@@ -412,14 +414,16 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
412
414
|
}
|
|
413
415
|
/**
|
|
414
416
|
* Clean root-owned bookkeeping for a sub-tree of facets: bulk-cancel
|
|
415
|
-
* schedules and routed Task wake mirrors under the
|
|
416
|
-
* and delete root-side facet fiber recovery leases for
|
|
417
|
+
* schedules, queue items, and routed Task wake mirrors under the
|
|
418
|
+
* owner-path prefix, and delete root-side facet fiber recovery leases for
|
|
419
|
+
* the same sub-tree.
|
|
417
420
|
*/
|
|
418
421
|
async cleanupPrefix(ownerPath) {
|
|
419
422
|
const prefix = agentPathKey(ownerPath);
|
|
420
423
|
if (prefix) {
|
|
421
424
|
await _classPrivateFieldGet2(_host, this).scheduler.__DO_NOT_USE_WILL_BREAK__cleanupRoutePrefix(prefix);
|
|
422
425
|
await _classPrivateFieldGet2(_host, this).tasks.__DO_NOT_USE_WILL_BREAK__cleanupRoutePrefix(prefix);
|
|
426
|
+
await _classPrivateFieldGet2(_host, this)._queue.__DO_NOT_USE_WILL_BREAK__cleanupRoutePrefix(prefix);
|
|
423
427
|
}
|
|
424
428
|
this.deleteRunRowsForPrefix(ownerPath);
|
|
425
429
|
await _classPrivateFieldGet2(_host, this)._syncHostJobs();
|
|
@@ -747,12 +751,12 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
747
751
|
async setConnectionState(connectionId, state) {
|
|
748
752
|
const connection = _classPrivateFieldGet2(_host, this)._webSockets.getConnection(connectionId);
|
|
749
753
|
if (!connection || !this.connectionHasChildTarget(connection)) return null;
|
|
750
|
-
|
|
754
|
+
ensureConnectionWrapped(connection);
|
|
751
755
|
connection.setState(state);
|
|
752
756
|
return this.getForwardedState(connection);
|
|
753
757
|
}
|
|
754
758
|
connectionTargetPath(connection) {
|
|
755
|
-
|
|
759
|
+
ensureConnectionWrapped(connection);
|
|
756
760
|
const outerUri = _classPrivateFieldGet2(_host, this)._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY);
|
|
757
761
|
if (typeof outerUri !== "string") return null;
|
|
758
762
|
return _assertClassBrand(_DynamicAgentsInternal_brand, this, _pathFromOuterUri).call(this, outerUri)?.path ?? null;
|
|
@@ -762,7 +766,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
762
766
|
return a.every((step, index) => step.className === b[index]?.className && step.name === b[index]?.name);
|
|
763
767
|
}
|
|
764
768
|
connectionHasChildTarget(connection) {
|
|
765
|
-
|
|
769
|
+
ensureConnectionWrapped(connection);
|
|
766
770
|
return typeof _classPrivateFieldGet2(_host, this)._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY) === "string";
|
|
767
771
|
}
|
|
768
772
|
connectionTargetsChild(connection) {
|
|
@@ -799,7 +803,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
799
803
|
const request = new Request(meta.uri ?? "http://placeholder/", { headers: meta.requestHeaders });
|
|
800
804
|
if (await this.forwardWebSocketConnect(connection, request, { gate: true })) return;
|
|
801
805
|
if (_classPrivateFieldGet2(_host, this).shouldConnectionBeReadonly(connection, { request })) _classPrivateFieldGet2(_host, this).setConnectionReadonly(connection, true);
|
|
802
|
-
if (!_classPrivateFieldGet2(_host, this).shouldSendProtocolMessages(connection, { request }))
|
|
806
|
+
if (!_classPrivateFieldGet2(_host, this).shouldSendProtocolMessages(connection, { request })) setConnectionProtocolEnabled(connection, false);
|
|
803
807
|
const childTags = await _classPrivateFieldGet2(_host, this).getConnectionTags(connection, { request });
|
|
804
808
|
connection.tags = [connection.id, ...childTags.filter((tag) => tag !== connection.id)];
|
|
805
809
|
this.storeVirtualConnection(connection);
|
|
@@ -881,7 +885,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
881
885
|
removeEventListener() {}
|
|
882
886
|
};
|
|
883
887
|
stored.connection = connection;
|
|
884
|
-
|
|
888
|
+
ensureConnectionWrapped(connection);
|
|
885
889
|
return connection;
|
|
886
890
|
}
|
|
887
891
|
storeVirtualConnection(connection) {
|
|
@@ -921,8 +925,7 @@ var DynamicAgentsInternal = class extends LifecycleCapability {
|
|
|
921
925
|
for (const meta of metas) _classPrivateFieldGet2(_virtualConnections, this).set(meta.id, { meta });
|
|
922
926
|
}
|
|
923
927
|
getRawConnectionState(connection) {
|
|
924
|
-
|
|
925
|
-
return _classPrivateFieldGet2(_host, this)._rawStateAccessors.get(connection)?.getRaw() ?? null;
|
|
928
|
+
return getConnectionRawState(connection);
|
|
926
929
|
}
|
|
927
930
|
getForwardedState(connection) {
|
|
928
931
|
const raw = this.getRawConnectionState(connection);
|
|
@@ -1022,7 +1025,7 @@ function _reportConnectionOperationFailure(connectionId, operation, error) {
|
|
|
1022
1025
|
});
|
|
1023
1026
|
}
|
|
1024
1027
|
function _connectionMetaForPath(connection, ownerPath) {
|
|
1025
|
-
|
|
1028
|
+
ensureConnectionWrapped(connection);
|
|
1026
1029
|
const outerUri = _classPrivateFieldGet2(_host, this)._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY);
|
|
1027
1030
|
if (typeof outerUri !== "string") return null;
|
|
1028
1031
|
const target = _assertClassBrand(_DynamicAgentsInternal_brand, this, _pathFromOuterUri).call(this, outerUri, ownerPath);
|
|
@@ -1072,7 +1075,7 @@ function _createConnectionBridge(connection) {
|
|
|
1072
1075
|
});
|
|
1073
1076
|
}
|
|
1074
1077
|
async function _resolveConnection(connection, request, options = { gate: false }) {
|
|
1075
|
-
|
|
1078
|
+
ensureConnectionWrapped(connection);
|
|
1076
1079
|
const outerUri = _classPrivateFieldGet2(_host, this)._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY);
|
|
1077
1080
|
const uri = typeof outerUri === "string" ? outerUri : connection.uri;
|
|
1078
1081
|
if (!uri) return null;
|
|
@@ -1213,12 +1216,6 @@ function sendRpcResponseIfOpen(connection, response) {
|
|
|
1213
1216
|
function isRPCRequest(msg) {
|
|
1214
1217
|
return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "rpc" && "id" in msg && typeof msg.id === "string" && "method" in msg && typeof msg.method === "string" && "args" in msg && Array.isArray(msg.args);
|
|
1215
1218
|
}
|
|
1216
|
-
/**
|
|
1217
|
-
* Type guard for state update messages
|
|
1218
|
-
*/
|
|
1219
|
-
function isStateUpdateMessage(msg) {
|
|
1220
|
-
return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "cf_agent_state" && "state" in msg;
|
|
1221
|
-
}
|
|
1222
1219
|
const _fiberALS = new AsyncLocalStorage();
|
|
1223
1220
|
const DEFAULT_KEEP_ALIVE_INTERVAL_MS = 3e4;
|
|
1224
1221
|
const DEFAULT_AGENT_TOOL_RECOVERY_TIMEOUT_MS = 2e3;
|
|
@@ -1247,57 +1244,15 @@ const DETACHED_NOTIFY_CALLBACK = "_cfDetachedNotifyFinish";
|
|
|
1247
1244
|
/**
|
|
1248
1245
|
* Schema version for the Agent's internal SQLite tables.
|
|
1249
1246
|
* Bump this when adding new tables, columns, or migrations.
|
|
1250
|
-
* The constructor stores this
|
|
1251
|
-
*
|
|
1247
|
+
* The constructor stores this under a namespaced KV key (the same convention
|
|
1248
|
+
* every capability uses for its own schema version) and checks it on wake to
|
|
1249
|
+
* skip DDL on established DOs.
|
|
1252
1250
|
*/
|
|
1253
1251
|
const CURRENT_SCHEMA_VERSION = 11;
|
|
1254
|
-
const
|
|
1255
|
-
const
|
|
1256
|
-
const STATE_WAS_CHANGED = "cf_state_was_changed";
|
|
1252
|
+
const SCHEMA_VERSION_KEY = "cf_agents:schema_version";
|
|
1253
|
+
const LEGACY_SCHEMA_VERSION_ROW_ID = "cf_schema_version";
|
|
1257
1254
|
const DEFAULT_STATE = {};
|
|
1258
|
-
|
|
1259
|
-
* Internal key used to store the readonly flag in connection state.
|
|
1260
|
-
* Prefixed with _cf_ to avoid collision with user state keys.
|
|
1261
|
-
*/
|
|
1262
|
-
const CF_READONLY_KEY = "_cf_readonly";
|
|
1263
|
-
/**
|
|
1264
|
-
* Internal key used to store the no-protocol flag in connection state.
|
|
1265
|
-
* When set, protocol messages (identity, state sync, MCP servers) are not
|
|
1266
|
-
* sent to this connection — neither on connect nor via broadcasts.
|
|
1267
|
-
*/
|
|
1268
|
-
const CF_NO_PROTOCOL_KEY = "_cf_no_protocol";
|
|
1269
|
-
/**
|
|
1270
|
-
* The set of all internal keys stored in connection state that must be
|
|
1271
|
-
* hidden from user code and preserved across setState calls.
|
|
1272
|
-
*/
|
|
1273
|
-
const CF_INTERNAL_KEYS = /* @__PURE__ */ new Set([
|
|
1274
|
-
CF_READONLY_KEY,
|
|
1275
|
-
CF_NO_PROTOCOL_KEY,
|
|
1276
|
-
"_cf_voiceInCall",
|
|
1277
|
-
CF_SUB_AGENT_OUTER_URL_KEY,
|
|
1278
|
-
CF_SUB_AGENT_TAGS_KEY
|
|
1279
|
-
]);
|
|
1280
|
-
/** Check if a raw connection state object contains any internal keys. */
|
|
1281
|
-
function rawHasInternalKeys(raw) {
|
|
1282
|
-
for (const key of Object.keys(raw)) if (CF_INTERNAL_KEYS.has(key)) return true;
|
|
1283
|
-
return false;
|
|
1284
|
-
}
|
|
1285
|
-
/** Return a copy of `raw` with all internal keys removed, or null if no user keys remain. */
|
|
1286
|
-
function stripInternalKeys(raw) {
|
|
1287
|
-
const result = {};
|
|
1288
|
-
let hasUserKeys = false;
|
|
1289
|
-
for (const key of Object.keys(raw)) if (!CF_INTERNAL_KEYS.has(key)) {
|
|
1290
|
-
result[key] = raw[key];
|
|
1291
|
-
hasUserKeys = true;
|
|
1292
|
-
}
|
|
1293
|
-
return hasUserKeys ? result : null;
|
|
1294
|
-
}
|
|
1295
|
-
/** Return a copy containing only the internal keys present in `raw`. */
|
|
1296
|
-
function extractInternalFlags(raw) {
|
|
1297
|
-
const result = {};
|
|
1298
|
-
for (const key of Object.keys(raw)) if (CF_INTERNAL_KEYS.has(key)) result[key] = raw[key];
|
|
1299
|
-
return result;
|
|
1300
|
-
}
|
|
1255
|
+
registerInternalConnectionKeys("_cf_voiceInCall", CF_SUB_AGENT_OUTER_URL_KEY, CF_SUB_AGENT_TAGS_KEY);
|
|
1301
1256
|
/** Max length for error strings broadcast to clients. */
|
|
1302
1257
|
const MAX_ERROR_STRING_LENGTH = 500;
|
|
1303
1258
|
/**
|
|
@@ -1388,27 +1343,6 @@ const DEFAULT_AGENT_STATIC_OPTIONS = {
|
|
|
1388
1343
|
*/
|
|
1389
1344
|
maxAlarmMemoryLimitStrikes: 3
|
|
1390
1345
|
};
|
|
1391
|
-
/**
|
|
1392
|
-
* Parse the raw `retry_options` TEXT column from a SQLite row into a
|
|
1393
|
-
* typed `RetryOptions` object, or `undefined` if not set.
|
|
1394
|
-
*/
|
|
1395
|
-
function parseRetryOptions(row) {
|
|
1396
|
-
const raw = row.retry_options;
|
|
1397
|
-
if (typeof raw !== "string") return void 0;
|
|
1398
|
-
return JSON.parse(raw);
|
|
1399
|
-
}
|
|
1400
|
-
/**
|
|
1401
|
-
* Resolve per-task retry options against class-level defaults and call
|
|
1402
|
-
* `tryN`. This is the retry-execution path for queue flush; Scheduler owns
|
|
1403
|
-
* its own copy for schedule callbacks.
|
|
1404
|
-
*/
|
|
1405
|
-
function resolveRetryConfig(taskRetry, defaults) {
|
|
1406
|
-
return {
|
|
1407
|
-
maxAttempts: taskRetry?.maxAttempts ?? defaults.maxAttempts,
|
|
1408
|
-
baseDelayMs: taskRetry?.baseDelayMs ?? defaults.baseDelayMs,
|
|
1409
|
-
maxDelayMs: taskRetry?.maxDelayMs ?? defaults.maxDelayMs
|
|
1410
|
-
};
|
|
1411
|
-
}
|
|
1412
1346
|
/** Compatibility alias for the lifecycle-owned current Agent accessor. */
|
|
1413
1347
|
const getCurrentAgent = getCurrentAgent$1;
|
|
1414
1348
|
/**
|
|
@@ -1433,7 +1367,7 @@ function withAgentContext(method) {
|
|
|
1433
1367
|
/**
|
|
1434
1368
|
* Base class for creating Agent implementations
|
|
1435
1369
|
* @template Env Environment type containing bindings
|
|
1436
|
-
* @template
|
|
1370
|
+
* @template TState State type to store within the Agent
|
|
1437
1371
|
*/
|
|
1438
1372
|
var Agent = class Agent extends DurableObject {
|
|
1439
1373
|
/** Run user initialization after lifecycle components have started. */
|
|
@@ -1505,31 +1439,16 @@ var Agent = class Agent extends DurableObject {
|
|
|
1505
1439
|
return this.ctx.id.toString();
|
|
1506
1440
|
}
|
|
1507
1441
|
/**
|
|
1508
|
-
* Current state of the Agent
|
|
1442
|
+
* Current state of the Agent.
|
|
1443
|
+
*
|
|
1444
|
+
* Delegates to the State capability, which owns lazy load and the
|
|
1445
|
+
* in-memory cache; Agent seeds `initialState` on first access.
|
|
1509
1446
|
*/
|
|
1510
1447
|
get state() {
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
if (result.length > 0) {
|
|
1516
|
-
const state = result[0].state;
|
|
1517
|
-
try {
|
|
1518
|
-
this._state = JSON.parse(state);
|
|
1519
|
-
} catch (e) {
|
|
1520
|
-
console.error("Failed to parse stored state, falling back to initialState:", e);
|
|
1521
|
-
if (this.initialState !== DEFAULT_STATE) {
|
|
1522
|
-
this._state = this.initialState;
|
|
1523
|
-
this._setStateInternal(this.initialState);
|
|
1524
|
-
} else {
|
|
1525
|
-
this.sql`DELETE FROM cf_agents_state WHERE id = ${STATE_ROW_ID}`;
|
|
1526
|
-
return;
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
return this._state;
|
|
1530
|
-
}
|
|
1531
|
-
if (this.initialState === DEFAULT_STATE) return;
|
|
1532
|
-
this._setStateInternal(this.initialState);
|
|
1448
|
+
const stored = this._state.get();
|
|
1449
|
+
if (stored !== void 0) return stored;
|
|
1450
|
+
if (this.initialState === DEFAULT_STATE) return void 0;
|
|
1451
|
+
this._state.set(this.initialState, "server");
|
|
1533
1452
|
return this.initialState;
|
|
1534
1453
|
}
|
|
1535
1454
|
get _resolvedOptions() {
|
|
@@ -1615,26 +1534,9 @@ var Agent = class Agent extends DurableObject {
|
|
|
1615
1534
|
* local dev and the constructor only runs once per DO instance).
|
|
1616
1535
|
*/
|
|
1617
1536
|
_ensureSchema() {
|
|
1618
|
-
this.
|
|
1619
|
-
CREATE TABLE IF NOT EXISTS cf_agents_state (
|
|
1620
|
-
id TEXT PRIMARY KEY NOT NULL,
|
|
1621
|
-
state TEXT
|
|
1622
|
-
)
|
|
1623
|
-
`;
|
|
1624
|
-
const versionRow = this.sql`
|
|
1625
|
-
SELECT state FROM cf_agents_state WHERE id = ${SCHEMA_VERSION_ROW_ID}
|
|
1626
|
-
`;
|
|
1627
|
-
const schemaVersion = versionRow.length > 0 ? Number(versionRow[0].state) : 0;
|
|
1537
|
+
const schemaVersion = this._readSchemaVersion();
|
|
1628
1538
|
if (schemaVersion < CURRENT_SCHEMA_VERSION) {
|
|
1629
1539
|
ensureMcpServerTable(this.ctx.storage);
|
|
1630
|
-
this.sql`
|
|
1631
|
-
CREATE TABLE IF NOT EXISTS cf_agents_queues (
|
|
1632
|
-
id TEXT PRIMARY KEY NOT NULL,
|
|
1633
|
-
payload TEXT,
|
|
1634
|
-
callback TEXT,
|
|
1635
|
-
created_at INTEGER DEFAULT (unixepoch())
|
|
1636
|
-
)
|
|
1637
|
-
`;
|
|
1638
1540
|
const addColumnIfNotExists = (sql) => {
|
|
1639
1541
|
try {
|
|
1640
1542
|
this.ctx.storage.sql.exec(sql);
|
|
@@ -1642,7 +1544,6 @@ var Agent = class Agent extends DurableObject {
|
|
|
1642
1544
|
if (!(error instanceof Error ? error.message : String(error)).toLowerCase().includes("duplicate column")) throw error;
|
|
1643
1545
|
}
|
|
1644
1546
|
};
|
|
1645
|
-
addColumnIfNotExists("ALTER TABLE cf_agents_queues ADD COLUMN retry_options TEXT");
|
|
1646
1547
|
this.sql`
|
|
1647
1548
|
CREATE TABLE IF NOT EXISTS cf_agents_workflows (
|
|
1648
1549
|
id TEXT PRIMARY KEY NOT NULL,
|
|
@@ -1667,7 +1568,6 @@ var Agent = class Agent extends DurableObject {
|
|
|
1667
1568
|
this.sql`
|
|
1668
1569
|
CREATE INDEX IF NOT EXISTS idx_workflows_name ON cf_agents_workflows(workflow_name)
|
|
1669
1570
|
`;
|
|
1670
|
-
this.ctx.storage.sql.exec("DELETE FROM cf_agents_state WHERE id = ?", STATE_WAS_CHANGED);
|
|
1671
1571
|
this.sql`
|
|
1672
1572
|
CREATE TABLE IF NOT EXISTS cf_agents_runs (
|
|
1673
1573
|
id TEXT PRIMARY KEY NOT NULL,
|
|
@@ -1752,10 +1652,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
1752
1652
|
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN detached_no_progress_budget_ms INTEGER");
|
|
1753
1653
|
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN last_progress_at INTEGER");
|
|
1754
1654
|
addColumnIfNotExists("ALTER TABLE cf_agent_tool_runs ADD COLUMN detached_on_milestones TEXT");
|
|
1755
|
-
this.
|
|
1756
|
-
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
1757
|
-
VALUES (${SCHEMA_VERSION_ROW_ID}, ${String(CURRENT_SCHEMA_VERSION)})
|
|
1758
|
-
`;
|
|
1655
|
+
this.ctx.storage.kv.put(SCHEMA_VERSION_KEY, CURRENT_SCHEMA_VERSION);
|
|
1759
1656
|
}
|
|
1760
1657
|
this._schemaInitialization = {
|
|
1761
1658
|
previousVersion: schemaVersion,
|
|
@@ -1763,9 +1660,31 @@ var Agent = class Agent extends DurableObject {
|
|
|
1763
1660
|
migrated: schemaVersion < CURRENT_SCHEMA_VERSION
|
|
1764
1661
|
};
|
|
1765
1662
|
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Read the Agent's schema version from its KV key. A DO created before the
|
|
1665
|
+
* State capability owned `cf_agents_state` has the version as a row in that
|
|
1666
|
+
* table instead: read it once, move it to the key, and delete the row so the
|
|
1667
|
+
* table is left with a single owner. Synchronous (`storage.kv`) because the
|
|
1668
|
+
* constructor gates DDL on it.
|
|
1669
|
+
*/
|
|
1670
|
+
_readSchemaVersion() {
|
|
1671
|
+
const stored = this.ctx.storage.kv.get(SCHEMA_VERSION_KEY);
|
|
1672
|
+
if (stored !== void 0) return stored;
|
|
1673
|
+
if (!(this.ctx.storage.sql.exec("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'cf_agents_state'").toArray().length > 0)) return 0;
|
|
1674
|
+
const rows = this.ctx.storage.sql.exec("SELECT state FROM cf_agents_state WHERE id = ?", LEGACY_SCHEMA_VERSION_ROW_ID).toArray();
|
|
1675
|
+
if (rows.length === 0) return 0;
|
|
1676
|
+
const version = Number(rows[0].state) || 0;
|
|
1677
|
+
this.ctx.storage.kv.put(SCHEMA_VERSION_KEY, version);
|
|
1678
|
+
this.ctx.storage.sql.exec("DELETE FROM cf_agents_state WHERE id = ?", LEGACY_SCHEMA_VERSION_ROW_ID);
|
|
1679
|
+
return version;
|
|
1680
|
+
}
|
|
1766
1681
|
constructor(ctx, env) {
|
|
1767
1682
|
super(ctx, env);
|
|
1768
1683
|
this.lifecycle = Lifecycle.install(this, { maxAlarmMemoryLimitStrikes: this._resolvedOptions.maxAlarmMemoryLimitStrikes });
|
|
1684
|
+
this._state = new State({
|
|
1685
|
+
validateStateChange: (nextState, source) => this.validateStateChange(nextState, source),
|
|
1686
|
+
onChanged: (nextState, source) => this._handleStateChanged(nextState, source)
|
|
1687
|
+
});
|
|
1769
1688
|
this._webSockets = new WebSockets({
|
|
1770
1689
|
handlers: {
|
|
1771
1690
|
onConnect: (connection, ctx) => this.onConnect(connection, ctx),
|
|
@@ -1773,13 +1692,12 @@ var Agent = class Agent extends DurableObject {
|
|
|
1773
1692
|
onClose: (connection, code, reason, wasClean) => this.onClose(connection, code, reason, wasClean),
|
|
1774
1693
|
onError: (connection, error) => this.onError(connection, error)
|
|
1775
1694
|
},
|
|
1776
|
-
|
|
1695
|
+
protocol: false,
|
|
1696
|
+
state: this._state,
|
|
1777
1697
|
getConnectionTags: (connection, ctx) => this.getConnectionTags(connection, ctx)
|
|
1778
1698
|
});
|
|
1779
|
-
this._state = DEFAULT_STATE;
|
|
1780
1699
|
this._disposables = new DisposableStore();
|
|
1781
1700
|
this._destroyed = false;
|
|
1782
|
-
this._rawStateAccessors = /* @__PURE__ */ new WeakMap();
|
|
1783
1701
|
this._persistenceHookMode = "none";
|
|
1784
1702
|
this._isFacet = false;
|
|
1785
1703
|
this._protocolBroadcastExcludeIds = /* @__PURE__ */ new Set();
|
|
@@ -1797,7 +1715,6 @@ var Agent = class Agent extends DurableObject {
|
|
|
1797
1715
|
this._ParentClass = Object.getPrototypeOf(this).constructor;
|
|
1798
1716
|
this.initialState = DEFAULT_STATE;
|
|
1799
1717
|
this.observability = genericObservability;
|
|
1800
|
-
this._flushingQueue = false;
|
|
1801
1718
|
this.maxConcurrentAgentTools = Infinity;
|
|
1802
1719
|
const routeHost = this;
|
|
1803
1720
|
setLifecycleRouteTransport(this.lifecycle, {
|
|
@@ -1832,6 +1749,20 @@ var Agent = class Agent extends DurableObject {
|
|
|
1832
1749
|
if (typeof method !== "function") return void 0;
|
|
1833
1750
|
return (payload, schedule) => method.call(this, payload, schedule);
|
|
1834
1751
|
});
|
|
1752
|
+
this._queue = new Queue({
|
|
1753
|
+
retry: this._resolvedOptions.retry,
|
|
1754
|
+
onError: (error) => runInInvocation({
|
|
1755
|
+
agent: this,
|
|
1756
|
+
connection: void 0,
|
|
1757
|
+
request: void 0,
|
|
1758
|
+
email: void 0
|
|
1759
|
+
}, () => this.onError(error))
|
|
1760
|
+
});
|
|
1761
|
+
setQueueCallbackResolver(this._queue, (name) => {
|
|
1762
|
+
const method = this[name];
|
|
1763
|
+
if (typeof method !== "function") return void 0;
|
|
1764
|
+
return (payload, item) => method.call(this, payload, item);
|
|
1765
|
+
});
|
|
1835
1766
|
this.tasks = new Tasks({ onError: (error) => this.onError(error) });
|
|
1836
1767
|
setTaskRoutedMemoryLimitHandler(this.tasks, (context) => {
|
|
1837
1768
|
return this.onAlarmMemoryLimit?.call(this, context);
|
|
@@ -1857,7 +1788,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
1857
1788
|
createAuthProvider: (callbackUrl) => this.createMcpOAuthProvider(callbackUrl)
|
|
1858
1789
|
});
|
|
1859
1790
|
});
|
|
1860
|
-
this.lifecycle.use(this.scheduler).use(this.mcp).use(this._webSockets
|
|
1791
|
+
this.lifecycle.use(this.scheduler).use(this._queue).use(this.mcp).use(this._state).use(this._webSockets).use(this.tasks).use(this._dynamicAgents);
|
|
1861
1792
|
let mcpBroadcastReady = false;
|
|
1862
1793
|
this._disposables.add(this.mcp.onServerStateChanged(() => {
|
|
1863
1794
|
if (mcpBroadcastReady) this.broadcastMcpServers();
|
|
@@ -1907,7 +1838,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
1907
1838
|
this.onMessage = async (connection, message) => {
|
|
1908
1839
|
const replyBridge = dynamicAgentRpcReplyContext.getStore()?.bridge;
|
|
1909
1840
|
if (await __DO_NOT_USE_WILL_BREAK__agentContext.exit(() => this._cf_forwardSubAgentWebSocketMessage(connection, message, replyBridge))) return;
|
|
1910
|
-
|
|
1841
|
+
ensureConnectionWrapped(connection);
|
|
1911
1842
|
return runInInvocation({
|
|
1912
1843
|
agent: this,
|
|
1913
1844
|
connection,
|
|
@@ -1921,25 +1852,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
1921
1852
|
} catch (_e) {
|
|
1922
1853
|
return this._tryCatch(() => _onMessage(connection, message));
|
|
1923
1854
|
}
|
|
1924
|
-
if (
|
|
1925
|
-
if (this.isConnectionReadonly(connection)) {
|
|
1926
|
-
connection.send(JSON.stringify({
|
|
1927
|
-
type: "cf_agent_state_error",
|
|
1928
|
-
error: "Connection is readonly"
|
|
1929
|
-
}));
|
|
1930
|
-
return;
|
|
1931
|
-
}
|
|
1932
|
-
try {
|
|
1933
|
-
this._setStateInternal(parsed.state, connection);
|
|
1934
|
-
} catch (e) {
|
|
1935
|
-
console.error("[Agent] State update rejected:", e);
|
|
1936
|
-
connection.send(JSON.stringify({
|
|
1937
|
-
type: "cf_agent_state_error",
|
|
1938
|
-
error: "State update rejected"
|
|
1939
|
-
}));
|
|
1940
|
-
}
|
|
1941
|
-
return;
|
|
1942
|
-
}
|
|
1855
|
+
if (this._webSockets.applyStateFrame(connection, parsed)) return;
|
|
1943
1856
|
if (isRPCRequest(parsed)) {
|
|
1944
1857
|
try {
|
|
1945
1858
|
const { id, method, args } = parsed;
|
|
@@ -2003,7 +1916,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
2003
1916
|
};
|
|
2004
1917
|
const _onConnect = this.onConnect.bind(this);
|
|
2005
1918
|
this.onConnect = async (connection, ctx) => {
|
|
2006
|
-
|
|
1919
|
+
ensureConnectionWrapped(connection);
|
|
2007
1920
|
const subAgentOuterUrl = ctx.request.headers.get(SUB_AGENT_OUTER_URL_HEADER);
|
|
2008
1921
|
if (subAgentOuterUrl) this._unsafe_setConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY, subAgentOuterUrl);
|
|
2009
1922
|
if (await __DO_NOT_USE_WILL_BREAK__agentContext.exit(() => this._cf_forwardSubAgentWebSocketConnect(connection, ctx.request, { gate: false }))) return;
|
|
@@ -2023,11 +1936,10 @@ var Agent = class Agent extends DurableObject {
|
|
|
2023
1936
|
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.`);
|
|
2024
1937
|
}
|
|
2025
1938
|
}
|
|
2026
|
-
|
|
1939
|
+
this._webSockets.sendIdentity(connection, {
|
|
2027
1940
|
name: this.name,
|
|
2028
|
-
agent: camelCaseToKebabCase(this._ParentClass.name)
|
|
2029
|
-
|
|
2030
|
-
}));
|
|
1941
|
+
agent: camelCaseToKebabCase(this._ParentClass.name)
|
|
1942
|
+
});
|
|
2031
1943
|
}
|
|
2032
1944
|
const wasExcludedFromStateInitBroadcast = this._protocolBroadcastExcludeIds.has(connection.id);
|
|
2033
1945
|
let currentState;
|
|
@@ -2037,15 +1949,12 @@ var Agent = class Agent extends DurableObject {
|
|
|
2037
1949
|
} finally {
|
|
2038
1950
|
if (!wasExcludedFromStateInitBroadcast) this._protocolBroadcastExcludeIds.delete(connection.id);
|
|
2039
1951
|
}
|
|
2040
|
-
if (currentState !== void 0)
|
|
2041
|
-
state: currentState,
|
|
2042
|
-
type: "cf_agent_state"
|
|
2043
|
-
}));
|
|
1952
|
+
if (currentState !== void 0) this._webSockets.sendState(connection);
|
|
2044
1953
|
connection.send(JSON.stringify({
|
|
2045
1954
|
mcp: this.getMcpServers(),
|
|
2046
1955
|
type: "cf_agent_mcp_servers"
|
|
2047
1956
|
}));
|
|
2048
|
-
} else this.
|
|
1957
|
+
} else this._webSockets.setProtocolEnabled(connection, false);
|
|
2049
1958
|
this._emit("connect", { connectionId: connection.id });
|
|
2050
1959
|
await this._replayAgentToolRuns(connection);
|
|
2051
1960
|
return this._tryCatch(() => _onConnect(connection, ctx));
|
|
@@ -2142,13 +2051,14 @@ var Agent = class Agent extends DurableObject {
|
|
|
2142
2051
|
for (const conn of this.getConnections()) if (!this.isConnectionProtocolEnabled(conn)) exclude.push(conn.id);
|
|
2143
2052
|
this.broadcast(msg, exclude);
|
|
2144
2053
|
}
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2054
|
+
/**
|
|
2055
|
+
* React to a persisted state change from the State capability.
|
|
2056
|
+
*
|
|
2057
|
+
* Reproduces the pre-migration steps 3-4: broadcast the new state to
|
|
2058
|
+
* protocol-enabled connections (excluding the originating connection) and
|
|
2059
|
+
* run the notification hook off the invocation tail.
|
|
2060
|
+
*/
|
|
2061
|
+
_handleStateChanged(nextState, source) {
|
|
2152
2062
|
this._broadcastProtocol(JSON.stringify({
|
|
2153
2063
|
state: nextState,
|
|
2154
2064
|
type: "cf_agent_state"
|
|
@@ -2180,69 +2090,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
2180
2090
|
setState(state) {
|
|
2181
2091
|
const store = __DO_NOT_USE_WILL_BREAK__agentContext.getStore();
|
|
2182
2092
|
if (store?.connection && this.isConnectionReadonly(store.connection)) throw new Error("Connection is readonly");
|
|
2183
|
-
this.
|
|
2184
|
-
}
|
|
2185
|
-
/**
|
|
2186
|
-
* Wraps connection.state and connection.setState so that internal
|
|
2187
|
-
* _cf_-prefixed flags (readonly, no-protocol) are hidden from user code
|
|
2188
|
-
* and cannot be accidentally overwritten.
|
|
2189
|
-
*
|
|
2190
|
-
* Idempotent — safe to call multiple times on the same connection.
|
|
2191
|
-
* After hibernation, the _rawStateAccessors WeakMap is empty but the
|
|
2192
|
-
* connection's state getter still reads from the persisted WebSocket
|
|
2193
|
-
* attachment. Calling this method re-captures the raw getter so that
|
|
2194
|
-
* predicate methods (isConnectionReadonly, isConnectionProtocolEnabled)
|
|
2195
|
-
* work correctly post-hibernation.
|
|
2196
|
-
*/
|
|
2197
|
-
_ensureConnectionWrapped(connection) {
|
|
2198
|
-
if (this._rawStateAccessors.has(connection)) return;
|
|
2199
|
-
const descriptor = Object.getOwnPropertyDescriptor(connection, "state");
|
|
2200
|
-
let getRaw;
|
|
2201
|
-
let setRaw;
|
|
2202
|
-
if (descriptor?.get) {
|
|
2203
|
-
getRaw = descriptor.get.bind(connection);
|
|
2204
|
-
setRaw = connection.setState.bind(connection);
|
|
2205
|
-
} else {
|
|
2206
|
-
let rawState = connection.state ?? null;
|
|
2207
|
-
getRaw = () => rawState;
|
|
2208
|
-
setRaw = (state) => {
|
|
2209
|
-
rawState = state;
|
|
2210
|
-
return rawState;
|
|
2211
|
-
};
|
|
2212
|
-
}
|
|
2213
|
-
this._rawStateAccessors.set(connection, {
|
|
2214
|
-
getRaw,
|
|
2215
|
-
setRaw
|
|
2216
|
-
});
|
|
2217
|
-
Object.defineProperty(connection, "state", {
|
|
2218
|
-
configurable: true,
|
|
2219
|
-
enumerable: true,
|
|
2220
|
-
get() {
|
|
2221
|
-
const raw = getRaw();
|
|
2222
|
-
if (raw != null && typeof raw === "object" && rawHasInternalKeys(raw)) return stripInternalKeys(raw);
|
|
2223
|
-
return raw;
|
|
2224
|
-
}
|
|
2225
|
-
});
|
|
2226
|
-
Object.defineProperty(connection, "setState", {
|
|
2227
|
-
configurable: true,
|
|
2228
|
-
writable: true,
|
|
2229
|
-
value(stateOrFn) {
|
|
2230
|
-
const raw = getRaw();
|
|
2231
|
-
const flags = raw != null && typeof raw === "object" ? extractInternalFlags(raw) : {};
|
|
2232
|
-
const hasFlags = Object.keys(flags).length > 0;
|
|
2233
|
-
let newUserState;
|
|
2234
|
-
if (typeof stateOrFn === "function") newUserState = stateOrFn(hasFlags ? stripInternalKeys(raw) : raw);
|
|
2235
|
-
else newUserState = stateOrFn;
|
|
2236
|
-
if (hasFlags) {
|
|
2237
|
-
if (newUserState != null && typeof newUserState === "object") return setRaw({
|
|
2238
|
-
...newUserState,
|
|
2239
|
-
...flags
|
|
2240
|
-
});
|
|
2241
|
-
return setRaw(flags);
|
|
2242
|
-
}
|
|
2243
|
-
return setRaw(newUserState);
|
|
2244
|
-
}
|
|
2245
|
-
});
|
|
2093
|
+
this._state.set(state, "server");
|
|
2246
2094
|
}
|
|
2247
2095
|
/**
|
|
2248
2096
|
* Mark a connection as readonly or readwrite
|
|
@@ -2250,17 +2098,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
2250
2098
|
* @param readonly Whether the connection should be readonly (default: true)
|
|
2251
2099
|
*/
|
|
2252
2100
|
setConnectionReadonly(connection, readonly = true) {
|
|
2253
|
-
|
|
2254
|
-
const accessors = this._rawStateAccessors.get(connection);
|
|
2255
|
-
const raw = accessors.getRaw() ?? {};
|
|
2256
|
-
if (readonly) accessors.setRaw({
|
|
2257
|
-
...raw,
|
|
2258
|
-
[CF_READONLY_KEY]: true
|
|
2259
|
-
});
|
|
2260
|
-
else {
|
|
2261
|
-
const { [CF_READONLY_KEY]: _, ...rest } = raw;
|
|
2262
|
-
accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);
|
|
2263
|
-
}
|
|
2101
|
+
setConnectionReadonly(connection, readonly);
|
|
2264
2102
|
}
|
|
2265
2103
|
/**
|
|
2266
2104
|
* Check if a connection is marked as readonly.
|
|
@@ -2271,8 +2109,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
2271
2109
|
* @returns True if the connection is readonly
|
|
2272
2110
|
*/
|
|
2273
2111
|
isConnectionReadonly(connection) {
|
|
2274
|
-
|
|
2275
|
-
return !!this._rawStateAccessors.get(connection).getRaw()?.[CF_READONLY_KEY];
|
|
2112
|
+
return isConnectionReadonly(connection);
|
|
2276
2113
|
}
|
|
2277
2114
|
/**
|
|
2278
2115
|
* ⚠️ INTERNAL — DO NOT USE IN APPLICATION CODE. ⚠️
|
|
@@ -2287,30 +2124,20 @@ var Agent = class Agent extends DurableObject {
|
|
|
2287
2124
|
* @internal
|
|
2288
2125
|
*/
|
|
2289
2126
|
_unsafe_getConnectionFlag(connection, key) {
|
|
2290
|
-
|
|
2291
|
-
return this._rawStateAccessors.get(connection).getRaw()?.[key];
|
|
2127
|
+
return getConnectionFlag(connection, key);
|
|
2292
2128
|
}
|
|
2293
2129
|
/**
|
|
2294
2130
|
* ⚠️ INTERNAL — DO NOT USE IN APPLICATION CODE. ⚠️
|
|
2295
2131
|
*
|
|
2296
2132
|
* Write an internal `_cf_`-prefixed flag to the raw connection state,
|
|
2297
2133
|
* bypassing the user-facing state wrapper. The key must be registered
|
|
2298
|
-
*
|
|
2299
|
-
* and hidden from `connection.state`.
|
|
2134
|
+
* with `registerInternalConnectionKeys` so it is preserved across user
|
|
2135
|
+
* `setState` calls and hidden from `connection.state`.
|
|
2300
2136
|
*
|
|
2301
2137
|
* @internal
|
|
2302
2138
|
*/
|
|
2303
2139
|
_unsafe_setConnectionFlag(connection, key, value) {
|
|
2304
|
-
|
|
2305
|
-
const accessors = this._rawStateAccessors.get(connection);
|
|
2306
|
-
const raw = accessors.getRaw() ?? {};
|
|
2307
|
-
if (value === void 0) {
|
|
2308
|
-
const { [key]: _, ...rest } = raw;
|
|
2309
|
-
accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);
|
|
2310
|
-
} else accessors.setRaw({
|
|
2311
|
-
...raw,
|
|
2312
|
-
[key]: value
|
|
2313
|
-
});
|
|
2140
|
+
setConnectionFlag(connection, key, value);
|
|
2314
2141
|
}
|
|
2315
2142
|
/**
|
|
2316
2143
|
* Override this method to determine if a connection should be readonly on connect
|
|
@@ -2351,21 +2178,7 @@ var Agent = class Agent extends DurableObject {
|
|
|
2351
2178
|
* @returns True if the connection receives protocol messages
|
|
2352
2179
|
*/
|
|
2353
2180
|
isConnectionProtocolEnabled(connection) {
|
|
2354
|
-
|
|
2355
|
-
return !this._rawStateAccessors.get(connection).getRaw()?.[CF_NO_PROTOCOL_KEY];
|
|
2356
|
-
}
|
|
2357
|
-
/**
|
|
2358
|
-
* Mark a connection as having protocol messages disabled.
|
|
2359
|
-
* Called internally when shouldSendProtocolMessages returns false.
|
|
2360
|
-
*/
|
|
2361
|
-
_setConnectionNoProtocol(connection) {
|
|
2362
|
-
this._ensureConnectionWrapped(connection);
|
|
2363
|
-
const accessors = this._rawStateAccessors.get(connection);
|
|
2364
|
-
const raw = accessors.getRaw() ?? {};
|
|
2365
|
-
accessors.setRaw({
|
|
2366
|
-
...raw,
|
|
2367
|
-
[CF_NO_PROTOCOL_KEY]: true
|
|
2368
|
-
});
|
|
2181
|
+
return isConnectionProtocolEnabled(connection);
|
|
2369
2182
|
}
|
|
2370
2183
|
/**
|
|
2371
2184
|
* Called before the Agent's state is persisted and broadcast.
|
|
@@ -2610,111 +2423,42 @@ var Agent = class Agent extends DurableObject {
|
|
|
2610
2423
|
});
|
|
2611
2424
|
}
|
|
2612
2425
|
/**
|
|
2613
|
-
* Queue a task to
|
|
2426
|
+
* Queue a task to run in the background.
|
|
2427
|
+
*
|
|
2428
|
+
* The item is durable: it runs from the Lifecycle alarm event loop after
|
|
2429
|
+
* this call returns, in push order, one at a time, with retries per
|
|
2430
|
+
* `options.retry`, and survives the Durable Object leaving memory.
|
|
2614
2431
|
* @param callback Name of the method to call
|
|
2615
2432
|
* @param payload Payload to pass to the callback
|
|
2616
2433
|
* @param options Options for the queued task
|
|
2617
2434
|
* @param options.retry Retry options for the callback execution
|
|
2435
|
+
* @param options.id Stable id; a push with an existing id replaces that item
|
|
2618
2436
|
* @returns The ID of the queued task
|
|
2619
2437
|
*/
|
|
2620
2438
|
async queue(callback, payload, options) {
|
|
2621
|
-
const id = nanoid(9);
|
|
2622
2439
|
if (typeof callback !== "string") throw new Error("Callback must be a string");
|
|
2623
2440
|
if (typeof this[callback] !== "function") throw new Error(`this.${callback} is not a function`);
|
|
2624
|
-
|
|
2625
|
-
const retryJson = options?.retry ? JSON.stringify(options.retry) : null;
|
|
2626
|
-
this.sql`
|
|
2627
|
-
INSERT OR REPLACE INTO cf_agents_queues (id, payload, callback, retry_options)
|
|
2628
|
-
VALUES (${id}, ${JSON.stringify(payload)}, ${callback}, ${retryJson})
|
|
2629
|
-
`;
|
|
2630
|
-
this._emit("queue:create", {
|
|
2631
|
-
callback,
|
|
2632
|
-
id
|
|
2633
|
-
});
|
|
2634
|
-
this._flushQueue().catch((e) => {
|
|
2635
|
-
console.error("Error flushing queue:", e);
|
|
2636
|
-
});
|
|
2637
|
-
return id;
|
|
2638
|
-
}
|
|
2639
|
-
async _flushQueue() {
|
|
2640
|
-
if (this._flushingQueue) return;
|
|
2641
|
-
this._flushingQueue = true;
|
|
2642
|
-
try {
|
|
2643
|
-
while (true) {
|
|
2644
|
-
const result = this.sql`
|
|
2645
|
-
SELECT * FROM cf_agents_queues
|
|
2646
|
-
ORDER BY created_at ASC
|
|
2647
|
-
`;
|
|
2648
|
-
if (!result || result.length === 0) break;
|
|
2649
|
-
for (const row of result || []) {
|
|
2650
|
-
const callback = this[row.callback];
|
|
2651
|
-
if (!callback) {
|
|
2652
|
-
console.error(`callback ${row.callback} not found`);
|
|
2653
|
-
await this.dequeue(row.id);
|
|
2654
|
-
continue;
|
|
2655
|
-
}
|
|
2656
|
-
const { connection, request, email } = __DO_NOT_USE_WILL_BREAK__agentContext.getStore() || {};
|
|
2657
|
-
await runInInvocation({
|
|
2658
|
-
agent: this,
|
|
2659
|
-
connection,
|
|
2660
|
-
request,
|
|
2661
|
-
email
|
|
2662
|
-
}, async () => {
|
|
2663
|
-
const { maxAttempts, baseDelayMs, maxDelayMs } = resolveRetryConfig(parseRetryOptions(row), this._resolvedOptions.retry);
|
|
2664
|
-
const parsedPayload = JSON.parse(row.payload);
|
|
2665
|
-
try {
|
|
2666
|
-
await tryN(maxAttempts, async (attempt) => {
|
|
2667
|
-
if (attempt > 1) this._emit("queue:retry", {
|
|
2668
|
-
callback: row.callback,
|
|
2669
|
-
id: row.id,
|
|
2670
|
-
attempt,
|
|
2671
|
-
maxAttempts
|
|
2672
|
-
});
|
|
2673
|
-
await callback.bind(this)(parsedPayload, row);
|
|
2674
|
-
}, {
|
|
2675
|
-
baseDelayMs,
|
|
2676
|
-
maxDelayMs
|
|
2677
|
-
});
|
|
2678
|
-
} catch (e) {
|
|
2679
|
-
console.error(`queue callback "${row.callback}" failed after ${maxAttempts} attempts`, e);
|
|
2680
|
-
this._emit("queue:error", {
|
|
2681
|
-
callback: row.callback,
|
|
2682
|
-
id: row.id,
|
|
2683
|
-
error: e instanceof Error ? e.message : String(e),
|
|
2684
|
-
attempts: maxAttempts
|
|
2685
|
-
});
|
|
2686
|
-
try {
|
|
2687
|
-
await this.onError(e);
|
|
2688
|
-
} catch {}
|
|
2689
|
-
} finally {
|
|
2690
|
-
this.dequeue(row.id);
|
|
2691
|
-
}
|
|
2692
|
-
}, { detached: true });
|
|
2693
|
-
}
|
|
2694
|
-
}
|
|
2695
|
-
} finally {
|
|
2696
|
-
this._flushingQueue = false;
|
|
2697
|
-
}
|
|
2441
|
+
return (await this._queue.push(callback, payload, options)).id;
|
|
2698
2442
|
}
|
|
2699
2443
|
/**
|
|
2700
2444
|
* Dequeue a task by ID
|
|
2701
2445
|
* @param id ID of the task to dequeue
|
|
2702
2446
|
*/
|
|
2703
2447
|
dequeue(id) {
|
|
2704
|
-
this.
|
|
2448
|
+
return this._queue.cancel(id);
|
|
2705
2449
|
}
|
|
2706
2450
|
/**
|
|
2707
2451
|
* Dequeue all tasks
|
|
2708
2452
|
*/
|
|
2709
2453
|
dequeueAll() {
|
|
2710
|
-
this.
|
|
2454
|
+
return this._queue.cancelAll();
|
|
2711
2455
|
}
|
|
2712
2456
|
/**
|
|
2713
2457
|
* Dequeue all tasks by callback
|
|
2714
2458
|
* @param callback Name of the callback to dequeue
|
|
2715
2459
|
*/
|
|
2716
2460
|
dequeueAllByCallback(callback) {
|
|
2717
|
-
this.
|
|
2461
|
+
return this._queue.cancelAll(callback);
|
|
2718
2462
|
}
|
|
2719
2463
|
/**
|
|
2720
2464
|
* Get a queued task by ID
|
|
@@ -2722,31 +2466,16 @@ var Agent = class Agent extends DurableObject {
|
|
|
2722
2466
|
* @returns The task or undefined if not found
|
|
2723
2467
|
*/
|
|
2724
2468
|
getQueue(id) {
|
|
2725
|
-
|
|
2726
|
-
SELECT * FROM cf_agents_queues WHERE id = ${id}
|
|
2727
|
-
`;
|
|
2728
|
-
if (!result || result.length === 0) return void 0;
|
|
2729
|
-
const row = result[0];
|
|
2730
|
-
return {
|
|
2731
|
-
...row,
|
|
2732
|
-
payload: JSON.parse(row.payload),
|
|
2733
|
-
retry: parseRetryOptions(row)
|
|
2734
|
-
};
|
|
2469
|
+
return this._queue.get(id);
|
|
2735
2470
|
}
|
|
2736
2471
|
/**
|
|
2737
|
-
* Get all
|
|
2472
|
+
* Get all queued tasks whose payload has `key` equal to `value`
|
|
2738
2473
|
* @param key Key to filter by
|
|
2739
2474
|
* @param value Value to filter by
|
|
2740
2475
|
* @returns Array of matching QueueItem objects
|
|
2741
2476
|
*/
|
|
2742
|
-
getQueues(key, value) {
|
|
2743
|
-
return this.
|
|
2744
|
-
SELECT * FROM cf_agents_queues
|
|
2745
|
-
`.filter((row) => JSON.parse(row.payload)[key] === value).map((row) => ({
|
|
2746
|
-
...row,
|
|
2747
|
-
payload: JSON.parse(row.payload),
|
|
2748
|
-
retry: parseRetryOptions(row)
|
|
2749
|
-
}));
|
|
2477
|
+
async getQueues(key, value) {
|
|
2478
|
+
return (await this._queue.list()).filter((item) => typeof item.payload === "object" && item.payload !== null && item.payload[key] === value);
|
|
2750
2479
|
}
|
|
2751
2480
|
_lifecycleRouteAddress() {
|
|
2752
2481
|
return this._dynamicAgents.lifecycleRouteAddress();
|
|
@@ -3540,12 +3269,16 @@ var Agent = class Agent extends DurableObject {
|
|
|
3540
3269
|
}
|
|
3541
3270
|
} finally {
|
|
3542
3271
|
this._runFiberActiveFibers.delete(id);
|
|
3543
|
-
|
|
3544
|
-
"
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3272
|
+
try {
|
|
3273
|
+
this._withAgentSpan("finalize_fiber", "fiber", {
|
|
3274
|
+
"cloudflare.agents.fiber.id": id,
|
|
3275
|
+
"cloudflare.agents.fiber.name": name
|
|
3276
|
+
}, () => {
|
|
3277
|
+
this.sql`DELETE FROM cf_agents_runs WHERE id = ${id}`;
|
|
3278
|
+
});
|
|
3279
|
+
} catch (error) {
|
|
3280
|
+
console.error(`[Agent] Failed to finalize fiber "${name}" (${id}); leaving run row for recovery:`, error);
|
|
3281
|
+
}
|
|
3549
3282
|
dispose();
|
|
3550
3283
|
if (root && registeredFacetRun) try {
|
|
3551
3284
|
await root._cf_unregisterFacetRun(this.selfPath, id);
|
|
@@ -6960,4 +6693,4 @@ var StreamingResponse = class {
|
|
|
6960
6693
|
//#endregion
|
|
6961
6694
|
export { routeAgentEmail as a, getCurrentAgent as i, DEFAULT_AGENT_STATIC_OPTIONS as n, StreamingResponse as r, Agent as t };
|
|
6962
6695
|
|
|
6963
|
-
//# sourceMappingURL=src-
|
|
6696
|
+
//# sourceMappingURL=src-BNU3ZiJM.js.map
|