agents 0.13.2 → 0.13.3

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.
@@ -1,5 +1,5 @@
1
1
  import {
2
- O as SessionMessage,
2
+ A as SessionMessage,
3
3
  a as alignBoundaryForward,
4
4
  c as createCompactFunction,
5
5
  d as sanitizeToolPairs,
@@ -11,7 +11,7 @@ import {
11
11
  s as computeSummaryBudget,
12
12
  t as COMPACTION_PREFIX,
13
13
  u as isCompactionMessage
14
- } from "../../../compaction-helpers-DAe-xiVY.js";
14
+ } from "../../../compaction-helpers-B-pG5J22.js";
15
15
 
16
16
  //#region src/experimental/memory/utils/tokens.d.ts
17
17
  /** Approximate characters per token for English text */
@@ -33,7 +33,7 @@ declare function estimateStringTokens(text: string): number;
33
33
  /**
34
34
  * Estimate total token count for an array of UIMessages.
35
35
  *
36
- * Walks each message's parts (text, tool invocations, tool results)
36
+ * Walks each message's parts (text, reasoning, tool invocations, tool results)
37
37
  * and applies per-message overhead.
38
38
  *
39
39
  * This is a heuristic. Do not use where exact counts are required.
@@ -1,5 +1,5 @@
1
1
  import { t as truncateToolOutput } from "../../../tool-output-truncation-CH-khbZ3.js";
2
- import { a as computeSummaryBudget, c as isCompactionMessage, d as TOKENS_PER_MESSAGE, f as WORDS_TOKEN_MULTIPLIER, i as buildSummaryPrompt, l as sanitizeToolPairs, m as estimateStringTokens, n as alignBoundaryBackward, o as createCompactFunction, p as estimateMessageTokens, r as alignBoundaryForward, s as findTailCutByTokens, t as COMPACTION_PREFIX, u as CHARS_PER_TOKEN } from "../../../compaction-helpers-DvcZnvQ1.js";
2
+ import { a as computeSummaryBudget, c as isCompactionMessage, d as TOKENS_PER_MESSAGE, f as WORDS_TOKEN_MULTIPLIER, i as buildSummaryPrompt, l as sanitizeToolPairs, m as estimateStringTokens, n as alignBoundaryBackward, o as createCompactFunction, p as estimateMessageTokens, r as alignBoundaryForward, s as findTailCutByTokens, t as COMPACTION_PREFIX, u as CHARS_PER_TOKEN } from "../../../compaction-helpers-fJyf8j4m.js";
3
3
  //#region src/experimental/memory/utils/compaction.ts
4
4
  /**
5
5
  * Read-time context truncation.
package/dist/index.d.ts CHANGED
@@ -66,7 +66,7 @@ import {
66
66
  y as AgentContext,
67
67
  z as MCPServersState,
68
68
  zt as SUB_PREFIX
69
- } from "./agent-tool-types-Dn9n-3SI.js";
69
+ } from "./agent-tool-types-l98LCbBl.js";
70
70
  import { t as RetryOptions } from "./retries-BVdRl5ZE.js";
71
71
  import {
72
72
  n as AgentsOAuthProvider,
package/dist/index.js CHANGED
@@ -114,6 +114,9 @@ function getNextCronTime(cron) {
114
114
  return parseCronExpression(cron).getNextDate();
115
115
  }
116
116
  const DEFAULT_KEEP_ALIVE_INTERVAL_MS = 3e4;
117
+ const SUB_AGENT_IDENTITY_VERSION_LEGACY = "legacy";
118
+ const SUB_AGENT_IDENTITY_VERSION_PATH_V2 = "path-v2";
119
+ const SUB_AGENT_IDENTITY_PATH_V2_PREFIX = "cf-agents:v2:";
117
120
  /**
118
121
  * Schema version for the Agent's internal SQLite tables.
119
122
  * Bump this when adding new tables, columns, or migrations.
@@ -125,6 +128,25 @@ const SCHEMA_VERSION_ROW_ID = "cf_schema_version";
125
128
  const STATE_ROW_ID = "cf_state_row_id";
126
129
  const STATE_WAS_CHANGED = "cf_state_was_changed";
127
130
  const DEFAULT_STATE = {};
131
+ async function sha256Hex(value) {
132
+ const bytes = new TextEncoder().encode(value);
133
+ const digest = await crypto.subtle.digest("SHA-256", bytes);
134
+ return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
135
+ }
136
+ function pathV2IdentityName(logicalName, digest) {
137
+ return `${SUB_AGENT_IDENTITY_PATH_V2_PREFIX}${encodeURIComponent(logicalName)}:${digest}`;
138
+ }
139
+ function logicalNameFromPathV2Identity(identityName) {
140
+ if (!identityName.startsWith(SUB_AGENT_IDENTITY_PATH_V2_PREFIX)) return null;
141
+ const rest = identityName.slice(13);
142
+ const separator = rest.lastIndexOf(":");
143
+ if (separator === -1) return null;
144
+ try {
145
+ return decodeURIComponent(rest.slice(0, separator));
146
+ } catch {
147
+ return null;
148
+ }
149
+ }
128
150
  /**
129
151
  * Validate that a stored `parentPath` has the expected shape. Used
130
152
  * when restoring from DO storage to guard against corrupted data.
@@ -848,6 +870,8 @@ var Agent = class Agent extends Server {
848
870
  email: void 0
849
871
  }, async () => {
850
872
  if (await this.ctx.storage.get("cf_agents_is_facet")) this._isFacet = true;
873
+ const storedFacetName = await this.ctx.storage.get("cf_agents_facet_name");
874
+ if (typeof storedFacetName === "string") this._facetName = storedFacetName;
851
875
  const storedParentPath = await this.ctx.storage.get("cf_agents_parent_path");
852
876
  if (isValidParentPath(storedParentPath)) this._parentPath = storedParentPath;
853
877
  try {
@@ -1569,6 +1593,13 @@ var Agent = class Agent extends Server {
1569
1593
  if (!binding) throw new Error(`Unable to resolve root scheduler "${root.className}" for sub-agent schedule delegation.`);
1570
1594
  return await getServerByName(binding, root.name);
1571
1595
  }
1596
+ _cf_rootResolvesToSelf() {
1597
+ const root = this._parentPath[0];
1598
+ if (!root) return false;
1599
+ const binding = this.ctx.exports?.[root.className];
1600
+ if (!binding?.idFromName) return false;
1601
+ return binding.idFromName(root.name).equals(this.ctx.id);
1602
+ }
1572
1603
  _validateScheduleCallback(when, callback, options) {
1573
1604
  if (typeof callback !== "string") throw new Error("Callback must be a string");
1574
1605
  if (typeof this[callback] !== "function") throw new Error(`this.${callback} is not a function`);
@@ -2545,6 +2576,18 @@ var Agent = class Agent extends Server {
2545
2576
  async runFiber(name, fn) {
2546
2577
  return this._runFiberInternal(nanoid(), name, fn);
2547
2578
  }
2579
+ /**
2580
+ * Internal framework entry point for fibers that need to compose their own
2581
+ * recovery metadata with user checkpoint data while preserving the public
2582
+ * `this.stash()` behavior.
2583
+ *
2584
+ * This deliberately stays protected/internal rather than becoming a public
2585
+ * `runFiber()` option until the durable execution API needs this generality.
2586
+ * @internal
2587
+ */
2588
+ async _runFiberWithStashWrapper(name, fn, options) {
2589
+ return this._runFiberInternal(nanoid(), name, fn, options);
2590
+ }
2548
2591
  async startFiber(name, fn, options) {
2549
2592
  const fiberId = options?.fiberId ?? nanoid();
2550
2593
  const idempotencyKey = options?.idempotencyKey;
@@ -2642,10 +2685,22 @@ var Agent = class Agent extends Server {
2642
2685
  VALUES (${id}, ${name}, NULL, ${Date.now()})
2643
2686
  `;
2644
2687
  this._runFiberActiveFibers.add(id);
2688
+ const writeSnapshot = (data) => {
2689
+ const snapshot = JSON.stringify(data);
2690
+ this.sql`
2691
+ UPDATE cf_agents_runs SET snapshot = ${snapshot}
2692
+ WHERE id = ${id}
2693
+ `;
2694
+ if (options?.managed) this.sql`
2695
+ UPDATE cf_agents_fibers SET snapshot = ${snapshot}
2696
+ WHERE fiber_id = ${id}
2697
+ `;
2698
+ };
2645
2699
  let root;
2646
2700
  let registeredFacetRun = false;
2647
2701
  let dispose = () => {};
2648
2702
  try {
2703
+ if ("initialSnapshot" in (options ?? {})) writeSnapshot(options?.initialSnapshot);
2649
2704
  if (this._isFacet) {
2650
2705
  root = await this._rootAlarmOwner();
2651
2706
  await root._cf_registerFacetRun(this.selfPath, id);
@@ -2653,15 +2708,7 @@ var Agent = class Agent extends Server {
2653
2708
  }
2654
2709
  dispose = await this.keepAlive();
2655
2710
  const stash = (data) => {
2656
- const snapshot = JSON.stringify(data);
2657
- this.sql`
2658
- UPDATE cf_agents_runs SET snapshot = ${snapshot}
2659
- WHERE id = ${id}
2660
- `;
2661
- if (options?.managed) this.sql`
2662
- UPDATE cf_agents_fibers SET snapshot = ${snapshot}
2663
- WHERE fiber_id = ${id}
2664
- `;
2711
+ writeSnapshot(options?.wrapStash ? options.wrapStash(data) : data);
2665
2712
  };
2666
2713
  try {
2667
2714
  const result = await _fiberALS.run({
@@ -3467,6 +3514,7 @@ var Agent = class Agent extends Server {
3467
3514
  }
3468
3515
  async _cf_hydrateSubAgentConnectionsFromRoot() {
3469
3516
  if (!this._isFacet || this._parentPath.length === 0) return;
3517
+ if (this._cf_rootResolvesToSelf()) return;
3470
3518
  const root = await this._rootAlarmOwner();
3471
3519
  const metas = await root._cf_subAgentConnectionMetas(this.selfPath);
3472
3520
  for (const meta of metas) this._cf_virtualSubAgentConnections.set(meta.id, {
@@ -3607,21 +3655,23 @@ var Agent = class Agent extends Server {
3607
3655
  * broadcast to their own WebSocket clients reached via sub-agent
3608
3656
  * routing.
3609
3657
  *
3610
- * The facet's name (and `this.name` getter) is handled entirely by
3611
- * partyserver via `ctx.id.name`, which is populated because the
3612
- * parent passed an explicit named Durable Object id to
3613
- * `ctx.facets.get()` — see {@link _cf_resolveSubAgent}. No
3614
- * `setName()` call or `__ps_name` storage write is needed; the
3615
- * facet's name survives cold wake automatically because the factory
3616
- * re-runs and `idFromName` is deterministic.
3658
+ * The facet's logical name is persisted separately from its routing id.
3659
+ * Legacy facets used the logical name directly as `ctx.id.name`; newer
3660
+ * facets can use path-scoped routing ids while preserving `this.name`.
3617
3661
  *
3618
3662
  * @internal Called by {@link subAgent}.
3619
3663
  */
3620
- async _cf_initAsFacet(name, parentPath = []) {
3621
- if (this.name !== name) throw new Error(`Facet bootstrap mismatch: expected this.name === "${name}" but got "${this.name}". This usually means the parent passed the wrong (or no) id to ctx.facets.get(). See _cf_resolveSubAgent.`);
3664
+ async _cf_initAsFacet(name, parentPath = [], identityName = name) {
3665
+ const routedName = super.name;
3666
+ if (routedName !== identityName) throw new Error(`Facet bootstrap mismatch: expected routed identity "${identityName}" but got "${routedName}". This usually means the parent passed the wrong id to ctx.facets.get(). See _cf_resolveSubAgent.`);
3622
3667
  this._isFacet = true;
3668
+ this._facetName = name;
3623
3669
  this._parentPath = parentPath;
3624
- await Promise.all([this.ctx.storage.put("cf_agents_is_facet", true), this.ctx.storage.put("cf_agents_parent_path", parentPath)]);
3670
+ await Promise.all([
3671
+ this.ctx.storage.put("cf_agents_is_facet", true),
3672
+ this.ctx.storage.put("cf_agents_facet_name", name),
3673
+ this.ctx.storage.put("cf_agents_parent_path", parentPath)
3674
+ ]);
3625
3675
  this._suppressProtocolBroadcasts = true;
3626
3676
  try {
3627
3677
  await this.__unsafe_ensureInitialized();
@@ -3629,6 +3679,9 @@ var Agent = class Agent extends Server {
3629
3679
  this._suppressProtocolBroadcasts = false;
3630
3680
  }
3631
3681
  }
3682
+ get name() {
3683
+ return this._facetName ?? logicalNameFromPathV2Identity(super.name) ?? super.name;
3684
+ }
3632
3685
  /**
3633
3686
  * Ancestor chain for this agent, root-first. Empty for top-level
3634
3687
  * DOs. Populated at facet init time; survives hibernation.
@@ -4333,27 +4386,37 @@ var Agent = class Agent extends Server {
4333
4386
  if (!Cls) throw new Error(`Sub-agent class "${className}" not found in worker exports. Make sure the class is exported from your worker entry point and that the export name matches the class name.`);
4334
4387
  if (name.includes("\0")) throw new Error(`Sub-agent name contains null character (\\0), which is reserved.`);
4335
4388
  const facetKey = `${className}\0${name}`;
4389
+ const childParentPath = this.selfPath;
4390
+ const childPath = [...childParentPath, {
4391
+ className,
4392
+ name
4393
+ }];
4336
4394
  const rootClassName = this._parentPath[0]?.className ?? this.constructor.name;
4337
4395
  const rootNs = ctx.exports[rootClassName];
4338
4396
  if (!rootNs?.idFromName) {
4339
4397
  const minificationHint = /^_*[a-z][a-z0-9]{0,2}$/.test(rootClassName) ? ` The class name "${rootClassName}" looks minified — make sure your bundler preserves class names (e.g. esbuild's \`keepNames: true\`).` : "";
4340
4398
  throw new Error(`Sub-agent bootstrap requires the root agent class "${rootClassName}" to be available as a Durable Object namespace, but ctx.exports["${rootClassName}"] is missing or doesn't expose idFromName.${minificationHint} Make sure the root agent class is exported under that class name and registered in your wrangler.jsonc durable_objects.bindings.`);
4341
4399
  }
4342
- const facetId = rootNs.idFromName(name);
4400
+ const identity = await this._cf_subAgentIdentity(className, name, childPath);
4401
+ const facetId = rootNs.idFromName(identity.name);
4343
4402
  const stub = ctx.facets.get(facetKey, () => ({
4344
4403
  class: Cls,
4345
4404
  id: facetId
4346
4405
  }));
4347
- const childParentPath = this.selfPath;
4348
- await __DO_NOT_USE_WILL_BREAK__agentContext.run({
4349
- agent: this,
4350
- connection: void 0,
4351
- request: void 0,
4352
- email: void 0
4353
- }, async () => {
4354
- await stub._cf_initAsFacet(name, childParentPath);
4355
- });
4356
- this._recordSubAgent(className, name);
4406
+ this._recordSubAgent(className, name, identity);
4407
+ try {
4408
+ await __DO_NOT_USE_WILL_BREAK__agentContext.run({
4409
+ agent: this,
4410
+ connection: void 0,
4411
+ request: void 0,
4412
+ email: void 0
4413
+ }, async () => {
4414
+ await stub._cf_initAsFacet(name, childParentPath, identity.name);
4415
+ });
4416
+ } catch (error) {
4417
+ if (!identity.existing) this._forgetSubAgent(className, name);
4418
+ throw error;
4419
+ }
4357
4420
  return stub;
4358
4421
  }
4359
4422
  /**
@@ -4398,6 +4461,13 @@ var Agent = class Agent extends Server {
4398
4461
  } catch {}
4399
4462
  this._forgetSubAgent(cls.name, name);
4400
4463
  }
4464
+ _addColumnIfNotExists(sql) {
4465
+ try {
4466
+ this.ctx.storage.sql.exec(sql);
4467
+ } catch (e) {
4468
+ if (!(e instanceof Error ? e.message : String(e)).toLowerCase().includes("duplicate column")) throw e;
4469
+ }
4470
+ }
4401
4471
  /** @internal */
4402
4472
  _ensureSubAgentRegistry() {
4403
4473
  if (this._subAgentRegistryReady) return;
@@ -4406,20 +4476,56 @@ var Agent = class Agent extends Server {
4406
4476
  class TEXT NOT NULL,
4407
4477
  name TEXT NOT NULL,
4408
4478
  created_at INTEGER NOT NULL,
4479
+ identity_version TEXT,
4480
+ identity_name TEXT,
4409
4481
  PRIMARY KEY (class, name)
4410
4482
  )
4411
4483
  `;
4484
+ this._addColumnIfNotExists("ALTER TABLE cf_agents_sub_agents ADD COLUMN identity_version TEXT");
4485
+ this._addColumnIfNotExists("ALTER TABLE cf_agents_sub_agents ADD COLUMN identity_name TEXT");
4412
4486
  this._subAgentRegistryReady = true;
4413
4487
  }
4414
4488
  /** @internal */
4415
- _recordSubAgent(className, name) {
4489
+ _recordSubAgent(className, name, identity) {
4416
4490
  this._ensureSubAgentRegistry();
4417
4491
  this.sql`
4418
- INSERT OR IGNORE INTO cf_agents_sub_agents (class, name, created_at)
4419
- VALUES (${className}, ${name}, ${Date.now()})
4492
+ INSERT OR IGNORE INTO cf_agents_sub_agents
4493
+ (class, name, created_at, identity_version, identity_name)
4494
+ VALUES
4495
+ (${className}, ${name}, ${Date.now()}, ${identity.version}, ${identity.name})
4420
4496
  `;
4421
4497
  }
4422
4498
  /** @internal */
4499
+ _subAgentRegistryRow(className, name) {
4500
+ this._ensureSubAgentRegistry();
4501
+ return this.sql`
4502
+ SELECT identity_version, identity_name
4503
+ FROM cf_agents_sub_agents
4504
+ WHERE class = ${className} AND name = ${name}
4505
+ LIMIT 1
4506
+ `[0] ?? null;
4507
+ }
4508
+ async _cf_subAgentIdentity(className, name, childPath) {
4509
+ const row = this._subAgentRegistryRow(className, name);
4510
+ if (row) {
4511
+ if (row.identity_version === SUB_AGENT_IDENTITY_VERSION_PATH_V2 && typeof row.identity_name === "string") return {
4512
+ version: SUB_AGENT_IDENTITY_VERSION_PATH_V2,
4513
+ name: row.identity_name,
4514
+ existing: true
4515
+ };
4516
+ return {
4517
+ version: SUB_AGENT_IDENTITY_VERSION_LEGACY,
4518
+ name,
4519
+ existing: true
4520
+ };
4521
+ }
4522
+ return {
4523
+ version: SUB_AGENT_IDENTITY_VERSION_PATH_V2,
4524
+ name: pathV2IdentityName(name, await sha256Hex(JSON.stringify(childPath))),
4525
+ existing: false
4526
+ };
4527
+ }
4528
+ /** @internal */
4423
4529
  _forgetSubAgent(className, name) {
4424
4530
  this._ensureSubAgentRegistry();
4425
4531
  this.sql`
@@ -4552,7 +4658,7 @@ var Agent = class Agent extends Server {
4552
4658
  if (!workflow) throw new Error(`Workflow binding '${workflowName}' not found in environment`);
4553
4659
  const agentBindingName = options?.agentBinding ?? this._findAgentBindingName();
4554
4660
  if (!agentBindingName) throw new Error("Could not detect Agent binding name from class name. Pass it explicitly via options.agentBinding");
4555
- const workflowId = options?.id ?? nanoid();
4661
+ const workflowId = options?.id ?? `wf_${nanoid()}`;
4556
4662
  const augmentedParams = {
4557
4663
  ...params,
4558
4664
  __agentName: this.name,