agentix-cli 0.52.0 → 0.52.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/{App-QVNQ5BQK.js → App-X6FGYBLX.js} +2 -2
  2. package/dist/{ChatApp-CC57XC23.js → ChatApp-XMUOXQ2M.js} +2 -2
  3. package/dist/{agent-ILH6ANOM.js → agent-KKVMU3VB.js} +2 -2
  4. package/dist/{board-dashboard-WG4ZZV4A.js → board-dashboard-KETIFTBD.js} +4 -4
  5. package/dist/{chunk-SRCXUZM2.js → chunk-3IUU4YFI.js} +2 -2
  6. package/dist/chunk-3IUU4YFI.js.map +1 -0
  7. package/dist/chunk-64UYAWAK.js +150 -0
  8. package/dist/chunk-64UYAWAK.js.map +1 -0
  9. package/dist/{chunk-CAA546XN.js → chunk-6BXKZY76.js} +2 -2
  10. package/dist/{chunk-6HAZ6YWI.js → chunk-76NNONUJ.js} +2 -2
  11. package/dist/{chunk-VMS3HVTT.js → chunk-7BQQWI4T.js} +2 -2
  12. package/dist/{chunk-XZTR5MBJ.js → chunk-7M7VJMGP.js} +2 -2
  13. package/dist/{chunk-H2TWRZC2.js → chunk-7NF45XCM.js} +2 -2
  14. package/dist/{chunk-NTG5ZXRI.js → chunk-7PK32QT5.js} +3 -3
  15. package/dist/{chunk-UL4E2CV4.js → chunk-AKAM4BNC.js} +13 -13
  16. package/dist/{chunk-U67EG5IF.js → chunk-AWRRBNWQ.js} +2 -2
  17. package/dist/{chunk-WDQ3BPFS.js → chunk-B5UA3X6E.js} +2 -2
  18. package/dist/{chunk-PSDCRZZM.js → chunk-E57WKMRR.js} +2 -2
  19. package/dist/{chunk-2KQTE4XI.js → chunk-H7R3F2CO.js} +2 -2
  20. package/dist/{chunk-JQR3NTHI.js → chunk-MHBUAU2B.js} +2 -2
  21. package/dist/{chunk-QP6XNTBB.js → chunk-NKSCUCVZ.js} +2 -2
  22. package/dist/{chunk-KFALP5NO.js → chunk-QDPLR3SB.js} +2 -2
  23. package/dist/{chunk-F7WY24UZ.js → chunk-QZ4M2KAC.js} +2 -2
  24. package/dist/{chunk-YE2BUU3Z.js → chunk-WCNKTV6G.js} +2 -2
  25. package/dist/{chunk-V7XZN3MQ.js → chunk-XOUIZBAQ.js} +2 -2
  26. package/dist/{chunk-ROCUOXCW.js → chunk-YPPTPBBV.js} +2 -2
  27. package/dist/{chunk-BNVF66YL.js → chunk-YS3Z2Z64.js} +2 -2
  28. package/dist/cli.js +1 -1
  29. package/dist/client-AVQSLPIZ.js +2 -0
  30. package/dist/{config-TVW7UCKG.js → config-FGCJVXYX.js} +2 -2
  31. package/dist/config-mutator-5JSG3CHW.js +2 -0
  32. package/dist/doctor-VITHTLEC.js +2 -0
  33. package/dist/index.d.ts +24 -1
  34. package/dist/index.js +1 -1
  35. package/dist/program-MNFDOQGQ.js +2 -0
  36. package/dist/{promote-4T64VW5K.js → promote-NBFF7ZIW.js} +2 -2
  37. package/dist/query-XCXR57IV.js +2 -0
  38. package/dist/{registry-E4QUXHMQ.js → registry-5ZP3ZNSH.js} +2 -2
  39. package/dist/{request-planner-BRLDCYU5.js → request-planner-ZEXFARZE.js} +2 -2
  40. package/dist/{review-candidates-QWW5PDUU.js → review-candidates-F2HNH2TZ.js} +2 -2
  41. package/dist/{routing-DP6S7OJL.js → routing-XSRZ7V23.js} +2 -2
  42. package/dist/schedule-tool-AKCVLCWK.js +2 -0
  43. package/dist/scheduler-BEGZJWJU.js +2 -0
  44. package/dist/{seat-3KUNRM5Z.js → seat-IPDLEUI5.js} +2 -2
  45. package/dist/{select-ILXHYJGD.js → select-BYOX63CR.js} +2 -2
  46. package/dist/{tool-SF3BCY55.js → tool-WW4YCMSP.js} +2 -2
  47. package/dist/wiki-IVJJQUKB.js +2 -0
  48. package/package.json +1 -1
  49. package/dist/chunk-SRCXUZM2.js.map +0 -1
  50. package/dist/chunk-YEV6W34S.js +0 -150
  51. package/dist/chunk-YEV6W34S.js.map +0 -1
  52. package/dist/client-I7GAAM3T.js +0 -2
  53. package/dist/config-mutator-JHM53P5A.js +0 -2
  54. package/dist/doctor-CXFMV6PT.js +0 -2
  55. package/dist/program-UXJWH5JG.js +0 -2
  56. package/dist/query-6IKL52WT.js +0 -2
  57. package/dist/schedule-tool-TPJ6GR47.js +0 -2
  58. package/dist/scheduler-7QPG6OTY.js +0 -2
  59. package/dist/wiki-WETANN3W.js +0 -2
  60. /package/dist/{App-QVNQ5BQK.js.map → App-X6FGYBLX.js.map} +0 -0
  61. /package/dist/{ChatApp-CC57XC23.js.map → ChatApp-XMUOXQ2M.js.map} +0 -0
  62. /package/dist/{agent-ILH6ANOM.js.map → agent-KKVMU3VB.js.map} +0 -0
  63. /package/dist/{board-dashboard-WG4ZZV4A.js.map → board-dashboard-KETIFTBD.js.map} +0 -0
  64. /package/dist/{chunk-CAA546XN.js.map → chunk-6BXKZY76.js.map} +0 -0
  65. /package/dist/{chunk-6HAZ6YWI.js.map → chunk-76NNONUJ.js.map} +0 -0
  66. /package/dist/{chunk-VMS3HVTT.js.map → chunk-7BQQWI4T.js.map} +0 -0
  67. /package/dist/{chunk-XZTR5MBJ.js.map → chunk-7M7VJMGP.js.map} +0 -0
  68. /package/dist/{chunk-H2TWRZC2.js.map → chunk-7NF45XCM.js.map} +0 -0
  69. /package/dist/{chunk-NTG5ZXRI.js.map → chunk-7PK32QT5.js.map} +0 -0
  70. /package/dist/{chunk-UL4E2CV4.js.map → chunk-AKAM4BNC.js.map} +0 -0
  71. /package/dist/{chunk-U67EG5IF.js.map → chunk-AWRRBNWQ.js.map} +0 -0
  72. /package/dist/{chunk-WDQ3BPFS.js.map → chunk-B5UA3X6E.js.map} +0 -0
  73. /package/dist/{chunk-PSDCRZZM.js.map → chunk-E57WKMRR.js.map} +0 -0
  74. /package/dist/{chunk-2KQTE4XI.js.map → chunk-H7R3F2CO.js.map} +0 -0
  75. /package/dist/{chunk-JQR3NTHI.js.map → chunk-MHBUAU2B.js.map} +0 -0
  76. /package/dist/{chunk-QP6XNTBB.js.map → chunk-NKSCUCVZ.js.map} +0 -0
  77. /package/dist/{chunk-KFALP5NO.js.map → chunk-QDPLR3SB.js.map} +0 -0
  78. /package/dist/{chunk-F7WY24UZ.js.map → chunk-QZ4M2KAC.js.map} +0 -0
  79. /package/dist/{chunk-YE2BUU3Z.js.map → chunk-WCNKTV6G.js.map} +0 -0
  80. /package/dist/{chunk-V7XZN3MQ.js.map → chunk-XOUIZBAQ.js.map} +0 -0
  81. /package/dist/{chunk-ROCUOXCW.js.map → chunk-YPPTPBBV.js.map} +0 -0
  82. /package/dist/{chunk-BNVF66YL.js.map → chunk-YS3Z2Z64.js.map} +0 -0
  83. /package/dist/{client-I7GAAM3T.js.map → client-AVQSLPIZ.js.map} +0 -0
  84. /package/dist/{config-TVW7UCKG.js.map → config-FGCJVXYX.js.map} +0 -0
  85. /package/dist/{config-mutator-JHM53P5A.js.map → config-mutator-5JSG3CHW.js.map} +0 -0
  86. /package/dist/{doctor-CXFMV6PT.js.map → doctor-VITHTLEC.js.map} +0 -0
  87. /package/dist/{program-UXJWH5JG.js.map → program-MNFDOQGQ.js.map} +0 -0
  88. /package/dist/{promote-4T64VW5K.js.map → promote-NBFF7ZIW.js.map} +0 -0
  89. /package/dist/{query-6IKL52WT.js.map → query-XCXR57IV.js.map} +0 -0
  90. /package/dist/{registry-E4QUXHMQ.js.map → registry-5ZP3ZNSH.js.map} +0 -0
  91. /package/dist/{request-planner-BRLDCYU5.js.map → request-planner-ZEXFARZE.js.map} +0 -0
  92. /package/dist/{review-candidates-QWW5PDUU.js.map → review-candidates-F2HNH2TZ.js.map} +0 -0
  93. /package/dist/{routing-DP6S7OJL.js.map → routing-XSRZ7V23.js.map} +0 -0
  94. /package/dist/{schedule-tool-TPJ6GR47.js.map → schedule-tool-AKCVLCWK.js.map} +0 -0
  95. /package/dist/{scheduler-7QPG6OTY.js.map → scheduler-BEGZJWJU.js.map} +0 -0
  96. /package/dist/{seat-3KUNRM5Z.js.map → seat-IPDLEUI5.js.map} +0 -0
  97. /package/dist/{select-ILXHYJGD.js.map → select-BYOX63CR.js.map} +0 -0
  98. /package/dist/{tool-SF3BCY55.js.map → tool-WW4YCMSP.js.map} +0 -0
  99. /package/dist/{wiki-WETANN3W.js.map → wiki-IVJJQUKB.js.map} +0 -0
