@standardagents/builder 0.10.1-next.bbd142a → 0.11.0-next.14455ae
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/LICENSE.txt +48 -0
- package/dist/built-in-routes.js +22190 -407
- package/dist/built-in-routes.js.map +1 -1
- package/dist/client/assets/index.css +1 -1
- package/dist/client/index.js +28 -19
- package/dist/client/vendor.js +1 -1
- package/dist/client/vue.js +1 -1
- package/dist/image-processing.d.ts +10 -6
- package/dist/image-processing.js +11 -138
- package/dist/image-processing.js.map +1 -1
- package/dist/index.d.ts +684 -832
- package/dist/index.js +7491 -4615
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +7 -0
- package/dist/plugin.js +394 -131
- package/dist/plugin.js.map +1 -1
- package/dist/sip.wasm +0 -0
- package/package.json +24 -23
- package/dist/client/assets/img/meta.svg +0 -19
- package/dist/client/assets/img/moonshotai.svg +0 -4
- package/dist/client/assets/img/zai.svg +0 -219
package/dist/plugin.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fs2 from 'fs';
|
|
2
2
|
import path3 from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import { createRequire } from 'module';
|
|
5
4
|
|
|
6
5
|
// src/plugin.ts
|
|
7
6
|
var TSCONFIG_CONTENT = `{
|
|
@@ -398,6 +397,9 @@ declare module 'virtual:@standardagents/builder' {
|
|
|
398
397
|
listThreads(params?: {
|
|
399
398
|
agent_name?: string;
|
|
400
399
|
user_id?: string;
|
|
400
|
+
search?: string;
|
|
401
|
+
startDate?: number;
|
|
402
|
+
endDate?: number;
|
|
401
403
|
limit?: number;
|
|
402
404
|
offset?: number;
|
|
403
405
|
}): Promise<{ threads: ThreadRegistryEntry[]; total: number }>;
|
|
@@ -579,14 +581,91 @@ function needsRegeneration(config) {
|
|
|
579
581
|
return false;
|
|
580
582
|
}
|
|
581
583
|
|
|
584
|
+
// src/utils/model-parser.ts
|
|
585
|
+
function getName(content) {
|
|
586
|
+
return content.match(/name:\s*['"]([^'"]+)['"]/)?.[1];
|
|
587
|
+
}
|
|
588
|
+
function getProvider(content) {
|
|
589
|
+
const stringMatch = content.match(/provider:\s*['"]([^'"]+)['"]/)?.[1];
|
|
590
|
+
if (stringMatch) return stringMatch;
|
|
591
|
+
const refMatch = content.match(/provider:\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*[,\n}]/)?.[1];
|
|
592
|
+
return refMatch || void 0;
|
|
593
|
+
}
|
|
594
|
+
function getModel(content) {
|
|
595
|
+
return content.match(/model:\s*['"]([^'"]+)['"]/)?.[1];
|
|
596
|
+
}
|
|
597
|
+
function getInputPrice(content) {
|
|
598
|
+
const match = content.match(/inputPrice:\s*([\d.]+)/);
|
|
599
|
+
return match ? parseFloat(match[1]) : void 0;
|
|
600
|
+
}
|
|
601
|
+
function getOutputPrice(content) {
|
|
602
|
+
const match = content.match(/outputPrice:\s*([\d.]+)/);
|
|
603
|
+
return match ? parseFloat(match[1]) : void 0;
|
|
604
|
+
}
|
|
605
|
+
function getCachedPrice(content) {
|
|
606
|
+
const match = content.match(/cachedPrice:\s*([\d.]+)/);
|
|
607
|
+
return match ? parseFloat(match[1]) : void 0;
|
|
608
|
+
}
|
|
609
|
+
function getIncludedProviders(content) {
|
|
610
|
+
const match = content.match(/includedProviders:\s*\[([^\]]*)\]/);
|
|
611
|
+
if (!match) return void 0;
|
|
612
|
+
const items = match[1].match(/['"]([^'"]+)['"]/g);
|
|
613
|
+
return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
|
|
614
|
+
}
|
|
615
|
+
function getFallbacks(content) {
|
|
616
|
+
const match = content.match(/fallbacks:\s*\[([^\]]*)\]/);
|
|
617
|
+
if (!match) return [];
|
|
618
|
+
const items = match[1].match(/['"]([^'"]+)['"]/g);
|
|
619
|
+
return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
|
|
620
|
+
}
|
|
621
|
+
function getProviderTools(content) {
|
|
622
|
+
const match = content.match(/providerTools:\s*\[([^\]]*)\]/);
|
|
623
|
+
if (!match) return [];
|
|
624
|
+
const items = match[1].match(/['"]([^'"]+)['"]/g);
|
|
625
|
+
return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
|
|
626
|
+
}
|
|
627
|
+
function getCapabilities(content) {
|
|
628
|
+
const match = content.match(/capabilities:\s*\{([^}]*)\}/s);
|
|
629
|
+
if (!match) return void 0;
|
|
630
|
+
const inner = match[1];
|
|
631
|
+
const caps = {};
|
|
632
|
+
const boolMatches = inner.matchAll(/(\w+):\s*(true|false)/g);
|
|
633
|
+
for (const m of boolMatches) {
|
|
634
|
+
caps[m[1]] = m[2] === "true";
|
|
635
|
+
}
|
|
636
|
+
const numMatches = inner.matchAll(/(\w+):\s*(\d+)/g);
|
|
637
|
+
for (const m of numMatches) {
|
|
638
|
+
caps[m[1]] = parseInt(m[2], 10);
|
|
639
|
+
}
|
|
640
|
+
return Object.keys(caps).length > 0 ? caps : void 0;
|
|
641
|
+
}
|
|
642
|
+
function parseModelFile(content) {
|
|
643
|
+
const name = getName(content);
|
|
644
|
+
if (!name) return null;
|
|
645
|
+
return {
|
|
646
|
+
name,
|
|
647
|
+
provider: getProvider(content),
|
|
648
|
+
model: getModel(content),
|
|
649
|
+
inputPrice: getInputPrice(content),
|
|
650
|
+
outputPrice: getOutputPrice(content),
|
|
651
|
+
cachedPrice: getCachedPrice(content),
|
|
652
|
+
includedProviders: getIncludedProviders(content),
|
|
653
|
+
fallbacks: getFallbacks(content),
|
|
654
|
+
providerTools: getProviderTools(content),
|
|
655
|
+
capabilities: getCapabilities(content)
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
|
|
582
659
|
// src/sdk/generators/generateModelFile.ts
|
|
583
|
-
function generateModelFile(data) {
|
|
660
|
+
function generateModelFile(data, options) {
|
|
661
|
+
const { providerName, providerPackage } = options;
|
|
584
662
|
const lines = [
|
|
585
663
|
`import { defineModel } from '@standardagents/builder';`,
|
|
664
|
+
`import { ${providerName} } from '${providerPackage}';`,
|
|
586
665
|
"",
|
|
587
666
|
`export default defineModel({`,
|
|
588
667
|
` name: '${escapeString(data.name)}',`,
|
|
589
|
-
` provider:
|
|
668
|
+
` provider: ${providerName},`,
|
|
590
669
|
` model: '${escapeString(data.model)}',`
|
|
591
670
|
];
|
|
592
671
|
if (data.includedProviders && data.includedProviders.length > 0) {
|
|
@@ -595,6 +674,9 @@ function generateModelFile(data) {
|
|
|
595
674
|
if (data.fallbacks && data.fallbacks.length > 0) {
|
|
596
675
|
lines.push(` fallbacks: ${JSON.stringify(data.fallbacks)},`);
|
|
597
676
|
}
|
|
677
|
+
if (data.providerTools && data.providerTools.length > 0) {
|
|
678
|
+
lines.push(` providerTools: ${JSON.stringify(data.providerTools)},`);
|
|
679
|
+
}
|
|
598
680
|
if (data.inputPrice !== void 0) {
|
|
599
681
|
lines.push(` inputPrice: ${data.inputPrice},`);
|
|
600
682
|
}
|
|
@@ -604,6 +686,36 @@ function generateModelFile(data) {
|
|
|
604
686
|
if (data.cachedPrice !== void 0) {
|
|
605
687
|
lines.push(` cachedPrice: ${data.cachedPrice},`);
|
|
606
688
|
}
|
|
689
|
+
if (data.capabilities && Object.keys(data.capabilities).length > 0) {
|
|
690
|
+
const caps = data.capabilities;
|
|
691
|
+
const capLines = [];
|
|
692
|
+
if (caps.supportsImages !== void 0) {
|
|
693
|
+
capLines.push(` supportsImages: ${caps.supportsImages},`);
|
|
694
|
+
}
|
|
695
|
+
if (caps.supportsToolCalls !== void 0) {
|
|
696
|
+
capLines.push(` supportsToolCalls: ${caps.supportsToolCalls},`);
|
|
697
|
+
}
|
|
698
|
+
if (caps.supportsStreaming !== void 0) {
|
|
699
|
+
capLines.push(` supportsStreaming: ${caps.supportsStreaming},`);
|
|
700
|
+
}
|
|
701
|
+
if (caps.supportsJsonMode !== void 0) {
|
|
702
|
+
capLines.push(` supportsJsonMode: ${caps.supportsJsonMode},`);
|
|
703
|
+
}
|
|
704
|
+
if (caps.maxContextTokens !== void 0) {
|
|
705
|
+
capLines.push(` maxContextTokens: ${caps.maxContextTokens},`);
|
|
706
|
+
}
|
|
707
|
+
if (caps.maxOutputTokens !== void 0) {
|
|
708
|
+
capLines.push(` maxOutputTokens: ${caps.maxOutputTokens},`);
|
|
709
|
+
}
|
|
710
|
+
if (caps.reasoningLevels !== void 0) {
|
|
711
|
+
capLines.push(` reasoningLevels: ${JSON.stringify(caps.reasoningLevels)},`);
|
|
712
|
+
}
|
|
713
|
+
if (capLines.length > 0) {
|
|
714
|
+
lines.push(` capabilities: {`);
|
|
715
|
+
lines.push(...capLines);
|
|
716
|
+
lines.push(` },`);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
607
719
|
lines.push(`});`);
|
|
608
720
|
lines.push("");
|
|
609
721
|
return lines.join("\n");
|
|
@@ -813,16 +925,6 @@ function generatePromptFile(data) {
|
|
|
813
925
|
const toolsCode = formatToolsArray(data.tools);
|
|
814
926
|
lines.push(` tools: ${toolsCode},`);
|
|
815
927
|
}
|
|
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
928
|
if (data.reasoning && hasNonNullProperties(data.reasoning)) {
|
|
827
929
|
const reasoningCode = formatReasoningConfig(data.reasoning);
|
|
828
930
|
lines.push(` reasoning: ${reasoningCode},`);
|
|
@@ -868,6 +970,12 @@ function formatToolConfig(config) {
|
|
|
868
970
|
if (config.init_user_message_property !== void 0 && config.init_user_message_property !== null) {
|
|
869
971
|
parts.push(`initUserMessageProperty: '${escapeString2(config.init_user_message_property)}'`);
|
|
870
972
|
}
|
|
973
|
+
if (config.init_attachments_property !== void 0 && config.init_attachments_property !== null) {
|
|
974
|
+
parts.push(`initAttachmentsProperty: '${escapeString2(config.init_attachments_property)}'`);
|
|
975
|
+
}
|
|
976
|
+
if (config.tenvs && Object.keys(config.tenvs).length > 0) {
|
|
977
|
+
parts.push(`tenvs: ${JSON.stringify(config.tenvs)}`);
|
|
978
|
+
}
|
|
871
979
|
return `{ ${parts.join(", ")} }`;
|
|
872
980
|
}
|
|
873
981
|
function formatReasoningConfig(reasoning) {
|
|
@@ -987,7 +1095,7 @@ function generateAgentFile(data) {
|
|
|
987
1095
|
if (data.type && data.type !== "ai_human") {
|
|
988
1096
|
lines.push(` type: '${data.type}',`);
|
|
989
1097
|
}
|
|
990
|
-
if (data.maxSessionTurns !== void 0) {
|
|
1098
|
+
if (data.maxSessionTurns !== void 0 && data.maxSessionTurns !== null) {
|
|
991
1099
|
lines.push(` maxSessionTurns: ${data.maxSessionTurns},`);
|
|
992
1100
|
}
|
|
993
1101
|
lines.push(` sideA: ${formatSideConfig(data.sideA)},`);
|
|
@@ -1000,8 +1108,8 @@ function generateAgentFile(data) {
|
|
|
1000
1108
|
if (data.toolDescription) {
|
|
1001
1109
|
lines.push(` toolDescription: '${escapeString3(data.toolDescription)}',`);
|
|
1002
1110
|
}
|
|
1003
|
-
if (data.
|
|
1004
|
-
lines.push(`
|
|
1111
|
+
if (data.tenvs && Object.keys(data.tenvs).length > 0) {
|
|
1112
|
+
lines.push(` tenvs: ${JSON.stringify(data.tenvs)},`);
|
|
1005
1113
|
}
|
|
1006
1114
|
lines.push(`});`);
|
|
1007
1115
|
lines.push("");
|
|
@@ -1022,11 +1130,11 @@ function formatSideConfig(config) {
|
|
|
1022
1130
|
if (config.stopToolResponseProperty) {
|
|
1023
1131
|
parts.push(` stopToolResponseProperty: '${escapeString3(config.stopToolResponseProperty)}',`);
|
|
1024
1132
|
}
|
|
1025
|
-
if (config.
|
|
1026
|
-
parts.push(`
|
|
1133
|
+
if (config.maxSteps !== void 0) {
|
|
1134
|
+
parts.push(` maxSteps: ${config.maxSteps},`);
|
|
1027
1135
|
}
|
|
1028
|
-
if (config.
|
|
1029
|
-
parts.push(`
|
|
1136
|
+
if (config.endSessionTool) {
|
|
1137
|
+
parts.push(` endSessionTool: '${escapeString3(config.endSessionTool)}',`);
|
|
1030
1138
|
}
|
|
1031
1139
|
if (config.manualStopCondition !== void 0) {
|
|
1032
1140
|
parts.push(` manualStopCondition: ${config.manualStopCondition},`);
|
|
@@ -1039,8 +1147,15 @@ function escapeString3(str) {
|
|
|
1039
1147
|
}
|
|
1040
1148
|
|
|
1041
1149
|
// src/sdk/persistence/index.ts
|
|
1150
|
+
var PROVIDER_PACKAGE_MAP = {
|
|
1151
|
+
openai: { name: "openai", package: "@standardagents/openai" },
|
|
1152
|
+
openrouter: { name: "openrouter", package: "@standardagents/openrouter" },
|
|
1153
|
+
anthropic: { name: "anthropic", package: "@standardagents/anthropic" },
|
|
1154
|
+
google: { name: "google", package: "@standardagents/google" },
|
|
1155
|
+
test: { name: "test", package: "@standardagents/builder/test" }
|
|
1156
|
+
};
|
|
1042
1157
|
function nameToFilename(name) {
|
|
1043
|
-
return name.replace(/[/\\]/g, "__").replace(/[:*?"
|
|
1158
|
+
return name.replace(/[/\\]/g, "__").replace(/[:*?"<>|.]/g, "_").replace(/-/g, "_");
|
|
1044
1159
|
}
|
|
1045
1160
|
function getModelFilePath(modelsDir, name) {
|
|
1046
1161
|
const filename = nameToFilename(name);
|
|
@@ -1062,7 +1177,17 @@ async function saveModel(modelsDir, data, overwrite = false) {
|
|
|
1062
1177
|
error: `Model file already exists: ${filePath}. Use update to modify existing models.`
|
|
1063
1178
|
};
|
|
1064
1179
|
}
|
|
1065
|
-
const
|
|
1180
|
+
const providerInfo = PROVIDER_PACKAGE_MAP[data.provider];
|
|
1181
|
+
if (!providerInfo) {
|
|
1182
|
+
return {
|
|
1183
|
+
success: false,
|
|
1184
|
+
error: `Unknown provider '${data.provider}'. Must be one of: ${Object.keys(PROVIDER_PACKAGE_MAP).join(", ")}`
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
const content = generateModelFile(data, {
|
|
1188
|
+
providerName: providerInfo.name,
|
|
1189
|
+
providerPackage: providerInfo.package
|
|
1190
|
+
});
|
|
1066
1191
|
await fs2.promises.writeFile(filePath, content, "utf-8");
|
|
1067
1192
|
return {
|
|
1068
1193
|
success: true,
|
|
@@ -1126,7 +1251,7 @@ function validateModelData(data) {
|
|
|
1126
1251
|
if (!data.provider || typeof data.provider !== "string") {
|
|
1127
1252
|
return "Model provider is required and must be a string";
|
|
1128
1253
|
}
|
|
1129
|
-
const validProviders =
|
|
1254
|
+
const validProviders = Object.keys(PROVIDER_PACKAGE_MAP);
|
|
1130
1255
|
if (!validProviders.includes(data.provider)) {
|
|
1131
1256
|
return `Invalid provider '${data.provider}'. Must be one of: ${validProviders.join(", ")}`;
|
|
1132
1257
|
}
|
|
@@ -1173,11 +1298,8 @@ function transformPromptData(data) {
|
|
|
1173
1298
|
required_schema: "requiredSchema",
|
|
1174
1299
|
include_chat: "includeChat",
|
|
1175
1300
|
include_past_tools: "includePastTools",
|
|
1176
|
-
before_tool: "beforeTool",
|
|
1177
|
-
after_tool: "afterTool",
|
|
1178
1301
|
parallel_tool_calls: "parallelToolCalls",
|
|
1179
1302
|
tool_choice: "toolChoice",
|
|
1180
|
-
handoff_agents: "handoffAgents",
|
|
1181
1303
|
reasoning_effort: "reasoningEffort",
|
|
1182
1304
|
reasoning_max_tokens: "reasoningMaxTokens",
|
|
1183
1305
|
reasoning_exclude: "reasoningExclude",
|
|
@@ -1328,9 +1450,6 @@ function validatePromptData(data) {
|
|
|
1328
1450
|
if (data.tools !== void 0 && !Array.isArray(data.tools)) {
|
|
1329
1451
|
return "tools must be an array";
|
|
1330
1452
|
}
|
|
1331
|
-
if (data.handoffAgents !== void 0 && !Array.isArray(data.handoffAgents)) {
|
|
1332
|
-
return "handoffAgents must be an array";
|
|
1333
|
-
}
|
|
1334
1453
|
if (data.reasoning !== void 0) {
|
|
1335
1454
|
if (typeof data.reasoning !== "object") {
|
|
1336
1455
|
return "reasoning must be an object";
|
|
@@ -1375,11 +1494,11 @@ function transformAgentData(data) {
|
|
|
1375
1494
|
if (data.side_a_stop_tool_response_property) {
|
|
1376
1495
|
transformed.sideA.stopToolResponseProperty = data.side_a_stop_tool_response_property;
|
|
1377
1496
|
}
|
|
1378
|
-
if (data.
|
|
1379
|
-
transformed.sideA.
|
|
1497
|
+
if (data.side_a_max_steps !== void 0) {
|
|
1498
|
+
transformed.sideA.maxSteps = data.side_a_max_steps;
|
|
1380
1499
|
}
|
|
1381
|
-
if (data.
|
|
1382
|
-
transformed.sideA.
|
|
1500
|
+
if (data.side_a_end_session_tool) {
|
|
1501
|
+
transformed.sideA.endSessionTool = data.side_a_end_session_tool;
|
|
1383
1502
|
}
|
|
1384
1503
|
if (data.side_a_manual_stop_condition !== void 0) {
|
|
1385
1504
|
transformed.sideA.manualStopCondition = data.side_a_manual_stop_condition;
|
|
@@ -1400,11 +1519,11 @@ function transformAgentData(data) {
|
|
|
1400
1519
|
if (data.side_b_stop_tool_response_property) {
|
|
1401
1520
|
transformed.sideB.stopToolResponseProperty = data.side_b_stop_tool_response_property;
|
|
1402
1521
|
}
|
|
1403
|
-
if (data.
|
|
1404
|
-
transformed.sideB.
|
|
1522
|
+
if (data.side_b_max_steps !== void 0) {
|
|
1523
|
+
transformed.sideB.maxSteps = data.side_b_max_steps;
|
|
1405
1524
|
}
|
|
1406
|
-
if (data.
|
|
1407
|
-
transformed.sideB.
|
|
1525
|
+
if (data.side_b_end_session_tool) {
|
|
1526
|
+
transformed.sideB.endSessionTool = data.side_b_end_session_tool;
|
|
1408
1527
|
}
|
|
1409
1528
|
if (data.side_b_manual_stop_condition !== void 0) {
|
|
1410
1529
|
transformed.sideB.manualStopCondition = data.side_b_manual_stop_condition;
|
|
@@ -1416,9 +1535,6 @@ function transformAgentData(data) {
|
|
|
1416
1535
|
if (data.tool_description) {
|
|
1417
1536
|
transformed.toolDescription = data.tool_description;
|
|
1418
1537
|
}
|
|
1419
|
-
if (data.tags) {
|
|
1420
|
-
transformed.tags = data.tags;
|
|
1421
|
-
}
|
|
1422
1538
|
return transformed;
|
|
1423
1539
|
}
|
|
1424
1540
|
function getAgentFilePath(agentsDir, name) {
|
|
@@ -1606,9 +1722,9 @@ function validateAgentData(data) {
|
|
|
1606
1722
|
if (data.sideA.stopTool && !data.sideA.stopToolResponseProperty) {
|
|
1607
1723
|
return "sideA.stopToolResponseProperty is required when sideA.stopTool is set";
|
|
1608
1724
|
}
|
|
1609
|
-
if (data.sideA.
|
|
1610
|
-
if (typeof data.sideA.
|
|
1611
|
-
return "sideA.
|
|
1725
|
+
if (data.sideA.maxSteps !== void 0) {
|
|
1726
|
+
if (typeof data.sideA.maxSteps !== "number" || data.sideA.maxSteps <= 0) {
|
|
1727
|
+
return "sideA.maxSteps must be a positive number";
|
|
1612
1728
|
}
|
|
1613
1729
|
}
|
|
1614
1730
|
if (data.type === "dual_ai") {
|
|
@@ -1621,35 +1737,24 @@ function validateAgentData(data) {
|
|
|
1621
1737
|
if (data.sideB.stopTool && !data.sideB.stopToolResponseProperty) {
|
|
1622
1738
|
return "sideB.stopToolResponseProperty is required when sideB.stopTool is set";
|
|
1623
1739
|
}
|
|
1624
|
-
if (data.sideB.
|
|
1625
|
-
if (typeof data.sideB.
|
|
1626
|
-
return "sideB.
|
|
1740
|
+
if (data.sideB.maxSteps !== void 0) {
|
|
1741
|
+
if (typeof data.sideB.maxSteps !== "number" || data.sideB.maxSteps <= 0) {
|
|
1742
|
+
return "sideB.maxSteps must be a positive number";
|
|
1627
1743
|
}
|
|
1628
1744
|
}
|
|
1629
1745
|
}
|
|
1630
1746
|
if (data.exposeAsTool && !data.toolDescription) {
|
|
1631
1747
|
return "toolDescription is required when exposeAsTool is true";
|
|
1632
1748
|
}
|
|
1633
|
-
if (data.maxSessionTurns !== void 0) {
|
|
1749
|
+
if (data.maxSessionTurns !== void 0 && data.maxSessionTurns !== null) {
|
|
1634
1750
|
if (typeof data.maxSessionTurns !== "number" || data.maxSessionTurns <= 0) {
|
|
1635
1751
|
return "maxSessionTurns must be a positive number";
|
|
1636
1752
|
}
|
|
1637
1753
|
}
|
|
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
1754
|
return null;
|
|
1649
1755
|
}
|
|
1650
1756
|
|
|
1651
1757
|
// src/plugin.ts
|
|
1652
|
-
createRequire(import.meta.url);
|
|
1653
1758
|
var VIRTUAL_TOOLS_ID = "virtual:@standardagents-tools";
|
|
1654
1759
|
var RESOLVED_VIRTUAL_TOOLS_ID = "\0" + VIRTUAL_TOOLS_ID;
|
|
1655
1760
|
var VIRTUAL_ROUTES_ID = "virtual:@standardagents-routes";
|
|
@@ -1668,6 +1773,10 @@ var VIRTUAL_PROMPTS_ID = "virtual:@standardagents-prompts";
|
|
|
1668
1773
|
var RESOLVED_VIRTUAL_PROMPTS_ID = "\0" + VIRTUAL_PROMPTS_ID;
|
|
1669
1774
|
var VIRTUAL_AGENTS_ID = "virtual:@standardagents-agents";
|
|
1670
1775
|
var RESOLVED_VIRTUAL_AGENTS_ID = "\0" + VIRTUAL_AGENTS_ID;
|
|
1776
|
+
var VIRTUAL_EFFECTS_ID = "virtual:@standardagents-effects";
|
|
1777
|
+
var RESOLVED_VIRTUAL_EFFECTS_ID = "\0" + VIRTUAL_EFFECTS_ID;
|
|
1778
|
+
var VIRTUAL_PROVIDERS_ID = "virtual:@standardagents-providers";
|
|
1779
|
+
var RESOLVED_VIRTUAL_PROVIDERS_ID = "\0" + VIRTUAL_PROVIDERS_ID;
|
|
1671
1780
|
var VIRTUAL_BUILDER_ID = "virtual:@standardagents/builder";
|
|
1672
1781
|
var RESOLVED_VIRTUAL_BUILDER_ID = "\0" + VIRTUAL_BUILDER_ID;
|
|
1673
1782
|
function scanApiDirectory(dir, baseRoute = "") {
|
|
@@ -1843,6 +1952,33 @@ async function scanPromptsDirectory(dir) {
|
|
|
1843
1952
|
async function scanAgentsDirectory(dir) {
|
|
1844
1953
|
return scanConfigDirectory(dir, /export\s+default\s+defineAgent/);
|
|
1845
1954
|
}
|
|
1955
|
+
async function scanEffectsDirectory(dir) {
|
|
1956
|
+
const effects = [];
|
|
1957
|
+
if (!fs2.existsSync(dir)) {
|
|
1958
|
+
return effects;
|
|
1959
|
+
}
|
|
1960
|
+
const entries = await fs2.promises.readdir(dir, { withFileTypes: true });
|
|
1961
|
+
for (const entry of entries) {
|
|
1962
|
+
if (entry.isFile() && entry.name.endsWith(".ts")) {
|
|
1963
|
+
const fileName = entry.name.replace(".ts", "");
|
|
1964
|
+
const filePath = path3.join(dir, entry.name);
|
|
1965
|
+
const importPath = "./" + path3.relative(process.cwd(), filePath).replace(/\\/g, "/");
|
|
1966
|
+
if (fileName === "CLAUDE" || fileName.startsWith("_")) {
|
|
1967
|
+
continue;
|
|
1968
|
+
}
|
|
1969
|
+
try {
|
|
1970
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
1971
|
+
if (!content.includes("defineEffect")) {
|
|
1972
|
+
continue;
|
|
1973
|
+
}
|
|
1974
|
+
} catch {
|
|
1975
|
+
continue;
|
|
1976
|
+
}
|
|
1977
|
+
effects.push({ name: fileName, importPath });
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
return effects;
|
|
1981
|
+
}
|
|
1846
1982
|
function parseRequestBody(req) {
|
|
1847
1983
|
return new Promise((resolve, reject) => {
|
|
1848
1984
|
let body = "";
|
|
@@ -1873,6 +2009,7 @@ function agentbuilder(options = {}) {
|
|
|
1873
2009
|
const modelsDir = options.modelsDir ? path3.resolve(process.cwd(), options.modelsDir) : path3.resolve(process.cwd(), "agents/models");
|
|
1874
2010
|
const promptsDir = options.promptsDir ? path3.resolve(process.cwd(), options.promptsDir) : path3.resolve(process.cwd(), "agents/prompts");
|
|
1875
2011
|
const agentsDir = options.agentsDir ? path3.resolve(process.cwd(), options.agentsDir) : path3.resolve(process.cwd(), "agents/agents");
|
|
2012
|
+
const effectsDir = options.effectsDir ? path3.resolve(process.cwd(), options.effectsDir) : path3.resolve(process.cwd(), "agents/effects");
|
|
1876
2013
|
const outputDir = path3.resolve(process.cwd(), ".agents");
|
|
1877
2014
|
const typeGenConfig = {
|
|
1878
2015
|
modelsDir,
|
|
@@ -2063,17 +2200,24 @@ function agentbuilder(options = {}) {
|
|
|
2063
2200
|
// WASM image processing deps - must be excluded to avoid pre-bundle cache issues
|
|
2064
2201
|
"@cf-wasm/photon",
|
|
2065
2202
|
"@cf-wasm/photon/workerd",
|
|
2203
|
+
"@standardagents/sip",
|
|
2204
|
+
// sip's jsquash dependencies (WASM-based decoders)
|
|
2066
2205
|
"@jsquash/avif",
|
|
2067
|
-
"@jsquash/
|
|
2068
|
-
"@jsquash/png",
|
|
2069
|
-
"@jsquash/webp",
|
|
2070
|
-
"@standardagents/sip"
|
|
2206
|
+
"@jsquash/webp"
|
|
2071
2207
|
];
|
|
2072
2208
|
const depsToInclude = [
|
|
2073
2209
|
"zod",
|
|
2074
2210
|
"openai"
|
|
2075
2211
|
];
|
|
2212
|
+
const currentDir = path3.dirname(fileURLToPath(import.meta.url));
|
|
2213
|
+
const isInDist = currentDir.endsWith("dist");
|
|
2214
|
+
const builderClientDir = path3.resolve(
|
|
2215
|
+
currentDir,
|
|
2216
|
+
isInDist ? "./client" : "../dist/client"
|
|
2217
|
+
);
|
|
2076
2218
|
return {
|
|
2219
|
+
// Set publicDir to builder's client assets so Cloudflare plugin preserves assets config
|
|
2220
|
+
publicDir: fs2.existsSync(builderClientDir) ? builderClientDir : void 0,
|
|
2077
2221
|
optimizeDeps: {
|
|
2078
2222
|
// Exclude our packages from pre-bundling - they contain cloudflare:workers imports
|
|
2079
2223
|
// that cannot be resolved during dependency optimization
|
|
@@ -2102,14 +2246,16 @@ function agentbuilder(options = {}) {
|
|
|
2102
2246
|
// WASM image processing deps
|
|
2103
2247
|
"@cf-wasm/photon",
|
|
2104
2248
|
"@cf-wasm/photon/workerd",
|
|
2249
|
+
"@standardagents/sip",
|
|
2250
|
+
// sip's jsquash dependencies (WASM-based decoders)
|
|
2105
2251
|
"@jsquash/avif",
|
|
2106
|
-
"@jsquash/
|
|
2107
|
-
"@jsquash/png",
|
|
2108
|
-
"@jsquash/webp",
|
|
2109
|
-
"@standardagents/sip"
|
|
2252
|
+
"@jsquash/webp"
|
|
2110
2253
|
];
|
|
2111
2254
|
const depsToInclude = [
|
|
2112
2255
|
"zod",
|
|
2256
|
+
"zod/v3",
|
|
2257
|
+
"zod/v4",
|
|
2258
|
+
"zod/v4/core",
|
|
2113
2259
|
"openai"
|
|
2114
2260
|
];
|
|
2115
2261
|
config.optimizeDeps = config.optimizeDeps || {};
|
|
@@ -2147,6 +2293,12 @@ function agentbuilder(options = {}) {
|
|
|
2147
2293
|
if (id === VIRTUAL_AGENTS_ID) {
|
|
2148
2294
|
return RESOLVED_VIRTUAL_AGENTS_ID;
|
|
2149
2295
|
}
|
|
2296
|
+
if (id === VIRTUAL_EFFECTS_ID) {
|
|
2297
|
+
return RESOLVED_VIRTUAL_EFFECTS_ID;
|
|
2298
|
+
}
|
|
2299
|
+
if (id === VIRTUAL_PROVIDERS_ID) {
|
|
2300
|
+
return RESOLVED_VIRTUAL_PROVIDERS_ID;
|
|
2301
|
+
}
|
|
2150
2302
|
if (id === VIRTUAL_BUILDER_ID) {
|
|
2151
2303
|
return RESOLVED_VIRTUAL_BUILDER_ID;
|
|
2152
2304
|
}
|
|
@@ -2222,9 +2374,56 @@ function isPublicRoute(routePath) {
|
|
|
2222
2374
|
return true;
|
|
2223
2375
|
}
|
|
2224
2376
|
|
|
2377
|
+
// Provider icon routes are public (used by <img src>)
|
|
2378
|
+
if (routePath.startsWith('/api/providers/') && routePath.includes('/icon')) {
|
|
2379
|
+
return true;
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2225
2382
|
return false;
|
|
2226
2383
|
}
|
|
2227
2384
|
|
|
2385
|
+
// CORS headers for API responses
|
|
2386
|
+
const CORS_HEADERS = {
|
|
2387
|
+
"Access-Control-Allow-Origin": "*",
|
|
2388
|
+
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
|
|
2389
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
|
|
2390
|
+
"Access-Control-Max-Age": "86400",
|
|
2391
|
+
};
|
|
2392
|
+
|
|
2393
|
+
// Helper to create headers with CORS
|
|
2394
|
+
function corsHeaders(contentType) {
|
|
2395
|
+
return {
|
|
2396
|
+
"Content-Type": contentType,
|
|
2397
|
+
...CORS_HEADERS,
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
// Helper to add CORS headers to any Response without touching the body
|
|
2402
|
+
function addCorsHeaders(response) {
|
|
2403
|
+
// Skip WebSocket upgrade responses - they can't be wrapped
|
|
2404
|
+
if (response.status === 101) {
|
|
2405
|
+
return response;
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2408
|
+
// Skip if already has CORS headers
|
|
2409
|
+
if (response.headers.has("Access-Control-Allow-Origin")) {
|
|
2410
|
+
return response;
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
// Create new headers with CORS added
|
|
2414
|
+
const newHeaders = new Headers(response.headers);
|
|
2415
|
+
for (const [key, value] of Object.entries(CORS_HEADERS)) {
|
|
2416
|
+
newHeaders.set(key, value);
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
// Return new Response with same body stream (not cloned, just transferred)
|
|
2420
|
+
return new Response(response.body, {
|
|
2421
|
+
status: response.status,
|
|
2422
|
+
statusText: response.statusText,
|
|
2423
|
+
headers: newHeaders,
|
|
2424
|
+
});
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2228
2427
|
export async function router(request, env) {
|
|
2229
2428
|
const url = new URL(request.url);
|
|
2230
2429
|
const pathname = url.pathname;
|
|
@@ -2234,6 +2433,14 @@ export async function router(request, env) {
|
|
|
2234
2433
|
return null;
|
|
2235
2434
|
}
|
|
2236
2435
|
|
|
2436
|
+
// Handle CORS preflight requests
|
|
2437
|
+
if (request.method === "OPTIONS") {
|
|
2438
|
+
return new Response(null, {
|
|
2439
|
+
status: 204,
|
|
2440
|
+
headers: CORS_HEADERS,
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2237
2444
|
// Strip mount point prefix for route matching, ensuring we keep the leading slash
|
|
2238
2445
|
let routePath = pathname.slice(MOUNT_POINT.length) || "/";
|
|
2239
2446
|
if (!routePath.startsWith('/')) {
|
|
@@ -2268,7 +2475,7 @@ ${threadRouteCode}
|
|
|
2268
2475
|
|
|
2269
2476
|
// If requireAuth returns a Response, it's an error (401)
|
|
2270
2477
|
if (authResult instanceof Response) {
|
|
2271
|
-
return authResult;
|
|
2478
|
+
return addCorsHeaders(authResult);
|
|
2272
2479
|
}
|
|
2273
2480
|
|
|
2274
2481
|
authContext = authResult;
|
|
@@ -2287,16 +2494,17 @@ ${threadRouteCode}
|
|
|
2287
2494
|
const result = await controller(context);
|
|
2288
2495
|
|
|
2289
2496
|
if (result instanceof Response) {
|
|
2290
|
-
return result;
|
|
2497
|
+
return addCorsHeaders(result);
|
|
2291
2498
|
}
|
|
2292
2499
|
if (typeof result === "string") {
|
|
2293
2500
|
return new Response(result, {
|
|
2294
|
-
headers:
|
|
2295
|
-
"Content-Type": "text/plain",
|
|
2296
|
-
},
|
|
2501
|
+
headers: corsHeaders("text/plain"),
|
|
2297
2502
|
});
|
|
2298
2503
|
}
|
|
2299
|
-
|
|
2504
|
+
// JSON responses get CORS headers
|
|
2505
|
+
return new Response(JSON.stringify(result), {
|
|
2506
|
+
headers: corsHeaders("application/json"),
|
|
2507
|
+
});
|
|
2300
2508
|
}
|
|
2301
2509
|
|
|
2302
2510
|
// Serve UI for all other routes (SPA fallback)
|
|
@@ -2311,13 +2519,15 @@ async function serveUI(pathname, env) {
|
|
|
2311
2519
|
// Create a proper request for the asset path
|
|
2312
2520
|
// Use a dummy origin since we only care about the path
|
|
2313
2521
|
// Re-add mount point since pathname was stripped by router
|
|
2314
|
-
|
|
2522
|
+
// Handle root mountPoint "/" specially to avoid double slashes
|
|
2523
|
+
const mountPrefix = MOUNT_POINT === "/" ? "" : MOUNT_POINT;
|
|
2524
|
+
const assetUrl = \`http://localhost\${mountPrefix}\${pathname}\`;
|
|
2315
2525
|
let response = await env.ASSETS.fetch(assetUrl);
|
|
2316
2526
|
|
|
2317
2527
|
// If not found, fall back to index.html for SPA routing
|
|
2318
2528
|
const isIndexHtml = response.status === 404 || pathname === "/" || !pathname.includes(".");
|
|
2319
2529
|
if (isIndexHtml) {
|
|
2320
|
-
response = await env.ASSETS.fetch(\`http://localhost\${
|
|
2530
|
+
response = await env.ASSETS.fetch(\`http://localhost\${mountPrefix}/index.html\`);
|
|
2321
2531
|
|
|
2322
2532
|
// Transform HTML to use configured mount point
|
|
2323
2533
|
if (response.status === 200) {
|
|
@@ -2464,6 +2674,55 @@ ${agentsCode}
|
|
|
2464
2674
|
};
|
|
2465
2675
|
|
|
2466
2676
|
export const agentNames = ${JSON.stringify(agents.filter((a) => !a.error).map((a) => a.name))};
|
|
2677
|
+
`;
|
|
2678
|
+
}
|
|
2679
|
+
if (id === RESOLVED_VIRTUAL_EFFECTS_ID) {
|
|
2680
|
+
const effects = await scanEffectsDirectory(effectsDir);
|
|
2681
|
+
const effectsCode = effects.map(({ name, importPath, error }) => {
|
|
2682
|
+
if (error) {
|
|
2683
|
+
const escapedError = error.replace(/"/g, '\\"').replace(/\n/g, "\\n");
|
|
2684
|
+
return ` "${name}": async () => { throw new Error("${escapedError}"); },`;
|
|
2685
|
+
} else {
|
|
2686
|
+
return ` "${name}": async () => {
|
|
2687
|
+
try {
|
|
2688
|
+
return (await import("${importPath}")).default;
|
|
2689
|
+
} catch (error) {
|
|
2690
|
+
console.error('Failed to import effect ${name}:', error);
|
|
2691
|
+
throw error;
|
|
2692
|
+
}
|
|
2693
|
+
},`;
|
|
2694
|
+
}
|
|
2695
|
+
}).join("\n");
|
|
2696
|
+
return `// Virtual agent effects module
|
|
2697
|
+
export const effects = {
|
|
2698
|
+
${effectsCode}
|
|
2699
|
+
};
|
|
2700
|
+
|
|
2701
|
+
export const effectNames = ${JSON.stringify(effects.filter((e) => !e.error).map((e) => e.name))};
|
|
2702
|
+
`;
|
|
2703
|
+
}
|
|
2704
|
+
if (id === RESOLVED_VIRTUAL_PROVIDERS_ID) {
|
|
2705
|
+
const firstPartyProviders = [
|
|
2706
|
+
{ name: "openai", package: "@standardagents/openai", label: "OpenAI", envKey: "OPENAI_API_KEY" },
|
|
2707
|
+
{ name: "openrouter", package: "@standardagents/openrouter", label: "OpenRouter", envKey: "OPENROUTER_API_KEY" }
|
|
2708
|
+
];
|
|
2709
|
+
const customProviders = (options.providers || []).map((pkg) => ({
|
|
2710
|
+
name: pkg.split("/").pop() || pkg,
|
|
2711
|
+
package: pkg,
|
|
2712
|
+
label: pkg.split("/").pop() || pkg,
|
|
2713
|
+
envKey: `${(pkg.split("/").pop() || pkg).toUpperCase().replace(/-/g, "_")}_API_KEY`,
|
|
2714
|
+
isCustom: true
|
|
2715
|
+
}));
|
|
2716
|
+
const allProviders = [...firstPartyProviders, ...customProviders];
|
|
2717
|
+
return `// Virtual providers module - lists available LLM provider packages
|
|
2718
|
+
export const providers = ${JSON.stringify(allProviders, null, 2)};
|
|
2719
|
+
|
|
2720
|
+
export const providerNames = ${JSON.stringify(allProviders.map((p) => p.name))};
|
|
2721
|
+
|
|
2722
|
+
// Provider factories - dynamic imports for code splitting
|
|
2723
|
+
export const providerFactories = {
|
|
2724
|
+
${allProviders.map((p) => ` "${p.name}": async () => (await import("${p.package}")).${p.name},`).join("\n")}
|
|
2725
|
+
};
|
|
2467
2726
|
`;
|
|
2468
2727
|
}
|
|
2469
2728
|
if (id === RESOLVED_VIRTUAL_BUILDER_ID) {
|
|
@@ -2472,6 +2731,7 @@ export const agentNames = ${JSON.stringify(agents.filter((a) => !a.error).map((a
|
|
|
2472
2731
|
const models = await scanModelsDirectory(modelsDir);
|
|
2473
2732
|
const prompts = await scanPromptsDirectory(promptsDir);
|
|
2474
2733
|
const agents = await scanAgentsDirectory(agentsDir);
|
|
2734
|
+
const effects = await scanEffectsDirectory(effectsDir);
|
|
2475
2735
|
const toAbsolutePath = (relativePath) => {
|
|
2476
2736
|
if (relativePath.startsWith("./")) {
|
|
2477
2737
|
return path3.resolve(process.cwd(), relativePath).replace(/\\/g, "/");
|
|
@@ -2550,6 +2810,22 @@ export const agentNames = ${JSON.stringify(agents.filter((a) => !a.error).map((a
|
|
|
2550
2810
|
console.error('Failed to import agent ${name}:', error);
|
|
2551
2811
|
throw error;
|
|
2552
2812
|
}
|
|
2813
|
+
},`;
|
|
2814
|
+
}
|
|
2815
|
+
}).join("\n");
|
|
2816
|
+
const effectsCode = effects.map(({ name, importPath, error }) => {
|
|
2817
|
+
const absPath = toAbsolutePath(importPath);
|
|
2818
|
+
if (error) {
|
|
2819
|
+
const escapedError = error.replace(/"/g, '\\"').replace(/\n/g, "\\n");
|
|
2820
|
+
return ` "${name}": async () => { throw new Error("${escapedError}"); },`;
|
|
2821
|
+
} else {
|
|
2822
|
+
return ` "${name}": async () => {
|
|
2823
|
+
try {
|
|
2824
|
+
return (await import("${absPath}")).default;
|
|
2825
|
+
} catch (error) {
|
|
2826
|
+
console.error('Failed to import effect ${name}:', error);
|
|
2827
|
+
throw error;
|
|
2828
|
+
}
|
|
2553
2829
|
},`;
|
|
2554
2830
|
}
|
|
2555
2831
|
}).join("\n");
|
|
@@ -2560,7 +2836,8 @@ import { DurableAgentBuilder as _BaseDurableAgentBuilder } from '@standardagents
|
|
|
2560
2836
|
|
|
2561
2837
|
// Import sip WASM module and initializer
|
|
2562
2838
|
// Static import allows workerd to pre-compile the WASM at bundle time
|
|
2563
|
-
|
|
2839
|
+
// WASM is bundled in builder's dist to avoid transitive dependency resolution issues
|
|
2840
|
+
import _sipWasm from '@standardagents/builder/dist/sip.wasm';
|
|
2564
2841
|
import { initWithWasmModule as _initSipWasm } from '@standardagents/sip';
|
|
2565
2842
|
|
|
2566
2843
|
// Re-export router from virtual:@standardagents-routes
|
|
@@ -2587,6 +2864,10 @@ const _agents = {
|
|
|
2587
2864
|
${agentsCode}
|
|
2588
2865
|
};
|
|
2589
2866
|
|
|
2867
|
+
const _effects = {
|
|
2868
|
+
${effectsCode}
|
|
2869
|
+
};
|
|
2870
|
+
|
|
2590
2871
|
/**
|
|
2591
2872
|
* DurableThread with all virtual module methods already implemented.
|
|
2592
2873
|
* Simply extend this class in your agents/Thread.ts file.
|
|
@@ -2621,6 +2902,10 @@ export class DurableThread extends _BaseDurableThread {
|
|
|
2621
2902
|
agents() {
|
|
2622
2903
|
return _agents;
|
|
2623
2904
|
}
|
|
2905
|
+
|
|
2906
|
+
effects() {
|
|
2907
|
+
return _effects;
|
|
2908
|
+
}
|
|
2624
2909
|
}
|
|
2625
2910
|
|
|
2626
2911
|
/**
|
|
@@ -2647,6 +2932,10 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
2647
2932
|
agents() {
|
|
2648
2933
|
return _agents;
|
|
2649
2934
|
}
|
|
2935
|
+
|
|
2936
|
+
effects() {
|
|
2937
|
+
return _effects;
|
|
2938
|
+
}
|
|
2650
2939
|
}
|
|
2651
2940
|
`;
|
|
2652
2941
|
}
|
|
@@ -2659,6 +2948,7 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
2659
2948
|
this.addWatchFile(modelsDir);
|
|
2660
2949
|
this.addWatchFile(promptsDir);
|
|
2661
2950
|
this.addWatchFile(agentsDir);
|
|
2951
|
+
this.addWatchFile(effectsDir);
|
|
2662
2952
|
},
|
|
2663
2953
|
configureServer(server) {
|
|
2664
2954
|
server.watcher.on("add", async (file) => {
|
|
@@ -2686,51 +2976,26 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
2686
2976
|
try {
|
|
2687
2977
|
const filePath = path3.join(modelsDir, file);
|
|
2688
2978
|
const content = fs4.readFileSync(filePath, "utf-8");
|
|
2689
|
-
const
|
|
2690
|
-
|
|
2691
|
-
const
|
|
2692
|
-
const getInputPrice = (c) => {
|
|
2693
|
-
const match = c.match(/inputPrice:\s*([\d.]+)/);
|
|
2694
|
-
return match ? parseFloat(match[1]) : void 0;
|
|
2695
|
-
};
|
|
2696
|
-
const getOutputPrice = (c) => {
|
|
2697
|
-
const match = c.match(/outputPrice:\s*([\d.]+)/);
|
|
2698
|
-
return match ? parseFloat(match[1]) : void 0;
|
|
2699
|
-
};
|
|
2700
|
-
const getCachedPrice = (c) => {
|
|
2701
|
-
const match = c.match(/cachedPrice:\s*([\d.]+)/);
|
|
2702
|
-
return match ? parseFloat(match[1]) : void 0;
|
|
2703
|
-
};
|
|
2704
|
-
const getIncludedProviders = (c) => {
|
|
2705
|
-
const match = c.match(/includedProviders:\s*\[([^\]]*)\]/);
|
|
2706
|
-
if (!match) return void 0;
|
|
2707
|
-
const items = match[1].match(/['"]([^'"]+)['"]/g);
|
|
2708
|
-
return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
|
|
2709
|
-
};
|
|
2710
|
-
const getFallbacks = (c) => {
|
|
2711
|
-
const match = c.match(/fallbacks:\s*\[([^\]]*)\]/);
|
|
2712
|
-
if (!match) return [];
|
|
2713
|
-
const items = match[1].match(/['"]([^'"]+)['"]/g);
|
|
2714
|
-
return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
|
|
2715
|
-
};
|
|
2716
|
-
const name = getName(content);
|
|
2717
|
-
if (!name) return null;
|
|
2718
|
-
const fallbacks = getFallbacks(content);
|
|
2719
|
-
const fallbackObjects = fallbacks.map((fallbackName, index) => ({
|
|
2979
|
+
const parsed = parseModelFile(content);
|
|
2980
|
+
if (!parsed || !parsed.name) return null;
|
|
2981
|
+
const fallbackObjects = parsed.fallbacks.map((fallbackName, index) => ({
|
|
2720
2982
|
id: fallbackName,
|
|
2721
2983
|
name: fallbackName,
|
|
2722
2984
|
order: index
|
|
2723
2985
|
}));
|
|
2724
2986
|
return {
|
|
2725
|
-
id: name,
|
|
2726
|
-
name,
|
|
2727
|
-
provider:
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2987
|
+
id: parsed.name,
|
|
2988
|
+
name: parsed.name,
|
|
2989
|
+
provider: parsed.provider,
|
|
2990
|
+
provider_id: parsed.provider,
|
|
2991
|
+
model: parsed.model,
|
|
2992
|
+
input_price: parsed.inputPrice,
|
|
2993
|
+
output_price: parsed.outputPrice,
|
|
2994
|
+
cached_price: parsed.cachedPrice,
|
|
2995
|
+
included_providers: parsed.includedProviders,
|
|
2733
2996
|
fallbacks: fallbackObjects,
|
|
2997
|
+
providerTools: parsed.providerTools,
|
|
2998
|
+
capabilities: parsed.capabilities,
|
|
2734
2999
|
created_at: Math.floor(Date.now() / 1e3)
|
|
2735
3000
|
};
|
|
2736
3001
|
} catch (error) {
|
|
@@ -2896,27 +3161,19 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
2896
3161
|
try {
|
|
2897
3162
|
const filePath = path3.join(promptsDir, file);
|
|
2898
3163
|
const content = fs4.readFileSync(filePath, "utf-8");
|
|
2899
|
-
const
|
|
3164
|
+
const getName2 = (c) => c.match(/name:\s*['"]([^'"]+)['"]/)?.[1];
|
|
2900
3165
|
const getToolDescription = (c) => c.match(/toolDescription:\s*['"]([^'"]+)['"]/)?.[1];
|
|
2901
|
-
const
|
|
3166
|
+
const getModel2 = (c) => c.match(/model:\s*['"]([^'"]+)['"]/)?.[1];
|
|
2902
3167
|
const getIncludeChat = (c) => c.match(/includeChat:\s*(true|false)/)?.[1] === "true";
|
|
2903
3168
|
const getIncludePastTools = (c) => c.match(/includePastTools:\s*(true|false)/)?.[1] === "true";
|
|
2904
3169
|
const getParallelToolCalls = (c) => c.match(/parallelToolCalls:\s*(true|false)/)?.[1] === "true";
|
|
2905
3170
|
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
3171
|
const getTools = (c) => {
|
|
2909
3172
|
const match = c.match(/tools:\s*\[([^\]]*)\]/);
|
|
2910
3173
|
if (!match) return [];
|
|
2911
3174
|
const items = match[1].match(/['"]([^'"]+)['"]/g);
|
|
2912
3175
|
return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
|
|
2913
3176
|
};
|
|
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
3177
|
const getPrompt = (c) => {
|
|
2921
3178
|
const backtickMatch = c.match(/prompt:\s*`([\s\S]*?)`/);
|
|
2922
3179
|
if (backtickMatch) return backtickMatch[1];
|
|
@@ -2926,9 +3183,9 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
2926
3183
|
if (arrayMatch) return arrayMatch[1];
|
|
2927
3184
|
return "";
|
|
2928
3185
|
};
|
|
2929
|
-
const name =
|
|
3186
|
+
const name = getName2(content);
|
|
2930
3187
|
if (!name) return null;
|
|
2931
|
-
const modelId =
|
|
3188
|
+
const modelId = getModel2(content);
|
|
2932
3189
|
const modelDef = modelId ? modelMap[modelId] : null;
|
|
2933
3190
|
return {
|
|
2934
3191
|
id: name,
|
|
@@ -2944,10 +3201,7 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
2944
3201
|
include_past_tools: getIncludePastTools(content),
|
|
2945
3202
|
parallel_tool_calls: getParallelToolCalls(content),
|
|
2946
3203
|
tool_choice: getToolChoice(content) || "auto",
|
|
2947
|
-
before_tool: getBeforeTool(content) || null,
|
|
2948
|
-
after_tool: getAfterTool(content) || null,
|
|
2949
3204
|
tools: getTools(content),
|
|
2950
|
-
prompts: getHandoffAgents(content),
|
|
2951
3205
|
reasoning: null,
|
|
2952
3206
|
// Complex to parse
|
|
2953
3207
|
created_at: Math.floor(Date.now() / 1e3)
|
|
@@ -3102,7 +3356,7 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
3102
3356
|
try {
|
|
3103
3357
|
const filePath = path3.join(agentsDir, file);
|
|
3104
3358
|
const content = fs4.readFileSync(filePath, "utf-8");
|
|
3105
|
-
const
|
|
3359
|
+
const getName2 = (c) => c.match(/name:\s*['"]([^'"]+)['"]/)?.[1];
|
|
3106
3360
|
const getTitle = (c) => c.match(/title:\s*['"]([^'"]+)['"]/)?.[1];
|
|
3107
3361
|
const getType = (c) => c.match(/type:\s*['"]([^'"]+)['"]/)?.[1];
|
|
3108
3362
|
const getDefaultPrompt = (c) => c.match(/defaultPrompt:\s*['"]([^'"]+)['"]/)?.[1];
|
|
@@ -3113,7 +3367,14 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
3113
3367
|
const items = match[1].match(/['"]([^'"]+)['"]/g);
|
|
3114
3368
|
return items ? items.map((s) => s.replace(/['"]/g, "")) : [];
|
|
3115
3369
|
};
|
|
3116
|
-
const
|
|
3370
|
+
const getSidePrompt = (c, side) => {
|
|
3371
|
+
const sideRegex = new RegExp(`${side}:\\s*\\{([^}]+)\\}`, "s");
|
|
3372
|
+
const sideMatch = c.match(sideRegex);
|
|
3373
|
+
if (!sideMatch) return null;
|
|
3374
|
+
const promptMatch = sideMatch[1].match(/prompt:\s*['"]([^'"]+)['"]/);
|
|
3375
|
+
return promptMatch ? promptMatch[1] : null;
|
|
3376
|
+
};
|
|
3377
|
+
const name = getName2(content);
|
|
3117
3378
|
if (!name) return null;
|
|
3118
3379
|
return {
|
|
3119
3380
|
id: name,
|
|
@@ -3123,6 +3384,8 @@ export class DurableAgentBuilder extends _BaseDurableAgentBuilder {
|
|
|
3123
3384
|
default_prompt: getDefaultPrompt(content) || "",
|
|
3124
3385
|
default_model: getDefaultModel(content) || "",
|
|
3125
3386
|
tools: getTools(content),
|
|
3387
|
+
side_a_agent_prompt: getSidePrompt(content, "sideA"),
|
|
3388
|
+
side_b_agent_prompt: getSidePrompt(content, "sideB"),
|
|
3126
3389
|
created_at: Math.floor(Date.now() / 1e3)
|
|
3127
3390
|
};
|
|
3128
3391
|
} catch (error) {
|