agent-worker 0.16.0 → 0.17.0
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/cli/index.mjs +646 -95
- package/dist/context-CoRTddGx.mjs +4 -0
- package/dist/index.d.mts +1 -0
- package/dist/{memory-provider-ZLOKyCxA.mjs → memory-provider-Z9D8NdwS.mjs} +1 -1
- package/dist/{runner-IkYhcbio.mjs → runner-BmT0Y8MD.mjs} +2 -2
- package/dist/{workflow-Ctto0bJt.mjs → workflow-LOZUlaDo.mjs} +87 -7
- package/package.json +2 -1
- package/dist/context-CdcZpO-0.mjs +0 -4
package/dist/cli/index.mjs
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { A as parseModel, I as getDefaultModel, L as isAutoProvider, P as createModelAsync, R as resolveModelFallback, a as createMockBackend, j as FRONTIER_MODELS, k as normalizeBackendType, n as createBackend } from "../backends-D7DT0uox.mjs";
|
|
3
3
|
import { t as createTool } from "../create-tool-gcUuI1FD.mjs";
|
|
4
4
|
import { generateText, stepCountIs, tool } from "ai";
|
|
5
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
|
-
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
7
7
|
import { appendFile, mkdir, open, readFile, readdir, stat, unlink, writeFile } from "node:fs/promises";
|
|
8
|
-
import { stringify } from "yaml";
|
|
8
|
+
import { parse, stringify } from "yaml";
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
import { homedir } from "node:os";
|
|
11
11
|
import { execSync, spawn } from "node:child_process";
|
|
@@ -21,6 +21,7 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
21
21
|
import { MockLanguageModelV3, mockValues } from "ai/test";
|
|
22
22
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
23
23
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
24
|
+
import { z as z$1 } from "zod/v4";
|
|
24
25
|
|
|
25
26
|
//#region rolldown:runtime
|
|
26
27
|
var __defProp = Object.defineProperty;
|
|
@@ -1709,76 +1710,106 @@ function formatInbox(inbox) {
|
|
|
1709
1710
|
return `- [${time}] From @${m.entry.from}${priority}${dm}: ${m.entry.content}`;
|
|
1710
1711
|
}).join("\n");
|
|
1711
1712
|
}
|
|
1713
|
+
/** Project context (what codebase to work on) */
|
|
1714
|
+
const projectSection = (ctx) => `## Project\nWorking on: ${ctx.projectDir}`;
|
|
1715
|
+
/** Inbox (unread messages for this agent) */
|
|
1716
|
+
const inboxSection = (ctx) => {
|
|
1717
|
+
const count = ctx.inbox.length;
|
|
1718
|
+
return `## Inbox (${count} ${count === 1 ? "message" : "messages"} for you)\n${formatInbox(ctx.inbox)}`;
|
|
1719
|
+
};
|
|
1720
|
+
/** Recent activity hint (use tool instead of injecting messages) */
|
|
1721
|
+
const activitySection = () => "## Recent Activity\nUse channel_read tool to view recent channel messages and conversation context if needed.";
|
|
1722
|
+
/** Shared document section */
|
|
1723
|
+
const documentSection = (ctx) => ctx.documentContent ? `## Shared Document\n${ctx.documentContent}` : null;
|
|
1724
|
+
/** Retry notice */
|
|
1725
|
+
const retrySection = (ctx) => ctx.retryAttempt > 1 ? `## Note\nThis is retry attempt ${ctx.retryAttempt}. Previous attempt failed.` : null;
|
|
1726
|
+
/** MCP tool instructions */
|
|
1727
|
+
const instructionsSection = (ctx) => {
|
|
1728
|
+
const lines = [];
|
|
1729
|
+
lines.push("## Instructions");
|
|
1730
|
+
lines.push("You are an agent in a multi-agent workflow. Communicate ONLY through the MCP tools below.");
|
|
1731
|
+
lines.push("Your text output is NOT seen by other agents — you MUST use channel_send to communicate.");
|
|
1732
|
+
lines.push("");
|
|
1733
|
+
lines.push("### Channel Tools");
|
|
1734
|
+
lines.push("- **channel_send**: Send a message to the shared channel. Use @agentname to mention/notify.");
|
|
1735
|
+
lines.push(" Use the \"to\" parameter for private DMs: channel_send({ message: \"...\", to: \"bob\" })");
|
|
1736
|
+
lines.push("- **channel_read**: Read recent channel messages (DMs and logs are auto-filtered).");
|
|
1737
|
+
lines.push("");
|
|
1738
|
+
lines.push("### Team Tools");
|
|
1739
|
+
lines.push("- **team_members**: List all agents you can @mention. Pass includeStatus=true to see their current state and tasks.");
|
|
1740
|
+
lines.push("- **team_doc_read/write/append/list/create**: Shared team documents.");
|
|
1741
|
+
lines.push("");
|
|
1742
|
+
lines.push("### Personal Tools");
|
|
1743
|
+
lines.push("- **my_inbox**: Check your unread messages.");
|
|
1744
|
+
lines.push("- **my_inbox_ack**: Acknowledge messages after processing (pass the latest message ID).");
|
|
1745
|
+
lines.push("- **my_status_set**: Update your status. Call when starting work (state='running', task='...') or when done (state='idle').");
|
|
1746
|
+
lines.push("");
|
|
1747
|
+
lines.push("### Proposal & Voting Tools");
|
|
1748
|
+
lines.push("- **team_proposal_create**: Create a proposal for team voting (types: election, decision, approval, assignment).");
|
|
1749
|
+
lines.push("- **team_vote**: Cast your vote on an active proposal. You can change your vote by voting again.");
|
|
1750
|
+
lines.push("- **team_proposal_status**: Check status of a proposal, or list all active proposals.");
|
|
1751
|
+
lines.push("- **team_proposal_cancel**: Cancel a proposal you created.");
|
|
1752
|
+
lines.push("");
|
|
1753
|
+
lines.push("### Resource Tools");
|
|
1754
|
+
lines.push("- **resource_create**: Store large content, get a reference (resource:id) for use anywhere.");
|
|
1755
|
+
lines.push("- **resource_read**: Read resource content by ID.");
|
|
1756
|
+
if (ctx.feedback) {
|
|
1757
|
+
lines.push("");
|
|
1758
|
+
lines.push("### Feedback Tool");
|
|
1759
|
+
lines.push("- **feedback_submit**: Report workflow improvement needs — a missing tool, an awkward step, or a capability gap.");
|
|
1760
|
+
lines.push(" Only use when you genuinely hit a pain point during your work.");
|
|
1761
|
+
}
|
|
1762
|
+
return lines.join("\n");
|
|
1763
|
+
};
|
|
1764
|
+
/** Workflow instructions (read → work → ack → exit) */
|
|
1765
|
+
const workflowSection = () => {
|
|
1766
|
+
const lines = [];
|
|
1767
|
+
lines.push("### Workflow");
|
|
1768
|
+
lines.push("1. Read your inbox messages above");
|
|
1769
|
+
lines.push("2. Do your assigned work using channel_send with @mentions");
|
|
1770
|
+
lines.push("3. Acknowledge your inbox with my_inbox_ack");
|
|
1771
|
+
lines.push("4. Exit when your task is complete");
|
|
1772
|
+
return lines.join("\n");
|
|
1773
|
+
};
|
|
1774
|
+
/** Exit guidance (when to stop) */
|
|
1775
|
+
const exitSection = () => {
|
|
1776
|
+
const lines = [];
|
|
1777
|
+
lines.push("### IMPORTANT: When to stop");
|
|
1778
|
+
lines.push("- Once your assigned task is complete, acknowledge your inbox and exit. Do NOT keep chatting.");
|
|
1779
|
+
lines.push("- Do NOT send pleasantries (\"you're welcome\", \"glad to help\", \"thanks again\") — they trigger unnecessary cycles.");
|
|
1780
|
+
lines.push("- Do NOT @mention another agent in your final message unless you need them to do more work.");
|
|
1781
|
+
lines.push("- If you receive a thank-you or acknowledgment, just call my_inbox_ack and exit. Do not reply.");
|
|
1782
|
+
return lines.join("\n");
|
|
1783
|
+
};
|
|
1712
1784
|
/**
|
|
1713
|
-
*
|
|
1785
|
+
* Default prompt sections — produces the same output as the original
|
|
1786
|
+
* monolithic buildAgentPrompt. New sections (soul, memory, todo) can
|
|
1787
|
+
* be inserted at specific positions without touching these.
|
|
1788
|
+
*/
|
|
1789
|
+
const DEFAULT_SECTIONS = [
|
|
1790
|
+
projectSection,
|
|
1791
|
+
inboxSection,
|
|
1792
|
+
activitySection,
|
|
1793
|
+
documentSection,
|
|
1794
|
+
retrySection,
|
|
1795
|
+
instructionsSection,
|
|
1796
|
+
workflowSection,
|
|
1797
|
+
exitSection
|
|
1798
|
+
];
|
|
1799
|
+
/**
|
|
1800
|
+
* Assemble prompt from sections. Joins non-null sections with blank lines.
|
|
1801
|
+
*/
|
|
1802
|
+
function assemblePrompt(sections, ctx) {
|
|
1803
|
+
return sections.map((section) => section(ctx)).filter((content) => content !== null).join("\n\n");
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Build the complete agent prompt from run context.
|
|
1807
|
+
*
|
|
1808
|
+
* Uses the default section list. For custom section lists,
|
|
1809
|
+
* use assemblePrompt() directly.
|
|
1714
1810
|
*/
|
|
1715
1811
|
function buildAgentPrompt(ctx) {
|
|
1716
|
-
|
|
1717
|
-
sections.push("## Project");
|
|
1718
|
-
sections.push(`Working on: ${ctx.projectDir}`);
|
|
1719
|
-
sections.push("");
|
|
1720
|
-
sections.push(`## Inbox (${ctx.inbox.length} message${ctx.inbox.length === 1 ? "" : "s"} for you)`);
|
|
1721
|
-
sections.push(formatInbox(ctx.inbox));
|
|
1722
|
-
sections.push("");
|
|
1723
|
-
sections.push("## Recent Activity");
|
|
1724
|
-
sections.push("Use channel_read tool to view recent channel messages and conversation context if needed.");
|
|
1725
|
-
if (ctx.documentContent) {
|
|
1726
|
-
sections.push("");
|
|
1727
|
-
sections.push("## Shared Document");
|
|
1728
|
-
sections.push(ctx.documentContent);
|
|
1729
|
-
}
|
|
1730
|
-
if (ctx.retryAttempt > 1) {
|
|
1731
|
-
sections.push("");
|
|
1732
|
-
sections.push(`## Note`);
|
|
1733
|
-
sections.push(`This is retry attempt ${ctx.retryAttempt}. Previous attempt failed.`);
|
|
1734
|
-
}
|
|
1735
|
-
sections.push("");
|
|
1736
|
-
sections.push("## Instructions");
|
|
1737
|
-
sections.push("You are an agent in a multi-agent workflow. Communicate ONLY through the MCP tools below.");
|
|
1738
|
-
sections.push("Your text output is NOT seen by other agents — you MUST use channel_send to communicate.");
|
|
1739
|
-
sections.push("");
|
|
1740
|
-
sections.push("### Channel Tools");
|
|
1741
|
-
sections.push("- **channel_send**: Send a message to the shared channel. Use @agentname to mention/notify.");
|
|
1742
|
-
sections.push(" Use the \"to\" parameter for private DMs: channel_send({ message: \"...\", to: \"bob\" })");
|
|
1743
|
-
sections.push("- **channel_read**: Read recent channel messages (DMs and logs are auto-filtered).");
|
|
1744
|
-
sections.push("");
|
|
1745
|
-
sections.push("### Team Tools");
|
|
1746
|
-
sections.push("- **team_members**: List all agents you can @mention. Pass includeStatus=true to see their current state and tasks.");
|
|
1747
|
-
sections.push("- **team_doc_read/write/append/list/create**: Shared team documents.");
|
|
1748
|
-
sections.push("");
|
|
1749
|
-
sections.push("### Personal Tools");
|
|
1750
|
-
sections.push("- **my_inbox**: Check your unread messages.");
|
|
1751
|
-
sections.push("- **my_inbox_ack**: Acknowledge messages after processing (pass the latest message ID).");
|
|
1752
|
-
sections.push("- **my_status_set**: Update your status. Call when starting work (state='running', task='...') or when done (state='idle').");
|
|
1753
|
-
sections.push("");
|
|
1754
|
-
sections.push("### Proposal & Voting Tools");
|
|
1755
|
-
sections.push("- **team_proposal_create**: Create a proposal for team voting (types: election, decision, approval, assignment).");
|
|
1756
|
-
sections.push("- **team_vote**: Cast your vote on an active proposal. You can change your vote by voting again.");
|
|
1757
|
-
sections.push("- **team_proposal_status**: Check status of a proposal, or list all active proposals.");
|
|
1758
|
-
sections.push("- **team_proposal_cancel**: Cancel a proposal you created.");
|
|
1759
|
-
sections.push("");
|
|
1760
|
-
sections.push("### Resource Tools");
|
|
1761
|
-
sections.push("- **resource_create**: Store large content, get a reference (resource:id) for use anywhere.");
|
|
1762
|
-
sections.push("- **resource_read**: Read resource content by ID.");
|
|
1763
|
-
if (ctx.feedback) {
|
|
1764
|
-
sections.push("");
|
|
1765
|
-
sections.push("### Feedback Tool");
|
|
1766
|
-
sections.push("- **feedback_submit**: Report workflow improvement needs — a missing tool, an awkward step, or a capability gap.");
|
|
1767
|
-
sections.push(" Only use when you genuinely hit a pain point during your work.");
|
|
1768
|
-
}
|
|
1769
|
-
sections.push("");
|
|
1770
|
-
sections.push("### Workflow");
|
|
1771
|
-
sections.push("1. Read your inbox messages above");
|
|
1772
|
-
sections.push("2. Do your assigned work using channel_send with @mentions");
|
|
1773
|
-
sections.push("3. Acknowledge your inbox with my_inbox_ack");
|
|
1774
|
-
sections.push("4. Exit when your task is complete");
|
|
1775
|
-
sections.push("");
|
|
1776
|
-
sections.push("### IMPORTANT: When to stop");
|
|
1777
|
-
sections.push("- Once your assigned task is complete, acknowledge your inbox and exit. Do NOT keep chatting.");
|
|
1778
|
-
sections.push("- Do NOT send pleasantries (\"you're welcome\", \"glad to help\", \"thanks again\") — they trigger unnecessary cycles.");
|
|
1779
|
-
sections.push("- Do NOT @mention another agent in your final message unless you need them to do more work.");
|
|
1780
|
-
sections.push("- If you receive a thank-you or acknowledgment, just call my_inbox_ack and exit. Do not reply.");
|
|
1781
|
-
return sections.join("\n");
|
|
1812
|
+
return assemblePrompt(DEFAULT_SECTIONS, ctx);
|
|
1782
1813
|
}
|
|
1783
1814
|
|
|
1784
1815
|
//#endregion
|
|
@@ -2849,6 +2880,12 @@ var daemon_exports = /* @__PURE__ */ __exportAll({
|
|
|
2849
2880
|
createDaemonApp: () => createDaemonApp,
|
|
2850
2881
|
startDaemon: () => startDaemon
|
|
2851
2882
|
});
|
|
2883
|
+
/** Key prefix for standalone agent workflow handles */
|
|
2884
|
+
const STANDALONE_PREFIX = "standalone:";
|
|
2885
|
+
/** Build a workflow key for standalone agents */
|
|
2886
|
+
function standaloneKey(agentName) {
|
|
2887
|
+
return `${STANDALONE_PREFIX}${agentName}`;
|
|
2888
|
+
}
|
|
2852
2889
|
let state = null;
|
|
2853
2890
|
let shuttingDown = false;
|
|
2854
2891
|
const mcpSessions = /* @__PURE__ */ new Map();
|
|
@@ -2856,6 +2893,10 @@ async function gracefulShutdown() {
|
|
|
2856
2893
|
if (shuttingDown) return;
|
|
2857
2894
|
shuttingDown = true;
|
|
2858
2895
|
if (state) {
|
|
2896
|
+
for (const [, loop] of state.loops) try {
|
|
2897
|
+
await loop.stop();
|
|
2898
|
+
} catch {}
|
|
2899
|
+
state.loops.clear();
|
|
2859
2900
|
for (const [, wf] of state.workflows) try {
|
|
2860
2901
|
await wf.shutdown();
|
|
2861
2902
|
} catch {}
|
|
@@ -2877,8 +2918,8 @@ async function parseJsonBody(c) {
|
|
|
2877
2918
|
return null;
|
|
2878
2919
|
}
|
|
2879
2920
|
}
|
|
2880
|
-
/** Map AgentConfig to the
|
|
2881
|
-
function
|
|
2921
|
+
/** Map AgentConfig to the ResolvedWorkflowAgent type needed by the factory */
|
|
2922
|
+
function configToResolvedWorkflowAgent(cfg) {
|
|
2882
2923
|
return {
|
|
2883
2924
|
backend: cfg.backend,
|
|
2884
2925
|
model: cfg.model,
|
|
@@ -2888,10 +2929,16 @@ function configToResolvedAgent(cfg) {
|
|
|
2888
2929
|
};
|
|
2889
2930
|
}
|
|
2890
2931
|
/**
|
|
2891
|
-
* Find an agent's loop
|
|
2892
|
-
*
|
|
2932
|
+
* Find an agent's loop.
|
|
2933
|
+
* First checks daemon-level loops (standalone agents),
|
|
2934
|
+
* then falls back to workflow-scoped loops (workflow agents).
|
|
2893
2935
|
*/
|
|
2894
2936
|
function findLoop(s, agentName) {
|
|
2937
|
+
const daemonLoop = s.loops.get(agentName);
|
|
2938
|
+
if (daemonLoop) return {
|
|
2939
|
+
loop: daemonLoop,
|
|
2940
|
+
workflow: s.workflows.get(standaloneKey(agentName)) ?? null
|
|
2941
|
+
};
|
|
2895
2942
|
for (const wf of s.workflows.values()) {
|
|
2896
2943
|
const l = wf.loops.get(agentName);
|
|
2897
2944
|
if (l) return {
|
|
@@ -2902,9 +2949,12 @@ function findLoop(s, agentName) {
|
|
|
2902
2949
|
return null;
|
|
2903
2950
|
}
|
|
2904
2951
|
/**
|
|
2905
|
-
* Ensure a standalone agent has a
|
|
2952
|
+
* Ensure a standalone agent has a loop + runtime.
|
|
2906
2953
|
* Creates the infrastructure lazily on first call (starts MCP server, etc.).
|
|
2907
2954
|
*
|
|
2955
|
+
* The loop is stored in `s.loops` (daemon-owned).
|
|
2956
|
+
* A WorkflowHandle is still created for runtime resource management (MCP, context).
|
|
2957
|
+
*
|
|
2908
2958
|
* This is the bridge between POST /agents (stores config only) and
|
|
2909
2959
|
* POST /run or /serve (needs a loop to execute).
|
|
2910
2960
|
*/
|
|
@@ -2913,11 +2963,13 @@ async function ensureAgentLoop(s, agentName) {
|
|
|
2913
2963
|
if (existing) return existing;
|
|
2914
2964
|
const cfg = s.configs.get(agentName);
|
|
2915
2965
|
if (!cfg) throw new Error(`Agent not found: ${agentName}`);
|
|
2916
|
-
const agentDef =
|
|
2917
|
-
const wfKey =
|
|
2966
|
+
const agentDef = configToResolvedWorkflowAgent(cfg);
|
|
2967
|
+
const wfKey = standaloneKey(agentName);
|
|
2968
|
+
const workflowName = cfg.workflow ?? "global";
|
|
2969
|
+
const workflowTag = cfg.tag ?? "main";
|
|
2918
2970
|
const runtime = await createMinimalRuntime({
|
|
2919
|
-
workflowName
|
|
2920
|
-
tag:
|
|
2971
|
+
workflowName,
|
|
2972
|
+
tag: workflowTag,
|
|
2921
2973
|
agentNames: [agentName]
|
|
2922
2974
|
});
|
|
2923
2975
|
let loop;
|
|
@@ -2931,10 +2983,12 @@ async function ensureAgentLoop(s, agentName) {
|
|
|
2931
2983
|
await runtime.shutdown();
|
|
2932
2984
|
throw err;
|
|
2933
2985
|
}
|
|
2986
|
+
s.loops.set(agentName, loop);
|
|
2934
2987
|
const handle = {
|
|
2935
|
-
name:
|
|
2936
|
-
tag:
|
|
2988
|
+
name: workflowName,
|
|
2989
|
+
tag: workflowTag,
|
|
2937
2990
|
key: wfKey,
|
|
2991
|
+
standalone: true,
|
|
2938
2992
|
agents: [agentName],
|
|
2939
2993
|
loops: new Map([[agentName, loop]]),
|
|
2940
2994
|
contextProvider: runtime.contextProvider,
|
|
@@ -2978,7 +3032,7 @@ function createDaemonApp(options) {
|
|
|
2978
3032
|
const s = getState();
|
|
2979
3033
|
if (!s) return c.json({ status: "unavailable" }, 503);
|
|
2980
3034
|
const standaloneAgents = [...s.configs.keys()];
|
|
2981
|
-
const workflowList = [...s.workflows.values()].map((wf) => ({
|
|
3035
|
+
const workflowList = [...s.workflows.values()].filter((wf) => !wf.standalone).map((wf) => ({
|
|
2982
3036
|
name: wf.name,
|
|
2983
3037
|
tag: wf.tag,
|
|
2984
3038
|
agents: wf.agents
|
|
@@ -3032,7 +3086,7 @@ function createDaemonApp(options) {
|
|
|
3032
3086
|
if (!s) return c.json({ error: "Not ready" }, 503);
|
|
3033
3087
|
const body = await parseJsonBody(c);
|
|
3034
3088
|
if (!body || typeof body !== "object") return c.json({ error: "Invalid JSON body" }, 400);
|
|
3035
|
-
const { name, model, system, backend = "default", provider, workflow
|
|
3089
|
+
const { name, model, system, backend = "default", provider, workflow, tag, schedule } = body;
|
|
3036
3090
|
if (!name || !model || !system) return c.json({ error: "name, model, system required" }, 400);
|
|
3037
3091
|
if (s.configs.has(name)) return c.json({ error: `Agent already exists: ${name}` }, 409);
|
|
3038
3092
|
const agentConfig = {
|
|
@@ -3077,7 +3131,14 @@ function createDaemonApp(options) {
|
|
|
3077
3131
|
if (!s) return c.json({ error: "Not ready" }, 503);
|
|
3078
3132
|
const name = c.req.param("name");
|
|
3079
3133
|
if (!s.configs.delete(name)) return c.json({ error: "Agent not found" }, 404);
|
|
3080
|
-
const
|
|
3134
|
+
const daemonLoop = s.loops.get(name);
|
|
3135
|
+
if (daemonLoop) {
|
|
3136
|
+
try {
|
|
3137
|
+
await daemonLoop.stop();
|
|
3138
|
+
} catch {}
|
|
3139
|
+
s.loops.delete(name);
|
|
3140
|
+
}
|
|
3141
|
+
const wfKey = standaloneKey(name);
|
|
3081
3142
|
const wf = s.workflows.get(wfKey);
|
|
3082
3143
|
if (wf) {
|
|
3083
3144
|
try {
|
|
@@ -3231,7 +3292,7 @@ function createDaemonApp(options) {
|
|
|
3231
3292
|
const key = `${workflowName}:${tag}`;
|
|
3232
3293
|
if (s.workflows.has(key)) return c.json({ error: `Workflow already running: ${key}` }, 409);
|
|
3233
3294
|
try {
|
|
3234
|
-
const { runWorkflowWithLoops } = await import("../runner-
|
|
3295
|
+
const { runWorkflowWithLoops } = await import("../runner-BmT0Y8MD.mjs");
|
|
3235
3296
|
const result = await runWorkflowWithLoops({
|
|
3236
3297
|
workflow,
|
|
3237
3298
|
workflowName,
|
|
@@ -3270,7 +3331,7 @@ function createDaemonApp(options) {
|
|
|
3270
3331
|
app.get("/workflows", (c) => {
|
|
3271
3332
|
const s = getState();
|
|
3272
3333
|
if (!s) return c.json({ error: "Not ready" }, 503);
|
|
3273
|
-
const workflows = [...s.workflows.values()].map((wf) => {
|
|
3334
|
+
const workflows = [...s.workflows.values()].filter((wf) => !wf.standalone).map((wf) => {
|
|
3274
3335
|
const agentStates = {};
|
|
3275
3336
|
for (const [name, loop] of wf.loops) agentStates[name] = loop.state;
|
|
3276
3337
|
return {
|
|
@@ -3334,6 +3395,7 @@ async function startDaemon(config = {}) {
|
|
|
3334
3395
|
});
|
|
3335
3396
|
state = {
|
|
3336
3397
|
configs: /* @__PURE__ */ new Map(),
|
|
3398
|
+
loops: /* @__PURE__ */ new Map(),
|
|
3337
3399
|
workflows: /* @__PURE__ */ new Map(),
|
|
3338
3400
|
store,
|
|
3339
3401
|
server,
|
|
@@ -3541,6 +3603,380 @@ function outputJson(data) {
|
|
|
3541
3603
|
console.log(JSON.stringify(data, null, 2));
|
|
3542
3604
|
}
|
|
3543
3605
|
|
|
3606
|
+
//#endregion
|
|
3607
|
+
//#region src/agent/definition.ts
|
|
3608
|
+
/**
|
|
3609
|
+
* AgentDefinition — Top-level persistent agent identity.
|
|
3610
|
+
*
|
|
3611
|
+
* This is the NEW AgentDefinition from AGENT-TOP-LEVEL architecture.
|
|
3612
|
+
* It describes WHO an agent is (prompt, soul, context) — not how it runs in a workflow.
|
|
3613
|
+
*
|
|
3614
|
+
* Loaded from .agents/*.yaml files. Workflows reference agents by name.
|
|
3615
|
+
*
|
|
3616
|
+
* Distinct from:
|
|
3617
|
+
* - WorkflowAgentDef (workflow/types.ts) — inline agent config within a workflow
|
|
3618
|
+
* - AgentConfig (agent/config.ts) — runtime config for daemon-created agents
|
|
3619
|
+
*/
|
|
3620
|
+
/**
|
|
3621
|
+
* Standard subdirectories within an agent's context directory.
|
|
3622
|
+
* Created automatically when the agent is loaded.
|
|
3623
|
+
*/
|
|
3624
|
+
const CONTEXT_SUBDIRS = [
|
|
3625
|
+
"memory",
|
|
3626
|
+
"notes",
|
|
3627
|
+
"conversations",
|
|
3628
|
+
"todo"
|
|
3629
|
+
];
|
|
3630
|
+
const AgentSoulSchema = z$1.object({
|
|
3631
|
+
role: z$1.string().optional(),
|
|
3632
|
+
expertise: z$1.array(z$1.string()).optional(),
|
|
3633
|
+
style: z$1.string().optional(),
|
|
3634
|
+
principles: z$1.array(z$1.string()).optional()
|
|
3635
|
+
}).passthrough();
|
|
3636
|
+
const ProviderConfigSchema = z$1.object({
|
|
3637
|
+
name: z$1.string(),
|
|
3638
|
+
base_url: z$1.string().optional(),
|
|
3639
|
+
api_key: z$1.string().optional()
|
|
3640
|
+
}).passthrough();
|
|
3641
|
+
const AgentPromptConfigSchema = z$1.union([z$1.object({
|
|
3642
|
+
system: z$1.string(),
|
|
3643
|
+
system_file: z$1.undefined().optional()
|
|
3644
|
+
}), z$1.object({
|
|
3645
|
+
system_file: z$1.string(),
|
|
3646
|
+
system: z$1.undefined().optional()
|
|
3647
|
+
})]);
|
|
3648
|
+
const AgentContextConfigSchema = z$1.object({
|
|
3649
|
+
dir: z$1.string().optional(),
|
|
3650
|
+
thin_thread: z$1.number().int().min(1).optional()
|
|
3651
|
+
});
|
|
3652
|
+
const ScheduleConfigSchema = z$1.object({
|
|
3653
|
+
wakeup: z$1.union([z$1.string(), z$1.number()]),
|
|
3654
|
+
prompt: z$1.string().optional()
|
|
3655
|
+
});
|
|
3656
|
+
const AgentDefinitionSchema = z$1.object({
|
|
3657
|
+
name: z$1.string().min(1),
|
|
3658
|
+
model: z$1.string().min(1),
|
|
3659
|
+
backend: z$1.enum([
|
|
3660
|
+
"sdk",
|
|
3661
|
+
"claude",
|
|
3662
|
+
"cursor",
|
|
3663
|
+
"codex",
|
|
3664
|
+
"opencode",
|
|
3665
|
+
"mock"
|
|
3666
|
+
]).optional(),
|
|
3667
|
+
provider: z$1.union([z$1.string(), ProviderConfigSchema]).optional(),
|
|
3668
|
+
prompt: AgentPromptConfigSchema,
|
|
3669
|
+
soul: AgentSoulSchema.optional(),
|
|
3670
|
+
context: AgentContextConfigSchema.optional(),
|
|
3671
|
+
max_tokens: z$1.number().int().positive().optional(),
|
|
3672
|
+
max_steps: z$1.number().int().positive().optional(),
|
|
3673
|
+
schedule: ScheduleConfigSchema.optional()
|
|
3674
|
+
});
|
|
3675
|
+
|
|
3676
|
+
//#endregion
|
|
3677
|
+
//#region src/agent/agent-handle.ts
|
|
3678
|
+
/**
|
|
3679
|
+
* AgentHandle — Runtime wrapper for an agent definition + persistent context.
|
|
3680
|
+
*
|
|
3681
|
+
* Created by AgentRegistry when an agent is loaded. Provides:
|
|
3682
|
+
* - Context directory management (memory/, notes/, conversations/, todo/)
|
|
3683
|
+
* - Read/write operations for personal context
|
|
3684
|
+
* - State tracking (idle, running, stopped, error)
|
|
3685
|
+
*
|
|
3686
|
+
* Phase 1 scope: context directory + read/write ops.
|
|
3687
|
+
* Phase 3 adds: loop, workspaces, threads.
|
|
3688
|
+
*/
|
|
3689
|
+
var AgentHandle = class {
|
|
3690
|
+
/** Agent definition (from YAML) */
|
|
3691
|
+
definition;
|
|
3692
|
+
/** Absolute path to agent's persistent context directory */
|
|
3693
|
+
contextDir;
|
|
3694
|
+
/** Current agent state */
|
|
3695
|
+
state = "idle";
|
|
3696
|
+
constructor(definition, contextDir) {
|
|
3697
|
+
this.definition = definition;
|
|
3698
|
+
this.contextDir = contextDir;
|
|
3699
|
+
}
|
|
3700
|
+
/** Agent name (convenience accessor) */
|
|
3701
|
+
get name() {
|
|
3702
|
+
return this.definition.name;
|
|
3703
|
+
}
|
|
3704
|
+
/**
|
|
3705
|
+
* Ensure the context directory and all subdirectories exist.
|
|
3706
|
+
* Called on agent load/creation. Idempotent.
|
|
3707
|
+
*/
|
|
3708
|
+
ensureContextDir() {
|
|
3709
|
+
for (const sub of CONTEXT_SUBDIRS) mkdirSync(join(this.contextDir, sub), { recursive: true });
|
|
3710
|
+
}
|
|
3711
|
+
/**
|
|
3712
|
+
* Read all memory entries as key-value records.
|
|
3713
|
+
* Memory files are YAML in memory/<key>.yaml.
|
|
3714
|
+
*/
|
|
3715
|
+
async readMemory() {
|
|
3716
|
+
const memDir = join(this.contextDir, "memory");
|
|
3717
|
+
if (!existsSync(memDir)) return {};
|
|
3718
|
+
const result = {};
|
|
3719
|
+
const files = await readdir(memDir);
|
|
3720
|
+
for (const file of files) {
|
|
3721
|
+
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
|
|
3722
|
+
const key = basename(file).replace(/\.ya?ml$/i, "");
|
|
3723
|
+
try {
|
|
3724
|
+
result[key] = parse(await readFile(join(memDir, file), "utf-8"));
|
|
3725
|
+
} catch (err) {
|
|
3726
|
+
console.warn(`Skipping malformed memory file ${file}:`, err);
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
return result;
|
|
3730
|
+
}
|
|
3731
|
+
/**
|
|
3732
|
+
* Write a memory entry. Creates/overwrites memory/<key>.yaml.
|
|
3733
|
+
*/
|
|
3734
|
+
async writeMemory(key, value) {
|
|
3735
|
+
const memDir = join(this.contextDir, "memory");
|
|
3736
|
+
await mkdir(memDir, { recursive: true });
|
|
3737
|
+
await writeFile(join(memDir, `${key}.yaml`), stringify(value));
|
|
3738
|
+
}
|
|
3739
|
+
/**
|
|
3740
|
+
* Read agent's notes, most recent first.
|
|
3741
|
+
* Notes are markdown files in notes/.
|
|
3742
|
+
*/
|
|
3743
|
+
async readNotes(limit) {
|
|
3744
|
+
const notesDir = join(this.contextDir, "notes");
|
|
3745
|
+
if (!existsSync(notesDir)) return [];
|
|
3746
|
+
const files = (await readdir(notesDir)).filter((f) => f.endsWith(".md")).sort().reverse();
|
|
3747
|
+
const selected = limit ? files.slice(0, limit) : files;
|
|
3748
|
+
return Promise.all(selected.map((f) => readFile(join(notesDir, f), "utf-8")));
|
|
3749
|
+
}
|
|
3750
|
+
/**
|
|
3751
|
+
* Append a note. Creates notes/<date>-<slug>.md.
|
|
3752
|
+
*/
|
|
3753
|
+
async appendNote(content, slug) {
|
|
3754
|
+
const notesDir = join(this.contextDir, "notes");
|
|
3755
|
+
await mkdir(notesDir, { recursive: true });
|
|
3756
|
+
const filename = `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slug ?? `note-${Date.now().toString(36)}`}.md`;
|
|
3757
|
+
await writeFile(join(notesDir, filename), content);
|
|
3758
|
+
return filename;
|
|
3759
|
+
}
|
|
3760
|
+
/**
|
|
3761
|
+
* Read active todos from todo/index.md.
|
|
3762
|
+
* Returns lines that look like incomplete tasks: "- [ ] ..."
|
|
3763
|
+
*/
|
|
3764
|
+
async readTodos() {
|
|
3765
|
+
const todoFile = join(this.contextDir, "todo", "index.md");
|
|
3766
|
+
if (!existsSync(todoFile)) return [];
|
|
3767
|
+
return (await readFile(todoFile, "utf-8")).split("\n").filter((line) => line.match(/^\s*-\s*\[\s*\]/)).map((line) => line.replace(/^\s*-\s*\[\s*\]\s*/, "").trim());
|
|
3768
|
+
}
|
|
3769
|
+
/**
|
|
3770
|
+
* Write the full todo list. Replaces todo/index.md.
|
|
3771
|
+
*/
|
|
3772
|
+
async writeTodos(todos) {
|
|
3773
|
+
const todoDir = join(this.contextDir, "todo");
|
|
3774
|
+
await mkdir(todoDir, { recursive: true });
|
|
3775
|
+
const content = todos.map((t) => `- [ ] ${t}`).join("\n") + "\n";
|
|
3776
|
+
await writeFile(join(todoDir, "index.md"), content);
|
|
3777
|
+
}
|
|
3778
|
+
};
|
|
3779
|
+
|
|
3780
|
+
//#endregion
|
|
3781
|
+
//#region src/agent/yaml-parser.ts
|
|
3782
|
+
/**
|
|
3783
|
+
* Agent YAML Parser — Load agent definitions from .agents/*.yaml files.
|
|
3784
|
+
*
|
|
3785
|
+
* Handles:
|
|
3786
|
+
* - Single file: parseAgentFile("path/to/alice.yaml")
|
|
3787
|
+
* - Directory: discoverAgents("path/to/project") → scans .agents/*.yaml
|
|
3788
|
+
* - Validation: Zod schema + semantic checks (system XOR system_file)
|
|
3789
|
+
* - Resolution: system_file → reads content into system (relative to YAML dir)
|
|
3790
|
+
*
|
|
3791
|
+
* The name field is optional in YAML — defaults to filename (without .yaml).
|
|
3792
|
+
*/
|
|
3793
|
+
/** Default directory for agent definitions (relative to project root) */
|
|
3794
|
+
const AGENTS_DIR = ".agents";
|
|
3795
|
+
/**
|
|
3796
|
+
* Parse an agent definition from a YAML file.
|
|
3797
|
+
*
|
|
3798
|
+
* Validates the schema, resolves system_file to inline content,
|
|
3799
|
+
* and infers name from filename if not specified.
|
|
3800
|
+
*
|
|
3801
|
+
* @throws Error if file doesn't exist, YAML is malformed, or validation fails.
|
|
3802
|
+
*/
|
|
3803
|
+
function parseAgentFile(filePath) {
|
|
3804
|
+
if (!existsSync(filePath)) throw new Error(`Agent file not found: ${filePath}`);
|
|
3805
|
+
const data = parse(readFileSync(filePath, "utf-8"));
|
|
3806
|
+
if (!data || typeof data !== "object") throw new Error(`Invalid YAML in ${filePath}: expected an object`);
|
|
3807
|
+
const obj = data;
|
|
3808
|
+
if (!obj.name) obj.name = basename(filePath).replace(/\.ya?ml$/i, "");
|
|
3809
|
+
const result = AgentDefinitionSchema.safeParse(obj);
|
|
3810
|
+
if (!result.success) {
|
|
3811
|
+
const issues = result.error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
3812
|
+
throw new Error(`Invalid agent definition in ${filePath}:\n${issues}`);
|
|
3813
|
+
}
|
|
3814
|
+
const def = result.data;
|
|
3815
|
+
if (def.prompt.system_file) {
|
|
3816
|
+
const promptPath = join(dirname(filePath), def.prompt.system_file);
|
|
3817
|
+
if (!existsSync(promptPath)) throw new Error(`system_file not found: ${def.prompt.system_file} (resolved: ${promptPath})`);
|
|
3818
|
+
const content = readFileSync(promptPath, "utf-8");
|
|
3819
|
+
return {
|
|
3820
|
+
...def,
|
|
3821
|
+
prompt: { system: content }
|
|
3822
|
+
};
|
|
3823
|
+
}
|
|
3824
|
+
return def;
|
|
3825
|
+
}
|
|
3826
|
+
/**
|
|
3827
|
+
* Discover all agent YAML files in a project's .agents/ directory.
|
|
3828
|
+
* Returns parsed and validated definitions.
|
|
3829
|
+
*
|
|
3830
|
+
* Non-fatal: logs warnings for invalid files, skips them.
|
|
3831
|
+
*
|
|
3832
|
+
* @param projectDir - Project root directory
|
|
3833
|
+
* @param log - Optional warning logger (default: console.warn)
|
|
3834
|
+
* @returns Array of valid agent definitions
|
|
3835
|
+
*/
|
|
3836
|
+
function discoverAgents(projectDir, log) {
|
|
3837
|
+
const agentsDir = join(projectDir, AGENTS_DIR);
|
|
3838
|
+
if (!existsSync(agentsDir)) return [];
|
|
3839
|
+
const warn = log ?? console.warn;
|
|
3840
|
+
const agents = [];
|
|
3841
|
+
let entries;
|
|
3842
|
+
try {
|
|
3843
|
+
entries = readdirSync(agentsDir);
|
|
3844
|
+
} catch {
|
|
3845
|
+
return [];
|
|
3846
|
+
}
|
|
3847
|
+
for (const entry of entries) {
|
|
3848
|
+
if (!entry.endsWith(".yaml") && !entry.endsWith(".yml")) continue;
|
|
3849
|
+
const filePath = join(agentsDir, entry);
|
|
3850
|
+
try {
|
|
3851
|
+
agents.push(parseAgentFile(filePath));
|
|
3852
|
+
} catch (err) {
|
|
3853
|
+
warn(`Skipping ${entry}: ${err instanceof Error ? err.message : String(err)}`);
|
|
3854
|
+
}
|
|
3855
|
+
}
|
|
3856
|
+
return agents;
|
|
3857
|
+
}
|
|
3858
|
+
/**
|
|
3859
|
+
* Serialize an agent definition to YAML string.
|
|
3860
|
+
* Used by CLI `agent create` to write .agents/<name>.yaml.
|
|
3861
|
+
*/
|
|
3862
|
+
function serializeAgent(def) {
|
|
3863
|
+
const obj = {
|
|
3864
|
+
name: def.name,
|
|
3865
|
+
model: def.model
|
|
3866
|
+
};
|
|
3867
|
+
if (def.backend) obj.backend = def.backend;
|
|
3868
|
+
if (def.provider) obj.provider = def.provider;
|
|
3869
|
+
obj.prompt = def.prompt;
|
|
3870
|
+
if (def.soul) obj.soul = def.soul;
|
|
3871
|
+
if (def.context) obj.context = def.context;
|
|
3872
|
+
if (def.max_tokens) obj.max_tokens = def.max_tokens;
|
|
3873
|
+
if (def.max_steps) obj.max_steps = def.max_steps;
|
|
3874
|
+
if (def.schedule) obj.schedule = def.schedule;
|
|
3875
|
+
return stringify(obj, { lineWidth: 120 });
|
|
3876
|
+
}
|
|
3877
|
+
|
|
3878
|
+
//#endregion
|
|
3879
|
+
//#region src/agent/agent-registry.ts
|
|
3880
|
+
/**
|
|
3881
|
+
* AgentRegistry — Loads and manages top-level agent definitions.
|
|
3882
|
+
*
|
|
3883
|
+
* Responsibilities:
|
|
3884
|
+
* - Discover agents from .agents/*.yaml
|
|
3885
|
+
* - Load definitions → create AgentHandles
|
|
3886
|
+
* - Register/unregister agents at runtime
|
|
3887
|
+
* - Ensure context directories exist
|
|
3888
|
+
* - Provide agent lookup by name
|
|
3889
|
+
*
|
|
3890
|
+
* Owned by the daemon. One registry per daemon process.
|
|
3891
|
+
*/
|
|
3892
|
+
var AgentRegistry = class {
|
|
3893
|
+
/** Loaded agent handles, keyed by name */
|
|
3894
|
+
agents = /* @__PURE__ */ new Map();
|
|
3895
|
+
/** Project root directory */
|
|
3896
|
+
projectDir;
|
|
3897
|
+
/** Agents directory (.agents/) */
|
|
3898
|
+
agentsDir;
|
|
3899
|
+
constructor(projectDir) {
|
|
3900
|
+
this.projectDir = projectDir;
|
|
3901
|
+
this.agentsDir = join(projectDir, AGENTS_DIR);
|
|
3902
|
+
}
|
|
3903
|
+
/**
|
|
3904
|
+
* Load all agents from .agents/*.yaml.
|
|
3905
|
+
* Skips invalid files (logs warnings).
|
|
3906
|
+
* Creates context directories for each loaded agent.
|
|
3907
|
+
*/
|
|
3908
|
+
loadFromDisk(log) {
|
|
3909
|
+
const defs = discoverAgents(this.projectDir, log);
|
|
3910
|
+
for (const def of defs) this.registerDefinition(def);
|
|
3911
|
+
}
|
|
3912
|
+
/**
|
|
3913
|
+
* Register an agent definition. Creates AgentHandle + ensures context dir.
|
|
3914
|
+
* Overwrites existing agent with same name (reload semantics).
|
|
3915
|
+
*/
|
|
3916
|
+
registerDefinition(def) {
|
|
3917
|
+
const handle = new AgentHandle(def, this.resolveContextDir(def));
|
|
3918
|
+
handle.ensureContextDir();
|
|
3919
|
+
this.agents.set(def.name, handle);
|
|
3920
|
+
return handle;
|
|
3921
|
+
}
|
|
3922
|
+
/**
|
|
3923
|
+
* Create a new agent: write YAML file + register.
|
|
3924
|
+
* @throws Error if agent already exists on disk.
|
|
3925
|
+
*/
|
|
3926
|
+
create(def) {
|
|
3927
|
+
const yamlPath = this.agentYamlPath(def.name);
|
|
3928
|
+
if (existsSync(yamlPath)) throw new Error(`Agent file already exists: ${yamlPath}`);
|
|
3929
|
+
mkdirSync(this.agentsDir, { recursive: true });
|
|
3930
|
+
writeFileSync(yamlPath, serializeAgent(def));
|
|
3931
|
+
return this.registerDefinition(def);
|
|
3932
|
+
}
|
|
3933
|
+
/**
|
|
3934
|
+
* Delete an agent: remove YAML file + context directory + unregister.
|
|
3935
|
+
* @returns true if agent existed and was deleted.
|
|
3936
|
+
*/
|
|
3937
|
+
delete(name) {
|
|
3938
|
+
const handle = this.agents.get(name);
|
|
3939
|
+
if (!handle) return false;
|
|
3940
|
+
this.agents.delete(name);
|
|
3941
|
+
const yamlPath = this.agentYamlPath(name);
|
|
3942
|
+
if (existsSync(yamlPath)) try {
|
|
3943
|
+
unlinkSync(yamlPath);
|
|
3944
|
+
} catch {}
|
|
3945
|
+
if (existsSync(handle.contextDir)) try {
|
|
3946
|
+
rmSync(handle.contextDir, {
|
|
3947
|
+
recursive: true,
|
|
3948
|
+
force: true
|
|
3949
|
+
});
|
|
3950
|
+
} catch {}
|
|
3951
|
+
return true;
|
|
3952
|
+
}
|
|
3953
|
+
/** Get agent handle by name */
|
|
3954
|
+
get(name) {
|
|
3955
|
+
return this.agents.get(name);
|
|
3956
|
+
}
|
|
3957
|
+
/** Check if agent exists */
|
|
3958
|
+
has(name) {
|
|
3959
|
+
return this.agents.has(name);
|
|
3960
|
+
}
|
|
3961
|
+
/** List all registered agent handles */
|
|
3962
|
+
list() {
|
|
3963
|
+
return [...this.agents.values()];
|
|
3964
|
+
}
|
|
3965
|
+
/** Number of registered agents */
|
|
3966
|
+
get size() {
|
|
3967
|
+
return this.agents.size;
|
|
3968
|
+
}
|
|
3969
|
+
/** Resolve agent's context directory (absolute path) */
|
|
3970
|
+
resolveContextDir(def) {
|
|
3971
|
+
if (def.context?.dir) return join(this.projectDir, def.context.dir);
|
|
3972
|
+
return join(this.agentsDir, def.name);
|
|
3973
|
+
}
|
|
3974
|
+
/** Path to agent's YAML file */
|
|
3975
|
+
agentYamlPath(name) {
|
|
3976
|
+
return join(this.agentsDir, `${name}.yaml`);
|
|
3977
|
+
}
|
|
3978
|
+
};
|
|
3979
|
+
|
|
3544
3980
|
//#endregion
|
|
3545
3981
|
//#region src/cli/commands/agent.ts
|
|
3546
3982
|
var agent_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -3655,7 +4091,7 @@ Examples:
|
|
|
3655
4091
|
return;
|
|
3656
4092
|
}
|
|
3657
4093
|
for (const a of agents) {
|
|
3658
|
-
const wf = a.tag === "main" ? `@${a.workflow}` : `@${a.workflow}:${a.tag}
|
|
4094
|
+
const wf = a.workflow ? a.tag === "main" ? `@${a.workflow}` : `@${a.workflow}:${a.tag}` : "";
|
|
3659
4095
|
const info = a.model || a.state || "";
|
|
3660
4096
|
console.log(`${a.name.padEnd(12)} ${info.padEnd(30)} ${wf}`);
|
|
3661
4097
|
}
|
|
@@ -3753,6 +4189,121 @@ Examples:
|
|
|
3753
4189
|
process.exit(1);
|
|
3754
4190
|
} else console.log(res.content ?? JSON.stringify(res));
|
|
3755
4191
|
});
|
|
4192
|
+
const agentCmd = program.command("agent").description("Manage persistent agent definitions (.agents/*.yaml)");
|
|
4193
|
+
agentCmd.command("create <name>").description("Create a persistent agent definition").option("-m, --model <model>", `Model (default: ${getDefaultModel()})`).addOption(new Option("-b, --backend <type>", "Backend type").choices([
|
|
4194
|
+
"sdk",
|
|
4195
|
+
"claude",
|
|
4196
|
+
"codex",
|
|
4197
|
+
"cursor",
|
|
4198
|
+
"opencode",
|
|
4199
|
+
"mock"
|
|
4200
|
+
]).default(void 0)).option("-s, --system <prompt>", "System prompt").option("-f, --system-file <file>", "Read system prompt from file").option("--role <role>", "Soul: agent role").option("--expertise <items>", "Soul: expertise (comma-separated)").option("--style <style>", "Soul: communication style").option("--dir <path>", "Project directory", ".").option("--json", "Output as JSON").addHelpText("after", `
|
|
4201
|
+
Creates .agents/<name>.yaml and context directory (.agents/<name>/).
|
|
4202
|
+
|
|
4203
|
+
Examples:
|
|
4204
|
+
$ agent-worker agent create alice -m anthropic/claude-sonnet-4-5 -s "You are a code reviewer."
|
|
4205
|
+
$ agent-worker agent create bob --role developer --expertise "typescript,testing"
|
|
4206
|
+
$ agent-worker agent create coder -f ./prompts/coder.md
|
|
4207
|
+
`).action(async (name, options) => {
|
|
4208
|
+
const registry = new AgentRegistry(resolve(options.dir));
|
|
4209
|
+
let system = options.system ?? "You are a helpful assistant.";
|
|
4210
|
+
if (options.systemFile) system = readFileSync(options.systemFile, "utf-8");
|
|
4211
|
+
const def = {
|
|
4212
|
+
name,
|
|
4213
|
+
model: options.model || getDefaultModel(),
|
|
4214
|
+
prompt: { system }
|
|
4215
|
+
};
|
|
4216
|
+
if (options.backend) def.backend = options.backend;
|
|
4217
|
+
if (options.role || options.expertise || options.style) {
|
|
4218
|
+
def.soul = {};
|
|
4219
|
+
if (options.role) def.soul.role = options.role;
|
|
4220
|
+
if (options.expertise) def.soul.expertise = options.expertise.split(",").map((s) => s.trim());
|
|
4221
|
+
if (options.style) def.soul.style = options.style;
|
|
4222
|
+
}
|
|
4223
|
+
try {
|
|
4224
|
+
const handle = registry.create(def);
|
|
4225
|
+
if (options.json) outputJson({
|
|
4226
|
+
name,
|
|
4227
|
+
model: def.model,
|
|
4228
|
+
contextDir: handle.contextDir
|
|
4229
|
+
});
|
|
4230
|
+
else {
|
|
4231
|
+
console.log(`Created: .agents/${name}.yaml`);
|
|
4232
|
+
console.log(`Context: ${handle.contextDir}`);
|
|
4233
|
+
}
|
|
4234
|
+
} catch (err) {
|
|
4235
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
4236
|
+
console.error(`Error: ${msg}`);
|
|
4237
|
+
process.exit(1);
|
|
4238
|
+
}
|
|
4239
|
+
});
|
|
4240
|
+
agentCmd.command("list").description("List persistent agent definitions").option("--dir <path>", "Project directory", ".").option("--json", "Output as JSON").action(async (options) => {
|
|
4241
|
+
const registry = new AgentRegistry(resolve(options.dir));
|
|
4242
|
+
registry.loadFromDisk();
|
|
4243
|
+
const agents = registry.list();
|
|
4244
|
+
if (options.json) {
|
|
4245
|
+
outputJson({ agents: agents.map((h) => ({
|
|
4246
|
+
name: h.name,
|
|
4247
|
+
model: h.definition.model,
|
|
4248
|
+
backend: h.definition.backend,
|
|
4249
|
+
soul: h.definition.soul,
|
|
4250
|
+
contextDir: h.contextDir
|
|
4251
|
+
})) });
|
|
4252
|
+
return;
|
|
4253
|
+
}
|
|
4254
|
+
if (agents.length === 0) {
|
|
4255
|
+
console.log("No agent definitions found in .agents/");
|
|
4256
|
+
return;
|
|
4257
|
+
}
|
|
4258
|
+
for (const h of agents) {
|
|
4259
|
+
const soul = h.definition.soul?.role ? ` (${h.definition.soul.role})` : "";
|
|
4260
|
+
console.log(`${h.name.padEnd(16)} ${h.definition.model}${soul}`);
|
|
4261
|
+
}
|
|
4262
|
+
});
|
|
4263
|
+
agentCmd.command("info <name>").description("Show agent definition details").option("--dir <path>", "Project directory", ".").option("--json", "Output as JSON").action(async (name, options) => {
|
|
4264
|
+
const registry = new AgentRegistry(resolve(options.dir));
|
|
4265
|
+
registry.loadFromDisk();
|
|
4266
|
+
const handle = registry.get(name);
|
|
4267
|
+
if (!handle) {
|
|
4268
|
+
console.error(`Agent not found: ${name}`);
|
|
4269
|
+
process.exit(1);
|
|
4270
|
+
}
|
|
4271
|
+
const def = handle.definition;
|
|
4272
|
+
if (options.json) {
|
|
4273
|
+
outputJson({
|
|
4274
|
+
...def,
|
|
4275
|
+
contextDir: handle.contextDir
|
|
4276
|
+
});
|
|
4277
|
+
return;
|
|
4278
|
+
}
|
|
4279
|
+
console.log(`Name: ${def.name}`);
|
|
4280
|
+
console.log(`Model: ${def.model}`);
|
|
4281
|
+
if (def.backend) console.log(`Backend: ${def.backend}`);
|
|
4282
|
+
if (def.prompt.system) {
|
|
4283
|
+
const preview = def.prompt.system.length > 80 ? def.prompt.system.slice(0, 77) + "..." : def.prompt.system;
|
|
4284
|
+
console.log(`Prompt: ${preview}`);
|
|
4285
|
+
}
|
|
4286
|
+
if (def.soul) {
|
|
4287
|
+
if (def.soul.role) console.log(`Role: ${def.soul.role}`);
|
|
4288
|
+
if (def.soul.expertise) console.log(`Expert: ${def.soul.expertise.join(", ")}`);
|
|
4289
|
+
if (def.soul.style) console.log(`Style: ${def.soul.style}`);
|
|
4290
|
+
if (def.soul.principles) {
|
|
4291
|
+
console.log(`Principles:`);
|
|
4292
|
+
for (const p of def.soul.principles) console.log(` - ${p}`);
|
|
4293
|
+
}
|
|
4294
|
+
}
|
|
4295
|
+
console.log(`Context: ${handle.contextDir}`);
|
|
4296
|
+
});
|
|
4297
|
+
agentCmd.command("delete <name>").description("Delete agent definition and context").option("--dir <path>", "Project directory", ".").action(async (name, options) => {
|
|
4298
|
+
const registry = new AgentRegistry(resolve(options.dir));
|
|
4299
|
+
registry.loadFromDisk();
|
|
4300
|
+
if (!registry.has(name)) {
|
|
4301
|
+
console.error(`Agent not found: ${name}`);
|
|
4302
|
+
process.exit(1);
|
|
4303
|
+
}
|
|
4304
|
+
registry.delete(name);
|
|
4305
|
+
console.log(`Deleted: ${name}`);
|
|
4306
|
+
});
|
|
3756
4307
|
}
|
|
3757
4308
|
|
|
3758
4309
|
//#endregion
|
|
@@ -3882,7 +4433,7 @@ Note: Workflow name is inferred from YAML 'name' field or filename.
|
|
|
3882
4433
|
Workflow-defined params (see 'params:' in YAML) are passed after '--'.
|
|
3883
4434
|
Set GITHUB_TOKEN env var to access private repositories.
|
|
3884
4435
|
`).action(async (file, options) => {
|
|
3885
|
-
const { parseWorkflowFile, parseWorkflowParams, formatParamHelp, runWorkflowWithLoops } = await import("../workflow-
|
|
4436
|
+
const { parseWorkflowFile, parseWorkflowParams, formatParamHelp, runWorkflowWithLoops } = await import("../workflow-LOZUlaDo.mjs");
|
|
3886
4437
|
const tag = options.tag || DEFAULT_TAG;
|
|
3887
4438
|
const parsedWorkflow = await parseWorkflowFile(file, { tag });
|
|
3888
4439
|
const workflowName = parsedWorkflow.name;
|
|
@@ -3905,7 +4456,7 @@ Note: Workflow name is inferred from YAML 'name' field or filename.
|
|
|
3905
4456
|
isCleaningUp = true;
|
|
3906
4457
|
console.log("\nInterrupted, cleaning up...");
|
|
3907
4458
|
if (loops) {
|
|
3908
|
-
const { shutdownLoops } = await import("../workflow-
|
|
4459
|
+
const { shutdownLoops } = await import("../workflow-LOZUlaDo.mjs");
|
|
3909
4460
|
const { createSilentLogger } = await Promise.resolve().then(() => logger_exports);
|
|
3910
4461
|
await shutdownLoops(loops, createSilentLogger());
|
|
3911
4462
|
}
|
|
@@ -3980,7 +4531,7 @@ Workflow runs inside the daemon. Use ls/stop to manage:
|
|
|
3980
4531
|
Note: Workflow name is inferred from YAML 'name' field or filename.
|
|
3981
4532
|
Workflow-defined params (see 'params:' in YAML) are passed after '--'.
|
|
3982
4533
|
`).action(async (file, options) => {
|
|
3983
|
-
const { parseWorkflowFile, parseWorkflowParams, formatParamHelp } = await import("../workflow-
|
|
4534
|
+
const { parseWorkflowFile, parseWorkflowParams, formatParamHelp } = await import("../workflow-LOZUlaDo.mjs");
|
|
3984
4535
|
const { ensureDaemon } = await Promise.resolve().then(() => agent_exports);
|
|
3985
4536
|
const tag = options.tag || DEFAULT_TAG;
|
|
3986
4537
|
const parsedWorkflow = await parseWorkflowFile(file, { tag });
|
|
@@ -4209,7 +4760,7 @@ Examples:
|
|
|
4209
4760
|
$ agent-worker doc read @review:pr-123 # Read specific workflow:tag document
|
|
4210
4761
|
`).action(async (targetInput) => {
|
|
4211
4762
|
const dir = await resolveDir(targetInput);
|
|
4212
|
-
const { createFileContextProvider } = await import("../context-
|
|
4763
|
+
const { createFileContextProvider } = await import("../context-CoRTddGx.mjs");
|
|
4213
4764
|
const content = await createFileContextProvider(dir, []).readDocument();
|
|
4214
4765
|
console.log(content || "(empty document)");
|
|
4215
4766
|
});
|
|
@@ -4227,7 +4778,7 @@ Examples:
|
|
|
4227
4778
|
process.exit(1);
|
|
4228
4779
|
}
|
|
4229
4780
|
const dir = await resolveDir(targetInput);
|
|
4230
|
-
const { createFileContextProvider } = await import("../context-
|
|
4781
|
+
const { createFileContextProvider } = await import("../context-CoRTddGx.mjs");
|
|
4231
4782
|
await createFileContextProvider(dir, []).writeDocument(content);
|
|
4232
4783
|
console.log("Document written");
|
|
4233
4784
|
});
|
|
@@ -4245,7 +4796,7 @@ Examples:
|
|
|
4245
4796
|
process.exit(1);
|
|
4246
4797
|
}
|
|
4247
4798
|
const dir = await resolveDir(targetInput);
|
|
4248
|
-
const { createFileContextProvider } = await import("../context-
|
|
4799
|
+
const { createFileContextProvider } = await import("../context-CoRTddGx.mjs");
|
|
4249
4800
|
await createFileContextProvider(dir, []).appendDocument(content);
|
|
4250
4801
|
console.log("Content appended");
|
|
4251
4802
|
});
|
|
@@ -4259,7 +4810,7 @@ async function resolveDir(targetInput) {
|
|
|
4259
4810
|
|
|
4260
4811
|
//#endregion
|
|
4261
4812
|
//#region package.json
|
|
4262
|
-
var version = "0.
|
|
4813
|
+
var version = "0.17.0";
|
|
4263
4814
|
|
|
4264
4815
|
//#endregion
|
|
4265
4816
|
//#region src/cli/index.ts
|
|
@@ -4289,4 +4840,4 @@ registerDocCommands(program);
|
|
|
4289
4840
|
program.parse();
|
|
4290
4841
|
|
|
4291
4842
|
//#endregion
|
|
4292
|
-
export {
|
|
4843
|
+
export { formatInbox$1 as $, resolveContextDir as A, MENTION_PATTERN as B, retrySection as C, FileContextProvider as D, runWithHttp as E, DefaultChannelStore as F, createResourceRef as G, RESOURCE_PREFIX$1 as H, FileStorage as I, shouldUseResource as J, extractMentions as K, MemoryStorage as L, DefaultResourceStore as M, DefaultDocumentStore as N, createFileContextProvider as O, DefaultInboxStore as P, createLogTool as Q, ContextProviderImpl as R, projectSection as S, LOOP_DEFAULTS as T, RESOURCE_SCHEME as U, MESSAGE_LENGTH_THRESHOLD as V, calculatePriority as W, formatProposal as X, createContextMCPServer as Y, formatProposalList as Z, documentSection as _, getBackendByType as a, inboxSection as b, createAgentLoop as c, generateWorkflowMCPConfig as d, formatToolParams as et, writeBackendMcpConfig as f, buildAgentPrompt as g, assemblePrompt as h, createSilentLogger as i, DefaultStatusStore as j, getDefaultContextDir as k, runSdkAgent as l, activitySection as m, createWiredLoop as n, EventLog as nt, getBackendForModel as o, DEFAULT_SECTIONS as p, generateResourceId as q, createChannelLogger as r, checkWorkflowIdle as s, createMinimalRuntime as t, getAgentId as tt, runMockAgent as u, exitSection as v, workflowSection as w, instructionsSection as x, formatInbox as y, CONTEXT_DEFAULTS as z };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { $ as formatInbox, A as resolveContextDir, B as MENTION_PATTERN, D as FileContextProvider, F as DefaultChannelStore, G as createResourceRef, H as RESOURCE_PREFIX, I as FileStorage, J as shouldUseResource, K as extractMentions, L as MemoryStorage, M as DefaultResourceStore, N as DefaultDocumentStore, O as createFileContextProvider, P as DefaultInboxStore, Q as createLogTool, R as ContextProviderImpl, U as RESOURCE_SCHEME, V as MESSAGE_LENGTH_THRESHOLD, W as calculatePriority, X as formatProposal, Y as createContextMCPServer, Z as formatProposalList, et as formatToolParams, j as DefaultStatusStore, k as getDefaultContextDir, nt as EventLog, q as generateResourceId, tt as getAgentId, z as CONTEXT_DEFAULTS } from "./cli/index.mjs";
|
|
2
|
+
import { n as createMemoryContextProvider, t as MemoryContextProvider } from "./memory-provider-Z9D8NdwS.mjs";
|
|
3
|
+
|
|
4
|
+
export { createFileContextProvider };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { F as DefaultChannelStore, L as MemoryStorage, M as DefaultResourceStore, N as DefaultDocumentStore, P as DefaultInboxStore, R as ContextProviderImpl, j as DefaultStatusStore } from "./cli/index.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/workflow/context/memory-provider.ts
|
|
4
4
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./backends-D7DT0uox.mjs";
|
|
2
2
|
import "./create-tool-gcUuI1FD.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { n as createMemoryContextProvider } from "./memory-provider-
|
|
3
|
+
import { D as FileContextProvider, E as runWithHttp, O as createFileContextProvider, Y as createContextMCPServer, i as createSilentLogger, n as createWiredLoop, nt as EventLog, r as createChannelLogger, s as checkWorkflowIdle } from "./cli/index.mjs";
|
|
4
|
+
import { n as createMemoryContextProvider } from "./memory-provider-Z9D8NdwS.mjs";
|
|
5
5
|
import { existsSync, mkdirSync } from "node:fs";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "./backends-D7DT0uox.mjs";
|
|
2
2
|
import "./create-tool-gcUuI1FD.mjs";
|
|
3
|
-
import { a as getBackendByType, b as
|
|
4
|
-
import "./memory-provider-
|
|
5
|
-
import { createWorkflowProvider, initWorkflow, n as interpolate, runWorkflowWithLoops, shutdownLoops, t as createContext } from "./runner-
|
|
3
|
+
import { A as resolveContextDir, C as retrySection, S as projectSection, T as LOOP_DEFAULTS, _ as documentSection, a as getBackendByType, b as inboxSection, c as createAgentLoop, d as generateWorkflowMCPConfig, f as writeBackendMcpConfig, g as buildAgentPrompt, h as assemblePrompt, i as createSilentLogger, l as runSdkAgent, m as activitySection, n as createWiredLoop, o as getBackendForModel, p as DEFAULT_SECTIONS, r as createChannelLogger, s as checkWorkflowIdle, t as createMinimalRuntime, u as runMockAgent, v as exitSection, w as workflowSection, x as instructionsSection, y as formatInbox, z as CONTEXT_DEFAULTS } from "./cli/index.mjs";
|
|
4
|
+
import "./memory-provider-Z9D8NdwS.mjs";
|
|
5
|
+
import { createWorkflowProvider, initWorkflow, n as interpolate, runWorkflowWithLoops, shutdownLoops, t as createContext } from "./runner-BmT0Y8MD.mjs";
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
|
|
7
7
|
import { basename, dirname, join, resolve } from "node:path";
|
|
8
8
|
import { parse } from "yaml";
|
|
@@ -10,6 +10,13 @@ import { homedir } from "node:os";
|
|
|
10
10
|
import { execFileSync } from "node:child_process";
|
|
11
11
|
import { parseArgs } from "node:util";
|
|
12
12
|
|
|
13
|
+
//#region src/workflow/types.ts
|
|
14
|
+
/** Type guard: is this agent entry a reference to a global agent? */
|
|
15
|
+
function isRefAgentEntry(entry) {
|
|
16
|
+
return "ref" in entry && typeof entry.ref === "string";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
13
20
|
//#region src/workflow/source.ts
|
|
14
21
|
/**
|
|
15
22
|
* Workflow source resolver — supports local files and remote GitHub references.
|
|
@@ -263,7 +270,8 @@ async function parseWorkflowFile(filePath, options) {
|
|
|
263
270
|
}
|
|
264
271
|
const name = raw.name || source.inferredName;
|
|
265
272
|
const agents = {};
|
|
266
|
-
for (const [agentName,
|
|
273
|
+
for (const [agentName, entry] of Object.entries(raw.agents)) if (isRefAgentEntry(entry)) agents[agentName] = resolveRefAgent(entry, options?.agentRegistry);
|
|
274
|
+
else agents[agentName] = await resolveInlineAgent(entry, source.readRelativeFile);
|
|
267
275
|
const context = resolveContext(raw.context, contextBaseDir, name, workflow, tag);
|
|
268
276
|
return {
|
|
269
277
|
name,
|
|
@@ -315,14 +323,14 @@ function resolveContext(config, workflowDir, workflowName, workflow, tag) {
|
|
|
315
323
|
};
|
|
316
324
|
}
|
|
317
325
|
/**
|
|
318
|
-
* Resolve agent definition (load system prompt from file if needed).
|
|
326
|
+
* Resolve an inline agent definition (load system prompt from file if needed).
|
|
319
327
|
*
|
|
320
328
|
* Uses a `readRelativeFile` function to abstract local vs remote file access.
|
|
321
329
|
* Also transforms `wakeup` and `wakeup_prompt` fields into a `ScheduleConfig`
|
|
322
330
|
* object, which is the format expected by the daemon and loop layers
|
|
323
331
|
* for setting up periodic wakeup timers.
|
|
324
332
|
*/
|
|
325
|
-
async function
|
|
333
|
+
async function resolveInlineAgent(agent, readRelativeFile) {
|
|
326
334
|
let resolvedSystemPrompt = agent.system_prompt;
|
|
327
335
|
if (resolvedSystemPrompt?.endsWith(".txt") || resolvedSystemPrompt?.endsWith(".md")) {
|
|
328
336
|
const content = await readRelativeFile(resolvedSystemPrompt);
|
|
@@ -336,7 +344,34 @@ async function resolveAgent(agent, readRelativeFile) {
|
|
|
336
344
|
return {
|
|
337
345
|
...agent,
|
|
338
346
|
resolvedSystemPrompt,
|
|
339
|
-
schedule
|
|
347
|
+
schedule,
|
|
348
|
+
isRef: false
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Resolve a ref agent entry — load from AgentRegistry, map to WorkflowAgentDef,
|
|
353
|
+
* apply workflow overrides (prompt.append, max_tokens, max_steps).
|
|
354
|
+
*/
|
|
355
|
+
function resolveRefAgent(entry, registry) {
|
|
356
|
+
if (!registry) throw new Error(`Agent ref "${entry.ref}" requires an AgentRegistry. Pass agentRegistry in ParseOptions.`);
|
|
357
|
+
const handle = registry.get(entry.ref);
|
|
358
|
+
if (!handle) throw new Error(`Agent ref "${entry.ref}" not found in registry. Available agents: ${registry.list().map((h) => h.definition.name).join(", ") || "(none)"}`);
|
|
359
|
+
const def = handle.definition;
|
|
360
|
+
const basePrompt = def.prompt.system ?? "";
|
|
361
|
+
let resolvedSystemPrompt = basePrompt;
|
|
362
|
+
if (entry.prompt?.append) resolvedSystemPrompt = basePrompt ? `${basePrompt}\n\n${entry.prompt.append}` : entry.prompt.append;
|
|
363
|
+
const backend = def.backend === "sdk" ? "default" : def.backend;
|
|
364
|
+
return {
|
|
365
|
+
model: def.model,
|
|
366
|
+
backend,
|
|
367
|
+
provider: def.provider,
|
|
368
|
+
system_prompt: basePrompt,
|
|
369
|
+
max_tokens: entry.max_tokens ?? def.max_tokens,
|
|
370
|
+
max_steps: entry.max_steps ?? def.max_steps,
|
|
371
|
+
schedule: def.schedule,
|
|
372
|
+
resolvedSystemPrompt,
|
|
373
|
+
handle,
|
|
374
|
+
isRef: true
|
|
340
375
|
};
|
|
341
376
|
}
|
|
342
377
|
/**
|
|
@@ -538,6 +573,51 @@ function validateAgent(name, agent, errors) {
|
|
|
538
573
|
return;
|
|
539
574
|
}
|
|
540
575
|
const a = agent;
|
|
576
|
+
if (typeof a.ref === "string") validateRefAgent(path, a, errors);
|
|
577
|
+
else validateInlineAgent(path, a, errors);
|
|
578
|
+
}
|
|
579
|
+
function validateRefAgent(path, a, errors) {
|
|
580
|
+
if (!a.ref.length) errors.push({
|
|
581
|
+
path: `${path}.ref`,
|
|
582
|
+
message: "Field \"ref\" must be a non-empty string"
|
|
583
|
+
});
|
|
584
|
+
if (a.prompt !== void 0) if (typeof a.prompt !== "object" || a.prompt === null) errors.push({
|
|
585
|
+
path: `${path}.prompt`,
|
|
586
|
+
message: "Field \"prompt\" for ref agents must be an object with optional \"append\""
|
|
587
|
+
});
|
|
588
|
+
else {
|
|
589
|
+
const p = a.prompt;
|
|
590
|
+
if (p.append !== void 0 && typeof p.append !== "string") errors.push({
|
|
591
|
+
path: `${path}.prompt.append`,
|
|
592
|
+
message: "Field \"prompt.append\" must be a string"
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
if (a.system_prompt !== void 0) errors.push({
|
|
596
|
+
path: `${path}.system_prompt`,
|
|
597
|
+
message: "Field \"system_prompt\" cannot be used with ref agents — use \"prompt.append\" instead"
|
|
598
|
+
});
|
|
599
|
+
for (const field of [
|
|
600
|
+
"model",
|
|
601
|
+
"backend",
|
|
602
|
+
"provider",
|
|
603
|
+
"tools",
|
|
604
|
+
"wakeup",
|
|
605
|
+
"wakeup_prompt",
|
|
606
|
+
"timeout"
|
|
607
|
+
]) if (a[field] !== void 0) errors.push({
|
|
608
|
+
path: `${path}.${field}`,
|
|
609
|
+
message: `Field "${field}" cannot be used with ref agents — it comes from the agent definition`
|
|
610
|
+
});
|
|
611
|
+
if (a.max_tokens !== void 0 && typeof a.max_tokens !== "number") errors.push({
|
|
612
|
+
path: `${path}.max_tokens`,
|
|
613
|
+
message: "Field \"max_tokens\" must be a number"
|
|
614
|
+
});
|
|
615
|
+
if (a.max_steps !== void 0 && typeof a.max_steps !== "number") errors.push({
|
|
616
|
+
path: `${path}.max_steps`,
|
|
617
|
+
message: "Field \"max_steps\" must be a number"
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
function validateInlineAgent(path, a, errors) {
|
|
541
621
|
const backend = typeof a.backend === "string" ? a.backend : "default";
|
|
542
622
|
if (a.model !== void 0 && typeof a.model !== "string") errors.push({
|
|
543
623
|
path: `${path}.model`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-worker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "SDK and CLI for creating and testing agent workers with Vercel AI SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"format": "oxfmt src",
|
|
30
30
|
"format:check": "oxfmt src --check",
|
|
31
31
|
"typecheck": "tsgo",
|
|
32
|
+
"gen:schema": "bun scripts/gen-workflow-ref.ts > docs/workflow/SCHEMA.md",
|
|
32
33
|
"prepublishOnly": "bun run build"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { A as MENTION_PATTERN, B as formatProposal, C as DefaultDocumentStore, D as MemoryStorage, E as FileStorage, F as createResourceRef, G as getAgentId, H as createLogTool, I as extractMentions, K as EventLog, L as generateResourceId, M as RESOURCE_PREFIX, N as RESOURCE_SCHEME, O as ContextProviderImpl, P as calculatePriority, R as shouldUseResource, S as DefaultResourceStore, T as DefaultChannelStore, U as formatInbox, V as formatProposalList, W as formatToolParams, _ as FileContextProvider, b as resolveContextDir, j as MESSAGE_LENGTH_THRESHOLD, k as CONTEXT_DEFAULTS, v as createFileContextProvider, w as DefaultInboxStore, x as DefaultStatusStore, y as getDefaultContextDir, z as createContextMCPServer } from "./cli/index.mjs";
|
|
2
|
-
import { n as createMemoryContextProvider, t as MemoryContextProvider } from "./memory-provider-ZLOKyCxA.mjs";
|
|
3
|
-
|
|
4
|
-
export { createFileContextProvider };
|