@standardagents/builder 0.10.1-next.bbd142a → 0.11.0-next.41deba4

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
@@ -8,6 +8,7 @@ interface AgentPluginOptions {
8
8
  modelsDir?: string;
9
9
  promptsDir?: string;
10
10
  agentsDir?: string;
11
+ effectsDir?: string;
11
12
  }
12
13
  declare function agentbuilder(options?: AgentPluginOptions): Plugin;
13
14
 
package/dist/plugin.js CHANGED
@@ -813,16 +813,6 @@ function generatePromptFile(data) {
813
813
  const toolsCode = formatToolsArray(data.tools);
814
814
  lines.push(` tools: ${toolsCode},`);
815
815
  }
816
- if (data.handoffAgents && data.handoffAgents.length > 0) {
817
- const agentsStr = data.handoffAgents.map((a) => `'${escapeString2(a)}'`).join(", ");
818
- lines.push(` handoffAgents: [${agentsStr}],`);
819
- }
820
- if (data.beforeTool) {
821
- lines.push(` beforeTool: '${escapeString2(data.beforeTool)}',`);
822
- }
823
- if (data.afterTool) {
824
- lines.push(` afterTool: '${escapeString2(data.afterTool)}',`);
825
- }
826
816
  if (data.reasoning && hasNonNullProperties(data.reasoning)) {
827
817
  const reasoningCode = formatReasoningConfig(data.reasoning);
828
818
  lines.push(` reasoning: ${reasoningCode},`);
@@ -987,7 +977,7 @@ function generateAgentFile(data) {
987
977
  if (data.type && data.type !== "ai_human") {
988
978
  lines.push(` type: '${data.type}',`);
989
979
  }
990
- if (data.maxSessionTurns !== void 0) {
980
+ if (data.maxSessionTurns !== void 0 && data.maxSessionTurns !== null) {
991
981
  lines.push(` maxSessionTurns: ${data.maxSessionTurns},`);
992
982
  }
993
983
  lines.push(` sideA: ${formatSideConfig(data.sideA)},`);
@@ -1000,9 +990,6 @@ function generateAgentFile(data) {
1000
990
  if (data.toolDescription) {
1001
991
  lines.push(` toolDescription: '${escapeString3(data.toolDescription)}',`);
1002
992
  }
1003
- if (data.tags && data.tags.length > 0) {
1004
- lines.push(` tags: ${JSON.stringify(data.tags)},`);
1005
- }
1006
993
  lines.push(`});`);
1007
994
  lines.push("");
1008
995
  return lines.join("\n");
@@ -1022,11 +1009,11 @@ function formatSideConfig(config) {
1022
1009
  if (config.stopToolResponseProperty) {
1023
1010
  parts.push(` stopToolResponseProperty: '${escapeString3(config.stopToolResponseProperty)}',`);
1024
1011
  }
1025
- if (config.maxTurns !== void 0) {
1026
- parts.push(` maxTurns: ${config.maxTurns},`);
1012
+ if (config.maxSteps !== void 0) {
1013
+ parts.push(` maxSteps: ${config.maxSteps},`);
1027
1014
  }
1028
- if (config.endConversationTool) {
1029
- parts.push(` endConversationTool: '${escapeString3(config.endConversationTool)}',`);
1015
+ if (config.endSessionTool) {
1016
+ parts.push(` endSessionTool: '${escapeString3(config.endSessionTool)}',`);
1030
1017
  }
1031
1018
  if (config.manualStopCondition !== void 0) {
1032
1019
  parts.push(` manualStopCondition: ${config.manualStopCondition},`);
@@ -1126,7 +1113,7 @@ function validateModelData(data) {
1126
1113
  if (!data.provider || typeof data.provider !== "string") {
1127
1114
  return "Model provider is required and must be a string";
1128
1115
  }
1129
- const validProviders = ["openai", "openrouter", "anthropic", "google"];
1116
+ const validProviders = ["openai", "openrouter", "anthropic", "google", "test"];
1130
1117
  if (!validProviders.includes(data.provider)) {
1131
1118
  return `Invalid provider '${data.provider}'. Must be one of: ${validProviders.join(", ")}`;
1132
1119
  }
@@ -1173,11 +1160,8 @@ function transformPromptData(data) {
1173
1160
  required_schema: "requiredSchema",
1174
1161
  include_chat: "includeChat",
1175
1162
  include_past_tools: "includePastTools",
1176
- before_tool: "beforeTool",
1177
- after_tool: "afterTool",
1178
1163
  parallel_tool_calls: "parallelToolCalls",
1179
1164
  tool_choice: "toolChoice",
1180
- handoff_agents: "handoffAgents",
1181
1165
  reasoning_effort: "reasoningEffort",
1182
1166
  reasoning_max_tokens: "reasoningMaxTokens",
1183
1167
  reasoning_exclude: "reasoningExclude",
@@ -1328,9 +1312,6 @@ function validatePromptData(data) {
1328
1312
  if (data.tools !== void 0 && !Array.isArray(data.tools)) {
1329
1313
  return "tools must be an array";
1330
1314
  }
1331
- if (data.handoffAgents !== void 0 && !Array.isArray(data.handoffAgents)) {
1332
- return "handoffAgents must be an array";
1333
- }
1334
1315
  if (data.reasoning !== void 0) {
1335
1316
  if (typeof data.reasoning !== "object") {
1336
1317
  return "reasoning must be an object";
@@ -1375,11 +1356,11 @@ function transformAgentData(data) {
1375
1356
  if (data.side_a_stop_tool_response_property) {
1376
1357
  transformed.sideA.stopToolResponseProperty = data.side_a_stop_tool_response_property;
1377
1358
  }
1378
- if (data.side_a_max_turns !== void 0) {
1379
- transformed.sideA.maxTurns = data.side_a_max_turns;
1359
+ if (data.side_a_max_steps !== void 0) {
1360
+ transformed.sideA.maxSteps = data.side_a_max_steps;
1380
1361
  }
1381
- if (data.side_a_end_conversation_tool) {
1382
- transformed.sideA.endConversationTool = data.side_a_end_conversation_tool;
1362
+ if (data.side_a_end_session_tool) {
1363
+ transformed.sideA.endSessionTool = data.side_a_end_session_tool;
1383
1364
  }
1384
1365
  if (data.side_a_manual_stop_condition !== void 0) {
1385
1366
  transformed.sideA.manualStopCondition = data.side_a_manual_stop_condition;
@@ -1400,11 +1381,11 @@ function transformAgentData(data) {
1400
1381
  if (data.side_b_stop_tool_response_property) {
1401
1382
  transformed.sideB.stopToolResponseProperty = data.side_b_stop_tool_response_property;
1402
1383
  }
1403
- if (data.side_b_max_turns !== void 0) {
1404
- transformed.sideB.maxTurns = data.side_b_max_turns;
1384
+ if (data.side_b_max_steps !== void 0) {
1385
+ transformed.sideB.maxSteps = data.side_b_max_steps;
1405
1386
  }
1406
- if (data.side_b_end_conversation_tool) {
1407
- transformed.sideB.endConversationTool = data.side_b_end_conversation_tool;
1387
+ if (data.side_b_end_session_tool) {
1388
+ transformed.sideB.endSessionTool = data.side_b_end_session_tool;
1408
1389
  }
1409
1390
  if (data.side_b_manual_stop_condition !== void 0) {
1410
1391
  transformed.sideB.manualStopCondition = data.side_b_manual_stop_condition;
@@ -1416,9 +1397,6 @@ function transformAgentData(data) {
1416
1397
  if (data.tool_description) {
1417
1398
  transformed.toolDescription = data.tool_description;
1418
1399
  }
1419
- if (data.tags) {
1420
- transformed.tags = data.tags;
1421
- }
1422
1400
  return transformed;
1423
1401
  }
1424
1402
  function getAgentFilePath(agentsDir, name) {
@@ -1606,9 +1584,9 @@ function validateAgentData(data) {
1606
1584
  if (data.sideA.stopTool && !data.sideA.stopToolResponseProperty) {
1607
1585
  return "sideA.stopToolResponseProperty is required when sideA.stopTool is set";
1608
1586
  }
1609
- if (data.sideA.maxTurns !== void 0) {
1610
- if (typeof data.sideA.maxTurns !== "number" || data.sideA.maxTurns <= 0) {
1611
- return "sideA.maxTurns must be a positive number";
1587
+ if (data.sideA.maxSteps !== void 0) {
1588
+ if (typeof data.sideA.maxSteps !== "number" || data.sideA.maxSteps <= 0) {
1589
+ return "sideA.maxSteps must be a positive number";
1612
1590
  }
1613
1591
  }
1614
1592
  if (data.type === "dual_ai") {
@@ -1621,30 +1599,20 @@ function validateAgentData(data) {
1621
1599
  if (data.sideB.stopTool && !data.sideB.stopToolResponseProperty) {
1622
1600
  return "sideB.stopToolResponseProperty is required when sideB.stopTool is set";
1623
1601
  }
1624
- if (data.sideB.maxTurns !== void 0) {
1625
- if (typeof data.sideB.maxTurns !== "number" || data.sideB.maxTurns <= 0) {
1626
- return "sideB.maxTurns must be a positive number";
1602
+ if (data.sideB.maxSteps !== void 0) {
1603
+ if (typeof data.sideB.maxSteps !== "number" || data.sideB.maxSteps <= 0) {
1604
+ return "sideB.maxSteps must be a positive number";
1627
1605
  }
1628
1606
  }
1629
1607
  }
1630
1608
  if (data.exposeAsTool && !data.toolDescription) {
1631
1609
  return "toolDescription is required when exposeAsTool is true";
1632
1610
  }
1633
- if (data.maxSessionTurns !== void 0) {
1611
+ if (data.maxSessionTurns !== void 0 && data.maxSessionTurns !== null) {
1634
1612
  if (typeof data.maxSessionTurns !== "number" || data.maxSessionTurns <= 0) {
1635
1613
  return "maxSessionTurns must be a positive number";
1636
1614
  }
1637
1615
  }
1638
- if (data.tags !== void 0) {
1639
- if (!Array.isArray(data.tags)) {
1640
- return "tags must be an array";
1641
- }
1642
- for (const tag of data.tags) {
1643
- if (typeof tag !== "string") {
1644
- return "Each tag must be a string";
1645
- }
1646
- }
1647
- }
1648
1616
  return null;
1649
1617
  }
1650
1618
 
@@ -1668,6 +1636,8 @@ var VIRTUAL_PROMPTS_ID = "virtual:@standardagents-prompts";
1668
1636
  var RESOLVED_VIRTUAL_PROMPTS_ID = "\0" + VIRTUAL_PROMPTS_ID;
1669
1637
  var VIRTUAL_AGENTS_ID = "virtual:@standardagents-agents";
1670
1638
  var RESOLVED_VIRTUAL_AGENTS_ID = "\0" + VIRTUAL_AGENTS_ID;
1639
+ var VIRTUAL_EFFECTS_ID = "virtual:@standardagents-effects";
1640
+ var RESOLVED_VIRTUAL_EFFECTS_ID = "\0" + VIRTUAL_EFFECTS_ID;
1671
1641
  var VIRTUAL_BUILDER_ID = "virtual:@standardagents/builder";
1672
1642
  var RESOLVED_VIRTUAL_BUILDER_ID = "\0" + VIRTUAL_BUILDER_ID;
1673
1643
  function scanApiDirectory(dir, baseRoute = "") {
@@ -1843,6 +1813,33 @@ async function scanPromptsDirectory(dir) {
1843
1813
  async function scanAgentsDirectory(dir) {
1844
1814
  return scanConfigDirectory(dir, /export\s+default\s+defineAgent/);
1845
1815
  }
1816
+ async function scanEffectsDirectory(dir) {
1817
+ const effects = [];
1818
+ if (!fs2.existsSync(dir)) {
1819
+ return effects;
1820
+ }
1821
+ const entries = await fs2.promises.readdir(dir, { withFileTypes: true });
1822
+ for (const entry of entries) {
1823
+ if (entry.isFile() && entry.name.endsWith(".ts")) {
1824
+ const fileName = entry.name.replace(".ts", "");
1825
+ const filePath = path3.join(dir, entry.name);
1826
+ const importPath = "./" + path3.relative(process.cwd(), filePath).replace(/\\/g, "/");
1827
+ if (fileName === "CLAUDE" || fileName.startsWith("_")) {
1828
+ continue;
1829
+ }
1830
+ try {
1831
+ const content = fs2.readFileSync(filePath, "utf-8");
1832
+ if (!content.includes("defineEffect")) {
1833
+ continue;
1834
+ }
1835
+ } catch {
1836
+ continue;
1837
+ }
1838
+ effects.push({ name: fileName, importPath });
1839
+ }
1840
+ }
1841
+ return effects;
1842
+ }
1846
1843
  function parseRequestBody(req) {
1847
1844
  return new Promise((resolve, reject) => {
1848
1845
  let body = "";
@@ -1873,6 +1870,7 @@ function agentbuilder(options = {}) {
1873
1870
  const modelsDir = options.modelsDir ? path3.resolve(process.cwd(), options.modelsDir) : path3.resolve(process.cwd(), "agents/models");
1874
1871
  const promptsDir = options.promptsDir ? path3.resolve(process.cwd(), options.promptsDir) : path3.resolve(process.cwd(), "agents/prompts");
1875
1872
  const agentsDir = options.agentsDir ? path3.resolve(process.cwd(), options.agentsDir) : path3.resolve(process.cwd(), "agents/agents");
1873
+ const effectsDir = options.effectsDir ? path3.resolve(process.cwd(), options.effectsDir) : path3.resolve(process.cwd(), "agents/effects");
1876
1874
  const outputDir = path3.resolve(process.cwd(), ".agents");
1877
1875
  const typeGenConfig = {
1878
1876
  modelsDir,
@@ -2063,11 +2061,10 @@ function agentbuilder(options = {}) {
2063
2061
  // WASM image processing deps - must be excluded to avoid pre-bundle cache issues
2064
2062
  "@cf-wasm/photon",
2065
2063
  "@cf-wasm/photon/workerd",
2064
+ "@standardagents/sip",
2065
+ // sip's jsquash dependencies (WASM-based decoders)
2066
2066
  "@jsquash/avif",
2067
- "@jsquash/jpeg",
2068
- "@jsquash/png",
2069
- "@jsquash/webp",
2070
- "@standardagents/sip"
2067
+ "@jsquash/webp"
2071
2068
  ];
2072
2069
  const depsToInclude = [
2073
2070
  "zod",
@@ -2102,11 +2099,10 @@ function agentbuilder(options = {}) {
2102
2099
  // WASM image processing deps
2103
2100
  "@cf-wasm/photon",
2104
2101
  "@cf-wasm/photon/workerd",
2102
+ "@standardagents/sip",
2103
+ // sip's jsquash dependencies (WASM-based decoders)
2105
2104
  "@jsquash/avif",
2106
- "@jsquash/jpeg",
2107
- "@jsquash/png",
2108
- "@jsquash/webp",
2109
- "@standardagents/sip"
2105
+ "@jsquash/webp"
2110
2106
  ];
2111
2107
  const depsToInclude = [
2112
2108
  "zod",
@@ -2147,6 +2143,9 @@ function agentbuilder(options = {}) {
2147
2143
  if (id === VIRTUAL_AGENTS_ID) {
2148
2144
  return RESOLVED_VIRTUAL_AGENTS_ID;
2149
2145
  }
2146
+ if (id === VIRTUAL_EFFECTS_ID) {
2147
+ return RESOLVED_VIRTUAL_EFFECTS_ID;
2148
+ }
2150
2149
  if (id === VIRTUAL_BUILDER_ID) {
2151
2150
  return RESOLVED_VIRTUAL_BUILDER_ID;
2152
2151
  }
@@ -2464,6 +2463,31 @@ ${agentsCode}
2464
2463
  };
2465
2464
 
2466
2465
  export const agentNames = ${JSON.stringify(agents.filter((a) => !a.error).map((a) => a.name))};
2466
+ `;
2467
+ }
2468
+ if (id === RESOLVED_VIRTUAL_EFFECTS_ID) {
2469
+ const effects = await scanEffectsDirectory(effectsDir);
2470
+ const effectsCode = effects.map(({ name, importPath, error }) => {
2471
+ if (error) {
2472
+ const escapedError = error.replace(/"/g, '\\"').replace(/\n/g, "\\n");
2473
+ return ` "${name}": async () => { throw new Error("${escapedError}"); },`;
2474
+ } else {
2475
+ return ` "${name}": async () => {
2476
+ try {
2477
+ return (await import("${importPath}")).default;
2478
+ } catch (error) {
2479
+ console.error('Failed to import effect ${name}:', error);
2480
+ throw error;
2481
+ }
2482
+ },`;
2483
+ }
2484
+ }).join("\n");
2485
+ return `// Virtual agent effects module
2486
+ export const effects = {
2487
+ ${effectsCode}
2488
+ };
2489
+
2490
+ export const effectNames = ${JSON.stringify(effects.filter((e) => !e.error).map((e) => e.name))};
2467
2491
  `;
2468
2492
  }
2469
2493
  if (id === RESOLVED_VIRTUAL_BUILDER_ID) {
@@ -2472,6 +2496,7 @@ export const agentNames = ${JSON.stringify(agents.filter((a) => !a.error).map((a
2472
2496
  const models = await scanModelsDirectory(modelsDir);
2473
2497
  const prompts = await scanPromptsDirectory(promptsDir);
2474
2498
  const agents = await scanAgentsDirectory(agentsDir);
2499
+ const effects = await scanEffectsDirectory(effectsDir);
2475
2500
  const toAbsolutePath = (relativePath) => {
2476
2501
  if (relativePath.startsWith("./")) {
2477
2502
  return path3.resolve(process.cwd(), relativePath).replace(/\\/g, "/");
@@ -2550,6 +2575,22 @@ export const agentNames = ${JSON.stringify(agents.filter((a) => !a.error).map((a
2550
2575
  console.error('Failed to import agent ${name}:', error);
2551
2576
  throw error;
2552
2577
  }
2578
+ },`;
2579
+ }
2580
+ }).join("\n");
2581
+ const effectsCode = effects.map(({ name, importPath, error }) => {
2582
+ const absPath = toAbsolutePath(importPath);
2583
+ if (error) {
2584
+ const escapedError = error.replace(/"/g, '\\"').replace(/\n/g, "\\n");
2585
+ return ` "${name}": async () => { throw new Error("${escapedError}"); },`;
2586
+ } else {
2587
+ return ` "${name}": async () => {
2588
+ try {
2589
+ return (await import("${absPath}")).default;
2590
+ } catch (error) {
2591
+ console.error('Failed to import effect ${name}:', error);
2592
+ throw error;
2593
+ }
2553
2594
  },`;
2554
2595
  }
2555
2596
  }).join("\n");
@@ -2587,6 +2628,10 @@ const _agents = {
2587
2628
  ${agentsCode}
2588
2629
  };
2589
2630
 
2631
+ const _effects = {
2632
+ ${effectsCode}
2633
+ };
2634
+
2590
2635
  /**
2591
2636
  * DurableThread with all virtual module methods already implemented.
2592
2637
  * Simply extend this class in your agents/Thread.ts file.
@@ -2621,6 +2666,10 @@ export class DurableThread extends _BaseDurableThread {
2621
2666
  agents() {
2622
2667
  return _agents;
2623
2668
  }
2669
+
2670
+ effects() {
2671
+ return _effects;
2672
+ }
2624
2673
  }
2625
2674
 
2626
2675
  /**
@@ -2647,6 +2696,10 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
2647
2696
  agents() {
2648
2697
  return _agents;
2649
2698
  }
2699
+
2700
+ effects() {
2701
+ return _effects;
2702
+ }
2650
2703
  }
2651
2704
  `;
2652
2705
  }
@@ -2659,6 +2712,7 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
2659
2712
  this.addWatchFile(modelsDir);
2660
2713
  this.addWatchFile(promptsDir);
2661
2714
  this.addWatchFile(agentsDir);
2715
+ this.addWatchFile(effectsDir);
2662
2716
  },
2663
2717
  configureServer(server) {
2664
2718
  server.watcher.on("add", async (file) => {
@@ -2903,20 +2957,12 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
2903
2957
  const getIncludePastTools = (c) => c.match(/includePastTools:\s*(true|false)/)?.[1] === "true";
2904
2958
  const getParallelToolCalls = (c) => c.match(/parallelToolCalls:\s*(true|false)/)?.[1] === "true";
2905
2959
  const getToolChoice = (c) => c.match(/toolChoice:\s*['"]([^'"]+)['"]/)?.[1];
2906
- const getBeforeTool = (c) => c.match(/beforeTool:\s*['"]([^'"]+)['"]/)?.[1];
2907
- const getAfterTool = (c) => c.match(/afterTool:\s*['"]([^'"]+)['"]/)?.[1];
2908
2960
  const getTools = (c) => {
2909
2961
  const match = c.match(/tools:\s*\[([^\]]*)\]/);
2910
2962
  if (!match) return [];
2911
2963
  const items = match[1].match(/['"]([^'"]+)['"]/g);
2912
2964
  return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
2913
2965
  };
2914
- const getHandoffAgents = (c) => {
2915
- const match = c.match(/handoffAgents:\s*\[([^\]]*)\]/);
2916
- if (!match) return [];
2917
- const items = match[1].match(/['"]([^'"]+)['"]/g);
2918
- return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
2919
- };
2920
2966
  const getPrompt = (c) => {
2921
2967
  const backtickMatch = c.match(/prompt:\s*`([\s\S]*?)`/);
2922
2968
  if (backtickMatch) return backtickMatch[1];
@@ -2944,10 +2990,7 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
2944
2990
  include_past_tools: getIncludePastTools(content),
2945
2991
  parallel_tool_calls: getParallelToolCalls(content),
2946
2992
  tool_choice: getToolChoice(content) || "auto",
2947
- before_tool: getBeforeTool(content) || null,
2948
- after_tool: getAfterTool(content) || null,
2949
2993
  tools: getTools(content),
2950
- prompts: getHandoffAgents(content),
2951
2994
  reasoning: null,
2952
2995
  // Complex to parse
2953
2996
  created_at: Math.floor(Date.now() / 1e3)