@standardagents/builder 0.40.4 → 0.40.5

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/index.js CHANGED
@@ -5083,9 +5083,7 @@ Message one with subagent_message(referenceId, message).`
5083
5083
  if (resumable) {
5084
5084
  await this.settleResumableChildAfterRun(
5085
5085
  state,
5086
- stub,
5087
- childThreadId,
5088
- childResult
5086
+ childThreadId
5089
5087
  );
5090
5088
  } else if (stub.terminateThread) {
5091
5089
  await stub.terminateThread(childThreadId);
@@ -5097,7 +5095,7 @@ Message one with subagent_message(referenceId, message).`
5097
5095
  attachments: copiedAttachments,
5098
5096
  subagent_id: childThreadId
5099
5097
  };
5100
- return resumable && !this.isTerminalSubagentResult(childResult) ? this.withReferenceInToolResult(toolResult, childThreadId) : toolResult;
5098
+ return resumable ? this.withReferenceInToolResult(toolResult, childThreadId) : toolResult;
5101
5099
  }
5102
5100
  const backgroundRun = (async () => {
5103
5101
  try {
@@ -5132,9 +5130,7 @@ Message one with subagent_message(referenceId, message).`
5132
5130
  if (resumable) {
5133
5131
  await this.settleResumableChildAfterRun(
5134
5132
  state,
5135
- stub,
5136
- childThreadId,
5137
- childResult
5133
+ childThreadId
5138
5134
  );
5139
5135
  } else if (stub.terminateThread) {
5140
5136
  await stub.terminateThread(childThreadId);
@@ -5529,18 +5525,8 @@ Message one with subagent_message(referenceId, message).`
5529
5525
  JSON.stringify(next)
5530
5526
  );
5531
5527
  }
5532
- static isTerminalSubagentResult(result) {
5533
- return result.terminal === true;
5534
- }
5535
- static async settleResumableChildAfterRun(state, childThread, reference, result) {
5536
- if (!this.isTerminalSubagentResult(result)) {
5537
- await this.updateChildStatus(state, reference, "idle");
5538
- return;
5539
- }
5540
- await this.updateChildStatus(state, reference, "terminated");
5541
- if (typeof childThread.terminateThread === "function") {
5542
- await childThread.terminateThread(reference);
5543
- }
5528
+ static async settleResumableChildAfterRun(state, reference) {
5529
+ await this.updateChildStatus(state, reference, "idle");
5544
5530
  }
5545
5531
  static async buildChildInvocationMessages(state, childThread, content, receivesMessages, parentAttachments, initialArguments) {
5546
5532
  const copiedAttachments = await this.copyAttachmentsBetweenThreads(
@@ -16819,7 +16805,7 @@ function createHmrReloader() {
16819
16805
  const isConfigFile = isModelFile || isProviderFile || isPromptFile || isAgentFile || isEffectFile;
16820
16806
  if (!isToolFile && !isThreadApiFile && !isHookFile && !isConfigFile && !isUserEndpointFile) return;
16821
16807
  reloader.invalidateSourceFileModule(server, file);
16822
- if (isConfigFile || isToolFile) regenerateTypes();
16808
+ if (isConfigFile || isToolFile || isHookFile) regenerateTypes();
16823
16809
  if (isToolFile) await reloader.reloadToolsModule(server);
16824
16810
  if (isModelFile) await reloader.reloadModelsModule(server);
16825
16811
  if (isProviderFile) await reloader.reloadProvidersModule(server);
@@ -18947,6 +18933,29 @@ async function scanPromptsDirectory(dir) {
18947
18933
  async function scanAgentsDirectory(dir) {
18948
18934
  return scanConfigDirectory(dir, /export\s+default\s+defineAgent/);
18949
18935
  }
18936
+ function findLegacyRootAgentFiles(agentsDir) {
18937
+ const agentsRoot = path9__default.dirname(agentsDir);
18938
+ if (path9__default.basename(agentsDir) !== "agents" || path9__default.basename(agentsRoot) !== "agents") {
18939
+ return [];
18940
+ }
18941
+ if (!fs9__default.existsSync(agentsRoot)) return [];
18942
+ return fs9__default.readdirSync(agentsRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".ts")).map((entry) => path9__default.join(agentsRoot, entry.name)).filter((filePath) => {
18943
+ try {
18944
+ return /export\s+default\s+defineAgent/.test(fs9__default.readFileSync(filePath, "utf8"));
18945
+ } catch {
18946
+ return false;
18947
+ }
18948
+ }).sort();
18949
+ }
18950
+ function warnLegacyRootAgentFiles(agentsDir) {
18951
+ const expectedDir = path9__default.relative(process.cwd(), agentsDir).replace(/\\/g, "/");
18952
+ for (const filePath of findLegacyRootAgentFiles(agentsDir)) {
18953
+ const source = path9__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
18954
+ console.warn(
18955
+ `[agentbuilder] Agent definition "${source}" is outside the scanned agent directory. Move it to "${expectedDir}/" so it is registered.`
18956
+ );
18957
+ }
18958
+ }
18950
18959
  async function scanEffectsDirectory(dir) {
18951
18960
  const effects = [];
18952
18961
  if (!fs9__default.existsSync(dir)) {
@@ -22657,7 +22666,32 @@ function isHostedInstance(env) {
22657
22666
  }
22658
22667
  return Boolean(value);
22659
22668
  }
22660
- function isTrustedLocalDevelopmentRequest(request, env) {
22669
+ function normalizeTrustedDevHosts(hosts) {
22670
+ const normalized = /* @__PURE__ */ new Set();
22671
+ for (const rawHost of hosts ?? []) {
22672
+ const candidate = rawHost.trim().toLowerCase().replace(/\.$/, "");
22673
+ try {
22674
+ const parsed = new URL(`http://${candidate}`);
22675
+ if (!candidate || candidate.includes("*") || parsed.hostname.toLowerCase().replace(/\.$/, "") !== candidate || parsed.port || parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
22676
+ throw new Error("invalid hostname");
22677
+ }
22678
+ } catch {
22679
+ throw new Error(
22680
+ `Invalid trusted development hostname "${rawHost}". Use an exact hostname without a scheme, port, path, or wildcard.`
22681
+ );
22682
+ }
22683
+ normalized.add(candidate);
22684
+ }
22685
+ return [...normalized];
22686
+ }
22687
+ function compiledTrustedDevHosts() {
22688
+ try {
22689
+ return typeof __STANDARD_AGENTS_TRUSTED_DEV_HOSTS__ !== "undefined" && Array.isArray(__STANDARD_AGENTS_TRUSTED_DEV_HOSTS__) ? __STANDARD_AGENTS_TRUSTED_DEV_HOSTS__ : [];
22690
+ } catch {
22691
+ return [];
22692
+ }
22693
+ }
22694
+ function isTrustedLocalDevelopmentRequest(request, env, trustedDevHosts = compiledTrustedDevHosts()) {
22661
22695
  if (isHostedInstance(env)) return false;
22662
22696
  let hostname;
22663
22697
  try {
@@ -22665,7 +22699,7 @@ function isTrustedLocalDevelopmentRequest(request, env) {
22665
22699
  } catch {
22666
22700
  return false;
22667
22701
  }
22668
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.endsWith(".localhost") || hostname.endsWith(".orb.local");
22702
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.endsWith(".localhost") || hostname.endsWith(".orb.local") || trustedDevHosts.some((trusted) => trusted.trim().toLowerCase() === hostname);
22669
22703
  }
22670
22704
  function isPublicApiRoute(routePath, request, env) {
22671
22705
  if (PUBLIC_ROUTES.has(routePath)) return true;
@@ -22814,7 +22848,8 @@ function createDevMiddleware(server, context) {
22814
22848
  installedProviderPackageMap,
22815
22849
  hmr,
22816
22850
  sourceDirs,
22817
- regenerateTypes
22851
+ regenerateTypes,
22852
+ trustedDevHosts
22818
22853
  } = context;
22819
22854
  server.watcher.on("add", async (file) => {
22820
22855
  await hmr.handleFileChange(file, server, sourceDirs, regenerateTypes);
@@ -22848,7 +22883,8 @@ function createDevMiddleware(server, context) {
22848
22883
  try {
22849
22884
  trustedLocalHost = isTrustedLocalDevelopmentRequest(
22850
22885
  new Request(`http://${req.headers.host || "invalid.remote"}${routePath}`),
22851
- {}
22886
+ {},
22887
+ trustedDevHosts
22852
22888
  );
22853
22889
  } catch {
22854
22890
  }
@@ -24040,6 +24076,18 @@ ${validUserProviders.map((p) => ` "${p.name}": async () => (await import("${p.i
24040
24076
  }
24041
24077
  }
24042
24078
  var DEFAULT_AGENTBUILDER_COMPATIBILITY_DATE = "2025-08-13";
24079
+ var REQUIRED_AGENTBUILDER_COMPATIBILITY_FLAGS = [
24080
+ "nodejs_compat",
24081
+ "enable_ctx_exports"
24082
+ ];
24083
+ function compatibilityFlagsWithBuilderRequirements(flags = []) {
24084
+ if (flags.some((flag) => typeof flag !== "string" || flag.trim().length === 0)) {
24085
+ throw new Error(
24086
+ "compatibilityFlags must contain non-empty Cloudflare compatibility flag names"
24087
+ );
24088
+ }
24089
+ return [.../* @__PURE__ */ new Set([...REQUIRED_AGENTBUILDER_COMPATIBILITY_FLAGS, ...flags])];
24090
+ }
24043
24091
  var depsToExclude = [
24044
24092
  "@standardagents/builder",
24045
24093
  "@standardagents/builder/runtime",
@@ -24070,7 +24118,7 @@ var firstPartyProviderPackages = [
24070
24118
  "@standardagents/openrouter",
24071
24119
  "@standardagents/xai"
24072
24120
  ];
24073
- var depsToInclude = [
24121
+ var baseDepsToInclude = [
24074
24122
  "zod",
24075
24123
  "zod/v3",
24076
24124
  "zod/v4",
@@ -24081,17 +24129,24 @@ var depsToInclude = [
24081
24129
  // a root dep). The `parent > child` form pre-bundles it at startup so Vite
24082
24130
  // doesn't discover it mid-request and reload the worker (which would destroy
24083
24131
  // an in-flight Durable Object execution and drop the client bridge).
24084
- "@standardagents/openrouter > @openrouter/sdk",
24085
24132
  "magic-string",
24086
24133
  "@standardagents/spec",
24087
24134
  // Incremental JSON reader used by the runtime to surface a tool's progress
24088
24135
  // argument from partial streamed tool-call arguments (tool_call_started).
24089
- "@formkit/jsonreader",
24090
- // Pre-bundle the provider packages themselves so their whole subtree (SDKs,
24091
- // pricing tables) lands in the initial optimized bundle and nothing is
24092
- // discovered lazily by workerd.
24093
- ...firstPartyProviderPackages
24136
+ "@formkit/jsonreader"
24094
24137
  ];
24138
+ function depsToInclude(options = {}) {
24139
+ const installedProviders = options.isPackageInstalled ? firstPartyProviderPackages.filter(options.isPackageInstalled) : firstPartyProviderPackages;
24140
+ const openRouterTransitive = installedProviders.includes("@standardagents/openrouter") ? ["@standardagents/openrouter > @openrouter/sdk"] : [];
24141
+ return [...baseDepsToInclude, ...openRouterTransitive, ...installedProviders];
24142
+ }
24143
+ function trustedDevHostDefines(options) {
24144
+ return {
24145
+ __STANDARD_AGENTS_TRUSTED_DEV_HOSTS__: JSON.stringify(
24146
+ normalizeTrustedDevHosts(options.trustedDevHosts)
24147
+ )
24148
+ };
24149
+ }
24095
24150
  var packingDeps = [
24096
24151
  "rollup",
24097
24152
  "@rollup/plugin-commonjs",
@@ -24100,7 +24155,7 @@ var packingDeps = [
24100
24155
  "fsevents",
24101
24156
  "typescript"
24102
24157
  ];
24103
- function createPluginViteConfig(pluginModuleUrl) {
24158
+ function createPluginViteConfig(pluginModuleUrl, options = {}) {
24104
24159
  const currentDir = path9__default.dirname(fileURLToPath(pluginModuleUrl));
24105
24160
  const isInDist = currentDir.endsWith("dist");
24106
24161
  const builderClientDir = path9__default.resolve(
@@ -24108,6 +24163,7 @@ function createPluginViteConfig(pluginModuleUrl) {
24108
24163
  isInDist ? "./client" : "../dist/client"
24109
24164
  );
24110
24165
  return {
24166
+ define: trustedDevHostDefines(options),
24111
24167
  publicDir: fs9__default.existsSync(builderClientDir) ? builderClientDir : void 0,
24112
24168
  build: {
24113
24169
  rollupOptions: {
@@ -24123,7 +24179,7 @@ function createPluginViteConfig(pluginModuleUrl) {
24123
24179
  // `npm run dev` ("There is a new version of the pre-bundle for X").
24124
24180
  holdUntilCrawlEnd: true,
24125
24181
  exclude: depsToExclude,
24126
- include: depsToInclude.filter((dep) => dep !== "zod/v3" && dep !== "zod/v4" && dep !== "zod/v4/core")
24182
+ include: depsToInclude(options).filter((dep) => dep !== "zod/v3" && dep !== "zod/v4" && dep !== "zod/v4/core")
24127
24183
  },
24128
24184
  ssr: {
24129
24185
  noExternal: [
@@ -24148,7 +24204,7 @@ function createAgentBuilderWorkerConfig(options) {
24148
24204
  // in vite.config.ts plus their agents/ source tree.
24149
24205
  main: options.workerEntry,
24150
24206
  compatibility_date: compatibilityDate,
24151
- compatibility_flags: ["nodejs_compat", "enable_ctx_exports"],
24207
+ compatibility_flags: compatibilityFlagsWithBuilderRequirements(options.compatibilityFlags),
24152
24208
  observability: {
24153
24209
  enabled: true
24154
24210
  },
@@ -24228,7 +24284,11 @@ function createAgentBuilderCloudflarePlugins(options) {
24228
24284
  }
24229
24285
  });
24230
24286
  }
24231
- function applyPluginEnvironmentConfig(config) {
24287
+ function applyPluginEnvironmentConfig(config, options = {}) {
24288
+ config.define = {
24289
+ ...config.define || {},
24290
+ ...trustedDevHostDefines(options)
24291
+ };
24232
24292
  config.optimizeDeps = config.optimizeDeps || {};
24233
24293
  config.optimizeDeps.holdUntilCrawlEnd = true;
24234
24294
  config.optimizeDeps.exclude = [
@@ -24237,7 +24297,7 @@ function applyPluginEnvironmentConfig(config) {
24237
24297
  ];
24238
24298
  config.optimizeDeps.include = [
24239
24299
  ...config.optimizeDeps.include || [],
24240
- ...depsToInclude.filter((dep) => !config.optimizeDeps?.include?.includes(dep))
24300
+ ...depsToInclude(options).filter((dep) => !config.optimizeDeps?.include?.includes(dep))
24241
24301
  ];
24242
24302
  config.build = config.build || {};
24243
24303
  config.build.rollupOptions = config.build.rollupOptions || {};
@@ -24297,6 +24357,7 @@ function normalizeDeviceApprovalBrand(value) {
24297
24357
  // src/plugin.ts
24298
24358
  function agentbuilder(options = {}) {
24299
24359
  const deviceApproval = normalizeDeviceApprovalBrand(options.deviceApproval);
24360
+ const trustedDevHosts = normalizeTrustedDevHosts(options.trustedDevHosts);
24300
24361
  const toolsDir = options.toolsDir ? path9__default.resolve(process.cwd(), options.toolsDir) : path9__default.resolve(process.cwd(), "agents/tools");
24301
24362
  const hooksDir = options.hooksDir ? path9__default.resolve(process.cwd(), options.hooksDir) : path9__default.resolve(process.cwd(), "agents/hooks");
24302
24363
  const threadApiDir = options.apiDir ? path9__default.resolve(process.cwd(), options.apiDir) : path9__default.resolve(process.cwd(), "agents/api");
@@ -24401,7 +24462,8 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
24401
24462
  installedProviderPackageMap,
24402
24463
  hmr,
24403
24464
  sourceDirs,
24404
- regenerateTypes
24465
+ regenerateTypes,
24466
+ trustedDevHosts
24405
24467
  };
24406
24468
  const workerEntry = path9__default.relative(process.cwd(), generatedWorkerEntry).split(path9__default.sep).join("/");
24407
24469
  const corePlugin = {
@@ -24409,12 +24471,18 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
24409
24471
  enforce: "pre",
24410
24472
  config() {
24411
24473
  writeGeneratedWorkerEntry();
24412
- const viteConfig = createPluginViteConfig(import.meta.url);
24474
+ const viteConfig = createPluginViteConfig(import.meta.url, {
24475
+ isPackageInstalled: isProviderPackageInstalled,
24476
+ trustedDevHosts
24477
+ });
24413
24478
  return viteConfig;
24414
24479
  },
24415
24480
  // Apply exclusions and inclusions to ALL environments including Cloudflare worker
24416
24481
  configEnvironment(_name, config) {
24417
- applyPluginEnvironmentConfig(config);
24482
+ applyPluginEnvironmentConfig(config, {
24483
+ isPackageInstalled: isProviderPackageInstalled,
24484
+ trustedDevHosts
24485
+ });
24418
24486
  },
24419
24487
  resolveId(id) {
24420
24488
  if (id === VIRTUAL_TOOLS_ID) {
@@ -24459,6 +24527,7 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
24459
24527
  },
24460
24528
  buildStart() {
24461
24529
  writeGeneratedWorkerEntry();
24530
+ warnLegacyRootAgentFiles(agentsDir);
24462
24531
  regenerateTypes();
24463
24532
  this.addWatchFile(toolsDir);
24464
24533
  this.addWatchFile(threadApiDir);
@@ -24539,7 +24608,8 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
24539
24608
  corePlugin,
24540
24609
  ...createAgentBuilderCloudflarePlugins({
24541
24610
  workerEntry,
24542
- compatibilityDate: options.compatibilityDate ?? DEFAULT_AGENTBUILDER_COMPATIBILITY_DATE
24611
+ compatibilityDate: options.compatibilityDate ?? DEFAULT_AGENTBUILDER_COMPATIBILITY_DATE,
24612
+ compatibilityFlags: options.compatibilityFlags
24543
24613
  })
24544
24614
  ];
24545
24615
  }
@@ -29229,12 +29299,9 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
29229
29299
  await parentThread.updateChildRegistryStatus(
29230
29300
  params.parent_thread_id,
29231
29301
  childThread.id,
29232
- childResult.terminal ? "terminated" : "idle"
29302
+ "idle"
29233
29303
  );
29234
29304
  }
29235
- if (childResult.terminal && typeof childThreadStub.terminateThread === "function") {
29236
- await childThreadStub.terminateThread(childThread.id);
29237
- }
29238
29305
  } else if (typeof childThreadStub.terminateThread === "function") {
29239
29306
  await childThreadStub.terminateThread(childThread.id);
29240
29307
  }
@@ -33230,11 +33297,13 @@ ${paths.join("\n")}`;
33230
33297
  try {
33231
33298
  const parentId = this.env.AGENT_BUILDER_THREAD.idFromName(parentThreadId);
33232
33299
  const parentStub = this.env.AGENT_BUILDER_THREAD.get(parentId);
33233
- const parentCommunication = await this.getParentCommunicationModeForChild(
33300
+ const childRegistryEntry = await this.getParentRegistryEntryForChild(
33234
33301
  parentStub,
33235
33302
  parentThreadId,
33236
33303
  threadId
33237
33304
  );
33305
+ const parentCommunication = childRegistryEntry?.parentCommunication === "explicit" ? "explicit" : "implicit";
33306
+ const resumableChild = childRegistryEntry?.resumable === true;
33238
33307
  const copiedRefs = await this.copyAttachmentRefsToThread(
33239
33308
  refs,
33240
33309
  parentStub,
@@ -33257,10 +33326,11 @@ ${resultContent}${attachmentSummary}`;
33257
33326
  });
33258
33327
  }
33259
33328
  const terminalChildRun = sessionStopped || hasTerminalSessionTools;
33329
+ const terminateChildThread = terminalChildRun && !resumableChild;
33260
33330
  await parentStub.updateChildRegistryStatus(
33261
33331
  parentThreadId,
33262
33332
  threadId,
33263
- terminalChildRun ? "terminated" : "idle"
33333
+ terminateChildThread ? "terminated" : "idle"
33264
33334
  );
33265
33335
  if (parentCommunication !== "explicit") {
33266
33336
  await this.persistParentHandoffStatusMessage(
@@ -33268,23 +33338,22 @@ ${resultContent}${attachmentSummary}`;
33268
33338
  isErrorTerminal ? "failure" : "result"
33269
33339
  );
33270
33340
  }
33271
- if (terminalChildRun) {
33341
+ if (terminateChildThread) {
33272
33342
  await this.terminateThread(threadId);
33273
33343
  }
33274
33344
  } catch (error) {
33275
33345
  console.error("[DurableThread] Failed to deliver subagent completion to parent:", error);
33276
33346
  }
33277
33347
  }
33278
- async getParentCommunicationModeForChild(parentStub, parentThreadId, childThreadId) {
33348
+ async getParentRegistryEntryForChild(parentStub, parentThreadId, childThreadId) {
33279
33349
  if (typeof parentStub.getChildrenRegistry !== "function") {
33280
- return "implicit";
33350
+ return void 0;
33281
33351
  }
33282
33352
  try {
33283
33353
  const entries = await parentStub.getChildrenRegistry(parentThreadId);
33284
- const childEntry = entries.find((entry) => entry.reference === childThreadId);
33285
- return childEntry?.parentCommunication === "explicit" ? "explicit" : "implicit";
33354
+ return entries.find((entry) => entry.reference === childThreadId);
33286
33355
  } catch {
33287
- return "implicit";
33356
+ return void 0;
33288
33357
  }
33289
33358
  }
33290
33359
  /**
@@ -34832,7 +34901,7 @@ ${resultContent}${attachmentSummary}`;
34832
34901
  void 0,
34833
34902
  INTERNAL_TOOL_DELIVERY
34834
34903
  );
34835
- if (delivered?.resume) sides.add(delivered.side);
34904
+ if (delivered) sides.add(delivered.side);
34836
34905
  }
34837
34906
  if (threadId) {
34838
34907
  for (const side of sides) {
@@ -35134,17 +35203,14 @@ ${resultContent}${attachmentSummary}`;
35134
35203
  deliveredResultWaiters = /* @__PURE__ */ new Map();
35135
35204
  notifyDeliveredResultWaiters(toolCallId) {
35136
35205
  const waiters = this.deliveredResultWaiters?.get(toolCallId);
35137
- if (!waiters || waiters.size === 0) return false;
35206
+ if (!waiters) return;
35138
35207
  this.deliveredResultWaiters.delete(toolCallId);
35139
- let notified = false;
35140
35208
  for (const wake of waiters) {
35141
35209
  try {
35142
35210
  wake();
35143
- notified = true;
35144
35211
  } catch {
35145
35212
  }
35146
35213
  }
35147
- return notified;
35148
35214
  }
35149
35215
  /**
35150
35216
  * Await a parked forwarded call's delivered result: one immediate read,
@@ -35289,46 +35355,37 @@ ${resultContent}${attachmentSummary}`;
35289
35355
  const side = pending.side === "b" ? "b" : "a";
35290
35356
  const content = ok ? result ?? "" : `Error: ${error ?? "tool failed"}`;
35291
35357
  const toolStatus = ok ? "success" : "error";
35292
- const resultMessageId = crypto.randomUUID();
35293
- const resultCreatedAt = Date.now() * TIMESTAMP_MULTIPLIER;
35294
- const accepted = this.ctx.storage.transactionSync(() => {
35295
- const claimed = this.ctx.storage.sql.exec(
35296
- `UPDATE pending_client_calls
35297
- SET status = 'resolved'
35298
- WHERE tool_call_id = ? AND status = 'pending'`,
35358
+ await this.ctx.storage.sql.exec(
35359
+ `UPDATE messages SET content = ?, tool_status = ? WHERE tool_call_id = ? AND role = 'tool'`,
35360
+ content,
35361
+ toolStatus,
35362
+ toolCallId
35363
+ );
35364
+ const updated = await this.ctx.storage.sql.exec(
35365
+ `SELECT COUNT(*) AS total FROM messages WHERE tool_call_id = ? AND role = 'tool'`,
35366
+ toolCallId
35367
+ );
35368
+ if (Number(updated.toArray()[0]?.total ?? 0) === 0) {
35369
+ const toolRow = await this.ctx.storage.sql.exec(
35370
+ `SELECT tool FROM pending_client_calls WHERE tool_call_id = ? LIMIT 1`,
35299
35371
  toolCallId
35300
35372
  );
35301
- if (claimed.rowsWritten !== 1) return false;
35302
- this.ctx.storage.sql.exec(
35303
- `UPDATE messages SET content = ?, tool_status = ? WHERE tool_call_id = ? AND role = 'tool'`,
35373
+ await this.ctx.storage.sql.exec(
35374
+ `INSERT INTO messages (id, role, content, name, tool_call_id, tool_status, created_at, status, prompt)
35375
+ VALUES (?, 'tool', ?, ?, ?, ?, ?, 'completed', NULL)`,
35376
+ crypto.randomUUID(),
35304
35377
  content,
35378
+ toolRow.toArray()[0]?.tool ?? null,
35379
+ toolCallId,
35305
35380
  toolStatus,
35306
- toolCallId
35381
+ Date.now() * TIMESTAMP_MULTIPLIER
35307
35382
  );
35308
- const updated = this.ctx.storage.sql.exec(
35309
- `SELECT COUNT(*) AS total FROM messages WHERE tool_call_id = ? AND role = 'tool'`,
35310
- toolCallId
35311
- );
35312
- if (Number(updated.toArray()[0]?.total ?? 0) === 0) {
35313
- const toolRow = this.ctx.storage.sql.exec(
35314
- `SELECT tool FROM pending_client_calls WHERE tool_call_id = ? LIMIT 1`,
35315
- toolCallId
35316
- );
35317
- this.ctx.storage.sql.exec(
35318
- `INSERT INTO messages (id, role, content, name, tool_call_id, tool_status, created_at, status, prompt)
35319
- VALUES (?, 'tool', ?, ?, ?, ?, ?, 'completed', NULL)`,
35320
- resultMessageId,
35321
- content,
35322
- toolRow.toArray()[0]?.tool ?? null,
35323
- toolCallId,
35324
- toolStatus,
35325
- resultCreatedAt
35326
- );
35327
- }
35328
- return true;
35329
- });
35330
- if (!accepted) return null;
35331
- const resumedInline = this.notifyDeliveredResultWaiters(toolCallId);
35383
+ }
35384
+ await this.ctx.storage.sql.exec(
35385
+ `UPDATE pending_client_calls SET status = 'resolved' WHERE tool_call_id = ?`,
35386
+ toolCallId
35387
+ );
35388
+ this.notifyDeliveredResultWaiters(toolCallId);
35332
35389
  try {
35333
35390
  const msgCursor = await this.ctx.storage.sql.exec(
35334
35391
  `SELECT id, role, content, name, tool_call_id, tool_status, created_at, depth
@@ -35339,7 +35396,7 @@ ${resultContent}${attachmentSummary}`;
35339
35396
  if (msg) this.broadcastMessage(msg);
35340
35397
  } catch {
35341
35398
  }
35342
- return { side, resume: !resumedInline };
35399
+ return { side };
35343
35400
  }
35344
35401
  // ─── Runtime byte streams ──────────────────────────────────────────────────
35345
35402
  // The existing bridge frames carry opaque capability metadata and bytes
@@ -36513,11 +36570,12 @@ ${resultContent}${attachmentSummary}`;
36513
36570
  if (!parentThreadId) return;
36514
36571
  const parentId = this.env.AGENT_BUILDER_THREAD.idFromName(parentThreadId);
36515
36572
  const parentStub = this.env.AGENT_BUILDER_THREAD.get(parentId);
36516
- const parentCommunication = await this.getParentCommunicationModeForChild(
36573
+ const childRegistryEntry = await this.getParentRegistryEntryForChild(
36517
36574
  parentStub,
36518
36575
  parentThreadId,
36519
36576
  threadId
36520
36577
  );
36578
+ const parentCommunication = childRegistryEntry?.parentCommunication === "explicit" ? "explicit" : "implicit";
36521
36579
  if (parentCommunication !== "explicit") {
36522
36580
  await parentStub.queueMessage(parentThreadId, {
36523
36581
  role: "user",