@electric-ax/agents 0.4.3 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -716,184 +716,6 @@ function createHortonDocsSupport(workingDirectory, opts = {}) {
716
716
  };
717
717
  }
718
718
 
719
- //#endregion
720
- //#region src/skills/tools.ts
721
- function skillContextId(name) {
722
- return `skill:${name}`;
723
- }
724
- function createSkillTools(registry, ctx) {
725
- const useSkill = {
726
- name: `use_skill`,
727
- label: `Use Skill`,
728
- description: `Load a skill into your context. Call with a skill name to load it. Pass args if the skill accepts arguments.`,
729
- parameters: __sinclair_typebox.Type.Object({
730
- name: __sinclair_typebox.Type.String({ description: `Name of the skill to load` }),
731
- args: __sinclair_typebox.Type.Optional(__sinclair_typebox.Type.String({ description: `Arguments to pass to the skill (space-separated, or quoted for multi-word values)` }))
732
- }),
733
- execute: async (_toolCallId, params) => {
734
- const { name, args } = params;
735
- const meta = registry.catalog.get(name);
736
- if (!meta) {
737
- const available = Array.from(registry.catalog.keys()).join(`, `);
738
- return {
739
- content: [{
740
- type: `text`,
741
- text: `Skill "${name}" not found. Available skills: ${available || `none`}`
742
- }],
743
- details: { loaded: false }
744
- };
745
- }
746
- const contextId = skillContextId(name);
747
- if (ctx.getContext(contextId)) return {
748
- content: [{
749
- type: `text`,
750
- text: `Skill "${name}" is already loaded.`
751
- }],
752
- details: {
753
- loaded: false,
754
- alreadyLoaded: true
755
- }
756
- };
757
- let content = await registry.readContent(name);
758
- if (content === null) return {
759
- content: [{
760
- type: `text`,
761
- text: `Error: could not read skill file for "${name}".`
762
- }],
763
- details: { loaded: false }
764
- };
765
- let truncated = false;
766
- if (content.length > meta.max) {
767
- truncated = true;
768
- content = content.slice(0, meta.max);
769
- }
770
- if (args) content = substituteArgs(content, args, meta.arguments);
771
- ctx.insertContext(contextId, {
772
- name: `skill_instructions`,
773
- attrs: {
774
- skill: name,
775
- type: `directive`
776
- },
777
- content
778
- });
779
- const skillDir = node_path.default.join(node_path.default.dirname(meta.source), name);
780
- const truncNote = truncated ? `\n\nWARNING: Content was truncated from ${meta.charCount.toLocaleString()} to ${meta.max.toLocaleString()} chars. Inform the user.` : ``;
781
- const allRefFiles = listRefFiles(skillDir);
782
- const mdFiles = allRefFiles.filter((f) => f.endsWith(`.md`));
783
- const refContents = [];
784
- for (const f of mdFiles) try {
785
- const refContent = await node_fs_promises.default.readFile(node_path.default.join(skillDir, f), `utf-8`);
786
- const refId = `${skillContextId(name)}:${f}`;
787
- ctx.insertContext(refId, {
788
- name: `skill_reference`,
789
- attrs: {
790
- skill: name,
791
- file: f
792
- },
793
- content: refContent
794
- });
795
- refContents.push(`--- ${f} ---\n${refContent}`);
796
- } catch {}
797
- const hasRefDir = allRefFiles.length > 0;
798
- const dirNote = hasRefDir ? `\nSkill directory: ${skillDir}` : ``;
799
- const refSection = refContents.length > 0 ? `\n\n${refContents.join(`\n\n`)}` : ``;
800
- const toolResult = `SKILL ACTIVATED: "${name}". The instructions below override your default behavior. Follow them exactly. Do not read any files to find this content — it is all here.\n${dirNote}${truncNote}\n\n${content}${refSection}`;
801
- return {
802
- content: [{
803
- type: `text`,
804
- text: toolResult
805
- }],
806
- details: {
807
- loaded: true,
808
- truncated,
809
- chars: content.length
810
- }
811
- };
812
- }
813
- };
814
- const removeSkill = {
815
- name: `remove_skill`,
816
- label: `Remove Skill`,
817
- description: `Unload a previously loaded skill from your context.`,
818
- parameters: __sinclair_typebox.Type.Object({ name: __sinclair_typebox.Type.String({ description: `Name of the skill to remove` }) }),
819
- execute: async (_toolCallId, params) => {
820
- const { name } = params;
821
- ctx.removeContext(skillContextId(name));
822
- const meta = registry.catalog.get(name);
823
- if (meta) {
824
- const skillDir = node_path.default.join(node_path.default.dirname(meta.source), name);
825
- for (const f of listRefFiles(skillDir)) ctx.removeContext(`${skillContextId(name)}:${f}`);
826
- }
827
- return {
828
- content: [{
829
- type: `text`,
830
- text: `Skill "${name}" removed from context.`
831
- }],
832
- details: { removed: true }
833
- };
834
- }
835
- };
836
- return [useSkill, removeSkill];
837
- }
838
- function parseArgs(raw) {
839
- const args = [];
840
- let current = ``;
841
- let inQuote = false;
842
- let quoteChar = ``;
843
- for (const ch of raw) if (inQuote) if (ch === quoteChar) inQuote = false;
844
- else current += ch;
845
- else if (ch === `"` || ch === `'`) {
846
- inQuote = true;
847
- quoteChar = ch;
848
- } else if (ch === ` ` || ch === `\t`) {
849
- if (current.length > 0) {
850
- args.push(current);
851
- current = ``;
852
- }
853
- } else current += ch;
854
- if (current.length > 0) args.push(current);
855
- return args;
856
- }
857
- function substituteArgs(content, rawArgs, argNames) {
858
- const parsed = parseArgs(rawArgs);
859
- let result = content;
860
- let matched = false;
861
- if (argNames) for (let i = 0; i < argNames.length && i < parsed.length; i++) {
862
- const pattern = new RegExp(`\\$${argNames[i]}\\b`, `g`);
863
- if (pattern.test(result)) {
864
- result = result.replace(pattern, parsed[i]);
865
- matched = true;
866
- }
867
- }
868
- for (let i = 0; i < parsed.length; i++) {
869
- const pattern = new RegExp(`\\$${i}\\b`, `g`);
870
- if (pattern.test(result)) {
871
- result = result.replace(pattern, parsed[i]);
872
- matched = true;
873
- }
874
- }
875
- if (result.includes(`$ARGUMENTS`)) {
876
- result = result.replace(/\$ARGUMENTS/g, rawArgs);
877
- matched = true;
878
- }
879
- if (!matched) result += `\n\nArguments: ${rawArgs}`;
880
- return result;
881
- }
882
- function listRefFiles(dir, prefix = ``) {
883
- try {
884
- const results = [];
885
- for (const entry of node_fs.default.readdirSync(dir)) {
886
- const full = node_path.default.join(dir, entry);
887
- const rel = prefix ? `${prefix}/${entry}` : entry;
888
- if (node_fs.default.statSync(full).isDirectory()) results.push(...listRefFiles(full, rel));
889
- else results.push(rel);
890
- }
891
- return results;
892
- } catch {
893
- return [];
894
- }
895
- }
896
-
897
719
  //#endregion