@@ -1,7 +1,7 @@
1
- import{g as S,h as j,o as O,p as I}from"./chunk-S7CVSKOX.js";import{m as A,p as T}from"./chunk-SRCXUZM2.js";T();import{Command as _}from"commander";import f from"chalk";import{execFileSync as h}from"child_process";import{accessSync as q,constants as z,existsSync as y,readFileSync as k,readdirSync as x,statSync as B}from"fs";import{join as E,resolve as m}from"path";import{homedir as M}from"os";import{createRequire as X}from"module";import{execFile as D}from"child_process";var L=(n,t)=>new Promise(e=>{try{D(n,t,{timeout:5e3},(i,s)=>e(i?null:String(s)))}catch{e(null)}}),R="Open System Settings \u203A Notifications \u203A AgentX Helper, turn on Allow notifications and choose Banners.";async function N(n={}){if((n.platform??process.platform)!=="darwin")return{state:"unsupported",message:"Desktop banners are only shown on a Mac."};let t=n.helper===void 0?I():n.helper;if(!t)return{state:"missing",message:"AgentX Helper is not installed, so banners come from Script Editor and show its icon.",fix:'Run agentx desktop install, then run agentx notify "Hello" --title "Test" and click Allow.'};let e=await(n.run??L)(t,["notify-status"]),i=null;try{i=e?JSON.parse(e):null}catch{i=null}return i?i.authorization==="notDetermined"?{state:"not-asked",path:t,message:"macOS has not asked yet whether AgentX Helper may notify; banners show the Script Editor icon until it does.",fix:'Run agentx notify "Hello" --title "Test" and click Allow when macOS asks.'}:i.authorization==="denied"?{state:"not-allowed",path:t,message:"macOS does not allow AgentX Helper to notify, so banners show the Script Editor icon.",fix:R}:i.alertStyle==="none"?{state:"hidden",path:t,message:"AgentX Helper may notify, but its banner style is None, so nothing appears on screen.",fix:R}:{state:"ready",path:t,message:"AgentX Helper posts banners with the AgentX icon."}:{state:"outdated",path:t,message:"AgentX Helper is too old to report whether it may notify.",fix:"Run agentx desktop install to update it."}}async function J(n={}){let t=[];await Z(t),G(t);let e=V(t);return e&&K(t,e),e&&U(t,e),e&&Q(t,e),e&&Y(t,e),e&&te(t,e),e&&await F(t,e),n.running!==!1&&e&&await ee(t,e),{checks:t,summary:P(t)}}var ye=new _().name("doctor").description("pre-flight health check: Node, config, credentials, daemon").option("--no-running","skip the live daemon probe").option("--json","emit machine-readable JSON (stable shape for CI)").action(async n=>{let{checks:t,summary:e}=await J({running:n.running!==!1});n.json?process.stdout.write(JSON.stringify({checks:t,summary:e},null,2)+`
1
+ import{g as S,h as j,o as O,p as I}from"./chunk-S7CVSKOX.js";import{m as A,p as T}from"./chunk-3IUU4YFI.js";T();import{Command as _}from"commander";import f from"chalk";import{execFileSync as h}from"child_process";import{accessSync as q,constants as z,existsSync as y,readFileSync as k,readdirSync as x,statSync as B}from"fs";import{join as E,resolve as m}from"path";import{homedir as M}from"os";import{createRequire as X}from"module";import{execFile as D}from"child_process";var L=(n,t)=>new Promise(e=>{try{D(n,t,{timeout:5e3},(i,s)=>e(i?null:String(s)))}catch{e(null)}}),R="Open System Settings \u203A Notifications \u203A AgentX Helper, turn on Allow notifications and choose Banners.";async function N(n={}){if((n.platform??process.platform)!=="darwin")return{state:"unsupported",message:"Desktop banners are only shown on a Mac."};let t=n.helper===void 0?I():n.helper;if(!t)return{state:"missing",message:"AgentX Helper is not installed, so banners come from Script Editor and show its icon.",fix:'Run agentx desktop install, then run agentx notify "Hello" --title "Test" and click Allow.'};let e=await(n.run??L)(t,["notify-status"]),i=null;try{i=e?JSON.parse(e):null}catch{i=null}return i?i.authorization==="notDetermined"?{state:"not-asked",path:t,message:"macOS has not asked yet whether AgentX Helper may notify; banners show the Script Editor icon until it does.",fix:'Run agentx notify "Hello" --title "Test" and click Allow when macOS asks.'}:i.authorization==="denied"?{state:"not-allowed",path:t,message:"macOS does not allow AgentX Helper to notify, so banners show the Script Editor icon.",fix:R}:i.alertStyle==="none"?{state:"hidden",path:t,message:"AgentX Helper may notify, but its banner style is None, so nothing appears on screen.",fix:R}:{state:"ready",path:t,message:"AgentX Helper posts banners with the AgentX icon."}:{state:"outdated",path:t,message:"AgentX Helper is too old to report whether it may notify.",fix:"Run agentx desktop install to update it."}}async function J(n={}){let t=[];await Z(t),G(t);let e=V(t);return e&&K(t,e),e&&U(t,e),e&&Q(t,e),e&&Y(t,e),e&&te(t,e),e&&await F(t,e),n.running!==!1&&e&&await ee(t,e),{checks:t,summary:P(t)}}var ye=new _().name("doctor").description("pre-flight health check: Node, config, credentials, daemon").option("--no-running","skip the live daemon probe").option("--json","emit machine-readable JSON (stable shape for CI)").action(async n=>{let{checks:t,summary:e}=await J({running:n.running!==!1});n.json?process.stdout.write(JSON.stringify({checks:t,summary:e},null,2)+`
2
2
  `):ne(t),process.exit(e.errors>0?1:0)});async function F(n,t,e=N){if(!O(t.notifications?.local).banner)return;let i=await e();i.state!=="unsupported"&&n.push({severity:i.state==="ready"?"ok":"warn",group:"Notifications",title:i.message,detail:i.path,fix:i.fix})}async function Z(n){let t=Number(process.versions.node.split(".")[0]);n.push({severity:t==22?"ok":"fail",group:"Environment",title:`Node.js ${process.versions.node}`,detail:t==22?void 0:"AgentX requires Node 22.x.",fix:t==22?void 0:"Install Node 22 (nvm install 22 && nvm use 22)"});let e=a=>{try{return h(process.platform==="win32"?"where":"which",[a],{encoding:"utf-8"}).trim().split(`
3
3
  `)[0]}catch{return null}},i=e("npm");n.push({severity:i?"ok":"fail",group:"Environment",title:i?"npm on PATH":"npm not found",detail:i||void 0});let s=e("claude");if(s){let a;try{a=h("claude",["--version"],{encoding:"utf-8",timeout:3e3}).trim()}catch{}n.push({severity:"ok",group:"Environment",title:`claude CLI ${a||"installed"}`,detail:s})}else n.push({severity:"warn",group:"Environment",title:"claude CLI not on PATH",detail:"Only required for agents on the claude-code tier.",fix:"See https://docs.anthropic.com/en/docs/claude-code"});let r=e("codex");if(r){let a;try{a=h("codex",["--version"],{encoding:"utf-8",timeout:3e3}).trim()}catch{}n.push({severity:"ok",group:"Environment",title:`codex CLI ${a||"installed"}`,detail:r})}else n.push({severity:"warn",group:"Environment",title:"codex CLI not on PATH",detail:"Only required for agents on the codex-cli tier.",fix:"Install with `npm i -g @openai/codex`."});let l=e("opencode");if(l){let a;try{a=h("opencode",["--version"],{encoding:"utf-8",timeout:3e3}).trim()}catch{}n.push({severity:"ok",group:"Environment",title:`opencode CLI ${a||"installed"}`,detail:l})}else n.push({severity:"warn",group:"Environment",title:"opencode CLI not on PATH",detail:"Only required for agents on the opencode tier.",fix:"Install from https://opencode.ai/docs/."});try{X(import.meta.url)("better-sqlite3"),n.push({severity:"ok",group:"Environment",title:`better-sqlite3 loads for Node ${process.version}`,detail:`NODE_MODULE_VERSION ${process.versions.modules}`})}catch(a){n.push({severity:"fail",group:"Environment",title:"better-sqlite3 native binding does not load",detail:a?.message??String(a),fix:`Run "pnpm rebuild better-sqlite3" with the same Node used by the daemon (${process.version}, modules ${process.versions.modules}).`})}}function G(n){if(process.platform!=="darwin")return;let t=E(M(),"Library/LaunchAgents"),e=[];try{e=x(t).filter(s=>/agentx\.voice.*\.plist$/.test(s))}catch{return}let i=s=>{try{return q(s,z.X_OK),!0}catch{return!1}};for(let s of e){let r=S(k(E(t,s),"utf-8")),l=j("ffmpeg",r,i);n.push(l?{severity:"ok",group:"Desktop",title:"ffmpeg reachable by the desktop app",detail:`${l} (${s})`}:{severity:"warn",group:"Desktop",title:"ffmpeg not reachable by the desktop app",detail:`Local Whisper transcription fails without it. ${s} sets PATH to ${r}.`,fix:"Install ffmpeg (brew install ffmpeg), then rerun agentx desktop install."})}}function V(n){let t=m(process.cwd(),"agentx.json");if(!y(t))return n.push({severity:"fail",group:"Config",title:"agentx.json not found",detail:`Looked in ${t}`,fix:"Run `agentx setup` to create one via the web wizard."}),null;let e;try{e=JSON.parse(k(t,"utf-8"))}catch(l){return n.push({severity:"fail",group:"Config",title:"agentx.json is not valid JSON",detail:l.message}),null}try{A(t),n.push({severity:"ok",group:"Config",title:`agentx.json valid (${Object.keys(e.agents||{}).length} agents, ${Object.keys(e.crons||{}).length} schedules)`})}catch(l){n.push({severity:"fail",group:"Config",title:"agentx.json failed schema validation",detail:l.message,fix:"Open /admin \u2192 Advanced tab to edit and re-save."})}let i=Object.entries(e.agents||{}).filter(([,l])=>l.tier==="claude-code");i.length>0&&((()=>{try{return h(process.platform==="win32"?"where":"which",["claude"],{stdio:"ignore"}),!0}catch{return!1}})()||n.push({severity:"fail",group:"Config",title:`${i.length} agent(s) use claude-code tier but claude CLI is missing`,detail:i.map(([a])=>a).join(", "),fix:"Install Claude Code (https://docs.anthropic.com/en/docs/claude-code) or switch these agents to tier=sdk."}));let s=Object.entries(e.agents||{}).filter(([,l])=>l.tier==="codex-cli");s.length>0&&((()=>{try{return h(process.platform==="win32"?"where":"which",["codex"],{stdio:"ignore"}),!0}catch{return!1}})()||n.push({severity:"fail",group:"Config",title:`${s.length} agent(s) use codex-cli tier but codex CLI is missing`,detail:s.map(([a])=>a).join(", "),fix:"Install Codex CLI with `npm i -g @openai/codex` or switch these agents to tier=claude-code."}));let r=Object.entries(e.agents||{}).filter(([,l])=>l.tier==="opencode");return r.length>0&&((()=>{try{return h(process.platform==="win32"?"where":"which",["opencode"],{stdio:"ignore"}),!0}catch{return!1}})()||n.push({severity:"fail",group:"Config",title:`${r.length} agent(s) use opencode tier but OpenCode CLI is missing`,detail:r.map(([a])=>a).join(", "),fix:"Install OpenCode from https://opencode.ai/docs/ or switch these agents to another tier."})),e}function K(n,t){let e=new Set;if($(t,e),e.size===0){n.push({severity:"ok",group:"Secrets",title:"No ${VAR} references in agentx.json"});return}let i=m(process.cwd(),".env"),s={};if(y(i))for(let a of k(i,"utf-8").split(/\r?\n/)){let g=a.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$/i);g&&(s[g[1]]=g[2])}let r=[],l=[];for(let a of e){let g=process.env[a]??s[a];g===void 0?r.push(a):(!g.trim()||/^["']?\s*["']?$/.test(g))&&l.push(a)}r.length===0&&l.length===0?n.push({severity:"ok",group:"Secrets",title:`${e.size} env reference(s) resolved`}):(r.length>0&&n.push({severity:"fail",group:"Secrets",title:`${r.length} env var(s) referenced in agentx.json but missing`,detail:r.join(", "),fix:`Add to .env \u2014 e.g. ${r[0]}=<value>`}),l.length>0&&n.push({severity:"warn",group:"Secrets",title:`${l.length} env var(s) set but empty`,detail:l.join(", ")}))}function $(n,t){if(typeof n=="string")for(let e of n.matchAll(/\$\{([A-Z_][A-Z0-9_]*)\}/g))t.add(e[1]);else if(Array.isArray(n))for(let e of n)$(e,t);else if(n&&typeof n=="object")for(let e of Object.values(n))$(e,t)}function U(n,t){let e=[];for(let[i,s]of Object.entries(t.agents||{})){if(!s.workspace)continue;let r=s.workspace.startsWith("/")?s.workspace:m(process.cwd(),s.workspace);try{B(r).isDirectory()||e.push(`${i}: ${r} (exists but not a directory)`)}catch{e.push(`${i}: ${r}`)}}e.length===0?n.push({severity:"ok",group:"Workspaces",title:"All agent workspace folders exist"}):n.push({severity:"warn",group:"Workspaces",title:`${e.length} agent workspace(s) missing`,detail:e.join(`
4
4
  `),fix:"The daemon will create missing folders on first task, but you won't see CLAUDE.md / skills until you populate them."})}function Q(n,t){let e=/\$\{[A-Za-z_][A-Za-z0-9_]*\}/g,i=[];for(let[s,r]of Object.entries(t.agents||{})){if(!r.workspace)continue;let l=r.workspace.startsWith("/")?r.workspace:m(process.cwd(),r.workspace);for(let a of["settings.json","settings.local.json"]){let g=m(l,".claude",a);if(!y(g))continue;let w;try{w=JSON.parse(k(g,"utf-8"))}catch(d){i.push({severity:"fail",agent:s,msg:`${a}: JSON parse error \u2014 ${d.message}`});continue}let b=w.env||{};for(let[d,p]of Object.entries(b)){if(typeof p!="string")continue;let u=p.match(e);u&&i.push({severity:"fail",agent:s,msg:`${a} env.${d} contains unexpanded ${[...new Set(u)].join(",")} \u2014 Claude Code does NOT expand \${VAR} in settings.json (use a fully-literal value)`})}let o=b.PATH;if(typeof o=="string"){let d=o.split(":").filter(Boolean);d.includes("/usr/bin")||i.push({severity:"fail",agent:s,msg:`${a} env.PATH missing /usr/bin \u2014 cat/head/sh/which will fail`}),d.includes("/bin")||i.push({severity:"fail",agent:s,msg:`${a} env.PATH missing /bin \u2014 ls/cp/mv will fail`})}let c=w.permissions;if(c&&typeof c=="object"&&"allow"in c){let d=c.allow,p=c.deny;Array.isArray(d)&&d.length===0&&Array.isArray(p)&&p.length>0&&i.push({severity:"warn",agent:s,msg:`${a} permissions.allow is explicitly [] with ${p.length} deny rules \u2014 agent may be locked out (omit the key to use defaults instead)`})}}}if(i.length===0){n.push({severity:"ok",group:"Workspace settings",title:`All ${Object.keys(t.agents||{}).length} agent .claude/settings.json files clean`});return}for(let s of i)n.push({severity:s.severity,group:"Workspace settings",title:`${s.agent}: ${s.msg}`,fix:s.severity==="fail"?"Edit .claude/settings.json \u2014 replace ${VAR} with the literal value or omit the key to inherit.":"Either remove the empty allow list or populate it."})}function Y(n,t){let e=t.webhooks??[],i=[],s=m(process.cwd(),t.workflows?.dir||".agentx/workflows"),r=new Set;try{if(y(s))for(let o of x(s))o.endsWith(".json")&&!o.startsWith("_")&&!o.endsWith(".disabled.json")&&r.add(o.replace(/\.json$/,""))}catch{}let l=new Set(["github","gitlab"]);for(let o of e){if(!o.enabled||!l.has(o.source))continue;!(o.triggers&&Object.keys(o.triggers).length>0)&&!o.defaultWorkflow&&i.push({severity:"warn",title:`webhook "${o.id}" (${o.source} -> ${o.agentId}) has no triggers map; every event-type collapses to the bound agent`,fix:'Add a triggers map: { "issues.opened": "wf-id", "pull_request.synchronize": "wf-id" } \u2014 or set defaultWorkflow.'})}for(let o of e)if(!(!o.enabled||!o.triggers)){for(let[c,d]of Object.entries(o.triggers))r.size>0&&!r.has(d)&&i.push({severity:"fail",title:`webhook "${o.id}".triggers["${c}"] -> "${d}" \u2014 no such workflow under ${t.workflows?.dir||".agentx/workflows"}`,fix:"Create the workflow file or fix the id in agentx.json"});o.defaultWorkflow&&r.size>0&&!r.has(o.defaultWorkflow)&&i.push({severity:"fail",title:`webhook "${o.id}".defaultWorkflow -> "${o.defaultWorkflow}" \u2014 no such workflow`,fix:"Create the workflow file or fix the id in agentx.json"})}try{if(y(s)){for(let o of x(s))if(!(!o.endsWith(".json")||o.startsWith("_")||o.endsWith(".disabled.json")))try{let c=JSON.parse(k(m(s,o),"utf-8"));c?.status==="active"&&c?.state==="quarantined"&&i.push({severity:"warn",title:`workflow "${c.id??o}" is status=active but state=quarantined \u2014 it looks live but will never dispatch`,fix:'Resolve the conflict the detector flagged, then set state back to "active" (or set status to "review" while parked).'})}catch{}}}catch{}let a=new Set((t.mesh?.peers??[]).map(o=>o.name));for(let o of e)!o.enabled||!o.node||a.has(o.node)||i.push({severity:"fail",title:`webhook "${o.id}" routes to mesh peer "${o.node}" which is not in mesh.peers`,fix:"Add the peer to mesh.peers or remove the node field on the webhook."});let g=new Map;for(let o of e){if(!o.enabled)continue;let c=`${o.source}:${o.agentId}`,d=g.get(c);d?i.push({severity:"warn",title:`webhook entries "${d}" and "${o.id}" both enabled for ${o.source} -> ${o.agentId}; only the first is dispatched`,fix:"Disable one entry, or merge their triggers maps into a single entry."}):g.set(c,o.id)}let w=new Set(Object.keys(t.agents??{}));for(let o of t.channels?.gitlab?.agentMappings??[])if(o?.agentId){if(o.node){a.has(o.node)||i.push({severity:"fail",title:`gitlab.agentMappings entry agentId="${o.agentId}" routes to mesh peer "${o.node}" which is not in mesh.peers`,fix:"Add the peer to mesh.peers or drop the node field on the mapping."});continue}w.has(o.agentId)||i.push({severity:"warn",title:`gitlab.agentMappings entry agentId="${o.agentId}" \u2014 no such agent in agents.* (and no node field, so it's not a cross-mesh route)`,fix:'Add the agent to agents.*, set node:"<peer>" if the agent lives remotely, or remove the mapping.'})}for(let[o,c]of Object.entries(t.channels?.telegram?.accounts??{}))c.agentBinding?w.has(c.agentBinding)||i.push({severity:"fail",title:`telegram account "${o}".agentBinding -> "${c.agentBinding}" \u2014 no such agent in agents.*`,fix:"Fix the agentBinding or define the agent in agents.*."}):i.push({severity:"fail",title:`telegram account "${o}" has no agentBinding; every DM to this bot will drop`,fix:"Set agentBinding to a valid agent id."});let b=new Set(["telegram-bot","whatsapp","slack-bot","discord-bot","gitlab-user","github-user","gmail","hotmail","smtp","hubspot","salesforce","pipedrive","odoo","trello","linear","asana","jira","notion","stripe","sentry","vercel","twilio","custom"]);for(let[o,c]of Object.entries(t.agents??{})){let d=c.integrations??[];if(!d.length)continue;let p=new Set;for(let u of d){let C=`${u.kind}::${u.label}`;p.has(C)&&i.push({severity:"warn",title:`agents.${o}.integrations: duplicate (${u.kind}, ${u.label})`,fix:"Remove the duplicate or rename one. (kind, label) must be unique per agent."}),p.add(C),b.has(u.kind)||i.push({severity:"warn",title:`agents.${o}.integrations: unknown kind "${u.kind}" on integration "${u.label}"`,fix:'Use a canonical kind from INTEGRATION_KINDS, or "custom" for ad-hoc services.'});let W=u.credentials||{};for(let[H,v]of Object.entries(W))typeof v=="string"&&/^[A-Z][A-Z0-9_]*$/.test(v)&&!process.env[v]&&i.push({severity:"warn",title:`agents.${o}.integrations[${u.kind}/${u.label}].${H} -> $${v} but env var is unset (in this shell)`,fix:`Set ${v} on the daemon environment. The daemon's process.env is what matters; this warning fires from your local shell.`})}}if(i.length===0){n.push({severity:"ok",group:"Routing",title:`${e.length} webhook(s), ${Object.keys(t.channels?.telegram?.accounts??{}).length} telegram account(s) \u2014 all routing references resolve`});return}for(let o of i)n.push({severity:o.severity,group:"Routing",title:o.title,fix:o.fix})}async function ee(n,t){let e=t.dashboard?.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800",i={};t.dashboard?.token&&(i.Authorization=`Bearer ${t.dashboard.token}`);try{let s=new AbortController,r=setTimeout(()=>s.abort(),2e3),l=await fetch(e+"/health",{headers:i,signal:s.signal});if(clearTimeout(r),!l.ok){n.push({severity:"warn",group:"Runtime",title:`Daemon responded ${l.status}`,detail:e});return}let a=await l.json();n.push({severity:"ok",group:"Runtime",title:`Daemon healthy \u2014 ${a.agents?.length??0} agents live, uptime ${Math.round((a.uptime??0)/60)}m`,detail:e})}catch{n.push({severity:"warn",group:"Runtime",title:"Daemon not reachable (not running?)",detail:e,fix:"Run `agentx daemon start`. Skip this check with `agentx doctor --no-running`."})}}function te(n,t){let e=Object.entries(t.agents||{}).filter(([,s])=>s?.codegraph===!0&&(s.tier==="claude-code"||s.tier==="codex-cli"));if(e.length===0)return;let i=null;try{i=h(process.platform==="win32"?"where":"which",["codegraph"],{encoding:"utf-8"}).trim().split(`
5
5
  `)[0]||null}catch{i=null}if(i){let s;try{s=h("codegraph",["--version"],{encoding:"utf-8",timeout:3e3}).trim()}catch{}n.push({severity:"ok",group:"CodeGraph",title:`codegraph CLI ${s||"installed"}`,detail:i})}else n.push({severity:"fail",group:"CodeGraph",title:"codegraph CLI not on PATH",detail:`${e.length} agent(s) have codegraph:true but the binary isn't available.`,fix:"Install with `npm i -g @colbymchenry/codegraph`."});for(let[s,r]of e){if(!r.workspace||!y(r.workspace)){n.push({severity:"warn",group:"CodeGraph",title:`${s}: workspace missing`,detail:`Workspace path ${r.workspace} does not exist \u2014 codegraph will skip this agent.`});continue}let l=m(r.workspace,".codegraph","codegraph.db");y(l)?n.push({severity:"ok",group:"CodeGraph",title:`${s}: index present`,detail:l}):n.push({severity:"warn",group:"CodeGraph",title:`${s}: index not built yet`,detail:".codegraph/ missing \u2014 daemon will background-index this workspace on next boot.",fix:`Run \`codegraph init --index ${r.workspace}\` to build it now.`})}}function P(n){return{errors:n.filter(t=>t.severity==="fail").length,warnings:n.filter(t=>t.severity==="warn").length,ok:n.filter(t=>t.severity==="ok").length}}function ne(n){console.log(),console.log(f.bold(" agentx doctor")),console.log();let t=new Map;for(let i of n)t.has(i.group)||t.set(i.group,[]),t.get(i.group).push(i);for(let[i,s]of t){console.log(f.bold(" "+i));for(let r of s){let l=r.severity==="ok"?f.green("\u2713"):r.severity==="warn"?f.yellow("!"):f.red("\u2717");console.log(` ${l} ${r.title}`),r.detail&&console.log(f.dim(" "+r.detail.replace(/\n/g,`
6
6
  `))),r.fix&&console.log(f.dim(" \u2192 "+r.fix))}console.log()}let e=P(n);e.errors>0?console.log(f.red.bold(` ${e.errors} error${e.errors===1?"":"s"}`)+(e.warnings?f.yellow(`, ${e.warnings} warning${e.warnings===1?"":"s"}`):"")+`. Fix the error${e.errors===1?"":"s"} and rerun.`):e.warnings>0?console.log(f.yellow.bold(` ${e.warnings} warning${e.warnings===1?"":"s"}.`)+f.dim(" Review but not blocking.")):console.log(f.green.bold(` All checks passed (${e.ok}).`)),console.log()}export{N as a,J as b,ye as c,F as d};
7
- //# sourceMappingURL=chunk-CAA546XN.js.map
7
+ //# sourceMappingURL=chunk-6BXKZY76.js.map
@@ -1,4 +1,4 @@
1
- import{a as R,b as j,c as O,d as W,e as D}from"./chunk-TFVUOC2C.js";import{b as C}from"./chunk-2GIDVZ4H.js";import{v,w as Q}from"./chunk-JQR3NTHI.js";import{b as $,c as M}from"./chunk-QOYAX2FT.js";import{readFileSync as T,existsSync as _}from"fs";Q();import{resolve as b}from"path";import{execSync as Y}from"child_process";async function V(n,i,s,e={}){let d=e.selectorModel??"haiku",a=e.synthModel??"sonnet",c=e.maxCandidates??3,l=e.maxHops??2,r=e.maxArticles??8,p=e.timeoutMs??6e4,u=e.log??console.error.bind(console,"[wiki-query]"),h=b(i.baseDir,"_index.md");if(!_(h))return w("no-catalog",n,"No _index.md found \u2014 run `agentx wiki status` to rebuild.");let k=T(h,"utf-8"),t=Date.now(),g=[],m="";try{let o=await B(n,i,s,c);o?(g=o,m=`[wiki-rerank seat] ${o.map(y=>y.title).join(" | ")}`):(m=await N(I(n,k,c),d,p),g=F(m))}catch(o){return u("selector failed:",o?.message),{...w("error",n,`Selector: ${o?.message||"unknown"}`),trace:{selectorMs:Date.now()-t,synthesisMs:0,selectorOutput:m}}}let A=Date.now()-t;if(g.length===0)return{...w("no-candidates",n,"Selector returned no candidates."),trace:{selectorMs:A,synthesisMs:0,selectorOutput:m}};let f=E(g,i,s,l,r);if(f.length===0)return{...w("no-candidates",n,"Candidates did not resolve to readable articles."),candidates:g,trace:{selectorMs:A,synthesisMs:0,selectorOutput:m}};let S=Date.now(),x="";try{x=await N(L(n,f),a,p*2)}catch(o){return u("synthesis failed:",o?.message),{...w("error",n,`Synthesis: ${o?.message||"unknown"}`),candidates:g,walked:f.map(y=>({title:y.meta.title,path:y.path,type:y.meta.type,hop:y.hop??0})),trace:{selectorMs:A,synthesisMs:Date.now()-S,selectorOutput:m}}}let P=Date.now()-S;return{answer:x.trim(),citations:f.map(o=>({title:o.meta.title,path:o.path,type:o.meta.type})),candidates:g,walked:f.map(o=>({title:o.meta.title,path:o.path,type:o.meta.type,hop:o.hop??0})),status:"ok",trace:{selectorMs:A,synthesisMs:P,selectorOutput:m}}}function w(n,i,s){return{answer:"",citations:[],candidates:[],walked:[],status:n,error:s}}function E(n,i,s,e,d){let a=new Map;for(let r of i.listArticles(s||""))a.set(r.meta.title.toLowerCase(),r.path);let c=new Map,l=[];for(let r of n)c.has(r.path)||l.push({path:r.path,hop:0});for(;l.length&&c.size<d;){let r=l.shift();if(c.has(r.path)||r.hop>e)continue;let p=s?i.readArticleAs(r.path,s):i.readArticle(r.path);if(p&&(c.set(r.path,{...p,hop:r.hop}),!(r.hop>=e)))for(let u of p.meta.related||[]){let h=a.get(u.toLowerCase());h&&!c.has(h)&&l.push({path:h,hop:r.hop+1})}}return Array.from(c.values())}async function B(n,i,s,e){try{let a=(i.rebuildIndex().articles??[]).filter(t=>t.path&&!t.path.includes("/_versions/"));if(a.length<2)return null;let c=a.map(t=>[t.title,(t.tags??[]).join(" "),(t.related??[]).join(" ")].join(" ")),l=M(n,$(c)).map(t=>t.docIndex);for(let t=0;t<a.length;t++)l.includes(t)||l.push(t);let p=l.slice(0,j).map(t=>({id:`k${t}`,title:a[t].title||a[t].path,tags:a[t].tags,excerpt:[a[t].type?`type: ${a[t].type}`:"",(a[t].related??[]).length?`related: ${(a[t].related??[]).join(", ")}`:""].filter(Boolean).join(" \xB7 ")})),u=await v(R,O({query:n,candidates:p,excerptChars:300}),W(p),{features:{agent:s??"unknown",stage:"catalog-selector"}});if(!u||u.mode!=="active")return null;let k=D(u.answers,p).ranked.slice(0,e).map(t=>a[Number(t.slice(1))]).filter(Boolean).map(t=>({title:t.title,path:t.path}));return k.length>0?k:null}catch{return null}}function I(n,i,s){return`You are picking candidate articles from a wiki catalog to answer a question. You do NOT answer the question. You pick which articles the answer is likely to come from.
1
+ import{a as R,b as j,c as O,d as W,e as D}from"./chunk-TFVUOC2C.js";import{b as C}from"./chunk-2GIDVZ4H.js";import{v,w as Q}from"./chunk-MHBUAU2B.js";import{b as $,c as M}from"./chunk-QOYAX2FT.js";import{readFileSync as T,existsSync as _}from"fs";Q();import{resolve as b}from"path";import{execSync as Y}from"child_process";async function V(n,i,s,e={}){let d=e.selectorModel??"haiku",a=e.synthModel??"sonnet",c=e.maxCandidates??3,l=e.maxHops??2,r=e.maxArticles??8,p=e.timeoutMs??6e4,u=e.log??console.error.bind(console,"[wiki-query]"),h=b(i.baseDir,"_index.md");if(!_(h))return w("no-catalog",n,"No _index.md found \u2014 run `agentx wiki status` to rebuild.");let k=T(h,"utf-8"),t=Date.now(),g=[],m="";try{let o=await B(n,i,s,c);o?(g=o,m=`[wiki-rerank seat] ${o.map(y=>y.title).join(" | ")}`):(m=await N(I(n,k,c),d,p),g=F(m))}catch(o){return u("selector failed:",o?.message),{...w("error",n,`Selector: ${o?.message||"unknown"}`),trace:{selectorMs:Date.now()-t,synthesisMs:0,selectorOutput:m}}}let A=Date.now()-t;if(g.length===0)return{...w("no-candidates",n,"Selector returned no candidates."),trace:{selectorMs:A,synthesisMs:0,selectorOutput:m}};let f=E(g,i,s,l,r);if(f.length===0)return{...w("no-candidates",n,"Candidates did not resolve to readable articles."),candidates:g,trace:{selectorMs:A,synthesisMs:0,selectorOutput:m}};let S=Date.now(),x="";try{x=await N(L(n,f),a,p*2)}catch(o){return u("synthesis failed:",o?.message),{...w("error",n,`Synthesis: ${o?.message||"unknown"}`),candidates:g,walked:f.map(y=>({title:y.meta.title,path:y.path,type:y.meta.type,hop:y.hop??0})),trace:{selectorMs:A,synthesisMs:Date.now()-S,selectorOutput:m}}}let P=Date.now()-S;return{answer:x.trim(),citations:f.map(o=>({title:o.meta.title,path:o.path,type:o.meta.type})),candidates:g,walked:f.map(o=>({title:o.meta.title,path:o.path,type:o.meta.type,hop:o.hop??0})),status:"ok",trace:{selectorMs:A,synthesisMs:P,selectorOutput:m}}}function w(n,i,s){return{answer:"",citations:[],candidates:[],walked:[],status:n,error:s}}function E(n,i,s,e,d){let a=new Map;for(let r of i.listArticles(s||""))a.set(r.meta.title.toLowerCase(),r.path);let c=new Map,l=[];for(let r of n)c.has(r.path)||l.push({path:r.path,hop:0});for(;l.length&&c.size<d;){let r=l.shift();if(c.has(r.path)||r.hop>e)continue;let p=s?i.readArticleAs(r.path,s):i.readArticle(r.path);if(p&&(c.set(r.path,{...p,hop:r.hop}),!(r.hop>=e)))for(let u of p.meta.related||[]){let h=a.get(u.toLowerCase());h&&!c.has(h)&&l.push({path:h,hop:r.hop+1})}}return Array.from(c.values())}async function B(n,i,s,e){try{let a=(i.rebuildIndex().articles??[]).filter(t=>t.path&&!t.path.includes("/_versions/"));if(a.length<2)return null;let c=a.map(t=>[t.title,(t.tags??[]).join(" "),(t.related??[]).join(" ")].join(" ")),l=M(n,$(c)).map(t=>t.docIndex);for(let t=0;t<a.length;t++)l.includes(t)||l.push(t);let p=l.slice(0,j).map(t=>({id:`k${t}`,title:a[t].title||a[t].path,tags:a[t].tags,excerpt:[a[t].type?`type: ${a[t].type}`:"",(a[t].related??[]).length?`related: ${(a[t].related??[]).join(", ")}`:""].filter(Boolean).join(" \xB7 ")})),u=await v(R,O({query:n,candidates:p,excerptChars:300}),W(p),{features:{agent:s??"unknown",stage:"catalog-selector"}});if(!u||u.mode!=="active")return null;let k=D(u.answers,p).ranked.slice(0,e).map(t=>a[Number(t.slice(1))]).filter(Boolean).map(t=>({title:t.title,path:t.path}));return k.length>0?k:null}catch{return null}}function I(n,i,s){return`You are picking candidate articles from a wiki catalog to answer a question. You do NOT answer the question. You pick which articles the answer is likely to come from.
2
2
 
3
3
  ## Question
4
4
 
@@ -42,4 +42,4 @@ ${s}
42
42
  Answer the question in 2\u20136 sentences. Cite articles by their title in square brackets like [Article Title]. If the articles do not answer the question, say so plainly (do not invent). Prefer concrete facts over hedging.
43
43
 
44
44
  Output ONLY the answer \u2014 no preamble, no "here is my answer:", no markdown fencing.`}function F(n){let i=n.match(/\[[\s\S]*?\]/);if(!i)return[];try{let s=JSON.parse(i[0]);return Array.isArray(s)?s.filter(e=>e&&typeof e.title=="string"&&typeof e.path=="string").map(e=>({title:e.title,path:e.path})):[]}catch{return[]}}async function N(n,i,s){let{writeFileSync:e,mkdirSync:d,rmSync:a}=await import("fs"),{tmpdir:c}=await import("os"),l=b(c(),`agentx-wiki-query-${process.pid}`);d(l,{recursive:!0});let r=b(l,`prompt-${Date.now()}.txt`);e(r,n);try{let p=`cat '${r}' | claude -p - --output-format json --max-turns 1 --model ${i} --disallowedTools "Bash Read Write Edit Glob Grep Agent WebSearch WebFetch NotebookEdit"`,u=Y(p,{env:C({...process.env}),encoding:"utf-8",timeout:s,maxBuffer:4*1024*1024});try{let h=JSON.parse(u);return String(h.result||h.content||"")}catch{return u}}finally{try{a(r,{force:!0})}catch{}}}export{V as a};
45
- //# sourceMappingURL=chunk-6HAZ6YWI.js.map
45
+ //# sourceMappingURL=chunk-76NNONUJ.js.map
@@ -1,5 +1,5 @@
1
- import{k as m,l as $,p as x}from"./chunk-SRCXUZM2.js";x();import{readFileSync as S,writeFileSync as P,existsSync as b}from"fs";import{resolve as f}from"path";function w(r){if(r)return f(r);let e=[f(process.cwd(),"agentx.json"),f(process.cwd(),".agentx/config.json")];for(let n of e)if(b(n))return n;return e[0]}function v(r){return JSON.parse(JSON.stringify(r))}async function O(r){try{let e=await fetch(`${r.replace(/\/$/,"")}/reload`,{method:"POST",signal:AbortSignal.timeout(3e3)});return e.ok?{ok:!0}:{ok:!1,reason:`HTTP ${e.status}`}}catch(e){return{ok:!1,reason:e?.cause?.code||e?.message||"unreachable"}}}async function J(r,e={}){let{validate:n=!0,dryRun:t=!1,reload:s=!0,configPath:u,daemonUrl:c}=e,o=w(u);if(!b(o))return{success:!1,path:o,error:`Config not found at ${o}. Run \`agentx init\` first.`};let d;try{d=S(o,"utf-8")}catch(a){return{success:!1,path:o,error:`Cannot read ${o}: ${a.message}`}}let g;try{g=JSON.parse(d)}catch(a){return{success:!1,path:o,error:`Invalid JSON in ${o}: ${a.message}`}}let i=v(g);try{await r(i)}catch(a){return{success:!1,path:o,error:`Mutator threw: ${a.message}`}}if(n){let a=$(i),l=m.safeParse(a);if(!l.success){let k=l.error.issues.map(y=>` ${y.path.join(".")||"<root>"}: ${y.message}`).join(`
1
+ import{k as m,l as $,p as x}from"./chunk-3IUU4YFI.js";x();import{readFileSync as S,writeFileSync as P,existsSync as b}from"fs";import{resolve as f}from"path";function w(r){if(r)return f(r);let e=[f(process.cwd(),"agentx.json"),f(process.cwd(),".agentx/config.json")];for(let n of e)if(b(n))return n;return e[0]}function v(r){return JSON.parse(JSON.stringify(r))}async function O(r){try{let e=await fetch(`${r.replace(/\/$/,"")}/reload`,{method:"POST",signal:AbortSignal.timeout(3e3)});return e.ok?{ok:!0}:{ok:!1,reason:`HTTP ${e.status}`}}catch(e){return{ok:!1,reason:e?.cause?.code||e?.message||"unreachable"}}}async function J(r,e={}){let{validate:n=!0,dryRun:t=!1,reload:s=!0,configPath:u,daemonUrl:c}=e,o=w(u);if(!b(o))return{success:!1,path:o,error:`Config not found at ${o}. Run \`agentx init\` first.`};let d;try{d=S(o,"utf-8")}catch(a){return{success:!1,path:o,error:`Cannot read ${o}: ${a.message}`}}let g;try{g=JSON.parse(d)}catch(a){return{success:!1,path:o,error:`Invalid JSON in ${o}: ${a.message}`}}let i=v(g);try{await r(i)}catch(a){return{success:!1,path:o,error:`Mutator threw: ${a.message}`}}if(n){let a=$(i),l=m.safeParse(a);if(!l.success){let k=l.error.issues.map(y=>` ${y.path.join(".")||"<root>"}: ${y.message}`).join(`
2
2
  `);return{success:!1,path:o,error:`Validation failed:
3
3
  ${k}`,after:i}}}if(t)return{success:!0,path:o,after:i,dryRun:!0};try{P(o,JSON.stringify(i,null,2)+`
4
4
  `)}catch(a){return{success:!1,path:o,error:`Write failed: ${a.message}`,after:i}}let p=!1,h;if(s){let a=c||R(i),l=await O(a);l.ok?p=!0:h=l.reason}return{success:!0,path:o,after:i,reloaded:p,reloadSkipped:h}}function R(r){let e=r?.node?.bind;if(!e)return"http://127.0.0.1:18800";let[n,t]=e.split(":");return`http://${n==="0.0.0.0"||n==="::"?"127.0.0.1":n}:${t}`}function N(r,e,n){let t=e.split("."),s=r;for(let u=0;u<t.length-1;u++){let c=t[u];(s[c]===void 0||s[c]===null)&&(s[c]={}),s=s[c]}s[t[t.length-1]]=n}function j(r,e){let n=e.split("."),t=r;for(let s of n){if(t==null)return;t=t[s]}return t}function A(r,e){let n=e.split("."),t=r;for(let s=0;s<n.length-1;s++){if(t==null)return;t=t[n[s]]}t!=null&&delete t[n[n.length-1]]}export{w as a,J as b,N as c,j as d,A as e};
5
- //# sourceMappingURL=chunk-VMS3HVTT.js.map
5
+ //# sourceMappingURL=chunk-7BQQWI4T.js.map
@@ -1,2 +1,2 @@
1
- import{e as o}from"./chunk-ROCUOXCW.js";import{resolve as a}from"path";import{existsSync as h,readdirSync as c,mkdirSync as l}from"fs";var g=class{baseDir;agentsDir;mode;sharedStore;agentStores=new Map;log;constructor(t=a(process.cwd(),".agentx/wiki"),e=console.error.bind(console,"[wiki-hub]"),i="graph"){this.baseDir=t,this.agentsDir=a(t,"agents"),this.mode=i,this.log=e,l(this.agentsDir,{recursive:!0}),this.sharedStore=new o(t,e)}getMode(){return this.mode}getAgentWiki(t){let e=`${t}:${this.mode}`;if(this.agentStores.has(e))return this.agentStores.get(e);let i=a(this.agentsDir,t,this.mode),r=new o(i,this.log);return this.agentStores.set(e,r),r}getSharedStore(){return this.sharedStore}listAgents(){let t=new Set,e=this.sharedStore.listEntries();for(let i of e)t.add(i.agentId);if(h(this.agentsDir))for(let i of c(this.agentsDir))!i.startsWith("_")&&!i.startsWith(".")&&t.add(i);return[...t].sort()}getAgentEntries(t){return this.sharedStore.listEntries({agentId:t})}getUnabsorbedEntries(t){let e=this.getAgentWiki(t),i=this.getAgentEntries(t),r=new Set,n=e.rebuildIndex();for(let s of n.articles)if(s.sources)for(let d of s.sources)r.add(d);return i.filter(s=>!r.has(s.id))}summary(){return this.listAgents().map(e=>{let i=this.getAgentEntries(e),n=this.getAgentWiki(e).rebuildIndex(),s=this.getUnabsorbedEntries(e);return{agentId:e,totalEntries:i.length,totalArticles:n.articles.length,unabsorbed:s.length,articles:n.articles}})}};export{g as a};
2
- //# sourceMappingURL=chunk-XZTR5MBJ.js.map
1
+ import{e as o}from"./chunk-YPPTPBBV.js";import{resolve as a}from"path";import{existsSync as h,readdirSync as c,mkdirSync as l}from"fs";var g=class{baseDir;agentsDir;mode;sharedStore;agentStores=new Map;log;constructor(t=a(process.cwd(),".agentx/wiki"),e=console.error.bind(console,"[wiki-hub]"),i="graph"){this.baseDir=t,this.agentsDir=a(t,"agents"),this.mode=i,this.log=e,l(this.agentsDir,{recursive:!0}),this.sharedStore=new o(t,e)}getMode(){return this.mode}getAgentWiki(t){let e=`${t}:${this.mode}`;if(this.agentStores.has(e))return this.agentStores.get(e);let i=a(this.agentsDir,t,this.mode),r=new o(i,this.log);return this.agentStores.set(e,r),r}getSharedStore(){return this.sharedStore}listAgents(){let t=new Set,e=this.sharedStore.listEntries();for(let i of e)t.add(i.agentId);if(h(this.agentsDir))for(let i of c(this.agentsDir))!i.startsWith("_")&&!i.startsWith(".")&&t.add(i);return[...t].sort()}getAgentEntries(t){return this.sharedStore.listEntries({agentId:t})}getUnabsorbedEntries(t){let e=this.getAgentWiki(t),i=this.getAgentEntries(t),r=new Set,n=e.rebuildIndex();for(let s of n.articles)if(s.sources)for(let d of s.sources)r.add(d);return i.filter(s=>!r.has(s.id))}summary(){return this.listAgents().map(e=>{let i=this.getAgentEntries(e),n=this.getAgentWiki(e).rebuildIndex(),s=this.getUnabsorbedEntries(e);return{agentId:e,totalEntries:i.length,totalArticles:n.articles.length,unabsorbed:s.length,articles:n.articles}})}};export{g as a};
2
+ //# sourceMappingURL=chunk-7M7VJMGP.js.map
@@ -1,2 +1,2 @@
1
- import{v as l,w}from"./chunk-JQR3NTHI.js";import{a as i,f as p}from"./chunk-72SZI2UW.js";w();p();var d="task-tier";function u(e){return{task:f(e.message,2e3),agent:e.agent,channel:e.channel??null,continuesExistingSession:e.isFollowUp??!1,...e.toolsAvailable?{toolsAvailable:e.toolsAvailable}:{}}}var c={needsFlagship:i("This task needs the strongest available model to be done correctly.",{true:"Doing it well takes real reasoning: writing or reviewing code, diagnosing a failure, planning work across several steps, weighing a judgement, handling money, touching production or anything irreversible, following a long or ambiguous instruction, or work where being subtly wrong would not be noticed. Anything where a weaker model would produce something that LOOKS right belongs here.",false:"It is mechanical and its result is obvious on sight: acknowledging or confirming a message, restating or formatting something already written, a greeting, a status echo, reading one file and reporting what it says, a lookup with one right answer, a scheduled heartbeat with nothing to decide."})};function g(e){return e.needsFlagship.noul}function f(e,n){return e.length>n?`${e.slice(0,n)}\u2026`:e}var h=.2,m=60*60*1e3;function F(e,n){if(e==="claude-code"){let t=n?.cheapModels?.[e]??n?.cheapModel;return t&&/^(claude-|haiku$|sonnet$|opus$)/.test(t)?t:void 0}if(e==="codex-cli"){let t=n?.cheapModels?.[e];return t&&/^(gpt-|o\d)/.test(t)?t:void 0}}async function M(e){let n=(o,r=null)=>({downgraded:!1,needsFlagship:r,reason:o});if(e.channel==="voice"||e.channel==="desktop"||e.channel==="opencode")return n(`${e.channel} requests retain the configured model`);if(!e.cheapModel)return n("no cheaper model configured");if(e.isFollowUp){let o=e.sessionIdleMs??0,r=e.cacheTtlMs??m;if(o<r)return n(`follow-up on a warm cache (idle ${Math.round(o/1e3)}s) \u2014 swapping would cost more than it saves`)}let t;try{t=await l(d,u(e),c,{incumbent:{needsFlagship:1},features:{agent:e.agent,channel:e.channel??"unknown"}})}catch{return n("routing seat threw \u2014 keeping the flagship")}if(!t)return n("routing seat unavailable \u2014 keeping the flagship");let s=g(t.answers);if(t.mode!=="active")return n(`shadow \u2014 would ${s<(e.threshold??h)?"downgrade":"keep"} (${s.toFixed(2)})`,s);let a=e.threshold??h;return s>=a?n(`needs the flagship (${s.toFixed(2)})`,s):{model:e.cheapModel,downgraded:!0,needsFlagship:s,reason:`mechanical task (${s.toFixed(2)} below ${a}) \u2192 ${e.cheapModel}`}}export{F as a,M as b};
2
- //# sourceMappingURL=chunk-H2TWRZC2.js.map
1
+ import{v as l,w}from"./chunk-MHBUAU2B.js";import{a as i,f as p}from"./chunk-72SZI2UW.js";w();p();var d="task-tier";function u(e){return{task:f(e.message,2e3),agent:e.agent,channel:e.channel??null,continuesExistingSession:e.isFollowUp??!1,...e.toolsAvailable?{toolsAvailable:e.toolsAvailable}:{}}}var c={needsFlagship:i("This task needs the strongest available model to be done correctly.",{true:"Doing it well takes real reasoning: writing or reviewing code, diagnosing a failure, planning work across several steps, weighing a judgement, handling money, touching production or anything irreversible, following a long or ambiguous instruction, or work where being subtly wrong would not be noticed. Anything where a weaker model would produce something that LOOKS right belongs here.",false:"It is mechanical and its result is obvious on sight: acknowledging or confirming a message, restating or formatting something already written, a greeting, a status echo, reading one file and reporting what it says, a lookup with one right answer, a scheduled heartbeat with nothing to decide."})};function g(e){return e.needsFlagship.noul}function f(e,n){return e.length>n?`${e.slice(0,n)}\u2026`:e}var h=.2,m=60*60*1e3;function F(e,n){if(e==="claude-code"){let t=n?.cheapModels?.[e]??n?.cheapModel;return t&&/^(claude-|haiku$|sonnet$|opus$)/.test(t)?t:void 0}if(e==="codex-cli"){let t=n?.cheapModels?.[e];return t&&/^(gpt-|o\d)/.test(t)?t:void 0}}async function M(e){let n=(o,r=null)=>({downgraded:!1,needsFlagship:r,reason:o});if(e.channel==="voice"||e.channel==="desktop"||e.channel==="opencode")return n(`${e.channel} requests retain the configured model`);if(!e.cheapModel)return n("no cheaper model configured");if(e.isFollowUp){let o=e.sessionIdleMs??0,r=e.cacheTtlMs??m;if(o<r)return n(`follow-up on a warm cache (idle ${Math.round(o/1e3)}s) \u2014 swapping would cost more than it saves`)}let t;try{t=await l(d,u(e),c,{incumbent:{needsFlagship:1},features:{agent:e.agent,channel:e.channel??"unknown"}})}catch{return n("routing seat threw \u2014 keeping the flagship")}if(!t)return n("routing seat unavailable \u2014 keeping the flagship");let s=g(t.answers);if(t.mode!=="active")return n(`shadow \u2014 would ${s<(e.threshold??h)?"downgrade":"keep"} (${s.toFixed(2)})`,s);let a=e.threshold??h;return s>=a?n(`needs the flagship (${s.toFixed(2)})`,s):{model:e.cheapModel,downgraded:!0,needsFlagship:s,reason:`mechanical task (${s.toFixed(2)} below ${a}) \u2192 ${e.cheapModel}`}}export{F as a,M as b};
2
+ //# sourceMappingURL=chunk-7NF45XCM.js.map
@@ -1,4 +1,4 @@
1
- import{A as rs,C as is,D as Co,J as jo,K as No,T as os,U as as,W as Lo,a as lo,b as Qn,f as Zn,g as uo,h as ho,j as go,l as wo,m as bo,n as ko,o as vo,p as So,q as $o,r as xo,s as Io,t as To,u as bt,w as ss,x as Ao,y as Je,z as Ro}from"./chunk-YE2BUU3Z.js";import{c as oo,f as ao,g as co}from"./chunk-QP6XNTBB.js";import{a as Do}from"./chunk-LQRBGQIR.js";import{a as po}from"./chunk-ZVP6GB4G.js";import{l as mo,m as fo,n as ts,o as ns,p as yo,q as Ve}from"./chunk-S7CVSKOX.js";import{o as es}from"./chunk-WDQ3BPFS.js";import{b as Eo,c as Mo,d as _o,e as Po,f as Oo}from"./chunk-L53FTKEP.js";import{A as Qi,B as Zi,C as eo,D as to,F as no,O as so,a as li,b as di,c as Bn,d as hi,e as fi,f as yi,g as Be,i as Vn,j as Jn,k as $i,r as xi,s as Ai,t as Ci,u as J,w as Ei,x as ee,y as qi,z as Yi}from"./chunk-YEV6W34S.js";import{a as Ii,h as _i,i as Pi,k as Vi,l as Ji,m as Xi,o as Ki}from"./chunk-U67EG5IF.js";import{a as wi,b as bi,c as ki,d as Wn,e as vi,f as Si}from"./chunk-N6EWZGIX.js";import{b as Fi,c as Gi,d as qn,f as ft,g as Hi,h as Bi,i as Wi,j as We,k as yt}from"./chunk-WP6KLXTP.js";import{a as zn,b as Ti}from"./chunk-DP7RTNDM.js";import{A as ro,B as wt,C as io,h as ni,n as si,o as Un}from"./chunk-PSDCRZZM.js";import{b as Zr}from"./chunk-SFQUP3BP.js";import{b as q,d as Ri,f as Xn,g as mt,i as te,j as Ui,k as ce,l as le,m as zi,s as Yn}from"./chunk-V7XZN3MQ.js";import{a as Oi,b as Kn,c as Di,d as ji,e as Ni,i as Li}from"./chunk-76Z4VHDX.js";import{b as Mi}from"./chunk-W4YR2RO2.js";import{d as gi,e as pi,j as mi}from"./chunk-DWADWDMU.js";import{b as ui}from"./chunk-2GIDVZ4H.js";import{d as ri,e as hu,m as oi,n as mu,o as ai,t as ci,v as Ie,w as pt}from"./chunk-JQR3NTHI.js";import{a as fe,b as He,f as Hn}from"./chunk-72SZI2UW.js";import{a as Fn,b as uu}from"./chunk-FCPTN6NF.js";import{a as gt,b as du}from"./chunk-7I7IEX4S.js";import{a as ei,d as ti}from"./chunk-VDMYBPYB.js";import{e as me}from"./chunk-DSYKYZMT.js";import{h as gu,m as Gn,n as ii,p as pu}from"./chunk-SRCXUZM2.js";import{d as xe}from"./chunk-QIJLFPWE.js";import{existsSync as fu,readFileSync as yu}from"fs";var Uo=["answer","narration","line"];function Fo(i){return i==="/voice/queue"||i.startsWith("/voice/queue/")}async function Go(i,e,t,n,s){if(n==="/voice/queue"){if(t==="GET")return{status:200,body:i.view()};if(t!=="POST")return{status:405,body:{error:"GET or POST"}};let l=String(s.text??"").trim(),c=String(s.agentId??s.agent??""),d=String(s.kind??"line");if(!l||!c||!Uo.includes(d))return{status:400,body:{error:`Required: text and agentId; kind is ${Uo.join(" | ")}`}};if(l.length>5e3)return{status:413,body:{error:"text is over 5000 characters"}};let u=e(c);if(!u)return{status:404,body:{error:`Unknown agent: ${c}`}};let{item:h,done:k}=i.enqueue({voice:u,text:l,agentId:c,kind:d});return s.wait!==!0?{status:202,body:{item:h}}:{status:200,body:{item:h,played:await k}}}if(t==="POST"&&n==="/voice/queue/pause")return i.pause(),{status:200,body:i.view()};if(t==="POST"&&n==="/voice/queue/resume")return i.resume(),{status:200,body:i.view()};let[,,,r,o,a]=n.split("/");if(t!=="POST"||!r||a!==void 0)return{status:404,body:{error:"Not found"}};switch(o){case"skip":return i.skip(r)?{status:200,body:i.view()}:cs(r);case"front":return i.front(r)?{status:200,body:i.view()}:cs(r);case"replay":{let l=i.replay(r);return l?{status:202,body:{item:l}}:cs(r)}default:return{status:404,body:{error:"Not found"}}}}function Ho(i){let e=n=>`${n.agentId??"someone"} (${n.kind}): "${n.text.length>80?`${n.text.slice(0,79)}\u2026`:n.text}" [${n.id}]`;return[i.playing?`Speaking: ${e(i.playing)}`:i.paused?"Paused: the listener is speaking; the queue plays on after.":"Nothing is speaking.",...i.waiting.map((n,s)=>`${s+1}. waiting: ${e(n)}`)].join(`
1
+ import{A as rs,C as is,D as Co,J as jo,K as No,T as os,U as as,W as Lo,a as lo,b as Qn,f as Zn,g as uo,h as ho,j as go,l as wo,m as bo,n as ko,o as vo,p as So,q as $o,r as xo,s as Io,t as To,u as bt,w as ss,x as Ao,y as Je,z as Ro}from"./chunk-WCNKTV6G.js";import{c as oo,f as ao,g as co}from"./chunk-NKSCUCVZ.js";import{a as Do}from"./chunk-LQRBGQIR.js";import{a as po}from"./chunk-ZVP6GB4G.js";import{l as mo,m as fo,n as ts,o as ns,p as yo,q as Ve}from"./chunk-S7CVSKOX.js";import{o as es}from"./chunk-B5UA3X6E.js";import{b as Eo,c as Mo,d as _o,e as Po,f as Oo}from"./chunk-L53FTKEP.js";import{A as Qi,B as Zi,C as eo,D as to,F as no,O as so,a as li,b as di,c as Bn,d as hi,e as fi,f as yi,g as Be,i as Vn,j as Jn,k as $i,r as xi,s as Ai,t as Ci,u as J,w as Ei,x as ee,y as qi,z as Yi}from"./chunk-64UYAWAK.js";import{a as Ii,h as _i,i as Pi,k as Vi,l as Ji,m as Xi,o as Ki}from"./chunk-AWRRBNWQ.js";import{a as wi,b as bi,c as ki,d as Wn,e as vi,f as Si}from"./chunk-N6EWZGIX.js";import{b as Fi,c as Gi,d as qn,f as ft,g as Hi,h as Bi,i as Wi,j as We,k as yt}from"./chunk-WP6KLXTP.js";import{a as zn,b as Ti}from"./chunk-DP7RTNDM.js";import{A as ro,B as wt,C as io,h as ni,n as si,o as Un}from"./chunk-E57WKMRR.js";import{b as Zr}from"./chunk-SFQUP3BP.js";import{b as q,d as Ri,f as Xn,g as mt,i as te,j as Ui,k as ce,l as le,m as zi,s as Yn}from"./chunk-XOUIZBAQ.js";import{a as Oi,b as Kn,c as Di,d as ji,e as Ni,i as Li}from"./chunk-76Z4VHDX.js";import{b as Mi}from"./chunk-W4YR2RO2.js";import{d as gi,e as pi,j as mi}from"./chunk-DWADWDMU.js";import{b as ui}from"./chunk-2GIDVZ4H.js";import{d as ri,e as hu,m as oi,n as mu,o as ai,t as ci,v as Ie,w as pt}from"./chunk-MHBUAU2B.js";import{a as fe,b as He,f as Hn}from"./chunk-72SZI2UW.js";import{a as Fn,b as uu}from"./chunk-FCPTN6NF.js";import{a as gt,b as du}from"./chunk-7I7IEX4S.js";import{a as ei,d as ti}from"./chunk-VDMYBPYB.js";import{e as me}from"./chunk-DSYKYZMT.js";import{h as gu,m as Gn,n as ii,p as pu}from"./chunk-3IUU4YFI.js";import{d as xe}from"./chunk-QIJLFPWE.js";import{existsSync as fu,readFileSync as yu}from"fs";var Uo=["answer","narration","line"];function Fo(i){return i==="/voice/queue"||i.startsWith("/voice/queue/")}async function Go(i,e,t,n,s){if(n==="/voice/queue"){if(t==="GET")return{status:200,body:i.view()};if(t!=="POST")return{status:405,body:{error:"GET or POST"}};let l=String(s.text??"").trim(),c=String(s.agentId??s.agent??""),d=String(s.kind??"line");if(!l||!c||!Uo.includes(d))return{status:400,body:{error:`Required: text and agentId; kind is ${Uo.join(" | ")}`}};if(l.length>5e3)return{status:413,body:{error:"text is over 5000 characters"}};let u=e(c);if(!u)return{status:404,body:{error:`Unknown agent: ${c}`}};let{item:h,done:k}=i.enqueue({voice:u,text:l,agentId:c,kind:d});return s.wait!==!0?{status:202,body:{item:h}}:{status:200,body:{item:h,played:await k}}}if(t==="POST"&&n==="/voice/queue/pause")return i.pause(),{status:200,body:i.view()};if(t==="POST"&&n==="/voice/queue/resume")return i.resume(),{status:200,body:i.view()};let[,,,r,o,a]=n.split("/");if(t!=="POST"||!r||a!==void 0)return{status:404,body:{error:"Not found"}};switch(o){case"skip":return i.skip(r)?{status:200,body:i.view()}:cs(r);case"front":return i.front(r)?{status:200,body:i.view()}:cs(r);case"replay":{let l=i.replay(r);return l?{status:202,body:{item:l}}:cs(r)}default:return{status:404,body:{error:"Not found"}}}}function Ho(i){let e=n=>`${n.agentId??"someone"} (${n.kind}): "${n.text.length>80?`${n.text.slice(0,79)}\u2026`:n.text}" [${n.id}]`;return[i.playing?`Speaking: ${e(i.playing)}`:i.paused?"Paused: the listener is speaking; the queue plays on after.":"Nothing is speaking.",...i.waiting.map((n,s)=>`${s+1}. waiting: ${e(n)}`)].join(`
2
2
  `)}var cs=i=>({status:404,body:{error:`No such line in the queue: ${i}`}});import{resolve as wu}from"path";var bu={name:"agentx",version:"0.1.0"},ku="2024-11-05",vu={tools:{},elicitation:{form:{}}},Su=0;async function Bo(i,e){let t=++Su;return ye({jsonrpc:"2.0",id:`elicit-${t}`,method:"elicitation/create",params:{mode:"form",message:i,requestedSchema:e}}),new Promise(n=>{ze.set(`elicit-${t}`,s=>{s?.action==="accept"&&s.content?n(s.content):n(null)}),setTimeout(()=>{ze.has(`elicit-${t}`)&&(ze.delete(`elicit-${t}`),n(null))},6e4)})}var ze=new Map,$u="http://localhost:19900",ls;function xu(){if(process.env.AGENTX_DAEMON_URL)return process.env.AGENTX_DAEMON_URL;for(let i of["agentx.json",".agentx/config.json"])try{let e=wu(process.cwd(),i);if(!fu(e))continue;let t=JSON.parse(yu(e,"utf-8"))?.node?.bind;if(typeof t!="string"||!t.includes(":"))continue;{let n=t.lastIndexOf(":"),s=t.slice(0,n),r=t.slice(n+1),o=!s||s==="0.0.0.0"||s==="::"||s==="*"?"127.0.0.1":s;if(r)return`http://${o}:${r}`}}catch{}return $u}function W(){return ls===void 0&&(ls=xu()),ls}var Iu=/\x1B\[[0-9;]*[A-Za-z]/g;function Te(i){return i.replace(Iu,"")}var Tu=[{name:"agentx_generate",description:"Generate code, components, pages, APIs, documents, tests, workflows, schemas, emails, diagrams, and more using AI. Understands the project's tech stack, schemas, and skills automatically.",inputSchema:{type:"object",properties:{task:{type:"string",description:"Describe what to generate (e.g., 'a responsive pricing card', 'REST API for users', 'GitHub Actions CI pipeline')"},type:{type:"string",description:"Output type: component, page, api, website, document, script, config, skill, media, report, test, workflow, schema, email, diagram, auto",default:"auto"},output_dir:{type:"string",description:"Optional output directory (relative to project root)"},cwd:{type:"string",description:"Project working directory (defaults to current directory)"}},required:["task"]}},{name:"agentx_inspect",description:"Analyze a project and return its tech stack, frameworks, databases, schemas, installed skills, and dependencies. Use this to understand a project before generating code.",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Project working directory (defaults to current directory)"}}}},{name:"agentx_skill_match",description:"Find installed skills that are relevant to a given task description. Returns matched skills with relevance scores.",inputSchema:{type:"object",properties:{task:{type:"string",description:"The task to match skills against"},cwd:{type:"string",description:"Project working directory"}},required:["task"]}},{name:"agentx_detect_output_type",description:"Auto-detect the best output type for a given task description based on keyword analysis.",inputSchema:{type:"object",properties:{task:{type:"string",description:"The task description to analyze"}},required:["task"]}},{name:"agentx_channel_reply",description:"Reply to a channel (GitLab issue/MR comment, GitHub issue/PR comment, Telegram/WhatsApp message). PREFER THIS over raw curl/glab/HTTP \u2014 it auto-applies agent identity from agentMappings, the cascade-prevention marker, intent-ledger audit, and a 60s body-hash dedupe so an accidental retry within the window is a no-op. Returns the posted message id. For agent-to-agent delegation use agentx_send_agent. For arbitrary outbound sends use agentx_send.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Channel name. gitlab | github | telegram | whatsapp | discord | slack"},chatId:{type:"string",description:"Stable chat id you received in this task's context. GitLab: 'org/repo:issue:123' or 'org/repo:merge_request:123'. GitHub: 'org/repo:issue:123' or 'org/repo:pull:123'. Telegram: numeric. WhatsApp: '+phone@s.whatsapp.net'."},text:{type:"string",description:"Reply body. Markdown for gitlab/github/discord; plain for sms/whatsapp."},agentId:{type:"string",description:"Optional posting identity. Defaults to channel-adapter resolution from agentMappings."},accountId:{type:"string",description:"Multi-account adapters (telegram) need this when the chat is reachable from more than one bot."},replyTo:{type:"string",description:"Optional reply-to message id for threaded channels."},idempotencyKey:{type:"string",description:"Optional explicit dedupe key. When omitted, a body hash is used. Use a stable key for 'overwrite my last status update' patterns."}},required:["channel","chatId","text"]}},{name:"agentx_channel_label",description:"Add and/or remove labels on a GitLab issue or merge_request through the canonical adapter (per-agent token, ledger). Use this instead of curl when changing labels on the entity that triggered the current task.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Currently 'gitlab'.",default:"gitlab"},project:{type:"string",description:"GitLab project path \u2014 'org/repo'."},kind:{type:"string",description:"'issue' or 'merge_request'."},iid:{type:"string",description:"Numeric iid as a string."},add:{type:"array",items:{type:"string"},description:"Labels to add."},remove:{type:"array",items:{type:"string"},description:"Labels to remove."},agentId:{type:"string",description:"Optional posting identity."}},required:["project","kind","iid"]}},{name:"agentx_send",description:"Low-level outbound send when you ALREADY have a channel-native chatId (Telegram numeric chat id, GitLab 'group/project:issue:123', WhatsApp '+phone@s.whatsapp.net'). For sending to another agent by name, use agentx_send_agent instead. For sending to a human contact by name, use agentx_send_contact instead.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Target channel: telegram, whatsapp, gitlab, discord"},chatId:{type:"string",description:'Chat ID. Telegram: numeric ("-1001234567890"). GitLab: "group/project:issue:123". WhatsApp: "+phone@s.whatsapp.net".'},text:{type:"string",description:"Message text to send"},agentId:{type:"string",description:"Agent ID to send as (determines bot account on Telegram, GitLab token, etc.)"}},required:["channel","chatId","text"]}},{name:"agentx_send_agent",description:"Send a message to ANOTHER AGENT by exact agentId \u2014 uses the AgentX A2A mesh (or local registry when the agent lives on this daemon). This is the deterministic path for agent-to-agent communication; it never falls through to a contact lookup, so an unknown agentId returns 404 with the list of known agents instead of silently sending to a similarly-named human. Use this when the target is a registered agent.",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Exact agentId of the target agent (e.g. 'peer', 'atlas'). Must match an agent in this daemon's registry or in a healthy mesh peer's directory."},text:{type:"string",description:"Message to send to the target agent"},senderAgentId:{type:"string",description:"Optional. The agentId on whose behalf this call is being made. Recorded in route_traces and (with A2A protocolVersion >= 2) validated by the receiving daemon."}},required:["agentId","text"]}},{name:"agentx_recent",description:"Read the most recent messages from a chat across ALL agents that have sessions for it. Returns inbound + each agent's replies in chronological order, so you can see what's actually been said in a Telegram chat / GitLab thread / WhatsApp DM regardless of which agent recorded it. Use this BEFORE speculating about what was sent \u2014 the cx/devops/marketing thread on 2026-04-29 about a Marketing/CX bot mixup would have been resolved in one call instead of three agents speculating. Bounded by sinceISO (default: last 24h) and limit (default: 30, max: 200).",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Channel name. Examples: telegram, whatsapp, gitlab, github, discord, cron, api, a2a."},chatId:{type:"string",description:'Channel-native chat id. Telegram: numeric (e.g. "1816212449" for a DM, "-1001234567890" for a group). GitLab: "group/project:issue:123". WhatsApp: "+phone@s.whatsapp.net".'},sinceISO:{type:"string",description:"Optional ISO timestamp lower bound. Defaults to 24h ago."},limit:{type:"number",description:"Optional cap on returned messages. Default 30, max 200."}},required:["channel","chatId"]}},{name:"agentx_send_contact",description:"Send a message to a HUMAN CONTACT by name. Resolves through .agentx/contacts.json (id \u2192 exact alias \u2192 fuzzy substring). Refuses fuzzy matches without confirmed:true so the agent must ask the user to disambiguate before sending. Refuses when the name also matches a registered agent (use agentx_send_agent for those). Use this when the target is a person, not a bot.",inputSchema:{type:"object",properties:{contactName:{type:"string",description:"Free-form contact name. Tried as id first, then alias, then fuzzy substring."},text:{type:"string",description:"Message to send to the contact"},channel:{type:"string",description:"Optional explicit channel (telegram | whatsapp | gitlab | discord). Defaults to the first channel configured for the contact."},confirmed:{type:"boolean",description:"Pass true ONLY after the user has confirmed a fuzzy match. Without it, fuzzy matches return 409 with the candidate so you can ask the user."},agentId:{type:"string",description:"Optional agent identity used for the outbound send (determines bot account / token)."}},required:["contactName","text"]}},{name:"agentx_task",description:"Send a task to a specific agent on the daemon. The agent processes it and returns a response. Use to delegate work to specialized agents.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID to send the task to"},message:{type:"string",description:"Task message for the agent"},senderAgentId:{type:"string",description:"Optional caller agent id. Defaults to AGENTX_AGENT_ID when the MCP server was launched by an AgentX runtime."},freshSession:{type:"boolean",description:"Start the target agent with a clean AgentX-side conversation. Defaults to true for agent-to-agent delegation."},chatId:{type:"string",description:"Optional stable chat/session id for this delegated task. Omit for a one-off isolated delegation."}},required:["agent","message"]}},{name:"agentx_agents",description:"List all agents registered on the daemon with their status (active tasks, total tasks, errors, tier).",inputSchema:{type:"object",properties:{}}},{name:"agentx_voice_queue",description:"See what this host is saying out loud and what waits to be said: every agent's spoken answers, narration, talks and lessons share one speaking queue. Use it before speaking at length, or when asked who is talking.",inputSchema:{type:"object",properties:{}}},{name:"agentx_health",description:"Get the daemon health status including node info, agents, crons, mesh peers, and uptime.",inputSchema:{type:"object",properties:{}}},{name:"agentx_attach_next",description:"Take the next message queued for the agent identity THIS session is attached to (attach mode). Returns the message plus who sent it and on which channel, or nothing when the inbox is empty. After calling this, just answer normally \u2014 your reply is captured automatically and sent back to the channel. Use when the user runs /inbox or asks you to check for waiting messages.",inputSchema:{type:"object",properties:{}}},{name:"agentx_attach_answer",description:"Explicitly answer the message currently claimed by this session (attach mode). Usually unnecessary \u2014 replying normally after agentx_attach_next is captured automatically. Use this only when your reply to the channel should differ from what you told the user in the terminal.",inputSchema:{type:"object",properties:{text:{type:"string",description:"The reply to send back to the channel, verbatim."}},required:["text"]}},{name:"agentx_crons",description:"List cron jobs and their health. Shows healthy, failing, disabled counts and per-job status with consecutive error counts.",inputSchema:{type:"object",properties:{}}},{name:"agentx_schedule",description:"Manage recurring routines (schedules) in plain English. Actions: list, create, pause, resume, delete. create and delete are REQUESTS: nothing takes effect until the operator approves (the operator is sent the parsed cron and next fire time). Tell the user it is pending approval. You can pause/resume/delete only routines you created, unless you are an admin agent. Example: {action:'create', when:'every monday at 10am', prompt:'Check the open invoices and summarise'}.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list","create","pause","resume","delete"],description:"What to do. Default: list."},id:{type:"string",description:"Schedule id. Required for pause/resume/delete; optional for create (auto-generated)."},when:{type:"string",description:"create: plain-English timing, e.g. 'every monday at 10am', 'weekdays at 6pm', 'every 15 minutes', '1st of every month at noon'."},prompt:{type:"string",description:"create: what the agent should do at each run."},agent:{type:"string",description:"create: agent that runs the routine. Default: you."},timezone:{type:"string",description:"create: IANA timezone. Default: the node's schedule default."},notify:{type:"string",description:"create: where results/failures go. 'here' (default: the current chat), 'none', or 'channel:chatId'."},mine:{type:"boolean",description:"list: only routines you created."},channel:{type:"string",description:"Current chat's channel, from your task context. Used as the default notify target when the runtime didn't provide it."},chatId:{type:"string",description:"Current chat id, from your task context."},accountId:{type:"string",description:"Optional bot account for multi-account channels."},callerAgentId:{type:"string",description:"Your agent id. Ignored when the AgentX runtime already identifies you (AGENTX_AGENT_ID)."}}}},{name:"agentx_approval",description:"Ask the operator for a yes/no decision by raising a decision card in their Approvals inbox, instead of asking in chat. Lead with your recommendation. Every card expires: say what should happen if nobody answers (if_silent). You get a message with the result when it is decided or expires. You cannot approve anything with this tool. Actions: create (default), status. Example: {title:'Publish the launch post draft', ask:'Publish the draft on Monday?', recommend:'Yes: it is reviewed and the date is agreed', if_silent:'discard', expires:'2d', source:'https://example.com/drafts/42'}.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","status"],description:"create (default) or status."},title:{type:"string",description:"create: what it is, in one line (max 120 characters)."},ask:{type:"string",description:"create: the yes/no question (max 300 characters)."},recommend:{type:"string",description:"create: your advice and why, in one line (max 300 characters)."},if_silent:{type:"string",enum:["discard","keep","pause","approve"],description:"create: what applies if nobody answers before it expires."},expires:{type:"string",description:"create: when the default applies. ISO date/time, or relative like '12h' or '3d'. Default: the node's setting (3 days)."},source:{type:"string",description:"create: link to the draft, PR or issue."},id:{type:"string",description:"status: the card id you got from create."},channel:{type:"string",description:"Current chat's channel, from your task context, so the result can mention it."},chatId:{type:"string",description:"Current chat id, from your task context."},callerAgentId:{type:"string",description:"Your agent id. Ignored when the AgentX runtime already identifies you (AGENTX_AGENT_ID)."}}}},{name:"agentx_debug",description:"Toggle debug mode on the daemon. Enable verbose logging for specific categories (webhook, agent, channel, cron, mesh, context, memory, all) or disable it.",inputSchema:{type:"object",properties:{action:{type:"string",description:'"on", "off", or "status"',default:"status"},categories:{type:"string",description:'Comma-separated categories to enable (e.g. "webhook,agent"). Only used with action=on.'}}}},{name:"agentx_wiki_query",description:"Query the agentx institutional wiki: a cross-agent knowledge base organized by article type (person, project, place, concept, event, decision, pattern). Use this BEFORE grep/memory-search when the question is about who / what happened / what we decided / how we do something. The query walks the catalog + wikilink graph and returns a synthesized answer with citations.",inputSchema:{type:"object",properties:{question:{type:"string",description:"The question to answer from the wiki, in natural language."},agent:{type:"string",description:"Which agent's wiki to query (default: first agent with a catalog). Each agent has its own wiki dir under .agentx/wiki/agents/<id>/"},wiki_dir:{type:"string",description:"Wiki root dir (default: <cwd>/.agentx/wiki)."},max_hops:{type:"number",description:"Wikilink hops from candidates (default 2, max 3).",default:2}},required:["question"]}},{name:"agentx_wiki_patch",description:"Edit a single wiki article via an LLM-applied instruction and write the result. Use this for targeted fixes, additions, or clarifications to an existing article when you already know what's wrong. For brand-new articles, use `agentx_wiki_interview` instead.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID whose wiki owns the article (required)."},title_or_path:{type:"string",description:"Article title (case-insensitive) or relative path like 'people/alex.md'."},instruction:{type:"string",description:"Plain-English edit instruction (e.g. 'Add a section on the KSA Supabase rollout'). The LLM makes the minimum edit that satisfies it."},model:{type:"string",description:"Claude model for the patch (default: sonnet).",default:"sonnet"},dry_run:{type:"boolean",description:"Preview the patched body without writing.",default:!1}},required:["agent","title_or_path","instruction"]}},{name:"agentx_wiki_interview",description:"Run a scripted wiki interview \u2014 synthesize ONE typed article from a list of Q&A answers, and save it. Non-interactive: caller supplies the answers upfront. Use for capturing tacit knowledge (person/project/decision/pattern/...) that never hit a channel. For editing an existing article, use `agentx_wiki_patch`.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID that will own the new article (required)."},topic:{type:"string",description:"What the article is about \u2014 e.g. 'Globex deployment procedure', 'Jane Doe', 'DemoSite KSA migration'."},type:{type:"string",description:"Article type: person | project | place | concept | event | decision | pattern"},answers:{type:"array",description:"Answers to the type-specific question bank (one per question, in order). Empty string = skip that question. Final entry is typically 'save'.",items:{type:"string"}},model:{type:"string",description:"Synthesis model (default: sonnet).",default:"sonnet"},commit:{type:"boolean",description:"Write the article (true) or just preview (false).",default:!0}},required:["agent","topic","type","answers"]}},{name:"agentx_graph_review",description:"Triage pending intent-graph classifications via the configured review agent. The review agent sees each pending classification, may call `wiki query` for institutional context, and decides approve/reject/skip. Structural changes (new org, new unit) gate here; leaf additions auto-approve without this step.",inputSchema:{type:"object",properties:{max:{type:"number",description:"Cap reviews this run (default 20).",default:20},dry_run:{type:"boolean",description:"Show decisions but don't apply approvals/rejections.",default:!1},agent:{type:"string",description:"Override the review agent (defaults to graph.reviewAgent or graph.draftAgent)."}}}}];async function Au(i,e){let t=e.cwd||process.cwd();switch(i){case"agentx_generate":{let n=e.task,s=e.type||"auto",r=e.output_dir,o=await wt({task:n,outputType:s,outputDir:r,cwd:t,overwrite:!0,dryRun:!1,context7:!0,interactive:!1,maxSteps:5}),a=[];return o.content&&a.push(o.content),o.files.written.length&&a.push(`
3
3
  Created ${o.files.written.length} file(s):
4
4
  ${o.files.written.map(l=>` - ${l}`).join(`
@@ -23,7 +23,7 @@ ${r.map(a=>`- **${a.skill.frontmatter.name}** (relevance: ${(a.relevance*100).to
23
23
  `)}]}}case"agentx_attach_answer":{let n=process.env.CLAUDE_CODE_SESSION_ID;if(!n)return{content:[{type:"text",text:"Not running inside a Claude Code session \u2014 attach mode is unavailable here."}]};let s=await fetch(`${W()}/attach/answer`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:n,text:String(e.text??"")})}),r=await s.json();if(!s.ok)return{content:[{type:"text",text:`Could not answer: ${r?.error??s.status}`}]};let o=r.pending>0?` ${r.pending} still queued.`:"";return{content:[{type:"text",text:`Sent to ${r.item?.channel}.${o}`}]}}case"agentx_crons":{let s=await(await fetch(`${W()}/crons/health`)).json(),r=`Healthy: ${s.healthy}, Failing: ${s.failing}, Disabled: ${s.disabled}, Missed: ${s.missed}`,o=(s.jobs||[]).map(a=>` ${a.id}: ${a.status}${a.consecutiveErrors?` (${a.consecutiveErrors} errors)`:""}${a.lastError?` \u2014 ${a.lastError.slice(0,100)}`:""}`).join(`
24
24
  `);return{content:[{type:"text",text:`${r}
25
25
 
26
- ${o}`}]}}case"agentx_schedule":{let{runScheduleTool:n,resolveScheduleCaller:s}=await import("./schedule-tool-TPJ6GR47.js");return{content:[{type:"text",text:await n(e,s(e),{notifyOperator:async(o,a)=>{let l=await fetch(`${W()}/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel:o.channel,chatId:o.chatId,accountId:o.accountId,text:a}),signal:AbortSignal.timeout(1e4)});if(!l.ok){let c=await l.json().catch(()=>({}));throw new Error(c?.error||`HTTP ${l.status}`)}}})}]}}case"agentx_approval":{let{runApprovalTool:n}=await import("./tool-SF3BCY55.js");return{content:[{type:"text",text:await n(e,{daemonUrl:W()})}]}}case"agentx_wiki_query":{let n=String(e.question||"").trim();if(!n)return{content:[{type:"text",text:"Error: `question` is required."}]};let{WikiHub:s}=await import("./wiki-WETANN3W.js"),{agenticQuery:r}=await import("./query-6IKL52WT.js"),{resolve:o}=await import("path"),a=e.wiki_dir||o(process.cwd(),".agentx/wiki"),l=new s(a,void 0,"graph"),c=e.agent||"";if(!c){let{existsSync:b}=await import("fs");for(let $ of l.listAgents()){let x=o(l.getAgentWiki($).baseDir,"_index.md");if(b(x)){c=$;break}}}if(!c)return{content:[{type:"text",text:"Error: no agent has a wiki catalog yet. Run `agentx wiki absorb` first."}]};let d=l.getAgentWiki(c),u=typeof e.max_hops=="number"?Math.min(3,Math.max(0,e.max_hops)):2,h=await r(n,d,c,{maxHops:u});if(h.status!=="ok")return{content:[{type:"text",text:`Query returned status "${h.status}"${h.error?`: ${h.error}`:""}`}]};let k=h.citations.map(b=>` - ${b.title} [${b.type||"?"}] (${b.path})`).join(`
26
+ ${o}`}]}}case"agentx_schedule":{let{runScheduleTool:n,resolveScheduleCaller:s}=await import("./schedule-tool-AKCVLCWK.js");return{content:[{type:"text",text:await n(e,s(e),{notifyOperator:async(o,a)=>{let l=await fetch(`${W()}/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel:o.channel,chatId:o.chatId,accountId:o.accountId,text:a}),signal:AbortSignal.timeout(1e4)});if(!l.ok){let c=await l.json().catch(()=>({}));throw new Error(c?.error||`HTTP ${l.status}`)}}})}]}}case"agentx_approval":{let{runApprovalTool:n}=await import("./tool-WW4YCMSP.js");return{content:[{type:"text",text:await n(e,{daemonUrl:W()})}]}}case"agentx_wiki_query":{let n=String(e.question||"").trim();if(!n)return{content:[{type:"text",text:"Error: `question` is required."}]};let{WikiHub:s}=await import("./wiki-IVJJQUKB.js"),{agenticQuery:r}=await import("./query-XCXR57IV.js"),{resolve:o}=await import("path"),a=e.wiki_dir||o(process.cwd(),".agentx/wiki"),l=new s(a,void 0,"graph"),c=e.agent||"";if(!c){let{existsSync:b}=await import("fs");for(let $ of l.listAgents()){let x=o(l.getAgentWiki($).baseDir,"_index.md");if(b(x)){c=$;break}}}if(!c)return{content:[{type:"text",text:"Error: no agent has a wiki catalog yet. Run `agentx wiki absorb` first."}]};let d=l.getAgentWiki(c),u=typeof e.max_hops=="number"?Math.min(3,Math.max(0,e.max_hops)):2,h=await r(n,d,c,{maxHops:u});if(h.status!=="ok")return{content:[{type:"text",text:`Query returned status "${h.status}"${h.error?`: ${h.error}`:""}`}]};let k=h.citations.map(b=>` - ${b.title} [${b.type||"?"}] (${b.path})`).join(`
27
27
  `),m=h.walked.length;return{content:[{type:"text",text:`${h.answer}
28
28
 
29
29
  Citations (${m} article${m===1?"":"s"} walked):
@@ -1104,4 +1104,4 @@ data: ${JSON.stringify(T)}
1104
1104
  `)}catch{}},A=setInterval(()=>{try{t.write(`: ping
1105
1105
 
1106
1106
  `)}catch{}},15e3);A.unref?.();try{for await(let C of this.mesh.sendTaskStream(p.peer,p.message,p.agent,{context:p.context}))I(C.event,C.data)}catch(C){I("error",{error:C?.message??String(C)})}finally{clearInterval(A);try{t.end()}catch{}}break}let w=p.context,S=typeof p.senderAgentId=="string"?p.senderAgentId:void 0;if(p.async===!0){let I=w?.channel,A=w?.chatId;if(!I||!A){this.json(t,400,{error:"async requires context.channel and context.chatId \u2014 there is no route back otherwise"});return}let C=`mesh-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;this.json(t,202,{accepted:!0,taskId:C,deliverTo:`${I}:${A}`,note:"result will be delivered to the originating chat when the peer finishes"});let T=p.peer,P=p.agent,O=this.mesh;(async()=>{let M=Date.now(),N;try{N=await O.sendTask(T,p.message,P,{context:w,senderAgentId:S}),this.log(`[mesh/task async ${C}] ${T}/${P??"default"} finished in ${Date.now()-M}ms`)}catch(L){N=`Delegation to ${T}/${P??"default"} failed: ${L?.message??L}`,this.log(`[mesh/task async ${C}] failed: ${L?.message??L}`)}try{await this.router.sendOutbound({channel:I,chatId:A,text:N,agentId:w?.agentId??S,accountId:w?.accountId})}catch(L){this.log(`[mesh/task async ${C}] delivery failed: ${L?.message??L}`)}})();break}let v=await this.mesh.sendTask(p.peer,p.message,p.agent,{context:w,senderAgentId:S});this.json(t,200,{response:v});break}case"POST /webrtc/signal/out":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let g=await U(e);if(!g.kind||!g.callId||!g.from||!g.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let f=await this.webrtc.handleOutgoing(g);this.json(t,f.ok?200:400,f);break}case"POST /webrtc/signal":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let g=await U(e);if(!g.kind||!g.callId||!g.from||!g.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let f=this.webrtc.handleIncoming(g);this.json(t,f.ok?200:400,f);break}case"POST /webrtc/bot/invite":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled (channels.webrtc.bot.enabled=false)"});return}let p=await U(e),g=p.callId,f=p.target,w=p.agentId||this.config.channels.webrtc?.bot.defaultAgentId;if(!g||!f||!w){this.json(t,400,{error:"Missing: callId, target, agentId (or defaultAgentId in config)"});return}let S=await this.botManager.invite({callId:g,target:f,agentId:w});this.json(t,S.ok?200:500,S);break}case"GET /webrtc/bots":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled"});return}this.json(t,200,{active:this.botManager.active()});break}case"GET /webrtc/history":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled"});return}this.json(t,200,{active:this.botManager.active(),history:this.botManager.history()});break}case"GET /webrtc/config":{let p=this.config.channels.webrtc;if(!p?.enabled){this.json(t,404,{error:"WebRTC signaling not enabled"});return}this.json(t,200,{localName:this.config.node.name,iceServers:[...p.stunServers.map(g=>({urls:g})),...p.turnServers],peers:this.mesh?.directory().map(g=>({name:g.peer,healthy:g.healthy}))||[]});break}case"GET /.well-known/agent-card.json":this.json(t,200,{name:this.config.node.name,description:`AgentX daemon node "${this.config.node.name}"`,url:`http://${this.config.node.bind}`,version:"1.0.0",capabilities:{streaming:!1,pushNotifications:!1,stateTransitionHistory:!1},skills:this.registry.list().map(p=>{let g=this.config.agents[p.id]||{},f=typeof g.description=="string"&&g.description.trim()||jy(g.systemPrompt)||`Agent "${p.name}" (${p.tier})`,w=Array.isArray(g.mentions)?g.mentions.slice(0,4):[];return{id:p.id,name:p.name,description:f,tags:[p.tier,...w]}}),channels:this.router.getChannelNames(),defaultInputModes:["text"],defaultOutputModes:["text"]});break;case"GET /wiki/agents":{let p=this.registry.getWikiHub();this.json(t,200,{nodeId:this.config.node.id,agents:p.summary()});break}case"GET /wiki/entries":{let p=this.registry.getWikiHub(),g=n.searchParams.get("agent")||void 0,f=n.searchParams.get("after")||void 0,w=g?p.getAgentEntries(g):p.getSharedStore().listEntries({after:f});this.json(t,200,{nodeId:this.config.node.id,count:w.length,entries:w.map(S=>({id:S.id,date:S.date,agentId:S.agentId,source:S.source,sourceContext:S.sourceContext,content:S.content}))});break}case"GET /wiki/articles":{let p=this.registry.getWikiHub(),g=n.searchParams.get("agent");if(!g){this.json(t,400,{error:"?agent= required"});break}let w=p.getAgentWiki(g).rebuildIndex();this.json(t,200,{nodeId:this.config.node.id,agentId:g,articles:w.articles});break}case"GET /wiki/article":{let p=this.registry.getWikiHub(),g=n.searchParams.get("agent"),f=n.searchParams.get("path");if(!g||!f){this.json(t,400,{error:"?agent= and ?path= required"});break}let S=p.getAgentWiki(g).readArticle(f);if(!S){this.json(t,404,{error:"Article not found"});break}this.json(t,200,{nodeId:this.config.node.id,agentId:g,path:S.path,title:S.meta.title,tags:S.meta.tags,owner:S.meta.owner,created:S.meta.created,lastUpdated:S.meta.lastUpdated,sources:S.meta.sources,content:S.content});break}case"GET /graph/schema":{let p=this.registry.getGraphStore();if(!p){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,schema:p.loadSchema()});break}case"GET /graph/nodes":{let p=this.registry.getGraphStore();if(!p){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,...p.loadNodes()});break}case"GET /graph/classifications":{let p=this.registry.getGraphStore();if(!p){this.json(t,404,{error:"graph disabled on this node"});break}let g=n.searchParams.get("status")||"approved",f=Math.max(1,Math.min(1e3,parseInt(n.searchParams.get("limit")||"200",10)||200)),w=p.listByStatus(g,f);this.json(t,200,{nodeId:this.config.node.id,status:g,count:w.length,classifications:w});break}default:this.json(t,404,{error:"Not found",endpoints:["GET /health","GET /agents","GET /crons","GET /routines \u2014 schedules + cron/hook workflows with staleness flags","GET /mesh","GET /wiki/agents","GET /wiki/entries[?agent=X&after=YYYY-MM-DD]","GET /wiki/articles?agent=X","GET /graph/schema","GET /graph/nodes","GET /graph/classifications[?status=approved|pending|rejected&limit=N]","POST /task { agent, message, context?, freshSession?: bool }","GET /agents/:id \u2014 resolved agent config (permission, tier, model, persistentProcess, toolUseRequired)","POST /agents/:id/selftest { message? } \u2014 canary probe; runs a fresh-session task and reports {ok, durationMs, tokens, billedModel}","GET /traces[?agentId=&channel=&chatId=&workflowRunId=&status=&since=&until=&limit=]","GET /traces/:taskId \u2014 full per-task execution trace (steps + tokens)","GET /api/processes \u2014 live persistent claude processes (JSON)","POST /api/processes/kill { agentId, channel, chatId, reason? }","GET /api/actions/builtin \u2014 list shipped built-in typed actions","POST /api/actions/builtin/:name \u2014 run a built-in with JSON body input","POST /mesh/task { peer, message }","POST /webhook/:agentId[/:source] \u2014 webhook callback","POST /reload \u2014 re-read agentx.json (hot-swaps crons)","GET /daemon/restart \u2014 in-flight count, service manager, pending restart","POST /daemon/restart \u2014 restart when idle { timeoutMinutes?, onTimeout? }","POST /daemon/restart/cancel","GET /.well-known/agent-card.json","GET /call \u2014 browser UI for P2P A/V calls (requires channels.webrtc.enabled)","GET /webrtc/config \u2014 ICE servers + peer directory for the call page","GET /webrtc/events?callId=&as= \u2014 SSE stream of signaling events","POST /webrtc/signal/out \u2014 browser-originated signal, forwarded to remote peer","POST /webrtc/signal \u2014 remote-peer-originated signal, fanned out to local browser","POST /webrtc/bot/invite { callId, target, agentId } \u2014 spawn a transcribing bot peer for a call","GET /webrtc/bots \u2014 active bot sessions"]})}}catch(r){this.json(t,500,{error:r.message})}}async handleOpenAICompat(e,t,n){let s=await U(e);await Ja(e,t,n,s,{execute:(r,o,a,l)=>this.registry.execute(r,o,a,l),agentIds:Object.keys(this.config.agents),cancel:(r,o,a,l)=>{let c=this.registry.list().find(d=>d.id===r)?.runningTasks.filter(d=>d.channel===o&&d.chatId===a)||[];for(let d of c)this.registry.cancelRunningTask(d.id,l)},log:r=>this.log(r)})}json(e,t,n){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(n,null,2))}resolveGitlabTokenForAgent(e){if(!e)return{token:this.config.channels.gitlab?.token,source:"global"};let t=(this.config.channels.gitlab?.agentMappings||[]).find(s=>s.agentId===e);if(t?.token)return{token:t.token,source:"agentMappings"};let n=ml(this.config,e,"gitlab-user","tokenEnv");return n.status==="ok"&&n.value?{token:n.value,source:`integrations(${n.envVar})`}:this.config.channels.gitlab?.token?{token:this.config.channels.gitlab.token,source:"global"}:{token:void 0,source:n.status}}resolveTodayUsage(){let e=Sc();if(e==="json")return this.registry.getTodayUsage();let t=vc(this.db);return e==="sqlite"||Object.keys(t.agents).length>0?t:this.registry.getTodayUsage()}installAgentMemorySurface(){let e=parseInt(this.config.node.bind.split(":")[1]||"18800",10);for(let t of this.registry.list()){let n=t.workspace;if(!(!n||!Ge(n)))try{let s=Y(n,".claude","skills");ou(s,{recursive:!0});let r=Y(s,wl);if(!Ge(r))Kr(r,qs(e)),this.log(` memory-skill: installed remember.md \u2192 ${t.id}`);else{let o=kl(ht(r,"utf-8"),e);o&&(Kr(r,o),this.log(` memory-skill: updated remember.md \u2192 ${t.id}`))}this.agentMemory.syncToWorkspace(t.id,n)}catch(s){this.log(` memory-skill: ${t.id} install failed \u2014 ${s?.message??s}`)}}}installAgentMcpConfig(){for(let[e,t]of Object.entries(this.config.agents)){let n=t.workspace;if(!n||!Ge(n))continue;let s=gi(t);try{switch(yl(n,s)){case"installed":this.log(` mcp: installed ${Object.keys(s).length} server(s) \u2192 ${e}`);break;case"updated":this.log(` mcp: updated .mcp.json (${Object.keys(s).length} server(s)) \u2192 ${e}`);break;case"removed":this.log(` mcp: removed managed .mcp.json (config now empty) \u2192 ${e}`);break;case"skipped-operator-owned":Object.keys(s).length>0&&this.log(` mcp: ${e} has operator-owned .mcp.json \u2014 skipping (delete file or marker to let agentx manage)`);break;case"noop":break}}catch(r){this.log(` mcp: ${e} install failed \u2014 ${r?.message??r}`)}}}workspaceFor(e){for(let t of this.registry.list())if(t.id===e)return t.workspace;return null}handleMemoryApi(e,t,n,s){return Qc(e,t,n,s,{mem:this.agentMemory,workspaceFor:r=>this.workspaceFor(r),runningTaskOwner:r=>this.registry.runningTaskOwner(r)})}async handleWorkflowEvent(e,t){if(!this.workflowDispatcher){this.json(t,503,{error:"workflow engine not enabled on this node"});return}let n;try{n=await Q(e)}catch(l){this.json(t,400,{error:"invalid JSON body",message:l.message});return}let s=n?.payload??n,r=s?.event,o=s?.entityRef;if(!r?.id||!o?.backend||!o?.id){this.json(t,400,{error:"missing event or entityRef"});return}let a=n?.kind;try{if(a==="trigger"&&s.trigger){let h=typeof n?.fromPeer=="string"?n.fromPeer:"unknown";this.log(`[workflows/mesh] received trigger from "${h}" source="${s.trigger.source}" chat="${s.trigger.chat??"*"}"`);let k=await this.workflowDispatcher.dispatch({trigger:s.trigger,entityRef:o,event:r,fromRemote:{peer:h}});this.log(`[workflows/mesh] dispatched broadcast: matched=${k.claimed.length} ${k.claimed.length?`(${k.claimed.map(m=>m.id).join(", ")})`:"[none \u2014 no workflow with mesh.allowRemote matched]"}`),this.json(t,202,{ok:!0,mode:"trigger-broadcast",matched:k.claimed.map(m=>m.id)});return}let d=(s.workflowId?this.workflowStore?.get(s.workflowId):null)?.nodes.find(h=>h.type.startsWith("trigger."))?.config??{},u={source:String(d.source??"hook"),project:d.filter?.project,repo:d.filter?.repo,chat:d.filter?.chat,labels:d.filter?.labels};await this.workflowDispatcher.dispatch({trigger:u,entityRef:o,event:r}),this.json(t,202,{ok:!0})}catch(l){this.log(`[workflows] /workflow/event failed: ${l.message}`),this.json(t,500,{error:l.message})}}async handleChannelSend(e,t){let n;try{n=await Q(e)}catch(l){this.json(t,400,{error:"invalid JSON body",message:l.message});return}let s=String(n?.channel??""),r=String(n?.chatId??""),o=String(n?.text??"");if(!s||!r||!o){this.json(t,400,{error:"channel, chatId, and text are required"});return}if(!this.router.getChannel(s)){this.json(t,404,{error:`channel "${s}" not hosted on this node`});return}try{let l=await this.router.sendOutbound({channel:s,chatId:r,text:o,accountId:typeof n.accountId=="string"?n.accountId:void 0,parseMode:typeof n.parseMode=="string"?n.parseMode:void 0,replyTo:typeof n.replyTo=="string"?n.replyTo:void 0});this.json(t,200,{ok:!0,messageId:l??null})}catch(l){this.log(`[mesh] /channel/send "${s}" failed: ${l.message}`),this.json(t,500,{error:l.message})}}async handleChannelChats(e,t,n={}){let s=new Set,r=[],o=[],a=(c,d)=>{let u=0;for(let h of c)!h.id||s.has(h.id)||(s.add(h.id),r.push({...h,source:d}),u++);u>0&&o.push(`${d}:${u}`)},l=this.router.getChannel(t);if(l?.listKnownChats)try{a(l.listKnownChats(),"local")}catch{}else if(l?.listChats)try{a(l.listChats().map(c=>({id:c.jid,name:c.name,kind:c.isGroup?"group":"dm"})),"local")}catch{}if(!n.localOnly&&this.mesh){let c=this.mesh.directory().filter(d=>d.healthy&&d.channels?.includes(t));await Promise.allSettled(c.map(async d=>{try{let u=await fetch(`${d.peerUrl}/channels/${encodeURIComponent(t)}/chats?local=1`,{headers:this.mesh.authHeaders(d.peer),signal:AbortSignal.timeout(5e3)});if(!u.ok)return;let h=await u.json();Array.isArray(h.chats)&&a(h.chats.map(k=>({id:k.id,name:k.name,kind:k.kind??"dm",accountId:k.accountId})),`mesh:${d.peer}`)}catch{}}))}this.json(e,200,{channel:t,source:o.join(", ")||"none",chats:r})}async handleWorkflowManualRun(e,t,n){if(!this.workflowDispatcher||!this.workflowStore){this.json(t,503,{error:"workflow engine not enabled on this node"});return}let s=this.workflowStore.get(n);if(!s){this.json(t,404,{error:`unknown workflow "${n}"`});return}let r=s.nodes.find(m=>m.type.startsWith("trigger."));if(!r){this.json(t,400,{error:`workflow "${n}" has no trigger node`});return}let o;try{o=await Q(e)}catch{o={}}let a=!!o?.force,l=o?.payload||{};if(r.type!=="trigger.manual"&&!a){this.json(t,409,{error:`workflow "${n}" trigger is "${r.type}"`,hint:'pass { "force": true } to fire anyway with a synthesized event (for testing)'});return}let c=r.config??{},d=a?String(c.source??"manual"):"manual",u=String(l.entityId||l.chatId||`manual-${Date.now().toString(36)}`),h={backend:a&&c.source?"channel":"manual",id:u},k=`manual:${n}:${u}:${Date.now()}`;try{let y=(await this.workflowDispatcher.dispatch({trigger:a?{source:d,project:c.filter?.project,repo:c.filter?.repo,chat:c.filter?.chat,labels:c.filter?.labels}:{source:"manual"},entityRef:h,event:{id:k,payload:l}})).runs[0]?.id;this.json(t,y?200:202,{ok:!0,runId:y,entityRef:h,source:d,force:a})}catch(m){this.log(`[workflows] manual run "${n}" failed: ${m.message}`),this.json(t,500,{error:m.message})}}},qr=Yr;xe(qr,"MESH_PROTECTED_PATHS",new Set(["/task","/ask","/mesh/task","/mesh/inbox/send","/workflow/event","/workflow/transition","/channel/send","/webrtc/signal","/gitlab/react","/gitlab/send-note","/gitlab/log-time","/github/send-comment"]));function jy(i){if(typeof i!="string")return"";let e=i.trim();if(!e)return"";let t=e.match(/^[^.!?\n]+[.!?]?/),n=(t?t[0]:e).trim();return n.length>140?n.slice(0,137)+"\u2026":n}function Q(i){return new Promise((e,t)=>{let n="";i.setEncoding("utf8"),i.on("data",s=>{n+=s}),i.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(s){t(s)}}),i.on("error",t)})}function au(i){let e=i;return e=e.replace(/```[\s\S]*?```/g,". "),e=e.replace(/`[^`]*`/g,""),e=e.replace(/\*\*(.*?)\*\*/g,"$1"),e=e.replace(/__(.*?)__/g,"$1"),e=e.replace(/\*([^*]+)\*/g,"$1"),e=e.replace(/_([^_]+)_/g,"$1"),e=e.replace(/~~(.*?)~~/g,"$1"),e=e.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),e=e.replace(/!\[([^\]]*)\]\([^)]+\)/g,"image$1 "),e=e.replace(/^#{1,6}\s+/gm,""),e=e.replace(/^[\s]*[-*+]\s+/gm,". "),e=e.replace(/^[\s]*\d+\.\s+/gm,". "),e=e.replace(/^[-=_]{3,}$/gm,""),e=e.replace(/^>\s*/gm,""),e=e.replace(/https?:\/\/\S+/g,"link"),e=e.replace(/\/\w+(\/\w+)+/g,t=>t.split("/").filter(Boolean).join(" slash ")),e=e.replace(/&/g," and "),e=e.replace(/@/g," at "),e=e.replace(/=>/g," returns "),e=e.replace(/->/g," to "),e=e.replace(/\|/g," or "),e=e.replace(/\be\.g\./gi,"for example"),e=e.replace(/\bi\.e\./gi,"that is"),e=e.replace(/\betc\./gi,"etcetera"),e=e.replace(/\bvs\.?\b/gi,"versus"),e=e.replace(/\n{2,}/g,". "),e=e.replace(/\n/g," "),e=e.replace(/\s+/g," "),e=e.replace(/\.\s*\./g,"."),e=e.replace(/\s+([.,!?])/g,"$1"),e=e.trim().replace(/^[.,:;]+\s*/,""),e.length>800&&(e=e.slice(0,800).replace(/\s+\S*$/,"")+"..."),e}function Ny(i,e){let t=["model","workspace","tier","permissionMode","mcpServers"],n=new Set,s=new Set([...Object.keys(i),...Object.keys(e)]);for(let r of s){let o=i[r],a=e[r];if(!o||!a){n.add("add/remove");continue}for(let l of t)JSON.stringify(o[l])!==JSON.stringify(a[l])&&n.add(`${r}.${l}`)}return Array.from(n).slice(0,6)}async function U(i){return new Promise((e,t)=>{let n="";i.on("data",s=>n+=s.toString()),i.on("end",()=>{try{e(n?JSON.parse(n):{})}catch{e({})}}),i.on("error",t)})}du();function ZT(i){typeof i=="string"&&(gt.error(i),process.exit(1)),i instanceof Error&&(gt.error(i.message),process.exit(1)),gt.error("Something went wrong. Please try again."),process.exit(1)}import Ln from"path";import cu from"fs-extra";import{fileURLToPath as Ly}from"url";function rA(){let i=[];try{let e=Ln.dirname(Ly(import.meta.url));e&&(i.push(Ln.resolve(e,"..","package.json")),i.push(Ln.resolve(e,"package.json")))}catch{}i.push(Ln.resolve(process.cwd(),"package.json"));for(let e of i)try{if(cu.existsSync(e)){let t=cu.readJSONSync(e);if(t&&t.name)return t}}catch{}return{name:"agentix-cli",version:"0.0.0"}}export{Ky as a,ds as b,we as c,Xe as d,Qe as e,ve as f,Rt as g,ac as h,wg as i,bg as j,uc as k,_e as l,Pe as m,ue as n,iv as o,bc as p,Bs as q,Zv as r,eS as s,tS as t,ol as u,Rp as v,oS as w,aS as x,Qt as y,st as z,Dl as A,Am as B,k0 as C,at as D,sn as E,pr as F,mr as G,cf as H,ge as I,ln as J,wr as K,br as L,$e as M,kr as N,un as O,gd as P,pn as Q,lt as R,wn as S,kn as T,kd as U,Ar as V,ae as W,re as X,Rd as Y,Cd as Z,Ed as _,Md as $,xn as aa,$n as ba,On as ca,Yd as da,Jr as ea,Zd as fa,$y as ga,Hx as ha,qr as ia,ZT as ja,rA as ka};
1107
- //# sourceMappingURL=chunk-NTG5ZXRI.js.map
1107
+ //# sourceMappingURL=chunk-7PK32QT5.js.map