@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/plugin.d.ts CHANGED
@@ -11,6 +11,8 @@ interface DeviceApprovalBrand {
11
11
 
12
12
  interface AgentPluginOptions {
13
13
  compatibilityDate?: string;
14
+ /** Additional Cloudflare compatibility flags required by this Worker. */
15
+ compatibilityFlags?: string[];
14
16
  toolsDir?: string;
15
17
  hooksDir?: string;
16
18
  apiDir?: string;
@@ -28,6 +30,13 @@ interface AgentPluginOptions {
28
30
  providers?: string[];
29
31
  /** Presentation used by the built-in device sign-in confirmation page. */
30
32
  deviceApproval?: DeviceApprovalBrand;
33
+ /**
34
+ * Exact additional hostnames trusted for local authoring APIs.
35
+ * Anyone who can reach the dev server through one of these names can attempt
36
+ * to authenticate to the authoring surface; same-origin and credential
37
+ * checks still apply.
38
+ */
39
+ trustedDevHosts?: string[];
31
40
  }
32
41
  declare function agentbuilder(options?: AgentPluginOptions): PluginOption[];
33
42
  declare const builder: typeof agentbuilder;
package/dist/plugin.js CHANGED
@@ -1226,7 +1226,7 @@ function createHmrReloader() {
1226
1226
  const isConfigFile = isModelFile || isProviderFile || isPromptFile || isAgentFile || isEffectFile;
1227
1227
  if (!isToolFile && !isThreadApiFile && !isHookFile && !isConfigFile && !isUserEndpointFile) return;
1228
1228
  reloader.invalidateSourceFileModule(server, file);
1229
- if (isConfigFile || isToolFile) regenerateTypes();
1229
+ if (isConfigFile || isToolFile || isHookFile) regenerateTypes();
1230
1230
  if (isToolFile) await reloader.reloadToolsModule(server);
1231
1231
  if (isModelFile) await reloader.reloadModelsModule(server);
1232
1232
  if (isProviderFile) await reloader.reloadProvidersModule(server);
@@ -3269,6 +3269,29 @@ async function scanPromptsDirectory(dir) {
3269
3269
  async function scanAgentsDirectory(dir) {
3270
3270
  return scanConfigDirectory(dir, /export\s+default\s+defineAgent/);
3271
3271
  }
3272
+ function findLegacyRootAgentFiles(agentsDir) {
3273
+ const agentsRoot = path9__default.dirname(agentsDir);
3274
+ if (path9__default.basename(agentsDir) !== "agents" || path9__default.basename(agentsRoot) !== "agents") {
3275
+ return [];
3276
+ }
3277
+ if (!fs9__default.existsSync(agentsRoot)) return [];
3278
+ 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) => {
3279
+ try {
3280
+ return /export\s+default\s+defineAgent/.test(fs9__default.readFileSync(filePath, "utf8"));
3281
+ } catch {
3282
+ return false;
3283
+ }
3284
+ }).sort();
3285
+ }
3286
+ function warnLegacyRootAgentFiles(agentsDir) {
3287
+ const expectedDir = path9__default.relative(process.cwd(), agentsDir).replace(/\\/g, "/");
3288
+ for (const filePath of findLegacyRootAgentFiles(agentsDir)) {
3289
+ const source = path9__default.relative(process.cwd(), filePath).replace(/\\/g, "/");
3290
+ console.warn(
3291
+ `[agentbuilder] Agent definition "${source}" is outside the scanned agent directory. Move it to "${expectedDir}/" so it is registered.`
3292
+ );
3293
+ }
3294
+ }
3272
3295
  async function scanEffectsDirectory(dir) {
3273
3296
  const effects = [];
3274
3297
  if (!fs9__default.existsSync(dir)) {
@@ -6960,7 +6983,32 @@ function isHostedInstance(env) {
6960
6983
  }
6961
6984
  return Boolean(value);
6962
6985
  }
6963
- function isTrustedLocalDevelopmentRequest(request, env) {
6986
+ function normalizeTrustedDevHosts(hosts) {
6987
+ const normalized = /* @__PURE__ */ new Set();
6988
+ for (const rawHost of hosts ?? []) {
6989
+ const candidate = rawHost.trim().toLowerCase().replace(/\.$/, "");
6990
+ try {
6991
+ const parsed = new URL(`http://${candidate}`);
6992
+ if (!candidate || candidate.includes("*") || parsed.hostname.toLowerCase().replace(/\.$/, "") !== candidate || parsed.port || parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
6993
+ throw new Error("invalid hostname");
6994
+ }
6995
+ } catch {
6996
+ throw new Error(
6997
+ `Invalid trusted development hostname "${rawHost}". Use an exact hostname without a scheme, port, path, or wildcard.`
6998
+ );
6999
+ }
7000
+ normalized.add(candidate);
7001
+ }
7002
+ return [...normalized];
7003
+ }
7004
+ function compiledTrustedDevHosts() {
7005
+ try {
7006
+ return typeof __STANDARD_AGENTS_TRUSTED_DEV_HOSTS__ !== "undefined" && Array.isArray(__STANDARD_AGENTS_TRUSTED_DEV_HOSTS__) ? __STANDARD_AGENTS_TRUSTED_DEV_HOSTS__ : [];
7007
+ } catch {
7008
+ return [];
7009
+ }
7010
+ }
7011
+ function isTrustedLocalDevelopmentRequest(request, env, trustedDevHosts = compiledTrustedDevHosts()) {
6964
7012
  if (isHostedInstance(env)) return false;
6965
7013
  let hostname;
6966
7014
  try {
@@ -6968,7 +7016,7 @@ function isTrustedLocalDevelopmentRequest(request, env) {
6968
7016
  } catch {
6969
7017
  return false;
6970
7018
  }
6971
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.endsWith(".localhost") || hostname.endsWith(".orb.local");
7019
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.endsWith(".localhost") || hostname.endsWith(".orb.local") || trustedDevHosts.some((trusted) => trusted.trim().toLowerCase() === hostname);
6972
7020
  }
6973
7021
  function isAdminOnlyApiRoute(routePath, method = "GET") {
6974
7022
  if (routePath === "/api/hooks") return true;
@@ -7063,7 +7111,8 @@ function createDevMiddleware(server, context) {
7063
7111
  installedProviderPackageMap,
7064
7112
  hmr,
7065
7113
  sourceDirs,
7066
- regenerateTypes
7114
+ regenerateTypes,
7115
+ trustedDevHosts
7067
7116
  } = context;
7068
7117
  server.watcher.on("add", async (file) => {
7069
7118
  await hmr.handleFileChange(file, server, sourceDirs, regenerateTypes);
@@ -7097,7 +7146,8 @@ function createDevMiddleware(server, context) {
7097
7146
  try {
7098
7147
  trustedLocalHost = isTrustedLocalDevelopmentRequest(
7099
7148
  new Request(`http://${req.headers.host || "invalid.remote"}${routePath}`),
7100
- {}
7149
+ {},
7150
+ trustedDevHosts
7101
7151
  );
7102
7152
  } catch {
7103
7153
  }
@@ -8289,6 +8339,18 @@ ${validUserProviders.map((p) => ` "${p.name}": async () => (await import("${p.i
8289
8339
  }
8290
8340
  }
8291
8341
  var DEFAULT_AGENTBUILDER_COMPATIBILITY_DATE = "2025-08-13";
8342
+ var REQUIRED_AGENTBUILDER_COMPATIBILITY_FLAGS = [
8343
+ "nodejs_compat",
8344
+ "enable_ctx_exports"
8345
+ ];
8346
+ function compatibilityFlagsWithBuilderRequirements(flags = []) {
8347
+ if (flags.some((flag) => typeof flag !== "string" || flag.trim().length === 0)) {
8348
+ throw new Error(
8349
+ "compatibilityFlags must contain non-empty Cloudflare compatibility flag names"
8350
+ );
8351
+ }
8352
+ return [.../* @__PURE__ */ new Set([...REQUIRED_AGENTBUILDER_COMPATIBILITY_FLAGS, ...flags])];
8353
+ }
8292
8354
  var depsToExclude = [
8293
8355
  "@standardagents/builder",
8294
8356
  "@standardagents/builder/runtime",
@@ -8319,7 +8381,7 @@ var firstPartyProviderPackages = [
8319
8381
  "@standardagents/openrouter",
8320
8382
  "@standardagents/xai"
8321
8383
  ];
8322
- var depsToInclude = [
8384
+ var baseDepsToInclude = [
8323
8385
  "zod",
8324
8386
  "zod/v3",
8325
8387
  "zod/v4",
@@ -8330,17 +8392,24 @@ var depsToInclude = [
8330
8392
  // a root dep). The `parent > child` form pre-bundles it at startup so Vite
8331
8393
  // doesn't discover it mid-request and reload the worker (which would destroy
8332
8394
  // an in-flight Durable Object execution and drop the client bridge).
8333
- "@standardagents/openrouter > @openrouter/sdk",
8334
8395
  "magic-string",
8335
8396
  "@standardagents/spec",
8336
8397
  // Incremental JSON reader used by the runtime to surface a tool's progress
8337
8398
  // argument from partial streamed tool-call arguments (tool_call_started).
8338
- "@formkit/jsonreader",
8339
- // Pre-bundle the provider packages themselves so their whole subtree (SDKs,
8340
- // pricing tables) lands in the initial optimized bundle and nothing is
8341
- // discovered lazily by workerd.
8342
- ...firstPartyProviderPackages
8399
+ "@formkit/jsonreader"
8343
8400
  ];
8401
+ function depsToInclude(options = {}) {
8402
+ const installedProviders = options.isPackageInstalled ? firstPartyProviderPackages.filter(options.isPackageInstalled) : firstPartyProviderPackages;
8403
+ const openRouterTransitive = installedProviders.includes("@standardagents/openrouter") ? ["@standardagents/openrouter > @openrouter/sdk"] : [];
8404
+ return [...baseDepsToInclude, ...openRouterTransitive, ...installedProviders];
8405
+ }
8406
+ function trustedDevHostDefines(options) {
8407
+ return {
8408
+ __STANDARD_AGENTS_TRUSTED_DEV_HOSTS__: JSON.stringify(
8409
+ normalizeTrustedDevHosts(options.trustedDevHosts)
8410
+ )
8411
+ };
8412
+ }
8344
8413
  var packingDeps = [
8345
8414
  "rollup",
8346
8415
  "@rollup/plugin-commonjs",
@@ -8349,7 +8418,7 @@ var packingDeps = [
8349
8418
  "fsevents",
8350
8419
  "typescript"
8351
8420
  ];
8352
- function createPluginViteConfig(pluginModuleUrl) {
8421
+ function createPluginViteConfig(pluginModuleUrl, options = {}) {
8353
8422
  const currentDir = path9__default.dirname(fileURLToPath(pluginModuleUrl));
8354
8423
  const isInDist = currentDir.endsWith("dist");
8355
8424
  const builderClientDir = path9__default.resolve(
@@ -8357,6 +8426,7 @@ function createPluginViteConfig(pluginModuleUrl) {
8357
8426
  isInDist ? "./client" : "../dist/client"
8358
8427
  );
8359
8428
  return {
8429
+ define: trustedDevHostDefines(options),
8360
8430
  publicDir: fs9__default.existsSync(builderClientDir) ? builderClientDir : void 0,
8361
8431
  build: {
8362
8432
  rollupOptions: {
@@ -8372,7 +8442,7 @@ function createPluginViteConfig(pluginModuleUrl) {
8372
8442
  // `npm run dev` ("There is a new version of the pre-bundle for X").
8373
8443
  holdUntilCrawlEnd: true,
8374
8444
  exclude: depsToExclude,
8375
- include: depsToInclude.filter((dep) => dep !== "zod/v3" && dep !== "zod/v4" && dep !== "zod/v4/core")
8445
+ include: depsToInclude(options).filter((dep) => dep !== "zod/v3" && dep !== "zod/v4" && dep !== "zod/v4/core")
8376
8446
  },
8377
8447
  ssr: {
8378
8448
  noExternal: [
@@ -8397,7 +8467,7 @@ function createAgentBuilderWorkerConfig(options) {
8397
8467
  // in vite.config.ts plus their agents/ source tree.
8398
8468
  main: options.workerEntry,
8399
8469
  compatibility_date: compatibilityDate,
8400
- compatibility_flags: ["nodejs_compat", "enable_ctx_exports"],
8470
+ compatibility_flags: compatibilityFlagsWithBuilderRequirements(options.compatibilityFlags),
8401
8471
  observability: {
8402
8472
  enabled: true
8403
8473
  },
@@ -8477,7 +8547,11 @@ function createAgentBuilderCloudflarePlugins(options) {
8477
8547
  }
8478
8548
  });
8479
8549
  }
8480
- function applyPluginEnvironmentConfig(config) {
8550
+ function applyPluginEnvironmentConfig(config, options = {}) {
8551
+ config.define = {
8552
+ ...config.define || {},
8553
+ ...trustedDevHostDefines(options)
8554
+ };
8481
8555
  config.optimizeDeps = config.optimizeDeps || {};
8482
8556
  config.optimizeDeps.holdUntilCrawlEnd = true;
8483
8557
  config.optimizeDeps.exclude = [
@@ -8486,7 +8560,7 @@ function applyPluginEnvironmentConfig(config) {
8486
8560
  ];
8487
8561
  config.optimizeDeps.include = [
8488
8562
  ...config.optimizeDeps.include || [],
8489
- ...depsToInclude.filter((dep) => !config.optimizeDeps?.include?.includes(dep))
8563
+ ...depsToInclude(options).filter((dep) => !config.optimizeDeps?.include?.includes(dep))
8490
8564
  ];
8491
8565
  config.build = config.build || {};
8492
8566
  config.build.rollupOptions = config.build.rollupOptions || {};
@@ -8546,6 +8620,7 @@ function normalizeDeviceApprovalBrand(value) {
8546
8620
  // src/plugin.ts
8547
8621
  function agentbuilder(options = {}) {
8548
8622
  const deviceApproval = normalizeDeviceApprovalBrand(options.deviceApproval);
8623
+ const trustedDevHosts = normalizeTrustedDevHosts(options.trustedDevHosts);
8549
8624
  const toolsDir = options.toolsDir ? path9__default.resolve(process.cwd(), options.toolsDir) : path9__default.resolve(process.cwd(), "agents/tools");
8550
8625
  const hooksDir = options.hooksDir ? path9__default.resolve(process.cwd(), options.hooksDir) : path9__default.resolve(process.cwd(), "agents/hooks");
8551
8626
  const threadApiDir = options.apiDir ? path9__default.resolve(process.cwd(), options.apiDir) : path9__default.resolve(process.cwd(), "agents/api");
@@ -8650,7 +8725,8 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
8650
8725
  installedProviderPackageMap,
8651
8726
  hmr,
8652
8727
  sourceDirs,
8653
- regenerateTypes
8728
+ regenerateTypes,
8729
+ trustedDevHosts
8654
8730
  };
8655
8731
  const workerEntry = path9__default.relative(process.cwd(), generatedWorkerEntry).split(path9__default.sep).join("/");
8656
8732
  const corePlugin = {
@@ -8658,12 +8734,18 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
8658
8734
  enforce: "pre",
8659
8735
  config() {
8660
8736
  writeGeneratedWorkerEntry();
8661
- const viteConfig = createPluginViteConfig(import.meta.url);
8737
+ const viteConfig = createPluginViteConfig(import.meta.url, {
8738
+ isPackageInstalled: isProviderPackageInstalled,
8739
+ trustedDevHosts
8740
+ });
8662
8741
  return viteConfig;
8663
8742
  },
8664
8743
  // Apply exclusions and inclusions to ALL environments including Cloudflare worker
8665
8744
  configEnvironment(_name, config) {
8666
- applyPluginEnvironmentConfig(config);
8745
+ applyPluginEnvironmentConfig(config, {
8746
+ isPackageInstalled: isProviderPackageInstalled,
8747
+ trustedDevHosts
8748
+ });
8667
8749
  },
8668
8750
  resolveId(id) {
8669
8751
  if (id === VIRTUAL_TOOLS_ID) {
@@ -8708,6 +8790,7 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
8708
8790
  },
8709
8791
  buildStart() {
8710
8792
  writeGeneratedWorkerEntry();
8793
+ warnLegacyRootAgentFiles(agentsDir);
8711
8794
  regenerateTypes();
8712
8795
  this.addWatchFile(toolsDir);
8713
8796
  this.addWatchFile(threadApiDir);
@@ -8788,7 +8871,8 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
8788
8871
  corePlugin,
8789
8872
  ...createAgentBuilderCloudflarePlugins({
8790
8873
  workerEntry,
8791
- compatibilityDate: options.compatibilityDate ?? DEFAULT_AGENTBUILDER_COMPATIBILITY_DATE
8874
+ compatibilityDate: options.compatibilityDate ?? DEFAULT_AGENTBUILDER_COMPATIBILITY_DATE,
8875
+ compatibilityFlags: options.compatibilityFlags
8792
8876
  })
8793
8877
  ];
8794
8878
  }