898
720
  //#region src/tools/spawn-worker.ts
899
721
  const WORKER_TOOL_NAMES = [
@@ -903,7 +725,8 @@ const WORKER_TOOL_NAMES = [
903
725
  `edit`,
904
726
  `web_search`,
905
727
  `fetch_url`,
906
- `spawn_worker`
728
+ `spawn_worker`,
729
+ `send`
907
730
  ];
908
731
  function createSpawnWorkerTool(ctx, modelConfig) {
909
732
  return {
@@ -1253,6 +1076,7 @@ When a user opens with a greeting ("hi", "hello", "hey", etc.) or a broad statem
1253
1076
  - web_search: search the web
1254
1077
  - fetch_url: fetch and convert a URL to markdown
1255
1078
  - spawn_worker: dispatch a subagent for an isolated task
1079
+ - send: send a message to an Electric Agent/entity by entity URL
1256
1080
  ${docsTools}${skillsTools}
1257
1081
 
1258
1082
  # Working with files
@@ -1300,6 +1124,7 @@ function createHortonTools(workingDirectory, ctx, readSet, opts = {}) {
1300
1124
  logPrefix: opts.logPrefix ?? `[horton]`
1301
1125
  })] : [__electric_ax_agents_runtime_tools.fetchUrlTool],
1302
1126
  createSpawnWorkerTool(ctx, opts.modelConfig),
1127
+ (0, __electric_ax_agents_runtime_tools.createSendTool)(ctx.send),
1303
1128
  ...opts.docsSearchTool ? [opts.docsSearchTool] : []
1304
1129
  ];
