agentix-cli 0.122.0 → 0.123.1
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/{App-2D5W26LY.js → App-NOCRE5SN.js} +2 -2
- package/dist/{ChatApp-FZFZD2XY.js → ChatApp-SETNTMED.js} +2 -2
- package/dist/{agent-PCRE3TRK.js → agent-YII7XBL4.js} +2 -2
- package/dist/{board-dashboard-ZDJ4UDW4.js → board-dashboard-BBLEP7OA.js} +292 -226
- package/dist/board-dashboard-BBLEP7OA.js.map +1 -0
- package/dist/{chunk-YUNMSLZN.js → chunk-22SWFBSL.js} +2 -2
- package/dist/{chunk-2UDSIG5K.js → chunk-27FYNGDW.js} +2 -2
- package/dist/{chunk-TYFGL2YS.js → chunk-AIYI2MFV.js} +2 -2
- package/dist/{chunk-54XX2LSW.js → chunk-AKLZ4YO2.js} +4 -4
- package/dist/{chunk-54XX2LSW.js.map → chunk-AKLZ4YO2.js.map} +1 -1
- package/dist/{chunk-5SLTRG66.js → chunk-DTSKSYEO.js} +2 -2
- package/dist/{chunk-SB7WMFJV.js → chunk-EV2WPHHS.js} +2 -2
- package/dist/chunk-EYIQVQMA.js +37 -0
- package/dist/chunk-EYIQVQMA.js.map +1 -0
- package/dist/{chunk-WJDFR3WE.js → chunk-FQQHUCFN.js} +2 -2
- package/dist/{chunk-NFS2VR3L.js → chunk-GOCYZJMS.js} +2 -2
- package/dist/{chunk-C52IPIKJ.js → chunk-JA6MVY7J.js} +2 -2
- package/dist/{chunk-7ZGTRXWS.js → chunk-KQW2U5MY.js} +2 -2
- package/dist/{chunk-BRVQZC6P.js → chunk-LJ6ORTLS.js} +2 -2
- package/dist/{chunk-ZWZADDXV.js → chunk-LRMUK6DC.js} +2 -2
- package/dist/{chunk-DMPTCBX6.js → chunk-M6WY53GO.js} +3 -3
- package/dist/chunk-M6WY53GO.js.map +1 -0
- package/dist/{chunk-XLCUHG3N.js → chunk-ODGGGU5J.js} +71 -69
- package/dist/chunk-ODGGGU5J.js.map +1 -0
- package/dist/{chunk-XBRVV4ZT.js → chunk-PGXACYDY.js} +2 -2
- package/dist/{chunk-ZLUROC2Y.js → chunk-TEXZEXQZ.js} +10 -10
- package/dist/chunk-TEXZEXQZ.js.map +1 -0
- package/dist/{chunk-EHKI2RKD.js → chunk-TJLTPONY.js} +2 -2
- package/dist/{chunk-XX6MLDTL.js → chunk-UNWXKBRF.js} +2 -2
- package/dist/{chunk-NYAMY7EA.js → chunk-W3DCOYAE.js} +2 -2
- package/dist/{chunk-QCPSGOSK.js → chunk-WEPON4FP.js} +2 -2
- package/dist/{chunk-YCMO3KZ4.js → chunk-WXABFPX7.js} +2 -2
- package/dist/{chunk-UVV6GUOG.js → chunk-XUKBXHTV.js} +256 -254
- package/dist/chunk-XUKBXHTV.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/{client-TFZEASIJ.js → client-S67ZQ5FC.js} +2 -2
- package/dist/{config-IXCOAOPZ.js → config-3AX5MHPN.js} +2 -2
- package/dist/config-mutator-BYFMZQBT.js +2 -0
- package/dist/doctor-KFZLZRUN.js +2 -0
- package/dist/{editor-chat-4MLCP5D2.js → editor-chat-ELKNLXM6.js} +10 -3
- package/dist/{editor-chat-4MLCP5D2.js.map → editor-chat-ELKNLXM6.js.map} +1 -1
- package/dist/follow-up-tool-ZVEYUJ6U.js +6 -0
- package/dist/follow-up-tool-ZVEYUJ6U.js.map +1 -0
- package/dist/{grants-NGBKFONG.js → grants-HIFE6L5N.js} +2 -2
- package/dist/index.d.ts +72 -2
- package/dist/index.js +1 -1
- package/dist/{program-CGPPGRMR.js → program-J7ETQWYX.js} +221 -221
- package/dist/program-J7ETQWYX.js.map +1 -0
- package/dist/{promote-VTVIPRTC.js → promote-BQTJNRTG.js} +2 -2
- package/dist/push-bridge-325SXDGN.js +1 -1
- package/dist/{query-3CVDT2GZ.js → query-6YBM4TPV.js} +2 -2
- package/dist/{registry-NOJMMWE3.js → registry-B7OS4AOM.js} +2 -2
- package/dist/{request-planner-E2Q5O66N.js → request-planner-BLULDFMJ.js} +2 -2
- package/dist/{review-candidates-I36HEYKX.js → review-candidates-HMQ6ZXBT.js} +2 -2
- package/dist/routing-WW56ZXGS.js +2 -0
- package/dist/schedule-tool-Y6RMN6ZT.js +2 -0
- package/dist/scheduler-4GB47SDH.js +2 -0
- package/dist/{seat-NGY2BMP6.js → seat-XGANYYMU.js} +2 -2
- package/dist/{select-X7VBGZ6X.js → select-2HW6Q7UX.js} +2 -2
- package/dist/{set-enabled-6NP63KCU.js → set-enabled-N5AGU5AH.js} +2 -2
- package/dist/{tool-WKIF52OH.js → tool-RJHDRV4X.js} +2 -2
- package/dist/{tool-EZIILXYL.js → tool-XRV6IQ2J.js} +2 -2
- package/dist/web/workflow-editor.global.js +1 -1
- package/dist/web/workflow-editor.global.js.map +1 -1
- package/dist/wiki-ZA4FU3PW.js +2 -0
- package/package.json +1 -1
- package/dist/board-dashboard-ZDJ4UDW4.js.map +0 -1
- package/dist/chunk-DMPTCBX6.js.map +0 -1
- package/dist/chunk-TLCURHW3.js +0 -28
- package/dist/chunk-TLCURHW3.js.map +0 -1
- package/dist/chunk-UVV6GUOG.js.map +0 -1
- package/dist/chunk-XLCUHG3N.js.map +0 -1
- package/dist/chunk-ZLUROC2Y.js.map +0 -1
- package/dist/config-mutator-EPYIZVSG.js +0 -2
- package/dist/doctor-G5TM5GVF.js +0 -2
- package/dist/program-CGPPGRMR.js.map +0 -1
- package/dist/routing-KBUZON5R.js +0 -2
- package/dist/schedule-tool-GUHHYYTO.js +0 -2
- package/dist/scheduler-PGUELFMB.js +0 -2
- package/dist/wiki-7BFVMMNR.js +0 -2
- /package/dist/{App-2D5W26LY.js.map → App-NOCRE5SN.js.map} +0 -0
- /package/dist/{ChatApp-FZFZD2XY.js.map → ChatApp-SETNTMED.js.map} +0 -0
- /package/dist/{agent-PCRE3TRK.js.map → agent-YII7XBL4.js.map} +0 -0
- /package/dist/{chunk-YUNMSLZN.js.map → chunk-22SWFBSL.js.map} +0 -0
- /package/dist/{chunk-2UDSIG5K.js.map → chunk-27FYNGDW.js.map} +0 -0
- /package/dist/{chunk-TYFGL2YS.js.map → chunk-AIYI2MFV.js.map} +0 -0
- /package/dist/{chunk-5SLTRG66.js.map → chunk-DTSKSYEO.js.map} +0 -0
- /package/dist/{chunk-SB7WMFJV.js.map → chunk-EV2WPHHS.js.map} +0 -0
- /package/dist/{chunk-WJDFR3WE.js.map → chunk-FQQHUCFN.js.map} +0 -0
- /package/dist/{chunk-NFS2VR3L.js.map → chunk-GOCYZJMS.js.map} +0 -0
- /package/dist/{chunk-C52IPIKJ.js.map → chunk-JA6MVY7J.js.map} +0 -0
- /package/dist/{chunk-7ZGTRXWS.js.map → chunk-KQW2U5MY.js.map} +0 -0
- /package/dist/{chunk-BRVQZC6P.js.map → chunk-LJ6ORTLS.js.map} +0 -0
- /package/dist/{chunk-ZWZADDXV.js.map → chunk-LRMUK6DC.js.map} +0 -0
- /package/dist/{chunk-XBRVV4ZT.js.map → chunk-PGXACYDY.js.map} +0 -0
- /package/dist/{chunk-EHKI2RKD.js.map → chunk-TJLTPONY.js.map} +0 -0
- /package/dist/{chunk-XX6MLDTL.js.map → chunk-UNWXKBRF.js.map} +0 -0
- /package/dist/{chunk-NYAMY7EA.js.map → chunk-W3DCOYAE.js.map} +0 -0
- /package/dist/{chunk-QCPSGOSK.js.map → chunk-WEPON4FP.js.map} +0 -0
- /package/dist/{chunk-YCMO3KZ4.js.map → chunk-WXABFPX7.js.map} +0 -0
- /package/dist/{client-TFZEASIJ.js.map → client-S67ZQ5FC.js.map} +0 -0
- /package/dist/{config-IXCOAOPZ.js.map → config-3AX5MHPN.js.map} +0 -0
- /package/dist/{config-mutator-EPYIZVSG.js.map → config-mutator-BYFMZQBT.js.map} +0 -0
- /package/dist/{doctor-G5TM5GVF.js.map → doctor-KFZLZRUN.js.map} +0 -0
- /package/dist/{grants-NGBKFONG.js.map → grants-HIFE6L5N.js.map} +0 -0
- /package/dist/{promote-VTVIPRTC.js.map → promote-BQTJNRTG.js.map} +0 -0
- /package/dist/{query-3CVDT2GZ.js.map → query-6YBM4TPV.js.map} +0 -0
- /package/dist/{registry-NOJMMWE3.js.map → registry-B7OS4AOM.js.map} +0 -0
- /package/dist/{request-planner-E2Q5O66N.js.map → request-planner-BLULDFMJ.js.map} +0 -0
- /package/dist/{review-candidates-I36HEYKX.js.map → review-candidates-HMQ6ZXBT.js.map} +0 -0
- /package/dist/{routing-KBUZON5R.js.map → routing-WW56ZXGS.js.map} +0 -0
- /package/dist/{schedule-tool-GUHHYYTO.js.map → schedule-tool-Y6RMN6ZT.js.map} +0 -0
- /package/dist/{scheduler-PGUELFMB.js.map → scheduler-4GB47SDH.js.map} +0 -0
- /package/dist/{seat-NGY2BMP6.js.map → seat-XGANYYMU.js.map} +0 -0
- /package/dist/{select-X7VBGZ6X.js.map → select-2HW6Q7UX.js.map} +0 -0
- /package/dist/{set-enabled-6NP63KCU.js.map → set-enabled-N5AGU5AH.js.map} +0 -0
- /package/dist/{tool-WKIF52OH.js.map → tool-RJHDRV4X.js.map} +0 -0
- /package/dist/{tool-EZIILXYL.js.map → tool-XRV6IQ2J.js.map} +0 -0
- /package/dist/{wiki-7BFVMMNR.js.map → wiki-ZA4FU3PW.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{b as o}from"./chunk-JXF54PT7.js";import"./chunk-QIJLFPWE.js";var s=o(process.versions.node);s&&(console.error(s),process.exit(1));var{buildProgram:r}=await import("./program-
|
|
2
|
+
import{b as o}from"./chunk-JXF54PT7.js";import"./chunk-QIJLFPWE.js";var s=o(process.versions.node);s&&(console.error(s),process.exit(1));var{buildProgram:r}=await import("./program-J7ETQWYX.js"),{installCliSignalExit:i}=await import("./signal-exit-WL7G3EEZ.js");i();var e=await r();process.argv.slice(2).length===0?e.outputHelp():e.parse();
|
|
3
3
|
//# sourceMappingURL=cli.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a,b,c,d,e,f,g}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=client-
|
|
1
|
+
import{a,b,c,d,e,f,g}from"./chunk-LJ6ORTLS.js";import"./chunk-TEXZEXQZ.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";export{b as fetchAgents,d as fetchCrons,c as fetchProcesses,e as killProcess,a as resolveConn,f as sendTask,g as streamTask};
|
|
2
|
+
//# sourceMappingURL=client-S67ZQ5FC.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{$ as b,_ as a,aa as c,ba as d,ca as e,da as f,ea as g,fa as h,ga as i,ha as j,ia as k,ja as l,ka as m,la as n,na as o}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=config-
|
|
1
|
+
import{$ as b,_ as a,aa as c,ba as d,ca as e,da as f,ea as g,fa as h,ga as i,ha as j,ia as k,ja as l,ka as m,la as n,na as o}from"./chunk-TEXZEXQZ.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";o();export{a as INTEGRATION_KINDS,j as approvalsConfigSchema,d as callsSchema,c as cameraBotSchema,k as daemonConfigSchema,b as eventSubscriptionSchema,l as expandEnvVars,m as loadDaemonConfig,h as membersConfigSchema,g as peopleConfigSchema,f as personSchema,i as requestStatusConfigSchema,e as requestsConfigSchema,n as validateWorkspaces};
|
|
2
|
+
//# sourceMappingURL=config-3AX5MHPN.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a,b,c,d,e}from"./chunk-UNWXKBRF.js";import"./chunk-TEXZEXQZ.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";export{b as applyConfigMutation,a as findConfigPath,d as getAtPath,c as setAtPath,e as unsetAtPath};
|
|
2
|
+
//# sourceMappingURL=config-mutator-BYFMZQBT.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{b as a,c as b,d as c,e as d,f as e}from"./chunk-W3DCOYAE.js";import"./chunk-S2GAEH2F.js";import"./chunk-JXF54PT7.js";import"./chunk-TEXZEXQZ.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";export{e as daemonVoiceCheck,b as doctor,a as runDoctorChecks,c as runNotificationChecks,d as runReminderChecks};
|
|
2
|
+
//# sourceMappingURL=doctor-KFZLZRUN.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import"./chunk-QIJLFPWE.js";function c(o){let
|
|
2
|
-
`)}function u(o){let
|
|
1
|
+
import"./chunk-QIJLFPWE.js";function c(o){let n=o.store.list().map(t=>({id:t.id,title:t.title})),e=[];if(e.push(a),e.push(""),e.push(i),e.push(""),e.push("# Environment \u2014 only reference values that exist"),e.push(""),e.push("## Available agents (for `agent` nodes)"),o.availableAgents.length===0)e.push(" (none registered \u2014 the user must add an agent first for `agent` nodes to work)");else for(let t of o.availableAgents)e.push(` - \`${t.id}\`${t.description?` \u2014 ${t.description}`:""}`);if(e.push(""),e.push("## Assignees (for `userTask.assignTo`)"),e.push(" Any agent id above, or a plain string naming the person responsible."),e.push(""),e.push("## Available roles (for `userTask.assignTo`)"),e.push(""),e.push("## Available channels (for `action.*` and `trigger.channel`)"),e.push(` ${o.availableChannels.length?o.availableChannels.map(t=>`\`${t}\``).join(", "):"(none live on this node)"}`),e.push(""),e.push("## Existing workflows (for `subProcess.workflowId`)"),n.length===0)e.push(" (no other workflows defined)");else for(let t of n)e.push(` - \`${t.id}\` \u2014 ${t.title}`);e.push(""),o.currentWorkflow&&(e.push("# Current workflow on canvas"),e.push(""),e.push("The user is editing this workflow. Build on it \u2014 do NOT replace it unless they explicitly ask."),e.push(""),e.push("```json"),e.push(JSON.stringify(o.currentWorkflow,null,2)),e.push("```"),e.push("")),e.push("# Conversation"),e.push("");for(let t of o.messages){let r=t.role==="user"?"USER":"ASSISTANT";e.push(`${r}: ${t.content}`),e.push("")}return e.push(l),e.join(`
|
|
2
|
+
`)}function u(o){let n=/```(?:json)?\s*\n([\s\S]*?)```/.exec(o),e=[];n&&e.push(n[1]);let t=o.match(/\{[\s\S]*\}/);t&&e.push(t[0]);for(let r of e)try{let s=JSON.parse(r);if(s&&typeof s=="object"&&"id"in s&&"nodes"in s)return s}catch{}return null}var a=`You are AgentX's workflow author. The user describes a business process in
|
|
3
3
|
plain language; you return a valid V2 workflow JSON that implements it.
|
|
4
4
|
|
|
5
5
|
Read the node catalog below. Prefer the BPM primitives (userTask,
|
|
@@ -65,6 +65,13 @@ for simple message-in \u2192 reply-out automations.`,i=`# V2 Node catalog
|
|
|
65
65
|
- \`signal.wait\` \u2014 pause until matching signal arrives. config: { "name": "approved", "scope": "workflow", "match": { "grantId": "{{trigger.id}}" } }
|
|
66
66
|
- \`timer.boundary\` \u2014 pause for a duration. config: { "after": "PT2H" | "P1D" | 60 (minutes) }
|
|
67
67
|
|
|
68
|
+
## The owner and other people (follow-up steps)
|
|
69
|
+
An edge without fromPort leaves on the main port (yes / sent / reply); add edges with fromPort for the others.
|
|
70
|
+
- \`owner.notify\` \u2014 tell the owner. config: { "text": "Deployed: {{deploy.reply}}" }
|
|
71
|
+
- \`owner.ask\` \u2014 a decision card for the owner; ports yes / no / expired. config: { "ask": "Ship it?", "recommend": "\u2026", "draft"?: "\u2026", "choices"?: ["a","b"] }. Output: { port, choice, text, note }
|
|
72
|
+
- \`person.message\` \u2014 message an employee or client once the owner approves the text (at start or on its own card); ports sent / declined. config: { "to": "Sam", "channel": "telegram", "chatId": "\u2026", "text": "\u2026" }
|
|
73
|
+
- \`person.wait\` \u2014 wait for that person's reply; ports reply / timeout. config: { "reminds": "<person.message id>", "timeout": "2d", "remindAfter": "1d" } (or channel + chatId). Output: { text, from, media }
|
|
74
|
+
|
|
68
75
|
## Actions \u2014 side-effect sinks
|
|
69
76
|
- \`action.send\` \u2014 post a message to any channel. config: { "channel": "telegram"|"whatsapp"|\u2026, "chatId": "{{trigger.chatId}}", "text": "Hi {{classify.reply}}", "accountId"?: "\u2026" }
|
|
70
77
|
- \`action.createIssue\` \u2014 open a GitLab issue. config: { "channel": "gitlab", "project": "acme/web", "title": "\u2026", "description": "\u2026", "labels": ["x"], "assignees": ["user"] }
|
|
@@ -136,4 +143,4 @@ Only reference agent ids, actor ids, role ids, and channel names that
|
|
|
136
143
|
appear in the Environment section above. If the user asks for an agent
|
|
137
144
|
that doesn't exist, tell them which agent to register first. Never
|
|
138
145
|
invent workflowIds for subProcess that aren't in the existing list.`;export{c as buildWorkflowAuthorPrompt,u as extractWorkflowJson};
|
|
139
|
-
//# sourceMappingURL=editor-chat-
|
|
146
|
+
//# sourceMappingURL=editor-chat-ELKNLXM6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/workflows/editor-chat.ts"],"sourcesContent":["import type { Workflow } from \"./types\"\nimport type { WorkflowStore } from \"./store\"\n\n// --- Workflow-builder chat context ---\n//\n// Produces the plain-text prompt the authoring agent reads. Packs\n// *everything* the agent needs to generate a valid V2 workflow JSON on\n// its first try: node catalog with config examples, available agent\n// ids, actor + role ids, channel adapter names, the user's existing\n// workflow list (for subProcess targets), and — when the author is\n// editing — the current workflow JSON as a starting point.\n//\n// The output is deliberately text, not JSON. Agents (LLMs) produce\n// better structured output when the schema is described as prose +\n// examples rather than as raw JSON Schema. The explicit \"reply with a\n// ```json block```\" instruction at the tail is what the API endpoint\n// parses back.\n\nexport interface ChatMessage {\n role: \"user\" | \"assistant\"\n content: string\n}\n\nexport interface BuildContextArgs {\n messages: ChatMessage[]\n store: WorkflowStore\n /** Full list of agent ids + optional descriptions. */\n availableAgents: Array<{ id: string; description?: string; tags?: string[] }>\n /** Adapter names the daemon has live (telegram, whatsapp, gitlab, ...). */\n availableChannels: string[]\n /** The workflow the user is currently editing (if any). */\n currentWorkflow?: Workflow\n}\n\n/** Build the single-string prompt the agent executes. */\nexport function buildWorkflowAuthorPrompt(args: BuildContextArgs): string {\n const workflows = args.store.list().map((w) => ({ id: w.id, title: w.title }))\n\n const parts: string[] = []\n\n parts.push(SYSTEM_HEADER)\n parts.push(\"\")\n parts.push(NODE_CATALOG)\n parts.push(\"\")\n parts.push(\"# Environment — only reference values that exist\")\n parts.push(\"\")\n parts.push(`## Available agents (for \\`agent\\` nodes)`)\n if (args.availableAgents.length === 0) {\n parts.push(\" (none registered — the user must add an agent first for `agent` nodes to work)\")\n } else {\n for (const a of args.availableAgents) {\n parts.push(` - \\`${a.id}\\`${a.description ? ` — ${a.description}` : \"\"}`)\n }\n }\n parts.push(\"\")\n parts.push(\"## Assignees (for `userTask.assignTo`)\")\n parts.push(\" Any agent id above, or a plain string naming the person responsible.\")\n parts.push(\"\")\n parts.push(\"## Available roles (for `userTask.assignTo`)\")\n parts.push(\"\")\n parts.push(\"## Available channels (for `action.*` and `trigger.channel`)\")\n parts.push(` ${args.availableChannels.length ? args.availableChannels.map((c) => `\\`${c}\\``).join(\", \") : \"(none live on this node)\"}`)\n parts.push(\"\")\n parts.push(\"## Existing workflows (for `subProcess.workflowId`)\")\n if (workflows.length === 0) parts.push(\" (no other workflows defined)\")\n else for (const w of workflows) parts.push(` - \\`${w.id}\\` — ${w.title}`)\n parts.push(\"\")\n\n if (args.currentWorkflow) {\n parts.push(\"# Current workflow on canvas\")\n parts.push(\"\")\n parts.push(\"The user is editing this workflow. Build on it — do NOT replace it unless they explicitly ask.\")\n parts.push(\"\")\n parts.push(\"```json\")\n parts.push(JSON.stringify(args.currentWorkflow, null, 2))\n parts.push(\"```\")\n parts.push(\"\")\n }\n\n parts.push(\"# Conversation\")\n parts.push(\"\")\n for (const m of args.messages) {\n const tag = m.role === \"user\" ? \"USER\" : \"ASSISTANT\"\n parts.push(`${tag}: ${m.content}`)\n parts.push(\"\")\n }\n\n parts.push(RESPONSE_RULES)\n return parts.join(\"\\n\")\n}\n\n/** Try to extract a workflow-shaped JSON block from an agent reply. Returns\n * null if no JSON block is present OR the JSON doesn't have the minimum\n * workflow fields (id, nodes). The caller still runs full zod validation\n * before writing. */\nexport function extractWorkflowJson(reply: string): Record<string, unknown> | null {\n // Prefer fenced ```json blocks; fall back to the largest {...} block.\n const fenced = /```(?:json)?\\s*\\n([\\s\\S]*?)```/.exec(reply)\n const candidates: string[] = []\n if (fenced) candidates.push(fenced[1])\n const braceMatch = reply.match(/\\{[\\s\\S]*\\}/)\n if (braceMatch) candidates.push(braceMatch[0])\n\n for (const raw of candidates) {\n try {\n const parsed = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && \"id\" in parsed && \"nodes\" in parsed) {\n return parsed as Record<string, unknown>\n }\n } catch { /* try next */ }\n }\n return null\n}\n\nconst SYSTEM_HEADER = `You are AgentX's workflow author. The user describes a business process in\nplain language; you return a valid V2 workflow JSON that implements it.\n\nRead the node catalog below. Prefer the BPM primitives (userTask,\nsubProcess, signal.emit/wait, timer.boundary, gateway.parallel, rule)\nwhen modelling processes with humans, deadlines, parallel streams, or\nnested activities. Prefer the bot primitives (agent, branch, action.*)\nfor simple message-in → reply-out automations.`\n\nconst NODE_CATALOG = `# V2 Node catalog\n\n## Triggers (exactly one per workflow)\n- \\`trigger.channel\\` — inbound channel event.\n config: { \"source\": \"whatsapp-message\" | \"telegram-message\" | \"slack-message\" | \"discord-message\" | \"gitlab-issue\" | \"gitlab-pipeline\", \"filter\": { \"chat\"?: \"*\", \"project\"?: \"acme/web\", \"labels\"?: [\"x\"] } }\n- \\`trigger.cron\\` — scheduled. config: { \"spec\": \"0 9 * * *\", \"timezone\": \"UTC\" }\n- \\`trigger.hook\\` — subscribes to any on:* hook event. config: { \"event\": \"on:gitlab-issue\" }\n- \\`trigger.poll\\` — runs a registered action every N seconds; one run per NEW item it prints (one JSON object per line). The item is the trigger payload.\n config: { \"actionId\": \"my-list-action\", \"everySeconds\": 60, \"key\": \"id\", \"filter\"?: [ { \"kind\": \"matches\", \"params\": { \"path\": \"text\", \"regex\": \"^@bot\" } } ] }\n- \\`trigger.manual\\` — kicked off by CLI or API. config: {}\n- \\`trigger.form\\` — human fills a form to start. config: { \"form\": FormSchema, \"startableBy\": \"role:public\" }\n\n## Compute\n- \\`agent\\` — run an agent with a templated prompt. Output: { reply, result (parsed RESULT: token), json?, durationMs }.\n config: { \"agentId\": \"<id>\", \"prompt\": \"Classify {{trigger.text}} — reply on one line: RESULT: a|b|c\", \"resultParser\": \"acme-result-token\" | \"json\", \"timeoutMinutes\": 2 }\n- \\`transform\\` — reshape upstream context.\n config: { \"path\": \"trigger.contact.phone\" } OR { \"template\": { \"key\": \"{{trigger.text}}\" } }\n\n## Control flow\n- \\`branch\\` — N-way switch (first match wins).\n config: { \"cases\": [{ \"when\": { \"kind\": \"equals\"|\"contains\"|\"matches\"|\"exists\", \"params\": { \"path\": \"classify.result\", \"value\": \"ok\" } }, \"to\": \"port1\" }], \"default\": \"fallbackPort\" }\n Wire with edges: { \"from\": \"branchId\", \"fromPort\": \"port1\", \"to\": \"nextNode\" }\n- \\`gateway.parallel\\` — fan-out (one → many) or join (many → one).\n config: { \"mode\": \"fanOut\" } — splits to every outgoing edge\n config: { \"mode\": \"join\" } — waits until every incoming edge arrives, then fires once\n- \\`rule\\` — DMN decision table, first matching row wins.\n config: {\n \"inputs\": [\"{{trigger.tier}}\", \"{{trigger.amount}}\"],\n \"rules\": [\n { \"when\": [\"gold\", \">100\"], \"to\": \"vip\", \"output\": { \"route\": \"vip\" } },\n { \"when\": [\"*\", \">50\"], \"to\": \"high\", \"output\": { \"route\": \"high\" } }\n ],\n \"default\": { \"to\": \"low\", \"output\": { \"route\": \"low\" } }\n }\n Cell syntax: \"*\" wildcard, exact \"value\", \">N\" \"<N\" \">=N\" \"<=N\", \"!=x\", \"/regex/\".\n- \\`checkpoint\\` — pause until a matching event.\n config: { \"name\": \"await-x\", \"waitFor\": { \"source\": \"manual\" }, \"resumeMatch\": {} }\n\n## BPM\n- \\`userTask\\` — assign a form to an actor or role; pauses until submission.\n config: {\n \"assignTo\": \"actor:alice\" | \"role:reviewers\",\n \"title\": \"Review expense {{trigger.values.amount}}\",\n \"description\": \"…\",\n \"dueIn\": \"P2D\" | \"PT2H\" | { \"minutes\": 60 },\n \"form\": FormSchema\n }\n Output: { submittedBy, submittedAt, values: { fieldKey: value }, action: \"primary\" | \"secondary\" }\n- \\`subProcess\\` — spawn a child workflow; parent pauses until child reaches end.\n config: {\n \"workflowId\": \"<other workflow id>\",\n \"inputMap\": { \"trigger\": { \"grantee\": \"{{trigger.values.name}}\" } } (or \"*\" for full inherit),\n \"awaitCompletion\": true\n }\n Output: { childRunId, status, output: <child's last bundle> }\n- \\`signal.emit\\` — publish an event. config: { \"name\": \"approved\", \"scope\": \"workflow\"|\"global\", \"payload\": {} }\n- \\`signal.wait\\` — pause until matching signal arrives. config: { \"name\": \"approved\", \"scope\": \"workflow\", \"match\": { \"grantId\": \"{{trigger.id}}\" } }\n- \\`timer.boundary\\` — pause for a duration. config: { \"after\": \"PT2H\" | \"P1D\" | 60 (minutes) }\n\n## Actions — side-effect sinks\n- \\`action.send\\` — post a message to any channel. config: { \"channel\": \"telegram\"|\"whatsapp\"|…, \"chatId\": \"{{trigger.chatId}}\", \"text\": \"Hi {{classify.reply}}\", \"accountId\"?: \"…\" }\n- \\`action.createIssue\\` — open a GitLab issue. config: { \"channel\": \"gitlab\", \"project\": \"acme/web\", \"title\": \"…\", \"description\": \"…\", \"labels\": [\"x\"], \"assignees\": [\"user\"] }\n- \\`action.setLabel\\` / \\`action.readLabel\\` / \\`action.react\\` / \\`action.editMessage\\` / \\`action.logTime\\` — self-explanatory; each maps 1:1 to a channel adapter method.\n- \\`action.callHTTP\\` — outbound HTTP. config: { \"method\": \"POST\"|\"GET\"|…, \"url\": \"https://…\", \"headers\": {}, \"body\": {}, \"timeoutMs\": 30000 }\n\n## Terminal\n- \\`end\\` — completes the run. config: { \"status\": \"completed\" | \"failed\" | \"canceled\" }\n\n## FormSchema (used by userTask + trigger.form)\n{\n \"title\": \"Review application\",\n \"description\": \"…\",\n \"fields\": [\n { \"key\": \"score\", \"label\": \"Score\", \"type\": \"number\", \"required\": true, \"validate\": { \"min\": 1, \"max\": 10 } },\n { \"key\": \"verdict\", \"label\": \"Verdict\", \"type\": \"select\", \"required\": true, \"options\": [\"approve\", \"reject\"] },\n { \"key\": \"notes\", \"label\": \"Notes\", \"type\": \"long-text\" }\n ],\n \"submitLabel\": \"Approve\",\n \"secondaryAction\": { \"key\": \"reject\", \"label\": \"Reject\" }\n}\nField types: text, long-text, number, boolean, date, select, multi-select, file.\nA form with a \\`secondaryAction\\` and no required-unfilled fields renders as one-tap Approve/Reject buttons in chat.\n\n## Templates\nEvery prompt + config value can reference \\`{{nodeId.path}}\\` against the run context. Examples:\n {{trigger.values.amount}} — field from the start form\n {{classify.result}} — parsed RESULT: token from an agent node\n {{review.values.score}} — submitted userTask field\n {{env.GITLAB_TOKEN}} — env var (must be listed in workflow.envAllow)\n\n## Edges\n[{ \"from\": \"nodeId\", \"to\": \"nodeId\" }, { \"from\": \"branchId\", \"fromPort\": \"case-label\", \"to\": \"nodeId\" }]\nEvery edge's from/to must reference an existing node. Branch + rule nodes MUST have outgoing edges whose fromPort matches a declared case/rule/default.\n\n## Workflow shell\n{\n \"id\": \"lower-kebab-id\",\n \"version\": 2,\n \"title\": \"Human readable\",\n \"description\": \"optional\",\n \"priority\": 0,\n \"fanOut\": false,\n \"envAllow\": [],\n \"maxChildDepth\": 5,\n \"retention\": { \"maxRuns\": 500, \"maxDays\": 90 },\n \"nodes\": [...],\n \"edges\": [...]\n}\n\n## Lint rules (all enforced on save)\n- exactly one trigger.* node\n- every edge references an existing node\n- every node is reachable from the trigger\n- at least one end/checkpoint/userTask/subProcess/signal.wait/timer.boundary is reachable\n- branch + rule outgoing fromPort values match declared cases (or default)\n- cycles are only allowed when the cycle crosses an agent/checkpoint/userTask/subProcess/signal.wait/timer.boundary`\n\nconst RESPONSE_RULES = `# Your reply\n\nRespond in ONE of two ways:\n\n1. **Clarification**: if the user's request is ambiguous, ask exactly ONE short follow-up question. No JSON.\n\n2. **Workflow**: if you have enough to produce a workflow, reply with:\n - 1–3 short lines explaining what you built\n - a \\`\\`\\`json code block containing the complete, valid V2 workflow\n - (no prose after the JSON block)\n\nOnly reference agent ids, actor ids, role ids, and channel names that\nappear in the Environment section above. If the user asks for an agent\nthat doesn't exist, tell them which agent to register first. Never\ninvent workflowIds for subProcess that aren't in the existing list.`"],"mappings":"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","names":["buildWorkflowAuthorPrompt","args","workflows","w","parts","SYSTEM_HEADER","NODE_CATALOG","a","c","m","tag","RESPONSE_RULES","extractWorkflowJson","reply","fenced","candidates","braceMatch","raw","parsed"]}
|
|
1
|
+
{"version":3,"sources":["../src/workflows/editor-chat.ts"],"sourcesContent":["import type { Workflow } from \"./types\"\nimport type { WorkflowStore } from \"./store\"\n\n// --- Workflow-builder chat context ---\n//\n// Produces the plain-text prompt the authoring agent reads. Packs\n// *everything* the agent needs to generate a valid V2 workflow JSON on\n// its first try: node catalog with config examples, available agent\n// ids, actor + role ids, channel adapter names, the user's existing\n// workflow list (for subProcess targets), and — when the author is\n// editing — the current workflow JSON as a starting point.\n//\n// The output is deliberately text, not JSON. Agents (LLMs) produce\n// better structured output when the schema is described as prose +\n// examples rather than as raw JSON Schema. The explicit \"reply with a\n// ```json block```\" instruction at the tail is what the API endpoint\n// parses back.\n\nexport interface ChatMessage {\n role: \"user\" | \"assistant\"\n content: string\n}\n\nexport interface BuildContextArgs {\n messages: ChatMessage[]\n store: WorkflowStore\n /** Full list of agent ids + optional descriptions. */\n availableAgents: Array<{ id: string; description?: string; tags?: string[] }>\n /** Adapter names the daemon has live (telegram, whatsapp, gitlab, ...). */\n availableChannels: string[]\n /** The workflow the user is currently editing (if any). */\n currentWorkflow?: Workflow\n}\n\n/** Build the single-string prompt the agent executes. */\nexport function buildWorkflowAuthorPrompt(args: BuildContextArgs): string {\n const workflows = args.store.list().map((w) => ({ id: w.id, title: w.title }))\n\n const parts: string[] = []\n\n parts.push(SYSTEM_HEADER)\n parts.push(\"\")\n parts.push(NODE_CATALOG)\n parts.push(\"\")\n parts.push(\"# Environment — only reference values that exist\")\n parts.push(\"\")\n parts.push(`## Available agents (for \\`agent\\` nodes)`)\n if (args.availableAgents.length === 0) {\n parts.push(\" (none registered — the user must add an agent first for `agent` nodes to work)\")\n } else {\n for (const a of args.availableAgents) {\n parts.push(` - \\`${a.id}\\`${a.description ? ` — ${a.description}` : \"\"}`)\n }\n }\n parts.push(\"\")\n parts.push(\"## Assignees (for `userTask.assignTo`)\")\n parts.push(\" Any agent id above, or a plain string naming the person responsible.\")\n parts.push(\"\")\n parts.push(\"## Available roles (for `userTask.assignTo`)\")\n parts.push(\"\")\n parts.push(\"## Available channels (for `action.*` and `trigger.channel`)\")\n parts.push(` ${args.availableChannels.length ? args.availableChannels.map((c) => `\\`${c}\\``).join(\", \") : \"(none live on this node)\"}`)\n parts.push(\"\")\n parts.push(\"## Existing workflows (for `subProcess.workflowId`)\")\n if (workflows.length === 0) parts.push(\" (no other workflows defined)\")\n else for (const w of workflows) parts.push(` - \\`${w.id}\\` — ${w.title}`)\n parts.push(\"\")\n\n if (args.currentWorkflow) {\n parts.push(\"# Current workflow on canvas\")\n parts.push(\"\")\n parts.push(\"The user is editing this workflow. Build on it — do NOT replace it unless they explicitly ask.\")\n parts.push(\"\")\n parts.push(\"```json\")\n parts.push(JSON.stringify(args.currentWorkflow, null, 2))\n parts.push(\"```\")\n parts.push(\"\")\n }\n\n parts.push(\"# Conversation\")\n parts.push(\"\")\n for (const m of args.messages) {\n const tag = m.role === \"user\" ? \"USER\" : \"ASSISTANT\"\n parts.push(`${tag}: ${m.content}`)\n parts.push(\"\")\n }\n\n parts.push(RESPONSE_RULES)\n return parts.join(\"\\n\")\n}\n\n/** Try to extract a workflow-shaped JSON block from an agent reply. Returns\n * null if no JSON block is present OR the JSON doesn't have the minimum\n * workflow fields (id, nodes). The caller still runs full zod validation\n * before writing. */\nexport function extractWorkflowJson(reply: string): Record<string, unknown> | null {\n // Prefer fenced ```json blocks; fall back to the largest {...} block.\n const fenced = /```(?:json)?\\s*\\n([\\s\\S]*?)```/.exec(reply)\n const candidates: string[] = []\n if (fenced) candidates.push(fenced[1])\n const braceMatch = reply.match(/\\{[\\s\\S]*\\}/)\n if (braceMatch) candidates.push(braceMatch[0])\n\n for (const raw of candidates) {\n try {\n const parsed = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && \"id\" in parsed && \"nodes\" in parsed) {\n return parsed as Record<string, unknown>\n }\n } catch { /* try next */ }\n }\n return null\n}\n\nconst SYSTEM_HEADER = `You are AgentX's workflow author. The user describes a business process in\nplain language; you return a valid V2 workflow JSON that implements it.\n\nRead the node catalog below. Prefer the BPM primitives (userTask,\nsubProcess, signal.emit/wait, timer.boundary, gateway.parallel, rule)\nwhen modelling processes with humans, deadlines, parallel streams, or\nnested activities. Prefer the bot primitives (agent, branch, action.*)\nfor simple message-in → reply-out automations.`\n\nconst NODE_CATALOG = `# V2 Node catalog\n\n## Triggers (exactly one per workflow)\n- \\`trigger.channel\\` — inbound channel event.\n config: { \"source\": \"whatsapp-message\" | \"telegram-message\" | \"slack-message\" | \"discord-message\" | \"gitlab-issue\" | \"gitlab-pipeline\", \"filter\": { \"chat\"?: \"*\", \"project\"?: \"acme/web\", \"labels\"?: [\"x\"] } }\n- \\`trigger.cron\\` — scheduled. config: { \"spec\": \"0 9 * * *\", \"timezone\": \"UTC\" }\n- \\`trigger.hook\\` — subscribes to any on:* hook event. config: { \"event\": \"on:gitlab-issue\" }\n- \\`trigger.poll\\` — runs a registered action every N seconds; one run per NEW item it prints (one JSON object per line). The item is the trigger payload.\n config: { \"actionId\": \"my-list-action\", \"everySeconds\": 60, \"key\": \"id\", \"filter\"?: [ { \"kind\": \"matches\", \"params\": { \"path\": \"text\", \"regex\": \"^@bot\" } } ] }\n- \\`trigger.manual\\` — kicked off by CLI or API. config: {}\n- \\`trigger.form\\` — human fills a form to start. config: { \"form\": FormSchema, \"startableBy\": \"role:public\" }\n\n## Compute\n- \\`agent\\` — run an agent with a templated prompt. Output: { reply, result (parsed RESULT: token), json?, durationMs }.\n config: { \"agentId\": \"<id>\", \"prompt\": \"Classify {{trigger.text}} — reply on one line: RESULT: a|b|c\", \"resultParser\": \"acme-result-token\" | \"json\", \"timeoutMinutes\": 2 }\n- \\`transform\\` — reshape upstream context.\n config: { \"path\": \"trigger.contact.phone\" } OR { \"template\": { \"key\": \"{{trigger.text}}\" } }\n\n## Control flow\n- \\`branch\\` — N-way switch (first match wins).\n config: { \"cases\": [{ \"when\": { \"kind\": \"equals\"|\"contains\"|\"matches\"|\"exists\", \"params\": { \"path\": \"classify.result\", \"value\": \"ok\" } }, \"to\": \"port1\" }], \"default\": \"fallbackPort\" }\n Wire with edges: { \"from\": \"branchId\", \"fromPort\": \"port1\", \"to\": \"nextNode\" }\n- \\`gateway.parallel\\` — fan-out (one → many) or join (many → one).\n config: { \"mode\": \"fanOut\" } — splits to every outgoing edge\n config: { \"mode\": \"join\" } — waits until every incoming edge arrives, then fires once\n- \\`rule\\` — DMN decision table, first matching row wins.\n config: {\n \"inputs\": [\"{{trigger.tier}}\", \"{{trigger.amount}}\"],\n \"rules\": [\n { \"when\": [\"gold\", \">100\"], \"to\": \"vip\", \"output\": { \"route\": \"vip\" } },\n { \"when\": [\"*\", \">50\"], \"to\": \"high\", \"output\": { \"route\": \"high\" } }\n ],\n \"default\": { \"to\": \"low\", \"output\": { \"route\": \"low\" } }\n }\n Cell syntax: \"*\" wildcard, exact \"value\", \">N\" \"<N\" \">=N\" \"<=N\", \"!=x\", \"/regex/\".\n- \\`checkpoint\\` — pause until a matching event.\n config: { \"name\": \"await-x\", \"waitFor\": { \"source\": \"manual\" }, \"resumeMatch\": {} }\n\n## BPM\n- \\`userTask\\` — assign a form to an actor or role; pauses until submission.\n config: {\n \"assignTo\": \"actor:alice\" | \"role:reviewers\",\n \"title\": \"Review expense {{trigger.values.amount}}\",\n \"description\": \"…\",\n \"dueIn\": \"P2D\" | \"PT2H\" | { \"minutes\": 60 },\n \"form\": FormSchema\n }\n Output: { submittedBy, submittedAt, values: { fieldKey: value }, action: \"primary\" | \"secondary\" }\n- \\`subProcess\\` — spawn a child workflow; parent pauses until child reaches end.\n config: {\n \"workflowId\": \"<other workflow id>\",\n \"inputMap\": { \"trigger\": { \"grantee\": \"{{trigger.values.name}}\" } } (or \"*\" for full inherit),\n \"awaitCompletion\": true\n }\n Output: { childRunId, status, output: <child's last bundle> }\n- \\`signal.emit\\` — publish an event. config: { \"name\": \"approved\", \"scope\": \"workflow\"|\"global\", \"payload\": {} }\n- \\`signal.wait\\` — pause until matching signal arrives. config: { \"name\": \"approved\", \"scope\": \"workflow\", \"match\": { \"grantId\": \"{{trigger.id}}\" } }\n- \\`timer.boundary\\` — pause for a duration. config: { \"after\": \"PT2H\" | \"P1D\" | 60 (minutes) }\n\n## The owner and other people (follow-up steps)\nAn edge without fromPort leaves on the main port (yes / sent / reply); add edges with fromPort for the others.\n- \\`owner.notify\\` — tell the owner. config: { \"text\": \"Deployed: {{deploy.reply}}\" }\n- \\`owner.ask\\` — a decision card for the owner; ports yes / no / expired. config: { \"ask\": \"Ship it?\", \"recommend\": \"…\", \"draft\"?: \"…\", \"choices\"?: [\"a\",\"b\"] }. Output: { port, choice, text, note }\n- \\`person.message\\` — message an employee or client once the owner approves the text (at start or on its own card); ports sent / declined. config: { \"to\": \"Sam\", \"channel\": \"telegram\", \"chatId\": \"…\", \"text\": \"…\" }\n- \\`person.wait\\` — wait for that person's reply; ports reply / timeout. config: { \"reminds\": \"<person.message id>\", \"timeout\": \"2d\", \"remindAfter\": \"1d\" } (or channel + chatId). Output: { text, from, media }\n\n## Actions — side-effect sinks\n- \\`action.send\\` — post a message to any channel. config: { \"channel\": \"telegram\"|\"whatsapp\"|…, \"chatId\": \"{{trigger.chatId}}\", \"text\": \"Hi {{classify.reply}}\", \"accountId\"?: \"…\" }\n- \\`action.createIssue\\` — open a GitLab issue. config: { \"channel\": \"gitlab\", \"project\": \"acme/web\", \"title\": \"…\", \"description\": \"…\", \"labels\": [\"x\"], \"assignees\": [\"user\"] }\n- \\`action.setLabel\\` / \\`action.readLabel\\` / \\`action.react\\` / \\`action.editMessage\\` / \\`action.logTime\\` — self-explanatory; each maps 1:1 to a channel adapter method.\n- \\`action.callHTTP\\` — outbound HTTP. config: { \"method\": \"POST\"|\"GET\"|…, \"url\": \"https://…\", \"headers\": {}, \"body\": {}, \"timeoutMs\": 30000 }\n\n## Terminal\n- \\`end\\` — completes the run. config: { \"status\": \"completed\" | \"failed\" | \"canceled\" }\n\n## FormSchema (used by userTask + trigger.form)\n{\n \"title\": \"Review application\",\n \"description\": \"…\",\n \"fields\": [\n { \"key\": \"score\", \"label\": \"Score\", \"type\": \"number\", \"required\": true, \"validate\": { \"min\": 1, \"max\": 10 } },\n { \"key\": \"verdict\", \"label\": \"Verdict\", \"type\": \"select\", \"required\": true, \"options\": [\"approve\", \"reject\"] },\n { \"key\": \"notes\", \"label\": \"Notes\", \"type\": \"long-text\" }\n ],\n \"submitLabel\": \"Approve\",\n \"secondaryAction\": { \"key\": \"reject\", \"label\": \"Reject\" }\n}\nField types: text, long-text, number, boolean, date, select, multi-select, file.\nA form with a \\`secondaryAction\\` and no required-unfilled fields renders as one-tap Approve/Reject buttons in chat.\n\n## Templates\nEvery prompt + config value can reference \\`{{nodeId.path}}\\` against the run context. Examples:\n {{trigger.values.amount}} — field from the start form\n {{classify.result}} — parsed RESULT: token from an agent node\n {{review.values.score}} — submitted userTask field\n {{env.GITLAB_TOKEN}} — env var (must be listed in workflow.envAllow)\n\n## Edges\n[{ \"from\": \"nodeId\", \"to\": \"nodeId\" }, { \"from\": \"branchId\", \"fromPort\": \"case-label\", \"to\": \"nodeId\" }]\nEvery edge's from/to must reference an existing node. Branch + rule nodes MUST have outgoing edges whose fromPort matches a declared case/rule/default.\n\n## Workflow shell\n{\n \"id\": \"lower-kebab-id\",\n \"version\": 2,\n \"title\": \"Human readable\",\n \"description\": \"optional\",\n \"priority\": 0,\n \"fanOut\": false,\n \"envAllow\": [],\n \"maxChildDepth\": 5,\n \"retention\": { \"maxRuns\": 500, \"maxDays\": 90 },\n \"nodes\": [...],\n \"edges\": [...]\n}\n\n## Lint rules (all enforced on save)\n- exactly one trigger.* node\n- every edge references an existing node\n- every node is reachable from the trigger\n- at least one end/checkpoint/userTask/subProcess/signal.wait/timer.boundary is reachable\n- branch + rule outgoing fromPort values match declared cases (or default)\n- cycles are only allowed when the cycle crosses an agent/checkpoint/userTask/subProcess/signal.wait/timer.boundary`\n\nconst RESPONSE_RULES = `# Your reply\n\nRespond in ONE of two ways:\n\n1. **Clarification**: if the user's request is ambiguous, ask exactly ONE short follow-up question. No JSON.\n\n2. **Workflow**: if you have enough to produce a workflow, reply with:\n - 1–3 short lines explaining what you built\n - a \\`\\`\\`json code block containing the complete, valid V2 workflow\n - (no prose after the JSON block)\n\nOnly reference agent ids, actor ids, role ids, and channel names that\nappear in the Environment section above. If the user asks for an agent\nthat doesn't exist, tell them which agent to register first. Never\ninvent workflowIds for subProcess that aren't in the existing list.`"],"mappings":"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","names":["buildWorkflowAuthorPrompt","args","workflows","w","parts","SYSTEM_HEADER","NODE_CATALOG","a","c","m","tag","RESPONSE_RULES","extractWorkflowJson","reply","fenced","candidates","braceMatch","raw","parsed"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{b as h}from"./chunk-WXABFPX7.js";import"./chunk-RKPAVWXF.js";import{b as m}from"./chunk-LLNPKE7H.js";import"./chunk-SHEUCITK.js";import"./chunk-EV2WPHHS.js";import"./chunk-LRMUK6DC.js";import"./chunk-UNWXKBRF.js";import"./chunk-FCPTN6NF.js";import"./chunk-7I7IEX4S.js";import"./chunk-TEXZEXQZ.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";var p=t=>typeof t=="string"?t.trim():"";function k(t){return[`Run ${t.runId} "${t.title}" [${t.status}] on step ${t.step}: waiting on ${t.waitingOn}.`,t.tags?.length?`Tags: ${t.tags.join(", ")}`:"",...(t.steps??[]).slice(-8).map(r=>`- ${String(r.at).slice(0,16).replace("T"," ")} ${r.step} ${r.status}${r.note?`: ${r.note}`:""}`)].filter(Boolean).join(`
|
|
2
|
+
`)}async function T(t,u){let r=u.fetch??fetch,$=u.daemonUrl.replace(/\/$/,""),a=(p(t.action)||"list").toLowerCase(),f=u.env??process.env,w=async i=>{let l=await r(`${$}${i}`,{signal:AbortSignal.timeout(1e4)}),n=await l.json().catch(()=>({}));return{ok:l.ok,status:l.status,data:n}};try{if(a==="list"){let e=await w("/follow-up");if(!e.ok)return`Error: ${e.data?.error||`HTTP ${e.status}`}`;let o=e.data.groups??[];return o.length?o.map(c=>[`${c.tag}:`,...c.rows.map(s=>`- ${s.runId} "${s.title}" on ${s.step}: waiting on ${s.waitingOn} (since ${String(s.since).slice(0,16).replace("T"," ")} UTC)`)].join(`
|
|
3
|
+
`)).join(`
|
|
4
|
+
`):"No follow-up workflows are running."}if(a==="match"){let e=p(t.request)||p(t.title);if(!e)return"Error: match needs `request`: the owner's request in their words.";let o=h(t,f),c=await w(`/follow-up/match?q=${encodeURIComponent(e)}${o?`&agentId=${encodeURIComponent(o.agentId)}`:""}`);if(!c.ok)return`Error: ${c.data?.error||`HTTP ${c.status}`}`;let s=c.data.matches??[];return s.length?["Saved workflows, best fit first (confidence 0-1):",...s.map(d=>`- ${d.workflowId} "${d.title}" (${d.confidence}${d.autoStart?", starts without asking":""}): ${d.steps.map(I=>I.id).join(" \u2192 ")}`),'Start one with {action:"start", workflowId:"<id>", title:"\u2026", tags:["client:<name>"]}. Run its steps through the workflow, not by hand.'].join(`
|
|
5
|
+
`):"No saved workflow fits. If the request has several steps, build one: start with title and steps."}if(a==="status"){let e=p(t.runId);if(!e)return"Error: status needs runId.";let o=await w(`/follow-up/${encodeURIComponent(e)}`);return o.ok?k(o.data.run):`Error: ${o.data?.error||`HTTP ${o.status}`}`}let i=h(t,f);if(!i)return"Error: couldn't tell which agent you are. Pass callerAgentId.";let l=await r(`${$}/follow-up`,{method:"POST",headers:{"Content-Type":"application/json",...m(f)},body:JSON.stringify({action:a,agentId:i.agentId,workflowId:t.workflowId,title:t.title,description:t.description,tags:t.tags,inputs:t.inputs,steps:t.steps,edges:t.edges,approval:t.approval,autoStart:t.autoStart,requestId:t.requestId,runId:t.runId,step:t.step,evidence:t.evidence,note:t.note,reason:t.reason,fromRun:t.fromRun}),signal:AbortSignal.timeout(2e4)}),n=await l.json().catch(()=>({}));if(!l.ok)return`Error: ${n?.error||`HTTP ${l.status}`}`;if(a==="start"){let e=n.run;return[`Started run ${e.runId} "${e.title}"${n.built?" (built from the steps you gave; propose it with fromRun to keep it)":""}.`,n.awaitingApproval?"It waits for the owner's approval before the first step.":`It is on step ${e.step}: ${e.waitingOn}.`,"AgentX follows it from here: it starts each step, reminds whoever is slow, and tells the owner when it ends. Do not run its steps by hand.",...n.warning?[`Note: ${n.warning}`]:[]].join(" ")}return a==="done"?`Step recorded as done. ${n.run?k(n.run):""}`.trim():a==="blocked"?"The step is marked blocked and the owner is told. Nothing more happens on it until it is sorted.":`Saved ${n.workflowId} switched off, and asked the owner (card ${n.cardId}) whether to keep it as a reusable workflow.`}catch(i){return`Error: couldn't reach the daemon (${i?.message??i}).`}}export{T as runWorkflowTool};
|
|
6
|
+
//# sourceMappingURL=follow-up-tool-ZVEYUJ6U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/workflows/follow-up-tool.ts"],"sourcesContent":["import { resolveScheduleCaller } from \"@/crons/schedule-tool\"\nimport { callerHeaders } from \"@/calls/service\"\n\n// --- Agent-facing `agentx_workflow` tool (#788) ---\n//\n// A request with several steps is run as a workflow, not by hand:\n// match saved workflows that fit the request in front of you\n// start start one (workflowId), or build one from the owner's words\n// (title + steps) and run it; tags say what it concerns\n// status one run: the step it is on and what it waits on\n// list every follow-up still going, grouped by tag\n// done the step you own is finished (evidence)\n// blocked your step cannot go on without the owner (reason)\n// propose ask the owner to keep a workflow as a reusable template\n// It talks to the daemon's /follow-up endpoints.\n\nexport interface WorkflowToolDeps {\n daemonUrl: string\n fetch?: typeof fetch\n env?: NodeJS.ProcessEnv\n}\n\nconst str = (v: unknown) => (typeof v === \"string\" ? v.trim() : \"\")\n\nfunction describe(run: any): string {\n const lines = [\n `Run ${run.runId} \"${run.title}\" [${run.status}] on step ${run.step}: waiting on ${run.waitingOn}.`,\n run.tags?.length ? `Tags: ${run.tags.join(\", \")}` : \"\",\n ...(run.steps ?? []).slice(-8).map((s: any) => `- ${String(s.at).slice(0, 16).replace(\"T\", \" \")} ${s.step} ${s.status}${s.note ? `: ${s.note}` : \"\"}`),\n ]\n return lines.filter(Boolean).join(\"\\n\")\n}\n\n/** Returns the text the agent sees. Every refusal is text, never a throw. */\nexport async function runWorkflowTool(args: Record<string, unknown>, deps: WorkflowToolDeps): Promise<string> {\n const doFetch = deps.fetch ?? fetch\n const base = deps.daemonUrl.replace(/\\/$/, \"\")\n const action = (str(args.action) || \"list\").toLowerCase()\n const env = deps.env ?? process.env\n const read = async (path: string) => {\n const res = await doFetch(`${base}${path}`, { signal: AbortSignal.timeout(10_000) })\n const data = await res.json().catch(() => ({})) as any\n return { ok: res.ok, status: res.status, data }\n }\n\n try {\n if (action === \"list\") {\n const r = await read(\"/follow-up\")\n if (!r.ok) return `Error: ${r.data?.error || `HTTP ${r.status}`}`\n const groups = r.data.groups ?? []\n if (!groups.length) return \"No follow-up workflows are running.\"\n return groups.map((g: any) => [`${g.tag}:`, ...g.rows.map((row: any) => `- ${row.runId} \"${row.title}\" on ${row.step}: waiting on ${row.waitingOn} (since ${String(row.since).slice(0, 16).replace(\"T\", \" \")} UTC)`)].join(\"\\n\")).join(\"\\n\")\n }\n if (action === \"match\") {\n const q = str(args.request) || str(args.title)\n if (!q) return \"Error: match needs `request`: the owner's request in their words.\"\n const caller = resolveScheduleCaller(args, env)\n const r = await read(`/follow-up/match?q=${encodeURIComponent(q)}${caller ? `&agentId=${encodeURIComponent(caller.agentId)}` : \"\"}`)\n if (!r.ok) return `Error: ${r.data?.error || `HTTP ${r.status}`}`\n const matches = r.data.matches ?? []\n if (!matches.length) return \"No saved workflow fits. If the request has several steps, build one: start with title and steps.\"\n return [\n \"Saved workflows, best fit first (confidence 0-1):\",\n ...matches.map((x: any) => `- ${x.workflowId} \"${x.title}\" (${x.confidence}${x.autoStart ? \", starts without asking\" : \"\"}): ${x.steps.map((s: any) => s.id).join(\" → \")}`),\n `Start one with {action:\"start\", workflowId:\"<id>\", title:\"…\", tags:[\"client:<name>\"]}. Run its steps through the workflow, not by hand.`,\n ].join(\"\\n\")\n }\n if (action === \"status\") {\n const runId = str(args.runId)\n if (!runId) return \"Error: status needs runId.\"\n const r = await read(`/follow-up/${encodeURIComponent(runId)}`)\n if (!r.ok) return `Error: ${r.data?.error || `HTTP ${r.status}`}`\n return describe(r.data.run)\n }\n\n const caller = resolveScheduleCaller(args, env)\n if (!caller) return \"Error: couldn't tell which agent you are. Pass callerAgentId.\"\n const res = await doFetch(`${base}/follow-up`, {\n method: \"POST\",\n // The headers name this run: the daemon refuses a write that does\n // not come from a running turn of the agent.\n headers: { \"Content-Type\": \"application/json\", ...callerHeaders(env) },\n body: JSON.stringify({\n action, agentId: caller.agentId,\n workflowId: args.workflowId, title: args.title, description: args.description, tags: args.tags, inputs: args.inputs,\n steps: args.steps, edges: args.edges, approval: args.approval, autoStart: args.autoStart, requestId: args.requestId,\n runId: args.runId, step: args.step, evidence: args.evidence, note: args.note, reason: args.reason, fromRun: args.fromRun,\n }),\n signal: AbortSignal.timeout(20_000),\n })\n const data = await res.json().catch(() => ({})) as any\n if (!res.ok) return `Error: ${data?.error || `HTTP ${res.status}`}`\n if (action === \"start\") {\n const run = data.run\n return [\n `Started run ${run.runId} \"${run.title}\"${data.built ? \" (built from the steps you gave; propose it with fromRun to keep it)\" : \"\"}.`,\n data.awaitingApproval ? \"It waits for the owner's approval before the first step.\" : `It is on step ${run.step}: ${run.waitingOn}.`,\n \"AgentX follows it from here: it starts each step, reminds whoever is slow, and tells the owner when it ends. Do not run its steps by hand.\",\n ...(data.warning ? [`Note: ${data.warning}`] : []),\n ].join(\" \")\n }\n if (action === \"done\") return `Step recorded as done. ${data.run ? describe(data.run) : \"\"}`.trim()\n if (action === \"blocked\") return \"The step is marked blocked and the owner is told. Nothing more happens on it until it is sorted.\"\n return `Saved ${data.workflowId} switched off, and asked the owner (card ${data.cardId}) whether to keep it as a reusable workflow.`\n } catch (e: any) {\n return `Error: couldn't reach the daemon (${e?.message ?? e}).`\n }\n}\n"],"mappings":"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","names":["str","v","describe","run","s","runWorkflowTool","args","deps","doFetch","base","action","env","read","path","res","data","r","groups","g","row","q","caller","resolveScheduleCaller","matches","x","runId","callerHeaders","e"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=grants-
|
|
1
|
+
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u}from"./chunk-WEPON4FP.js";import"./chunk-AKLZ4YO2.js";import"./chunk-Y4CYQV7G.js";import"./chunk-2QNT5JDS.js";import"./chunk-QIJLFPWE.js";export{c as DEFAULT_GRANT_DAYS,a as GUEST_SCOPE_PREFIX,b as JOIN_CARD_BY,h as JOIN_FAILED,d as MAX_GRANT_DAYS,j as NO_GRANT,l as PAUSED,k as WAITING_HOST,s as endGrant,o as grantBrief,u as grantForGuest,e as grantIdOf,n as guestAccess,p as guestTask,g as inviteGuest,i as joinGuest,f as newGrantId,q as pauseGrant,r as resumeGrant,m as settleGrant,t as updateGrant};
|
|
2
|
+
//# sourceMappingURL=grants-HIFE6L5N.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -6653,6 +6653,36 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
6653
6653
|
autoRunThreshold?: number | undefined;
|
|
6654
6654
|
suggestThreshold?: number | undefined;
|
|
6655
6655
|
}>>;
|
|
6656
|
+
/** Follow-up workflows (#788): agents start a saved workflow for a
|
|
6657
|
+
* request, or build one from the owner's words, and the engine
|
|
6658
|
+
* follows each step to the end. */
|
|
6659
|
+
followUp: z.ZodDefault<z.ZodObject<{
|
|
6660
|
+
/** Agents get agentx_workflow and the hint naming a saved workflow
|
|
6661
|
+
* that fits the request. */
|
|
6662
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
6663
|
+
/** Per agent, by id: false turns it off for that agent. */
|
|
6664
|
+
agents: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
6665
|
+
/** An agent step with no progress for this long gets a reminder. */
|
|
6666
|
+
stallMinutes: z.ZodDefault<z.ZodNumber>;
|
|
6667
|
+
/** Reminders before the step counts as blocked and you are told. */
|
|
6668
|
+
maxNudges: z.ZodDefault<z.ZodNumber>;
|
|
6669
|
+
/** When you approve messages to people: all at once when a run
|
|
6670
|
+
* starts ("start"), or each before it is sent ("step"). A workflow
|
|
6671
|
+
* can set its own `approval`. */
|
|
6672
|
+
approval: z.ZodDefault<z.ZodEnum<["start", "step"]>>;
|
|
6673
|
+
}, "strip", z.ZodTypeAny, {
|
|
6674
|
+
enabled: boolean;
|
|
6675
|
+
agents: Record<string, boolean>;
|
|
6676
|
+
approval: "start" | "step";
|
|
6677
|
+
stallMinutes: number;
|
|
6678
|
+
maxNudges: number;
|
|
6679
|
+
}, {
|
|
6680
|
+
enabled?: boolean | undefined;
|
|
6681
|
+
agents?: Record<string, boolean> | undefined;
|
|
6682
|
+
approval?: "start" | "step" | undefined;
|
|
6683
|
+
stallMinutes?: number | undefined;
|
|
6684
|
+
maxNudges?: number | undefined;
|
|
6685
|
+
}>>;
|
|
6656
6686
|
/** Controls whether the dashboard exposes the visual editor. "readonly"
|
|
6657
6687
|
* serves the list + run timelines but strips write controls from the
|
|
6658
6688
|
* page. "disabled" hides the tab entirely. */
|
|
@@ -6660,6 +6690,13 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
6660
6690
|
}, "strip", z.ZodTypeAny, {
|
|
6661
6691
|
dir: string;
|
|
6662
6692
|
enabled: boolean;
|
|
6693
|
+
followUp: {
|
|
6694
|
+
enabled: boolean;
|
|
6695
|
+
agents: Record<string, boolean>;
|
|
6696
|
+
approval: "start" | "step";
|
|
6697
|
+
stallMinutes: number;
|
|
6698
|
+
maxNudges: number;
|
|
6699
|
+
};
|
|
6663
6700
|
n8n: {
|
|
6664
6701
|
apiKey: string;
|
|
6665
6702
|
baseUrl: string;
|
|
@@ -6674,6 +6711,13 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
6674
6711
|
}, {
|
|
6675
6712
|
dir?: string | undefined;
|
|
6676
6713
|
enabled?: boolean | undefined;
|
|
6714
|
+
followUp?: {
|
|
6715
|
+
enabled?: boolean | undefined;
|
|
6716
|
+
agents?: Record<string, boolean> | undefined;
|
|
6717
|
+
approval?: "start" | "step" | undefined;
|
|
6718
|
+
stallMinutes?: number | undefined;
|
|
6719
|
+
maxNudges?: number | undefined;
|
|
6720
|
+
} | undefined;
|
|
6677
6721
|
n8n?: {
|
|
6678
6722
|
apiKey?: string | undefined;
|
|
6679
6723
|
baseUrl?: string | undefined;
|
|
@@ -6902,8 +6946,8 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
6902
6946
|
* them while ToolSearch is available, so a list saves only their
|
|
6903
6947
|
* names (about 300 tokens) unless tool search is off. A tool left
|
|
6904
6948
|
* off cannot be found even through ToolSearch. `agentx_approval`,
|
|
6905
|
-
* `agentx_request`, `agentx_events
|
|
6906
|
-
* always kept, and so are `agentx_agents`, `agentx_recent` and
|
|
6949
|
+
* `agentx_request`, `agentx_events`, `agentx_attach_next` and
|
|
6950
|
+
* `agentx_workflow` are always kept, and so are `agentx_agents`, `agentx_recent` and
|
|
6907
6951
|
* `agentx_wiki_query` while `contextOnDemand` is on. A name that is
|
|
6908
6952
|
* not an agentx tool is rejected, so a typo cannot silently drop a
|
|
6909
6953
|
* reply tool. Only an agentx server started as a command (stdio)
|
|
@@ -7863,6 +7907,13 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
7863
7907
|
workflows: {
|
|
7864
7908
|
dir: string;
|
|
7865
7909
|
enabled: boolean;
|
|
7910
|
+
followUp: {
|
|
7911
|
+
enabled: boolean;
|
|
7912
|
+
agents: Record<string, boolean>;
|
|
7913
|
+
approval: "start" | "step";
|
|
7914
|
+
stallMinutes: number;
|
|
7915
|
+
maxNudges: number;
|
|
7916
|
+
};
|
|
7866
7917
|
n8n: {
|
|
7867
7918
|
apiKey: string;
|
|
7868
7919
|
baseUrl: string;
|
|
@@ -8781,6 +8832,13 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
8781
8832
|
workflows?: {
|
|
8782
8833
|
dir?: string | undefined;
|
|
8783
8834
|
enabled?: boolean | undefined;
|
|
8835
|
+
followUp?: {
|
|
8836
|
+
enabled?: boolean | undefined;
|
|
8837
|
+
agents?: Record<string, boolean> | undefined;
|
|
8838
|
+
approval?: "start" | "step" | undefined;
|
|
8839
|
+
stallMinutes?: number | undefined;
|
|
8840
|
+
maxNudges?: number | undefined;
|
|
8841
|
+
} | undefined;
|
|
8784
8842
|
n8n?: {
|
|
8785
8843
|
apiKey?: string | undefined;
|
|
8786
8844
|
baseUrl?: string | undefined;
|
|
@@ -9722,6 +9780,15 @@ declare class AgentXDaemon {
|
|
|
9722
9780
|
* closed ones are deleted (src/requests/sweep.ts). Plans first: a
|
|
9723
9781
|
* blocked step marks its request told, so the owner hears once. */
|
|
9724
9782
|
private sweepRequests;
|
|
9783
|
+
/** Tell the owner through the notify path: a push to the default
|
|
9784
|
+
* channel, the Mac banner where there is one (#788). */
|
|
9785
|
+
private notifyOwner;
|
|
9786
|
+
/** A card raised for a workflow (#788): a step's answer resumes its
|
|
9787
|
+
* run; a proposed workflow is kept (switched on) on a yes. */
|
|
9788
|
+
private workflowCardResult;
|
|
9789
|
+
/** A follow-up run ended: its request closes with the steps' evidence,
|
|
9790
|
+
* or needs attention (the summary already told the owner). */
|
|
9791
|
+
private workflowRequestEnded;
|
|
9725
9792
|
/** A check-in pass when one is due, or `force` now. macOS only. */
|
|
9726
9793
|
runCheckin(force?: PassKind): Promise<PassResult | null>;
|
|
9727
9794
|
private stopReminders?;
|
|
@@ -12248,6 +12315,8 @@ interface RunningTask {
|
|
|
12248
12315
|
/** Intent-graph path this request was classified under, once known.
|
|
12249
12316
|
* Classification runs alongside the turn, so it is absent until then. */
|
|
12250
12317
|
intentPath?: string[];
|
|
12318
|
+
/** Step autonomy the turn runs at (report | propose | act). Unset = act. */
|
|
12319
|
+
autonomy?: AgentTask["autonomy"];
|
|
12251
12320
|
}
|
|
12252
12321
|
type TaskOutputSubscriber = (chunk: string) => void;
|
|
12253
12322
|
/** Persisted record of a finished task, written to .agentx/task-history. */
|
|
@@ -12584,6 +12653,7 @@ declare class AgentRegistry {
|
|
|
12584
12653
|
}): {
|
|
12585
12654
|
taskId: string;
|
|
12586
12655
|
context: NonNullable<AgentTask["context"]>;
|
|
12656
|
+
autonomy?: AgentTask["autonomy"];
|
|
12587
12657
|
} | null;
|
|
12588
12658
|
/** Whether every slot of `agentId` is taken, and by which runs. Lets a
|
|
12589
12659
|
* synchronous delegation refuse at once when the only slot is held by
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as St,b as kt,c as vt,d as xt,e as $t,f as Ct,g as Pt,h as bt,la as Tt,ma as Mt}from"./chunk-
|
|
1
|
+
import{a as St,b as kt,c as vt,d as xt,e as $t,f as Ct,g as Pt,h as bt,la as Tt,ma as Mt}from"./chunk-XUKBXHTV.js";import"./chunk-M6WY53GO.js";import"./chunk-GTJIKXDB.js";import"./chunk-GOCYZJMS.js";import"./chunk-S2GAEH2F.js";import"./chunk-BGG3ZSMW.js";import"./chunk-ZVP6GB4G.js";import"./chunk-XGOBZCYC.js";import"./chunk-WCXXXAHV.js";import"./chunk-GRMCAO3Q.js";import"./chunk-LQE73AZR.js";import"./chunk-2D3RYIDU.js";import"./chunk-WEPON4FP.js";import"./chunk-AKLZ4YO2.js";import"./chunk-PPUN7YHA.js";import"./chunk-VZLIBDLH.js";import"./chunk-EKJG63EJ.js";import"./chunk-AIYI2MFV.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import"./chunk-EMGB23H5.js";import"./chunk-JWDJMFU6.js";import"./chunk-KZKDVIOE.js";import{ca as yt,m as lt,n as ct,o as dt,p as mt,q as pt}from"./chunk-ODGGGU5J.js";import"./chunk-EYIQVQMA.js";import"./chunk-GLQLCBJS.js";import"./chunk-6W74CHNW.js";import{a as L}from"./chunk-UG2OF2EI.js";import{A as D,B as z,C as V,a as ye,b as we,c as Se,d as Ae,e as Ie,f as Oe,g as Ne,h as He,i as je,j as Ue,k as _e,l as I,m as q,n as Be,o as qe,p as Ye,q as O,r as ze,s as Ve,t as Xe,u as x,v as Y,w as Qe,x as Ze,y as et,z as wt}from"./chunk-DTSKSYEO.js";import{a as B,b as M,c as F}from"./chunk-SFQUP3BP.js";import"./chunk-Y4CYQV7G.js";import"./chunk-LLNPKE7H.js";import"./chunk-SHEUCITK.js";import"./chunk-EV2WPHHS.js";import"./chunk-GV7S5BAX.js";import"./chunk-SZDACK6O.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import{s as ut}from"./chunk-LRMUK6DC.js";import"./chunk-UNWXKBRF.js";import"./chunk-VWTBHLMX.js";import"./chunk-KQW2U5MY.js";import{a as ht}from"./chunk-PGXACYDY.js";import"./chunk-36AXN6ZB.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-J3SOEFRE.js";import"./chunk-SIU6STB2.js";import"./chunk-X5C5W3E4.js";import"./chunk-GSX4NK2N.js";import"./chunk-JA6MVY7J.js";import"./chunk-MYVHVJWZ.js";import"./chunk-AV7T3SYT.js";import"./chunk-Y5MFVVTM.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import"./chunk-22SWFBSL.js";import{f as gt,g as ft}from"./chunk-FQQHUCFN.js";import"./chunk-WPNRDEHW.js";import"./chunk-56KNKUFF.js";import{j as it,k as rt,l as at}from"./chunk-TJLTPONY.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import{a as ke,b as ve,c as xe,d as $e,e as Ce,f as Pe,g as be,h as Te,i as Me,j as Re,l as Ee,m as Ge,o as T,p as W}from"./chunk-2PJKGZWP.js";import{a as m,b as G}from"./chunk-7I7IEX4S.js";import{b as Fe,c as Le,d as A,e as De}from"./chunk-JHCI6XCJ.js";import{a as Ke,b as Je,e as We}from"./chunk-DSYKYZMT.js";import{ia as tt,ka as st,la as ot,na as nt}from"./chunk-TEXZEXQZ.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";W();G();import{execa as Rt}from"execa";import{existsSync as se,promises as X}from"fs";import S from"path";import ie from"node-fetch";async function Et(o,e){let t=o.split("/");if(t.length<2)throw new Error(`Invalid skill package ID: ${o}. Expected format: owner/repo`);let s=t[0],i=t[1],n=t[2];try{let a=n?`${s}/${i}/${n}`:`${s}/${i}`;await Rt("npx",["-y","skills","add",a],{cwd:e,stdio:"pipe"}),m.success(`Installed skill package: ${o}`);let r=S.resolve(e,".skills",`${s}_${i}`);if(se(r))return await ne(r,o);let d=S.resolve(e,".skills");return se(d)?await ne(d,o):[]}catch{return m.info(`Fetching skills directly from GitHub: ${s}/${i}`),await Gt(s,i,n,e)}}async function Gt(o,e,t,s){let i=[];try{let n=`https://api.github.com/repos/${o}/${e}/git/trees/main?recursive=1`,a=await ie(n);if(!a.ok)throw new Error(`GitHub API error: ${a.status}`);let d=(await a.json()).tree.filter(p=>p.type==="blob"&&p.path.endsWith("SKILL.md"));if(t){let p=d.find(f=>f.path.includes(`/${t}/`)||f.path===`${t}/SKILL.md`);if(p){let f=await oe(o,e,p.path,s);f&&i.push(f)}}else for(let p of d){let f=await oe(o,e,p.path,s);f&&i.push(f)}}catch(n){m.error(`Failed to fetch skills from GitHub: ${n.message}`)}return i}async function oe(o,e,t,s){try{let i=`https://raw.githubusercontent.com/${o}/${e}/main/${t}`,n=await ie(i);if(!n.ok)return null;let a=await n.text(),r=A(a);if(r){r.source="remote",r.packageId=`${o}/${e}`;let d=S.dirname(t),p=S.resolve(s,".skills",`${o}_${e}`,d);await X.mkdir(p,{recursive:!0}),await X.writeFile(S.resolve(p,"SKILL.md"),a),r.path=S.resolve(p,"SKILL.md")}return r}catch{return null}}async function ne(o,e){let t=[],{default:s}=await import("fast-glob"),i=await s.glob("**/SKILL.md",{cwd:o,deep:5});for(let n of i)try{let a=S.resolve(o,n),r=await X.readFile(a,"utf8"),d=A(r);d&&(d.source="remote",d.path=a,d.packageId=e,t.push(d))}catch{}return t}async function At(o,e,t,s,i){let n=["---",`name: ${o}`,`description: ${e}`];if(s?.length){n.push("tags:");for(let a of s)n.push(` - ${a}`)}if(i?.length){n.push("globs:");for(let a of i)n.push(` - ${a}`)}return n.push("---"),`${n.join(`
|
|
2
2
|
`)}
|
|
3
3
|
|
|
4
4
|
${t}`}async function It(o){let{loadLocalSkills:e}=await import("./loader-YFVSSYSL.js");return e(o)}async function Ot(o,e,t,s,i){let a=[{role:"system",content:`You are a skill author for the Agent Skills ecosystem (skills.sh).
|