@electric-ax/agents 0.4.5 → 0.4.8
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/entrypoint.js +42 -8
- package/dist/index.cjs +43 -8
- package/dist/index.d.cts +14 -69
- package/dist/index.d.ts +14 -69
- package/dist/index.js +43 -9
- package/package.json +2 -2
package/dist/entrypoint.js
CHANGED
|
@@ -4,6 +4,7 @@ import fs from "node:fs";
|
|
|
4
4
|
import pino from "pino";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { appendPathToUrl, completeWithLowCostModel, createEntityRegistry, createPullWakeRunner, createRuntimeHandler, createSkillTools, createSkillsRegistry, db, detectAvailableProviders, readCodexAccessToken, registerToolProvider, unregisterToolProvider } from "@electric-ax/agents-runtime";
|
|
7
|
+
import { braveSearchTool, createBashTool, createEditTool, createEventSourceTools, createFetchUrlTool, createReadFileTool, createSendTool, createWriteTool, fetchUrlTool } from "@electric-ax/agents-runtime/tools";
|
|
7
8
|
import { eq, not, queryOnce } from "@durable-streams/state";
|
|
8
9
|
import { z } from "zod";
|
|
9
10
|
import { createHash } from "node:crypto";
|
|
@@ -13,7 +14,6 @@ import { Type } from "@sinclair/typebox";
|
|
|
13
14
|
import { load } from "sqlite-vec";
|
|
14
15
|
import { nanoid } from "nanoid";
|
|
15
16
|
import { getModels } from "@mariozechner/pi-ai";
|
|
16
|
-
import { braveSearchTool, createBashTool, createEditTool, createFetchUrlTool, createReadFileTool, createSendTool, createWriteTool, fetchUrlTool } from "@electric-ax/agents-runtime/tools";
|
|
17
17
|
import { bridgeMcpTool, buildPromptTools, buildResourceTools, createRegistry, keychainPersistence, loadConfig, mcp, watchConfig } from "@electric-ax/agents-mcp";
|
|
18
18
|
|
|
19
19
|
//#region src/log.ts
|
|
@@ -785,12 +785,14 @@ const REASONING_EFFORT_VALUES = [
|
|
|
785
785
|
const DEFAULT_ANTHROPIC_MODEL = `claude-sonnet-4-6`;
|
|
786
786
|
const DEFAULT_OPENAI_MODEL = `gpt-4.1`;
|
|
787
787
|
const DEFAULT_CODEX_MODEL = `gpt-5.4`;
|
|
788
|
+
const DEFAULT_DEEPSEEK_MODEL = `deepseek-v4-flash`;
|
|
788
789
|
function modelValue(provider, id) {
|
|
789
790
|
return `${provider}:${id}`;
|
|
790
791
|
}
|
|
791
792
|
function providerLabel(provider) {
|
|
792
793
|
if (provider === `anthropic`) return `Anthropic`;
|
|
793
794
|
if (provider === `openai-codex`) return `OpenAI Codex`;
|
|
795
|
+
if (provider === `deepseek`) return `DeepSeek`;
|
|
794
796
|
return `OpenAI`;
|
|
795
797
|
}
|
|
796
798
|
function configuredProviders() {
|
|
@@ -817,6 +819,9 @@ async function fetchAvailableModelIds(provider) {
|
|
|
817
819
|
"anthropic-version": `2023-06-01`
|
|
818
820
|
},
|
|
819
821
|
signal: AbortSignal.timeout(3e3)
|
|
822
|
+
}) : provider === `deepseek` ? await fetch(`https://api.deepseek.com/v1/models`, {
|
|
823
|
+
headers: { authorization: `Bearer ${process.env.DEEPSEEK_API_KEY ?? ``}` },
|
|
824
|
+
signal: AbortSignal.timeout(3e3)
|
|
820
825
|
}) : await fetch(`https://api.openai.com/v1/models`, {
|
|
821
826
|
headers: { authorization: `Bearer ${process.env.OPENAI_API_KEY ?? ``}` },
|
|
822
827
|
signal: AbortSignal.timeout(3e3)
|
|
@@ -877,7 +882,7 @@ async function createBuiltinModelCatalog(options = {}) {
|
|
|
877
882
|
if (providers.length === 0 && options.allowMockFallback) return mockFallbackCatalog();
|
|
878
883
|
const choices = (await Promise.all(providers.map((provider) => choicesForProvider(provider)))).flat();
|
|
879
884
|
if (choices.length === 0) return options.allowMockFallback ? mockFallbackCatalog() : null;
|
|
880
|
-
const defaultChoice = choices.find((choice) => choice.provider === `anthropic` && choice.id === DEFAULT_ANTHROPIC_MODEL) ?? choices.find((choice) => choice.provider === `openai` && choice.id === DEFAULT_OPENAI_MODEL) ?? choices.find((choice) => choice.provider === `openai-codex` && choice.id === DEFAULT_CODEX_MODEL) ?? choices[0];
|
|
885
|
+
const defaultChoice = choices.find((choice) => choice.provider === `anthropic` && choice.id === DEFAULT_ANTHROPIC_MODEL) ?? choices.find((choice) => choice.provider === `openai` && choice.id === DEFAULT_OPENAI_MODEL) ?? choices.find((choice) => choice.provider === `openai-codex` && choice.id === DEFAULT_CODEX_MODEL) ?? choices.find((choice) => choice.provider === `deepseek` && choice.id === DEFAULT_DEEPSEEK_MODEL) ?? choices[0];
|
|
881
886
|
return {
|
|
882
887
|
choices,
|
|
883
888
|
defaultChoice
|
|
@@ -998,6 +1003,7 @@ async function generateTitle(userMessage, llmCall, onFallback) {
|
|
|
998
1003
|
}
|
|
999
1004
|
function buildHortonSystemPrompt(workingDirectory, opts = {}) {
|
|
1000
1005
|
const docsTools = opts.hasDocsSupport ? `\n- search_durable_agents_docs: hybrid search over the built-in Durable Agents docs index` : ``;
|
|
1006
|
+
const eventSourceTools = opts.hasEventSourceTools ? `\n- list_event_sources: list external webhook/event feeds you can subscribe to, including available buckets and parameters\n- subscribe_event_source: subscribe yourself to one of those feeds or buckets so matching future events wake you\n- list_event_source_subscriptions: list your active event source subscriptions\n- unsubscribe_event_source: remove one of your event source subscriptions by id` : ``;
|
|
1001
1007
|
const skillsTools = opts.hasSkills ? `\n- use_skill: load a skill (knowledge, instructions, or a tutorial) into your context to help with the user's request\n- remove_skill: unload a skill from context when you're done with it` : ``;
|
|
1002
1008
|
const docsGuidance = opts.hasDocsSupport ? `\n- For ANY question about Electric Agents, Durable Agents, or this framework, ALWAYS use search_durable_agents_docs FIRST. Do not use web_search or fetch_url for Electric Agents topics unless the docs search returns no useful results.\n- The search tool returns chunk content directly — you do not need to read the source files.\n- Use repo read/bash tools only for non-doc files or when you need to inspect exact implementation code in the workspace.` : ``;
|
|
1003
1009
|
const skillsGuidance = opts.hasSkills ? `\n# Skills\nYou have access to skills — specialized knowledge and guided workflows you can load on demand. Your context includes a skills catalog listing what's available. When the user's request matches a skill's description or keywords, load it with use_skill.
|
|
@@ -1051,8 +1057,8 @@ When a user opens with a greeting ("hi", "hello", "hey", etc.) or a broad statem
|
|
|
1051
1057
|
- web_search: search the web
|
|
1052
1058
|
- fetch_url: fetch and convert a URL to markdown
|
|
1053
1059
|
- spawn_worker: dispatch a subagent for an isolated task
|
|
1054
|
-
- send: send a message to an Electric Agent/entity
|
|
1055
|
-
${docsTools}${skillsTools}
|
|
1060
|
+
- send: send a message to an Electric Agent/entity. To schedule future work for yourself, call send with self: true and afterMs.
|
|
1061
|
+
${eventSourceTools}${docsTools}${skillsTools}
|
|
1056
1062
|
|
|
1057
1063
|
# Working with files
|
|
1058
1064
|
- Prefer edit over write when modifying existing files.
|
|
@@ -1085,6 +1091,11 @@ Report outcomes faithfully. If a command failed, say so with the relevant output
|
|
|
1085
1091
|
Working directory: ${workingDirectory}
|
|
1086
1092
|
The current year is ${new Date().getFullYear()}.`;
|
|
1087
1093
|
}
|
|
1094
|
+
function getToolName(tool) {
|
|
1095
|
+
if (typeof tool !== `object` || tool === null) return null;
|
|
1096
|
+
const name = tool.name;
|
|
1097
|
+
return typeof name === `string` ? name : null;
|
|
1098
|
+
}
|
|
1088
1099
|
function createHortonTools(workingDirectory, ctx, readSet, opts = {}) {
|
|
1089
1100
|
return [
|
|
1090
1101
|
createBashTool(workingDirectory),
|
|
@@ -1099,7 +1110,7 @@ function createHortonTools(workingDirectory, ctx, readSet, opts = {}) {
|
|
|
1099
1110
|
logPrefix: opts.logPrefix ?? `[horton]`
|
|
1100
1111
|
})] : [fetchUrlTool],
|
|
1101
1112
|
createSpawnWorkerTool(ctx, opts.modelConfig),
|
|
1102
|
-
createSendTool(ctx.send),
|
|
1113
|
+
createSendTool(ctx.send, { selfEntityUrl: ctx.entityUrl }),
|
|
1103
1114
|
...opts.docsSearchTool ? [opts.docsSearchTool] : []
|
|
1104
1115
|
];
|
|
1105
1116
|
}
|
|
@@ -1151,6 +1162,7 @@ function createAssistantHandler(options) {
|
|
|
1151
1162
|
...skillsRegistry && skillsRegistry.catalog.size > 0 ? createSkillTools(skillsRegistry, ctx) : [],
|
|
1152
1163
|
...mcp.tools()
|
|
1153
1164
|
];
|
|
1165
|
+
const hasEventSourceTools = tools.some((tool) => getToolName(tool) === `list_event_sources`);
|
|
1154
1166
|
const titlePromise = ctx.firstWake && !ctx.tags.title ? (async () => {
|
|
1155
1167
|
const firstUserMessage = await extractFirstUserMessage(ctx);
|
|
1156
1168
|
if (!firstUserMessage) return;
|
|
@@ -1237,7 +1249,8 @@ function createAssistantHandler(options) {
|
|
|
1237
1249
|
hasSkills,
|
|
1238
1250
|
docsUrl,
|
|
1239
1251
|
modelProvider: modelConfig.provider,
|
|
1240
|
-
modelId: String(modelConfig.model)
|
|
1252
|
+
modelId: String(modelConfig.model),
|
|
1253
|
+
hasEventSourceTools
|
|
1241
1254
|
}),
|
|
1242
1255
|
...modelConfig,
|
|
1243
1256
|
tools,
|
|
@@ -1349,7 +1362,7 @@ function buildToolsForWorker(tools, workingDirectory, ctx, readSet) {
|
|
|
1349
1362
|
out.push(createSpawnWorkerTool(ctx));
|
|
1350
1363
|
break;
|
|
1351
1364
|
case `send`:
|
|
1352
|
-
out.push(createSendTool(ctx.send));
|
|
1365
|
+
out.push(createSendTool(ctx.send, { selfEntityUrl: ctx.entityUrl }));
|
|
1353
1366
|
break;
|
|
1354
1367
|
}
|
|
1355
1368
|
return out;
|
|
@@ -1477,6 +1490,27 @@ function registerWorker(registry, options) {
|
|
|
1477
1490
|
|
|
1478
1491
|
//#endregion
|
|
1479
1492
|
//#region src/bootstrap.ts
|
|
1493
|
+
function toolName(tool) {
|
|
1494
|
+
return typeof tool.name === `string` ? tool.name : null;
|
|
1495
|
+
}
|
|
1496
|
+
function dedupeToolsByName(tools) {
|
|
1497
|
+
const seen = new Set();
|
|
1498
|
+
const deduped = [];
|
|
1499
|
+
for (const tool of tools) {
|
|
1500
|
+
const name = toolName(tool);
|
|
1501
|
+
if (name && seen.has(name)) continue;
|
|
1502
|
+
if (name) seen.add(name);
|
|
1503
|
+
deduped.push(tool);
|
|
1504
|
+
}
|
|
1505
|
+
return deduped;
|
|
1506
|
+
}
|
|
1507
|
+
function createBuiltinElectricTools(custom) {
|
|
1508
|
+
return async (context) => {
|
|
1509
|
+
const builtinTools = createEventSourceTools(context);
|
|
1510
|
+
const customTools = custom ? await custom(context) : [];
|
|
1511
|
+
return dedupeToolsByName([...builtinTools, ...customTools]);
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1480
1514
|
async function createBuiltinAgentHandler(options) {
|
|
1481
1515
|
const { agentServerUrl, serveEndpoint, workingDirectory, streamFn, createElectricTools, publicUrl, runtimeName, baseSkillsDir: baseSkillsDirOverride, serverHeaders, defaultDispatchPolicyForType } = options;
|
|
1482
1516
|
const modelCatalog = await createBuiltinModelCatalog({ allowMockFallback: Boolean(streamFn) });
|
|
@@ -1519,7 +1553,7 @@ async function createBuiltinAgentHandler(options) {
|
|
|
1519
1553
|
defaultDispatchPolicyForType,
|
|
1520
1554
|
serverHeaders,
|
|
1521
1555
|
idleTimeout: 5 * 6e4,
|
|
1522
|
-
createElectricTools,
|
|
1556
|
+
createElectricTools: createBuiltinElectricTools(createElectricTools),
|
|
1523
1557
|
publicUrl,
|
|
1524
1558
|
name: runtimeName ?? `builtin-agents`
|
|
1525
1559
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ const require_server_headers = require('./server-headers-65vIhxvJ.cjs');
|
|
|
26
26
|
const node_path = __toESM(require("node:path"));
|
|
27
27
|
const node_url = __toESM(require("node:url"));
|
|
28
28
|
const __electric_ax_agents_runtime = __toESM(require("@electric-ax/agents-runtime"));
|
|
29
|
+
const __electric_ax_agents_runtime_tools = __toESM(require("@electric-ax/agents-runtime/tools"));
|
|
29
30
|
const node_fs = __toESM(require("node:fs"));
|
|
30
31
|
const pino = __toESM(require("pino"));
|
|
31
32
|
const __durable_streams_state = __toESM(require("@durable-streams/state"));
|
|
@@ -37,7 +38,6 @@ const __sinclair_typebox = __toESM(require("@sinclair/typebox"));
|
|
|
37
38
|
const sqlite_vec = __toESM(require("sqlite-vec"));
|
|
38
39
|
const nanoid = __toESM(require("nanoid"));
|
|
39
40
|
const __mariozechner_pi_ai = __toESM(require("@mariozechner/pi-ai"));
|
|
40
|
-
const __electric_ax_agents_runtime_tools = __toESM(require("@electric-ax/agents-runtime/tools"));
|
|
41
41
|
const __electric_ax_agents_mcp = __toESM(require("@electric-ax/agents-mcp"));
|
|
42
42
|
|
|
43
43
|
//#region src/log.ts
|
|
@@ -809,12 +809,14 @@ const REASONING_EFFORT_VALUES = [
|
|
|
809
809
|
const DEFAULT_ANTHROPIC_MODEL = `claude-sonnet-4-6`;
|
|
810
810
|
const DEFAULT_OPENAI_MODEL = `gpt-4.1`;
|
|
811
811
|
const DEFAULT_CODEX_MODEL = `gpt-5.4`;
|
|
812
|
+
const DEFAULT_DEEPSEEK_MODEL = `deepseek-v4-flash`;
|
|
812
813
|
function modelValue(provider, id) {
|
|
813
814
|
return `${provider}:${id}`;
|
|
814
815
|
}
|
|
815
816
|
function providerLabel(provider) {
|
|
816
817
|
if (provider === `anthropic`) return `Anthropic`;
|
|
817
818
|
if (provider === `openai-codex`) return `OpenAI Codex`;
|
|
819
|
+
if (provider === `deepseek`) return `DeepSeek`;
|
|
818
820
|
return `OpenAI`;
|
|
819
821
|
}
|
|
820
822
|
function configuredProviders() {
|
|
@@ -841,6 +843,9 @@ async function fetchAvailableModelIds(provider) {
|
|
|
841
843
|
"anthropic-version": `2023-06-01`
|
|
842
844
|
},
|
|
843
845
|
signal: AbortSignal.timeout(3e3)
|
|
846
|
+
}) : provider === `deepseek` ? await fetch(`https://api.deepseek.com/v1/models`, {
|
|
847
|
+
headers: { authorization: `Bearer ${process.env.DEEPSEEK_API_KEY ?? ``}` },
|
|
848
|
+
signal: AbortSignal.timeout(3e3)
|
|
844
849
|
}) : await fetch(`https://api.openai.com/v1/models`, {
|
|
845
850
|
headers: { authorization: `Bearer ${process.env.OPENAI_API_KEY ?? ``}` },
|
|
846
851
|
signal: AbortSignal.timeout(3e3)
|
|
@@ -901,7 +906,7 @@ async function createBuiltinModelCatalog(options = {}) {
|
|
|
901
906
|
if (providers.length === 0 && options.allowMockFallback) return mockFallbackCatalog();
|
|
902
907
|
const choices = (await Promise.all(providers.map((provider) => choicesForProvider(provider)))).flat();
|
|
903
908
|
if (choices.length === 0) return options.allowMockFallback ? mockFallbackCatalog() : null;
|
|
904
|
-
const defaultChoice = choices.find((choice) => choice.provider === `anthropic` && choice.id === DEFAULT_ANTHROPIC_MODEL) ?? choices.find((choice) => choice.provider === `openai` && choice.id === DEFAULT_OPENAI_MODEL) ?? choices.find((choice) => choice.provider === `openai-codex` && choice.id === DEFAULT_CODEX_MODEL) ?? choices[0];
|
|
909
|
+
const defaultChoice = choices.find((choice) => choice.provider === `anthropic` && choice.id === DEFAULT_ANTHROPIC_MODEL) ?? choices.find((choice) => choice.provider === `openai` && choice.id === DEFAULT_OPENAI_MODEL) ?? choices.find((choice) => choice.provider === `openai-codex` && choice.id === DEFAULT_CODEX_MODEL) ?? choices.find((choice) => choice.provider === `deepseek` && choice.id === DEFAULT_DEEPSEEK_MODEL) ?? choices[0];
|
|
905
910
|
return {
|
|
906
911
|
choices,
|
|
907
912
|
defaultChoice
|
|
@@ -1023,6 +1028,7 @@ async function generateTitle(userMessage, llmCall, onFallback) {
|
|
|
1023
1028
|
}
|
|
1024
1029
|
function buildHortonSystemPrompt(workingDirectory, opts = {}) {
|
|
1025
1030
|
const docsTools = opts.hasDocsSupport ? `\n- search_durable_agents_docs: hybrid search over the built-in Durable Agents docs index` : ``;
|
|
1031
|
+
const eventSourceTools = opts.hasEventSourceTools ? `\n- list_event_sources: list external webhook/event feeds you can subscribe to, including available buckets and parameters\n- subscribe_event_source: subscribe yourself to one of those feeds or buckets so matching future events wake you\n- list_event_source_subscriptions: list your active event source subscriptions\n- unsubscribe_event_source: remove one of your event source subscriptions by id` : ``;
|
|
1026
1032
|
const skillsTools = opts.hasSkills ? `\n- use_skill: load a skill (knowledge, instructions, or a tutorial) into your context to help with the user's request\n- remove_skill: unload a skill from context when you're done with it` : ``;
|
|
1027
1033
|
const docsGuidance = opts.hasDocsSupport ? `\n- For ANY question about Electric Agents, Durable Agents, or this framework, ALWAYS use search_durable_agents_docs FIRST. Do not use web_search or fetch_url for Electric Agents topics unless the docs search returns no useful results.\n- The search tool returns chunk content directly — you do not need to read the source files.\n- Use repo read/bash tools only for non-doc files or when you need to inspect exact implementation code in the workspace.` : ``;
|
|
1028
1034
|
const skillsGuidance = opts.hasSkills ? `\n# Skills\nYou have access to skills — specialized knowledge and guided workflows you can load on demand. Your context includes a skills catalog listing what's available. When the user's request matches a skill's description or keywords, load it with use_skill.
|
|
@@ -1076,8 +1082,8 @@ When a user opens with a greeting ("hi", "hello", "hey", etc.) or a broad statem
|
|
|
1076
1082
|
- web_search: search the web
|
|
1077
1083
|
- fetch_url: fetch and convert a URL to markdown
|
|
1078
1084
|
- spawn_worker: dispatch a subagent for an isolated task
|
|
1079
|
-
- send: send a message to an Electric Agent/entity
|
|
1080
|
-
${docsTools}${skillsTools}
|
|
1085
|
+
- send: send a message to an Electric Agent/entity. To schedule future work for yourself, call send with self: true and afterMs.
|
|
1086
|
+
${eventSourceTools}${docsTools}${skillsTools}
|
|
1081
1087
|
|
|
1082
1088
|
# Working with files
|
|
1083
1089
|
- Prefer edit over write when modifying existing files.
|
|
@@ -1110,6 +1116,11 @@ Report outcomes faithfully. If a command failed, say so with the relevant output
|
|
|
1110
1116
|
Working directory: ${workingDirectory}
|
|
1111
1117
|
The current year is ${new Date().getFullYear()}.`;
|
|
1112
1118
|
}
|
|
1119
|
+
function getToolName(tool) {
|
|
1120
|
+
if (typeof tool !== `object` || tool === null) return null;
|
|
1121
|
+
const name = tool.name;
|
|
1122
|
+
return typeof name === `string` ? name : null;
|
|
1123
|
+
}
|
|
1113
1124
|
function createHortonTools(workingDirectory, ctx, readSet, opts = {}) {
|
|
1114
1125
|
return [
|
|
1115
1126
|
(0, __electric_ax_agents_runtime_tools.createBashTool)(workingDirectory),
|
|
@@ -1124,7 +1135,7 @@ function createHortonTools(workingDirectory, ctx, readSet, opts = {}) {
|
|
|
1124
1135
|
logPrefix: opts.logPrefix ?? `[horton]`
|
|
1125
1136
|
})] : [__electric_ax_agents_runtime_tools.fetchUrlTool],
|
|
1126
1137
|
createSpawnWorkerTool(ctx, opts.modelConfig),
|
|
1127
|
-
(0, __electric_ax_agents_runtime_tools.createSendTool)(ctx.send),
|
|
1138
|
+
(0, __electric_ax_agents_runtime_tools.createSendTool)(ctx.send, { selfEntityUrl: ctx.entityUrl }),
|
|
1128
1139
|
...opts.docsSearchTool ? [opts.docsSearchTool] : []
|
|
1129
1140
|
];
|
|
1130
1141
|
}
|
|
@@ -1176,6 +1187,7 @@ function createAssistantHandler(options) {
|
|
|
1176
1187
|
...skillsRegistry && skillsRegistry.catalog.size > 0 ? (0, __electric_ax_agents_runtime.createSkillTools)(skillsRegistry, ctx) : [],
|
|
1177
1188
|
...__electric_ax_agents_mcp.mcp.tools()
|
|
1178
1189
|
];
|
|
1190
|
+
const hasEventSourceTools = tools.some((tool) => getToolName(tool) === `list_event_sources`);
|
|
1179
1191
|
const titlePromise = ctx.firstWake && !ctx.tags.title ? (async () => {
|
|
1180
1192
|
const firstUserMessage = await extractFirstUserMessage(ctx);
|
|
1181
1193
|
if (!firstUserMessage) return;
|
|
@@ -1262,7 +1274,8 @@ function createAssistantHandler(options) {
|
|
|
1262
1274
|
hasSkills,
|
|
1263
1275
|
docsUrl,
|
|
1264
1276
|
modelProvider: modelConfig.provider,
|
|
1265
|
-
modelId: String(modelConfig.model)
|
|
1277
|
+
modelId: String(modelConfig.model),
|
|
1278
|
+
hasEventSourceTools
|
|
1266
1279
|
}),
|
|
1267
1280
|
...modelConfig,
|
|
1268
1281
|
tools,
|
|
@@ -1374,7 +1387,7 @@ function buildToolsForWorker(tools, workingDirectory, ctx, readSet) {
|
|
|
1374
1387
|
out.push(createSpawnWorkerTool(ctx));
|
|
1375
1388
|
break;
|
|
1376
1389
|
case `send`:
|
|
1377
|
-
out.push((0, __electric_ax_agents_runtime_tools.createSendTool)(ctx.send));
|
|
1390
|
+
out.push((0, __electric_ax_agents_runtime_tools.createSendTool)(ctx.send, { selfEntityUrl: ctx.entityUrl }));
|
|
1378
1391
|
break;
|
|
1379
1392
|
}
|
|
1380
1393
|
return out;
|
|
@@ -1503,6 +1516,27 @@ function registerWorker(registry, options) {
|
|
|
1503
1516
|
//#endregion
|
|
1504
1517
|
//#region src/bootstrap.ts
|
|
1505
1518
|
const DEFAULT_BUILTIN_AGENT_HANDLER_PATH = `/_electric/builtin-agent-handler`;
|
|
1519
|
+
function toolName(tool) {
|
|
1520
|
+
return typeof tool.name === `string` ? tool.name : null;
|
|
1521
|
+
}
|
|
1522
|
+
function dedupeToolsByName(tools) {
|
|
1523
|
+
const seen = new Set();
|
|
1524
|
+
const deduped = [];
|
|
1525
|
+
for (const tool of tools) {
|
|
1526
|
+
const name = toolName(tool);
|
|
1527
|
+
if (name && seen.has(name)) continue;
|
|
1528
|
+
if (name) seen.add(name);
|
|
1529
|
+
deduped.push(tool);
|
|
1530
|
+
}
|
|
1531
|
+
return deduped;
|
|
1532
|
+
}
|
|
1533
|
+
function createBuiltinElectricTools(custom) {
|
|
1534
|
+
return async (context) => {
|
|
1535
|
+
const builtinTools = (0, __electric_ax_agents_runtime_tools.createEventSourceTools)(context);
|
|
1536
|
+
const customTools = custom ? await custom(context) : [];
|
|
1537
|
+
return dedupeToolsByName([...builtinTools, ...customTools]);
|
|
1538
|
+
};
|
|
1539
|
+
}
|
|
1506
1540
|
async function createBuiltinAgentHandler(options) {
|
|
1507
1541
|
const { agentServerUrl, serveEndpoint, workingDirectory, streamFn, createElectricTools, publicUrl, runtimeName, baseSkillsDir: baseSkillsDirOverride, serverHeaders, defaultDispatchPolicyForType } = options;
|
|
1508
1542
|
const modelCatalog = await createBuiltinModelCatalog({ allowMockFallback: Boolean(streamFn) });
|
|
@@ -1545,7 +1579,7 @@ async function createBuiltinAgentHandler(options) {
|
|
|
1545
1579
|
defaultDispatchPolicyForType,
|
|
1546
1580
|
serverHeaders,
|
|
1547
1581
|
idleTimeout: 5 * 6e4,
|
|
1548
|
-
createElectricTools,
|
|
1582
|
+
createElectricTools: createBuiltinElectricTools(createElectricTools),
|
|
1549
1583
|
publicUrl,
|
|
1550
1584
|
name: runtimeName ?? `builtin-agents`
|
|
1551
1585
|
});
|
|
@@ -1887,6 +1921,7 @@ Object.defineProperty(exports, 'braveSearchTool', {
|
|
|
1887
1921
|
exports.buildHortonSystemPrompt = buildHortonSystemPrompt
|
|
1888
1922
|
exports.createAgentHandler = createAgentHandler
|
|
1889
1923
|
exports.createBuiltinAgentHandler = createBuiltinAgentHandler
|
|
1924
|
+
exports.createBuiltinElectricTools = createBuiltinElectricTools
|
|
1890
1925
|
exports.createHortonDocsSupport = createHortonDocsSupport
|
|
1891
1926
|
exports.createHortonTools = createHortonTools
|
|
1892
1927
|
exports.createSpawnWorkerTool = createSpawnWorkerTool
|
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AgentConfig, AgentTool, AvailableProvider, DispatchPolicy, EntityRegistry,
|
|
2
|
-
import { ChangeEvent } from "@durable-streams/state";
|
|
1
|
+
import { AgentConfig, AgentTool, AvailableProvider, DispatchPolicy, EntityRegistry, HandlerContext, HeadersProvider, ProcessWakeConfig, PullWakeRunnerConfig, RuntimeHandler, SkillsRegistry, WakeEvent } from "@electric-ax/agents-runtime";
|
|
3
2
|
import { AgentTool as AgentTool$1, StreamFn } from "@mariozechner/pi-agent-core";
|
|
4
3
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
5
4
|
import { ListedEntry as McpListedEntry, McpConfig, McpServerConfig, McpServerConfig as McpServerConfig$1, Registry, Registry as McpRegistry, RegistrySnapshot, RegistrySubscriber } from "@electric-ax/agents-mcp";
|
|
5
|
+
import { ChangeEvent } from "@durable-streams/state";
|
|
6
6
|
import { braveSearchTool } from "@electric-ax/agents-runtime/tools";
|
|
7
7
|
|
|
8
8
|
//#region src/bootstrap.d.ts
|
|
@@ -14,6 +14,7 @@ interface AgentHandlerResult {
|
|
|
14
14
|
typeNames: Array<string>;
|
|
15
15
|
skillsRegistry: SkillsRegistry | null;
|
|
16
16
|
}
|
|
17
|
+
type BuiltinElectricToolsFactory = NonNullable<ProcessWakeConfig[`createElectricTools`]>;
|
|
17
18
|
interface BuiltinAgentHandlerOptions {
|
|
18
19
|
agentServerUrl: string;
|
|
19
20
|
serveEndpoint?: string;
|
|
@@ -25,43 +26,15 @@ interface BuiltinAgentHandlerOptions {
|
|
|
25
26
|
baseSkillsDir?: string;
|
|
26
27
|
serverHeaders?: HeadersProvider;
|
|
27
28
|
defaultDispatchPolicyForType?: (typeName: string) => DispatchPolicy | undefined;
|
|
28
|
-
createElectricTools?:
|
|
29
|
-
entityUrl: string;
|
|
30
|
-
entityType: string;
|
|
31
|
-
args: Readonly<Record<string, unknown>>;
|
|
32
|
-
db: EntityStreamDBWithActions;
|
|
33
|
-
events: Array<ChangeEvent>;
|
|
34
|
-
upsertCronSchedule: (opts: {
|
|
35
|
-
id: string;
|
|
36
|
-
expression: string;
|
|
37
|
-
timezone?: string;
|
|
38
|
-
payload?: unknown;
|
|
39
|
-
debounceMs?: number;
|
|
40
|
-
timeoutMs?: number;
|
|
41
|
-
}) => Promise<{
|
|
42
|
-
txid: string;
|
|
43
|
-
}>;
|
|
44
|
-
upsertFutureSendSchedule: (opts: {
|
|
45
|
-
id: string;
|
|
46
|
-
payload: unknown;
|
|
47
|
-
targetUrl?: string;
|
|
48
|
-
fireAt: string;
|
|
49
|
-
from?: string;
|
|
50
|
-
messageType?: string;
|
|
51
|
-
}) => Promise<{
|
|
52
|
-
txid: string;
|
|
53
|
-
}>;
|
|
54
|
-
deleteSchedule: (opts: {
|
|
55
|
-
id: string;
|
|
56
|
-
}) => Promise<{
|
|
57
|
-
txid: string;
|
|
58
|
-
}>;
|
|
59
|
-
}) => Array<AgentTool> | Promise<Array<AgentTool>>;
|
|
29
|
+
createElectricTools?: BuiltinElectricToolsFactory;
|
|
60
30
|
}
|
|
31
|
+
declare function createBuiltinElectricTools(custom?: BuiltinElectricToolsFactory): BuiltinElectricToolsFactory;
|
|
61
32
|
declare function createBuiltinAgentHandler(options: BuiltinAgentHandlerOptions): Promise<AgentHandlerResult | null>;
|
|
62
33
|
declare function createAgentHandler(agentServerUrl: string, workingDirectory?: string, streamFn?: StreamFn, createElectricTools?: BuiltinAgentHandlerOptions[`createElectricTools`], serveEndpoint?: string): Promise<AgentHandlerResult | null>;
|
|
63
34
|
declare function registerBuiltinAgentTypes(bootstrap: AgentHandlerResult): Promise<void>;
|
|
64
|
-
declare const registerAgentTypes: typeof registerBuiltinAgentTypes;
|
|
35
|
+
declare const registerAgentTypes: typeof registerBuiltinAgentTypes;
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
65
38
|
//#region src/server.d.ts
|
|
66
39
|
interface BuiltinAgentsServerOptions {
|
|
67
40
|
agentServerUrl: string;
|
|
@@ -106,38 +79,7 @@ interface BuiltinAgentsServerOptions {
|
|
|
106
79
|
loadProjectMcpConfig?: boolean;
|
|
107
80
|
/** Override for the built-in skills directory; required when embedders bundle this package. */
|
|
108
81
|
baseSkillsDir?: string;
|
|
109
|
-
createElectricTools?:
|
|
110
|
-
entityUrl: string;
|
|
111
|
-
entityType: string;
|
|
112
|
-
args: Readonly<Record<string, unknown>>;
|
|
113
|
-
db: EntityStreamDBWithActions;
|
|
114
|
-
events: Array<ChangeEvent>;
|
|
115
|
-
upsertCronSchedule: (opts: {
|
|
116
|
-
id: string;
|
|
117
|
-
expression: string;
|
|
118
|
-
timezone?: string;
|
|
119
|
-
payload?: unknown;
|
|
120
|
-
debounceMs?: number;
|
|
121
|
-
timeoutMs?: number;
|
|
122
|
-
}) => Promise<{
|
|
123
|
-
txid: string;
|
|
124
|
-
}>;
|
|
125
|
-
upsertFutureSendSchedule: (opts: {
|
|
126
|
-
id: string;
|
|
127
|
-
payload: unknown;
|
|
128
|
-
targetUrl?: string;
|
|
129
|
-
fireAt: string;
|
|
130
|
-
from?: string;
|
|
131
|
-
messageType?: string;
|
|
132
|
-
}) => Promise<{
|
|
133
|
-
txid: string;
|
|
134
|
-
}>;
|
|
135
|
-
deleteSchedule: (opts: {
|
|
136
|
-
id: string;
|
|
137
|
-
}) => Promise<{
|
|
138
|
-
txid: string;
|
|
139
|
-
}>;
|
|
140
|
-
}) => Array<AgentTool> | Promise<Array<AgentTool>>;
|
|
82
|
+
createElectricTools?: NonNullable<ProcessWakeConfig[`createElectricTools`]>;
|
|
141
83
|
}
|
|
142
84
|
declare class BuiltinAgentsServer {
|
|
143
85
|
private bootstrap;
|
|
@@ -154,7 +96,9 @@ declare class BuiltinAgentsServer {
|
|
|
154
96
|
start(): Promise<string>;
|
|
155
97
|
stop(): Promise<void>;
|
|
156
98
|
private registerPullWakeRunner;
|
|
157
|
-
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
158
102
|
//#region src/entrypoint-lib.d.ts
|
|
159
103
|
type EnvSource = Record<string, string | undefined>;
|
|
160
104
|
interface BuiltinAgentsEntrypointOptions extends BuiltinAgentsServerOptions {}
|
|
@@ -206,6 +150,7 @@ declare const HORTON_MODEL = "claude-sonnet-4-6";
|
|
|
206
150
|
declare function generateTitle(userMessage: string, llmCall: (prompt: string) => Promise<string>, onFallback?: (reason: string) => void): Promise<string>;
|
|
207
151
|
declare function buildHortonSystemPrompt(workingDirectory: string, opts?: {
|
|
208
152
|
hasDocsSupport?: boolean;
|
|
153
|
+
hasEventSourceTools?: boolean;
|
|
209
154
|
hasSkills?: boolean;
|
|
210
155
|
docsUrl?: string;
|
|
211
156
|
modelProvider?: string;
|
|
@@ -258,4 +203,4 @@ declare function createHortonDocsSupport(workingDirectory: string, opts?: {
|
|
|
258
203
|
}): HortonDocsSupport | null;
|
|
259
204
|
|
|
260
205
|
//#endregion
|
|
261
|
-
export { AgentHandlerResult, BuiltinAgentHandlerOptions, BuiltinAgentsEntrypointOptions, BuiltinAgentsEntrypointServer, BuiltinAgentsServer, BuiltinAgentsServerOptions, DEFAULT_BUILTIN_AGENT_HANDLER_PATH, HORTON_MODEL, McpConfig, McpListedEntry, McpRegistry, McpServerConfig, RegistrySnapshot, RegistrySubscriber, RunBuiltinAgentsEntrypointOptions, WORKER_TOOL_NAMES, WorkerToolName, braveSearchTool, buildHortonSystemPrompt, createAgentHandler, createBuiltinAgentHandler, createHortonDocsSupport, createHortonTools, createSpawnWorkerTool, generateTitle, registerAgentTypes, registerBuiltinAgentTypes, registerHorton, registerWorker, resolveBuiltinAgentsEntrypointOptions, runBuiltinAgentsEntrypoint };
|
|
206
|
+
export { AgentHandlerResult, BuiltinAgentHandlerOptions, BuiltinAgentsEntrypointOptions, BuiltinAgentsEntrypointServer, BuiltinAgentsServer, BuiltinAgentsServerOptions, BuiltinElectricToolsFactory, DEFAULT_BUILTIN_AGENT_HANDLER_PATH, HORTON_MODEL, McpConfig, McpListedEntry, McpRegistry, McpServerConfig, RegistrySnapshot, RegistrySubscriber, RunBuiltinAgentsEntrypointOptions, WORKER_TOOL_NAMES, WorkerToolName, braveSearchTool, buildHortonSystemPrompt, createAgentHandler, createBuiltinAgentHandler, createBuiltinElectricTools, createHortonDocsSupport, createHortonTools, createSpawnWorkerTool, generateTitle, registerAgentTypes, registerBuiltinAgentTypes, registerHorton, registerWorker, resolveBuiltinAgentsEntrypointOptions, runBuiltinAgentsEntrypoint };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AgentConfig, AgentTool, AvailableProvider, DispatchPolicy, EntityRegistry,
|
|
2
|
-
import { ChangeEvent } from "@durable-streams/state";
|
|
1
|
+
import { AgentConfig, AgentTool, AvailableProvider, DispatchPolicy, EntityRegistry, HandlerContext, HeadersProvider, ProcessWakeConfig, PullWakeRunnerConfig, RuntimeHandler, SkillsRegistry, WakeEvent } from "@electric-ax/agents-runtime";
|
|
3
2
|
import { braveSearchTool } from "@electric-ax/agents-runtime/tools";
|
|
3
|
+
import { ChangeEvent } from "@durable-streams/state";
|
|
4
4
|
import { ListedEntry as McpListedEntry, McpConfig, McpServerConfig, McpServerConfig as McpServerConfig$1, Registry, Registry as McpRegistry, RegistrySnapshot, RegistrySubscriber } from "@electric-ax/agents-mcp";
|
|
5
5
|
import { AgentTool as AgentTool$1, StreamFn } from "@mariozechner/pi-agent-core";
|
|
6
6
|
import { IncomingMessage, ServerResponse } from "node:http";
|
|
@@ -14,6 +14,7 @@ interface AgentHandlerResult {
|
|
|
14
14
|
typeNames: Array<string>;
|
|
15
15
|
skillsRegistry: SkillsRegistry | null;
|
|
16
16
|
}
|
|
17
|
+
type BuiltinElectricToolsFactory = NonNullable<ProcessWakeConfig[`createElectricTools`]>;
|
|
17
18
|
interface BuiltinAgentHandlerOptions {
|
|
18
19
|
agentServerUrl: string;
|
|
19
20
|
serveEndpoint?: string;
|
|
@@ -25,43 +26,15 @@ interface BuiltinAgentHandlerOptions {
|
|
|
25
26
|
baseSkillsDir?: string;
|
|
26
27
|
serverHeaders?: HeadersProvider;
|
|
27
28
|
defaultDispatchPolicyForType?: (typeName: string) => DispatchPolicy | undefined;
|
|
28
|
-
createElectricTools?:
|
|
29
|
-
entityUrl: string;
|
|
30
|
-
entityType: string;
|
|
31
|
-
args: Readonly<Record<string, unknown>>;
|
|
32
|
-
db: EntityStreamDBWithActions;
|
|
33
|
-
events: Array<ChangeEvent>;
|
|
34
|
-
upsertCronSchedule: (opts: {
|
|
35
|
-
id: string;
|
|
36
|
-
expression: string;
|
|
37
|
-
timezone?: string;
|
|
38
|
-
payload?: unknown;
|
|
39
|
-
debounceMs?: number;
|
|
40
|
-
timeoutMs?: number;
|
|
41
|
-
}) => Promise<{
|
|
42
|
-
txid: string;
|
|
43
|
-
}>;
|
|
44
|
-
upsertFutureSendSchedule: (opts: {
|
|
45
|
-
id: string;
|
|
46
|
-
payload: unknown;
|
|
47
|
-
targetUrl?: string;
|
|
48
|
-
fireAt: string;
|
|
49
|
-
from?: string;
|
|
50
|
-
messageType?: string;
|
|
51
|
-
}) => Promise<{
|
|
52
|
-
txid: string;
|
|
53
|
-
}>;
|
|
54
|
-
deleteSchedule: (opts: {
|
|
55
|
-
id: string;
|
|
56
|
-
}) => Promise<{
|
|
57
|
-
txid: string;
|
|
58
|
-
}>;
|
|
59
|
-
}) => Array<AgentTool> | Promise<Array<AgentTool>>;
|
|
29
|
+
createElectricTools?: BuiltinElectricToolsFactory;
|
|
60
30
|
}
|
|
31
|
+
declare function createBuiltinElectricTools(custom?: BuiltinElectricToolsFactory): BuiltinElectricToolsFactory;
|
|
61
32
|
declare function createBuiltinAgentHandler(options: BuiltinAgentHandlerOptions): Promise<AgentHandlerResult | null>;
|
|
62
33
|
declare function createAgentHandler(agentServerUrl: string, workingDirectory?: string, streamFn?: StreamFn, createElectricTools?: BuiltinAgentHandlerOptions[`createElectricTools`], serveEndpoint?: string): Promise<AgentHandlerResult | null>;
|
|
63
34
|
declare function registerBuiltinAgentTypes(bootstrap: AgentHandlerResult): Promise<void>;
|
|
64
|
-
declare const registerAgentTypes: typeof registerBuiltinAgentTypes;
|
|
35
|
+
declare const registerAgentTypes: typeof registerBuiltinAgentTypes;
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
65
38
|
//#region src/server.d.ts
|
|
66
39
|
interface BuiltinAgentsServerOptions {
|
|
67
40
|
agentServerUrl: string;
|
|
@@ -106,38 +79,7 @@ interface BuiltinAgentsServerOptions {
|
|
|
106
79
|
loadProjectMcpConfig?: boolean;
|
|
107
80
|
/** Override for the built-in skills directory; required when embedders bundle this package. */
|
|
108
81
|
baseSkillsDir?: string;
|
|
109
|
-
createElectricTools?:
|
|
110
|
-
entityUrl: string;
|
|
111
|
-
entityType: string;
|
|
112
|
-
args: Readonly<Record<string, unknown>>;
|
|
113
|
-
db: EntityStreamDBWithActions;
|
|
114
|
-
events: Array<ChangeEvent>;
|
|
115
|
-
upsertCronSchedule: (opts: {
|
|
116
|
-
id: string;
|
|
117
|
-
expression: string;
|
|
118
|
-
timezone?: string;
|
|
119
|
-
payload?: unknown;
|
|
120
|
-
debounceMs?: number;
|
|
121
|
-
timeoutMs?: number;
|
|
122
|
-
}) => Promise<{
|
|
123
|
-
txid: string;
|
|
124
|
-
}>;
|
|
125
|
-
upsertFutureSendSchedule: (opts: {
|
|
126
|
-
id: string;
|
|
127
|
-
payload: unknown;
|
|
128
|
-
targetUrl?: string;
|
|
129
|
-
fireAt: string;
|
|
130
|
-
from?: string;
|
|
131
|
-
messageType?: string;
|
|
132
|
-
}) => Promise<{
|
|
133
|
-
txid: string;
|
|
134
|
-
}>;
|
|
135
|
-
deleteSchedule: (opts: {
|
|
136
|
-
id: string;
|
|
137
|
-
}) => Promise<{
|
|
138
|
-
txid: string;
|
|
139
|
-
}>;
|
|
140
|
-
}) => Array<AgentTool> | Promise<Array<AgentTool>>;
|
|
82
|
+
createElectricTools?: NonNullable<ProcessWakeConfig[`createElectricTools`]>;
|
|
141
83
|
}
|
|
142
84
|
declare class BuiltinAgentsServer {
|
|
143
85
|
private bootstrap;
|
|
@@ -154,7 +96,9 @@ declare class BuiltinAgentsServer {
|
|
|
154
96
|
start(): Promise<string>;
|
|
155
97
|
stop(): Promise<void>;
|
|
156
98
|
private registerPullWakeRunner;
|
|
157
|
-
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
158
102
|
//#region src/entrypoint-lib.d.ts
|
|
159
103
|
type EnvSource = Record<string, string | undefined>;
|
|
160
104
|
interface BuiltinAgentsEntrypointOptions extends BuiltinAgentsServerOptions {}
|
|
@@ -206,6 +150,7 @@ declare const HORTON_MODEL = "claude-sonnet-4-6";
|
|
|
206
150
|
declare function generateTitle(userMessage: string, llmCall: (prompt: string) => Promise<string>, onFallback?: (reason: string) => void): Promise<string>;
|
|
207
151
|
declare function buildHortonSystemPrompt(workingDirectory: string, opts?: {
|
|
208
152
|
hasDocsSupport?: boolean;
|
|
153
|
+
hasEventSourceTools?: boolean;
|
|
209
154
|
hasSkills?: boolean;
|
|
210
155
|
docsUrl?: string;
|
|
211
156
|
modelProvider?: string;
|
|
@@ -258,4 +203,4 @@ declare function createHortonDocsSupport(workingDirectory: string, opts?: {
|
|
|
258
203
|
}): HortonDocsSupport | null;
|
|
259
204
|
|
|
260
205
|
//#endregion
|
|
261
|
-
export { AgentHandlerResult, BuiltinAgentHandlerOptions, BuiltinAgentsEntrypointOptions, BuiltinAgentsEntrypointServer, BuiltinAgentsServer, BuiltinAgentsServerOptions, DEFAULT_BUILTIN_AGENT_HANDLER_PATH, HORTON_MODEL, McpConfig, McpListedEntry, McpRegistry, McpServerConfig, RegistrySnapshot, RegistrySubscriber, RunBuiltinAgentsEntrypointOptions, WORKER_TOOL_NAMES, WorkerToolName, braveSearchTool, buildHortonSystemPrompt, createAgentHandler, createBuiltinAgentHandler, createHortonDocsSupport, createHortonTools, createSpawnWorkerTool, generateTitle, registerAgentTypes, registerBuiltinAgentTypes, registerHorton, registerWorker, resolveBuiltinAgentsEntrypointOptions, runBuiltinAgentsEntrypoint };
|
|
206
|
+
export { AgentHandlerResult, BuiltinAgentHandlerOptions, BuiltinAgentsEntrypointOptions, BuiltinAgentsEntrypointServer, BuiltinAgentsServer, BuiltinAgentsServerOptions, BuiltinElectricToolsFactory, DEFAULT_BUILTIN_AGENT_HANDLER_PATH, HORTON_MODEL, McpConfig, McpListedEntry, McpRegistry, McpServerConfig, RegistrySnapshot, RegistrySubscriber, RunBuiltinAgentsEntrypointOptions, WORKER_TOOL_NAMES, WorkerToolName, braveSearchTool, buildHortonSystemPrompt, createAgentHandler, createBuiltinAgentHandler, createBuiltinElectricTools, createHortonDocsSupport, createHortonTools, createSpawnWorkerTool, generateTitle, registerAgentTypes, registerBuiltinAgentTypes, registerHorton, registerWorker, resolveBuiltinAgentsEntrypointOptions, runBuiltinAgentsEntrypoint };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { mergeElectricPrincipalHeader } from "./server-headers-KD5yHFYT.js";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { appendPathToUrl, completeWithLowCostModel, createEntityRegistry, createPullWakeRunner, createRuntimeHandler, createSkillTools, createSkillsRegistry, db, detectAvailableProviders, readCodexAccessToken, registerToolProvider, unregisterToolProvider } from "@electric-ax/agents-runtime";
|
|
5
|
+
import { braveSearchTool, braveSearchTool as braveSearchTool$1, createBashTool, createEditTool, createEventSourceTools, createFetchUrlTool, createReadFileTool, createSendTool, createWriteTool, fetchUrlTool } from "@electric-ax/agents-runtime/tools";
|
|
5
6
|
import fs from "node:fs";
|
|
6
7
|
import pino from "pino";
|
|
7
8
|
import { eq, not, queryOnce } from "@durable-streams/state";
|
|
@@ -13,7 +14,6 @@ import { Type } from "@sinclair/typebox";
|
|
|
13
14
|
import { load } from "sqlite-vec";
|
|
14
15
|
import { nanoid } from "nanoid";
|
|
15
16
|
import { getModels } from "@mariozechner/pi-ai";
|
|
16
|
-
import { braveSearchTool, braveSearchTool as braveSearchTool$1, createBashTool, createEditTool, createFetchUrlTool, createReadFileTool, createSendTool, createWriteTool, fetchUrlTool } from "@electric-ax/agents-runtime/tools";
|
|
17
17
|
import { bridgeMcpTool, buildPromptTools, buildResourceTools, createRegistry, keychainPersistence, loadConfig, mcp, watchConfig } from "@electric-ax/agents-mcp";
|
|
18
18
|
|
|
19
19
|
//#region src/log.ts
|
|
@@ -785,12 +785,14 @@ const REASONING_EFFORT_VALUES = [
|
|
|
785
785
|
const DEFAULT_ANTHROPIC_MODEL = `claude-sonnet-4-6`;
|
|
786
786
|
const DEFAULT_OPENAI_MODEL = `gpt-4.1`;
|
|
787
787
|
const DEFAULT_CODEX_MODEL = `gpt-5.4`;
|
|
788
|
+
const DEFAULT_DEEPSEEK_MODEL = `deepseek-v4-flash`;
|
|
788
789
|
function modelValue(provider, id) {
|
|
789
790
|
return `${provider}:${id}`;
|
|
790
791
|
}
|
|
791
792
|
function providerLabel(provider) {
|
|
792
793
|
if (provider === `anthropic`) return `Anthropic`;
|
|
793
794
|
if (provider === `openai-codex`) return `OpenAI Codex`;
|
|
795
|
+
if (provider === `deepseek`) return `DeepSeek`;
|
|
794
796
|
return `OpenAI`;
|
|
795
797
|
}
|
|
796
798
|
function configuredProviders() {
|
|
@@ -817,6 +819,9 @@ async function fetchAvailableModelIds(provider) {
|
|
|
817
819
|
"anthropic-version": `2023-06-01`
|
|
818
820
|
},
|
|
819
821
|
signal: AbortSignal.timeout(3e3)
|
|
822
|
+
}) : provider === `deepseek` ? await fetch(`https://api.deepseek.com/v1/models`, {
|
|
823
|
+
headers: { authorization: `Bearer ${process.env.DEEPSEEK_API_KEY ?? ``}` },
|
|
824
|
+
signal: AbortSignal.timeout(3e3)
|
|
820
825
|
}) : await fetch(`https://api.openai.com/v1/models`, {
|
|
821
826
|
headers: { authorization: `Bearer ${process.env.OPENAI_API_KEY ?? ``}` },
|
|
822
827
|
signal: AbortSignal.timeout(3e3)
|
|
@@ -877,7 +882,7 @@ async function createBuiltinModelCatalog(options = {}) {
|
|
|
877
882
|
if (providers.length === 0 && options.allowMockFallback) return mockFallbackCatalog();
|
|
878
883
|
const choices = (await Promise.all(providers.map((provider) => choicesForProvider(provider)))).flat();
|
|
879
884
|
if (choices.length === 0) return options.allowMockFallback ? mockFallbackCatalog() : null;
|
|
880
|
-
const defaultChoice = choices.find((choice) => choice.provider === `anthropic` && choice.id === DEFAULT_ANTHROPIC_MODEL) ?? choices.find((choice) => choice.provider === `openai` && choice.id === DEFAULT_OPENAI_MODEL) ?? choices.find((choice) => choice.provider === `openai-codex` && choice.id === DEFAULT_CODEX_MODEL) ?? choices[0];
|
|
885
|
+
const defaultChoice = choices.find((choice) => choice.provider === `anthropic` && choice.id === DEFAULT_ANTHROPIC_MODEL) ?? choices.find((choice) => choice.provider === `openai` && choice.id === DEFAULT_OPENAI_MODEL) ?? choices.find((choice) => choice.provider === `openai-codex` && choice.id === DEFAULT_CODEX_MODEL) ?? choices.find((choice) => choice.provider === `deepseek` && choice.id === DEFAULT_DEEPSEEK_MODEL) ?? choices[0];
|
|
881
886
|
return {
|
|
882
887
|
choices,
|
|
883
888
|
defaultChoice
|
|
@@ -999,6 +1004,7 @@ async function generateTitle(userMessage, llmCall, onFallback) {
|
|
|
999
1004
|
}
|
|
1000
1005
|
function buildHortonSystemPrompt(workingDirectory, opts = {}) {
|
|
1001
1006
|
const docsTools = opts.hasDocsSupport ? `\n- search_durable_agents_docs: hybrid search over the built-in Durable Agents docs index` : ``;
|
|
1007
|
+
const eventSourceTools = opts.hasEventSourceTools ? `\n- list_event_sources: list external webhook/event feeds you can subscribe to, including available buckets and parameters\n- subscribe_event_source: subscribe yourself to one of those feeds or buckets so matching future events wake you\n- list_event_source_subscriptions: list your active event source subscriptions\n- unsubscribe_event_source: remove one of your event source subscriptions by id` : ``;
|
|
1002
1008
|
const skillsTools = opts.hasSkills ? `\n- use_skill: load a skill (knowledge, instructions, or a tutorial) into your context to help with the user's request\n- remove_skill: unload a skill from context when you're done with it` : ``;
|
|
1003
1009
|
const docsGuidance = opts.hasDocsSupport ? `\n- For ANY question about Electric Agents, Durable Agents, or this framework, ALWAYS use search_durable_agents_docs FIRST. Do not use web_search or fetch_url for Electric Agents topics unless the docs search returns no useful results.\n- The search tool returns chunk content directly — you do not need to read the source files.\n- Use repo read/bash tools only for non-doc files or when you need to inspect exact implementation code in the workspace.` : ``;
|
|
1004
1010
|
const skillsGuidance = opts.hasSkills ? `\n# Skills\nYou have access to skills — specialized knowledge and guided workflows you can load on demand. Your context includes a skills catalog listing what's available. When the user's request matches a skill's description or keywords, load it with use_skill.
|
|
@@ -1052,8 +1058,8 @@ When a user opens with a greeting ("hi", "hello", "hey", etc.) or a broad statem
|
|
|
1052
1058
|
- web_search: search the web
|
|
1053
1059
|
- fetch_url: fetch and convert a URL to markdown
|
|
1054
1060
|
- spawn_worker: dispatch a subagent for an isolated task
|
|
1055
|
-
- send: send a message to an Electric Agent/entity
|
|
1056
|
-
${docsTools}${skillsTools}
|
|
1061
|
+
- send: send a message to an Electric Agent/entity. To schedule future work for yourself, call send with self: true and afterMs.
|
|
1062
|
+
${eventSourceTools}${docsTools}${skillsTools}
|
|
1057
1063
|
|
|
1058
1064
|
# Working with files
|
|
1059
1065
|
- Prefer edit over write when modifying existing files.
|
|
@@ -1086,6 +1092,11 @@ Report outcomes faithfully. If a command failed, say so with the relevant output
|
|
|
1086
1092
|
Working directory: ${workingDirectory}
|
|
1087
1093
|
The current year is ${new Date().getFullYear()}.`;
|
|
1088
1094
|
}
|
|
1095
|
+
function getToolName(tool) {
|
|
1096
|
+
if (typeof tool !== `object` || tool === null) return null;
|
|
1097
|
+
const name = tool.name;
|
|
1098
|
+
return typeof name === `string` ? name : null;
|
|
1099
|
+
}
|
|
1089
1100
|
function createHortonTools(workingDirectory, ctx, readSet, opts = {}) {
|
|
1090
1101
|
return [
|
|
1091
1102
|
createBashTool(workingDirectory),
|
|
@@ -1100,7 +1111,7 @@ function createHortonTools(workingDirectory, ctx, readSet, opts = {}) {
|
|
|
1100
1111
|
logPrefix: opts.logPrefix ?? `[horton]`
|
|
1101
1112
|
})] : [fetchUrlTool],
|
|
1102
1113
|
createSpawnWorkerTool(ctx, opts.modelConfig),
|
|
1103
|
-
createSendTool(ctx.send),
|
|
1114
|
+
createSendTool(ctx.send, { selfEntityUrl: ctx.entityUrl }),
|
|
1104
1115
|
...opts.docsSearchTool ? [opts.docsSearchTool] : []
|
|
1105
1116
|
];
|
|
1106
1117
|
}
|
|
@@ -1152,6 +1163,7 @@ function createAssistantHandler(options) {
|
|
|
1152
1163
|
...skillsRegistry && skillsRegistry.catalog.size > 0 ? createSkillTools(skillsRegistry, ctx) : [],
|
|
1153
1164
|
...mcp.tools()
|
|
1154
1165
|
];
|
|
1166
|
+
const hasEventSourceTools = tools.some((tool) => getToolName(tool) === `list_event_sources`);
|
|
1155
1167
|
const titlePromise = ctx.firstWake && !ctx.tags.title ? (async () => {
|
|
1156
1168
|
const firstUserMessage = await extractFirstUserMessage(ctx);
|
|
1157
1169
|
if (!firstUserMessage) return;
|
|
@@ -1238,7 +1250,8 @@ function createAssistantHandler(options) {
|
|
|
1238
1250
|
hasSkills,
|
|
1239
1251
|
docsUrl,
|
|
1240
1252
|
modelProvider: modelConfig.provider,
|
|
1241
|
-
modelId: String(modelConfig.model)
|
|
1253
|
+
modelId: String(modelConfig.model),
|
|
1254
|
+
hasEventSourceTools
|
|
1242
1255
|
}),
|
|
1243
1256
|
...modelConfig,
|
|
1244
1257
|
tools,
|
|
@@ -1350,7 +1363,7 @@ function buildToolsForWorker(tools, workingDirectory, ctx, readSet) {
|
|
|
1350
1363
|
out.push(createSpawnWorkerTool(ctx));
|
|
1351
1364
|
break;
|
|
1352
1365
|
case `send`:
|
|
1353
|
-
out.push(createSendTool(ctx.send));
|
|
1366
|
+
out.push(createSendTool(ctx.send, { selfEntityUrl: ctx.entityUrl }));
|
|
1354
1367
|
break;
|
|
1355
1368
|
}
|
|
1356
1369
|
return out;
|
|
@@ -1479,6 +1492,27 @@ function registerWorker(registry, options) {
|
|
|
1479
1492
|
//#endregion
|
|
1480
1493
|
//#region src/bootstrap.ts
|
|
1481
1494
|
const DEFAULT_BUILTIN_AGENT_HANDLER_PATH = `/_electric/builtin-agent-handler`;
|
|
1495
|
+
function toolName(tool) {
|
|
1496
|
+
return typeof tool.name === `string` ? tool.name : null;
|
|
1497
|
+
}
|
|
1498
|
+
function dedupeToolsByName(tools) {
|
|
1499
|
+
const seen = new Set();
|
|
1500
|
+
const deduped = [];
|
|
1501
|
+
for (const tool of tools) {
|
|
1502
|
+
const name = toolName(tool);
|
|
1503
|
+
if (name && seen.has(name)) continue;
|
|
1504
|
+
if (name) seen.add(name);
|
|
1505
|
+
deduped.push(tool);
|
|
1506
|
+
}
|
|
1507
|
+
return deduped;
|
|
1508
|
+
}
|
|
1509
|
+
function createBuiltinElectricTools(custom) {
|
|
1510
|
+
return async (context) => {
|
|
1511
|
+
const builtinTools = createEventSourceTools(context);
|
|
1512
|
+
const customTools = custom ? await custom(context) : [];
|
|
1513
|
+
return dedupeToolsByName([...builtinTools, ...customTools]);
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1482
1516
|
async function createBuiltinAgentHandler(options) {
|
|
1483
1517
|
const { agentServerUrl, serveEndpoint, workingDirectory, streamFn, createElectricTools, publicUrl, runtimeName, baseSkillsDir: baseSkillsDirOverride, serverHeaders, defaultDispatchPolicyForType } = options;
|
|
1484
1518
|
const modelCatalog = await createBuiltinModelCatalog({ allowMockFallback: Boolean(streamFn) });
|
|
@@ -1521,7 +1555,7 @@ async function createBuiltinAgentHandler(options) {
|
|
|
1521
1555
|
defaultDispatchPolicyForType,
|
|
1522
1556
|
serverHeaders,
|
|
1523
1557
|
idleTimeout: 5 * 6e4,
|
|
1524
|
-
createElectricTools,
|
|
1558
|
+
createElectricTools: createBuiltinElectricTools(createElectricTools),
|
|
1525
1559
|
publicUrl,
|
|
1526
1560
|
name: runtimeName ?? `builtin-agents`
|
|
1527
1561
|
});
|
|
@@ -1850,4 +1884,4 @@ async function runBuiltinAgentsEntrypoint({ env = process.env, cwd = process.cwd
|
|
|
1850
1884
|
}
|
|
1851
1885
|
|
|
1852
1886
|
//#endregion
|
|
1853
|
-
export { BuiltinAgentsServer, DEFAULT_BUILTIN_AGENT_HANDLER_PATH, HORTON_MODEL, WORKER_TOOL_NAMES, braveSearchTool, buildHortonSystemPrompt, createAgentHandler, createBuiltinAgentHandler, createHortonDocsSupport, createHortonTools, createSpawnWorkerTool, generateTitle, registerAgentTypes, registerBuiltinAgentTypes, registerHorton, registerWorker, resolveBuiltinAgentsEntrypointOptions, runBuiltinAgentsEntrypoint };
|
|
1887
|
+
export { BuiltinAgentsServer, DEFAULT_BUILTIN_AGENT_HANDLER_PATH, HORTON_MODEL, WORKER_TOOL_NAMES, braveSearchTool, buildHortonSystemPrompt, createAgentHandler, createBuiltinAgentHandler, createBuiltinElectricTools, createHortonDocsSupport, createHortonTools, createSpawnWorkerTool, generateTitle, registerAgentTypes, registerBuiltinAgentTypes, registerHorton, registerWorker, resolveBuiltinAgentsEntrypointOptions, runBuiltinAgentsEntrypoint };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electric-ax/agents",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
4
4
|
"description": "Built-in Electric Agents runtimes such as Horton and worker",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"sqlite-vec": "^0.1.9",
|
|
50
50
|
"zod": "^4.3.6",
|
|
51
51
|
"@electric-ax/agents-mcp": "0.2.2",
|
|
52
|
-
"@electric-ax/agents-runtime": "0.3.
|
|
52
|
+
"@electric-ax/agents-runtime": "0.3.4"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/better-sqlite3": "^7.6.13",
|