1305
1130
  }
@@ -1348,7 +1173,7 @@ function createAssistantHandler(options) {
1348
1173
  modelCatalog,
1349
1174
  logPrefix: `[horton ${ctx.entityUrl}]`
1350
1175
  }),
1351
- ...skillsRegistry && skillsRegistry.catalog.size > 0 ? createSkillTools(skillsRegistry, ctx) : [],
1176
+ ...skillsRegistry && skillsRegistry.catalog.size > 0 ? (0, __electric_ax_agents_runtime.createSkillTools)(skillsRegistry, ctx) : [],
1352
1177
  ...__electric_ax_agents_mcp.mcp.tools()
1353
1178
  ];
1354
1179
  const titlePromise = ctx.firstWake && !ctx.tags.title ? (async () => {
@@ -1548,6 +1373,9 @@ function buildToolsForWorker(tools, workingDirectory, ctx, readSet) {
1548
1373
  case `spawn_worker`:
1549
1374
  out.push(createSpawnWorkerTool(ctx));
1550
1375
  break;
1376
+ case `send`:
1377
+ out.push((0, __electric_ax_agents_runtime_tools.createSendTool)(ctx.send));
1378
+ break;
1551
1379
  }
1552
1380
  return out;
1553
1381
  }
@@ -1672,259 +1500,6 @@ function registerWorker(registry, options) {
1672
1500
  });
1673
1501
  }
1674
1502
 
