agentix-cli 0.139.0 → 0.139.2

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.
Files changed (62) hide show
  1. package/dist/{agent-PRHZGF6J.js → agent-5CEDGNDW.js} +2 -2
  2. package/dist/{board-dashboard-GBEBQUFJ.js → board-dashboard-F5GP2X22.js} +2 -2
  3. package/dist/{builtin-YD7MC572.js → builtin-U5S2XCNJ.js} +2 -2
  4. package/dist/chunk-3W2BHUGM.js +11 -0
  5. package/dist/chunk-3W2BHUGM.js.map +1 -0
  6. package/dist/{chunk-KO6BU3B3.js → chunk-4LNJR5PC.js} +2 -2
  7. package/dist/{chunk-34XYHSL6.js → chunk-65LN6GQP.js} +230 -229
  8. package/dist/chunk-65LN6GQP.js.map +1 -0
  9. package/dist/chunk-6TTGRTDO.js +3 -0
  10. package/dist/chunk-6TTGRTDO.js.map +1 -0
  11. package/dist/{chunk-MUC7MMTT.js → chunk-BUKXFZEO.js} +2 -2
  12. package/dist/{chunk-2BEZU5OF.js → chunk-HWYU6XG2.js} +2 -2
  13. package/dist/chunk-HWYU6XG2.js.map +1 -0
  14. package/dist/{chunk-RIYQNADV.js → chunk-LGB6ILTW.js} +3 -3
  15. package/dist/{chunk-JBYLG3CQ.js → chunk-P4TSZDVO.js} +2 -2
  16. package/dist/{chunk-HF5EF335.js → chunk-VE3SSOQX.js} +4 -4
  17. package/dist/chunk-VE3SSOQX.js.map +1 -0
  18. package/dist/{chunk-XQVL2RYG.js → chunk-WTMZW5X7.js} +2 -2
  19. package/dist/{chunk-H4NSB54D.js → chunk-XVTD6I34.js} +2 -2
  20. package/dist/{chunk-U6EJ53DA.js → chunk-YWEGKAE2.js} +2 -2
  21. package/dist/cli.js +1 -1
  22. package/dist/{enrich-R2LIDLPZ.js → enrich-FPK3OW77.js} +2 -2
  23. package/dist/{event-levels-WOYYEWSZ.js → event-levels-NBOMTB23.js} +2 -2
  24. package/dist/{follow-up-tool-QRECR3AH.js → follow-up-tool-M2KCLRQQ.js} +2 -2
  25. package/dist/index.d.ts +14 -1
  26. package/dist/index.js +1 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/{program-7VHY5RVZ.js → program-SJT7PIFO.js} +6 -6
  29. package/dist/program-SJT7PIFO.js.map +1 -0
  30. package/dist/{registry-B276QJ75.js → registry-Q7VNRLZA.js} +2 -2
  31. package/dist/{rules-UVUJTVOE.js → rules-5ZZQZLQA.js} +2 -2
  32. package/dist/send-answer-ZG7UHCVS.js +2 -0
  33. package/dist/{tool-UPXUWIMM.js → tool-DFPOFXGA.js} +2 -2
  34. package/dist/{tool-5WCC7SKQ.js → tool-GJ75MWV5.js} +2 -2
  35. package/dist/wiki-enrich-JNQ2RPWU.js +2 -0
  36. package/dist/wiki-enrich-JNQ2RPWU.js.map +1 -0
  37. package/package.json +1 -1
  38. package/dist/chunk-2BEZU5OF.js.map +0 -1
  39. package/dist/chunk-34XYHSL6.js.map +0 -1
  40. package/dist/chunk-HF5EF335.js.map +0 -1
  41. package/dist/chunk-Q4XP5TBI.js +0 -11
  42. package/dist/chunk-Q4XP5TBI.js.map +0 -1
  43. package/dist/program-7VHY5RVZ.js.map +0 -1
  44. package/dist/wiki-enrich-7SBCPK2E.js +0 -2
  45. /package/dist/{agent-PRHZGF6J.js.map → agent-5CEDGNDW.js.map} +0 -0
  46. /package/dist/{board-dashboard-GBEBQUFJ.js.map → board-dashboard-F5GP2X22.js.map} +0 -0
  47. /package/dist/{builtin-YD7MC572.js.map → builtin-U5S2XCNJ.js.map} +0 -0
  48. /package/dist/{chunk-KO6BU3B3.js.map → chunk-4LNJR5PC.js.map} +0 -0
  49. /package/dist/{chunk-MUC7MMTT.js.map → chunk-BUKXFZEO.js.map} +0 -0
  50. /package/dist/{chunk-RIYQNADV.js.map → chunk-LGB6ILTW.js.map} +0 -0
  51. /package/dist/{chunk-JBYLG3CQ.js.map → chunk-P4TSZDVO.js.map} +0 -0
  52. /package/dist/{chunk-XQVL2RYG.js.map → chunk-WTMZW5X7.js.map} +0 -0
  53. /package/dist/{chunk-H4NSB54D.js.map → chunk-XVTD6I34.js.map} +0 -0
  54. /package/dist/{chunk-U6EJ53DA.js.map → chunk-YWEGKAE2.js.map} +0 -0
  55. /package/dist/{enrich-R2LIDLPZ.js.map → enrich-FPK3OW77.js.map} +0 -0
  56. /package/dist/{event-levels-WOYYEWSZ.js.map → event-levels-NBOMTB23.js.map} +0 -0
  57. /package/dist/{follow-up-tool-QRECR3AH.js.map → follow-up-tool-M2KCLRQQ.js.map} +0 -0
  58. /package/dist/{registry-B276QJ75.js.map → registry-Q7VNRLZA.js.map} +0 -0
  59. /package/dist/{rules-UVUJTVOE.js.map → rules-5ZZQZLQA.js.map} +0 -0
  60. /package/dist/{wiki-enrich-7SBCPK2E.js.map → send-answer-ZG7UHCVS.js.map} +0 -0
  61. /package/dist/{tool-UPXUWIMM.js.map → tool-DFPOFXGA.js.map} +0 -0
  62. /package/dist/{tool-5WCC7SKQ.js.map → tool-GJ75MWV5.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{$ as $r,H as mr,I as hr,J as yr,L as wr,M as br,N as xr,O as Ir,R as Sr,S as Tr,V as kr,W as vr,a as Zs,b as er,ba as Ar,d as nr,f as ze,l as kt,m as pr,t as vt,v as fr}from"./chunk-2BEZU5OF.js";import{a as Vs}from"./chunk-QSKG754X.js";import{b as tr}from"./chunk-MEFPXHQJ.js";import{a as gr}from"./chunk-W4YR2RO2.js";import{b as rr,c as pn,d as ir,e as Tt,h as ar}from"./chunk-JS2LEURJ.js";import{e as Xs,f as Ys}from"./chunk-36AXN6ZB.js";import{a as ln,b as sr}from"./chunk-J3SOEFRE.js";import{a as gn,b as or}from"./chunk-SIU6STB2.js";import{e as dr,i as cr,j as ur,k as lr}from"./chunk-X5C5W3E4.js";import{a as zs}from"./chunk-AXHP6TMT.js";import{g as Js,h as Qs}from"./chunk-7KAQHNLT.js";import{c as Ns,f as Ls}from"./chunk-JJZVFDG6.js";import{s as Ds,v as St,w as Os,y as ye,z as un}from"./chunk-LMZCB7TT.js";import{a as Qe,b as Ee,f as It}from"./chunk-72SZI2UW.js";import{a as _e,b as rn}from"./chunk-FCPTN6NF.js";import{a as Fs,c as Us}from"./chunk-MYVHVJWZ.js";import{d as De,h as Ae}from"./chunk-6TURWSMN.js";import{a as Hs,b as Bs,c as js,d as Ws,l as qs}from"./chunk-AV7T3SYT.js";import{a as Gs,b as Ks}from"./chunk-Y5MFVVTM.js";import{c as Ss,d as Ts}from"./chunk-QOYAX2FT.js";import{e as $e}from"./chunk-DSYKYZMT.js";import{$ as Rs,Aa as $a,G as As,I as dn,K as ka,N as Cs,R as va,X as Ms,Y as cn,Z as Ps,_ as Je,aa as _s,ga as Es}from"./chunk-MGM33GOW.js";import{g as Ke,h as Sa}from"./chunk-BRK6M6LA.js";import{f as an,n as Ta}from"./chunk-UIBUZ2N3.js";import{a as ks,b as le,c as vs,d as $s,e as on}from"./chunk-2QNT5JDS.js";un();It();var $t="tool-set",Cr=["answer","code","full"],Mr={answer:["Read","Grep","Glob"],code:["Read","Grep","Glob","Edit","MultiEdit","Write","Bash"]},Aa=.1;function Rr(n){return{task:Pr(n.message,2e3),agent:n.agent,channel:n.channel??null,...n.agentPrompt?{agentInstructions:Pr(n.agentPrompt,600)}:{}}}var _r={bundle:Ee({answer:"Read-only: the task can be done by reading, searching and listing files and then replying. It changes no file and runs no command (no tests, no git, no scripts).",code:"Change files or run commands in the workspace: edit or write files, run tests, builds, git or shell commands. Still all inside the workspace, with no web access, no sub-agents and no notebooks.",full:"Needs more than that, or it is not clear: fetching or searching the web, starting sub-agents, notebooks, or anything the other two do not clearly cover."},"Which set of built-in tools does an agent need to do this task completely? Pick the smallest set that is clearly enough.")};function Er(n,e=Aa){let s=n?.bundle?.probabilities;if(!s)return"full";let r=fn(s.answer),o=fn(s.code),i=fn(s.full);return r===null||o===null||i===null?"full":o+i<e?"answer":i<e?"code":"full"}function Dr(n){let e=[...n].filter(t=>!t.startsWith("mcp__"));return e.every(t=>Mr.answer.includes(t))?"answer":e.every(t=>Mr.code.includes(t))?"code":"full"}function Or(n,e){return Cr.indexOf(n)<Cr.indexOf(e)}function fn(n){return typeof n=="number"&&Number.isFinite(n)?n:null}function Pr(n,e){return n.length>e?`${n.slice(0,e)}\u2026`:n}var Nr=!1;function Lr(n,e){let t=St($t);if(t!=="off")return t==="active"&&!Nr&&(Nr=!0,e(`[decisions] seat "${$t}" is set to active, but only shadow is built: it records and changes nothing`)),ye($t,Rr(n),_r,{incumbent:{bundle:"full"},links:[{kind:"task",id:n.taskId}],features:{agent:n.agent,channel:n.channel??"unknown"}}).then(s=>{if(!s)return null;let r=s.answers,o=Er(r),i=r.bundle?.probabilities??{};return{callId:s.callId,bundle:o,probabilities:i}}).catch(()=>null)}function Fr(n,e,t){return n.then(s=>{if(!s||e.error||!e.eventsSeen)return;let r=[...e.toolUses.keys()],o=Dr(r);Os(s.callId,"bundle",o,{kind:"outcome",labeledBy:"tool-use"});let i=a=>typeof s.probabilities[a]=="number"?s.probabilities[a].toFixed(2):"-";t(`[${e.agentId}] tool-set shadow: would start with ${s.bundle} (answer ${i("answer")}, code ${i("code")}, full ${i("full")}); run used ${r.filter(a=>!a.startsWith("mcp__")).join(", ")||"no built-in tool"} \u2192 needed ${o}`+(Or(s.bundle,o)?" \u2014 MISS":""))}).catch(()=>{})}function Ca(n,e){return!n||n<=0||!e||e<=0?10:Math.min(200,Math.max(1,Math.round(e/n)))}function Ur(n,e){let t=Ca(n.contextTokens,n.turnInputTokens),s=n.idleMs<e.cacheTtlMinutes*6e4,r=.1*(t-1),o=e.freshTokens*(e.cacheWriteFactor+r),i=n.contextTokens;if(!i||i<=0)return{rotate:!1,resumeCost:null,freshCost:o,warm:s,requestsPerTurn:t};let a=i*((s?.1:e.cacheWriteFactor)+r);return{rotate:a>o*e.margin,resumeCost:a,freshCost:o,warm:s,requestsPerTurn:t}}function mn(n){let e=s=>`${Math.round(s/1e3)}k`,t=n.warm?"warm cache":"cold cache";return n.resumeCost===null?`resume: no context reading (${t})`:`${n.rotate?"start fresh":"resume"}: resume \u2248${e(n.resumeCost)}, fresh \u2248${e(n.freshCost)} input-token equivalents (${t}, ${n.requestsPerTurn} requests/turn)`}un();It();var Hr="session-continuity",Br={continues:Qe("The new request continues the task the user was already working on in the previous request, rather than starting a separate one.",{true:`The new request advances, narrows, corrects or follows up on the previous request's task \u2014 including terse replies such as "and the cost?" or "why?" that mean nothing on their own.`,false:"The new request opens a subject that could be answered without having seen the previous request, even if it arrived seconds later or belongs to the same broad field."}),needsHistory:Qe("Does the new request refer to something stated earlier in the conversation?")};function jr(n){let e=(n.recentRequests??[]).filter(Boolean);return{newRequest:hn(n.message,1200),previousRequest:n.previousMessage?hn(n.previousMessage,800):null,...e.length?{earlierRequests:e.map(t=>hn(t,400))}:{},minutesSinceLastTurn:n.minutesSinceLastTurn,turnsSoFar:n.turnCount,currentContextTokens:n.lastTurnContextTokens,agent:n.agentId,channel:n.channel}}function Wr(n,e){if(e.mechanicalRotation)return!1;let t=e.maxContinuity??.2,s=n.continues.noul,r=n.needsHistory.noul;return s<=t&&r<=t}function hn(n,e){let t=String(n??"");return t.length>e?t.slice(0,e):t}import{execa as Ot}from"execa";import{spawn as Ma}from"node:child_process";import{createHash as Pa}from"node:crypto";import{createInterface as Ra}from"node:readline";var we=class extends Error{},_a=n=>Ma("codex",["app-server",...n.args],{cwd:n.cwd,env:n.env,stdio:["pipe","pipe","pipe"]}),yn=class{child;pending=new Map;nextId=0;dead=!1;busy=!1;threadId;idle;notify;failTurn;constructor(e,t){this.child=t(e),this.child.stderr.resume(),Ra({input:this.child.stdout}).on("line",r=>{let o;try{o=JSON.parse(r)}catch{return}if(o.method&&o.id!==void 0)this.write({id:o.id,error:{code:-32601,message:"Interactive requests are not supported by AgentX"}});else if(o.id!==void 0){let i=this.pending.get(o.id);if(!i)return;this.pending.delete(o.id),o.error?i.reject(new Error(o.error.message||"Codex RPC failed")):i.resolve(o.result)}else o.method&&this.notify?.(o.method,o.params)}),this.child.on("error",r=>this.close(r)),this.child.stdin.on("error",r=>this.close(r)),this.child.on("exit",()=>this.close(new Error("Codex app-server exited")))}write(e){this.dead||this.child.stdin.write(JSON.stringify(e)+`
1
+ import{$ as $r,H as mr,I as hr,J as yr,L as wr,M as br,N as xr,O as Ir,R as Sr,S as Tr,V as kr,W as vr,a as Zs,b as er,ba as Ar,d as nr,f as ze,l as kt,m as pr,t as vt,v as fr}from"./chunk-HWYU6XG2.js";import{a as Vs}from"./chunk-QSKG754X.js";import{b as tr}from"./chunk-MEFPXHQJ.js";import{a as gr}from"./chunk-W4YR2RO2.js";import{b as rr,c as pn,d as ir,e as Tt,h as ar}from"./chunk-JS2LEURJ.js";import{e as Xs,f as Ys}from"./chunk-36AXN6ZB.js";import{a as ln,b as sr}from"./chunk-J3SOEFRE.js";import{a as gn,b as or}from"./chunk-SIU6STB2.js";import{e as dr,i as cr,j as ur,k as lr}from"./chunk-X5C5W3E4.js";import{a as zs}from"./chunk-AXHP6TMT.js";import{g as Js,h as Qs}from"./chunk-7KAQHNLT.js";import{c as Ns,f as Ls}from"./chunk-JJZVFDG6.js";import{s as Ds,v as St,w as Os,y as ye,z as un}from"./chunk-LMZCB7TT.js";import{a as Qe,b as Ee,f as It}from"./chunk-72SZI2UW.js";import{a as _e,b as rn}from"./chunk-FCPTN6NF.js";import{a as Fs,c as Us}from"./chunk-MYVHVJWZ.js";import{d as De,h as Ae}from"./chunk-6TURWSMN.js";import{a as Hs,b as Bs,c as js,d as Ws,l as qs}from"./chunk-AV7T3SYT.js";import{a as Gs,b as Ks}from"./chunk-Y5MFVVTM.js";import{c as Ss,d as Ts}from"./chunk-QOYAX2FT.js";import{e as $e}from"./chunk-DSYKYZMT.js";import{$ as Rs,Aa as $a,G as As,I as dn,K as ka,N as Cs,R as va,X as Ms,Y as cn,Z as Ps,_ as Je,aa as _s,ga as Es}from"./chunk-MGM33GOW.js";import{g as Ke,h as Sa}from"./chunk-BRK6M6LA.js";import{f as an,n as Ta}from"./chunk-UIBUZ2N3.js";import{a as ks,b as le,c as vs,d as $s,e as on}from"./chunk-2QNT5JDS.js";un();It();var $t="tool-set",Cr=["answer","code","full"],Mr={answer:["Read","Grep","Glob"],code:["Read","Grep","Glob","Edit","MultiEdit","Write","Bash"]},Aa=.1;function Rr(n){return{task:Pr(n.message,2e3),agent:n.agent,channel:n.channel??null,...n.agentPrompt?{agentInstructions:Pr(n.agentPrompt,600)}:{}}}var _r={bundle:Ee({answer:"Read-only: the task can be done by reading, searching and listing files and then replying. It changes no file and runs no command (no tests, no git, no scripts).",code:"Change files or run commands in the workspace: edit or write files, run tests, builds, git or shell commands. Still all inside the workspace, with no web access, no sub-agents and no notebooks.",full:"Needs more than that, or it is not clear: fetching or searching the web, starting sub-agents, notebooks, or anything the other two do not clearly cover."},"Which set of built-in tools does an agent need to do this task completely? Pick the smallest set that is clearly enough.")};function Er(n,e=Aa){let s=n?.bundle?.probabilities;if(!s)return"full";let r=fn(s.answer),o=fn(s.code),i=fn(s.full);return r===null||o===null||i===null?"full":o+i<e?"answer":i<e?"code":"full"}function Dr(n){let e=[...n].filter(t=>!t.startsWith("mcp__"));return e.every(t=>Mr.answer.includes(t))?"answer":e.every(t=>Mr.code.includes(t))?"code":"full"}function Or(n,e){return Cr.indexOf(n)<Cr.indexOf(e)}function fn(n){return typeof n=="number"&&Number.isFinite(n)?n:null}function Pr(n,e){return n.length>e?`${n.slice(0,e)}\u2026`:n}var Nr=!1;function Lr(n,e){let t=St($t);if(t!=="off")return t==="active"&&!Nr&&(Nr=!0,e(`[decisions] seat "${$t}" is set to active, but only shadow is built: it records and changes nothing`)),ye($t,Rr(n),_r,{incumbent:{bundle:"full"},links:[{kind:"task",id:n.taskId}],features:{agent:n.agent,channel:n.channel??"unknown"}}).then(s=>{if(!s)return null;let r=s.answers,o=Er(r),i=r.bundle?.probabilities??{};return{callId:s.callId,bundle:o,probabilities:i}}).catch(()=>null)}function Fr(n,e,t){return n.then(s=>{if(!s||e.error||!e.eventsSeen)return;let r=[...e.toolUses.keys()],o=Dr(r);Os(s.callId,"bundle",o,{kind:"outcome",labeledBy:"tool-use"});let i=a=>typeof s.probabilities[a]=="number"?s.probabilities[a].toFixed(2):"-";t(`[${e.agentId}] tool-set shadow: would start with ${s.bundle} (answer ${i("answer")}, code ${i("code")}, full ${i("full")}); run used ${r.filter(a=>!a.startsWith("mcp__")).join(", ")||"no built-in tool"} \u2192 needed ${o}`+(Or(s.bundle,o)?" \u2014 MISS":""))}).catch(()=>{})}function Ca(n,e){return!n||n<=0||!e||e<=0?10:Math.min(200,Math.max(1,Math.round(e/n)))}function Ur(n,e){let t=Ca(n.contextTokens,n.turnInputTokens),s=n.idleMs<e.cacheTtlMinutes*6e4,r=.1*(t-1),o=e.freshTokens*(e.cacheWriteFactor+r),i=n.contextTokens;if(!i||i<=0)return{rotate:!1,resumeCost:null,freshCost:o,warm:s,requestsPerTurn:t};let a=i*((s?.1:e.cacheWriteFactor)+r);return{rotate:a>o*e.margin,resumeCost:a,freshCost:o,warm:s,requestsPerTurn:t}}function mn(n){let e=s=>`${Math.round(s/1e3)}k`,t=n.warm?"warm cache":"cold cache";return n.resumeCost===null?`resume: no context reading (${t})`:`${n.rotate?"start fresh":"resume"}: resume \u2248${e(n.resumeCost)}, fresh \u2248${e(n.freshCost)} input-token equivalents (${t}, ${n.requestsPerTurn} requests/turn)`}un();It();var Hr="session-continuity",Br={continues:Qe("The new request continues the task the user was already working on in the previous request, rather than starting a separate one.",{true:`The new request advances, narrows, corrects or follows up on the previous request's task \u2014 including terse replies such as "and the cost?" or "why?" that mean nothing on their own.`,false:"The new request opens a subject that could be answered without having seen the previous request, even if it arrived seconds later or belongs to the same broad field."}),needsHistory:Qe("Does the new request refer to something stated earlier in the conversation?")};function jr(n){let e=(n.recentRequests??[]).filter(Boolean);return{newRequest:hn(n.message,1200),previousRequest:n.previousMessage?hn(n.previousMessage,800):null,...e.length?{earlierRequests:e.map(t=>hn(t,400))}:{},minutesSinceLastTurn:n.minutesSinceLastTurn,turnsSoFar:n.turnCount,currentContextTokens:n.lastTurnContextTokens,agent:n.agentId,channel:n.channel}}function Wr(n,e){if(e.mechanicalRotation)return!1;let t=e.maxContinuity??.2,s=n.continues.noul,r=n.needsHistory.noul;return s<=t&&r<=t}function hn(n,e){let t=String(n??"");return t.length>e?t.slice(0,e):t}import{execa as Ot}from"execa";import{spawn as Ma}from"node:child_process";import{createHash as Pa}from"node:crypto";import{createInterface as Ra}from"node:readline";var we=class extends Error{},_a=n=>Ma("codex",["app-server",...n.args],{cwd:n.cwd,env:n.env,stdio:["pipe","pipe","pipe"]}),yn=class{child;pending=new Map;nextId=0;dead=!1;busy=!1;threadId;idle;notify;failTurn;constructor(e,t){this.child=t(e),this.child.stderr.resume(),Ra({input:this.child.stdout}).on("line",r=>{let o;try{o=JSON.parse(r)}catch{return}if(o.method&&o.id!==void 0)this.write({id:o.id,error:{code:-32601,message:"Interactive requests are not supported by AgentX"}});else if(o.id!==void 0){let i=this.pending.get(o.id);if(!i)return;this.pending.delete(o.id),o.error?i.reject(new Error(o.error.message||"Codex RPC failed")):i.resolve(o.result)}else o.method&&this.notify?.(o.method,o.params)}),this.child.on("error",r=>this.close(r)),this.child.stdin.on("error",r=>this.close(r)),this.child.on("exit",()=>this.close(new Error("Codex app-server exited")))}write(e){this.dead||this.child.stdin.write(JSON.stringify(e)+`
2
2
  `)}rpc(e,t){if(this.dead)return Promise.reject(new Error("Codex connection closed"));let s=++this.nextId;return new Promise((r,o)=>{this.pending.set(s,{resolve:r,reject:o}),this.write({id:s,method:e,params:t})})}close(e=new Error("Codex connection closed")){if(this.dead)return;this.dead=!0,clearTimeout(this.idle);for(let s of this.pending.values())s.reject(e);this.pending.clear(),this.failTurn?.(e),this.child.kill("SIGTERM"),setTimeout(()=>{this.child.exitCode===null&&this.child.kill("SIGKILL")},5e3).unref()}},wn=class{constructor(e=_a,t=8,s=3e5){this.launchProcess=e;this.capacity=t;this.idleMs=s}entries=new Map;stop(){for(let{connection:e}of this.entries.values())e.close();this.entries.clear()}async run(e){let t=Date.now();if(e.signal?.aborted)return{content:"",error:"task cancelled by operator",duration:0};let s=Pa("sha256").update(JSON.stringify([e.cwd,e.model,e.bypass,e.args,Object.entries(e.env).sort(([w],[P])=>w.localeCompare(P))])).digest("hex"),r=this.entries.get(e.key);if(r?.connection.busy)throw new we("Conversation already running");r&&(r.fingerprint!==s||e.fresh||r.connection.dead)&&(r.connection.close(),this.entries.delete(e.key),r=void 0);let o=!!r;if(!r){if(this.entries.size>=this.capacity){let w=[...this.entries].find(([,P])=>!P.connection.busy);if(!w)throw new we("Codex warm process capacity reached");w[1].connection.close(),this.entries.delete(w[0])}try{r={fingerprint:s,connection:new yn(e,this.launchProcess)}}catch{throw new we("Could not start Codex app-server")}this.entries.set(e.key,r)}let i=r.connection;i.busy=!0,clearTimeout(i.idle);let a=!1,c="",d,u,g,m,h=!1,p=()=>i.close(new Error("task cancelled by operator"));e.signal?.addEventListener("abort",p,{once:!0});let x=setTimeout(()=>i.close(new Error("Codex turn timed out")),e.timeoutMs),S=setTimeout(()=>i.close(new Error("Codex initialization timed out")),15e3);try{o||(await i.rpc("initialize",{clientInfo:{name:"agentx",version:"1.0.0"},capabilities:{}}),i.write({method:"initialized",params:{}})),i.threadId&&i.threadId!==e.resume&&(await i.rpc("thread/unsubscribe",{threadId:i.threadId}),i.threadId=void 0);let w={cwd:e.cwd,model:e.model,approvalPolicy:"never",sandbox:e.bypass?"danger-full-access":"workspace-write"};u=(await i.rpc(e.resume&&!e.fresh?"thread/resume":"thread/start",{...w,...e.resume&&!e.fresh?{threadId:e.resume}:{}})).thread.id,i.threadId=u,clearTimeout(S),e.onEvent?.({type:"codex.ready",reused:o,startupMs:Date.now()-t,model:e.model});let R=new Promise((L,M)=>{i.failTurn=M,i.notify=(D,U)=>{if(U?.threadId!==u)return;let N=U.item,q={agentMessage:"agent_message",commandExecution:"command_execution",fileChange:"file_change",mcpToolCall:"mcp_tool_call"};if(e.onEvent?.({...U,type:D.replace("/","."),...N?{item:{...N,type:q[N.type]||N.type}}:{}}),D==="item/completed"&&N?.type==="agentMessage"&&N.phase==="final_answer"&&(d=N.text),D==="item/agentMessage/delta"&&(h||(h=!0,e.onEvent?.({type:"codex.first_output",elapsedMs:Date.now()-t,reused:o})),c+=U.delta,e.onDelta?.(U.delta,c)),D==="thread/tokenUsage/updated"){let H=U.tokenUsage.last;m=H.inputTokens;let K=H.cachedInputTokens||0;g={inputTokens:(g?.inputTokens||0)+Math.max(0,(H.inputTokens||0)-K),outputTokens:(g?.outputTokens||0)+(H.outputTokens||0),cacheReadTokens:(g?.cacheReadTokens||0)+K,cacheCreateTokens:(g?.cacheCreateTokens||0)+(H.cacheWriteInputTokens||0)}}D==="turn/completed"&&(U.turn.status==="completed"?L():M(new Error(U.turn.error?.message||`Codex turn ${U.turn.status}`)))}});return R.catch(()=>{}),a=!0,await i.rpc("turn/start",{threadId:u,input:[{type:"text",text:e.prompt,text_elements:[]}]}),await R,{content:d??c,codexSessionId:u,billedModel:e.model,usage:g,contextTokens:m,duration:Date.now()-t}}catch(w){if(i.close(),!a&&!e.signal?.aborted)throw new we(w.message);return{content:c,codexSessionId:u,usage:g,contextTokens:m,error:w.message,duration:Date.now()-t}}finally{clearTimeout(S),clearTimeout(x),e.signal?.removeEventListener("abort",p),i.notify=void 0,i.failTurn=void 0,i.busy=!1,i.dead?this.entries.get(e.key)?.connection===i&&this.entries.delete(e.key):(i.idle=setTimeout(()=>{i.close(),this.entries.delete(e.key)},this.idleMs),i.idle.unref())}}},qr=new wn;import{execFile as Za}from"child_process";import{StringDecoder as et}from"string_decoder";import{mkdtempSync as co,readFileSync as uo,rmSync as lo}from"fs";import{join as Et}from"path";import{tmpdir as go}from"os";function At(n){let e=(n||"").trim();if(!e)return{message:"Unknown error from the model.",kind:"unknown",retryable:!1};if(/timed out after/i.test(e))return{message:e.slice(0,300),kind:"timeout",retryable:!0,raw:e};if(/not logged in|please run \/login/i.test(e))return{kind:"auth",retryable:!0,message:"The agent's Claude Code session is logged out.",fix:"Usually a transient OAuth refresh race under concurrent load \u2014 retry in a moment. If it persists, run `/login` in the agent's workspace.",raw:e};if(/specified API usage limits/i.test(e)){let d=e.match(/regain access on ([^.\n]+?)(?:\.|$)/i);return{kind:"usage_cap",retryable:!1,message:`Claude Code subscription /usage cap exhausted.${d?` Resets ${d[1].trim()}.`:""}`,fix:"Raise the cap at https://claude.ai/settings/usage (this is the user-set monthly limit on the OAuth account, not Anthropic API billing). If the daemon is using a different account than expected, check CLAUDE_CODE_OAUTH_TOKEN / ANTHROPIC_API_KEY in the spawn env \u2014 capped keys leak the same error.",raw:e}}if(/out of extra usage/i.test(e))return{kind:"overage_disabled",retryable:!0,message:"Claude Max-plan overage is unavailable (disabled or depleted at the org level).",fix:"Enable overage / extra usage at https://claude.ai/settings/usage (this is the subscription account's toggle \u2014 not Anthropic API billing). Warm sessions can still succeed via prompt cache; cold dispatches will keep failing until overage is re-enabled.",raw:e};if(/credit balance (is )?too low|out of credit|credit(s)? exhausted|insufficient credit/i.test(e))return{kind:"out_of_credits",retryable:!1,message:"The agent is out of Anthropic credits.",fix:"Top up at https://console.anthropic.com/settings/billing (or claude.ai/settings/usage for Max subscribers), then retry.",raw:e};let t=e.match(/\{.*\}\s*$/s)||e.match(/\{[\s\S]*\}/),s;if(t)try{s=JSON.parse(t[0])}catch{}let r=s?.error||s,o=typeof r?.type=="string"?r.type:void 0,i=typeof r?.message=="string"?r.message:void 0,a=e.match(/API Error:\s*(\d{3})/i),c=a?parseInt(a[1],10):void 0;return i&&/out of extra usage/i.test(i)?{kind:"overage_disabled",retryable:!0,message:"Claude Max-plan overage is unavailable (disabled or depleted at the org level).",fix:"Enable overage / extra usage at https://claude.ai/settings/usage (this is the subscription account's toggle \u2014 not Anthropic API billing). Warm sessions can still succeed via prompt cache; cold dispatches will keep failing until overage is re-enabled.",raw:e}:i&&/out of (extra )?usage|out of credit|credit(s)? exhausted|insufficient credit|credit balance (is )?too low|low credit balance/i.test(i)?{kind:"out_of_credits",retryable:!1,message:"The agent is out of Anthropic credits.",fix:"Top up at https://console.anthropic.com/settings/billing (or claude.ai/settings/usage for Max subscribers), then retry.",raw:e}:i&&/context|prompt is too long|too many tokens|maximum context length/i.test(i)?{kind:"context_too_large",retryable:!1,message:"The conversation has grown past what the model can hold.",fix:"Clear session history or switch the agent to a bigger context model.",raw:e}:o==="authentication_error"||i&&/authentication|invalid.*api.*key|no api key|not authenticated/i.test(i)?{kind:"auth",retryable:!1,message:"Authentication failed talking to Anthropic.",fix:"Check ANTHROPIC_API_KEY in .env (or the Claude Code login for claude-code tier agents).",raw:e}:o==="permission_error"||c===403?{kind:"permission",retryable:!1,message:i||"The API key doesn't have permission for this request.",raw:e}:o==="rate_limit_error"||c===429?{kind:"rate_limit",retryable:!0,message:"Anthropic's API rate-limited this request.",fix:"AgentX will retry automatically. If it recurs, lower the agent's concurrency or spread scheduled jobs.",raw:e}:o==="overloaded_error"||c===529||c===503?{kind:"overloaded",retryable:!0,message:"Anthropic's API is temporarily overloaded.",fix:"AgentX will retry in a moment.",raw:e}:o==="invalid_request_error"||c===400?{kind:"invalid_request",retryable:!1,message:i||"The model rejected the request as invalid.",raw:e}:c&&c>=500?{kind:"upstream_api",retryable:!0,message:i||`Anthropic API error (HTTP ${c}).`,fix:"Transient \u2014 retry. Check https://status.anthropic.com if it persists.",raw:e}:{kind:"unknown",retryable:!1,message:e.replace(/\s+/g," ").slice(0,220),raw:e}}function Ct(n){return n.fix?`${n.message} \u2014 ${n.fix}`:n.message}function Mt(n){if(!n||typeof n!="object")return;let e,t=-1,s=-1;for(let[r,o]of Object.entries(n)){let i=o&&typeof o=="object"?o:{},a=typeof i.costUSD=="number"?i.costUSD:0,c=(Number(i.inputTokens)||0)+(Number(i.outputTokens)||0)+(Number(i.cacheReadInputTokens)||0)+(Number(i.cacheCreationInputTokens)||0);(a>t||a===t&&c>s)&&(e=r,t=a,s=c)}return e}var Gr=null;function Pt(){return Gr}function fl(n){Gr=n}function Xe(n){return`${n.agentId}:${n.channel}:${n.chatId}`}function Ea(n,e){if(n.state()==="busy")return null;let s=n.snapshot(),r=n.opts?.model;return r&&e.model&&r!==e.model?`model changed (${r} -> ${e.model})`:e.resumeSessionId?s.claudeSessionId&&s.claudeSessionId!==e.resumeSessionId?`session changed (${s.claudeSessionId.slice(0,8)} -> ${e.resumeSessionId.slice(0,8)})`:null:s.claudeSessionId?"session rotated":null}var Oe=class extends Error{constructor(t,s,r){super(t);this.scope=s;this.cap=r;this.name="RegistryCapExceeded"}},Kr=class{handles=new Map;sweeper;handleWorkspace=new Map;cfg;constructor(e){this.cfg={maxProcessesGlobal:e.maxProcessesGlobal??64,maxProcessesPerAgent:e.maxProcessesPerAgent??16,idleTimeoutMs:e.idleTimeoutMs??3e4,staleTimeoutMs:e.staleTimeoutMs??45*60*1e3,sweepIntervalMs:e.sweepIntervalMs??5e3,factory:e.factory,log:e.log??(()=>{}),currentWorkspaceHash:e.currentWorkspaceHash}}start(){this.sweeper||(this.sweeper=setInterval(()=>this.sweepIdle(),this.cfg.sweepIntervalMs),typeof this.sweeper.unref=="function"&&this.sweeper.unref())}async stop(){this.sweeper&&(clearInterval(this.sweeper),this.sweeper=void 0);let e=Array.from(this.handles.values());this.handles.clear(),await Promise.allSettled(e.map(t=>t.kill("registry-stop")))}acquire(e,t){let s=Xe(e),r=this.handles.get(s);if(r&&r.state()!=="dead"){let a=Ea(r,t);if(!a)return r.claim?.(),r;this.handles.delete(s),this.handleWorkspace.delete(s),this.cfg.log(`[process-registry] respawning ${s}: ${a}`),r.kill(a).catch(()=>{})}if(this.handles.size>=this.cfg.maxProcessesGlobal&&this.evictOldestIdle({scope:"global"}),this.countForAgent(e.agentId)>=this.cfg.maxProcessesPerAgent&&this.evictOldestIdle({scope:"agent",agentId:e.agentId}),this.handles.size>=this.cfg.maxProcessesGlobal)throw new Oe(`process registry at global cap (${this.cfg.maxProcessesGlobal}) and no idle handle to evict`,"global",this.cfg.maxProcessesGlobal);if(this.countForAgent(e.agentId)>=this.cfg.maxProcessesPerAgent)throw new Oe(`process registry at per-agent cap for ${e.agentId} (${this.cfg.maxProcessesPerAgent}) and no idle handle to evict`,"agent",this.cfg.maxProcessesPerAgent);let i=this.cfg.factory.spawn(e,t);return this.handles.set(s,i),this.handleWorkspace.set(s,t.workspace),this.cfg.log(`[process-registry] spawned ${s}`),i}release(e,t={}){let s=Xe(e),r=this.handles.get(s);r&&(this.handles.delete(s),this.handleWorkspace.delete(s),t.kill&&r.kill(t.reason??"release"))}list(){return Array.from(this.handles.values()).map(e=>e.snapshot())}hasLive(e){let t=Xe(e),s=this.handles.get(t);return s!=null&&s.state()!=="dead"}async kill(e,t="operator"){let s=Xe(e),r=this.handles.get(s);r&&(this.handles.delete(s),this.handleWorkspace.delete(s),await r.kill(t))}countForAgent(e){let t=0;for(let s of this.handles.values())s.key.agentId===e&&s.state()!=="dead"&&(t+=1);return t}evictOldestIdle(e){let t,s=Number.POSITIVE_INFINITY;for(let o of this.handles.values()){if(o.state()!=="idle"||e.scope==="agent"&&o.key.agentId!==e.agentId)continue;let i=o.snapshot().lastTurnAt;i<s&&(s=i,t=o)}if(!t)return!1;let r=Xe(t.key);return this.handles.delete(r),t.kill("evicted (cap reached)"),this.cfg.log(`[process-registry] evicted ${r} (cap)`),!0}sweepIdle(){let e=Date.now();for(let[t,s]of this.handles.entries()){let r=s.snapshot();if(s.state()==="dead"){this.handles.delete(t),this.handleWorkspace.delete(t),this.cfg.log(`[process-registry] reaped dead ${t}`);continue}if(s.state()!=="idle")continue;let o=e-r.lastTurnAt;if(o>=this.cfg.staleTimeoutMs){this.handles.delete(t),this.handleWorkspace.delete(t),s.kill(`stale (idle ${Math.round(o/1e3)}s)`),this.cfg.log(`[process-registry] killed stale ${t}`);continue}if(o>=this.cfg.idleTimeoutMs){this.handles.delete(t),this.handleWorkspace.delete(t),s.kill(`idle (${Math.round(o/1e3)}s)`),this.cfg.log(`[process-registry] killed idle ${t}`);continue}if(this.cfg.currentWorkspaceHash){let i=this.handleWorkspace.get(t);if(i){let a=null;try{a=this.cfg.currentWorkspaceHash(s.key,i)}catch(c){this.cfg.log(`[process-registry] drift-check failed for ${t}: ${c?.message||c}`);continue}if(a!==r.claudeMdHash){this.handles.delete(t),this.handleWorkspace.delete(t);let c=r.claudeMdHash??"unmarked",d=a??"unmarked";s.kill(`claude-md drifted (${c} \u2192 ${d})`),this.cfg.log(`[process-registry] killed drifted ${t} (${c} \u2192 ${d})`)}}}}}};import{spawn as Da}from"child_process";import{randomUUID as Oa}from"crypto";import{existsSync as Na,readFileSync as La}from"fs";import{resolve as Fa}from"path";function Ua(n){let e=Fa(n,"CLAUDE.md");if(!Na(e))return null;try{let t=La(e,"utf8");return qs(t)}catch{return null}}var Ha=20*60*1e3,Ba=5e3,Ye=class extends Error{constructor(t){super(`turn exceeded its ${Math.round(t/6e4)}m budget`);this.budgetMs=t}},Ve=class extends Error{constructor(t){super(`claude process stopped mid-turn (${t})`);this.reason=t}};function ja(n,e){return n.AGENTX_AGENT_ID=e.agentId,n.AGENTX_CHANNEL=e.channel,n.AGENTX_CHAT_ID=e.chatId,delete n.AGENTX_TASK_ID,n}var Jr=class{constructor(e={}){this.opts=e}spawn(e,t){return new bn(e,t,this.opts)}},bn=class{constructor(e,t,s){this.key=e;this.opts=t;this.factoryOpts=s;let r=s.binary??"claude",o=this.buildArgs(t),i=this.log=s.log??(()=>{});this.child=Da(r,o,{cwd:t.workspace,env:Ae(ja({...process.env},e),t.billing),stdio:["pipe","pipe","pipe"]}),this.snap={key:e,pid:this.child.pid??null,claudeSessionId:t.resumeSessionId??null,state:"warm-cold",spawnedAt:Date.now(),lastTurnAt:Date.now(),turnCount:0,lastInputTokens:0,pendingTaskId:null,claudeMdHash:Ua(t.workspace)},this.child.stdout.setEncoding("utf8"),this.child.stdout.on("data",a=>this.onStdout(a)),this.child.stderr.setEncoding("utf8"),this.child.stderr.on("data",a=>i(`[claude pid=${this.snap.pid}] stderr: ${a.trim()}`)),this.child.on("exit",a=>{this.exited=!0,this.exitCode=a,this.snap={...this.snap,state:"dead",deadReason:this.killReason??`exit=${a}`};let c=this.waiters.splice(0);for(let d of c)d(null)}),this.child.on("error",a=>{i(`[claude pid=${this.snap.pid}] spawn error: ${a.message}`),this.killReason=`spawn-error: ${a.message}`})}child;buf="";pendingEvents=[];waiters=[];exited=!1;exitCode=null;killReason;turnQueue=Promise.resolve();snap;log;state(){return this.snap.state}snapshot(){return{...this.snap}}async*runTurn(e){let t,s=new Promise(h=>{t=h}),r=this.turnQueue;if(this.turnQueue=r.then(()=>s),await r,this.exited||this.snap.state==="dead")throw t(),new Error(`claude process for ${this.key.agentId}:${this.key.chatId} is dead (${this.snap.deadReason??"?"})`);let o=Date.now();this.snap={...this.snap,state:"busy",pendingTaskId:e.taskId,lastTurnAt:o};let i=Oa(),a=JSON.stringify({type:"user",uuid:i,message:{role:"user",content:e.message}});this.child.stdin.write(a+`
3
3
  `);let c=e.deadlineMs??Ha,d=o+c,u=()=>(this.kill(`turn deadline (${Math.round(c/6e4)}m)`),new Ye(c)),g=!1,m=null;try{for(;;){let h=d-Date.now();if(h<=0)throw u();let p=await this.nextEvent(h);if(p===null&&this.killReason)throw new Ve(this.killReason);if(p===null&&!this.exited)throw u();if(p===null)throw new Error(`claude process exited mid-turn (code=${this.exitCode}, reason=${this.snap.deadReason??"?"})`);if(!g){if(p.type==="user"&&p.uuid===i)g=!0,m&&(yield{type:m.type,raw:m});else if(p.type==="system"&&p.subtype==="init")m=p;else if(p.type==="result"){m=null;let x=typeof p.result=="string"?p.result:"";this.log(`[claude pid=${this.snap.pid}] dropped a reply no question asked for (${x.length} chars): ${x.slice(0,120)}`)}continue}if(yield{type:p.type,raw:p},p.type==="result"){this.onResultEvent(p);return}}}finally{let h=this.snap.state==="busy";this.snap={...this.snap,...h?{state:"idle",lastTurnAt:Date.now()}:{},pendingTaskId:null},t()}}claim(){this.snap.state!=="dead"&&(this.snap={...this.snap,lastTurnAt:Date.now()})}async kill(e){if(this.exited)return;this.killReason=e,this.snap={...this.snap,state:"dead",deadReason:e};try{this.child.kill("SIGTERM")}catch{}let t=this.waiters.splice(0);for(let r of t)r(null);let s=await new Promise(r=>{let o=setTimeout(()=>{try{this.child.kill("SIGKILL")}catch{}r(!0)},Ba);this.child.once("exit",()=>{clearTimeout(o),r(!1)})})}buildArgs(e){let t=["-p","--input-format","stream-json","--output-format","stream-json","--verbose","--replay-user-messages"];return e.model&&t.push("--model",e.model),e.permissionMode==="bypassPermissions"&&t.push("--dangerously-skip-permissions"),e.resumeSessionId&&t.push("--resume",e.resumeSessionId),e.systemPromptAppend&&e.systemPromptAppend.trim().length>0&&t.push("--append-system-prompt",e.systemPromptAppend),e.extraArgs&&t.push(...e.extraArgs),this.factoryOpts.extraArgs&&t.push(...this.factoryOpts.extraArgs),t}onStdout(e){this.buf+=e;let t;for(;(t=this.buf.indexOf(`
4
4
  `))!==-1;){let s=this.buf.slice(0,t);if(this.buf=this.buf.slice(t+1),!s.trim())continue;let r;try{r=JSON.parse(s)}catch{continue}this.waiters.length>0?this.waiters.shift()(r):this.pendingEvents.push(r)}}nextEvent(e){return this.pendingEvents.length>0?Promise.resolve(this.pendingEvents.shift()):this.exited?Promise.resolve(null):new Promise(t=>{let s=!1,r=setTimeout(()=>{if(s)return;s=!0;let i=this.waiters.indexOf(o);i>=0&&this.waiters.splice(i,1),t(null)},e),o=i=>{s||(s=!0,clearTimeout(r),t(i))};this.waiters.push(o)})}onResultEvent(e){let t=e.usage??{},s=typeof e.session_id=="string"?e.session_id:this.snap.claudeSessionId;this.snap={...this.snap,lastTurnAt:Date.now(),turnCount:this.snap.turnCount+1,lastInputTokens:typeof t.input_tokens=="number"?t.input_tokens:this.snap.lastInputTokens,claudeSessionId:s,state:"idle"}}};on();Ta();rn();import{resolve as Qr,join as zr}from"path";var Wa=4e3;function Rt(n){try{let e=zr(Qr(n.root),".agentx","db.sqlite"),t=an({path:e});if(!t)return null;try{t.pragma("busy_timeout = 3000")}catch{}let s=_e(),r=n.input.command?n.input.command.slice(0,Wa):n.input.filePath??null;return t.prepare(`INSERT INTO guardrail_decisions
@@ -31,7 +31,7 @@ ${n}`}function td(n,e,t,s,r){let o=["run","--format","json","--thinking"],i=t||n
31
31
  `,g)}};L.stdout?.on("data",T=>{N+=H.write(T);let b=N.split(`
32
32
  `);N=b.pop()||"";for(let O of b)X(O)}),L.stderr?.on("data",T=>{q+=K.write(T)});let A=await L;if(i&&i.removeEventListener("abort",U),N+=H.end(),N.trim()&&X(N),q+=K.end(),M)return{content:"",error:D||"task cancelled by operator",errorKind:"cancelled",duration:Date.now()-c,opencodeSessionId:h};if(A.exitCode!==0||p){let T=A,b;return T.timedOut?b=`OpenCode timed out after ${Math.round(P/6e4)}m. Bump agent.maxExecutionMinutes for "${n.name||"this agent"}" if tasks need longer.`:p?b=p:T.code==="ENOENT"||/ENOENT|spawn opencode/i.test((T.shortMessage||"")+" "+q)?b=oo():b=q.trim()||`OpenCode exited with code ${T.exitCode??"unknown"}`,{content:"",...V(b),duration:Date.now()-c,usage:m,opencodeSessionId:h}}return S=!1,{content:g.trim(),duration:Date.now()-c,usage:m,billedModel:e.model||n.model,opencodeSessionId:h}}catch(P){if(i?.aborted)return{content:"",error:"task cancelled by operator",errorKind:"cancelled",duration:Date.now()-c};let R=/ENOENT|spawn opencode/i.test(P?.message||"")?oo():P?.message;return{content:g,...V(R||"OpenCode failed"),duration:Date.now()-c,usage:m,opencodeSessionId:h}}finally{w?.(),x?.release(S)}}async function gd(n,e,t,s){let r=Date.now();try{let o=await import("@anthropic-ai/claude-agent-sdk"),{query:i}=o,a=xe(n,e,s),c="",d=i({prompt:a,options:{model:e.model||n.model,cwd:n.workspace,permissionMode:"bypassPermissions"}});for await(let u of d)u.type==="result"&&u.subtype==="success"&&(c=u.result||"");return{content:c,duration:Date.now()-r}}catch(o){return{content:"",...V(`SDK error: ${o.message}`),duration:Date.now()-r}}}async function pd(n,e,t,s,r,o,i,a,c){let d=Date.now(),u=Math.max(6e4,(n.maxExecutionMinutes??20)*6e4),g=new AbortController,m=!1,h=()=>{let S=a.reason?.message||(typeof a.reason=="string"?a.reason:"task cancelled by operator");try{g.abort(new Error(S))}catch{}};a&&(a.aborted?h():a.addEventListener("abort",h,{once:!0}));let p=setTimeout(()=>{m=!0;try{g.abort(new Error(`orchestrator timed out after ${Math.round(u/6e4)}m`))}catch{}},u);p.unref?.();let x=()=>({content:"",...V(`Orchestrator timed out after ${Math.round(u/6e4)}m. Bump agent.maxExecutionMinutes for "${n.name||"this agent"}" if tasks need longer.`),duration:Date.now()-d});try{let S=n.provider||"claude-code",w=s?`${s}
33
33
 
34
- ${e.message}`:e.message,P=e.context?.sender,R=typeof P=="string"&&/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(P),L=e.context?.channel==="web-chat"&&R?{userId:P,agentId:e.agentId||"acme-public"}:void 0,M=Ws(n),D=Object.keys(M).length>0,U={task:w,cwd:n.workspace,provider:S,model:e.model||n.model,apiKey:t,overwrite:!0,interactive:!1,context7:!1,acmeContext:L,providerOpts:o,abortSignal:g.signal,mcpServers:D?M:void 0};if(r){let{generateStream:X}=await import("./agent-PRHZGF6J.js"),A="",T,b,O,B;for await(let C of X(U)){if(c)try{c(C)}catch{}if(C.type==="text_delta")A+=C.text,r(C.text,A);else if(C.type==="thinking_delta")C.text&&i&&i(C.text);else if(C.type==="generate_result"){if(C.result.content&&C.result.content!==A){let W=C.result.content.slice(A.length);W?(A=C.result.content,r(W,A)):A=C.result.content}T=C.result.tokensUsed,C.result.inputTokens!=null&&(b=C.result.inputTokens),C.result.outputTokens!=null&&(O=C.result.outputTokens)}else if(C.type==="done"){if(C.result.content&&C.result.content!==A){let W=C.result.content.slice(A.length);W?(A=C.result.content,r(W,A)):A=C.result.content}C.result.tokensUsed!=null&&(T=C.result.tokensUsed)}else C.type==="error"&&(B=C.error)}return B&&!A?m?x():B==="cancelled"||a?.aborted||g.signal.aborted?{content:"",error:"task cancelled by operator",errorKind:"cancelled",duration:Date.now()-d}:{content:"",...V(`Orchestrator error: ${B}`),duration:Date.now()-d}:((b===void 0||O===void 0)&&T&&(b=Math.round(T*.7),O=T-b),{content:A||"Done.",tokensUsed:T,usage:b!==void 0||O!==void 0?{inputTokens:b||0,outputTokens:O||0,cacheReadTokens:0,cacheCreateTokens:0}:void 0,duration:Date.now()-d})}let{generate:N}=await import("./agent-PRHZGF6J.js"),q=await N(U),H=q.inputTokens,K=q.outputTokens;if((H===void 0||K===void 0)&&q.tokensUsed){let X=q.tokensUsed;H=Math.round(X*.7),K=X-H}return{content:q.content||"Done.",tokensUsed:q.tokensUsed,usage:H!==void 0||K!==void 0?{inputTokens:H||0,outputTokens:K||0,cacheReadTokens:0,cacheCreateTokens:0}:void 0,duration:Date.now()-d}}catch(S){return m?x():S?.message==="cancelled"||a?.aborted||g.signal.aborted?{content:"",error:"task cancelled by operator",errorKind:"cancelled",duration:Date.now()-d}:{content:"",...V(`Orchestrator error: ${S.message}`),duration:Date.now()-d}}finally{clearTimeout(p),a&&a.removeEventListener("abort",h)}}var In=class{open=new Set;observe(e){e?.type!=="system"||typeof e.task_id!="string"||(e.subtype==="task_started"&&e.is_backgrounded!==!1?this.open.add(e.task_id):e.subtype==="task_notification"&&this.open.delete(e.task_id))}get pending(){return this.open.size}},fd=1e3;async function md(n,e){let t=Promise.resolve(n).then(i=>({kind:"exit",r:i})),s,r=e.then(()=>new Promise(i=>{s=setTimeout(()=>i({kind:"grace"}),fd),s.unref?.()})),o=await Promise.race([t,r]);return s&&clearTimeout(s),o.kind==="exit"?o.r:(t.catch(()=>{}),{exitCode:0,stdout:"",stderr:"",detachedAfterResult:!0})}async function hd(n,e,t,s,r,o,i){let a=Pt();if(!a)return null;let c=Date.now(),{channel:d,chatId:u}=Lt(e.context),g={agentId:e.agentId,channel:d,chatId:u};if(e.freshSession)try{await a.kill(g,"freshSession=true")}catch{}let m,h=!1;try{let A=a.list().length;m=a.acquire(g,{agentId:e.agentId,channel:d,chatId:u,workspace:n.workspace,model:e.model||n.model,permissionMode:n.permissionMode,billing:n.billing,systemPromptAppend:e.systemPromptAppend,resumeSessionId:s,extraArgs:e.claudeArgs}),h=a.list().length>A}catch(A){return A instanceof Oe,null}h&&vn(e.agentId,n,e.model,s,"persistent");let p=xe(n,e,t),x="",S,w,P,R,L,M,D,U="",N="",q=A=>{if(!i||!A)return;let T;if(N&&A.startsWith(N)?T=A.slice(N.length):T=U&&!U.endsWith(`
34
+ ${e.message}`:e.message,P=e.context?.sender,R=typeof P=="string"&&/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(P),L=e.context?.channel==="web-chat"&&R?{userId:P,agentId:e.agentId||"acme-public"}:void 0,M=Ws(n),D=Object.keys(M).length>0,U={task:w,cwd:n.workspace,provider:S,model:e.model||n.model,apiKey:t,overwrite:!0,interactive:!1,context7:!1,acmeContext:L,providerOpts:o,abortSignal:g.signal,mcpServers:D?M:void 0};if(r){let{generateStream:X}=await import("./agent-5CEDGNDW.js"),A="",T,b,O,B;for await(let C of X(U)){if(c)try{c(C)}catch{}if(C.type==="text_delta")A+=C.text,r(C.text,A);else if(C.type==="thinking_delta")C.text&&i&&i(C.text);else if(C.type==="generate_result"){if(C.result.content&&C.result.content!==A){let W=C.result.content.slice(A.length);W?(A=C.result.content,r(W,A)):A=C.result.content}T=C.result.tokensUsed,C.result.inputTokens!=null&&(b=C.result.inputTokens),C.result.outputTokens!=null&&(O=C.result.outputTokens)}else if(C.type==="done"){if(C.result.content&&C.result.content!==A){let W=C.result.content.slice(A.length);W?(A=C.result.content,r(W,A)):A=C.result.content}C.result.tokensUsed!=null&&(T=C.result.tokensUsed)}else C.type==="error"&&(B=C.error)}return B&&!A?m?x():B==="cancelled"||a?.aborted||g.signal.aborted?{content:"",error:"task cancelled by operator",errorKind:"cancelled",duration:Date.now()-d}:{content:"",...V(`Orchestrator error: ${B}`),duration:Date.now()-d}:((b===void 0||O===void 0)&&T&&(b=Math.round(T*.7),O=T-b),{content:A||"Done.",tokensUsed:T,usage:b!==void 0||O!==void 0?{inputTokens:b||0,outputTokens:O||0,cacheReadTokens:0,cacheCreateTokens:0}:void 0,duration:Date.now()-d})}let{generate:N}=await import("./agent-5CEDGNDW.js"),q=await N(U),H=q.inputTokens,K=q.outputTokens;if((H===void 0||K===void 0)&&q.tokensUsed){let X=q.tokensUsed;H=Math.round(X*.7),K=X-H}return{content:q.content||"Done.",tokensUsed:q.tokensUsed,usage:H!==void 0||K!==void 0?{inputTokens:H||0,outputTokens:K||0,cacheReadTokens:0,cacheCreateTokens:0}:void 0,duration:Date.now()-d}}catch(S){return m?x():S?.message==="cancelled"||a?.aborted||g.signal.aborted?{content:"",error:"task cancelled by operator",errorKind:"cancelled",duration:Date.now()-d}:{content:"",...V(`Orchestrator error: ${S.message}`),duration:Date.now()-d}}finally{clearTimeout(p),a&&a.removeEventListener("abort",h)}}var In=class{open=new Set;observe(e){e?.type!=="system"||typeof e.task_id!="string"||(e.subtype==="task_started"&&e.is_backgrounded!==!1?this.open.add(e.task_id):e.subtype==="task_notification"&&this.open.delete(e.task_id))}get pending(){return this.open.size}},fd=1e3;async function md(n,e){let t=Promise.resolve(n).then(i=>({kind:"exit",r:i})),s,r=e.then(()=>new Promise(i=>{s=setTimeout(()=>i({kind:"grace"}),fd),s.unref?.()})),o=await Promise.race([t,r]);return s&&clearTimeout(s),o.kind==="exit"?o.r:(t.catch(()=>{}),{exitCode:0,stdout:"",stderr:"",detachedAfterResult:!0})}async function hd(n,e,t,s,r,o,i){let a=Pt();if(!a)return null;let c=Date.now(),{channel:d,chatId:u}=Lt(e.context),g={agentId:e.agentId,channel:d,chatId:u};if(e.freshSession)try{await a.kill(g,"freshSession=true")}catch{}let m,h=!1;try{let A=a.list().length;m=a.acquire(g,{agentId:e.agentId,channel:d,chatId:u,workspace:n.workspace,model:e.model||n.model,permissionMode:n.permissionMode,billing:n.billing,systemPromptAppend:e.systemPromptAppend,resumeSessionId:s,extraArgs:e.claudeArgs}),h=a.list().length>A}catch(A){return A instanceof Oe,null}h&&vn(e.agentId,n,e.model,s,"persistent");let p=xe(n,e,t),x="",S,w,P,R,L,M,D,U="",N="",q=A=>{if(!i||!A)return;let T;if(N&&A.startsWith(N)?T=A.slice(N.length):T=U&&!U.endsWith(`
35
35
  `)?`
36
36
 
37
37
  ${A}`:A,N=A,!!T){U+=T;try{i(T,U)}catch{}}},H=!1,K=()=>{H=!0,a.kill(g,"operator-cancel").catch(()=>{})};o&&(o.aborted?K():o.addEventListener("abort",K,{once:!0}));let X=!1;try{let A=Math.max(6e4,(n.maxExecutionMinutes??20)*6e4);for await(let T of m.runTurn({message:p,taskId:e.taskId??"unknown",deadlineMs:A})){if(X=!0,r)try{r(T.raw)}catch{}if(T.type==="assistant"){let b=T.raw.message?.content??[];for(let B of b)B.type==="text"&&typeof B.text=="string"?(x=B.text,q(B.text)):B.type==="tool_use"&&(N="");let O=T.raw.message?.usage;if(O){let B=(O.input_tokens||0)+(O.cache_read_input_tokens||0)+(O.cache_creation_input_tokens||0);B>0&&(R=B)}}if(T.type==="result"){let b=T.raw;if(b.is_error){let O=V(typeof b.result=="string"?b.result:"claude error");S=O.error,w=O.errorKind}else typeof b.result=="string"&&b.result.length>0&&(x=b.result,U||q(b.result));typeof b.session_id=="string"&&(D=b.session_id),b.usage&&(P={inputTokens:b.usage.input_tokens||0,outputTokens:b.usage.output_tokens||0,cacheReadTokens:b.usage.cache_read_input_tokens||0,cacheCreateTokens:b.usage.cache_creation_input_tokens||0}),typeof b.num_turns=="number"&&(L=b.num_turns),typeof b.message?.model=="string"?M=b.message.model:typeof b.model=="string"?M=b.model:M=Mt(b.modelUsage)||M}}}catch(A){if(H)S="task cancelled by operator",w="cancelled";else if(X)if(A instanceof Ve)S=`Claude Code was stopped mid-turn (${A.reason}), before its time limit`,w="interrupted";else if(A instanceof Ye){let T=V(`Claude Code timed out after ${Math.round(A.budgetMs/6e4)}m. Bump agent.maxExecutionMinutes for "${n.name||e.agentId}" if tasks need longer.`);S=T.error,w=T.errorKind}else{let T=V(`persistent claude process error: ${A?.message||String(A)}`);S=T.error,w=T.errorKind}else return console.error(`[runtime] persistent handle unusable before first event (${A?.message||A}); falling back to spawn-per-task`),a.release(g,{kill:!0,reason:"pre-turn failure"}),o&&o.removeEventListener("abort",K),null}finally{o&&o.removeEventListener("abort",K)}return H&&!S&&(S="task cancelled by operator",w="cancelled"),{content:H?"":x,error:S,errorKind:w,duration:Date.now()-c,usage:P,contextTokens:R,numTurns:L,billedModel:M,claudeSessionId:D}}function Io(n){let e=le(n.autonomy);if(!e&&!n.personLimits)return{args:[]};if(!n.taskId)return{error:"a guarded task requires a task id to enforce"};let t=e?Vr(n.autonomy,n.agentId,n.taskId):{args:[]};return"error"in t||!n.personLimits?t:so(t.args,n.taskId,n.agentId)}function yd(n){return le(n.autonomy)||!!n.personLimits}async function wd(n,e,t,s,r,o,i){let a=le(e.autonomy)?e.autonomy:void 0,c=a&&Zr(a,n.tier)||e.personLimits&&ro(n.tier);if(c)return{content:"",error:c,...a?{autonomy:a}:{}};let d=e.taskId||`guarded-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,u={...e,taskId:d,message:a?`${$s(a)}
@@ -157,4 +157,4 @@ ${ve}`),f+=ve.length}catch{}}}let ya=Vt.length>0?Vt.join(`
157
157
 
158
158
  Agent: ${$.content}`,meta:Ku(ee,e.context)})}catch{}Ks(e.agentId,e.message,$.content,{channel:y,chatId:I,sender:zt},this.memoryStore).catch(()=>{}),No(e.agentId,e.message,$.content,{channel:y,date:new Date().toISOString().slice(0,10)},this.patternStore).catch(()=>{})}let J=$.billedModel||e.model||d.def.model,he=e.context?.channel,bt=he&&(e.context?.chatId||e.context?.group||e.context?.sender)?`${he}:${e.context?.chatId||e.context?.group||e.context?.sender}`:void 0;this.tokenTracker.record(e.agentId,$.duration||0,$.usage,e.message.length,$.content.length,!1,J,he,bt),this.log(`[${e.agentId}] completed in ${$.duration}ms`+($.tokensUsed?` (${$.tokensUsed} tokens)`:"")+` ${O()}`)}return $}catch(l){d.errors++,this.log(`[${e.agentId}] unexpected error: ${l.message}`);let f=At(l.message);return re={content:"",error:Ct(f),errorKind:f.kind},re}finally{if(xs.stop(),Is&&ae&&Te)try{let l=re?.usage,f=Sr(Te,ae,{error:re?re.error||void 0:S.signal.aborted?Re(S.signal).message:"run ended before completion",canceled:Tr(re?.errorKind)||this.stoppedRuns.has(p.id)||this.interruptedRuns.has(p.id)||!re&&S.signal.aborted,durationMs:Date.now()-p.startedAt.getTime(),...l?{inputTokens:l.inputTokens,outputTokens:l.outputTokens}:{},readOnly:nn,exemptQuestions:this.config.workflows?.required?.exemptQuestions??!0});f&&f!=="discarded"&&this.log(`[${e.agentId}] workflow run ${ae} ${f.status} (${f.meta?.wrap?.mode??"linear"})`)}catch(l){this.log(`[${e.agentId}] workflows.required: could not close run ${ae} (non-fatal): ${l?.message||l}`)}se(re),Kn(re)}}getActiveTaskCount(){let e=0;for(let t of this.agents.values())e+=t.activeTasks;return e}runningAgentDrainSeconds(){let e=[];for(let t of this.agents.values())t.activeTasks>0&&e.push(t.def.drainTimeoutSeconds);return e}list(){return Array.from(this.agents.values()).map(e=>{let t=this.lastSummaries.get(e.id);return{id:e.id,name:e.def.name,tier:e.def.tier,model:e.def.model,workspace:e.def.workspace,active:e.activeTasks,total:e.totalTasks,errors:e.errors,lastActive:e.lastActive,runningTasks:this.withWorkflowSteps(e.runningTasks),lastSummary:t?{text:t.text,at:t.at.toISOString(),ok:t.ok}:void 0,hourlyTasks:this.getHourlySparkline(e.id,24)}})}withWorkflowSteps(e){let t=this.workflowRuns;return!t||!e.some(s=>s.workflow)?e:e.map(s=>{if(!s.workflow)return s;try{let r=t.get(s.workflow.runId);return r?{...s,workflow:{...s.workflow,workflowId:r.workflowId,step:kr(r),title:r.meta?.title??r.workflowId}}:s}catch{return s}})}persistTaskRecord(e){let t=e.endedAt.slice(0,10),s=Q(process.cwd(),je,this.safe(e.agentId),t);de(s)||Ou(s,{recursive:!0});let r=Q(s,`${this.safe(e.id)}.json`);Lu(r,JSON.stringify(e,null,2),"utf-8")}getHourlySparkline(e,t=24){let s=Date.now(),r=this.sparklineCache.get(e);if(r&&s-r.at<6e4&&r.hourly.length===t)return r.hourly;let o=new Array(t).fill(0),i=s-t*36e5,a=Q(process.cwd(),je,this.safe(e));if(!de(a))return this.sparklineCache.set(e,{hourly:o,at:s}),o;let c=new Date(s).toISOString().slice(0,10),d=new Date(s-864e5).toISOString().slice(0,10);new Date(s).setUTCHours(0,0,0,0);for(let g of[d,c]){let m=Q(a,g);if(de(m))try{for(let h of ge(m)){if(!h.endsWith(".json"))continue;let p=h.split("-")[0],x=parseInt(p,10);if(!Number.isFinite(x)||x<i||x>s)continue;let S=Math.floor((s-x)/36e5),w=t-1-S;w>=0&&w<t&&o[w]++}}catch{}}return this.sparklineCache.set(e,{hourly:o,at:s}),o}hydrateLastSummariesFromDisk(){let e=Q(process.cwd(),je);if(!de(e))return 0;let t=0;for(let s of ge(e)){let r=Q(e,s),o;try{o=ge(r).filter(i=>/^\d{4}-\d{2}-\d{2}$/.test(i)).sort().reverse()}catch{continue}e:for(let i of o){let a=Q(r,i),c;try{c=ge(a).filter(d=>d.endsWith(".json")).sort().reverse()}catch{continue}for(let d of c)try{let u=JSON.parse(it(Q(a,d),"utf-8")),g=(u.responseText||u.error||"").trim();if(!g)continue;let m=g.split(/\r?\n/)[0].slice(0,140);this.lastSummaries.set(u.agentId,{text:m,at:new Date(u.endedAt),ok:u.ok}),t++;break e}catch{}}}return t}pruneTaskHistory(e=Gu){let t=Q(process.cwd(),je);if(!de(t))return 0;let s=Date.now()-e*24*60*60*1e3,r=0;for(let o of ge(t)){let i=Q(t,o),a;try{a=ge(i)}catch{continue}for(let c of a){let d=Date.parse(c+"T00:00:00Z");if(!(Number.isNaN(d)||d>=s))try{Nu(Q(i,c),{recursive:!0,force:!0}),r++}catch{}}}return r}listTaskHistory(e,t=50){let s=Q(process.cwd(),je,this.safe(e));if(!de(s))return[];let r=ge(s).filter(i=>/^\d{4}-\d{2}-\d{2}$/.test(i)).sort().reverse(),o=[];for(let i of r){if(o.length>=t)break;let a=Q(s,i),c;try{c=ge(a).filter(d=>d.endsWith(".json"))}catch{continue}c.sort().reverse();for(let d of c){if(o.length>=t)break;try{let u=JSON.parse(it(Q(a,d),"utf-8")),{transcript:g,responseText:m,...h}=u;o.push(h)}catch{}}}return o}getTaskRecord(e,t){let s=Q(process.cwd(),je,this.safe(e));if(!de(s))return null;let r=this.safe(t),o=ge(s).filter(i=>/^\d{4}-\d{2}-\d{2}$/.test(i)).sort().reverse();for(let i of o){let a=Q(s,i,`${r}.json`);if(de(a))try{return JSON.parse(it(a,"utf-8"))}catch{return null}}return null}safe(e){return e.replace(/[^a-zA-Z0-9_.:-]/g,"_")}postQueuedResponseToChannel(e,t,s){let r=gr();if(!r)return;let o=t?.channel,i=t?.chatId;if(!o||!i||s.errorKind==="cancelled"||s.errorKind==="interrupted"||s.errorKind==="stopped"||ze(s.error))return;let a=s.error?`Error: ${s.error}`:(s.content||"").trim();a&&r.sendOutbound({channel:o,chatId:i,text:a,agentId:e}).catch(c=>this.log(`[${e}] queued response post failed: ${c?.message??c}`))}runningTaskOwner(e){for(let t of this.agents.values()){let s=t.runningTasks.find(r=>r.id===e);if(s)return{agentId:t.id,channel:s.channel,chatId:s.chatId}}return null}findRunningTurn(e,t={}){let s=this.agents.get(e);if(!s)return null;let r;if(t.taskId)r=s.runningTasks.find(i=>i.id===t.taskId);else if(t.channel&&t.chatId){let i=s.runningTasks.filter(a=>{let c=Lt(a);return c.channel===t.channel&&c.chatId===t.chatId});r=i.length===1?i[0]:void 0}if(!r)return null;let o=this.runningContexts.get(r.id);return o?{taskId:r.id,context:o,...r.autonomy?{autonomy:r.autonomy}:{},...r.workflow?{workflowRunId:r.workflow.runId}:{}}:null}slotHolders(e){let t=this.agents.get(e);return t?{full:t.activeTasks>=t.def.maxConcurrent,runIds:t.runningTasks.map(s=>s.id)}:null}isChatBusy(e,t,s){return this.messageQueue.isBusy(e,t,s)}runningIntentPath(e,t,s){let r=this.agents.get(e);if(!r)return;let o;for(let i of r.runningTasks)i.channel!==t||i.chatId!==s||(!o||i.startedAt>o.startedAt)&&(o=i);return o?.intentPath?.slice()}cancelRunningTask(e,t="operator"){let s=this.taskAborts.get(e);if(!s)return null;try{s.controller.abort(new Error(t))}catch{}return this.log(`[${s.agentId}] task ${e} cancelled \u2014 ${t}`),{agentId:s.agentId,channel:s.channel,chatId:s.chatId}}stopRunningTask(e,t){let s=this.taskAborts.get(e);if(!s||s.controller.signal.aborted)return!1;this.stoppedRuns.set(e,t);try{s.controller.abort(new Error(t))}catch{}return this.log(`[${s.agentId}] task ${e} stopped \u2014 ${t}`),!0}whenRunEnds(e,t){return this.taskAborts.has(e)?new Promise(s=>{let r=setTimeout(s,t);r.unref?.();let o=this.runEndWaiters.get(e)??[];o.push(()=>{clearTimeout(r),s()}),this.runEndWaiters.set(e,o)}):Promise.resolve()}signalTarget(e){let t;if(e.taskId)t=this.taskAborts.has(e.taskId)?e.taskId:void 0;else if(e.agentId&&e.channel&&e.chatId){let r=[...this.taskAborts].filter(([,o])=>o.agentId===e.agentId&&o.channel===e.channel&&o.chatId===e.chatId).map(([o])=>o);t=r.length===1?r[0]:void 0}let s=t?this.taskAborts.get(t):void 0;return!t||!s?null:{taskId:t,traceId:s.traceId,agentId:s.agentId,channel:s.channel,chatId:s.chatId,sender:s.sender,rootId:s.rootId,originalMessage:s.originalMessage,origin:s.origin??null,...s.workflowRunId?{workflowRunId:s.workflowRunId}:{}}}interruptRunning(e){let t=0;for(let[s,r]of this.taskAborts){this.interruptedRuns.set(s,e);try{r.controller.abort(new Error(e))}catch{}this.log(`[${r.agentId}] task ${s} interrupted \u2014 ${e}`),t++}return t}cancelChatTasks(e,t,s,r="operator"){let o=0;for(let[i,a]of this.taskAborts)a.agentId===e&&a.channel===t&&a.chatId===s&&this.cancelRunningTask(i,r)&&o++;return o}queueFollowUp(e,t,s,r={}){let o=this.taskAborts.get(e);if(!o)return null;let{agentId:i,channel:a,chatId:c,originalMessage:d}=o,u=o.controller.signal.aborted,g=!1;u&&d&&(g=this.sessions.removeLastUserMessageIfMatches(i,a,c,d));let m=Date.now();this.messageQueue.enqueue(i,a,c,{text:t,sender:s,timestamp:m,channel:a,chatId:c,originalContext:{channel:a,chatId:c,sender:s}});let h=this.messageQueue.pendingCount(i,a,c);Z().emit("task:queued",{agentId:i,channel:a,chatId:c,at:new Date(m).toISOString(),sender:{name:s},humanRoot:!1,person:Ms(this.config.people)?.id??null,messagePreview:t.slice(0,200),queuedAt:m});let p=!1;if(r.replace){let x=r.reason||`replaced by follow-up from ${s}`;try{o.controller.abort(new Error(x))}catch{}this.log(`[${i}] task ${e} replaced by follow-up \u2014 ${x}`),p=!0}else this.log(`[${i}] follow-up queued for task ${e} (pending=${h}${g?", edited cancelled turn":""})`);return{agentId:i,channel:a,chatId:c,replaced:p,edited:g,pending:h}}async continueFinishedTask(e,t,s,r,o={}){let i=this.getTaskRecord(e,t);if(!i)return{ok:!1,status:404,error:`no task ${t} for agent ${e}`};if(i.channel!=="cron"||!i.chatId)return{ok:!1,status:409,error:`task ${t} is finished; only scheduled (cron) runs can be resumed from the dashboard`};let a=i.channel,c=i.chatId;return new Promise(d=>{let u=!1,g=m=>{u||(u=!0,d(m))};this.log(`[${e}] operator resumed ${a}:${c} from finished task ${t}`),this.execute({message:s,agentId:e,model:o.model?.(c),context:{channel:a,chatId:c,sender:r},onStart:m=>g({ok:!0,agentId:e,channel:a,chatId:c,taskId:m,queued:!1})}).then(m=>{ze(m.error)?g({ok:!0,agentId:e,channel:a,chatId:c,queued:!0}):m.error?g({ok:!1,status:500,error:m.error||"run did not start"}):g({ok:!0,agentId:e,channel:a,chatId:c,queued:!1,answeredBy:m.viaAttachedSession?"attached":"other"})}).catch(m=>g({ok:!1,status:500,error:m?.message??String(m)}))})}subscribeToTaskOutput(e,t){let s=this.taskOutputs.get(e);return s?s.done?{initial:s.buffer,done:!0,unsubscribe:()=>{}}:(s.subscribers.add(t),{initial:s.buffer,done:!1,unsubscribe:()=>{s.subscribers.delete(t)}}):null}getUsage(e=7){return this.tokenTracker.summary(e)}getTodayUsage(){return this.tokenTracker.today()}getTokenTracker(){return this.tokenTracker}};function Zu(n,e){return n===!1||e!=="telegram"&&e!=="whatsapp"&&e!=="app"?"":["[Rich replies]","On this chat channel you may add buttons, a poll, or media to a reply by appending ONE fenced block at the very end:","```agentx:ui",'{ "buttons": [{"label": "Open docs", "url": "https://..."}], "poll": {"question": "Ship it?", "options": ["Yes", "No"]}, "media": {"type": "image", "url": "https://..."} }',"```","All fields are optional; include only what helps. Buttons must be https URLs (tappable callback actions aren't supported yet). Use this sparingly \u2014 only when a link, choice, or image genuinely improves the reply. The block is stripped from the visible text.",...e==="app"?[`In this phone app you may also offer up to 4 short answers the user can tap instead of typing: "quickReplies": ["Yes", "Not now"] (at most 40 characters each), or a button with a reply instead of a url: {"label": "Run the tests", "reply": "Please run the tests"}. A tap sends that text as the user's next message, nothing more. Offer them only when the user is likely to answer with one of them.`]:[]].join(`
159
159
  `)}export{qr as a,fl as b,Kr as c,Ua as d,Jr as e,Rt as f,Al as g,Rl as h,_l as i,Ll as j,Lt as k,id as l,bo as m,ld as n,gd as o,pd as p,So as q,Ft as r,Ut as s,Dd as t,lg as u,gg as v,Rn as w,Z as x,Lo as y,qd as z,Qd as A,Ho as B,Mg as C,Bo as D,Go as E,Yo as F,Wg as G,Vo as H,jt as I,Qg as J,zg as K,ot as L,Zc as M,eu as N,tu as O,nu as P,su as Q,Fn as R,Hu as S,Bu as T,Ff as U,Uf as V,Ku as W,Ju as X,zu as Y,Gn as Z,Ji as _,Qi as $,Yu as aa,zi as ba,Xi as ca,Zu as da};
160
- //# sourceMappingURL=chunk-RIYQNADV.js.map
160
+ //# sourceMappingURL=chunk-LGB6ILTW.js.map
@@ -1,4 +1,4 @@
1
- import{a as Re,b as w,c as z,d as Pe,e as ie,f as se,g as M,h as le,i as N,j as O,n as De,o as ze,p as _e,q as We}from"./chunk-H4NSB54D.js";import{b as oe}from"./chunk-MTX4UPNB.js";import{e as Ee,i as Te}from"./chunk-QAWKN2N4.js";import{c as Ie,d as ae,e as T,f as re,g as B}from"./chunk-B2QYMUTD.js";import{a as G,b as Ce}from"./chunk-EJIY45FZ.js";import{a as Se}from"./chunk-7LN4VKDU.js";import{a as Ae}from"./chunk-IMLAPB7G.js";import{i as ne,k as ke}from"./chunk-AKWBDCMU.js";import{b as xe}from"./chunk-YMX3QCV7.js";import{c as ye,e as we}from"./chunk-LQE73AZR.js";import{b as $e}from"./chunk-MRIVENBY.js";import{G as K}from"./chunk-2BEZU5OF.js";import{a as L,b as F}from"./chunk-NMYPZR4W.js";import{a as ve}from"./chunk-AXHP6TMT.js";import{a as be}from"./chunk-ROLSSYXE.js";import{A as me,Aa as te,E as dt,V as fe,aa as ct,pa as ee,ra as H,sa as he,z as Z}from"./chunk-MGM33GOW.js";import{existsSync as j,readFileSync as Oe,writeFileSync as Ue,appendFileSync as ut,mkdirSync as mt}from"fs";import{dirname as ft,resolve as _}from"path";import{fileURLToPath as ht}from"url";import{hostname as bt}from"os";import{spawn as vt}from"child_process";function Me(e,t){let n=e.configExists?e.agentCount===0?"Add your first agent":"Add another agent":"Set up your team",a=`<header class="ax-topbar">
1
+ import{a as Re,b as w,c as z,d as Pe,e as ie,f as se,g as M,h as le,i as N,j as O,n as De,o as ze,p as _e,q as We}from"./chunk-XVTD6I34.js";import{e as Ee,i as Te}from"./chunk-QAWKN2N4.js";import{b as oe}from"./chunk-MTX4UPNB.js";import{c as Ie,d as ae,e as T,f as re,g as B}from"./chunk-B2QYMUTD.js";import{a as G,b as Ce}from"./chunk-EJIY45FZ.js";import{a as Se}from"./chunk-7LN4VKDU.js";import{a as Ae}from"./chunk-IMLAPB7G.js";import{b as $e}from"./chunk-MRIVENBY.js";import{i as ne,k as ke}from"./chunk-AKWBDCMU.js";import{b as xe}from"./chunk-YMX3QCV7.js";import{c as ye,e as we}from"./chunk-LQE73AZR.js";import{G as K}from"./chunk-HWYU6XG2.js";import{a as L,b as F}from"./chunk-NMYPZR4W.js";import{a as ve}from"./chunk-AXHP6TMT.js";import{a as be}from"./chunk-ROLSSYXE.js";import{A as me,Aa as te,E as dt,V as fe,aa as ct,pa as ee,ra as H,sa as he,z as Z}from"./chunk-MGM33GOW.js";import{existsSync as j,readFileSync as Oe,writeFileSync as Ue,appendFileSync as ut,mkdirSync as mt}from"fs";import{dirname as ft,resolve as _}from"path";import{fileURLToPath as ht}from"url";import{hostname as bt}from"os";import{spawn as vt}from"child_process";function Me(e,t){let n=e.configExists?e.agentCount===0?"Add your first agent":"Add another agent":"Set up your team",a=`<header class="ax-topbar">
2
2
  <div class="ax-topbar__left">
3
3
  <div class="ax-brand">
4
4
  <span class="ax-brand__mark">AX</span>
@@ -858,4 +858,4 @@ tr:hover td { background: var(--bg-hover); }
858
858
  WHERE person = ? AND state IN (${n.map(()=>"?").join(",")})
859
859
  ${a}`).all(t,...n,...o).map(i=>({id:i.id,state:i.state,channel:i.channel,agentId:i.agent_id,text:i.text,createdAt:i.created_at})):[]}function ga(e,t){return et(e,t,Z,"ORDER BY created_at")}function ua(e,t,n=50){return et(e,t,[...Z,...me],"ORDER BY created_at DESC, rowid DESC LIMIT ?",Math.max(1,Math.min(n,500)))}ct();var ue="member:",Yt=90,Vt="members",Xt="tailscale-user-login",Qt=400,Zt=60*60*1e3;function en(e){let t=e.scopes.find(n=>n.startsWith(ue));return t?t.slice(ue.length):null}function nt(e,t){if(!e)return null;let n=t.verify(e),a=n?en(n):null;return n&&a?{rec:n,personId:a}:null}function ya(e,t){let n=e.people().find(s=>s.id===t);if(!n)return{ok:!1,error:`No person "${t}". Add them first: agentx people add ${t} --name "\u2026"`};let{token:a,record:o}=e.tokens.create({name:`${n.name} (machine not paired yet)`,scopes:[`${ue}${n.id}`],expiresInDays:Yt}),{code:r,expiresAt:i}=e.codes.create({token:a,tokenId:o.id,name:n.id});return e.members.log({person:n.id,device:o.id,event:"invited"}),{ok:!0,code:r,expiresAt:i,tokenId:o.id,person:n}}var tn=Math.round(ye/6e4);function nn(e){return e==="client"?"Your project":"My work"}function wa(e){let t=nn(e.person.role),n=e.person.role==="client"?`I use AgentX to keep track of the work I do for you. It has a page for you, "${t}": what you asked us for, and where each request stands.`:`I use AgentX to give our AI agents their jobs. It has a page for you, "${t}": what you asked the agents for, and where each request stands.`;return[`Hi ${e.person.name},`,"",n,"","To open it:","1. Accept the Tailscale share I sent you. Tailscale is a small program that connects your computer to mine, privately.",`2. Open ${e.origin.replace(/\/+$/,"")}/member in Edge or Chrome, give your computer a name and type this code: ${we(e.code)}`,` The code works once, for ${tn} minutes. If it has stopped working, tell me and I will send you a new one.`,"","I then approve your machine, and the page opens by itself."].join(`
860
860
  `)}var an="The private network says someone else is connecting from this machine. Ask the person who invited you for a new code.",rn="Too many machines are waiting for the owner's answer. Try again later.",tt="That code didn't work. Check it, or ask the person who invited you for a new one.",at=(e,t)=>{let n=e.headers[t];return(Array.isArray(n)?n[0]:n||"").trim()};function rt(e){let t=e.socket?.remoteAddress||"";return t==="127.0.0.1"||t==="::1"||t==="::ffff:127.0.0.1"}function on(e){if(!rt(e))return null;let t=at(e,Xt).toLowerCase();return t?t.slice(0,80):null}function sn(e){let t=e.socket?.remoteAddress||"unknown";if(!rt(e))return t;let n=at(e,"x-forwarded-for").split(",").pop().trim();return/^[0-9a-fA-F:.]{2,45}$/.test(n)?n:t}function ln(e){return typeof e=="string"?e.replace(/[^\p{L}\p{N} ._'()-]/gu," ").replace(/\s+/g," ").trim().slice(0,60):""}function dn(e){return e.identities.map(fe).filter(t=>!!t&&t.channel==="tailscale").map(t=>t.value)}async function ka(e,t){let n=Date.now(),a=t.now??Date.now,o=t.log??(b=>console.log(b)),r=sn(e),i=t.limiter.retryAfter(r);if(i>0)return o(`[member] pair-code refused from ${r}: locked out for ${i}s more`),{status:429,body:{error:"too many attempts",retryAfter:i},retryAfter:i};let s=null,l="";try{let b=await xe(e,2048);s=b.code,l=ln(b.machine)}catch{}let c=t.codes.redeem(s),d=c?nt(c.token,t.tokens):null;if(await pn(n,t.minMs??Qt),!c||!d)return t.limiter.fail(r),o(`[member] pair-code failed from ${r}`),{status:401,body:{error:tt}};t.limiter.succeed(r);let{rec:m,personId:p}=d,k=t.people().find(b=>b.id===p);if(!k)return t.tokens.revoke(m.id),t.members.log({person:p,device:m.id,event:"refused",address:r,detail:"person no longer listed"}),o(`[member] pair-code for ${p} refused from ${r}: person no longer listed`),{status:403,body:{error:tt}};let u=on(e),f=dn(k);if(f.length&&(!u||!f.includes(u)))return t.tokens.revoke(m.id),t.members.log({person:p,device:m.id,event:"refused",address:r,detail:`network login ${u??"missing"}; expected ${f.join(" or ")}`}),o(`[member] ${p}: pairing from ${r} refused: the network says "${u??"nobody"}", expected ${f.join(" or ")}`),{status:403,body:{error:an}};let I=l||"Unnamed machine",x=k.name.slice(0,40),v=ke(t.root,{title:`New machine for ${x}`,ask:`From ${r}, ${u?`network login ${u}`:"no network login reported"}. Machine name, as typed there: "${I}". Let it see ${x}'s own work?`,recommend:`Yes if ${x} told you they just paired this machine. No if you did not expect it.`,if_silent:"discard",raised_by:Vt},{now:a()});return v.ok?(t.members.add({tokenId:m.id,personId:p,name:I,state:"pending",cardId:v.card.id,address:r,...u?{network:u}:{},createdAt:new Date(a()).toISOString()}),t.members.log({person:p,device:m.id,event:"paired",address:r,detail:I}),o(`[member] ${p} paired "${I}" from ${r}; waiting for the owner (card ${v.card.id})`),{status:200,body:{person:p,name:I,state:"pending"},token:c.token}):(t.tokens.revoke(m.id),t.members.log({person:p,device:m.id,event:"refused",address:r,detail:v.error}),o(`[member] ${p}: pairing from ${r} refused: ${v.error}`),{status:503,body:{error:rn}})}var Q="this machine is not paired",cn="waiting for the owner to approve this machine";function ot(e){return e?e.status==="decided"?e.verdict??null:e.status==="expired"?"no":null:null}function $a(e,t){return t.state==="pending"&&t.cardId?ot(ne(e,t.cardId)):null}function Aa(e,t,n){let a=t.now??Date.now,o=t.log??(d=>console.log(d)),r=nt(e,t.tokens);if(!r)return{ok:!1,status:401,error:Q};let{rec:i,personId:s}=r,l=t.members.byToken(i.id);if(!l||l.state==="removed"||l.personId!==s)return{ok:!1,status:401,error:Q};if(t.people&&!t.people().some(d=>d.id===s))return it(t,i.id,"person no longer listed"),o(`[member] ${s}: "${l.name}" ended: person no longer listed`),{ok:!1,status:401,error:Q};if(l.state==="pending"){let d=l.cardId?ne(t.root,l.cardId):null,m=ot(d);if(m==="yes")l=t.members.update(i.id,{state:"active",approvedAt:new Date(a()).toISOString()})??l,t.members.log({person:s,device:i.id,event:"approved",detail:d?.decided_by}),o(`[member] ${s}: "${l.name}" approved`);else if(m==="no"){let p=d?.status==="expired"?"the owner did not answer in time":"the owner said no";return t.tokens.revoke(i.id),t.members.update(i.id,{state:"removed",removedAt:new Date(a()).toISOString(),removedReason:p}),t.members.log({person:s,device:i.id,event:"refused",detail:p}),o(`[member] ${s}: "${l.name}" refused: ${p}`),{ok:!1,status:401,error:Q}}else return{ok:!1,status:403,error:cn,waiting:!0}}let c=l.lastSeenAt?Date.parse(l.lastSeenAt):0;return n&&(a()-c>=Zt||l.lastAddress!==n)&&(l=t.members.update(i.id,{lastSeenAt:new Date(a()).toISOString(),lastAddress:n})??l,t.members.log({person:s,device:i.id,event:"signed-in",address:n})),{ok:!0,device:l,personId:s,rec:i}}function it(e,t,n="removed by the owner"){let a=e.members.byToken(t);if(!a)return null;e.tokens.revoke(t);let o=e.members.update(t,{state:"removed",removedAt:new Date((e.now??Date.now)()).toISOString(),removedReason:n});return e.members.log({person:a.personId,device:t,event:"removed",detail:n}),o}function Sa(e,t){return e.members.devices(t).filter(n=>n.state!=="removed").map(n=>it(e,n.tokenId,"person removed by the owner")).filter(n=>!!n)}async function pn(e,t){let n=e+t-Date.now();n>0&&await new Promise(a=>setTimeout(a,n))}var st=["gitlab","github"];function gn(e,t,n){let a=String(t||"").trim().toLowerCase();if(!st.includes(a))throw new Error(`Request status works on ${st.join(" and ")}, not on "${t}".`);e.requestStatus=e.requestStatus&&typeof e.requestStatus=="object"?e.requestStatus:{};let o=Array.isArray(e.requestStatus.channels)?e.requestStatus.channels.map(r=>String(r).toLowerCase()):[];return e.requestStatus.channels=n?[...new Set([...o,a])]:o.filter(r=>r!==a),`request status on ${a} is ${n?"on":"off"}`}function Ea(e){return Array.isArray(e?.requestStatus?.channels)?e.requestStatus.channels.map(t=>String(t).toLowerCase()):[]}function Ta(e){let{summary:t}=G(n=>gn(n,e?.channel,!!e?.enabled));return{summary:t}}function Pa(e){return new Set(Object.entries(e).filter(([,t])=>t?.wiki?.absorb?.enabled===!1).map(([t])=>t))}function Da(e,t){return t.only?{agents:[t.only],skipped:[]}:{agents:e.filter(n=>!t.off.has(n)),skipped:e.filter(n=>t.off.has(n))}}function za(e,t){return`absorb is off for this agent (agents.${e}.wiki.absorb.enabled); skipped.${e===t?" It reads the wiki notes inbox, so the inbox was not read.":""} Use --agent ${e} to run it anyway.`}function _a(e,t){if(t){if(!e.wiki?.absorb)return;delete e.wiki.absorb.enabled,Object.keys(e.wiki.absorb).length===0&&delete e.wiki.absorb,Object.keys(e.wiki).length===0&&delete e.wiki;return}e.wiki??={},e.wiki.absorb??={},e.wiki.absorb.enabled=!1}var un="https://ntfy.sh";function Ma(e){return{enabled:!!e?.enabled,server:e?.server||un,topicSet:!!e?.topic,tokenSet:!!e?.token}}function Na(e,t){let n={...e??{}};if("enabled"in t&&(n.enabled=!!t.enabled),"server"in t){let a=String(t.server).trim().replace(/\/+$/,"");if(!/^https?:\/\/\S+$/.test(a))throw new Error("ntfy server must be an http(s) URL");n.server=a}if("topic"in t){let a=String(t.topic).trim();if(!a)throw new Error("ntfy topic cannot be empty");n.topic=a}if("token"in t){let a=String(t.token??"").trim();a?n.token=a:delete n.token}if(n.enabled&&!n.topic)throw new Error("set a topic before enabling ntfy");return n}export{Be as a,An as b,Sn as c,In as d,Pn as e,Dn as f,zn as g,pa as h,ga as i,ua as j,Yt as k,ya as l,tn as m,nn as n,wa as o,sn as p,ka as q,$a as r,Aa as s,it as t,Sa as u,st as v,gn as w,Ea as x,Ta as y,Pa as z,Da as A,za as B,_a as C,Ma as D,Na as E,Ht as F,ta as G,sa as H,la as I};
861
- //# sourceMappingURL=chunk-JBYLG3CQ.js.map
861
+ //# sourceMappingURL=chunk-P4TSZDVO.js.map
@@ -1,8 +1,8 @@
1
1
  import{a as w}from"./chunk-W4YR2RO2.js";var x=new Map,ie=/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/;function g(e){if(!ie.test(e.name))throw new Error(`built-in action name must be dotted lowercase identifier (got "${e.name}")`);x.set(e.name,e)}function ae(e){return x.get(e)}function ce(){let e=[];for(let[n,t]of x.entries())e.push({name:n,description:t.description,timeoutMs:t.timeoutMs});return e.sort((n,t)=>n.name.localeCompare(t.name)),e}function T(){x.clear()}var le=6e4;async function ue(e,n){let t=x.get(e);if(!t)throw new Error(`unknown built-in action: ${e}`);let r=t.inputSchema.parse(n),o=t.timeoutMs??le,i=t.handler(r),a=new Promise((b,I)=>{setTimeout(()=>I(new Error(`built-in action ${e} timed out after ${o}ms`)),o)}),c=await Promise.race([i,a]),m=t.outputSchema.safeParse(c);return m.success||process.stderr.write(`[builtin-action] ${e} output failed schema validation: ${m.error.message}
2
- `),c}import{z as l}from"zod";var R=null;function k(){return R}function rt(e){R=e}var de=l.object({agentId:l.string().min(1),message:l.string().min(1),freshSession:l.boolean().default(!0),channel:l.string().default("api"),chatId:l.string().optional(),senderAgentId:l.string().optional(),timeoutMs:l.number().int().min(1).max(6e5).default(9e4)}),pe=l.object({agentId:l.string(),reply:l.string(),error:l.string().optional(),errorKind:l.string().optional(),usage:l.object({inputTokens:l.number().int().default(0),outputTokens:l.number().int().default(0),cacheReadTokens:l.number().int().default(0),cacheCreateTokens:l.number().int().default(0)}).default({inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreateTokens:0}),durationMs:l.number().int().default(0)}),M={name:"agent.call",description:"Dispatch a task to a local agent on the same daemon (fresh session by default \u2014 replaces ad-hoc 'Bash curl /task' delegation)",inputSchema:de,outputSchema:pe,timeoutMs:6e5,handler:async e=>{let n=k();if(!n)throw new Error("agent registry not wired (daemon not started or running in a non-daemon process)");let t=e.chatId??`agent-call-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,r=Date.now(),o=await n.execute({agentId:e.agentId,message:e.message,freshSession:e.freshSession,context:{channel:e.channel,chatId:t}});return{agentId:e.agentId,reply:o.content??"",error:o.error,errorKind:o.errorKind,usage:{inputTokens:o.usage?.inputTokens??0,outputTokens:o.usage?.outputTokens??0,cacheReadTokens:o.usage?.cacheReadTokens??0,cacheCreateTokens:o.usage?.cacheCreateTokens??0},durationMs:o.duration??Date.now()-r}}};import{z as s}from"zod";var ge=s.object({channel:s.string().min(1),chatId:s.string().min(1),text:s.string().min(1),agentId:s.string().optional(),accountId:s.string().optional(),replyTo:s.string().optional(),idempotencyKey:s.string().optional(),buttons:s.array(s.object({label:s.string(),url:s.string()})).optional(),poll:s.object({name:s.string(),values:s.array(s.string()),selectableCount:s.number().optional()}).optional(),media:s.object({type:s.enum(["image","document","audio","video"]),url:s.string(),caption:s.string().optional()}).optional()}),me=s.object({messageId:s.string().nullable()}),C={name:"channel.reply",description:"Post a reply to a channel (gitlab/github comment, telegram/whatsapp message, \u2026) through the canonical adapter \u2014 auto-marker, auto-dedupe within 60s, identity resolved from agentMappings.",inputSchema:ge,outputSchema:me,timeoutMs:3e4,handler:async e=>{let n=w();if(!n)throw new Error("message router not wired (daemon not started or running in a non-daemon process)");let t=e.idempotencyKey??"",r=await n.sendOutbound({channel:e.channel,chatId:e.chatId,text:e.text,agentId:e.agentId,accountId:e.accountId,replyTo:e.replyTo,buttons:e.buttons,poll:e.poll,media:e.media},{idempotencyKey:t,dedupeWindowMs:6e4});return{messageId:typeof r=="string"?r:null}}},he=s.object({channel:s.literal("gitlab"),project:s.string().min(1),kind:s.enum(["issue","merge_request"]),iid:s.string().min(1),add:s.array(s.string()).default([]),remove:s.array(s.string()).default([]),agentId:s.string().optional()}),fe=s.object({labels:s.array(s.string())}),B={name:"channel.label",description:"Add and/or remove labels on a GitLab issue/MR through the adapter (per-agent token, ledger, no raw curl).",inputSchema:he,outputSchema:fe,timeoutMs:3e4,handler:async e=>{let n=w();if(!n)throw new Error("message router not wired");let t=n.getChannel?.(e.channel);if(!t?.setLabels)throw new Error(`channel "${e.channel}" does not expose setLabels`);let r=await t.setLabels({project:e.project,kind:e.kind,iid:e.iid,add:e.add,remove:e.remove,agentId:e.agentId});return{labels:Array.isArray(r)?r:[]}}},ye=s.object({channel:s.literal("gitlab"),project:s.string().min(1),kind:s.enum(["issue","merge_request"]),iid:s.string().min(1),assignees:s.array(s.string()).default([]),agentId:s.string().optional()}),be=s.object({assigneeIds:s.array(s.number())}),E={name:"channel.assign",description:"Set assignees on a GitLab issue or MR (replaces the assignee list). Pass empty array to unassign. Use during Triage\u2192To Do flip to assign the coding agent, or to designate reviewer/merger on an MR.",inputSchema:ye,outputSchema:be,timeoutMs:3e4,handler:async e=>{let n=w();if(!n)throw new Error("message router not wired");let t=n.getChannel?.(e.channel);if(!t?.setAssignees)throw new Error(`channel "${e.channel}" does not expose setAssignees`);let r=await t.setAssignees({project:e.project,kind:e.kind,iid:e.iid,assignees:e.assignees,agentId:e.agentId});return{assigneeIds:Array.isArray(r)?r:[]}}},Ie=s.object({channel:s.literal("gitlab"),project:s.string().min(1),title:s.string().min(1),description:s.string().default(""),labels:s.array(s.string()).default([]),assignees:s.array(s.string()).default([]),agentId:s.string().optional(),relateToIid:s.string().optional()}),we=s.object({iid:s.number(),url:s.string(),related:s.boolean().default(!1)}),L={name:"channel.create_issue",description:"Create a GitLab issue from an agent (PM test cases, CX client requests). Honors per-agent identity; resolves assignee usernames to ids; optional /relate to a parent issue.",inputSchema:Ie,outputSchema:we,timeoutMs:6e4,handler:async e=>{let n=w();if(!n)throw new Error("message router not wired");let t=n.getChannel?.(e.channel);if(!t?.createIssue)throw new Error(`channel "${e.channel}" does not expose createIssue`);let r=await t.createIssue({project:e.project,title:e.title,description:e.description,labels:e.labels,assignees:e.assignees,agentId:e.agentId});if(!r)throw new Error("createIssue returned null \u2014 see daemon log for details");let o=!1;return e.relateToIid&&t.relateIssue&&(o=await t.relateIssue({project:e.project,sourceIid:String(r.iid),targetIid:e.relateToIid,agentId:e.agentId})),{iid:r.iid,url:r.url,related:o}}};import{z as p}from"zod";var xe=p.object({model:p.string().default("claude-haiku-4-5"),prompt:p.string().min(1),schema:p.record(p.string(),p.unknown()),systemPrompt:p.string().optional(),maxTokens:p.number().int().min(1).max(8e3).default(1024),timeoutMs:p.number().int().min(1).max(12e4).default(6e4)}),Se=p.object({data:p.unknown(),model:p.string(),usage:p.object({inputTokens:p.number().int(),outputTokens:p.number().int()})}),Ae="https://api.anthropic.com/v1/messages",Oe="2023-06-01",j={name:"extract.structured",description:"Single-call typed extraction: prompt + JSON-Schema \u2192 structured data via forced tool_use",inputSchema:xe,outputSchema:Se,timeoutMs:12e4,handler:async e=>{let n=process.env.ANTHROPIC_API_KEY;if(!n)throw new Error("ANTHROPIC_API_KEY env var is not set \u2014 extract.structured needs direct API access");let t={model:e.model,max_tokens:e.maxTokens,messages:[{role:"user",content:e.prompt}],tools:[{name:"respond_with_structure",description:"Return a structured value matching the schema",input_schema:e.schema}],tool_choice:{type:"tool",name:"respond_with_structure"}};e.systemPrompt&&(t.system=e.systemPrompt);let r=new AbortController,o=setTimeout(()=>r.abort(),e.timeoutMs),i;try{i=await fetch(Ae,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":n,"anthropic-version":Oe},body:JSON.stringify(t),signal:r.signal})}finally{clearTimeout(o)}if(!i.ok){let I=await i.text().catch(()=>"");throw new Error(`anthropic API ${i.status}: ${I.slice(0,500)}`)}let a=await i.json(),c=Array.isArray(a.content)?a.content:[],m=c.find(I=>I?.type==="tool_use"&&I?.name==="respond_with_structure");if(!m||m.input===void 0)throw new Error(`anthropic API returned no respond_with_structure tool_use (got ${c.length} blocks)`);let b=a.usage??{};return{data:m.input,model:typeof a.model=="string"?a.model:e.model,usage:{inputTokens:typeof b.input_tokens=="number"?b.input_tokens:0,outputTokens:typeof b.output_tokens=="number"?b.output_tokens:0}}}};import{z as u}from"zod";import{existsSync as _e,readFileSync as Te,appendFileSync as Re,mkdirSync as ke,statSync as Me}from"fs";import{resolve as v,dirname as Ce,isAbsolute as Be}from"path";var D=8*1024*1024;function z(e){let n=Be(e)?e:v(process.cwd(),e),r=(process.env.AGENTX_BUILTIN_FILE_ROOTS||process.cwd()).split(":").map(o=>v(o));for(let o of r)if(n===o||n.startsWith(o+"/"))return n;throw new Error(`path "${e}" is outside the allowed roots`)}var Ee=u.object({path:u.string().min(1),maxLines:u.number().int().min(1).max(1e4).default(200),fromEnd:u.boolean().default(!1)}),Le=u.object({path:u.string(),lines:u.array(u.string()),totalLines:u.number().int(),truncated:u.boolean()}),P={name:"file.read_lines",description:"Read a text file as an array of lines (utf-8, 8MB cap, scoped to allowed roots)",inputSchema:Ee,outputSchema:Le,timeoutMs:1e4,handler:async e=>{let n=z(e.path);if(!_e(n))throw new Error(`file not found: ${e.path}`);let t=Me(n);if(!t.isFile())throw new Error(`not a regular file: ${e.path}`);if(t.size>D)throw new Error(`file too large (${t.size} > ${D} bytes)`);let o=Te(n,"utf8").split(`
2
+ `),c}import{z as l}from"zod";var k=null;function R(){return k}function rt(e){k=e}var de=l.object({agentId:l.string().min(1),message:l.string().min(1),freshSession:l.boolean().default(!0),channel:l.string().default("api"),chatId:l.string().optional(),senderAgentId:l.string().optional(),timeoutMs:l.number().int().min(1).max(6e5).default(9e4)}),pe=l.object({agentId:l.string(),reply:l.string(),error:l.string().optional(),errorKind:l.string().optional(),usage:l.object({inputTokens:l.number().int().default(0),outputTokens:l.number().int().default(0),cacheReadTokens:l.number().int().default(0),cacheCreateTokens:l.number().int().default(0)}).default({inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreateTokens:0}),durationMs:l.number().int().default(0)}),M={name:"agent.call",description:"Dispatch a task to a local agent on the same daemon (fresh session by default \u2014 replaces ad-hoc 'Bash curl /task' delegation)",inputSchema:de,outputSchema:pe,timeoutMs:6e5,handler:async e=>{let n=R();if(!n)throw new Error("agent registry not wired (daemon not started or running in a non-daemon process)");let t=e.chatId??`agent-call-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,r=Date.now(),o=await n.execute({agentId:e.agentId,message:e.message,freshSession:e.freshSession,context:{channel:e.channel,chatId:t}});return{agentId:e.agentId,reply:o.content??"",error:o.error,errorKind:o.errorKind,usage:{inputTokens:o.usage?.inputTokens??0,outputTokens:o.usage?.outputTokens??0,cacheReadTokens:o.usage?.cacheReadTokens??0,cacheCreateTokens:o.usage?.cacheCreateTokens??0},durationMs:o.duration??Date.now()-r}}};import{z as s}from"zod";var ge=s.object({channel:s.string().min(1),chatId:s.string().min(1),text:s.string().min(1),agentId:s.string().optional(),accountId:s.string().optional(),replyTo:s.string().optional(),idempotencyKey:s.string().optional(),buttons:s.array(s.object({label:s.string(),url:s.string()})).optional(),poll:s.object({name:s.string(),values:s.array(s.string()),selectableCount:s.number().optional()}).optional(),media:s.object({type:s.enum(["image","document","audio","video"]),url:s.string(),caption:s.string().optional()}).optional()}),me=s.object({messageId:s.string().nullable()}),C={name:"channel.reply",description:"Post a reply to a channel (gitlab/github comment, telegram/whatsapp message, \u2026) through the canonical adapter \u2014 auto-marker, auto-dedupe within 60s, identity resolved from agentMappings.",inputSchema:ge,outputSchema:me,timeoutMs:3e4,handler:async e=>{let n=w();if(!n)throw new Error("message router not wired (daemon not started or running in a non-daemon process)");let t=e.idempotencyKey??"",r=await n.sendOutbound({channel:e.channel,chatId:e.chatId,text:e.text,agentId:e.agentId,accountId:e.accountId,replyTo:e.replyTo,buttons:e.buttons,poll:e.poll,media:e.media},{idempotencyKey:t,dedupeWindowMs:6e4});return{messageId:typeof r=="string"?r:null}}},he=s.object({channel:s.literal("gitlab"),project:s.string().min(1),kind:s.enum(["issue","merge_request"]),iid:s.string().min(1),add:s.array(s.string()).default([]),remove:s.array(s.string()).default([]),agentId:s.string().optional()}),fe=s.object({labels:s.array(s.string())}),E={name:"channel.label",description:"Add and/or remove labels on a GitLab issue/MR through the adapter (per-agent token, ledger, no raw curl).",inputSchema:he,outputSchema:fe,timeoutMs:3e4,handler:async e=>{let n=w();if(!n)throw new Error("message router not wired");let t=n.getChannel?.(e.channel);if(!t?.setLabels)throw new Error(`channel "${e.channel}" does not expose setLabels`);let r=await t.setLabels({project:e.project,kind:e.kind,iid:e.iid,add:e.add,remove:e.remove,agentId:e.agentId});if(!Array.isArray(r))throw new Error("setLabels did not apply the change \u2014 see daemon log for details");return{labels:r}}},ye=s.object({channel:s.literal("gitlab"),project:s.string().min(1),kind:s.enum(["issue","merge_request"]),iid:s.string().min(1),assignees:s.array(s.string()).default([]),agentId:s.string().optional()}),be=s.object({assigneeIds:s.array(s.number())}),L={name:"channel.assign",description:"Set assignees on a GitLab issue or MR (replaces the assignee list). Pass empty array to unassign. Use during Triage\u2192To Do flip to assign the coding agent, or to designate reviewer/merger on an MR.",inputSchema:ye,outputSchema:be,timeoutMs:3e4,handler:async e=>{let n=w();if(!n)throw new Error("message router not wired");let t=n.getChannel?.(e.channel);if(!t?.setAssignees)throw new Error(`channel "${e.channel}" does not expose setAssignees`);let r=await t.setAssignees({project:e.project,kind:e.kind,iid:e.iid,assignees:e.assignees,agentId:e.agentId});if(!Array.isArray(r))throw new Error("setAssignees did not apply the change (no assignee resolved, or no token) \u2014 see daemon log for details");return{assigneeIds:r}}},Ie=s.object({channel:s.literal("gitlab"),project:s.string().min(1),title:s.string().min(1),description:s.string().default(""),labels:s.array(s.string()).default([]),assignees:s.array(s.string()).default([]),agentId:s.string().optional(),relateToIid:s.string().optional()}),we=s.object({iid:s.number(),url:s.string(),related:s.boolean().default(!1)}),B={name:"channel.create_issue",description:"Create a GitLab issue from an agent (PM test cases, CX client requests). Honors per-agent identity; resolves assignee usernames to ids; optional /relate to a parent issue.",inputSchema:Ie,outputSchema:we,timeoutMs:6e4,handler:async e=>{let n=w();if(!n)throw new Error("message router not wired");let t=n.getChannel?.(e.channel);if(!t?.createIssue)throw new Error(`channel "${e.channel}" does not expose createIssue`);let r=await t.createIssue({project:e.project,title:e.title,description:e.description,labels:e.labels,assignees:e.assignees,agentId:e.agentId});if(!r)throw new Error("createIssue returned null \u2014 see daemon log for details");let o=!1;return e.relateToIid&&t.relateIssue&&(o=await t.relateIssue({project:e.project,sourceIid:String(r.iid),targetIid:e.relateToIid,agentId:e.agentId})),{iid:r.iid,url:r.url,related:o}}};import{z as p}from"zod";var xe=p.object({model:p.string().default("claude-haiku-4-5"),prompt:p.string().min(1),schema:p.record(p.string(),p.unknown()),systemPrompt:p.string().optional(),maxTokens:p.number().int().min(1).max(8e3).default(1024),timeoutMs:p.number().int().min(1).max(12e4).default(6e4)}),Se=p.object({data:p.unknown(),model:p.string(),usage:p.object({inputTokens:p.number().int(),outputTokens:p.number().int()})}),Ae="https://api.anthropic.com/v1/messages",Oe="2023-06-01",j={name:"extract.structured",description:"Single-call typed extraction: prompt + JSON-Schema \u2192 structured data via forced tool_use",inputSchema:xe,outputSchema:Se,timeoutMs:12e4,handler:async e=>{let n=process.env.ANTHROPIC_API_KEY;if(!n)throw new Error("ANTHROPIC_API_KEY env var is not set \u2014 extract.structured needs direct API access");let t={model:e.model,max_tokens:e.maxTokens,messages:[{role:"user",content:e.prompt}],tools:[{name:"respond_with_structure",description:"Return a structured value matching the schema",input_schema:e.schema}],tool_choice:{type:"tool",name:"respond_with_structure"}};e.systemPrompt&&(t.system=e.systemPrompt);let r=new AbortController,o=setTimeout(()=>r.abort(),e.timeoutMs),i;try{i=await fetch(Ae,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":n,"anthropic-version":Oe},body:JSON.stringify(t),signal:r.signal})}finally{clearTimeout(o)}if(!i.ok){let I=await i.text().catch(()=>"");throw new Error(`anthropic API ${i.status}: ${I.slice(0,500)}`)}let a=await i.json(),c=Array.isArray(a.content)?a.content:[],m=c.find(I=>I?.type==="tool_use"&&I?.name==="respond_with_structure");if(!m||m.input===void 0)throw new Error(`anthropic API returned no respond_with_structure tool_use (got ${c.length} blocks)`);let b=a.usage??{};return{data:m.input,model:typeof a.model=="string"?a.model:e.model,usage:{inputTokens:typeof b.input_tokens=="number"?b.input_tokens:0,outputTokens:typeof b.output_tokens=="number"?b.output_tokens:0}}}};import{z as u}from"zod";import{existsSync as _e,readFileSync as Te,appendFileSync as ke,mkdirSync as Re,statSync as Me}from"fs";import{resolve as v,dirname as Ce,isAbsolute as Ee}from"path";var D=8*1024*1024;function z(e){let n=Ee(e)?e:v(process.cwd(),e),r=(process.env.AGENTX_BUILTIN_FILE_ROOTS||process.cwd()).split(":").map(o=>v(o));for(let o of r)if(n===o||n.startsWith(o+"/"))return n;throw new Error(`path "${e}" is outside the allowed roots`)}var Le=u.object({path:u.string().min(1),maxLines:u.number().int().min(1).max(1e4).default(200),fromEnd:u.boolean().default(!1)}),Be=u.object({path:u.string(),lines:u.array(u.string()),totalLines:u.number().int(),truncated:u.boolean()}),P={name:"file.read_lines",description:"Read a text file as an array of lines (utf-8, 8MB cap, scoped to allowed roots)",inputSchema:Le,outputSchema:Be,timeoutMs:1e4,handler:async e=>{let n=z(e.path);if(!_e(n))throw new Error(`file not found: ${e.path}`);let t=Me(n);if(!t.isFile())throw new Error(`not a regular file: ${e.path}`);if(t.size>D)throw new Error(`file too large (${t.size} > ${D} bytes)`);let o=Te(n,"utf8").split(`
3
3
  `);o.length>0&&o[o.length-1]===""&&o.pop();let i=o.length,a,c;return i<=e.maxLines?(a=o,c=!1):(c=!0,a=e.fromEnd?o.slice(i-e.maxLines):o.slice(0,e.maxLines)),{path:n,lines:a,totalLines:i,truncated:c}}},je=u.object({path:u.string().min(1),records:u.array(u.unknown()).min(1),createDirs:u.boolean().default(!1)}),ve=u.object({path:u.string(),written:u.number().int(),bytesAppended:u.number().int()}),$={name:"file.write_jsonl",description:"Append JSON records to a file as newline-delimited JSON (utf-8, scoped to allowed roots)",inputSchema:je,outputSchema:ve,timeoutMs:1e4,handler:async e=>{let n=z(e.path),t=[];for(let o of e.records)try{t.push(JSON.stringify(o))}catch(i){throw new Error(`record ${t.length} not JSON-serializable: ${i?.message||String(i)}`)}let r=t.join(`
4
4
  `)+`
5
- `;return e.createDirs&&ke(Ce(n),{recursive:!0}),Re(n,r,"utf8"),{path:n,written:t.length,bytesAppended:Buffer.byteLength(r,"utf8")}}};import{z as d}from"zod";var F=1024*1024,S=d.record(d.string(),d.string()),De=["http:","https:"];function N(e){let n;try{n=new URL(e)}catch{throw new Error(`invalid url: ${e}`)}if(!De.includes(n.protocol))throw new Error(`scheme not allowed (only http/https): ${n.protocol}`);return n}var ze=d.object({url:d.string().min(1),headers:S.optional(),timeoutMs:d.number().int().min(1).max(6e4).default(3e4)}),J=d.object({status:d.number().int(),statusText:d.string(),headers:S,body:d.string(),truncated:d.boolean(),url:d.string()});async function U(e){if(!e.body)return{body:"",truncated:!1};let n=e.body.getReader(),t=new TextDecoder,r=0,o="",i=!1;for(;;){let{done:a,value:c}=await n.read();if(a)break;if(c){if(r+=c.length,r>F){o+=t.decode(c.slice(0,F-(r-c.length)),{stream:!1}),i=!0;try{await n.cancel()}catch{}break}o+=t.decode(c,{stream:!0})}}return o+=t.decode(),{body:o,truncated:i}}function H(e){let n={};return e.forEach((t,r)=>{n[r]=t}),n}var K={name:"http.fetch",description:"GET a URL, return body + status + headers (1MB cap, http/https only)",inputSchema:ze,outputSchema:J,timeoutMs:35e3,handler:async e=>{N(e.url);let n=new AbortController,t=setTimeout(()=>n.abort(),e.timeoutMs);try{let r=await fetch(e.url,{method:"GET",headers:e.headers??{},signal:n.signal}),{body:o,truncated:i}=await U(r);return{status:r.status,statusText:r.statusText,headers:H(r.headers),body:o,truncated:i,url:r.url}}finally{clearTimeout(t)}}},Pe=d.object({url:d.string().min(1),body:d.unknown(),headers:S.optional(),timeoutMs:d.number().int().min(1).max(6e4).default(3e4)}),q={name:"http.post",description:"POST a JSON body to a URL, return body + status + headers (1MB cap, http/https only)",inputSchema:Pe,outputSchema:J,timeoutMs:35e3,handler:async e=>{N(e.url);let n=new AbortController,t=setTimeout(()=>n.abort(),e.timeoutMs);try{let r={"Content-Type":"application/json",...e.headers??{}},o=await fetch(e.url,{method:"POST",headers:r,body:JSON.stringify(e.body??{}),signal:n.signal}),{body:i,truncated:a}=await U(o);return{status:o.status,statusText:o.statusText,headers:H(o.headers),body:i,truncated:a,url:o.url}}finally{clearTimeout(t)}}};import{z as f}from"zod";var W=null;function G(){return W}function It(e){W=e}var $e=f.object({peer:f.string().min(1),agent:f.string().optional(),message:f.string().min(1),timeoutMs:f.number().int().min(1).max(6e5).default(9e4),senderAgentId:f.string().optional(),freshSession:f.boolean().default(!0)}),Fe=f.object({peer:f.string(),agent:f.string().nullable(),response:f.string()}),X={name:"mesh.delegate",description:"Send a task to a remote mesh peer's agent and return the response text",inputSchema:$e,outputSchema:Fe,timeoutMs:6e5,handler:async e=>{let n=G();if(!n)throw new Error("mesh not enabled on this daemon (config.mesh.enabled = false)");let t=await n.sendTask(e.peer,e.message,e.agent,{timeoutMs:e.timeoutMs,senderAgentId:e.senderAgentId,freshSession:e.freshSession});return{peer:e.peer,agent:e.agent??null,response:t}}};import{z as h}from"zod";import{existsSync as Y,mkdirSync as Ne,readFileSync as O,writeFileSync as Je,statSync as Ue}from"fs";import{resolve as V,basename as He,relative as Ke}from"path";import qe from"fast-glob";import Q from"minisearch";var Z=["title","body"],ee=["title","body","path","indexedAt"];function _(e,n=".agentx/rag"){return V(process.cwd(),n,e,"index.json")}function We(){return new Q({fields:Z,storeFields:ee,searchOptions:{boost:{title:2},fuzzy:.2,prefix:!0}})}function Ge(e,n){let t=O(e,"utf8"),r=t.match(/^\s*#\s+(.+)$/m),o=r?r[1].trim():He(e).replace(/\.[^.]+$/,"");return{id:n,title:o,body:t,path:e,indexedAt:new Date().toISOString()}}async function kt(e,n,t={}){let r=t.cwd??process.cwd(),o=(await qe(n,{cwd:r,absolute:!0,dot:!1})).filter(c=>{try{return Ue(c).isFile()}catch{return!1}}),i=We();for(let c of o){let m=Ke(r,c),b=Ge(c,m);i.add(b),t.verbose&&process.stderr.write(`[rag] indexed ${m} (${b.body.length} bytes)
5
+ `;return e.createDirs&&Re(Ce(n),{recursive:!0}),ke(n,r,"utf8"),{path:n,written:t.length,bytesAppended:Buffer.byteLength(r,"utf8")}}};import{z as d}from"zod";var F=1024*1024,S=d.record(d.string(),d.string()),De=["http:","https:"];function N(e){let n;try{n=new URL(e)}catch{throw new Error(`invalid url: ${e}`)}if(!De.includes(n.protocol))throw new Error(`scheme not allowed (only http/https): ${n.protocol}`);return n}var ze=d.object({url:d.string().min(1),headers:S.optional(),timeoutMs:d.number().int().min(1).max(6e4).default(3e4)}),J=d.object({status:d.number().int(),statusText:d.string(),headers:S,body:d.string(),truncated:d.boolean(),url:d.string()});async function U(e){if(!e.body)return{body:"",truncated:!1};let n=e.body.getReader(),t=new TextDecoder,r=0,o="",i=!1;for(;;){let{done:a,value:c}=await n.read();if(a)break;if(c){if(r+=c.length,r>F){o+=t.decode(c.slice(0,F-(r-c.length)),{stream:!1}),i=!0;try{await n.cancel()}catch{}break}o+=t.decode(c,{stream:!0})}}return o+=t.decode(),{body:o,truncated:i}}function H(e){let n={};return e.forEach((t,r)=>{n[r]=t}),n}var K={name:"http.fetch",description:"GET a URL, return body + status + headers (1MB cap, http/https only)",inputSchema:ze,outputSchema:J,timeoutMs:35e3,handler:async e=>{N(e.url);let n=new AbortController,t=setTimeout(()=>n.abort(),e.timeoutMs);try{let r=await fetch(e.url,{method:"GET",headers:e.headers??{},signal:n.signal}),{body:o,truncated:i}=await U(r);return{status:r.status,statusText:r.statusText,headers:H(r.headers),body:o,truncated:i,url:r.url}}finally{clearTimeout(t)}}},Pe=d.object({url:d.string().min(1),body:d.unknown(),headers:S.optional(),timeoutMs:d.number().int().min(1).max(6e4).default(3e4)}),q={name:"http.post",description:"POST a JSON body to a URL, return body + status + headers (1MB cap, http/https only)",inputSchema:Pe,outputSchema:J,timeoutMs:35e3,handler:async e=>{N(e.url);let n=new AbortController,t=setTimeout(()=>n.abort(),e.timeoutMs);try{let r={"Content-Type":"application/json",...e.headers??{}},o=await fetch(e.url,{method:"POST",headers:r,body:JSON.stringify(e.body??{}),signal:n.signal}),{body:i,truncated:a}=await U(o);return{status:o.status,statusText:o.statusText,headers:H(o.headers),body:i,truncated:a,url:o.url}}finally{clearTimeout(t)}}};import{z as f}from"zod";var W=null;function G(){return W}function It(e){W=e}var $e=f.object({peer:f.string().min(1),agent:f.string().optional(),message:f.string().min(1),timeoutMs:f.number().int().min(1).max(6e5).default(9e4),senderAgentId:f.string().optional(),freshSession:f.boolean().default(!0)}),Fe=f.object({peer:f.string(),agent:f.string().nullable(),response:f.string()}),X={name:"mesh.delegate",description:"Send a task to a remote mesh peer's agent and return the response text",inputSchema:$e,outputSchema:Fe,timeoutMs:6e5,handler:async e=>{let n=G();if(!n)throw new Error("mesh not enabled on this daemon (config.mesh.enabled = false)");let t=await n.sendTask(e.peer,e.message,e.agent,{timeoutMs:e.timeoutMs,senderAgentId:e.senderAgentId,freshSession:e.freshSession});return{peer:e.peer,agent:e.agent??null,response:t}}};import{z as h}from"zod";import{existsSync as Y,mkdirSync as Ne,readFileSync as O,writeFileSync as Je,statSync as Ue}from"fs";import{resolve as V,basename as He,relative as Ke}from"path";import qe from"fast-glob";import Q from"minisearch";var Z=["title","body"],ee=["title","body","path","indexedAt"];function _(e,n=".agentx/rag"){return V(process.cwd(),n,e,"index.json")}function We(){return new Q({fields:Z,storeFields:ee,searchOptions:{boost:{title:2},fuzzy:.2,prefix:!0}})}function Ge(e,n){let t=O(e,"utf8"),r=t.match(/^\s*#\s+(.+)$/m),o=r?r[1].trim():He(e).replace(/\.[^.]+$/,"");return{id:n,title:o,body:t,path:e,indexedAt:new Date().toISOString()}}async function Rt(e,n,t={}){let r=t.cwd??process.cwd(),o=(await qe(n,{cwd:r,absolute:!0,dot:!1})).filter(c=>{try{return Ue(c).isFile()}catch{return!1}}),i=We();for(let c of o){let m=Ke(r,c),b=Ge(c,m);i.add(b),t.verbose&&process.stderr.write(`[rag] indexed ${m} (${b.body.length} bytes)
6
6
  `)}let a=_(e,t.baseDir);return Ne(V(a,".."),{recursive:!0}),Je(a,JSON.stringify(i.toJSON()),"utf8"),{docs:o.length,path:a}}function Xe(e,n={}){let t=_(e,n.baseDir);if(!Y(t))return null;try{let r=O(t,"utf8");return Q.loadJSON(r,{fields:Z,storeFields:ee,searchOptions:{boost:{title:2},fuzzy:.2,prefix:!0}})}catch(r){return process.stderr.write(`[rag] failed to load ${t}: ${r?.message||String(r)}
7
- `),null}}var A=80,Ye=A*2+60;function Ve(e,n){let t=e.toLowerCase(),r=-1;for(let c of n){let m=t.indexOf(c.toLowerCase());m>=0&&(r===-1||m<r)&&(r=m)}if(r===-1)return e.slice(0,Ye).replace(/\s+/g," ").trim();let o=Math.max(0,r-A),i=Math.min(e.length,r+A),a=e.slice(o,i).replace(/\s+/g," ").trim();return(o>0?"\u2026":"")+a+(i<e.length?"\u2026":"")}function te(e,n,t={}){let r=Xe(e,{baseDir:t.baseDir});if(!r)return[];let o=Math.max(1,Math.min(50,t.k??5));return r.search(n).slice(0,o).map(a=>({id:a.id,title:a.title,path:a.path,score:a.score,snippet:Ve(a.body||"",a.terms||[])}))}function Mt(e,n={}){let t=_(e,n.baseDir);if(!Y(t))return{exists:!1,path:t,docs:0};try{let r=JSON.parse(O(t,"utf8")),o=r?.storedFields??r?._storedFields;if(typeof r?.documentCount=="number")return{exists:!0,path:t,docs:r.documentCount};let i=o&&typeof o=="object"?Object.keys(o).length:0;return{exists:!0,path:t,docs:i}}catch{return{exists:!0,path:t,docs:0}}}var Qe=h.object({agentId:h.string().min(1),query:h.string().min(1),k:h.number().int().min(1).max(50).default(5)}),Ze=h.object({hits:h.array(h.object({id:h.string(),title:h.string(),path:h.string(),score:h.number(),snippet:h.string()}))}),ne={name:"rag.lexical",description:"BM25-style lexical search over an agent's pre-built index (no embeddings, deterministic)",inputSchema:Qe,outputSchema:Ze,timeoutMs:5e3,handler:async e=>({hits:te(e.agentId,e.query,{k:e.k})})};import{z as y}from"zod";var re;function jt(e){re=e}function se(){return re}var et=y.object({id:y.string().min(1),reason:y.string().max(500).optional(),by:y.string().min(1).max(100).default("workflow")}),tt=y.object({ok:y.boolean(),id:y.string(),agentId:y.string().nullable(),error:y.string().optional()}),oe={name:"signal.resume",description:"Resume a task a stop signal paused, from its resume plan, in the same chat",inputSchema:et,outputSchema:tt,handler:async e=>{let n=se();if(!n)return{ok:!1,id:e.id,agentId:null,error:"signals are not running in this process"};let t=await n.resume({kind:"owner",name:e.by},e.id,e.reason);return t.ok?{ok:!0,id:t.record.id,agentId:t.record.agentId}:{ok:!1,id:e.id,agentId:n.get(e.id)?.agentId??null,error:t.error}}};function Gt(){g(M),g(E),g(L),g(B),g(C),g(j),g(P),g($),g(K),g(q),g(X),g(ne),g(oe)}function Xt(){T()}export{ae as a,ce as b,ue as c,rt as d,It as e,kt as f,te as g,Mt as h,jt as i,Gt as j,Xt as k};
8
- //# sourceMappingURL=chunk-HF5EF335.js.map
7
+ `),null}}var A=80,Ye=A*2+60;function Ve(e,n){let t=e.toLowerCase(),r=-1;for(let c of n){let m=t.indexOf(c.toLowerCase());m>=0&&(r===-1||m<r)&&(r=m)}if(r===-1)return e.slice(0,Ye).replace(/\s+/g," ").trim();let o=Math.max(0,r-A),i=Math.min(e.length,r+A),a=e.slice(o,i).replace(/\s+/g," ").trim();return(o>0?"\u2026":"")+a+(i<e.length?"\u2026":"")}function te(e,n,t={}){let r=Xe(e,{baseDir:t.baseDir});if(!r)return[];let o=Math.max(1,Math.min(50,t.k??5));return r.search(n).slice(0,o).map(a=>({id:a.id,title:a.title,path:a.path,score:a.score,snippet:Ve(a.body||"",a.terms||[])}))}function Mt(e,n={}){let t=_(e,n.baseDir);if(!Y(t))return{exists:!1,path:t,docs:0};try{let r=JSON.parse(O(t,"utf8")),o=r?.storedFields??r?._storedFields;if(typeof r?.documentCount=="number")return{exists:!0,path:t,docs:r.documentCount};let i=o&&typeof o=="object"?Object.keys(o).length:0;return{exists:!0,path:t,docs:i}}catch{return{exists:!0,path:t,docs:0}}}var Qe=h.object({agentId:h.string().min(1),query:h.string().min(1),k:h.number().int().min(1).max(50).default(5)}),Ze=h.object({hits:h.array(h.object({id:h.string(),title:h.string(),path:h.string(),score:h.number(),snippet:h.string()}))}),ne={name:"rag.lexical",description:"BM25-style lexical search over an agent's pre-built index (no embeddings, deterministic)",inputSchema:Qe,outputSchema:Ze,timeoutMs:5e3,handler:async e=>({hits:te(e.agentId,e.query,{k:e.k})})};import{z as y}from"zod";var re;function jt(e){re=e}function se(){return re}var et=y.object({id:y.string().min(1),reason:y.string().max(500).optional(),by:y.string().min(1).max(100).default("workflow")}),tt=y.object({ok:y.boolean(),id:y.string(),agentId:y.string().nullable(),error:y.string().optional()}),oe={name:"signal.resume",description:"Resume a task a stop signal paused, from its resume plan, in the same chat",inputSchema:et,outputSchema:tt,handler:async e=>{let n=se();if(!n)return{ok:!1,id:e.id,agentId:null,error:"signals are not running in this process"};let t=await n.resume({kind:"owner",name:e.by},e.id,e.reason);return t.ok?{ok:!0,id:t.record.id,agentId:t.record.agentId}:{ok:!1,id:e.id,agentId:n.get(e.id)?.agentId??null,error:t.error}}};function Gt(){g(M),g(L),g(B),g(E),g(C),g(j),g(P),g($),g(K),g(q),g(X),g(ne),g(oe)}function Xt(){T()}export{ae as a,ce as b,ue as c,rt as d,It as e,Rt as f,te as g,Mt as h,jt as i,Gt as j,Xt as k};
8
+ //# sourceMappingURL=chunk-VE3SSOQX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/actions/builtin/registry.ts","../src/actions/builtin/agent.ts","../src/agents/registry-instance.ts","../src/actions/builtin/channel.ts","../src/actions/builtin/extract.ts","../src/actions/builtin/file.ts","../src/actions/builtin/http.ts","../src/actions/builtin/mesh.ts","../src/a2a/mesh-instance.ts","../src/actions/builtin/rag.ts","../src/rag/lexical-index.ts","../src/actions/builtin/signal.ts","../src/agents/signals/instance.ts","../src/actions/builtin/index.ts"],"sourcesContent":["import type { BuiltinAction, BuiltinActionMetadata } from \"./types\"\n\n// --- Built-in action registry ---\n//\n// Process-global. Built-ins register at module-load time via the\n// barrel in ./index.ts; the daemon never has to wire them up\n// explicitly. Lookup is O(1).\n\nconst _registry = new Map<string, BuiltinAction>()\n\nconst NAME_PATTERN = /^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$/\n\n/**\n * Register a built-in. Idempotent — re-registering the same name\n * overwrites (useful for tests). Throws on malformed names so the\n * dotted-namespace contract stays consistent across the codebase.\n */\nexport function registerBuiltin<I, O>(action: BuiltinAction<I, O>): void {\n if (!NAME_PATTERN.test(action.name)) {\n throw new Error(`built-in action name must be dotted lowercase identifier (got \"${action.name}\")`)\n }\n _registry.set(action.name, action as BuiltinAction)\n}\n\nexport function getBuiltin(name: string): BuiltinAction | undefined {\n return _registry.get(name)\n}\n\n/** List metadata for every registered built-in, sorted by name. The\n * full schemas aren't included here — operators fetch the JSON-schema\n * rendering separately to keep the list response small. */\nexport function listBuiltins(): BuiltinActionMetadata[] {\n const out: BuiltinActionMetadata[] = []\n for (const [name, a] of _registry.entries()) {\n out.push({ name, description: a.description, timeoutMs: a.timeoutMs })\n }\n out.sort((a, b) => a.name.localeCompare(b.name))\n return out\n}\n\n/** Test-only — wipe the registry between cases. Production never clears. */\nexport function _resetBuiltinsForTesting(): void {\n _registry.clear()\n}\n\nconst DEFAULT_TIMEOUT_MS = 60_000\n\n/**\n * Run a built-in. Wraps the handler in:\n * - input validation (Zod parse — throws on bad shape)\n * - per-action timeout (with daemon-default fallback)\n * - output validation (Zod parse — log on mismatch but pass through;\n * output drift shouldn't break callers, just signal)\n *\n * Returns the validated output, or rejects on timeout / handler error.\n * Callers (HTTP route, CLI) catch and translate to error responses.\n */\nexport async function runBuiltin<I, O>(name: string, rawInput: unknown): Promise<O> {\n const action = _registry.get(name) as BuiltinAction<I, O> | undefined\n if (!action) {\n throw new Error(`unknown built-in action: ${name}`)\n }\n const input = action.inputSchema.parse(rawInput) as I\n const timeoutMs = action.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n const handlerPromise = action.handler(input)\n const timeoutPromise = new Promise<O>((_, reject) => {\n setTimeout(() => reject(new Error(`built-in action ${name} timed out after ${timeoutMs}ms`)), timeoutMs)\n })\n\n const output = await Promise.race([handlerPromise, timeoutPromise])\n\n // Soft validation on output — log mismatches but pass the value\n // through. A handler that drifts from its schema shouldn't break\n // production; surfacing the drift in the daemon log is enough signal.\n const parsed = action.outputSchema.safeParse(output)\n if (!parsed.success) {\n process.stderr.write(`[builtin-action] ${name} output failed schema validation: ${parsed.error.message}\\n`)\n }\n return output\n}\n","import { z } from \"zod\"\nimport { getAgentRegistry } from \"@/agents/registry-instance\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- agent.call ---\n//\n// Same-node sub-agent delegation, typed and traceable. Counterpart to\n// `mesh.delegate`: that one calls a remote peer's agent over HTTP+mesh,\n// this one calls a local agent on the same daemon — the common case for\n// triage/router patterns where one agent classifies + dispatches to a\n// specialized worker on the same machine.\n//\n// Why this exists separately from the daemon's POST /task endpoint:\n// - Going through HTTP for a same-node call is wasteful and harder\n// to trace (the action becomes a Bash + curl + parse-JSON dance,\n// exactly what AGENTX_HANDOFF.md item #1 flagged).\n// - Calling registry.execute() directly captures the call as a\n// structured action step in /traces (action=agent.call,\n// input=<typed>, output=<reply>) instead of opaque shell text.\n// - freshSession defaults to TRUE — the run-3/run-4 stickiness bug\n// was triage's curl reusing a warm pool; this default makes\n// \"safe\" the easy path.\n//\n// Architecturally this is a documented cross-tier seam: a Tier-3\n// procedure reaches into the Tier-1 agent registry via the explicit\n// getAgentRegistry() singleton (see registry-instance.ts and\n// test/tier-discipline.test.ts:DOCUMENTED_SEAMS).\n\nconst agentCallInput = z.object({\n /** Local agent id to dispatch the task to. */\n agentId: z.string().min(1),\n /** The task message — verbatim user message or a synthesized prompt. */\n message: z.string().min(1),\n /** Force a fresh session on the receiving agent. Defaults to TRUE so\n * that triage/router agents don't accidentally inherit a previous\n * visitor's conversation state. Pass `false` only when you genuinely\n * want continuity (rare for delegation). */\n freshSession: z.boolean().default(true),\n /** Optional channel + chatId. Defaults to a synthetic per-call chatId\n * so multiple concurrent delegations don't share a session. */\n channel: z.string().default(\"api\"),\n chatId: z.string().optional(),\n /** Identity of the calling agent — passed through to the receiving\n * agent's context for trace-stitching and (eventually) capability\n * validation. */\n senderAgentId: z.string().optional(),\n /** Per-call timeout. Default 90s — long enough for most agent\n * reasoning; capped at 10min. */\n timeoutMs: z.number().int().min(1).max(600_000).default(90_000),\n})\ntype AgentCallInput = z.infer<typeof agentCallInput>\n\nconst agentCallOutput = z.object({\n agentId: z.string(),\n /** The agent's reply. Same shape as POST /task's `content`. */\n reply: z.string(),\n /** Optional structured error if the underlying agent run failed.\n * Surfaced so callers can branch on auth/billing/tool-required. */\n error: z.string().optional(),\n errorKind: z.string().optional(),\n /** Token usage for cost accounting. */\n usage: z.object({\n inputTokens: z.number().int().default(0),\n outputTokens: z.number().int().default(0),\n cacheReadTokens: z.number().int().default(0),\n cacheCreateTokens: z.number().int().default(0),\n }).default({ inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheCreateTokens: 0 }),\n durationMs: z.number().int().default(0),\n})\ntype AgentCallOutput = z.infer<typeof agentCallOutput>\n\nexport const agentCall: BuiltinAction<AgentCallInput, AgentCallOutput> = {\n name: \"agent.call\",\n description: \"Dispatch a task to a local agent on the same daemon (fresh session by default — replaces ad-hoc 'Bash curl /task' delegation)\",\n inputSchema: agentCallInput,\n outputSchema: agentCallOutput,\n timeoutMs: 600_000,\n handler: async (input) => {\n const registry = getAgentRegistry()\n if (!registry) {\n throw new Error(\"agent registry not wired (daemon not started or running in a non-daemon process)\")\n }\n // Synthesize a per-call chatId by default so concurrent delegations\n // don't share a session. Caller can override for explicit continuity.\n const chatId = input.chatId ?? `agent-call-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`\n const started = Date.now()\n // senderAgentId is intentionally NOT placed in context (the\n // standard AgentTask context shape doesn't include it). The receiving\n // agent's prompt can reference {{trigger.input.senderAgentId}} if\n // configured; for trace stitching, the action's invocation already\n // creates a parent step so children land under the same task tree.\n const response = await registry.execute({\n agentId: input.agentId,\n message: input.message,\n freshSession: input.freshSession,\n context: {\n channel: input.channel,\n chatId,\n },\n })\n return {\n agentId: input.agentId,\n reply: response.content ?? \"\",\n error: response.error,\n errorKind: (response as any).errorKind,\n usage: {\n inputTokens: response.usage?.inputTokens ?? 0,\n outputTokens: response.usage?.outputTokens ?? 0,\n cacheReadTokens: (response.usage as any)?.cacheReadTokens ?? 0,\n cacheCreateTokens: (response.usage as any)?.cacheCreateTokens ?? 0,\n },\n durationMs: response.duration ?? (Date.now() - started),\n }\n },\n}\n","import type { AgentRegistry } from \"./registry\"\n\n// --- Singleton accessor for the live AgentRegistry ---\n//\n// Mirrors src/agents/process-registry-instance.ts and src/a2a/mesh-instance.ts.\n// Daemon registers the registry at boot; cross-tier composition seams (e.g.\n// the agent.call built-in action that needs to dispatch a local task without\n// going through HTTP) read it via getAgentRegistry().\n//\n// This is a DOCUMENTED SEAM under the three-tier discipline rule — listed in\n// test/tier-discipline.test.ts:DOCUMENTED_SEAMS so a procedure module can\n// import this without violating \"procedures must not import the agent\n// registry runtime\". The escape hatch is intentional: local delegation\n// reuses the registry's session management + permission resolution + trace\n// recording, which would otherwise need to be duplicated in the action.\n\nlet _registry: AgentRegistry | null = null\n\nexport function getAgentRegistry(): AgentRegistry | null {\n return _registry\n}\n\nexport function setAgentRegistry(r: AgentRegistry | null): void {\n _registry = r\n}\n\n/** Test-only — guarantees a clean slate between cases. */\nexport function resetAgentRegistryForTesting(): void {\n _registry = null\n}\n","import { z } from \"zod\"\nimport { getMessageRouter } from \"@/channels/router-instance\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- channel.reply / channel.label / channel.assign ---\n//\n// Canonical channel-output surface for agents. Replaces the raw-curl\n// playbook in agent skills with a typed action that:\n//\n// - posts through the live MessageRouter -> adapter chain (so the\n// adapter's marker + identity resolution + ledger recording all\n// fire automatically — no per-agent token in workspace files)\n// - dedupes within a 60s window keyed on (channel, chatId, body)\n// via router.sendOutbound's idempotency layer — so the same\n// dedupe protects every caller (HTTP /send, channel.reply,\n// cron notifications, cross-channel routing)\n// - returns the posted message id, or null when dedupe suppressed\n// the post (the messageId from the prior post)\n//\n// Architecturally this is the cleanest decoupling we can offer right\n// now: agent reasoning produces structured actions; the actions touch\n// the world through agentx; agentx owns cross-cutting concerns\n// (dedupe, marker, audit, rate limiting, identity) at the router\n// layer where every send-out converges.\n//\n// `auto_reply_legacy` (separate flag, on the channel config) preserves\n// today's \"router auto-posts response.content\" until every agent skill\n// has migrated to channel.reply. Once migration is complete the flag\n// gets removed and the agent's response.content stops being auto-\n// relayed entirely.\n\n// --- channel.reply ---\n\nconst channelReplyInput = z.object({\n /** Channel name (gitlab | github | telegram | whatsapp | discord | slack). */\n channel: z.string().min(1),\n /** Stable chat id — for gitlab: `org/repo:issue:123` or `org/repo:merge_request:123`.\n * For telegram/whatsapp: the chat or sender id. The format is the same one\n * the agent received in its task context as `chatId`. */\n chatId: z.string().min(1),\n /** Message body. Markdown for gitlab/github/discord; plain for sms/whatsapp. */\n text: z.string().min(1),\n /** Posting identity. When omitted, the channel adapter resolves identity\n * from agentMappings — for gitlab that's the per-agent gitlab token.\n * For telegram/discord it picks an account that's in the chat. */\n agentId: z.string().optional(),\n /** Multi-account adapters (telegram) need this when the chat is reachable\n * from more than one bot. Falls back to the adapter's chatAccountMap. */\n accountId: z.string().optional(),\n /** Optional reply-to message id for threaded channels. */\n replyTo: z.string().optional(),\n /** Custom dedupe key. When provided, replaces the default body-hash\n * scheme — useful for \"I want to overwrite my last status update\"\n * patterns where the body changes but the intent is the same post. */\n idempotencyKey: z.string().optional(),\n /** Optional rich payloads (telegram/whatsapp). URL buttons render as an\n * inline keyboard; poll/media send as their own message. */\n buttons: z.array(z.object({ label: z.string(), url: z.string() })).optional(),\n poll: z.object({ name: z.string(), values: z.array(z.string()), selectableCount: z.number().optional() }).optional(),\n media: z.object({\n type: z.enum([\"image\", \"document\", \"audio\", \"video\"]),\n url: z.string(),\n caption: z.string().optional(),\n }).optional(),\n})\ntype ChannelReplyInput = z.infer<typeof channelReplyInput>\n\nconst channelReplyOutput = z.object({\n /** Adapter-returned id, or null when the adapter couldn't surface one\n * (or the call was suppressed by the router's 60s dedupe window — in\n * which case this returns the prior post's id when known). */\n messageId: z.string().nullable(),\n})\ntype ChannelReplyOutput = z.infer<typeof channelReplyOutput>\n\nexport const channelReply: BuiltinAction<ChannelReplyInput, ChannelReplyOutput> = {\n name: \"channel.reply\",\n description: \"Post a reply to a channel (gitlab/github comment, telegram/whatsapp message, …) through the canonical adapter — auto-marker, auto-dedupe within 60s, identity resolved from agentMappings.\",\n inputSchema: channelReplyInput,\n outputSchema: channelReplyOutput,\n timeoutMs: 30_000,\n handler: async (input) => {\n const router = getMessageRouter()\n if (!router) {\n throw new Error(\"message router not wired (daemon not started or running in a non-daemon process)\")\n }\n // Empty-string idempotencyKey tells the router to use a body-hash\n // dedupe key. Caller can override with their own key for \"overwrite\n // last status\" patterns where the body changes but intent matches.\n const idempotencyKey = input.idempotencyKey ?? \"\"\n const messageId = await router.sendOutbound(\n {\n channel: input.channel,\n chatId: input.chatId,\n text: input.text,\n agentId: input.agentId,\n accountId: input.accountId,\n replyTo: input.replyTo,\n buttons: input.buttons,\n poll: input.poll,\n media: input.media,\n },\n { idempotencyKey, dedupeWindowMs: 60_000 },\n )\n return { messageId: typeof messageId === \"string\" ? messageId : null }\n },\n}\n\n// --- channel.label ---\n//\n// Add and/or remove labels on the inbound entity. GitLab + GitHub both\n// expose this; other channels error politely. Like channel.reply this\n// goes through the live adapter chain (per-agent token, marker, ledger).\n\nconst channelLabelInput = z.object({\n /** Currently supports \"gitlab\"; \"github\" wired when the github adapter\n * surfaces a typed label call (today the adapter-level setLabels is\n * gitlab-only). Pass the channel that owns the entity. */\n channel: z.literal(\"gitlab\"),\n /** GitLab project path — `org/repo`. */\n project: z.string().min(1),\n /** \"issue\" or \"merge_request\". */\n kind: z.enum([\"issue\", \"merge_request\"]),\n /** Numeric iid as a string. */\n iid: z.string().min(1),\n add: z.array(z.string()).default([]),\n remove: z.array(z.string()).default([]),\n /** Posting identity — defaults to channel-adapter resolution. */\n agentId: z.string().optional(),\n})\ntype ChannelLabelInput = z.infer<typeof channelLabelInput>\n\nconst channelLabelOutput = z.object({\n labels: z.array(z.string()),\n})\ntype ChannelLabelOutput = z.infer<typeof channelLabelOutput>\n\nexport const channelLabel: BuiltinAction<ChannelLabelInput, ChannelLabelOutput> = {\n name: \"channel.label\",\n description: \"Add and/or remove labels on a GitLab issue/MR through the adapter (per-agent token, ledger, no raw curl).\",\n inputSchema: channelLabelInput,\n outputSchema: channelLabelOutput,\n timeoutMs: 30_000,\n handler: async (input) => {\n const router = getMessageRouter()\n if (!router) throw new Error(\"message router not wired\")\n const adapter = (router as any).getChannel?.(input.channel) as\n | { setLabels?: (args: { project: string; kind?: \"issue\" | \"merge_request\"; iid: string; add?: string[]; remove?: string[]; agentId?: string }) => Promise<string[] | null> }\n | undefined\n if (!adapter?.setLabels) {\n throw new Error(`channel \"${input.channel}\" does not expose setLabels`)\n }\n const labels = await adapter.setLabels({\n project: input.project,\n kind: input.kind,\n iid: input.iid,\n add: input.add,\n remove: input.remove,\n agentId: input.agentId,\n })\n // null means the change did not land; an empty list is a real answer.\n if (!Array.isArray(labels)) throw new Error(\"setLabels did not apply the change — see daemon log for details\")\n return { labels }\n },\n}\n\n// --- channel.assign ---\n//\n// Replace the assignees on a GitLab issue or MR. PM uses this to assign\n// the coding agent when flipping Triage→To Do; coders use it to assign\n// reviewers/mergers; QA uses it to assign testers. Same identity model\n// as channel.label — per-agent token, ledger.\n\nconst channelAssignInput = z.object({\n channel: z.literal(\"gitlab\"),\n project: z.string().min(1),\n kind: z.enum([\"issue\", \"merge_request\"]),\n iid: z.string().min(1),\n /** GitLab usernames. Empty array = unassign all. */\n assignees: z.array(z.string()).default([]),\n agentId: z.string().optional(),\n})\ntype ChannelAssignInput = z.infer<typeof channelAssignInput>\n\nconst channelAssignOutput = z.object({\n /** Numeric user_ids assigned (post-resolution from usernames). */\n assigneeIds: z.array(z.number()),\n})\ntype ChannelAssignOutput = z.infer<typeof channelAssignOutput>\n\nexport const channelAssign: BuiltinAction<ChannelAssignInput, ChannelAssignOutput> = {\n name: \"channel.assign\",\n description: \"Set assignees on a GitLab issue or MR (replaces the assignee list). Pass empty array to unassign. Use during Triage→To Do flip to assign the coding agent, or to designate reviewer/merger on an MR.\",\n inputSchema: channelAssignInput,\n outputSchema: channelAssignOutput,\n timeoutMs: 30_000,\n handler: async (input) => {\n const router = getMessageRouter()\n if (!router) throw new Error(\"message router not wired\")\n const adapter = (router as any).getChannel?.(input.channel) as\n | { setAssignees?: (args: { project: string; kind?: \"issue\" | \"merge_request\"; iid: string; assignees: string[]; agentId?: string }) => Promise<number[] | null> }\n | undefined\n if (!adapter?.setAssignees) {\n throw new Error(`channel \"${input.channel}\" does not expose setAssignees`)\n }\n const ids = await adapter.setAssignees({\n project: input.project,\n kind: input.kind,\n iid: input.iid,\n assignees: input.assignees,\n agentId: input.agentId,\n })\n if (!Array.isArray(ids)) throw new Error(\"setAssignees did not apply the change (no assignee resolved, or no token) — see daemon log for details\")\n return { assigneeIds: ids }\n },\n}\n\n// --- channel.create_issue ---\n//\n// Create a GitLab issue from inside an agent task. PM uses this to spin\n// off test-case issues from the parent dev issue; CX uses it to file\n// issues from WhatsApp/email client requests. The /relate cross-link\n// happens on a follow-up call — the GitLab API doesn't take it inline.\n\nconst channelCreateIssueInput = z.object({\n channel: z.literal(\"gitlab\"),\n project: z.string().min(1),\n title: z.string().min(1),\n description: z.string().default(\"\"),\n labels: z.array(z.string()).default([]),\n /** Usernames to assign on creation. */\n assignees: z.array(z.string()).default([]),\n agentId: z.string().optional(),\n /** Optional: when set, the new issue is /relate'd to this iid via a\n * follow-up POST to /issues/:src/links — same project. Caller-friendly\n * shortcut so the test-case-create flow is one call, not two. */\n relateToIid: z.string().optional(),\n})\ntype ChannelCreateIssueInput = z.infer<typeof channelCreateIssueInput>\n\nconst channelCreateIssueOutput = z.object({\n iid: z.number(),\n url: z.string(),\n related: z.boolean().default(false),\n})\ntype ChannelCreateIssueOutput = z.infer<typeof channelCreateIssueOutput>\n\nexport const channelCreateIssue: BuiltinAction<ChannelCreateIssueInput, ChannelCreateIssueOutput> = {\n name: \"channel.create_issue\",\n description: \"Create a GitLab issue from an agent (PM test cases, CX client requests). Honors per-agent identity; resolves assignee usernames to ids; optional /relate to a parent issue.\",\n inputSchema: channelCreateIssueInput,\n outputSchema: channelCreateIssueOutput,\n timeoutMs: 60_000,\n handler: async (input) => {\n const router = getMessageRouter()\n if (!router) throw new Error(\"message router not wired\")\n const adapter = (router as any).getChannel?.(input.channel) as\n | {\n createIssue?: (args: {\n project: string; title: string; description?: string;\n labels?: string[]; assignees?: string[]; agentId?: string;\n }) => Promise<{ iid: number; url: string } | null>\n relateIssue?: (args: { project: string; sourceIid: string; targetIid: string; agentId?: string }) => Promise<boolean>\n }\n | undefined\n if (!adapter?.createIssue) {\n throw new Error(`channel \"${input.channel}\" does not expose createIssue`)\n }\n const created = await adapter.createIssue({\n project: input.project,\n title: input.title,\n description: input.description,\n labels: input.labels,\n assignees: input.assignees,\n agentId: input.agentId,\n })\n if (!created) {\n throw new Error(\"createIssue returned null — see daemon log for details\")\n }\n let related = false\n if (input.relateToIid && adapter.relateIssue) {\n related = await adapter.relateIssue({\n project: input.project,\n sourceIid: String(created.iid),\n targetIid: input.relateToIid,\n agentId: input.agentId,\n })\n }\n return { iid: created.iid, url: created.url, related }\n },\n}\n","import { z } from \"zod\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- extract.structured ---\n//\n// Single-call structured extraction: ask Claude for a JSON value\n// matching a caller-supplied JSON-Schema. The agent / workflow gets\n// typed structured data back — no parser needed downstream.\n//\n// Implementation: Anthropic Messages API with a forced tool_use whose\n// input_schema is the caller's schema. Forced tool use guarantees the\n// model's response is the structured value, not free-form text. We\n// extract the tool's `input` and return it verbatim.\n//\n// Why we hit the API directly instead of routing through the\n// claude-code subprocess (or the SDK):\n// - The persistent-process path keeps a turn slot busy for >2s\n// even on warm cache; for a single extraction this is overkill.\n// - The SDK adds a 10MB+ dependency; raw fetch needs zero new deps.\n// - The model + auth are the same — ANTHROPIC_API_KEY env var.\n//\n// Input shape:\n// model: Anthropic model id (\"claude-sonnet-4-6\" / \"claude-haiku-4-5\" / etc.)\n// prompt: User-message text the model extracts from.\n// schema: JSON-Schema-shaped object (NOT a Zod schema) — this is what\n// the model is told to fill in. Caller-defined.\n// maxTokens: Output-token cap, default 1024.\n//\n// Output shape:\n// data: The structured value, exactly as the model returned it.\n// Validated only against \"is an object/array/scalar\" — the\n// caller's schema is the contract; we don't re-validate\n// because that would require shipping a JSON-Schema validator.\n// usage: Token counts for cost accounting.\n// model: Model that actually billed (echoed from the response).\n\nconst extractInput = z.object({\n model: z.string().default(\"claude-haiku-4-5\"),\n prompt: z.string().min(1),\n /** JSON-Schema describing the output shape. Passed to the Claude\n * API as the input_schema of a forced tool_use. */\n schema: z.record(z.string(), z.unknown()),\n /** Optional system prompt prepended to the conversation. */\n systemPrompt: z.string().optional(),\n maxTokens: z.number().int().min(1).max(8_000).default(1024),\n /** Per-call timeout. Default 60s. */\n timeoutMs: z.number().int().min(1).max(120_000).default(60_000),\n})\ntype ExtractInput = z.infer<typeof extractInput>\n\nconst extractOutput = z.object({\n data: z.unknown(),\n model: z.string(),\n usage: z.object({\n inputTokens: z.number().int(),\n outputTokens: z.number().int(),\n }),\n})\ntype ExtractOutput = z.infer<typeof extractOutput>\n\nconst ANTHROPIC_API = \"https://api.anthropic.com/v1/messages\"\nconst ANTHROPIC_VERSION = \"2023-06-01\"\n\nexport const extractStructured: BuiltinAction<ExtractInput, ExtractOutput> = {\n name: \"extract.structured\",\n description: \"Single-call typed extraction: prompt + JSON-Schema → structured data via forced tool_use\",\n inputSchema: extractInput,\n outputSchema: extractOutput,\n timeoutMs: 120_000,\n handler: async (input) => {\n const apiKey = process.env.ANTHROPIC_API_KEY\n if (!apiKey) {\n throw new Error(\"ANTHROPIC_API_KEY env var is not set — extract.structured needs direct API access\")\n }\n\n // Use a forced tool_use with input_schema = the caller's schema.\n // tool_choice: { type: \"tool\", name: \"respond_with_structure\" }\n // makes the model produce a tool_use block as the entire reply,\n // whose `input` field IS the structured value.\n const requestBody: Record<string, unknown> = {\n model: input.model,\n max_tokens: input.maxTokens,\n messages: [{ role: \"user\", content: input.prompt }],\n tools: [{\n name: \"respond_with_structure\",\n description: \"Return a structured value matching the schema\",\n input_schema: input.schema,\n }],\n tool_choice: { type: \"tool\", name: \"respond_with_structure\" },\n }\n if (input.systemPrompt) {\n requestBody.system = input.systemPrompt\n }\n\n const ctrl = new AbortController()\n const t = setTimeout(() => ctrl.abort(), input.timeoutMs)\n let res: Response\n try {\n res = await fetch(ANTHROPIC_API, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": ANTHROPIC_VERSION,\n },\n body: JSON.stringify(requestBody),\n signal: ctrl.signal,\n })\n } finally {\n clearTimeout(t)\n }\n\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\")\n throw new Error(`anthropic API ${res.status}: ${errBody.slice(0, 500)}`)\n }\n const body: any = await res.json()\n const blocks = Array.isArray(body.content) ? body.content : []\n const toolUse = blocks.find((b: any) => b?.type === \"tool_use\" && b?.name === \"respond_with_structure\")\n if (!toolUse || toolUse.input === undefined) {\n throw new Error(`anthropic API returned no respond_with_structure tool_use (got ${blocks.length} blocks)`)\n }\n\n const usage = body.usage ?? {}\n return {\n data: toolUse.input,\n model: typeof body.model === \"string\" ? body.model : input.model,\n usage: {\n inputTokens: typeof usage.input_tokens === \"number\" ? usage.input_tokens : 0,\n outputTokens: typeof usage.output_tokens === \"number\" ? usage.output_tokens : 0,\n },\n }\n },\n}\n","import { z } from \"zod\"\nimport { existsSync, readFileSync, appendFileSync, mkdirSync, statSync } from \"fs\"\nimport { resolve, dirname, isAbsolute } from \"path\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- Built-in file actions ---\n//\n// file.read_lines — read a text file, return up to maxLines string lines\n// file.write_jsonl — append N JSON objects as newline-delimited records\n//\n// Both are workspace-scoped: paths must resolve under one of the\n// allowed roots set via AGENTX_BUILTIN_FILE_ROOTS env var (or the cwd\n// by default). This is the boundary that keeps an agent from reading\n// /etc/passwd or writing into the daemon's own .agentx state. Path\n// traversal (../..) is rejected via the resolved-path containment\n// check, not regex on the input.\n//\n// Why these two specifically (per improvement plan #6 catalog):\n// - read_lines: typed plumbing for \"give me the last N log lines\"\n// pattern that workflows currently shell out to `tail` for.\n// - write_jsonl: typed plumbing for \"log a structured event into\n// this agent's working file\" — the workflow-as-program framing\n// wants this as a primitive, not as `echo {} >> file`.\n\nconst MAX_FILE_BYTES = 8 * 1024 * 1024 // 8 MB cap on read\n\n/**\n * Resolve and validate a target path against the allowed roots.\n * Returns the absolute path on success; throws otherwise. Allowed\n * roots default to process.cwd() unless the operator overrides via\n * AGENTX_BUILTIN_FILE_ROOTS (colon-separated). This mirrors how\n * Claude Code's own --add-dir flag is applied at spawn.\n */\nfunction resolveAllowed(input: string): string {\n const abs = isAbsolute(input) ? input : resolve(process.cwd(), input)\n const rootsEnv = process.env.AGENTX_BUILTIN_FILE_ROOTS || process.cwd()\n const roots = rootsEnv.split(\":\").map((r) => resolve(r))\n for (const root of roots) {\n if (abs === root || abs.startsWith(root + \"/\")) return abs\n }\n throw new Error(`path \"${input}\" is outside the allowed roots`)\n}\n\nconst readLinesInput = z.object({\n path: z.string().min(1),\n /** Cap the returned line count. Default 200, hard cap 10000. */\n maxLines: z.number().int().min(1).max(10_000).default(200),\n /** When true, return only the LAST maxLines (tail-style). Default false (head). */\n fromEnd: z.boolean().default(false),\n})\ntype ReadLinesInput = z.infer<typeof readLinesInput>\n\nconst readLinesOutput = z.object({\n path: z.string(),\n lines: z.array(z.string()),\n totalLines: z.number().int(),\n truncated: z.boolean(),\n})\ntype ReadLinesOutput = z.infer<typeof readLinesOutput>\n\nexport const fileReadLines: BuiltinAction<ReadLinesInput, ReadLinesOutput> = {\n name: \"file.read_lines\",\n description: \"Read a text file as an array of lines (utf-8, 8MB cap, scoped to allowed roots)\",\n inputSchema: readLinesInput,\n outputSchema: readLinesOutput,\n timeoutMs: 10_000,\n handler: async (input) => {\n const abs = resolveAllowed(input.path)\n if (!existsSync(abs)) throw new Error(`file not found: ${input.path}`)\n const stat = statSync(abs)\n if (!stat.isFile()) throw new Error(`not a regular file: ${input.path}`)\n if (stat.size > MAX_FILE_BYTES) {\n throw new Error(`file too large (${stat.size} > ${MAX_FILE_BYTES} bytes)`)\n }\n const content = readFileSync(abs, \"utf8\")\n // Split on \\n but drop a trailing empty token if the file ended in \\n —\n // the canonical \"logs end with a newline\" case.\n const all = content.split(\"\\n\")\n if (all.length > 0 && all[all.length - 1] === \"\") all.pop()\n const totalLines = all.length\n let lines: string[]\n let truncated: boolean\n if (totalLines <= input.maxLines) {\n lines = all\n truncated = false\n } else {\n truncated = true\n lines = input.fromEnd ? all.slice(totalLines - input.maxLines) : all.slice(0, input.maxLines)\n }\n return { path: abs, lines, totalLines, truncated }\n },\n}\n\nconst writeJsonlInput = z.object({\n path: z.string().min(1),\n /** Records to append, one JSON line each. Each must be a JSON-serializable\n * value; non-serializable inputs are rejected before any FS write. */\n records: z.array(z.unknown()).min(1),\n /** When true, ensure the parent directory exists (mkdir -p). Default false. */\n createDirs: z.boolean().default(false),\n})\ntype WriteJsonlInput = z.infer<typeof writeJsonlInput>\n\nconst writeJsonlOutput = z.object({\n path: z.string(),\n written: z.number().int(),\n bytesAppended: z.number().int(),\n})\ntype WriteJsonlOutput = z.infer<typeof writeJsonlOutput>\n\nexport const fileWriteJsonl: BuiltinAction<WriteJsonlInput, WriteJsonlOutput> = {\n name: \"file.write_jsonl\",\n description: \"Append JSON records to a file as newline-delimited JSON (utf-8, scoped to allowed roots)\",\n inputSchema: writeJsonlInput,\n outputSchema: writeJsonlOutput,\n timeoutMs: 10_000,\n handler: async (input) => {\n const abs = resolveAllowed(input.path)\n\n // Pre-serialize EVERYTHING before opening the file so a bad\n // record can't leave a half-written file behind. Each record\n // becomes one JSON line; embedded newlines in strings are\n // escaped naturally by JSON.stringify.\n const lines: string[] = []\n for (const r of input.records) {\n try {\n lines.push(JSON.stringify(r))\n } catch (e: any) {\n throw new Error(`record ${lines.length} not JSON-serializable: ${e?.message || String(e)}`)\n }\n }\n const payload = lines.join(\"\\n\") + \"\\n\"\n\n if (input.createDirs) {\n mkdirSync(dirname(abs), { recursive: true })\n }\n appendFileSync(abs, payload, \"utf8\")\n return { path: abs, written: lines.length, bytesAppended: Buffer.byteLength(payload, \"utf8\") }\n },\n}\n","import { z } from \"zod\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- Built-in HTTP actions ---\n//\n// http.fetch — typed GET, returns body+status+headers\n// http.post — typed POST with JSON body, same response shape\n//\n// Why bake these in when agents already have Bash + curl: the typed\n// shape lets workflows pipe response data into structured downstream\n// nodes without parsing curl output. Headers and status are\n// first-class. Errors are returned as a result, not thrown — so\n// workflow conditional nodes can branch on them.\n//\n// Body size is capped at 1MB to keep responses bounded; truncate is\n// reported back. Allowed schemes are http and https only — file:// /\n// data:// / etc. would let an agent read arbitrary local resources\n// through this action, which violates the \"agents talk over the\n// network\" boundary.\n\nconst MAX_BODY_BYTES = 1024 * 1024 // 1 MB\n\nconst HEADER_RECORD = z.record(z.string(), z.string())\n\nconst allowedSchemes = [\"http:\", \"https:\"] as const\n\nfunction assertAllowed(url: string): URL {\n let u: URL\n try { u = new URL(url) }\n catch { throw new Error(`invalid url: ${url}`) }\n if (!(allowedSchemes as readonly string[]).includes(u.protocol)) {\n throw new Error(`scheme not allowed (only http/https): ${u.protocol}`)\n }\n return u\n}\n\nconst fetchInput = z.object({\n url: z.string().min(1),\n headers: HEADER_RECORD.optional(),\n /** Per-call timeout in ms. Default 30s. Capped at the registry's\n * 60s ceiling regardless. */\n timeoutMs: z.number().int().min(1).max(60_000).default(30_000),\n})\ntype FetchInput = z.infer<typeof fetchInput>\n\nconst fetchOutput = z.object({\n status: z.number().int(),\n statusText: z.string(),\n headers: HEADER_RECORD,\n body: z.string(),\n truncated: z.boolean(),\n url: z.string(),\n})\ntype FetchOutput = z.infer<typeof fetchOutput>\n\nasync function readCappedText(res: Response): Promise<{ body: string; truncated: boolean }> {\n if (!res.body) return { body: \"\", truncated: false }\n const reader = res.body.getReader()\n const dec = new TextDecoder()\n let total = 0\n let body = \"\"\n let truncated = false\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n if (value) {\n total += value.length\n if (total > MAX_BODY_BYTES) {\n // Keep what we have, mark truncated, stop reading.\n body += dec.decode(value.slice(0, MAX_BODY_BYTES - (total - value.length)), { stream: false })\n truncated = true\n try { await reader.cancel() } catch { /* */ }\n break\n }\n body += dec.decode(value, { stream: true })\n }\n }\n body += dec.decode()\n return { body, truncated }\n}\n\nfunction headersToObject(h: Headers): Record<string, string> {\n const out: Record<string, string> = {}\n h.forEach((v, k) => { out[k] = v })\n return out\n}\n\nexport const httpFetch: BuiltinAction<FetchInput, FetchOutput> = {\n name: \"http.fetch\",\n description: \"GET a URL, return body + status + headers (1MB cap, http/https only)\",\n inputSchema: fetchInput,\n outputSchema: fetchOutput,\n timeoutMs: 35_000,\n handler: async (input) => {\n assertAllowed(input.url)\n const ctrl = new AbortController()\n const t = setTimeout(() => ctrl.abort(), input.timeoutMs)\n try {\n const res = await fetch(input.url, { method: \"GET\", headers: input.headers ?? {}, signal: ctrl.signal })\n const { body, truncated } = await readCappedText(res)\n return {\n status: res.status,\n statusText: res.statusText,\n headers: headersToObject(res.headers),\n body,\n truncated,\n url: res.url,\n }\n } finally {\n clearTimeout(t)\n }\n },\n}\n\nconst postInput = z.object({\n url: z.string().min(1),\n /** JSON body, serialized to string at request time. Caller passes\n * any JSON-serializable value here — strings, objects, arrays. */\n body: z.unknown(),\n headers: HEADER_RECORD.optional(),\n timeoutMs: z.number().int().min(1).max(60_000).default(30_000),\n})\ntype PostInput = z.infer<typeof postInput>\n\nexport const httpPost: BuiltinAction<PostInput, FetchOutput> = {\n name: \"http.post\",\n description: \"POST a JSON body to a URL, return body + status + headers (1MB cap, http/https only)\",\n inputSchema: postInput,\n outputSchema: fetchOutput,\n timeoutMs: 35_000,\n handler: async (input) => {\n assertAllowed(input.url)\n const ctrl = new AbortController()\n const t = setTimeout(() => ctrl.abort(), input.timeoutMs)\n try {\n const headers = { \"Content-Type\": \"application/json\", ...(input.headers ?? {}) }\n const res = await fetch(input.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(input.body ?? {}),\n signal: ctrl.signal,\n })\n const { body, truncated } = await readCappedText(res)\n return {\n status: res.status,\n statusText: res.statusText,\n headers: headersToObject(res.headers),\n body,\n truncated,\n url: res.url,\n }\n } finally {\n clearTimeout(t)\n }\n },\n}\n","import { z } from \"zod\"\nimport { getMesh } from \"@/a2a/mesh-instance\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- mesh.delegate ---\n//\n// Send a task to a remote agentx peer (mesh node) and return the\n// peer's response text. Same wire as the legacy POST /mesh/task HTTP\n// route, but typed and callable directly from agents and workflows\n// without a Bash shell-out — exactly the \"mesh.delegate (peer call,\n// no shell required)\" line item from improvement plan #6.\n//\n// Why this matters even though POST /mesh/task already exists:\n// - Workflows can pipe the response into a typed downstream node.\n// - Agent-side, the call is one /api/actions/builtin POST instead\n// of \"shell out, parse JSON, hope you wrote the curl right\".\n// - The action interface advertises peer-name + agent-name shape\n// so authoring tools can validate before dispatch.\n\nconst meshDelegateInput = z.object({\n /** Mesh peer name as configured in mesh.peers[].name. */\n peer: z.string().min(1),\n /** Optional remote agent id; falls back to first agent on the peer. */\n agent: z.string().optional(),\n message: z.string().min(1),\n /** Per-call timeout. Default 90s; capped by the registry's 60s\n * ceiling unless the action declares a larger timeoutMs. */\n timeoutMs: z.number().int().min(1).max(600_000).default(90_000),\n /** Identity of the agent making the delegated call. Forwarded to\n * the receiving daemon for route-trace + (eventually) capability\n * validation. Optional during the log-warn rollout. */\n senderAgentId: z.string().optional(),\n /** Force a fresh session on the receiving agent. Defaults to TRUE\n * for cross-agent delegation — without this, a triage agent's\n * delegation reuses whatever conversation the worker pool last\n * served, leaking the previous visitor's context (run-3 / run-4\n * benchmark finding). Pass `false` only when you genuinely want\n * the worker to keep state across delegations. */\n freshSession: z.boolean().default(true),\n})\ntype MeshDelegateInput = z.infer<typeof meshDelegateInput>\n\nconst meshDelegateOutput = z.object({\n peer: z.string(),\n agent: z.string().nullable(),\n response: z.string(),\n})\ntype MeshDelegateOutput = z.infer<typeof meshDelegateOutput>\n\nexport const meshDelegate: BuiltinAction<MeshDelegateInput, MeshDelegateOutput> = {\n name: \"mesh.delegate\",\n description: \"Send a task to a remote mesh peer's agent and return the response text\",\n inputSchema: meshDelegateInput,\n outputSchema: meshDelegateOutput,\n // Allow the action's max well above the registry default so a\n // long peer task isn't capped at 60s.\n timeoutMs: 600_000,\n handler: async (input) => {\n const mesh = getMesh()\n if (!mesh) {\n throw new Error(\"mesh not enabled on this daemon (config.mesh.enabled = false)\")\n }\n const response = await mesh.sendTask(input.peer, input.message, input.agent, {\n timeoutMs: input.timeoutMs,\n senderAgentId: input.senderAgentId,\n freshSession: input.freshSession,\n })\n return {\n peer: input.peer,\n agent: input.agent ?? null,\n response,\n }\n },\n}\n","import type { A2AMesh } from \"./mesh\"\n\n// --- Singleton accessor for the live A2AMesh ---\n//\n// Mirrors src/agents/process-registry-instance.ts. The daemon\n// instantiates A2AMesh in its boot sequence and registers it here so\n// process-global consumers (built-in actions, mesh.delegate) can reach\n// it without changing every call site's signature. Setter is null-able\n// because mesh-disabled deployments still need a valid module.\n\nlet _mesh: A2AMesh | null = null\n\nexport function getMesh(): A2AMesh | null {\n return _mesh\n}\n\nexport function setMesh(m: A2AMesh | null): void {\n _mesh = m\n}\n\n/** Test-only — clears the reference between cases. */\nexport function _resetMeshForTesting(): void {\n _mesh = null\n}\n","import { z } from \"zod\"\nimport { lexicalSearch } from \"@/rag/lexical-index\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- rag.lexical ---\n//\n// Improvement plan #7 — embedding-free retrieval-augmented context.\n// Looks up an agent's lexical (BM25) index built via `agentx rag add`\n// and returns the top hits with score + path + body excerpt. No\n// embedding API call, no key, deterministic.\n\nconst ragLexicalInput = z.object({\n /** Agent whose index to query. Each agent has its own index at\n * .agentx/rag/<agentId>/. */\n agentId: z.string().min(1),\n query: z.string().min(1),\n /** Top-k results. Default 5, hard cap 50. */\n k: z.number().int().min(1).max(50).default(5),\n})\ntype RagLexicalInput = z.infer<typeof ragLexicalInput>\n\nconst ragLexicalOutput = z.object({\n hits: z.array(z.object({\n id: z.string(),\n title: z.string(),\n path: z.string(),\n score: z.number(),\n snippet: z.string(),\n })),\n})\ntype RagLexicalOutput = z.infer<typeof ragLexicalOutput>\n\nexport const ragLexical: BuiltinAction<RagLexicalInput, RagLexicalOutput> = {\n name: \"rag.lexical\",\n description: \"BM25-style lexical search over an agent's pre-built index (no embeddings, deterministic)\",\n inputSchema: ragLexicalInput,\n outputSchema: ragLexicalOutput,\n timeoutMs: 5_000,\n handler: async (input) => {\n const hits = lexicalSearch(input.agentId, input.query, { k: input.k })\n return { hits }\n },\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync } from \"fs\"\nimport { resolve, basename, relative } from \"path\"\nimport fg from \"fast-glob\"\n// minisearch ships both CJS and ESM; tsup transpiles either way.\nimport MiniSearch from \"minisearch\"\n\n// --- Lexical RAG index per agent ---\n//\n// Improvement plan #7 — embedding-free retrieval-augmented context for\n// agents. BM25-style scoring via the minisearch library (~30KB pure\n// JS, no native deps). Each agent gets its own index at\n// `.agentx/rag/<agentId>/index.json`; `agentx rag add` builds it from\n// a glob, the rag.lexical built-in action queries it.\n//\n// Fields indexed: title (extracted from first H1 or filename) + body\n// (full file text). Title is boosted 2× at search time so a\n// well-titled doc beats a body-only mention. Path is stored as a\n// non-indexed field so query results can cite the source file.\n//\n// Why not use embeddings: zero new keys, deterministic results, fast\n// (sub-ms search even with hundreds of docs), works offline. The\n// trade is no semantic synonymy — but for the kinds of operator\n// docs / wiki entries / playbook lookups agents typically need,\n// keyword recall is enough. Embedding-backed mode is opt-in\n// future work.\n\nexport interface IndexedDoc {\n /** Stable id within an index — usually the workspace-relative path. */\n id: string\n title: string\n body: string\n /** Absolute path on disk. Stored, not indexed. */\n path: string\n /** ISO timestamp when this doc was indexed. */\n indexedAt: string\n}\n\nexport interface RagSearchHit {\n id: string\n title: string\n path: string\n score: number\n /** A short body excerpt around the highest-scoring term. Useful for\n * citation-style \"here's what we found\" responses. */\n snippet: string\n}\n\nconst FIELDS_INDEXED = [\"title\", \"body\"]\nconst FIELDS_STORED = [\"title\", \"body\", \"path\", \"indexedAt\"]\n\nfunction indexFilePath(agentId: string, baseDir: string = \".agentx/rag\"): string {\n return resolve(process.cwd(), baseDir, agentId, \"index.json\")\n}\n\nfunction newSearchEngine(): MiniSearch<IndexedDoc> {\n return new MiniSearch<IndexedDoc>({\n fields: FIELDS_INDEXED,\n storeFields: FIELDS_STORED,\n searchOptions: { boost: { title: 2 }, fuzzy: 0.2, prefix: true },\n })\n}\n\n/**\n * Read a markdown / text file and split into indexable fields. Title\n * comes from the first H1 line (`# ...`); falls back to the filename\n * stem when there isn't one. Body is the full text.\n */\nfunction fileToDoc(absPath: string, idBase: string): IndexedDoc {\n const text = readFileSync(absPath, \"utf8\")\n const h1Match = text.match(/^\\s*#\\s+(.+)$/m)\n const title = h1Match ? h1Match[1].trim() : basename(absPath).replace(/\\.[^.]+$/, \"\")\n return {\n id: idBase,\n title,\n body: text,\n path: absPath,\n indexedAt: new Date().toISOString(),\n }\n}\n\n/**\n * Build an index from one or more globs. Globs resolve from cwd. The\n * resulting index is persisted under .agentx/rag/<agentId>/index.json\n * and returned to the caller for synchronous use.\n */\nexport async function buildIndex(\n agentId: string,\n globs: string[],\n opts: { baseDir?: string; cwd?: string; verbose?: boolean } = {},\n): Promise<{ docs: number; path: string }> {\n const cwd = opts.cwd ?? process.cwd()\n const files = (await fg(globs, { cwd, absolute: true, dot: false }))\n .filter((p) => {\n try { return statSync(p).isFile() } catch { return false }\n })\n\n const ms = newSearchEngine()\n for (const abs of files) {\n const idBase = relative(cwd, abs)\n const doc = fileToDoc(abs, idBase)\n ms.add(doc)\n if (opts.verbose) process.stderr.write(`[rag] indexed ${idBase} (${doc.body.length} bytes)\\n`)\n }\n\n const out = indexFilePath(agentId, opts.baseDir)\n mkdirSync(resolve(out, \"..\"), { recursive: true })\n writeFileSync(out, JSON.stringify(ms.toJSON()), \"utf8\")\n return { docs: files.length, path: out }\n}\n\n/**\n * Load a previously-built index. Returns null when no index exists for\n * this agent (caller can fall back to \"no RAG\" gracefully). Loading is\n * a small JSON parse + minisearch deserialize — sub-millisecond on\n * typical operator-doc indices.\n */\nexport function loadIndex(\n agentId: string,\n opts: { baseDir?: string } = {},\n): MiniSearch<IndexedDoc> | null {\n const path = indexFilePath(agentId, opts.baseDir)\n if (!existsSync(path)) return null\n try {\n const raw = readFileSync(path, \"utf8\")\n return MiniSearch.loadJSON<IndexedDoc>(raw, {\n fields: FIELDS_INDEXED,\n storeFields: FIELDS_STORED,\n searchOptions: { boost: { title: 2 }, fuzzy: 0.2, prefix: true },\n })\n } catch (e: any) {\n process.stderr.write(`[rag] failed to load ${path}: ${e?.message || String(e)}\\n`)\n return null\n }\n}\n\nconst SNIPPET_RADIUS = 80\nconst SNIPPET_MAX = SNIPPET_RADIUS * 2 + 60\n\n/** Extract a snippet around the FIRST occurrence of any of `terms` in\n * `body`. Returns the head of the body when no term hits. */\nfunction makeSnippet(body: string, terms: string[]): string {\n const lc = body.toLowerCase()\n let bestPos = -1\n for (const t of terms) {\n const i = lc.indexOf(t.toLowerCase())\n if (i >= 0 && (bestPos === -1 || i < bestPos)) bestPos = i\n }\n if (bestPos === -1) {\n return body.slice(0, SNIPPET_MAX).replace(/\\s+/g, \" \").trim()\n }\n const start = Math.max(0, bestPos - SNIPPET_RADIUS)\n const end = Math.min(body.length, bestPos + SNIPPET_RADIUS)\n const slice = body.slice(start, end).replace(/\\s+/g, \" \").trim()\n return (start > 0 ? \"…\" : \"\") + slice + (end < body.length ? \"…\" : \"\")\n}\n\nexport interface SearchOpts {\n /** How many top hits to return. Default 5, capped at 50. */\n k?: number\n baseDir?: string\n}\n\n/**\n * Lexical query against an agent's index. Returns at most `k` results,\n * each with a score, the title, the source path, and a snippet around\n * the matched term. Empty array when no index exists or no hits.\n */\nexport function lexicalSearch(\n agentId: string,\n query: string,\n opts: SearchOpts = {},\n): RagSearchHit[] {\n const ms = loadIndex(agentId, { baseDir: opts.baseDir })\n if (!ms) return []\n const k = Math.max(1, Math.min(50, opts.k ?? 5))\n const raw = ms.search(query) as unknown as Array<{\n id: string\n score: number\n title: string\n body: string\n path: string\n terms: string[]\n }>\n return raw.slice(0, k).map((r) => ({\n id: r.id,\n title: r.title,\n path: r.path,\n score: r.score,\n snippet: makeSnippet(r.body || \"\", r.terms || []),\n }))\n}\n\n/** List metadata about an agent's index without loading the full thing. */\nexport function indexInfo(agentId: string, opts: { baseDir?: string } = {}): {\n exists: boolean\n path: string\n docs: number\n} {\n const path = indexFilePath(agentId, opts.baseDir)\n if (!existsSync(path)) return { exists: false, path, docs: 0 }\n try {\n const raw = JSON.parse(readFileSync(path, \"utf8\"))\n // minisearch v7 puts the stored fields under `storedFields` (no\n // leading underscore), keyed by internal numeric doc id. Earlier\n // versions used `_storedFields`. Honour both for robustness across\n // minor minisearch upgrades.\n const sf = raw?.storedFields ?? raw?._storedFields\n if (typeof raw?.documentCount === \"number\") return { exists: true, path, docs: raw.documentCount }\n const docs = sf && typeof sf === \"object\" ? Object.keys(sf).length : 0\n return { exists: true, path, docs }\n } catch {\n return { exists: true, path, docs: 0 }\n }\n}\n","import { z } from \"zod\"\nimport { getSignalService } from \"@/agents/signals/instance\"\nimport type { BuiltinAction } from \"./types\"\n\n// --- signal.resume (#857) ---\n//\n// Resume a task a stop signal paused, from a workflow step: the task runs\n// again in its own chat with its resume plan prepended. The step acts for\n// the owner who wrote the workflow; `by` names it in the event and plan.\n\nconst signalResumeInput = z.object({\n /** The stopped task's id (`agentx signal list`). */\n id: z.string().min(1),\n reason: z.string().max(500).optional(),\n /** Who to name as the resumer. Default \"workflow\". */\n by: z.string().min(1).max(100).default(\"workflow\"),\n})\ntype SignalResumeInput = z.infer<typeof signalResumeInput>\n\nconst signalResumeOutput = z.object({\n ok: z.boolean(),\n id: z.string(),\n agentId: z.string().nullable(),\n error: z.string().optional(),\n})\ntype SignalResumeOutput = z.infer<typeof signalResumeOutput>\n\nexport const signalResume: BuiltinAction<SignalResumeInput, SignalResumeOutput> = {\n name: \"signal.resume\",\n description: \"Resume a task a stop signal paused, from its resume plan, in the same chat\",\n inputSchema: signalResumeInput,\n outputSchema: signalResumeOutput,\n handler: async (input) => {\n const service = getSignalService()\n if (!service) return { ok: false, id: input.id, agentId: null, error: \"signals are not running in this process\" }\n const r = await service.resume({ kind: \"owner\", name: input.by }, input.id, input.reason)\n if (!r.ok) return { ok: false, id: input.id, agentId: service.get(input.id)?.agentId ?? null, error: r.error }\n return { ok: true, id: r.record.id, agentId: r.record.agentId }\n },\n}\n","import type { SignalService } from \"./service\"\n\n// Process-wide handle, set by the daemon once the service exists, so the\n// `signal.resume` built-in action (workflow steps) can reach it.\n\nlet instance: SignalService | undefined\n\nexport function setSignalService(s: SignalService | undefined): void {\n instance = s\n}\n\nexport function getSignalService(): SignalService | undefined {\n return instance\n}\n","// --- Built-in actions barrel ---\n//\n// Importing this module registers every shipped built-in into the\n// process-global registry. The daemon imports it once at startup so\n// callers (HTTP routes, CLI, workflows) can look actions up by name.\n//\n// To add a new built-in: define it in a sibling file, import here,\n// pass it to registerBuiltin(). Keep the imports alphabetical for\n// human review.\n\nimport { registerBuiltin, _resetBuiltinsForTesting as _registryReset } from \"./registry\"\nimport { agentCall } from \"./agent\"\nimport { channelAssign, channelCreateIssue, channelLabel, channelReply } from \"./channel\"\nimport { extractStructured } from \"./extract\"\nimport { fileReadLines, fileWriteJsonl } from \"./file\"\nimport { httpFetch, httpPost } from \"./http\"\nimport { meshDelegate } from \"./mesh\"\nimport { ragLexical } from \"./rag\"\nimport { signalResume } from \"./signal\"\n\n/**\n * Register every shipped built-in. Idempotent — re-registering the\n * same name overwrites with the latest handler (registerBuiltin's\n * own contract), so calling this multiple times is safe and matches\n * the in-memory registry's current state.\n */\nexport function registerAllBuiltins(): void {\n registerBuiltin(agentCall)\n registerBuiltin(channelAssign)\n registerBuiltin(channelCreateIssue)\n registerBuiltin(channelLabel)\n registerBuiltin(channelReply)\n registerBuiltin(extractStructured)\n registerBuiltin(fileReadLines)\n registerBuiltin(fileWriteJsonl)\n registerBuiltin(httpFetch)\n registerBuiltin(httpPost)\n registerBuiltin(meshDelegate)\n registerBuiltin(ragLexical)\n registerBuiltin(signalResume)\n}\n\n/** Test-only — clears the registry. Re-call registerAllBuiltins to repopulate. */\nexport function _resetBuiltinsForTesting(): void {\n _registryReset()\n}\n\nexport { getBuiltin, listBuiltins, runBuiltin } from \"./registry\"\nexport type { BuiltinAction, BuiltinActionMetadata } from \"./types\"\n"],"mappings":"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","names":["_registry","NAME_PATTERN","registerBuiltin","action","getBuiltin","name","listBuiltins","out","a","b","_resetBuiltinsForTesting","DEFAULT_TIMEOUT_MS","runBuiltin","rawInput","input","timeoutMs","handlerPromise","timeoutPromise","_","reject","output","parsed","z","_registry","getAgentRegistry","setAgentRegistry","r","agentCallInput","z","agentCallOutput","agentCall","input","registry","getAgentRegistry","chatId","started","response","z","channelReplyInput","z","channelReplyOutput","channelReply","input","router","getMessageRouter","idempotencyKey","messageId","channelLabelInput","channelLabelOutput","channelLabel","adapter","labels","channelAssignInput","channelAssignOutput","channelAssign","ids","channelCreateIssueInput","channelCreateIssueOutput","channelCreateIssue","created","related","z","extractInput","extractOutput","ANTHROPIC_API","ANTHROPIC_VERSION","extractStructured","input","apiKey","requestBody","ctrl","t","res","errBody","body","blocks","toolUse","b","usage","z","existsSync","readFileSync","appendFileSync","mkdirSync","statSync","resolve","dirname","isAbsolute","MAX_FILE_BYTES","resolveAllowed","input","abs","roots","r","root","readLinesInput","readLinesOutput","fileReadLines","stat","all","totalLines","lines","truncated","writeJsonlInput","writeJsonlOutput","fileWriteJsonl","e","payload","z","MAX_BODY_BYTES","HEADER_RECORD","allowedSchemes","assertAllowed","url","u","fetchInput","fetchOutput","readCappedText","res","reader","dec","total","body","truncated","done","value","headersToObject","h","out","v","k","httpFetch","input","ctrl","postInput","httpPost","headers","z","_mesh","getMesh","setMesh","m","meshDelegateInput","z","meshDelegateOutput","meshDelegate","input","mesh","getMesh","response","z","existsSync","mkdirSync","readFileSync","writeFileSync","statSync","resolve","basename","relative","fg","MiniSearch","FIELDS_INDEXED","FIELDS_STORED","indexFilePath","agentId","baseDir","newSearchEngine","fileToDoc","absPath","idBase","text","h1Match","title","buildIndex","globs","opts","cwd","files","p","ms","abs","doc","out","loadIndex","path","raw","e","SNIPPET_RADIUS","SNIPPET_MAX","makeSnippet","body","terms","lc","bestPos","t","i","start","end","slice","lexicalSearch","query","k","r","indexInfo","sf","docs","ragLexicalInput","z","ragLexicalOutput","ragLexical","input","lexicalSearch","z","instance","setSignalService","s","getSignalService","signalResumeInput","z","signalResumeOutput","signalResume","input","service","getSignalService","r","registerAllBuiltins","registerBuiltin","agentCall","channelAssign","channelCreateIssue","channelLabel","channelReply","extractStructured","fileReadLines","fileWriteJsonl","httpFetch","httpPost","meshDelegate","ragLexical","signalResume","_resetBuiltinsForTesting"]}
@@ -1,4 +1,4 @@
1
- import t from"chalk";import{spawn as S}from"child_process";import{resolve as j}from"path";var E=l=>l||j(process.cwd(),".agentx/wiki");function N(l){return async d=>{let{claudeCliEnv:e}=await import("./workspace-env-ROH45HXN.js"),h=["-p","-","--output-format","json","--max-turns","1","--model",l,"--tools","","--strict-mcp-config","--mcp-config",'{"mcpServers":{}}',"--settings",'{"disableAllHooks":true}',"--setting-sources","","--no-session-persistence"],y=await new Promise(($,a)=>{let s=S("claude",h,{env:e(),stdio:["pipe","pipe","pipe"]}),p="",g="",i=setTimeout(()=>s.kill("SIGTERM"),24e4);s.stdout.on("data",r=>{p+=r}),s.stderr.on("data",r=>{g+=r}),s.on("error",r=>{clearTimeout(i),a(r)}),s.on("close",r=>{clearTimeout(i),r===0?$(p):a(new Error(`claude exited ${r}: ${g.trim().slice(0,200)}`))}),s.stdin.end(d)}),c=JSON.parse(y);if(c.is_error)throw new Error(`model error: ${String(c.result).slice(0,200)}`);return{text:String(c.result??""),costUsd:Number(c.total_cost_usd)||0}}}function I(l){l.command("enrich [entities...]").description("write a full overview, sourced typed facts and linked history on entity pages (person, organization, project, place, assets)").option("--dir <path>","wiki directory (default .agentx/wiki)").option("--types <list>","comma-separated entity types","person,organization,project,place,device,server,app,domain,account").option("--max <n>","most entities per run","10").option("--max-cost <usd>","stop before the next call once the run spent this much","1").option("--model <m>","model","sonnet").option("--force","redo entities whose sources did not change").option("--dry-run","show what would be written, write nothing").option("--create <title>","first create a page for a thing other pages only name, then enrich it (needs --as and --owner)").option("--as <type>","type of the page --create makes, e.g. organization").option("--owner <agent>","agent whose wiki gets the page --create makes").option("--json","print the run as JSON").action(async(d,e)=>{let{WikiHub:h}=await import("./hub-XGWCWKMT.js"),{GraphCache:y}=await import("./graph-ZVKV3JBD.js"),{loadOntology:c}=await import("./load-LQ2I2PQI.js"),{loadRoster:$}=await import("./roster-BZGKG2ZA.js"),{ENRICH_TYPES:a,loadEnrichState:s,runEnrich:p,saveEnrichState:g}=await import("./enrich-R2LIDLPZ.js"),i=E(e.dir),r=e.types.split(",").map(o=>o.trim()).filter(Boolean),b=r.filter(o=>!a.includes(o));if(b.length){console.error(t.red(` not an entity type this job handles: ${b.join(", ")} (use ${a.join(", ")})`)),process.exitCode=1;return}let x=Number(e.max);if(!Number.isInteger(x)||x<1){console.error(t.red(" --max must be a whole number of entities, 1 or more")),process.exitCode=1;return}let w=Number(e.maxCost);if(!Number.isFinite(w)||w<=0){console.error(t.red(" --max-cost must be a positive number of dollars")),process.exitCode=1;return}let m=new h(i,()=>{});if(e.create){let{createEntityPage:o}=await import("./enrich-R2LIDLPZ.js");if(!e.as||!a.includes(e.as)||!e.owner){console.error(t.red(` --create needs --as <${a.join("|")}> and --owner <agent>`)),process.exitCode=1;return}if(m.syncedFrom(e.owner)){console.error(t.red(` ${e.owner}'s pages are copied from another node; pick an agent that runs here`)),process.exitCode=1;return}if(e.dryRun)console.log(t.dim(` --dry-run: would create "${e.create}" (${e.as}) in ${e.owner}'s wiki`));else{let f=o(m,e.create,e.as,e.owner,new Date().toISOString().slice(0,10));console.log(f?t.green(` created ${e.owner}/${f}`):t.dim(` ${e.owner} already has a page titled "${e.create}"`))}d=[...d,e.create],r.includes(e.as)||r.push(e.as)}let{ontology:v}=c(i),k=new y().get(m,v,$(i,m.listAgents([]),v.agent_names)),C=s(i),u=await p(m,k,N(e.model),{types:r,only:d,max:x,maxCostUsd:w,dryRun:!!e.dryRun,force:!!e.force,today:new Date().toISOString().slice(0,10),save:o=>g(i,o)},C);if(e.json){console.log(JSON.stringify(u,null,2));return}for(let o of u.outcomes){let f=o.status==="written"?t.green("\u2713"):o.status==="dry-run"?t.cyan("~"):t.yellow("\xB7");console.log(` ${f} ${o.title} ${t.dim(`${o.status} \xB7 ${o.page??"no page"} \xB7 overview ${o.overview?"yes":"no"} \xB7 ${o.statements} facts \xB7 ${o.links} links \xB7 $${o.costUsd.toFixed(3)}`)}`);for(let n of o.facts??[])console.log(t.dim(` fact: ${n.property} \u2192 ${n.value}${n.role?` (${n.role})`:""} \xB7 source ${n.source}`));for(let n of o.dropped.slice(0,6))console.log(t.dim(` dropped: ${n}`));o.preview&&console.log(t.dim(o.preview.split(`
1
+ import t from"chalk";import{spawn as S}from"child_process";import{resolve as j}from"path";var E=l=>l||j(process.cwd(),".agentx/wiki");function N(l){return async d=>{let{claudeCliEnv:e}=await import("./workspace-env-ROH45HXN.js"),h=["-p","-","--output-format","json","--max-turns","1","--model",l,"--tools","","--strict-mcp-config","--mcp-config",'{"mcpServers":{}}',"--settings",'{"disableAllHooks":true}',"--setting-sources","","--no-session-persistence"],y=await new Promise(($,a)=>{let s=S("claude",h,{env:e(),stdio:["pipe","pipe","pipe"]}),p="",g="",i=setTimeout(()=>s.kill("SIGTERM"),24e4);s.stdout.on("data",r=>{p+=r}),s.stderr.on("data",r=>{g+=r}),s.on("error",r=>{clearTimeout(i),a(r)}),s.on("close",r=>{clearTimeout(i),r===0?$(p):a(new Error(`claude exited ${r}: ${g.trim().slice(0,200)}`))}),s.stdin.end(d)}),c=JSON.parse(y);if(c.is_error)throw new Error(`model error: ${String(c.result).slice(0,200)}`);return{text:String(c.result??""),costUsd:Number(c.total_cost_usd)||0}}}function I(l){l.command("enrich [entities...]").description("write a full overview, sourced typed facts and linked history on entity pages (person, organization, project, place, assets)").option("--dir <path>","wiki directory (default .agentx/wiki)").option("--types <list>","comma-separated entity types","person,organization,project,place,device,server,app,domain,account").option("--max <n>","most entities per run","10").option("--max-cost <usd>","stop before the next call once the run spent this much","1").option("--model <m>","model","sonnet").option("--force","redo entities whose sources did not change").option("--dry-run","show what would be written, write nothing").option("--create <title>","first create a page for a thing other pages only name, then enrich it (needs --as and --owner)").option("--as <type>","type of the page --create makes, e.g. organization").option("--owner <agent>","agent whose wiki gets the page --create makes").option("--json","print the run as JSON").action(async(d,e)=>{let{WikiHub:h}=await import("./hub-XGWCWKMT.js"),{GraphCache:y}=await import("./graph-ZVKV3JBD.js"),{loadOntology:c}=await import("./load-LQ2I2PQI.js"),{loadRoster:$}=await import("./roster-BZGKG2ZA.js"),{ENRICH_TYPES:a,loadEnrichState:s,runEnrich:p,saveEnrichState:g}=await import("./enrich-FPK3OW77.js"),i=E(e.dir),r=e.types.split(",").map(o=>o.trim()).filter(Boolean),b=r.filter(o=>!a.includes(o));if(b.length){console.error(t.red(` not an entity type this job handles: ${b.join(", ")} (use ${a.join(", ")})`)),process.exitCode=1;return}let x=Number(e.max);if(!Number.isInteger(x)||x<1){console.error(t.red(" --max must be a whole number of entities, 1 or more")),process.exitCode=1;return}let w=Number(e.maxCost);if(!Number.isFinite(w)||w<=0){console.error(t.red(" --max-cost must be a positive number of dollars")),process.exitCode=1;return}let m=new h(i,()=>{});if(e.create){let{createEntityPage:o}=await import("./enrich-FPK3OW77.js");if(!e.as||!a.includes(e.as)||!e.owner){console.error(t.red(` --create needs --as <${a.join("|")}> and --owner <agent>`)),process.exitCode=1;return}if(m.syncedFrom(e.owner)){console.error(t.red(` ${e.owner}'s pages are copied from another node; pick an agent that runs here`)),process.exitCode=1;return}if(e.dryRun)console.log(t.dim(` --dry-run: would create "${e.create}" (${e.as}) in ${e.owner}'s wiki`));else{let f=o(m,e.create,e.as,e.owner,new Date().toISOString().slice(0,10));console.log(f?t.green(` created ${e.owner}/${f}`):t.dim(` ${e.owner} already has a page titled "${e.create}"`))}d=[...d,e.create],r.includes(e.as)||r.push(e.as)}let{ontology:v}=c(i),k=new y().get(m,v,$(i,m.listAgents([]),v.agent_names)),C=s(i),u=await p(m,k,N(e.model),{types:r,only:d,max:x,maxCostUsd:w,dryRun:!!e.dryRun,force:!!e.force,today:new Date().toISOString().slice(0,10),save:o=>g(i,o)},C);if(e.json){console.log(JSON.stringify(u,null,2));return}for(let o of u.outcomes){let f=o.status==="written"?t.green("\u2713"):o.status==="dry-run"?t.cyan("~"):t.yellow("\xB7");console.log(` ${f} ${o.title} ${t.dim(`${o.status} \xB7 ${o.page??"no page"} \xB7 overview ${o.overview?"yes":"no"} \xB7 ${o.statements} facts \xB7 ${o.links} links \xB7 $${o.costUsd.toFixed(3)}`)}`);for(let n of o.facts??[])console.log(t.dim(` fact: ${n.property} \u2192 ${n.value}${n.role?` (${n.role})`:""} \xB7 source ${n.source}`));for(let n of o.dropped.slice(0,6))console.log(t.dim(` dropped: ${n}`));o.preview&&console.log(t.dim(o.preview.split(`
2
2
  `).slice(0,12).map(n=>` | ${n}`).join(`
3
3
  `)))}u.outcomes.length===0&&console.log(t.dim(" nothing to do: no entity of these types changed since the last run (--force redoes them)")),console.log(t.dim(` spent $${u.costUsd.toFixed(3)} of $${w}${u.capped?" \xB7 stopped at the cap":""}`))})}export{N as a,I as b};
4
- //# sourceMappingURL=chunk-XQVL2RYG.js.map
4
+ //# sourceMappingURL=chunk-WTMZW5X7.js.map