1675
- //#endregion
1676
- //#region src/skills/preamble.ts
1677
- function parsePreamble(content) {
1678
- const lines = content.split(`\n`);
1679
- if (lines[0]?.trim() !== `---`) return {};
1680
- let closingIndex = -1;
1681
- for (let i = 1; i < Math.min(lines.length, 25); i++) if (lines[i]?.trim() === `---`) {
1682
- closingIndex = i;
1683
- break;
1684
- }
1685
- if (closingIndex === -1) return {};
1686
- const result = {};
1687
- for (let i = 1; i < closingIndex; i++) {
1688
- const line = lines[i];
1689
- const colonIndex = line.indexOf(`:`);
1690
- if (colonIndex === -1) continue;
1691
- const key = line.slice(0, colonIndex).trim();
1692
- const rawValue = line.slice(colonIndex + 1).trim();
1693
- switch (key) {
1694
- case `description`:
1695
- result.description = stripQuotes(rawValue);
1696
- break;
1697
- case `whenToUse`:
1698
- result.whenToUse = stripQuotes(rawValue);
1699
- break;
1700
- case `keywords`: {
1701
- if (rawValue.length === 0) {
1702
- const items = [];
1703
- for (let j = i + 1; j < closingIndex; j++) {
1704
- const next = lines[j];
1705
- const match = next.match(/^\s+-\s+(.+)$/);
1706
- if (match) {
1707
- items.push(match[1].trim());
1708
- i = j;
1709
- } else break;
1710
- }
1711
- result.keywords = items;
1712
- } else result.keywords = parseKeywords(rawValue);
1713
- break;
1714
- }
1715
- case `arguments`: {
1716
- if (rawValue.length === 0) {
1717
- const items = [];
1718
- for (let j = i + 1; j < closingIndex; j++) {
1719
- const next = lines[j];
1720
- const match = next.match(/^\s+-\s+(.+)$/);
1721
- if (match) {
1722
- items.push(match[1].trim());
1723
- i = j;
1724
- } else break;
1725
- }
1726
- result.arguments = items;
1727
- } else result.arguments = parseKeywords(rawValue);
1728
- break;
1729
- }
1730
- case `argument-hint`:
1731
- result.argumentHint = stripQuotes(rawValue);
1732
- break;
1733
- case `user-invocable`:
1734
- result.userInvocable = rawValue === `true`;
1735
- break;
1736
- case `max`: {
1737
- const num = parseInt(rawValue, 10);
1738
- if (!Number.isNaN(num) && num > 0) result.max = num;
1739
- break;
1740
- }
1741
- }
1742
- }
1743
- return result;
1744
- }
1745
- function parseKeywords(raw) {
1746
- const stripped = raw.replace(/^\[/, ``).replace(/\]$/, ``);
1747
- return stripped.split(`,`).map((s) => s.trim()).filter((s) => s.length > 0);
1748
- }
1749
- function stripQuotes(value) {
1750
- if (value.length >= 2 && value.startsWith(`"`) && value.endsWith(`"`)) return value.slice(1, -1);
1751
- return value;
1752
- }
1753
-
1754
- //#endregion
1755
- //#region src/skills/extract-meta.ts
1756
- const DEFAULT_MAX = 1e4;
1757
- async function extractSkillMeta(name, content) {
1758
- const preamble = parsePreamble(content);
1759
- if (preamble.description && preamble.whenToUse && preamble.keywords) return {
1760
- description: preamble.description,
1761
- whenToUse: preamble.whenToUse,
1762
- keywords: preamble.keywords,
1763
- ...preamble.arguments && { arguments: preamble.arguments },
1764
- ...preamble.argumentHint && { argumentHint: preamble.argumentHint },
1765
- ...preamble.userInvocable && { userInvocable: true },
1766
- max: preamble.max ?? DEFAULT_MAX
1767
- };
1768
- try {
1769
- return await llmExtract(name, content, preamble);
1770
- } catch (err) {
1771
- serverLog.warn(`[skills] LLM metadata extraction failed for "${name}": ${err instanceof Error ? err.message : String(err)}`);
1772
- }
1773
- return {
1774
- description: preamble.description ?? humanize(name),
1775
- whenToUse: preamble.whenToUse ?? `User asks about ${humanize(name).toLowerCase()}`,
1776
- keywords: preamble.keywords ?? [name],
1777
- max: preamble.max ?? DEFAULT_MAX
1778
- };
1779
- }
1780
- async function llmExtract(name, content, partial) {
1781
- const truncated = content.slice(0, 8e3);
1782
- const prompt = `Analyze this skill document and extract metadata. The skill is named "${name}".
1783
-
1784
- <skill>
1785
- ${truncated}
1786
- </skill>
1787
-
1788
- Return ONLY a JSON object with these fields:
1789
- - "description": one-line summary of what this skill provides (max 100 chars)
1790
- - "whenToUse": when should an AI agent load this skill (max 200 chars)
1791
- - "keywords": array of 3-8 relevant keywords
1792
-
1793
- Return raw JSON, no markdown fences.`;
1794
- const text = await (0, __electric_ax_agents_runtime.completeWithLowCostModel)({
1795
- purpose: `skill metadata extraction`,
1796
- systemPrompt: `Extract metadata from skill documents. Return only valid JSON that matches the requested schema.`,
1797
- prompt,
1798
- maxTokens: 256,
1799
- log: (message) => serverLog.info(message),
1800
- logPrefix: `[skills]`
1801
- });
1802
- const parsed = JSON.parse(text);
1803
- return {
1804
- description: partial.description ?? parsed.description ?? humanize(name),
1805
- whenToUse: partial.whenToUse ?? parsed.whenToUse ?? `User asks about ${name}`,
1806
- keywords: partial.keywords ?? parsed.keywords ?? [name],
1807
- max: partial.max ?? DEFAULT_MAX
1808
- };
1809
- }
1810
- function humanize(name) {
1811
- return name.replace(/[-_]/g, ` `).replace(/\b\w/g, (c) => c.toUpperCase());
1812
- }
1813
-
1814
- //#endregion
1815
- //#region src/skills/registry.ts
1816
- const CACHE_FILENAME = `skills-cache.json`;
1817
- async function createSkillsRegistry(opts) {
1818
- const { baseSkillsDir, appSkillsDir, cacheDir } = opts;
1819
- const cachePath = node_path.default.join(cacheDir, CACHE_FILENAME);
1820
- const existingCache = await loadCache(cachePath);
1821
- const files = new Map();
1822
- await scanDir(baseSkillsDir, files);
1823
- if (appSkillsDir) await scanDir(appSkillsDir, files);
1824
- const catalog = new Map();
1825
- for (const [name, filePath] of files) {
1826
- const content = await node_fs_promises.default.readFile(filePath, `utf-8`);
1827
- const hash = sha256(content);
1828
- const cached = existingCache[name];
1829
- if (cached && cached.contentHash === hash && cached.source === filePath) {
1830
- catalog.set(name, cached);
1831
- continue;
1832
- }
1833
- serverLog.info(`[skills] extracting metadata for "${name}"`);
1834
- const meta = await extractSkillMeta(name, content);
1835
- const entry = {
1836
- name,
1837
- ...meta,
1838
- charCount: content.length,
1839
- contentHash: hash,
1840
- source: filePath
1841
- };
1842
- catalog.set(name, entry);
1843
- }
1844
- await saveCache(cachePath, catalog, cacheDir);
1845
- return {
1846
- catalog,
1847
- renderCatalog(budget) {
1848
- if (catalog.size === 0) return ``;
1849
- const skills = Array.from(catalog.values());
1850
- const full = renderSkillList(skills, `full`);
1851
- if (!budget || full.length <= budget) return full;
1852
- const compact = renderSkillList(skills, `compact`);
1853
- if (compact.length <= budget) return compact;
1854
- return renderSkillList(skills, `names`);
1855
- },
1856
- async readContent(name) {
1857
- const meta = catalog.get(name);
1858
- if (!meta) return null;
1859
- try {
1860
- return await node_fs_promises.default.readFile(meta.source, `utf-8`);
1861
- } catch {
1862
- return null;
1863
- }
1864
- }
1865
- };
1866
- }
1867
- async function scanDir(dir, out) {
1868
- let entries;
1869
- try {
1870
- entries = await node_fs_promises.default.readdir(dir, { withFileTypes: true });
1871
- } catch {
1872
- return;
1873
- }
1874
- for (const entry of entries) {
1875
- if (!entry.isFile() || !entry.name.endsWith(`.md`)) continue;
1876
- const name = entry.name.slice(0, -3);
1877
- out.set(name, node_path.default.resolve(dir, entry.name));
1878
- }
1879
- }
1880
- async function loadCache(cachePath) {
1881
- try {
1882
- const raw = await node_fs_promises.default.readFile(cachePath, `utf-8`);
1883
- return JSON.parse(raw);
1884
- } catch {
1885
- return {};
1886
- }
1887
- }
1888
- async function saveCache(cachePath, catalog, cacheDir) {
1889
- const obj = {};
1890
- for (const [name, meta] of catalog) obj[name] = meta;
1891
- node_fs.default.mkdirSync(cacheDir, { recursive: true });
1892
- await node_fs_promises.default.writeFile(node_path.default.join(cacheDir, `.gitignore`), `*\n`, `utf-8`);
1893
- await node_fs_promises.default.writeFile(cachePath, JSON.stringify(obj, null, 2), `utf-8`);
1894
- }
1895
- function sha256(content) {
1896
- return (0, node_crypto.createHash)(`sha256`).update(content).digest(`hex`);
1897
- }
1898
- function renderSkillList(skills, mode) {
1899
- const invocable = skills.filter((s) => s.userInvocable);
1900
- const others = skills.filter((s) => !s.userInvocable);
1901
- const lines = [`Available skills:`];
1902
- if (invocable.length > 0 && mode !== `names`) {
1903
- lines.push(`\nUser-invocable (the user can trigger these directly):`);
1904
- for (const meta of invocable) {
1905
- const hint = meta.argumentHint ? ` ${meta.argumentHint}` : ``;
1906
- lines.push(`- /${meta.name}${hint} — ${mode === `compact` ? truncate(meta.description, 100) : meta.description}`);
1907
- }
1908
- if (others.length > 0) lines.push(``);
1909
- }
1910
- const all = mode === `names` ? skills : others.length > 0 ? others : invocable.length === 0 ? skills : [];
1911
- for (const meta of all) {
1912
- if (mode === `names`) {
1913
- const prefix = meta.userInvocable ? `/${meta.name}` : meta.name;
1914
- lines.push(`- ${prefix}: ${truncate(meta.description, 60)}`);
1915
- continue;
1916
- }
1917
- lines.push(`- ${meta.name} (${meta.charCount.toLocaleString()} chars): ${mode === `compact` ? truncate(meta.description, 100) : meta.description}`);
1918
- lines.push(` Use when: ${meta.whenToUse}`);
1919
- if (mode === `full`) lines.push(` Keywords: ${meta.keywords.join(`, `)}`);
1920
- if (meta.argumentHint) lines.push(` Usage: use_skill("${meta.name}", "${meta.argumentHint}")`);
1921
- }
1922
- return lines.join(`\n`);
1923
- }
1924
- function truncate(str, max) {
1925
- return str.length <= max ? str : str.slice(0, max - 3) + `...`;
1926
- }
1927
-
1928
1503
  //#endregion
1929
1504
  //#region src/bootstrap.ts
1930
1505
  const DEFAULT_BUILTIN_AGENT_HANDLER_PATH = `/_electric/builtin-agent-handler`;
@@ -1940,7 +1515,7 @@ async function createBuiltinAgentHandler(options) {
1940
1515
  const baseSkillsDir = baseSkillsDirOverride ?? node_path.default.resolve(here, `../skills`);
1941
1516
  let skillsRegistry = null;
1942
1517
  try {
1943
- skillsRegistry = await createSkillsRegistry({
1518
+ skillsRegistry = await (0, __electric_ax_agents_runtime.createSkillsRegistry)({
1944
1519
  baseSkillsDir,
1945
1520
  appSkillsDir: node_path.default.resolve(cwd, `skills`),
1946
1521
  cacheDir: node_path.default.resolve(cwd, `.electric-agents`)
package/dist/index.d.cts CHANGED
@@ -1,32 +1,10 @@
1
- import { AgentConfig, AgentTool, AvailableProvider, DispatchPolicy, EntityRegistry, EntityStreamDBWithActions, HandlerContext, HeadersProvider, PullWakeRunnerConfig, RuntimeHandler, WakeEvent } from "@electric-ax/agents-runtime";
1
+ import { AgentConfig, AgentTool, AvailableProvider, DispatchPolicy, EntityRegistry, EntityStreamDBWithActions, HandlerContext, HeadersProvider, PullWakeRunnerConfig, RuntimeHandler, SkillsRegistry, WakeEvent } from "@electric-ax/agents-runtime";
2
2
  import { ChangeEvent } from "@durable-streams/state";
3
3
  import { AgentTool as AgentTool$1, StreamFn } from "@mariozechner/pi-agent-core";
4
4
  import { IncomingMessage, ServerResponse } from "node:http";
5
5
  import { ListedEntry as McpListedEntry, McpConfig, McpServerConfig, McpServerConfig as McpServerConfig$1, Registry, Registry as McpRegistry, RegistrySnapshot, RegistrySubscriber } from "@electric-ax/agents-mcp";
6
6
  import { braveSearchTool } from "@electric-ax/agents-runtime/tools";
7
7
 
8
- //#region src/skills/types.d.ts
9
- interface SkillMeta {
10
- name: string;
11
- description: string;
12
- whenToUse: string;
13
- keywords: Array<string>;
14
- arguments?: Array<string>;
15
- argumentHint?: string;
16
- userInvocable?: boolean;
17
- max: number;
18
- charCount: number;
19
- contentHash: string;
20
- source: string;
21
- }
22
- interface SkillsRegistry {
23
- /** All skill metadata, keyed by name. */
24
- catalog: ReadonlyMap<string, SkillMeta>;
25
- /** Render the skill catalog as text for context injection. Fits within budget (chars). */
26
- renderCatalog: (budget?: number) => string;
27
- /** Read skill content from disk. Returns null if skill not found. */
28
- readContent: (name: string) => Promise<string | null>;
29
- } //#endregion
30
8
  //#region src/bootstrap.d.ts
31
9
  declare const DEFAULT_BUILTIN_AGENT_HANDLER_PATH = "/_electric/builtin-agent-handler";
32
10
  interface AgentHandlerResult {
@@ -83,9 +61,7 @@ interface BuiltinAgentHandlerOptions {
83
61
  declare function createBuiltinAgentHandler(options: BuiltinAgentHandlerOptions): Promise<AgentHandlerResult | null>;
84
62
  declare function createAgentHandler(agentServerUrl: string, workingDirectory?: string, streamFn?: StreamFn, createElectricTools?: BuiltinAgentHandlerOptions[`createElectricTools`], serveEndpoint?: string): Promise<AgentHandlerResult | null>;
85
63
  declare function registerBuiltinAgentTypes(bootstrap: AgentHandlerResult): Promise<void>;
86
- declare const registerAgentTypes: typeof registerBuiltinAgentTypes;
87
-
88
- //#endregion
64
+ declare const registerAgentTypes: typeof registerBuiltinAgentTypes; //#endregion
89
65
  //#region src/server.d.ts
90
66
  interface BuiltinAgentsServerOptions {
91
67
  agentServerUrl: string;
@@ -178,9 +154,7 @@ declare class BuiltinAgentsServer {
178
154
  start(): Promise<string>;
179
155
  stop(): Promise<void>;
180
156
  private registerPullWakeRunner;
181
- }
182
-
183
- //#endregion
157
+ } //#endregion
184
158
  //#region src/entrypoint-lib.d.ts
185
159
  type EnvSource = Record<string, string | undefined>;
186
160
  interface BuiltinAgentsEntrypointOptions extends BuiltinAgentsServerOptions {}
@@ -261,7 +235,7 @@ declare function registerWorker(registry: EntityRegistry, options: {
261
235
 
262
236
  //#endregion
263
237
  //#region src/tools/spawn-worker.d.ts
264
- declare const WORKER_TOOL_NAMES: readonly ["bash", "read", "write", "edit", "web_search", "fetch_url", "spawn_worker"];
238
+ declare const WORKER_TOOL_NAMES: readonly ["bash", "read", "write", "edit", "web_search", "fetch_url", "spawn_worker", "send"];
265
239
  type WorkerToolName = (typeof WORKER_TOOL_NAMES)[number];
266
240
  declare function createSpawnWorkerTool(ctx: HandlerContext, modelConfig?: BuiltinAgentModelConfig): AgentTool$1;
267
241
 
package/dist/index.d.ts CHANGED
@@ -1,32 +1,10 @@
1
- import { AgentConfig, AgentTool, AvailableProvider, DispatchPolicy, EntityRegistry, EntityStreamDBWithActions, HandlerContext, HeadersProvider, PullWakeRunnerConfig, RuntimeHandler, WakeEvent } from "@electric-ax/agents-runtime";
1
+ import { AgentConfig, AgentTool, AvailableProvider, DispatchPolicy, EntityRegistry, EntityStreamDBWithActions, HandlerContext, HeadersProvider, PullWakeRunnerConfig, RuntimeHandler, SkillsRegistry, WakeEvent } from "@electric-ax/agents-runtime";
2
2
  import { ChangeEvent } from "@durable-streams/state";
3
3
  import { braveSearchTool } from "@electric-ax/agents-runtime/tools";
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";
7
7
 
8
- //#region src/skills/types.d.ts
9
- interface SkillMeta {
10
- name: string;
11
- description: string;
12
- whenToUse: string;
13
- keywords: Array<string>;
14
- arguments?: Array<string>;
15
- argumentHint?: string;
16
- userInvocable?: boolean;
17
- max: number;
18
- charCount: number;
19
- contentHash: string;
20
- source: string;
21
- }
22
- interface SkillsRegistry {
23
- /** All skill metadata, keyed by name. */
24
- catalog: ReadonlyMap<string, SkillMeta>;
25
- /** Render the skill catalog as text for context injection. Fits within budget (chars). */
26
- renderCatalog: (budget?: number) => string;
27
- /** Read skill content from disk. Returns null if skill not found. */
28
- readContent: (name: string) => Promise<string | null>;
29
- } //#endregion
30
8
  //#region src/bootstrap.d.ts
31
9
  declare const DEFAULT_BUILTIN_AGENT_HANDLER_PATH = "/_electric/builtin-agent-handler";
32
10
  interface AgentHandlerResult {
@@ -83,9 +61,7 @@ interface BuiltinAgentHandlerOptions {
83
61
  declare function createBuiltinAgentHandler(options: BuiltinAgentHandlerOptions): Promise<AgentHandlerResult | null>;
84
62
  declare function createAgentHandler(agentServerUrl: string, workingDirectory?: string, streamFn?: StreamFn, createElectricTools?: BuiltinAgentHandlerOptions[`createElectricTools`], serveEndpoint?: string): Promise<AgentHandlerResult | null>;
85
63
  declare function registerBuiltinAgentTypes(bootstrap: AgentHandlerResult): Promise<void>;
86
- declare const registerAgentTypes: typeof registerBuiltinAgentTypes;
87
-
88
- //#endregion
64
+ declare const registerAgentTypes: typeof registerBuiltinAgentTypes; //#endregion
89
65
  //#region src/server.d.ts
90
66
  interface BuiltinAgentsServerOptions {
91
67
  agentServerUrl: string;
@@ -178,9 +154,7 @@ declare class BuiltinAgentsServer {
178
154
  start(): Promise<string>;
179
155
  stop(): Promise<void>;
180
156
  private registerPullWakeRunner;
181
- }
182
-
183
- //#endregion
157
+ } //#endregion
184
158
  //#region src/entrypoint-lib.d.ts
185
159
  type EnvSource = Record<string, string | undefined>;
186
160
  interface BuiltinAgentsEntrypointOptions extends BuiltinAgentsServerOptions {}
@@ -261,7 +235,7 @@ declare function registerWorker(registry: EntityRegistry, options: {
261
235
 
262
236
  //#endregion
263
237
  //#region src/tools/spawn-worker.d.ts
264
- declare const WORKER_TOOL_NAMES: readonly ["bash", "read", "write", "edit", "web_search", "fetch_url", "spawn_worker"];
238
+ declare const WORKER_TOOL_NAMES: readonly ["bash", "read", "write", "edit", "web_search", "fetch_url", "spawn_worker", "send"];
265
239
  type WorkerToolName = (typeof WORKER_TOOL_NAMES)[number];
266
240
  declare function createSpawnWorkerTool(ctx: HandlerContext, modelConfig?: BuiltinAgentModelConfig): AgentTool$1;
267
241