agentix-cli 0.114.0 → 0.114.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 (40) hide show
  1. package/dist/{agent-5F4EKGQN.js → agent-NGCPRTBH.js} +2 -2
  2. package/dist/{board-dashboard-GGW5ZZLT.js → board-dashboard-7B2B564A.js} +244 -244
  3. package/dist/{board-dashboard-GGW5ZZLT.js.map → board-dashboard-7B2B564A.js.map} +1 -1
  4. package/dist/{chunk-O2RVUM2B.js → chunk-CSLVHAYV.js} +2 -2
  5. package/dist/{chunk-QQIWLN3H.js → chunk-DOQ6Y7GZ.js} +5 -5
  6. package/dist/chunk-DOQ6Y7GZ.js.map +1 -0
  7. package/dist/{chunk-4COYYJJY.js → chunk-EVB23EHN.js} +2 -2
  8. package/dist/chunk-JVSTKXMI.js +6 -0
  9. package/dist/chunk-JVSTKXMI.js.map +1 -0
  10. package/dist/{chunk-XTO4GRGN.js → chunk-QBWJGDKE.js} +3 -3
  11. package/dist/{chunk-XX7NXI3Y.js → chunk-TZIPWZY6.js} +2 -2
  12. package/dist/{chunk-HPY54DU6.js → chunk-UMFFIUU6.js} +2 -2
  13. package/dist/{chunk-YU5NDKPA.js → chunk-UZB5UO35.js} +2 -2
  14. package/dist/{chunk-VQM77L54.js → chunk-Z6OPM7EH.js} +2 -2
  15. package/dist/{chunk-6WNQY6K2.js → chunk-ZXQYOSHP.js} +2 -2
  16. package/dist/cli.js +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/{program-IEMICVO3.js → program-4IMJEMDM.js} +7 -7
  19. package/dist/{promote-S7SKOKX2.js → promote-4VTXBVUC.js} +2 -2
  20. package/dist/{query-GOBQ3GL5.js → query-B32UDQJS.js} +2 -2
  21. package/dist/{registry-HUJEORRW.js → registry-GY4X2GZX.js} +2 -2
  22. package/dist/{wiki-FZHSX4K3.js → wiki-LVYHDK2R.js} +2 -2
  23. package/package.json +1 -1
  24. package/dist/chunk-ILGLEA3I.js +0 -6
  25. package/dist/chunk-ILGLEA3I.js.map +0 -1
  26. package/dist/chunk-QQIWLN3H.js.map +0 -1
  27. /package/dist/{agent-5F4EKGQN.js.map → agent-NGCPRTBH.js.map} +0 -0
  28. /package/dist/{chunk-O2RVUM2B.js.map → chunk-CSLVHAYV.js.map} +0 -0
  29. /package/dist/{chunk-4COYYJJY.js.map → chunk-EVB23EHN.js.map} +0 -0
  30. /package/dist/{chunk-XTO4GRGN.js.map → chunk-QBWJGDKE.js.map} +0 -0
  31. /package/dist/{chunk-XX7NXI3Y.js.map → chunk-TZIPWZY6.js.map} +0 -0
  32. /package/dist/{chunk-HPY54DU6.js.map → chunk-UMFFIUU6.js.map} +0 -0
  33. /package/dist/{chunk-YU5NDKPA.js.map → chunk-UZB5UO35.js.map} +0 -0
  34. /package/dist/{chunk-VQM77L54.js.map → chunk-Z6OPM7EH.js.map} +0 -0
  35. /package/dist/{chunk-6WNQY6K2.js.map → chunk-ZXQYOSHP.js.map} +0 -0
  36. /package/dist/{program-IEMICVO3.js.map → program-4IMJEMDM.js.map} +0 -0
  37. /package/dist/{promote-S7SKOKX2.js.map → promote-4VTXBVUC.js.map} +0 -0
  38. /package/dist/{query-GOBQ3GL5.js.map → query-B32UDQJS.js.map} +0 -0
  39. /package/dist/{registry-HUJEORRW.js.map → registry-GY4X2GZX.js.map} +0 -0
  40. /package/dist/{wiki-FZHSX4K3.js.map → wiki-LVYHDK2R.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{a as fd,b as Ps,g as hd}from"./chunk-C4S5XQKD.js";import{a as Kl,c as Ql}from"./chunk-LP227A6L.js";import{A as ar,B as pd,D as ud,a as so,b as Xl,f as Bt,g as Zl,h as ed,i as od,j as td,l as nd,m as sd,n as id,o as ir,p as rd,u as ad,v as cd,w as rr,x as ld}from"./chunk-HPY54DU6.js";import{a as dd,c as gd,d as md}from"./chunk-4FU4BFCH.js";import"./chunk-SCJ5ZXEN.js";import{a as Ji,b as xc}from"./chunk-RKPAVWXF.js";import{$ as Dn,A as kl,B as vl,C as xl,D as Sl,E as El,F as Al,G as Tl,H as _l,I as Cs,J as Co,K as Bo,L as qt,M as Is,N as Ns,O as Zi,P as Dl,Q as Pl,R as Ml,S as Ll,T as ql,U as Fl,V as Ft,W as Ut,X as Ul,Y as Wl,Z as Le,_ as Rs,a as Ic,aa as er,b as Nc,ba as Bl,ca as Gl,da as nr,ea as Yl,fa as _s,ga as Wt,h as $s,ha as Ds,i as Pc,ia as sr,j as Nn,ja as Vl,k as bs,l as qc,m as Fc,n as Qc,o as Zc,p as As,q as Gi,r as il,s as ml,t as pl,u as hl,v as yl,w as wl,x as $l,y as bl,z as Yi}from"./chunk-QQIWLN3H.js";import{A as Ts,G as gl,Ma as Jl,Na as or,Oa as Hl,Pa as tr,V as Rn,Y as Vi,Z as js,_ as jl,bb as vo,db as zl,fa as Wo,ga as Ol,ha as Xi,ja as Ki,la as Cl,ma as Il,na as _n,ra as Os,ua as Nl,va as Rl,w as zi,wa as Qi,x as ll,z as dl}from"./chunk-6WNQY6K2.js";import{a as Rc,d as _c,e as Dc}from"./chunk-VTWSW4KB.js";import{a as ks,b as vs,c as Uc,d as Wc,e as Bc,g as Jc,h as Hc,j as Gc,k as zc,l as Yc,m as Vc,p as xs,s as Xc,t as Kc}from"./chunk-S2GAEH2F.js";import"./chunk-GTJIKXDB.js";import"./chunk-BGG3ZSMW.js";import"./chunk-ZVP6GB4G.js";import"./chunk-PPUN7YHA.js";import"./chunk-VZLIBDLH.js";import{a as ul,b as fl}from"./chunk-EKJG63EJ.js";import{a as Mc,p as Lc}from"./chunk-4COYYJJY.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as no}from"./chunk-ACFQBLPX.js";import{c as el,e as Ss,g as Es}from"./chunk-LQE73AZR.js";import{a as ol,b as tl,c as nl,d as sl}from"./chunk-2D3RYIDU.js";import"./chunk-QLWGLRT5.js";import{a as rl,e as al,g as cl}from"./chunk-JIT5GPTX.js";import{L as Uo,R as wc,ca as bc,g as tc,r as nc,y as Ui,z as ac}from"./chunk-XTO4GRGN.js";import{b as Rt,g as Dt,h as ys,i as ws,j as Pt,k as cc,l as ct,m as Cn,u as $c}from"./chunk-J3GXZQXY.js";import{e as uc,f as Bi,k as fc}from"./chunk-GLQLCBJS.js";import{b as _t}from"./chunk-6W74CHNW.js";import"./chunk-YU5NDKPA.js";import"./chunk-SFQUP3BP.js";import{b as In}from"./chunk-LLNPKE7H.js";import{a as kc,b as vc}from"./chunk-SHEUCITK.js";import"./chunk-Y4CYQV7G.js";import{a as Hi,e as Sc,f as Ec,h as Ac,i as Tc,k as jc,l as Oc,m as Cc}from"./chunk-YLKCFW2R.js";import{a as Mt}from"./chunk-GV7S5BAX.js";import{c as dc}from"./chunk-SZDACK6O.js";import{f as gc,g as mc,h as Wi}from"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import{a as ic,k as pc}from"./chunk-VGI4EZTP.js";import{a as hc,b as re,c as Ie,d as Lt,e as yc}from"./chunk-CYKPDILL.js";import"./chunk-VWTBHLMX.js";import{a as qi}from"./chunk-VQM77L54.js";import"./chunk-XX7NXI3Y.js";import"./chunk-36AXN6ZB.js";import"./chunk-KA2UIZXG.js";import{a as Fi,b as sc}from"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-J3SOEFRE.js";import"./chunk-SIU6STB2.js";import{j as rc}from"./chunk-X5C5W3E4.js";import{e as lc}from"./chunk-GSX4NK2N.js";import"./chunk-HG6QA6EU.js";import"./chunk-MYVHVJWZ.js";import{n as oc}from"./chunk-AV7T3SYT.js";import"./chunk-Y5MFVVTM.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import"./chunk-O2RVUM2B.js";import{g as Fo,i as hs}from"./chunk-ILGLEA3I.js";import"./chunk-WPNRDEHW.js";import{b as Nt,d as ec}from"./chunk-2GIDVZ4H.js";import{a as Pi,b as _a,c as tu,d as ps,e as Da,f as Ya,g as au,h as Va,i as cu,m as It,n as Ka,q as Qa,u as Za,y as ko,z as On}from"./chunk-A35RTVMM.js";import{a as Oo,b as Ct,e as Ha,f as jn}from"./chunk-72SZI2UW.js";import{a as Xa,b as lu}from"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-JXF54PT7.js";import"./chunk-2PJKGZWP.js";import{a as jo,b as ou}from"./chunk-7I7IEX4S.js";import"./chunk-JHCI6XCJ.js";import"./chunk-DSYKYZMT.js";import{A as su,O as Wa,P as Mi,R as Li,Y as iu,h as Pa,ha as Ba,i as Ma,ia as Ja,j as La,ja as T,k as qa,ka as fs,l as Fa,m as nu,ma as te,z as Ua}from"./chunk-Y5HBYSJW.js";import{f as qo,n as us}from"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import{g as Ga,k as za,l as ru}from"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";import{Command as du}from"commander";var yd=new du().name("a2a").description("start an A2A (Agent-to-Agent) protocol server for external agent integration").option("--port <port>","server port","3171").option("--host <host>","server host","0.0.0.0").option("-p, --provider <provider>","AI provider","claude-code").option("-m, --model <model>","model to use").option("--api-key <key>","API key for the provider").option("-c, --cwd <cwd>","working directory",process.cwd()).option("--no-cors","disable CORS headers").action(async e=>{await new Nc({port:parseInt(e.port,10),host:e.host,provider:e.provider,model:e.model,apiKey:e.apiKey,cwd:e.cwd,cors:e.cors!==!1}).start()});te();import{Command as gu}from"commander";import{execFileSync as co}from"node:child_process";import{cpSync as wd,existsSync as dr,mkdirSync as cr,mkdtempSync as mu,readdirSync as pu,rmSync as $d,writeFileSync as bd}from"node:fs";import{dirname as kd,join as qe}from"node:path";import{homedir as Ms,release as uu,tmpdir as fu}from"node:os";import{setTimeout as hu}from"node:timers/promises";function Ls(){let e=Uc(process.platform,process.arch,uu());if(e)throw new Error(e)}function qs(){let e=qe(Ms(),"Library/LaunchAgents"),o=[];try{o=pu(e).filter(Jc)}catch{}let t=o.flatMap(n=>{let s=qe(e,n);try{return[{file:s,plist:co("plutil",["-convert","xml1","-o","-",s],{encoding:"utf8",stdio:["ignore","pipe","ignore"]})}]}catch{return[]}});return Hc(e,t)}function Pn(e){return`gui/${process.getuid()}/${e.label}`}async function lr(e){try{co("launchctl",["bootout",Pn(e)],{stdio:"pipe"})}catch{}for(let o=0;o<30;o++){try{co("launchctl",["print",Pn(e)],{stdio:"pipe"})}catch{return}await hu(200)}throw new Error("The desktop login service did not stop. Retry agentx desktop stop before installing.")}function vd(e){if(!dr(e.file))throw new Error("Run agentx desktop install first.");let o=!0;try{co("launchctl",["print",Pn(e)],{stdio:"pipe"})}catch{o=!1}o||co("launchctl",["bootstrap",`gui/${process.getuid()}`,e.file],{stdio:"pipe"}),co("launchctl",["kickstart",Pn(e)],{stdio:"pipe"})}function yu(){let e=Vc();if(e&&dr(qe(e,"apps/mac-voice/build.sh")))return e;throw new Error("Desktop sources are missing from this installation. Update AgentX to a release containing apps/mac-voice and apps/mac-helper.")}var Jt=new gu("desktop").description("install and control the macOS desktop assistant");Jt.command("install").description("build, install, and start voice and computer-use helpers at login").option("--agent <id>","pin this agent; without it, pick the agent from the menu-bar icon").option("--dry-run","show the installation plan without building or changing login items").action(async e=>{Ls();let o=T(),t=Wc(o.agents,e.agent),n=e.agent,s=o.dashboard?.daemonUrl||`http://${o.node.bind.replace(/^0\.0\.0\.0:/,"127.0.0.1:")}`,i=yu(),r=qe(Ms(),"Applications"),{keep:a,remove:c}=qs();if(console.log(`Desktop assistant \u2192 ${qe(r,ks)}
1
+ import{a as fd,b as Ps,g as hd}from"./chunk-C4S5XQKD.js";import{a as Kl,c as Ql}from"./chunk-LP227A6L.js";import{A as ar,B as pd,D as ud,a as so,b as Xl,f as Bt,g as Zl,h as ed,i as od,j as td,l as nd,m as sd,n as id,o as ir,p as rd,u as ad,v as cd,w as rr,x as ld}from"./chunk-UMFFIUU6.js";import{a as dd,c as gd,d as md}from"./chunk-4FU4BFCH.js";import"./chunk-SCJ5ZXEN.js";import{a as Ji,b as xc}from"./chunk-RKPAVWXF.js";import{$ as Dn,A as kl,B as vl,C as xl,D as Sl,E as El,F as Al,G as Tl,H as _l,I as Cs,J as Co,K as Bo,L as qt,M as Is,N as Ns,O as Zi,P as Dl,Q as Pl,R as Ml,S as Ll,T as ql,U as Fl,V as Ft,W as Ut,X as Ul,Y as Wl,Z as Le,_ as Rs,a as Ic,aa as er,b as Nc,ba as Bl,ca as Gl,da as nr,ea as Yl,fa as _s,ga as Wt,h as $s,ha as Ds,i as Pc,ia as sr,j as Nn,ja as Vl,k as bs,l as qc,m as Fc,n as Qc,o as Zc,p as As,q as Gi,r as il,s as ml,t as pl,u as hl,v as yl,w as wl,x as $l,y as bl,z as Yi}from"./chunk-DOQ6Y7GZ.js";import{A as Ts,G as gl,Ma as Jl,Na as or,Oa as Hl,Pa as tr,V as Rn,Y as Vi,Z as js,_ as jl,bb as vo,db as zl,fa as Wo,ga as Ol,ha as Xi,ja as Ki,la as Cl,ma as Il,na as _n,ra as Os,ua as Nl,va as Rl,w as zi,wa as Qi,x as ll,z as dl}from"./chunk-ZXQYOSHP.js";import{a as Rc,d as _c,e as Dc}from"./chunk-VTWSW4KB.js";import{a as ks,b as vs,c as Uc,d as Wc,e as Bc,g as Jc,h as Hc,j as Gc,k as zc,l as Yc,m as Vc,p as xs,s as Xc,t as Kc}from"./chunk-S2GAEH2F.js";import"./chunk-GTJIKXDB.js";import"./chunk-BGG3ZSMW.js";import"./chunk-ZVP6GB4G.js";import"./chunk-PPUN7YHA.js";import"./chunk-VZLIBDLH.js";import{a as ul,b as fl}from"./chunk-EKJG63EJ.js";import{a as Mc,p as Lc}from"./chunk-EVB23EHN.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as no}from"./chunk-ACFQBLPX.js";import{c as el,e as Ss,g as Es}from"./chunk-LQE73AZR.js";import{a as ol,b as tl,c as nl,d as sl}from"./chunk-2D3RYIDU.js";import"./chunk-QLWGLRT5.js";import{a as rl,e as al,g as cl}from"./chunk-JIT5GPTX.js";import{L as Uo,R as wc,ca as bc,g as tc,r as nc,y as Ui,z as ac}from"./chunk-QBWJGDKE.js";import{b as Rt,g as Dt,h as ys,i as ws,j as Pt,k as cc,l as ct,m as Cn,u as $c}from"./chunk-J3GXZQXY.js";import{e as uc,f as Bi,k as fc}from"./chunk-GLQLCBJS.js";import{b as _t}from"./chunk-6W74CHNW.js";import"./chunk-UZB5UO35.js";import"./chunk-SFQUP3BP.js";import{b as In}from"./chunk-LLNPKE7H.js";import{a as kc,b as vc}from"./chunk-SHEUCITK.js";import"./chunk-Y4CYQV7G.js";import{a as Hi,e as Sc,f as Ec,h as Ac,i as Tc,k as jc,l as Oc,m as Cc}from"./chunk-YLKCFW2R.js";import{a as Mt}from"./chunk-GV7S5BAX.js";import{c as dc}from"./chunk-SZDACK6O.js";import{f as gc,g as mc,h as Wi}from"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import{a as ic,k as pc}from"./chunk-VGI4EZTP.js";import{a as hc,b as re,c as Ie,d as Lt,e as yc}from"./chunk-CYKPDILL.js";import"./chunk-VWTBHLMX.js";import{a as qi}from"./chunk-Z6OPM7EH.js";import"./chunk-TZIPWZY6.js";import"./chunk-36AXN6ZB.js";import"./chunk-KA2UIZXG.js";import{a as Fi,b as sc}from"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-J3SOEFRE.js";import"./chunk-SIU6STB2.js";import{j as rc}from"./chunk-X5C5W3E4.js";import{e as lc}from"./chunk-GSX4NK2N.js";import"./chunk-HG6QA6EU.js";import"./chunk-MYVHVJWZ.js";import{n as oc}from"./chunk-AV7T3SYT.js";import"./chunk-Y5MFVVTM.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import"./chunk-CSLVHAYV.js";import{g as Fo,i as hs}from"./chunk-JVSTKXMI.js";import"./chunk-WPNRDEHW.js";import{b as Nt,d as ec}from"./chunk-2GIDVZ4H.js";import{a as Pi,b as _a,c as tu,d as ps,e as Da,f as Ya,g as au,h as Va,i as cu,m as It,n as Ka,q as Qa,u as Za,y as ko,z as On}from"./chunk-A35RTVMM.js";import{a as Oo,b as Ct,e as Ha,f as jn}from"./chunk-72SZI2UW.js";import{a as Xa,b as lu}from"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-JXF54PT7.js";import"./chunk-2PJKGZWP.js";import{a as jo,b as ou}from"./chunk-7I7IEX4S.js";import"./chunk-JHCI6XCJ.js";import"./chunk-DSYKYZMT.js";import{A as su,O as Wa,P as Mi,R as Li,Y as iu,h as Pa,ha as Ba,i as Ma,ia as Ja,j as La,ja as T,k as qa,ka as fs,l as Fa,m as nu,ma as te,z as Ua}from"./chunk-Y5HBYSJW.js";import{f as qo,n as us}from"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import{g as Ga,k as za,l as ru}from"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";import{Command as du}from"commander";var yd=new du().name("a2a").description("start an A2A (Agent-to-Agent) protocol server for external agent integration").option("--port <port>","server port","3171").option("--host <host>","server host","0.0.0.0").option("-p, --provider <provider>","AI provider","claude-code").option("-m, --model <model>","model to use").option("--api-key <key>","API key for the provider").option("-c, --cwd <cwd>","working directory",process.cwd()).option("--no-cors","disable CORS headers").action(async e=>{await new Nc({port:parseInt(e.port,10),host:e.host,provider:e.provider,model:e.model,apiKey:e.apiKey,cwd:e.cwd,cors:e.cors!==!1}).start()});te();import{Command as gu}from"commander";import{execFileSync as co}from"node:child_process";import{cpSync as wd,existsSync as dr,mkdirSync as cr,mkdtempSync as mu,readdirSync as pu,rmSync as $d,writeFileSync as bd}from"node:fs";import{dirname as kd,join as qe}from"node:path";import{homedir as Ms,release as uu,tmpdir as fu}from"node:os";import{setTimeout as hu}from"node:timers/promises";function Ls(){let e=Uc(process.platform,process.arch,uu());if(e)throw new Error(e)}function qs(){let e=qe(Ms(),"Library/LaunchAgents"),o=[];try{o=pu(e).filter(Jc)}catch{}let t=o.flatMap(n=>{let s=qe(e,n);try{return[{file:s,plist:co("plutil",["-convert","xml1","-o","-",s],{encoding:"utf8",stdio:["ignore","pipe","ignore"]})}]}catch{return[]}});return Hc(e,t)}function Pn(e){return`gui/${process.getuid()}/${e.label}`}async function lr(e){try{co("launchctl",["bootout",Pn(e)],{stdio:"pipe"})}catch{}for(let o=0;o<30;o++){try{co("launchctl",["print",Pn(e)],{stdio:"pipe"})}catch{return}await hu(200)}throw new Error("The desktop login service did not stop. Retry agentx desktop stop before installing.")}function vd(e){if(!dr(e.file))throw new Error("Run agentx desktop install first.");let o=!0;try{co("launchctl",["print",Pn(e)],{stdio:"pipe"})}catch{o=!1}o||co("launchctl",["bootstrap",`gui/${process.getuid()}`,e.file],{stdio:"pipe"}),co("launchctl",["kickstart",Pn(e)],{stdio:"pipe"})}function yu(){let e=Vc();if(e&&dr(qe(e,"apps/mac-voice/build.sh")))return e;throw new Error("Desktop sources are missing from this installation. Update AgentX to a release containing apps/mac-voice and apps/mac-helper.")}var Jt=new gu("desktop").description("install and control the macOS desktop assistant");Jt.command("install").description("build, install, and start voice and computer-use helpers at login").option("--agent <id>","pin this agent; without it, pick the agent from the menu-bar icon").option("--dry-run","show the installation plan without building or changing login items").action(async e=>{Ls();let o=T(),t=Wc(o.agents,e.agent),n=e.agent,s=o.dashboard?.daemonUrl||`http://${o.node.bind.replace(/^0\.0\.0\.0:/,"127.0.0.1:")}`,i=yu(),r=qe(Ms(),"Applications"),{keep:a,remove:c}=qs();if(console.log(`Desktop assistant \u2192 ${qe(r,ks)}
2
2
  Computer-use helper \u2192 ${qe(r,vs)}
3
3
  Agent \u2192 ${n?`${t} (pinned)`:"picked from the menu-bar icon"}
4
4
  Daemon \u2192 ${s}
@@ -453,7 +453,7 @@ return aid ?? null`}function py(e,o){if(e.kind==="path"){let s=e.pts,i=s[Math.fl
453
453
  Latest runs (${s.length})`),s.length===0&&console.log(F.dim(" nothing recorded yet"));for(let r of s){let a=r.status==="ok"?F.green("ok"):r.status==="in-flight"?F.yellow("running"):F.red(r.status);console.log(` ${F.dim(Om(r.startedAt))} ${(r.channel??"?").padEnd(9)} ${r.agentId} ${a} ${Cm(r.messagePreview)}`)}console.log()});us();su();import{Command as Iw}from"commander";import{existsSync as Nw}from"fs";import ye from"chalk";var cn=new Iw("requests").description("what you asked agents for that is not finished, oldest first"),Dm={in_progress:"in progress",waiting_owner:"waiting on you",waiting_other:"waiting on another agent",needs_attention:"needs attention",done:"done",declined:"declined",dropped:"dropped"};function Zr(){if(!Nw(hc()))return console.error(ye.red(" no agentx.json here: run this from the install folder, the one that holds agentx.json")),process.exitCode=1,null;let e=qo();return e?new Ua(e):(process.exitCode=1,null)}var mi=e=>new Date(e).toISOString().slice(0,16).replace("T"," ")+" UTC";function Pm(e){let o=e.state==="needs_attention"?ye.red:e.state==="waiting_owner"?ye.yellow:ye.dim;console.log(` ${ye.cyan(e.id)} ${o(`[${Dm[e.state]??e.state}]`)} ${ye.dim(`${mi(e.createdAt)} \xB7 ${e.channel} \xB7 ${e.agentId}`)}`),console.log(` ${e.text.replace(/\s+/g," ").trim().slice(0,240)}`),e.state==="waiting_owner"&&e.question&&console.log(ye.yellow(` Question: ${e.question}`)),e.state==="needs_attention"&&e.attentionReason&&console.log(ye.red(` ${e.attentionReason}`)),e.evidence&&console.log(ye.green(` Evidence: ${e.evidence}`)),e.closeReason&&console.log(ye.dim(` Reason: ${e.closeReason}`))}cn.command("list",{isDefault:!0}).alias("ls").description("open requests, oldest first").option("--json","machine-readable output").action(e=>{let o=Zr();if(!o)return;let t=o.listOpen();if(e.json){console.log(JSON.stringify(t,null,2));return}if(zi().enabled||console.log(ye.dim(" requests are off: turn them on with `agentx requests settings --enabled on`")),t.length===0){console.log(ye.dim(" no open requests"));return}for(let n of t)Pm(n);console.log(ye.dim(`
454
454
  ${t.length} open. Close one: agentx requests done <id> --evidence <link> \xB7 agentx requests drop <id>`))});cn.command("show <id>").description("one request and the runs, delegations and cards linked to it").action(e=>{let o=Zr();if(!o)return;let t=o.get(e);if(!t||t.state==="candidate"){console.error(ye.red(` no request "${e}"`)),process.exitCode=1;return}Pm(t),console.log(ye.dim(` Last activity ${mi(t.updatedAt)}${t.closedAt?` \xB7 closed ${mi(t.closedAt)}`:""}`));for(let n of o.links(e))console.log(ye.dim(` ${n.kind} ${n.ref} (${mi(n.at)})`))});function Mm(e,o,t,n){cn.command(`${e} <id>`).description(o).option(t,e==="done"?"link to the proof: PR, issue, message, deploy":"why it is dropped").action((s,i)=>{let r=Zr();if(!r)return;let a=e==="done"?i.evidence:i.reason??"dropped by the owner";if(!a){console.error(ye.red(` ${n}`)),process.exitCode=1;return}let c=r.get(s);if(!c||c.state==="candidate"){console.error(ye.red(` no request "${s}"`)),process.exitCode=1;return}if(!r.close(s,e==="done"?"done":"dropped",a,Date.now())){console.error(ye.red(` ${s} is already closed (${Dm[c.state]??c.state})`)),process.exitCode=1;return}console.log(ye.green(` \u2713 ${s} ${e==="done"?"closed as done":"dropped"}`))})}Mm("done","close a request as finished, with a link to the evidence","--evidence <link>","a finished request needs --evidence <link>");Mm("drop","drop a request you no longer want","--reason <text>","");cn.command("settings").description("show or change the requests settings").option("--enabled <on|off>","record and follow your requests").option("--from <id,...>",'who counts as you on channels other people can reach, as channel:id (your login on GitLab and GitHub, your sender id elsewhere); "none" to clear').option("--channels <name,...>",'channels to record on; "all" for every channel a person writes on').option("--stale-hours <n>","hours without activity before an open request comes back to you").option("--retention-days <n>","days a closed request is kept").action(async e=>{let o={};try{let n=(i,r)=>{if(r===void 0)return;let a=Number(r);if(!(a>0))throw new Error(`${i} must be a positive number`);return a},s=(i,r)=>i===void 0?void 0:i===r?[]:i.split(",").map(a=>a.trim()).filter(Boolean);if(e.enabled!==void 0){if(e.enabled!=="on"&&e.enabled!=="off")throw new Error("--enabled takes on or off");o.enabled=e.enabled==="on"}o.from=s(e.from,"none"),o.channels=s(e.channels,"all"),o.staleAfterHours=n("--stale-hours",e.staleHours),o.retentionDays=n("--retention-days",e.retentionDays)}catch(n){console.error(ye.red(` ${n.message}`)),process.exitCode=1;return}if(Object.values(o).some(n=>n!==void 0)){let n=await ll(o);if(!n.success){console.error(ye.red(` ${n.error}`)),process.exitCode=1;return}console.log(ye.green(" \u2713 saved")+(n.reloaded?ye.dim(" (daemon reloaded)"):""))}let t=zi();console.log(` Requests ${t.enabled?"on":"off"}`),console.log(` Channels ${t.channels.length?t.channels.join(", "):"every channel a person writes on"}`),console.log(` Counts as you ${t.from.length?t.from.join(", "):"only voice, the app and the dashboard on this machine"}`),console.log(` Comes back after ${t.staleAfterHours} hour(s) without activity`),console.log(` Closed requests kept ${t.retentionDays} day(s)`)});import{Command as Rw}from"commander";import ln from"chalk";te();var Lm=new Rw("request-status").description("show each person the state of their request in the thread where they asked (GitLab, GitHub)").argument("[channel]",rr.join(" or ")).argument("[state]","on or off").action(async(e,o)=>{if(e!==void 0){o!=="on"&&o!=="off"&&(console.error(ln.red("\u2717 say on or off, for example: agentx request-status gitlab on")),process.exit(1));let n="",s=await re(i=>{n=ld(i,e,o==="on")});s.success||(console.error(ln.red(`\u2717 ${s.error}`)),process.exit(1)),console.log(ln.green(`\u2713 ${n}`)),s.reloaded&&console.log(ln.dim(" daemon hot-reloaded"))}let t=T().requestStatus.channels.map(n=>n.toLowerCase());for(let n of rr)console.log(` ${n.padEnd(8)} ${t.includes(n)?ln.green("on"):ln.dim("off")}`)});import{Command as t$}from"commander";import dn from"chalk";import ce from"chalk";import es from"prompts";import{readFileSync as _w,writeFileSync as Dw,existsSync as Pw}from"fs";import{resolve as qm}from"path";var Mw=/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;function Lw(e){let o=e.trim();return o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'")?o.slice(1,-1):o}function ea(e){return/[\s#"'\\]/.test(e)||e===""?JSON.stringify(e):e}function Fm(e=".env"){let o=qm(e);if(!Pw(o))return[];let t=_w(o,"utf-8"),n=[];for(let s of t.split(/\r?\n/)){if(s.trim()===""){n.push({kind:"blank",raw:s});continue}if(s.trim().startsWith("#")){n.push({kind:"comment",raw:s});continue}let i=s.match(Mw);i?n.push({kind:"kv",key:i[1],value:Lw(i[2]),raw:s}):n.push({kind:"comment",raw:s})}return n.length&&n[n.length-1].kind==="blank"&&n.pop(),n}function qw(e){return e.map(o=>o.kind==="kv"?`${o.key}=${ea(o.value)}`:o.raw).join(`
455
455
  `)+`
456
- `}function Zn(e,o,t=".env"){let n=qm(t),s=Fm(n),i=s.findIndex(r=>r.kind==="kv"&&r.key===e);i>=0?s[i]={kind:"kv",key:e,value:o,raw:`${e}=${ea(o)}`}:(s.length&&s[s.length-1].kind!=="blank"&&s.push({kind:"blank",raw:""}),s.push({kind:"kv",key:e,value:o,raw:`${e}=${ea(o)}`})),Dw(n,qw(s))}function oa(e,o=".env"){return Fm(o).find(s=>s.kind==="kv"&&s.key===e)?.value}var Um="https://t.me/BotFather";async function Fw(e){try{let o=await fetch(`https://api.telegram.org/bot${e}/getMe`,{signal:AbortSignal.timeout(8e3)});if(!o.ok)return null;let t=await o.json();return t?.ok?t.result:null}catch{return null}}async function Uw(e,o){let t=Date.now()+o,n=0;try{let i=await(await fetch(`https://api.telegram.org/bot${e}/getUpdates?offset=-1&timeout=0`,{signal:AbortSignal.timeout(5e3)})).json();i?.result?.length&&(n=i.result[0].update_id+1)}catch{}for(;Date.now()<t;)try{let i=await(await fetch(`https://api.telegram.org/bot${e}/getUpdates?offset=${n}&timeout=10`,{signal:AbortSignal.timeout(15e3)})).json();for(let r of i?.result||[]){n=Math.max(n,r.update_id+1);let a=r.message||r.edited_message||r.channel_post;if(a?.chat?.id)return{chatId:a.chat.id,chatTitle:a.chat.title||a.chat.username||a.chat.first_name,from:a.from?.first_name||a.from?.username||"unknown"}}}catch{}return null}async function Wm(e={}){console.log(),console.log(ce.bold(" Connect Telegram")),console.log(),console.log(ce.dim(` 1. Open ${Um}`)),console.log(ce.dim(" /newbot (or /mybots \u2192 pick existing \u2192 API Token)")),console.log(ce.dim(" 2. Copy the HTTP API token \u2014 looks like 123456789:ABCdef...")),console.log();let{wantsBrowser:o}=await es({type:"confirm",name:"wantsBrowser",message:"Open BotFather in your browser?",initial:!0});o&&gt(Um);let{token:t}=await es({type:"password",name:"token",message:"Paste the bot token from BotFather:",validate:k=>/^\d+:[A-Za-z0-9_-]{20,}$/.test(k.trim())||"That doesn't look like a Telegram token"});t||(console.log(ce.red(" Aborted")),process.exit(1)),process.stdout.write(" Verifying token... ");let n=await Fw(t.trim());n||(console.log(ce.red("\u2717 invalid or revoked")),process.exit(1)),console.log(ce.green(`\u2713 ${n.first_name} (@${n.username})`));let{readFileSync:s,existsSync:i}=await import("fs"),{resolve:r}=await import("path"),a=e.configPath||r(process.cwd(),"agentx.json");i(a)||(console.log(ce.red(` No agentx.json at ${a}. Run: agentx init`)),process.exit(1));let c=JSON.parse(s(a,"utf-8")),l=Object.keys(c.agents||{});l.length===0&&(console.log(ce.red(" No agents configured. Run: agentx agent add")),process.exit(1));let g=e.agent;g||(g=(await es({type:"select",name:"agent",message:"Bind this bot to which agent?",choices:l.map($=>({title:$,value:$})),initial:0})).agent),g||(console.log(ce.red(" Aborted")),process.exit(1));let d=c.channels?.telegram?.accounts||{},u=e.account||g;d[u]&&d[u].agentBinding!==g&&(u=(await es({type:"text",name:"account",message:`Account "${u}" is already in use. Pick a different label:`,initial:`${g}-2`,validate:$=>/^[a-z0-9-]+$/i.test($)||"lowercase letters, digits, hyphens only"})).account),u||(console.log(ce.red(" Aborted")),process.exit(1));let f=`TG_${u.toUpperCase().replace(/-/g,"_")}_BOT_TOKEN`;Zn(f,t.trim()),process.env[f]=t.trim();let p=await re(k=>{Ie(k,"channels.telegram.enabled",!0),Ie(k,`channels.telegram.accounts.${u}`,{token:`\${${f}}`,agentBinding:g});let $=Lt(k,`agents.${g}.mentions`)||[],E=`@${n.username}`;$.includes(E)||($.push(E),Ie(k,`agents.${g}.mentions`,$))},{configPath:e.configPath});if(p.success||(console.log(ce.red(` \u2717 ${p.error}`)),process.exit(1)),console.log(),console.log(ce.green(` \u2713 Bot @${n.username} bound to agent "${g}"`)),console.log(ce.dim(` Token stored in .env as ${f}`)),console.log(ce.dim(` Mentions updated to include @${n.username}`)),p.reloaded?console.log(ce.dim(" Daemon hot-reloaded.")):console.log(ce.dim(" Start the daemon to begin polling (agentx daemon start)")),e.skipChatCapture)return;console.log();let{capture:y}=await es({type:"confirm",name:"capture",message:"Listen for a message so we can set this as your default --notify target?",initial:!0});if(!y)return;console.log(),console.log(ce.dim(` Send any message to @${n.username} from the chat you want to use.`)),console.log(ce.dim(" Waiting up to 90s..."));let w=await Uw(t.trim(),9e4);if(!w){console.log(ce.yellow(" No message received \u2014 skipping. You can set it later with:")),console.log(ce.dim(" agentx config set notifications.destination.channel telegram")),console.log(ce.dim(" agentx config set notifications.destination.chatId <chatId>")),console.log(ce.dim(` agentx config set notifications.destination.accountId ${u}`));return}let b=await re(k=>{Ie(k,"notifications.destination",{channel:"telegram",chatId:String(w.chatId),accountId:u})},{configPath:e.configPath});if(!b.success){console.log(ce.red(` \u2717 failed to save destination: ${b.error}`));return}console.log(ce.green(" \u2713 Default --notify target set")),console.log(ce.dim(` Chat: ${w.chatTitle||w.chatId} (from ${w.from})`)),console.log(ce.dim(" From now on, --notify me resolves to this chat.")),b.reloaded&&console.log(ce.dim(" Daemon hot-reloaded."))}import ve from"chalk";import ta from"prompts";import{existsSync as sa,mkdirSync as Ww,readdirSync as Bw,readFileSync as Bm}from"fs";import{resolve as na}from"path";var Jw=".agentx/whatsapp-sessions";function Hw(){let e=na(process.cwd(),".agentx/daemon.pid");if(!sa(e))return!1;try{let o=parseInt(Bm(e,"utf-8").trim(),10);return o?(process.kill(o,0),!0):!1}catch{return!1}}function Gw(e){if(!sa(e))return!1;try{return Bw(e).some(o=>o.includes("creds")||o.endsWith(".json"))}catch{return!1}}async function zw(e,o){let t;try{t=await import("@whiskeysockets/baileys")}catch{return o(ve.red(" WhatsApp pairing needs @whiskeysockets/baileys.")),o(ve.red(" Install with: pnpm add @whiskeysockets/baileys (or npm install)")),!1}let{makeWASocket:n,useMultiFileAuthState:s}=t.default||t;Ww(e,{recursive:!0});let{state:i,saveCreds:r}=await s(e),a;try{a=(await t.fetchLatestBaileysVersion()).version}catch{}let c={level:"silent",trace:()=>{},debug:()=>{},info:()=>{},warn:()=>{},fatal:()=>{},error:()=>{},child:()=>c},l=n({auth:{creds:i.creds,keys:t.makeCacheableSignalKeyStore?t.makeCacheableSignalKeyStore(i.keys,c):i.keys},...a?{version:a}:{},logger:c,printQRInTerminal:!1,browser:["agentx-connect","pairing","1.0"],syncFullHistory:!1,markOnlineOnConnect:!1});return l.ev.on("creds.update",r),await new Promise(g=>{let u=setTimeout(()=>{o(ve.yellow(" Timed out waiting for scan (2min)."));try{l.end(void 0)}catch{}g(!1)},12e4);l.ev.on("connection.update",async f=>{if(f.qr){o(ve.dim(" Scan this QR with WhatsApp \u2192 Linked devices \u2192 Link a device:")),o("");try{let{default:p}=await import("qrcode-terminal");p.generate(f.qr,{small:!0})}catch{o(` QR: ${f.qr}`)}o("")}if(f.connection==="open"){clearTimeout(u),o(ve.green(" \u2713 Paired"));try{l.end(void 0)}catch{}g(!0)}f.connection==="close"&&!f.qr&&f.lastDisconnect?.error?.output?.statusCode===401&&(clearTimeout(u),o(ve.red(" \u2717 Authorization failed \u2014 rescan required")),g(!1))})})}async function Jm(e={}){if(console.log(),console.log(ve.bold(" Connect WhatsApp")),console.log(),Hw()){console.log(ve.yellow(" \u26A0 The daemon is running. Stop it first so pairing can open a fresh Baileys session:")),console.log(ve.dim(" agentx daemon stop")),console.log();let{cont:l}=await ta({type:"confirm",name:"cont",message:"Continue anyway? (expect errors)",initial:!1});l||(console.log(ve.red(" Aborted")),process.exit(1))}let o=e.configPath||na(process.cwd(),"agentx.json");sa(o)||(console.log(ve.red(` No agentx.json at ${o}. Run: agentx init`)),process.exit(1));let t=JSON.parse(Bm(o,"utf-8")),n=e.sessionDir||t.channels?.whatsapp?.sessionDir||Jw,s=na(process.cwd(),n),i=Object.keys(t.agents||{});i.length===0&&(console.log(ve.red(" No agents configured. Run: agentx agent add")),process.exit(1));let r=e.agent;r||(r=(await ta({type:"select",name:"agent",message:"Default agent for incoming messages:",choices:i.map(g=>({title:g,value:g})),initial:0})).agent),r||(console.log(ve.red(" Aborted")),process.exit(1));let a=!e.skipPair;if(Gw(s)&&a){let{keep:l}=await ta({type:"confirm",name:"keep",message:`An existing session was found at ${n}. Keep it (recommended), or pair again?`,initial:!0});a=!l,l&&console.log(ve.dim(" Keeping existing session \u2014 skipping QR pair."))}a&&(await zw(s,g=>console.log(g))||(console.log(ve.red(" Pairing failed. You can retry with `agentx connect whatsapp`.")),process.exit(1)));let c=await re(l=>{Ie(l,"channels.whatsapp.enabled",!0),Ie(l,"channels.whatsapp.sessionDir",n),Ie(l,"channels.whatsapp.defaultAgent",r)},{configPath:e.configPath});c.success||(console.log(ve.red(` \u2717 ${c.error}`)),process.exit(1)),console.log(),console.log(ve.green(` \u2713 WhatsApp bound to agent "${r}"`)),console.log(ve.dim(` Session: ${n}`)),console.log(ve.dim(" Start the daemon to begin receiving:")),console.log(ve.dim(" agentx daemon start")),console.log(ve.dim(" Add routes later with:")),console.log(ve.dim(` agentx config set channels.whatsapp.routes '[{"contact":"+1234567890","agent":"${r}"}]'`)),console.log()}import{randomBytes as Yw}from"crypto";import je from"chalk";import Hm from"prompts";var pi="agentx-mesh:",ui="//join/";function Vw(e){return Buffer.from(e,"utf-8").toString("base64url")}function Xw(e){return Buffer.from(e,"base64url").toString("utf-8")}function Kw(e){return`${pi}${ui}${Vw(JSON.stringify(e))}`}function Qw(e){if(!e.startsWith(`${pi}${ui}`))throw new Error(`Not a mesh invite link \u2014 expected ${pi}${ui}\u2026`);let o=e.slice(pi.length+ui.length),t=JSON.parse(Xw(o));if(t.version!==1)throw new Error(`Unsupported invite version: ${t.version}`);if(typeof t.url!="string"||typeof t.token!="string"||typeof t.name!="string")throw new Error("Invite payload missing required fields (url, token, name)");return t}function Zw(){return Yw(32).toString("hex")}function e$(e){let o=e?.node?.bind||"127.0.0.1:18800",[t,n]=o.split(":");return`http://${t}:${n}`}function o$(e){return e?.node?.name||e?.node?.id||"node"}async function Gm(e){let{readFileSync:o,existsSync:t}=await import("fs"),{resolve:n}=await import("path"),s=e.configPath||n(process.cwd(),"agentx.json");t(s)||(console.log(je.red(` No agentx.json at ${s}. Run: agentx init`)),process.exit(1));let i=JSON.parse(o(s,"utf-8")),r=oa("MESH_TOKEN");r||(r=Zw(),Zn("MESH_TOKEN",r),console.log(je.dim(" Generated new MESH_TOKEN (32 bytes) and saved to .env")));let a=e.url||e$(i);if((a.includes("0.0.0.0")||a.includes("127.0.0.1")||a.includes("localhost"))&&!e.url){let{url:d}=await Hm({type:"text",name:"url",message:"This node's URL as peers should reach it (e.g. http://100.x.x.x:18800):",initial:a,validate:u=>/^https?:\/\//.test(u)||"must start with http:// or https://"});d||(console.log(je.red(" Aborted")),process.exit(1)),a=d}let l=await re(d=>{Ie(d,"mesh.enabled",!0)},{configPath:e.configPath});l.success||(console.log(je.red(` \u2717 ${l.error}`)),process.exit(1));let g=Kw({url:a,token:r,name:o$(i),version:1});console.log(),console.log(je.bold(" Mesh invite")),console.log(),console.log(` ${je.cyan(g)}`),console.log(),console.log(je.dim(" Run on the other node:")),console.log(je.dim(` agentx connect mesh join "${g}"`)),console.log(),console.log(je.yellow(" Share over a trusted channel only \u2014 whoever holds this link can join your mesh.")),console.log()}async function zm(e,o={}){let t;try{t=Qw(e)}catch(i){console.log(je.red(` \u2717 ${i.message}`)),process.exit(1)}let n=oa("MESH_TOKEN");if(n&&n!==t.token){let{overwrite:i}=await Hm({type:"confirm",name:"overwrite",message:"A different MESH_TOKEN already exists in .env. Overwrite with the invite's token?",initial:!1});i||(console.log(je.red(" Aborted (keeping existing .env)")),process.exit(1))}Zn("MESH_TOKEN",t.token);let s=await re(i=>{Ie(i,"mesh.enabled",!0);let r=Lt(i,"mesh.peers")||[],a=r.findIndex(l=>l.name===t.name),c={name:t.name,url:t.url,token:"${MESH_TOKEN}"};a>=0?r[a]=c:r.push(c),Ie(i,"mesh.peers",r)},{configPath:o.configPath});s.success||(console.log(je.red(` \u2717 ${s.error}`)),process.exit(1)),console.log(je.green(" \u2713 Joined mesh")),console.log(je.dim(` Peer: ${t.name} @ ${t.url}`)),console.log(je.dim(" Shared token stored in .env as MESH_TOKEN")),s.reloaded?console.log(je.dim(" Daemon hot-reloaded.")):console.log(je.dim(" Restart the daemon to start the mesh (agentx daemon start).")),console.log();try{let i=await fetch(`${t.url.replace(/\/$/,"")}/.well-known/agent-card.json`,{signal:AbortSignal.timeout(5e3)});if(i.ok){let r=await i.json(),a=Array.isArray(r.agents)?r.agents.length:"?";console.log(je.dim(` Reachable \u2014 ${t.name} exposes ${a} agents`))}else console.log(je.yellow(` Peer returned HTTP ${i.status} \u2014 double-check the URL`))}catch(i){console.log(je.yellow(` Could not reach ${t.url} right now (${i?.cause?.code||i.message}) \u2014 verify VPN / Tailscale when the peer daemon is up`))}}var gn=new t$().name("connect").description("connect a channel or mesh peer \u2014 no manual file editing required");gn.command("telegram").description("pair a Telegram bot \u2014 persists token in .env, binds to an agent, auto-detects default chat").option("--agent <id>","agent to bind the bot to (skips the prompt)").option("--account <name>","account label in channels.telegram.accounts (defaults to agent id)").option("--skip-chat-capture","don't listen for the first message after pairing").option("-c, --config <path>","path to agentx.json").action(async e=>{await Wm({agent:e.agent,account:e.account,configPath:e.config,skipChatCapture:!!e.skipChatCapture})});gn.command("whatsapp").description("pair WhatsApp via QR (prints in terminal), then writes channels.whatsapp config").option("--agent <id>","default agent for inbound messages").option("--session-dir <path>","session directory (default: .agentx/whatsapp-sessions)").option("--skip-pair","skip QR pairing (use when session already exists)").option("-c, --config <path>","path to agentx.json").action(async e=>{await Jm({agent:e.agent,sessionDir:e.sessionDir,skipPair:!!e.skipPair,configPath:e.config})});var Ym=gn.command("mesh").description("mesh invite + join \u2014 replaces manual MESH_TOKEN copy-paste");Ym.command("invite").description("emit a single-use join link for another AgentX node").option("--url <url>","this node's URL as peers should reach it (Tailscale IP etc.)").option("-c, --config <path>","path to agentx.json").action(async e=>{await Gm({url:e.url,configPath:e.config})});Ym.command("join <link>").description("accept an invite link from another AgentX node").option("-c, --config <path>","path to agentx.json").action(async(e,o)=>{await zm(e,{configPath:o.config})});gn.action(()=>{console.log(),console.log(dn.bold(" agentx connect \u2014 which channel?")),console.log(),console.log(` ${dn.cyan("agentx connect telegram")} \u2014 pair a Telegram bot`),console.log(` ${dn.cyan("agentx connect whatsapp")} \u2014 pair WhatsApp via QR`),console.log(` ${dn.cyan("agentx connect mesh invite")} \u2014 emit a mesh join link for another node`),console.log(` ${dn.cyan("agentx connect mesh join <link>")} \u2014 accept a mesh invite`),console.log(),console.log(dn.dim(" GitLab connect is the next slice.")),console.log()});te();import{Command as n$}from"commander";import X from"chalk";var St=new n$().name("usage").description("token usage analysis and reporting");St.command("today",{isDefault:!0}).description("show today's token usage").action(async()=>{try{let e=T(),[o,t]=e.node.bind.split(":"),s=await(await fetch(`http://${o||"127.0.0.1"}:${t}/usage`,{signal:AbortSignal.timeout(3e3)})).json();if(console.log(),console.log(X.bold(" Token Usage (last 7 days)")),console.log(),s.totalTasks===0){console.log(X.dim(" No tasks recorded yet")),console.log();return}let i=a=>a.toLocaleString();console.log(` Total: ${X.bold(i(s.totalTokens))} tokens across ${s.totalTasks} tasks`),console.log(` Input: ${i(s.totalInput)}`),console.log(` Output: ${i(s.totalOutput)}`),console.log(` Cache read: ${i(s.totalCacheRead)}`),console.log(` Cache create: ${i(s.totalCacheCreate)}`),s.cacheHitRatio>0&&console.log(` Cache hit: ${(s.cacheHitRatio*100).toFixed(1)}%`),s.totalErrors>0&&console.log(` Errors: ${X.red(String(s.totalErrors))}`),console.log(),console.log(X.bold(" By Agent:"));let r=Object.entries(s.byAgent||{});r.sort((a,c)=>c[1].total-a[1].total);for(let[a,c]of r){let l=i(c.total||c.input+c.output+c.cacheRead+c.cacheCreate),g=c.avgDuration?`${(c.avgDuration/1e3).toFixed(1)}s avg`:"";console.log(` ${X.cyan(a)}: ${l} tokens (${c.tasks} tasks) ${X.dim(g)}`)}console.log()}catch(e){e.cause?.code==="ECONNREFUSED"?console.log(X.red(" Daemon not running. Start with: agentx daemon start")):console.log(X.red(` ${e.message}`))}});St.command("plan").description("show the Claude plan windows as Claude Code last reported them, and any hold on fresh sessions").option("--lift","lift the hold on fresh sessions now, without waiting for the reset time").option("--json","raw JSON output").action(async e=>{try{let o=T(),[t,n]=o.node.bind.split(":"),s=`http://${t||"127.0.0.1"}:${n}`,i=e.lift?await fetch(`${s}/usage/plan/lift`,{method:"POST",signal:AbortSignal.timeout(3e3)}):await fetch(`${s}/usage/plan`,{signal:AbortSignal.timeout(3e3)});if(!i.ok)throw new Error(`Daemon answered ${i.status}. It may be older than this command; restart it.`);let r=await i.json();if(e.json){console.log(JSON.stringify(r,null,2));return}let a=d=>d.replace(/_/g," ");if(console.log(),e.lift){let d=r.lifted.map(u=>a(u.window));console.log(d.length?` Lifted the hold on: ${d.join(", ")}. The next fresh session asks Claude again.`:X.dim(" No hold to lift.")),console.log();return}let c=r.now,l=new Set(r.holds.map(d=>d.window));console.log(X.bold(" Claude plan (as Claude Code last reported it)")),console.log(),r.provider.length===0&&console.log(X.dim(" No report yet. Claude Code reports on each turn; the list is empty after a daemon restart."));for(let d of r.provider){let u=d.usingOverage?"extra usage":d.status==="allowed_warning"?"nearly full":d.status,f=typeof d.utilization=="number"?`${Math.round(d.utilization*100)}% used`:"",p=Math.max(1,Math.round((d.resetsAt-c)/6e4)),y=d.resetsAt>c?p<60?`resets in ${p} min`:p<48*60?`resets in ${Math.round(p/60)} h`:`resets in ${Math.round(p/1440)} days`:"",w=l.has(d.window)?X.red("holding fresh sessions"):"";console.log(` ${a(d.window).padEnd(18)} ${u.padEnd(12)} ${[f,y,w].filter(Boolean).join(", ")}`)}console.log();let g=d=>d?` of ${d}`:"";console.log(` Fresh sessions started: ${r.lastHour}${g(r.maxPerHour)} in the last hour, ${r.last5h}${g(r.maxPer5h)} in the last 5 hours`),l.size&&console.log(X.dim(" To try again now: agentx usage plan --lift")),console.log()}catch(o){o.cause?.code==="ECONNREFUSED"?console.log(X.red(" Daemon not running. Start with: agentx daemon start")):console.log(X.red(` ${o.message}`))}});St.command("report").description("run full session analysis (parses Claude Code JSONL files)").option("--days <n>","analyze last N days","7").action(async e=>{let{execSync:o}=await import("child_process"),{existsSync:t}=await import("fs"),{resolve:n}=await import("path"),s=n(process.cwd(),"scripts/token-report.py");if(!t(s)){console.log(X.red(` Script not found: ${s}`)),console.log(X.dim(" The token analyzer script should be at scripts/token-report.py"));return}console.log(X.dim(" Analyzing Claude Code sessions..."));try{o(`SINCE_DAYS=${e.days} python3 "${s}"`,{stdio:"inherit"})}catch{console.log(X.red(" Analysis failed. Is Python 3 installed?"))}});St.command("channels").description("cost per channel over a fixed range of days, next to a saved baseline").requiredOption("--from <date>","first day, YYYY-MM-DD").requiredOption("--to <date>","last day, YYYY-MM-DD").option("--save <file>","write this range's figures to a JSON file").option("--baseline <file>","a file written by --save, shown beside this range").option("--json","raw JSON output").action(async e=>{let{readFileSync:o,writeFileSync:t}=await import("fs"),{TokenTracker:n}=await import("./token-tracker-W7DFDEFN.js"),{channelCosts:s,costPerTask:i}=await import("./usage-channels-KBLEC4NE.js"),r=p=>/^\d{4}-\d{2}-\d{2}$/.test(p)&&!Number.isNaN(Date.parse(p));if(!r(e.from)||!r(e.to)||e.from>e.to){console.log(X.red(" --from and --to must be YYYY-MM-DD, with --from not after --to")),process.exitCode=1;return}let a=s(new n,e.from,e.to);e.save&&t(e.save,JSON.stringify(a,null,2));let c=null;if(e.baseline)try{c=JSON.parse(o(e.baseline,"utf-8"))}catch(p){console.log(X.red(` Cannot read baseline ${e.baseline}: ${p.message}`)),process.exitCode=1;return}if(e.json){console.log(JSON.stringify(c?{baseline:c,current:a}:a,null,2));return}let l=p=>p===null?"-":`$${p.toFixed(p<10?3:2)}`,g=p=>`${(p/1e6).toFixed(1)}M`;console.log(),console.log(X.bold(` Cost per channel, ${a.from} to ${a.to} (${a.days} day(s) with data)`)),c&&console.log(X.dim(` Baseline: ${c.from} to ${c.to} (${c.days} day(s) with data)`)),console.log();let d=` ${"channel".padEnd(14)} ${"tasks".padStart(6)} ${"cache read".padStart(11)} ${"cache write".padStart(11)} ${"output".padStart(8)} ${"cost".padStart(10)} ${"per task".padStart(9)}`;console.log(X.dim(c?`${d} ${"baseline".padStart(9)} ${"change".padStart(7)}`:d));let f=[...new Set([...Object.keys(a.channels),...Object.keys(c?.channels||{})])].map(p=>[p,a.channels[p],c?.channels[p]]).sort((p,y)=>(y[1]?.cost||0)-(p[1]?.cost||0));f.push(["TOTAL",a.total,c?.total]);for(let[p,y,w]of f){let b=i(y),k=` ${p.padEnd(14)} ${String(y?.tasks||0).padStart(6)} ${g(y?.cacheRead||0).padStart(11)} ${g(y?.cacheCreate||0).padStart(11)} ${g(y?.output||0).padStart(8)} ${l(y?.cost||0).padStart(10)} ${l(b).padStart(9)}`;if(c){let $=i(w),E=b!==null&&$?`${((b-$)/$*100).toFixed(0)}%`:"-";k+=` ${l($).padStart(9)} ${E.padStart(7)}`}console.log(k)}console.log(),c&&console.log(X.dim(" change = cost per task against the baseline; the two ranges do not have the same tasks.")),e.save&&console.log(X.dim(` Saved ${e.save}`)),console.log()});St.command("surfaces").description("which CLI commands and dashboard pages are actually used").option("--days <n>","window in days","30").option("--kind <kind>","cli | page (default: both)").option("--unused","list registered surfaces with ZERO recorded use instead").option("--json","raw JSON output").action(async e=>{let{listSurfaceUse:o}=await import("./surface-usage-HCJTUS6Z.js"),t=e.kind==="cli"||e.kind==="page"?e.kind:void 0,n=o({kind:t,sinceDays:Number(e.days)||30});if(e.unused){let{buildProgram:i}=await import("./program-IEMICVO3.js"),r=await i(),a=new Set(n.filter(d=>d.kind==="cli").map(d=>d.name)),c=[],l=(d,u)=>{for(let f of d.commands??[]){let p=u?`${u} ${f.name()}`:f.name();c.push(p),l(f,p)}};l(r,"");let g=c.filter(d=>!a.has(d)).sort();if(e.json){console.log(JSON.stringify({windowDays:Number(e.days)||30,unused:g},null,2));return}console.log(),console.log(X.bold(` Never used in the last ${e.days} days (${g.length}/${c.length})`)),console.log();for(let d of g)console.log(` ${X.dim("\xB7")} ${d}`);console.log(),console.log(X.dim(" Zero use is necessary but not sufficient to remove a surface \u2014")),console.log(X.dim(" it must also fail the impact test. See docs/architecture/surface-reduction.md")),console.log();return}if(e.json){console.log(JSON.stringify(n,null,2));return}if(n.length===0){console.log(),console.log(X.dim(` No surface usage recorded in the last ${e.days} days.`)),console.log(X.dim(" Counting starts once this build has been running for a while.")),console.log();return}console.log(),console.log(X.bold(` Surface usage \u2014 last ${e.days} days`)),console.log();let s="";for(let i of n){i.kind!==s&&(console.log(X.dim(` ${i.kind==="cli"?"CLI commands":"Dashboard pages"}`)),s=i.kind);let r=String(i.count).padStart(6),a=X.dim(`${i.days}d`);console.log(` ${X.cyan(r)} ${i.name.padEnd(28)} ${a}`)}console.log(),console.log(X.dim(` ${n.length} surface(s) with recorded use. See --unused for the rest.`)),console.log()});import{Command as s$}from"commander";import xe from"chalk";import{readFileSync as i$}from"fs";import{resolve as r$}from"path";te();var tt=new s$().name("board").description("kanban board dashboard \u2014 visual work view over configured sources");tt.command("serve",{isDefault:!0}).description("start the dashboard server (live view always; boards if configured)").option("--port <n>","override dashboard.port").option("--bind <host>","override dashboard.bind (e.g. 0.0.0.0)").action(async e=>{try{try{ec(r$(process.cwd(),".env"))}catch{}let o=a$(e.port,e.bind),{startBoardDashboard:t}=await import("./board-dashboard-GGW5ZZLT.js");t(o)}catch(o){console.log(xe.red(` ${o.message}`)),process.env.DEBUG&&o.stack&&console.log(xe.dim(o.stack)),process.exit(1)}});function a$(e,o){try{let t=T();return e&&(t.dashboard.port=parseInt(e,10)),o&&(t.dashboard.bind=o),t}catch{return console.log(xe.yellow(" No agentx.json found \u2014 starting dashboard in setup-only mode.")),console.log(xe.dim(" Visit http://127.0.0.1:"+(e||"4202")+` to run the wizard.
456
+ `}function Zn(e,o,t=".env"){let n=qm(t),s=Fm(n),i=s.findIndex(r=>r.kind==="kv"&&r.key===e);i>=0?s[i]={kind:"kv",key:e,value:o,raw:`${e}=${ea(o)}`}:(s.length&&s[s.length-1].kind!=="blank"&&s.push({kind:"blank",raw:""}),s.push({kind:"kv",key:e,value:o,raw:`${e}=${ea(o)}`})),Dw(n,qw(s))}function oa(e,o=".env"){return Fm(o).find(s=>s.kind==="kv"&&s.key===e)?.value}var Um="https://t.me/BotFather";async function Fw(e){try{let o=await fetch(`https://api.telegram.org/bot${e}/getMe`,{signal:AbortSignal.timeout(8e3)});if(!o.ok)return null;let t=await o.json();return t?.ok?t.result:null}catch{return null}}async function Uw(e,o){let t=Date.now()+o,n=0;try{let i=await(await fetch(`https://api.telegram.org/bot${e}/getUpdates?offset=-1&timeout=0`,{signal:AbortSignal.timeout(5e3)})).json();i?.result?.length&&(n=i.result[0].update_id+1)}catch{}for(;Date.now()<t;)try{let i=await(await fetch(`https://api.telegram.org/bot${e}/getUpdates?offset=${n}&timeout=10`,{signal:AbortSignal.timeout(15e3)})).json();for(let r of i?.result||[]){n=Math.max(n,r.update_id+1);let a=r.message||r.edited_message||r.channel_post;if(a?.chat?.id)return{chatId:a.chat.id,chatTitle:a.chat.title||a.chat.username||a.chat.first_name,from:a.from?.first_name||a.from?.username||"unknown"}}}catch{}return null}async function Wm(e={}){console.log(),console.log(ce.bold(" Connect Telegram")),console.log(),console.log(ce.dim(` 1. Open ${Um}`)),console.log(ce.dim(" /newbot (or /mybots \u2192 pick existing \u2192 API Token)")),console.log(ce.dim(" 2. Copy the HTTP API token \u2014 looks like 123456789:ABCdef...")),console.log();let{wantsBrowser:o}=await es({type:"confirm",name:"wantsBrowser",message:"Open BotFather in your browser?",initial:!0});o&&gt(Um);let{token:t}=await es({type:"password",name:"token",message:"Paste the bot token from BotFather:",validate:k=>/^\d+:[A-Za-z0-9_-]{20,}$/.test(k.trim())||"That doesn't look like a Telegram token"});t||(console.log(ce.red(" Aborted")),process.exit(1)),process.stdout.write(" Verifying token... ");let n=await Fw(t.trim());n||(console.log(ce.red("\u2717 invalid or revoked")),process.exit(1)),console.log(ce.green(`\u2713 ${n.first_name} (@${n.username})`));let{readFileSync:s,existsSync:i}=await import("fs"),{resolve:r}=await import("path"),a=e.configPath||r(process.cwd(),"agentx.json");i(a)||(console.log(ce.red(` No agentx.json at ${a}. Run: agentx init`)),process.exit(1));let c=JSON.parse(s(a,"utf-8")),l=Object.keys(c.agents||{});l.length===0&&(console.log(ce.red(" No agents configured. Run: agentx agent add")),process.exit(1));let g=e.agent;g||(g=(await es({type:"select",name:"agent",message:"Bind this bot to which agent?",choices:l.map($=>({title:$,value:$})),initial:0})).agent),g||(console.log(ce.red(" Aborted")),process.exit(1));let d=c.channels?.telegram?.accounts||{},u=e.account||g;d[u]&&d[u].agentBinding!==g&&(u=(await es({type:"text",name:"account",message:`Account "${u}" is already in use. Pick a different label:`,initial:`${g}-2`,validate:$=>/^[a-z0-9-]+$/i.test($)||"lowercase letters, digits, hyphens only"})).account),u||(console.log(ce.red(" Aborted")),process.exit(1));let f=`TG_${u.toUpperCase().replace(/-/g,"_")}_BOT_TOKEN`;Zn(f,t.trim()),process.env[f]=t.trim();let p=await re(k=>{Ie(k,"channels.telegram.enabled",!0),Ie(k,`channels.telegram.accounts.${u}`,{token:`\${${f}}`,agentBinding:g});let $=Lt(k,`agents.${g}.mentions`)||[],E=`@${n.username}`;$.includes(E)||($.push(E),Ie(k,`agents.${g}.mentions`,$))},{configPath:e.configPath});if(p.success||(console.log(ce.red(` \u2717 ${p.error}`)),process.exit(1)),console.log(),console.log(ce.green(` \u2713 Bot @${n.username} bound to agent "${g}"`)),console.log(ce.dim(` Token stored in .env as ${f}`)),console.log(ce.dim(` Mentions updated to include @${n.username}`)),p.reloaded?console.log(ce.dim(" Daemon hot-reloaded.")):console.log(ce.dim(" Start the daemon to begin polling (agentx daemon start)")),e.skipChatCapture)return;console.log();let{capture:y}=await es({type:"confirm",name:"capture",message:"Listen for a message so we can set this as your default --notify target?",initial:!0});if(!y)return;console.log(),console.log(ce.dim(` Send any message to @${n.username} from the chat you want to use.`)),console.log(ce.dim(" Waiting up to 90s..."));let w=await Uw(t.trim(),9e4);if(!w){console.log(ce.yellow(" No message received \u2014 skipping. You can set it later with:")),console.log(ce.dim(" agentx config set notifications.destination.channel telegram")),console.log(ce.dim(" agentx config set notifications.destination.chatId <chatId>")),console.log(ce.dim(` agentx config set notifications.destination.accountId ${u}`));return}let b=await re(k=>{Ie(k,"notifications.destination",{channel:"telegram",chatId:String(w.chatId),accountId:u})},{configPath:e.configPath});if(!b.success){console.log(ce.red(` \u2717 failed to save destination: ${b.error}`));return}console.log(ce.green(" \u2713 Default --notify target set")),console.log(ce.dim(` Chat: ${w.chatTitle||w.chatId} (from ${w.from})`)),console.log(ce.dim(" From now on, --notify me resolves to this chat.")),b.reloaded&&console.log(ce.dim(" Daemon hot-reloaded."))}import ve from"chalk";import ta from"prompts";import{existsSync as sa,mkdirSync as Ww,readdirSync as Bw,readFileSync as Bm}from"fs";import{resolve as na}from"path";var Jw=".agentx/whatsapp-sessions";function Hw(){let e=na(process.cwd(),".agentx/daemon.pid");if(!sa(e))return!1;try{let o=parseInt(Bm(e,"utf-8").trim(),10);return o?(process.kill(o,0),!0):!1}catch{return!1}}function Gw(e){if(!sa(e))return!1;try{return Bw(e).some(o=>o.includes("creds")||o.endsWith(".json"))}catch{return!1}}async function zw(e,o){let t;try{t=await import("@whiskeysockets/baileys")}catch{return o(ve.red(" WhatsApp pairing needs @whiskeysockets/baileys.")),o(ve.red(" Install with: pnpm add @whiskeysockets/baileys (or npm install)")),!1}let{makeWASocket:n,useMultiFileAuthState:s}=t.default||t;Ww(e,{recursive:!0});let{state:i,saveCreds:r}=await s(e),a;try{a=(await t.fetchLatestBaileysVersion()).version}catch{}let c={level:"silent",trace:()=>{},debug:()=>{},info:()=>{},warn:()=>{},fatal:()=>{},error:()=>{},child:()=>c},l=n({auth:{creds:i.creds,keys:t.makeCacheableSignalKeyStore?t.makeCacheableSignalKeyStore(i.keys,c):i.keys},...a?{version:a}:{},logger:c,printQRInTerminal:!1,browser:["agentx-connect","pairing","1.0"],syncFullHistory:!1,markOnlineOnConnect:!1});return l.ev.on("creds.update",r),await new Promise(g=>{let u=setTimeout(()=>{o(ve.yellow(" Timed out waiting for scan (2min)."));try{l.end(void 0)}catch{}g(!1)},12e4);l.ev.on("connection.update",async f=>{if(f.qr){o(ve.dim(" Scan this QR with WhatsApp \u2192 Linked devices \u2192 Link a device:")),o("");try{let{default:p}=await import("qrcode-terminal");p.generate(f.qr,{small:!0})}catch{o(` QR: ${f.qr}`)}o("")}if(f.connection==="open"){clearTimeout(u),o(ve.green(" \u2713 Paired"));try{l.end(void 0)}catch{}g(!0)}f.connection==="close"&&!f.qr&&f.lastDisconnect?.error?.output?.statusCode===401&&(clearTimeout(u),o(ve.red(" \u2717 Authorization failed \u2014 rescan required")),g(!1))})})}async function Jm(e={}){if(console.log(),console.log(ve.bold(" Connect WhatsApp")),console.log(),Hw()){console.log(ve.yellow(" \u26A0 The daemon is running. Stop it first so pairing can open a fresh Baileys session:")),console.log(ve.dim(" agentx daemon stop")),console.log();let{cont:l}=await ta({type:"confirm",name:"cont",message:"Continue anyway? (expect errors)",initial:!1});l||(console.log(ve.red(" Aborted")),process.exit(1))}let o=e.configPath||na(process.cwd(),"agentx.json");sa(o)||(console.log(ve.red(` No agentx.json at ${o}. Run: agentx init`)),process.exit(1));let t=JSON.parse(Bm(o,"utf-8")),n=e.sessionDir||t.channels?.whatsapp?.sessionDir||Jw,s=na(process.cwd(),n),i=Object.keys(t.agents||{});i.length===0&&(console.log(ve.red(" No agents configured. Run: agentx agent add")),process.exit(1));let r=e.agent;r||(r=(await ta({type:"select",name:"agent",message:"Default agent for incoming messages:",choices:i.map(g=>({title:g,value:g})),initial:0})).agent),r||(console.log(ve.red(" Aborted")),process.exit(1));let a=!e.skipPair;if(Gw(s)&&a){let{keep:l}=await ta({type:"confirm",name:"keep",message:`An existing session was found at ${n}. Keep it (recommended), or pair again?`,initial:!0});a=!l,l&&console.log(ve.dim(" Keeping existing session \u2014 skipping QR pair."))}a&&(await zw(s,g=>console.log(g))||(console.log(ve.red(" Pairing failed. You can retry with `agentx connect whatsapp`.")),process.exit(1)));let c=await re(l=>{Ie(l,"channels.whatsapp.enabled",!0),Ie(l,"channels.whatsapp.sessionDir",n),Ie(l,"channels.whatsapp.defaultAgent",r)},{configPath:e.configPath});c.success||(console.log(ve.red(` \u2717 ${c.error}`)),process.exit(1)),console.log(),console.log(ve.green(` \u2713 WhatsApp bound to agent "${r}"`)),console.log(ve.dim(` Session: ${n}`)),console.log(ve.dim(" Start the daemon to begin receiving:")),console.log(ve.dim(" agentx daemon start")),console.log(ve.dim(" Add routes later with:")),console.log(ve.dim(` agentx config set channels.whatsapp.routes '[{"contact":"+1234567890","agent":"${r}"}]'`)),console.log()}import{randomBytes as Yw}from"crypto";import je from"chalk";import Hm from"prompts";var pi="agentx-mesh:",ui="//join/";function Vw(e){return Buffer.from(e,"utf-8").toString("base64url")}function Xw(e){return Buffer.from(e,"base64url").toString("utf-8")}function Kw(e){return`${pi}${ui}${Vw(JSON.stringify(e))}`}function Qw(e){if(!e.startsWith(`${pi}${ui}`))throw new Error(`Not a mesh invite link \u2014 expected ${pi}${ui}\u2026`);let o=e.slice(pi.length+ui.length),t=JSON.parse(Xw(o));if(t.version!==1)throw new Error(`Unsupported invite version: ${t.version}`);if(typeof t.url!="string"||typeof t.token!="string"||typeof t.name!="string")throw new Error("Invite payload missing required fields (url, token, name)");return t}function Zw(){return Yw(32).toString("hex")}function e$(e){let o=e?.node?.bind||"127.0.0.1:18800",[t,n]=o.split(":");return`http://${t}:${n}`}function o$(e){return e?.node?.name||e?.node?.id||"node"}async function Gm(e){let{readFileSync:o,existsSync:t}=await import("fs"),{resolve:n}=await import("path"),s=e.configPath||n(process.cwd(),"agentx.json");t(s)||(console.log(je.red(` No agentx.json at ${s}. Run: agentx init`)),process.exit(1));let i=JSON.parse(o(s,"utf-8")),r=oa("MESH_TOKEN");r||(r=Zw(),Zn("MESH_TOKEN",r),console.log(je.dim(" Generated new MESH_TOKEN (32 bytes) and saved to .env")));let a=e.url||e$(i);if((a.includes("0.0.0.0")||a.includes("127.0.0.1")||a.includes("localhost"))&&!e.url){let{url:d}=await Hm({type:"text",name:"url",message:"This node's URL as peers should reach it (e.g. http://100.x.x.x:18800):",initial:a,validate:u=>/^https?:\/\//.test(u)||"must start with http:// or https://"});d||(console.log(je.red(" Aborted")),process.exit(1)),a=d}let l=await re(d=>{Ie(d,"mesh.enabled",!0)},{configPath:e.configPath});l.success||(console.log(je.red(` \u2717 ${l.error}`)),process.exit(1));let g=Kw({url:a,token:r,name:o$(i),version:1});console.log(),console.log(je.bold(" Mesh invite")),console.log(),console.log(` ${je.cyan(g)}`),console.log(),console.log(je.dim(" Run on the other node:")),console.log(je.dim(` agentx connect mesh join "${g}"`)),console.log(),console.log(je.yellow(" Share over a trusted channel only \u2014 whoever holds this link can join your mesh.")),console.log()}async function zm(e,o={}){let t;try{t=Qw(e)}catch(i){console.log(je.red(` \u2717 ${i.message}`)),process.exit(1)}let n=oa("MESH_TOKEN");if(n&&n!==t.token){let{overwrite:i}=await Hm({type:"confirm",name:"overwrite",message:"A different MESH_TOKEN already exists in .env. Overwrite with the invite's token?",initial:!1});i||(console.log(je.red(" Aborted (keeping existing .env)")),process.exit(1))}Zn("MESH_TOKEN",t.token);let s=await re(i=>{Ie(i,"mesh.enabled",!0);let r=Lt(i,"mesh.peers")||[],a=r.findIndex(l=>l.name===t.name),c={name:t.name,url:t.url,token:"${MESH_TOKEN}"};a>=0?r[a]=c:r.push(c),Ie(i,"mesh.peers",r)},{configPath:o.configPath});s.success||(console.log(je.red(` \u2717 ${s.error}`)),process.exit(1)),console.log(je.green(" \u2713 Joined mesh")),console.log(je.dim(` Peer: ${t.name} @ ${t.url}`)),console.log(je.dim(" Shared token stored in .env as MESH_TOKEN")),s.reloaded?console.log(je.dim(" Daemon hot-reloaded.")):console.log(je.dim(" Restart the daemon to start the mesh (agentx daemon start).")),console.log();try{let i=await fetch(`${t.url.replace(/\/$/,"")}/.well-known/agent-card.json`,{signal:AbortSignal.timeout(5e3)});if(i.ok){let r=await i.json(),a=Array.isArray(r.agents)?r.agents.length:"?";console.log(je.dim(` Reachable \u2014 ${t.name} exposes ${a} agents`))}else console.log(je.yellow(` Peer returned HTTP ${i.status} \u2014 double-check the URL`))}catch(i){console.log(je.yellow(` Could not reach ${t.url} right now (${i?.cause?.code||i.message}) \u2014 verify VPN / Tailscale when the peer daemon is up`))}}var gn=new t$().name("connect").description("connect a channel or mesh peer \u2014 no manual file editing required");gn.command("telegram").description("pair a Telegram bot \u2014 persists token in .env, binds to an agent, auto-detects default chat").option("--agent <id>","agent to bind the bot to (skips the prompt)").option("--account <name>","account label in channels.telegram.accounts (defaults to agent id)").option("--skip-chat-capture","don't listen for the first message after pairing").option("-c, --config <path>","path to agentx.json").action(async e=>{await Wm({agent:e.agent,account:e.account,configPath:e.config,skipChatCapture:!!e.skipChatCapture})});gn.command("whatsapp").description("pair WhatsApp via QR (prints in terminal), then writes channels.whatsapp config").option("--agent <id>","default agent for inbound messages").option("--session-dir <path>","session directory (default: .agentx/whatsapp-sessions)").option("--skip-pair","skip QR pairing (use when session already exists)").option("-c, --config <path>","path to agentx.json").action(async e=>{await Jm({agent:e.agent,sessionDir:e.sessionDir,skipPair:!!e.skipPair,configPath:e.config})});var Ym=gn.command("mesh").description("mesh invite + join \u2014 replaces manual MESH_TOKEN copy-paste");Ym.command("invite").description("emit a single-use join link for another AgentX node").option("--url <url>","this node's URL as peers should reach it (Tailscale IP etc.)").option("-c, --config <path>","path to agentx.json").action(async e=>{await Gm({url:e.url,configPath:e.config})});Ym.command("join <link>").description("accept an invite link from another AgentX node").option("-c, --config <path>","path to agentx.json").action(async(e,o)=>{await zm(e,{configPath:o.config})});gn.action(()=>{console.log(),console.log(dn.bold(" agentx connect \u2014 which channel?")),console.log(),console.log(` ${dn.cyan("agentx connect telegram")} \u2014 pair a Telegram bot`),console.log(` ${dn.cyan("agentx connect whatsapp")} \u2014 pair WhatsApp via QR`),console.log(` ${dn.cyan("agentx connect mesh invite")} \u2014 emit a mesh join link for another node`),console.log(` ${dn.cyan("agentx connect mesh join <link>")} \u2014 accept a mesh invite`),console.log(),console.log(dn.dim(" GitLab connect is the next slice.")),console.log()});te();import{Command as n$}from"commander";import X from"chalk";var St=new n$().name("usage").description("token usage analysis and reporting");St.command("today",{isDefault:!0}).description("show today's token usage").action(async()=>{try{let e=T(),[o,t]=e.node.bind.split(":"),s=await(await fetch(`http://${o||"127.0.0.1"}:${t}/usage`,{signal:AbortSignal.timeout(3e3)})).json();if(console.log(),console.log(X.bold(" Token Usage (last 7 days)")),console.log(),s.totalTasks===0){console.log(X.dim(" No tasks recorded yet")),console.log();return}let i=a=>a.toLocaleString();console.log(` Total: ${X.bold(i(s.totalTokens))} tokens across ${s.totalTasks} tasks`),console.log(` Input: ${i(s.totalInput)}`),console.log(` Output: ${i(s.totalOutput)}`),console.log(` Cache read: ${i(s.totalCacheRead)}`),console.log(` Cache create: ${i(s.totalCacheCreate)}`),s.cacheHitRatio>0&&console.log(` Cache hit: ${(s.cacheHitRatio*100).toFixed(1)}%`),s.totalErrors>0&&console.log(` Errors: ${X.red(String(s.totalErrors))}`),console.log(),console.log(X.bold(" By Agent:"));let r=Object.entries(s.byAgent||{});r.sort((a,c)=>c[1].total-a[1].total);for(let[a,c]of r){let l=i(c.total||c.input+c.output+c.cacheRead+c.cacheCreate),g=c.avgDuration?`${(c.avgDuration/1e3).toFixed(1)}s avg`:"";console.log(` ${X.cyan(a)}: ${l} tokens (${c.tasks} tasks) ${X.dim(g)}`)}console.log()}catch(e){e.cause?.code==="ECONNREFUSED"?console.log(X.red(" Daemon not running. Start with: agentx daemon start")):console.log(X.red(` ${e.message}`))}});St.command("plan").description("show the Claude plan windows as Claude Code last reported them, and any hold on fresh sessions").option("--lift","lift the hold on fresh sessions now, without waiting for the reset time").option("--json","raw JSON output").action(async e=>{try{let o=T(),[t,n]=o.node.bind.split(":"),s=`http://${t||"127.0.0.1"}:${n}`,i=e.lift?await fetch(`${s}/usage/plan/lift`,{method:"POST",signal:AbortSignal.timeout(3e3)}):await fetch(`${s}/usage/plan`,{signal:AbortSignal.timeout(3e3)});if(!i.ok)throw new Error(`Daemon answered ${i.status}. It may be older than this command; restart it.`);let r=await i.json();if(e.json){console.log(JSON.stringify(r,null,2));return}let a=d=>d.replace(/_/g," ");if(console.log(),e.lift){let d=r.lifted.map(u=>a(u.window));console.log(d.length?` Lifted the hold on: ${d.join(", ")}. The next fresh session asks Claude again.`:X.dim(" No hold to lift.")),console.log();return}let c=r.now,l=new Set(r.holds.map(d=>d.window));console.log(X.bold(" Claude plan (as Claude Code last reported it)")),console.log(),r.provider.length===0&&console.log(X.dim(" No report yet. Claude Code reports on each turn; the list is empty after a daemon restart."));for(let d of r.provider){let u=d.usingOverage?"extra usage":d.status==="allowed_warning"?"nearly full":d.status,f=typeof d.utilization=="number"?`${Math.round(d.utilization*100)}% used`:"",p=Math.max(1,Math.round((d.resetsAt-c)/6e4)),y=d.resetsAt>c?p<60?`resets in ${p} min`:p<48*60?`resets in ${Math.round(p/60)} h`:`resets in ${Math.round(p/1440)} days`:"",w=l.has(d.window)?X.red("holding fresh sessions"):"";console.log(` ${a(d.window).padEnd(18)} ${u.padEnd(12)} ${[f,y,w].filter(Boolean).join(", ")}`)}console.log();let g=d=>d?` of ${d}`:"";console.log(` Fresh sessions started: ${r.lastHour}${g(r.maxPerHour)} in the last hour, ${r.last5h}${g(r.maxPer5h)} in the last 5 hours`),l.size&&console.log(X.dim(" To try again now: agentx usage plan --lift")),console.log()}catch(o){o.cause?.code==="ECONNREFUSED"?console.log(X.red(" Daemon not running. Start with: agentx daemon start")):console.log(X.red(` ${o.message}`))}});St.command("report").description("run full session analysis (parses Claude Code JSONL files)").option("--days <n>","analyze last N days","7").action(async e=>{let{execSync:o}=await import("child_process"),{existsSync:t}=await import("fs"),{resolve:n}=await import("path"),s=n(process.cwd(),"scripts/token-report.py");if(!t(s)){console.log(X.red(` Script not found: ${s}`)),console.log(X.dim(" The token analyzer script should be at scripts/token-report.py"));return}console.log(X.dim(" Analyzing Claude Code sessions..."));try{o(`SINCE_DAYS=${e.days} python3 "${s}"`,{stdio:"inherit"})}catch{console.log(X.red(" Analysis failed. Is Python 3 installed?"))}});St.command("channels").description("cost per channel over a fixed range of days, next to a saved baseline").requiredOption("--from <date>","first day, YYYY-MM-DD").requiredOption("--to <date>","last day, YYYY-MM-DD").option("--save <file>","write this range's figures to a JSON file").option("--baseline <file>","a file written by --save, shown beside this range").option("--json","raw JSON output").action(async e=>{let{readFileSync:o,writeFileSync:t}=await import("fs"),{TokenTracker:n}=await import("./token-tracker-W7DFDEFN.js"),{channelCosts:s,costPerTask:i}=await import("./usage-channels-KBLEC4NE.js"),r=p=>/^\d{4}-\d{2}-\d{2}$/.test(p)&&!Number.isNaN(Date.parse(p));if(!r(e.from)||!r(e.to)||e.from>e.to){console.log(X.red(" --from and --to must be YYYY-MM-DD, with --from not after --to")),process.exitCode=1;return}let a=s(new n,e.from,e.to);e.save&&t(e.save,JSON.stringify(a,null,2));let c=null;if(e.baseline)try{c=JSON.parse(o(e.baseline,"utf-8"))}catch(p){console.log(X.red(` Cannot read baseline ${e.baseline}: ${p.message}`)),process.exitCode=1;return}if(e.json){console.log(JSON.stringify(c?{baseline:c,current:a}:a,null,2));return}let l=p=>p===null?"-":`$${p.toFixed(p<10?3:2)}`,g=p=>`${(p/1e6).toFixed(1)}M`;console.log(),console.log(X.bold(` Cost per channel, ${a.from} to ${a.to} (${a.days} day(s) with data)`)),c&&console.log(X.dim(` Baseline: ${c.from} to ${c.to} (${c.days} day(s) with data)`)),console.log();let d=` ${"channel".padEnd(14)} ${"tasks".padStart(6)} ${"cache read".padStart(11)} ${"cache write".padStart(11)} ${"output".padStart(8)} ${"cost".padStart(10)} ${"per task".padStart(9)}`;console.log(X.dim(c?`${d} ${"baseline".padStart(9)} ${"change".padStart(7)}`:d));let f=[...new Set([...Object.keys(a.channels),...Object.keys(c?.channels||{})])].map(p=>[p,a.channels[p],c?.channels[p]]).sort((p,y)=>(y[1]?.cost||0)-(p[1]?.cost||0));f.push(["TOTAL",a.total,c?.total]);for(let[p,y,w]of f){let b=i(y),k=` ${p.padEnd(14)} ${String(y?.tasks||0).padStart(6)} ${g(y?.cacheRead||0).padStart(11)} ${g(y?.cacheCreate||0).padStart(11)} ${g(y?.output||0).padStart(8)} ${l(y?.cost||0).padStart(10)} ${l(b).padStart(9)}`;if(c){let $=i(w),E=b!==null&&$?`${((b-$)/$*100).toFixed(0)}%`:"-";k+=` ${l($).padStart(9)} ${E.padStart(7)}`}console.log(k)}console.log(),c&&console.log(X.dim(" change = cost per task against the baseline; the two ranges do not have the same tasks.")),e.save&&console.log(X.dim(` Saved ${e.save}`)),console.log()});St.command("surfaces").description("which CLI commands and dashboard pages are actually used").option("--days <n>","window in days","30").option("--kind <kind>","cli | page (default: both)").option("--unused","list registered surfaces with ZERO recorded use instead").option("--json","raw JSON output").action(async e=>{let{listSurfaceUse:o}=await import("./surface-usage-HCJTUS6Z.js"),t=e.kind==="cli"||e.kind==="page"?e.kind:void 0,n=o({kind:t,sinceDays:Number(e.days)||30});if(e.unused){let{buildProgram:i}=await import("./program-4IMJEMDM.js"),r=await i(),a=new Set(n.filter(d=>d.kind==="cli").map(d=>d.name)),c=[],l=(d,u)=>{for(let f of d.commands??[]){let p=u?`${u} ${f.name()}`:f.name();c.push(p),l(f,p)}};l(r,"");let g=c.filter(d=>!a.has(d)).sort();if(e.json){console.log(JSON.stringify({windowDays:Number(e.days)||30,unused:g},null,2));return}console.log(),console.log(X.bold(` Never used in the last ${e.days} days (${g.length}/${c.length})`)),console.log();for(let d of g)console.log(` ${X.dim("\xB7")} ${d}`);console.log(),console.log(X.dim(" Zero use is necessary but not sufficient to remove a surface \u2014")),console.log(X.dim(" it must also fail the impact test. See docs/architecture/surface-reduction.md")),console.log();return}if(e.json){console.log(JSON.stringify(n,null,2));return}if(n.length===0){console.log(),console.log(X.dim(` No surface usage recorded in the last ${e.days} days.`)),console.log(X.dim(" Counting starts once this build has been running for a while.")),console.log();return}console.log(),console.log(X.bold(` Surface usage \u2014 last ${e.days} days`)),console.log();let s="";for(let i of n){i.kind!==s&&(console.log(X.dim(` ${i.kind==="cli"?"CLI commands":"Dashboard pages"}`)),s=i.kind);let r=String(i.count).padStart(6),a=X.dim(`${i.days}d`);console.log(` ${X.cyan(r)} ${i.name.padEnd(28)} ${a}`)}console.log(),console.log(X.dim(` ${n.length} surface(s) with recorded use. See --unused for the rest.`)),console.log()});import{Command as s$}from"commander";import xe from"chalk";import{readFileSync as i$}from"fs";import{resolve as r$}from"path";te();var tt=new s$().name("board").description("kanban board dashboard \u2014 visual work view over configured sources");tt.command("serve",{isDefault:!0}).description("start the dashboard server (live view always; boards if configured)").option("--port <n>","override dashboard.port").option("--bind <host>","override dashboard.bind (e.g. 0.0.0.0)").action(async e=>{try{try{ec(r$(process.cwd(),".env"))}catch{}let o=a$(e.port,e.bind),{startBoardDashboard:t}=await import("./board-dashboard-7B2B564A.js");t(o)}catch(o){console.log(xe.red(` ${o.message}`)),process.env.DEBUG&&o.stack&&console.log(xe.dim(o.stack)),process.exit(1)}});function a$(e,o){try{let t=T();return e&&(t.dashboard.port=parseInt(e,10)),o&&(t.dashboard.bind=o),t}catch{return console.log(xe.yellow(" No agentx.json found \u2014 starting dashboard in setup-only mode.")),console.log(xe.dim(" Visit http://127.0.0.1:"+(e||"4202")+` to run the wizard.
457
457
  `)),{node:{id:"setup",name:"Setup",bind:"127.0.0.1:18800"},providers:{},agents:{},channels:{},crons:{},mesh:{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},boards:[],dashboard:{enabled:!0,port:e?parseInt(e,10):4202,bind:o||"127.0.0.1",daemonUrl:"http://localhost:18800",daemons:[]},business:void 0,session:{staleMinutes:120}}}}tt.command("list").description("list configured boards").action(()=>{try{let e=T();if(!e.boards?.length){console.log(xe.dim(`
458
458
  No boards configured.
459
459
  `));return}console.log();for(let o of e.boards){console.log(` ${xe.cyan(o.id)} \u2014 ${o.name}`);let t=o.source;console.log(xe.dim(` source: ${t.type}${t.projects?" ("+t.projects.join(", ")+")":""}`)),o.primaryToolLabel&&console.log(xe.dim(` primary label: ${o.primaryToolLabel}`)),console.log(xe.dim(` window: ${o.timeRangeDays} days`))}console.log()}catch(e){console.log(xe.red(` ${e.message}`)),process.exit(1)}});tt.command("add <id>").description("add a GitLab board to agentx.json").requiredOption("--name <name>","human-readable board name").requiredOption("--projects <paths>","comma-separated GitLab project paths (e.g. 'globex/system,globex/website')").option("--label <label>","primary tool label ANDed into every query (e.g. 'Tool::Claude')").option("--days <n>","open-window time range in days","30").option("--closed-days <n>","closed-window in days","30").action((e,o)=>{try{os(t=>{if(Array.isArray(t.boards)||(t.boards=[]),t.boards.find(i=>i.id===e))throw new Error(`board "${e}" already exists`);let n=String(o.projects).split(",").map(i=>i.trim()).filter(Boolean);if(n.length===0)throw new Error("--projects must include at least one path");let s={id:e,name:o.name,source:{type:"gitlab",projects:n},timeRangeDays:parseInt(o.days,10)||30,closedWindowDays:parseInt(o.closedDays,10)||30};return o.label&&(s.primaryToolLabel=o.label),t.boards.push(s),`added board "${e}" (${n.join(", ")})`})}catch(t){console.log(xe.red(` ${t.message}`)),process.exit(1)}});tt.command("edit <id>").description("edit board fields without re-creating it").option("--name <name>","rename").option("--projects <paths>","comma-separated GitLab project paths (replaces the list)").option("--label <label>","primary tool label (set to '-' to clear)").option("--days <n>","open-window time range in days").option("--closed-days <n>","closed-window in days").action((e,o)=>{try{os(t=>{let s=(Array.isArray(t.boards)?t.boards:[]).find(r=>r.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=[];if(o.name&&(s.name=o.name,i.push(`name="${o.name}"`)),o.projects){let r=String(o.projects).split(",").map(a=>a.trim()).filter(Boolean);if(r.length===0)throw new Error("--projects must include at least one path");s.source={...s.source||{type:"gitlab"},type:"gitlab",projects:r},i.push(`projects=${r.length}`)}if(o.label!==void 0&&(o.label==="-"?(delete s.primaryToolLabel,i.push("label cleared")):(s.primaryToolLabel=o.label,i.push(`label="${o.label}"`))),o.days&&(s.timeRangeDays=parseInt(o.days,10)||s.timeRangeDays,i.push(`days=${s.timeRangeDays}`)),o.closedDays&&(s.closedWindowDays=parseInt(o.closedDays,10)||s.closedWindowDays,i.push(`closed-days=${s.closedWindowDays}`)),i.length===0)throw new Error("no changes \u2014 pass at least one option");return`board "${e}" updated (${i.join(", ")})`})}catch(t){console.log(xe.red(` ${t.message}`)),process.exit(1)}});var ia=tt.command("column").description("manage a board's columns (add / remove / edit / list)");ia.command("list <boardId>").description("list columns on a board, in order").action(e=>{try{let t=(JSON.parse(i$("agentx.json","utf-8")).boards||[]).find(s=>s.id===e);if(!t)throw new Error(`board "${e}" not found`);let n=t.columns||[];if(n.length===0){console.log(xe.dim(" no columns (board falls back to GitLab default flow)"));return}for(let s of n){let i=s.kind==="scoped-label"?`scoped="${s.scopedLabel}"`:s.kind==="label"?`label="${s.mapsToLabel||""}"`:s.kind==="open-backlog"?`prefix="${s.scopedPrefix}"`:s.kind;console.log(` ${xe.cyan(s.id.padEnd(12))} ${s.title.padEnd(14)} ${xe.dim(i)}`)}}catch(o){console.log(xe.red(` ${o.message}`)),process.exit(1)}});ia.command("add <boardId> <columnId>").description("add a column to a board").requiredOption("--title <title>","column title").option("--kind <kind>","open-backlog | scoped-label | closed | label","scoped-label").option("--scoped <label>","for kind=scoped-label, the full label (e.g. 'Status::Doing')").option("--label <label>","for kind=label, the label name to add/remove").option("--scoped-prefix <prefix>","for kind=open-backlog/scoped-label","Status").option("--accent <color>","hex/CSS color for the column accent bar").action((e,o,t)=>{try{os(n=>{let i=(Array.isArray(n.boards)?n.boards:[]).find(a=>a.id===e);if(!i)throw new Error(`board "${e}" not found`);if(i.columns=i.columns||[],i.columns.find(a=>a.id===o))throw new Error(`column "${o}" already exists on board "${e}"`);let r={id:o,title:t.title,kind:t.kind,scopedPrefix:t.scopedPrefix};if(t.kind==="scoped-label"){if(!t.scoped)throw new Error("--scoped required for kind=scoped-label");r.scopedLabel=t.scoped}if(t.kind==="label"){if(!t.label)throw new Error("--label required for kind=label");r.mapsToLabel=t.label}return t.accent&&(r.accent=t.accent),i.columns.push(r),`column "${o}" added to board "${e}"`})}catch(n){console.log(xe.red(` ${n.message}`)),process.exit(1)}});ia.command("remove <boardId> <columnId>").alias("rm").description("remove a column from a board").action((e,o)=>{try{os(t=>{let s=(Array.isArray(t.boards)?t.boards:[]).find(r=>r.id===e);if(!s)throw new Error(`board "${e}" not found`);let i=(s.columns||[]).length;if(s.columns=(s.columns||[]).filter(r=>r.id!==o),s.columns.length===i)throw new Error(`column "${o}" not found`);return`column "${o}" removed from board "${e}"`})}catch(t){console.log(xe.red(` ${t.message}`)),process.exit(1)}});tt.command("remove <id>").alias("rm").description("remove a board from agentx.json").action(e=>{try{os(o=>{if(!Array.isArray(o.boards)||o.boards.length===0)throw new Error("no boards configured");let t=o.boards.length;if(o.boards=o.boards.filter(n=>n.id!==e),o.boards.length===t)throw new Error(`board "${e}" not found`);return`removed board "${e}"`})}catch(o){console.log(xe.red(` ${o.message}`)),process.exit(1)}});function os(e){let{summary:o,backupPath:t}=so(n=>e(n));console.log(xe.green(`
@@ -466,7 +466,7 @@ ${x.content}
466
466
 
467
467
  `),$="";if(e.facts!==!1){let{extractHints:x,resolveFacts:R,mergeRecords:I,renderFactsBlock:C,installPrompts:M,defaultSources:H,recordsFromEntries:q}=await import("./facts-ROUMKS7I.js");if(!a){let G=new Set;for(let Ce of t.listAgents())for(let Se of t.getAgentWiki(Ce).listArticles(Ce))Se.meta.type==="person"&&G.add(Se.meta.title);a=[...G]}let Y=x(p.map(G=>({context:G.sourceContext,content:G.content,sender:typeof G.meta?.sender=="string"?G.meta.sender:void 0})),{known:a}),fe=q(p);if(Y.length>0||fe.length>0){let G=H(),{records:Ce,results:Se}=Y.length>0?await R(Y,{sources:G}):{records:[],results:[]},L=I([...fe,...Ce]);$=C(L);let oo=[...fe.length>0?[`entries:${fe.length}`]:[],...Se.filter(Ee=>Ee.records.length>0).map(Ee=>`${Ee.source}:${Ee.records.length}`)];console.log(m.dim(` Facts: ${Y.length} entities \u2192 ${L.length} resolved${oo.length?` (${oo.join(" ")})`:""}`));for(let Ee of M(Se,G))console.log(m.yellow(` ! ${Ee.source} ${Ee.kind} \u2014 would supply ${Ee.provides.join(", ")}`)),console.log(m.dim(` ${Ee.hint}`))}}let E=Mc(o,u,b,w.articles,k,p.length,$);console.log(m.dim(` Mode: ${aa(o)}`));let S=U(y.baseDir,"_tmp");Do(S,{recursive:!0});let v=U(S,"absorb-prompt.txt");At(v,E),console.log(m.dim(" Compiling with Claude..."));try{let x;try{x=Et(`cat '${v}' | claude -p - --output-format json --max-turns 3 --model sonnet --disallowedTools "Bash Read Write Edit Glob Grep Agent WebSearch WebFetch NotebookEdit"`,{env:Nt({...process.env}),encoding:"utf-8",timeout:9e5,maxBuffer:10*1024*1024})}catch(L){if(x=L.stdout||"",!x)throw L}let R=x;try{let L=JSON.parse(x);R=L.result||L.content||"",R||(console.log(m.dim(` Claude envelope keys: ${Object.keys(L).join(", ")}`)),console.log(m.dim(` is_error: ${L.is_error}, stop_reason: ${L.stop_reason}`)))}catch{}let I,C=[],M=R.indexOf("{"),H=R.indexOf("["),q=M>=0&&(H<0||M<H)?M:H;if(q===-1){console.log(m.red(" No JSON found in response")),console.log(m.dim(R.slice(0,500)));continue}let Y=R[q],fe=Y==="{"?"}":"]",G=0,Ce=-1;for(let L=q;L<R.length;L++)if(R[L]===Y)G++;else if(R[L]===fe&&(G--,G===0)){Ce=L+1;break}if(Ce===-1){console.log(m.red(" Unbalanced JSON"));continue}let Se=R.slice(q,Ce);try{let L=JSON.parse(Se);Array.isArray(L)?I=L:(I=L.articles||[],C=L.gaps||[])}catch(L){console.log(m.red(` JSON parse error: ${L.message}`)),console.log(m.dim(` First 300 chars: ${Se.slice(0,300)}`));continue}for(let L of I){let oo=new Date().toISOString().slice(0,10),Ee=l(L.sources||[],p);y.writeArticle(L.path,{title:L.title,type:L.type,related:Array.isArray(L.related)?L.related:void 0,tags:L.tags||[],owner:u,access:"public",created:oo,lastUpdated:oo,sources:L.sources||[],graphPath:Ee},L.content,u);let at=L.type?m.magenta(`[${L.type}]`)+" ":"",_=Array.isArray(L.related)&&L.related.length?` \u2192 ${L.related.slice(0,3).join(", ")}${L.related.length>3?", \u2026":""}`:"";console.log(` ${m.green("+")} ${at}${L.path}: ${L.title}${m.dim(_)}`);let $e=(L.tags||[]).slice(0,4).join(", ");$e&&console.log(m.dim(` tags: ${$e}`)),Ee?.length&&(console.log(m.dim(` graphPath: ${Ee.join(" \u203A ")}`)),d++),g++}if(C.length>0){console.log(),console.log(m.yellow(` Gaps detected (${C.length} missing pieces):`));for(let L of C)console.log(m.yellow(` ? ${L}`));try{let{QuestionStore:L}=await import("./questions-ZATLU5AW.js"),oo=new L(Tt(e.dir)).add(C.map(Ee=>({kind:"article",agentId:u,path:"",subject:String(Ee).slice(0,120),question:`No article yet for: ${String(Ee).slice(0,160)}`})));oo.added>0&&console.log(m.dim(` queued ${oo.added} for follow-up (agentx wiki questions)`))}catch{}}y.rebuildIndex()}catch(x){console.log(m.red(` Absorb failed: ${x.message?.slice(0,200)}`)),x.stderr&&console.log(m.dim(String(x.stderr).slice(0,300))),x.stdout&&console.log(m.dim("stdout: "+String(x.stdout).slice(0,300)))}}if(console.log(),e.dryRun)console.log(m.dim(" Dry run \u2014 no changes made"));else if(g>0&&(console.log(m.green(` ${g} articles compiled across ${n.length} agent(s)`)),i)){let u=g>0?Math.round(d/g*100):0;console.log(m.dim(` ${d}/${g} carry graphPath (${u}%) \u2014 wiki retrieval graph weight is now non-zero for those`))}console.log()});ne.command("promote").description("promote per-agent memories into shared, authoritative wiki articles").option("--dir <path>","wiki directory (default .agentx/wiki)").option("--memory-dir <path>","the .agentx dir holding agent-memory/ (default .agentx)").option("--since <duration>","memory window, e.g. 24h, 7d","7d").option("--agent <id>","only this agent's memories").option("--types <list>","comma-separated memory types","project,reference,feedback").option("--max <n>","max candidate memories per run","20").option("--via <agentId>","route the LLM call through an agent \u2014 uses the agent's own session, no API key").option("--model <model>","direct Anthropic API \u2014 needs ANTHROPIC_API_KEY").option("--daemon <url>","daemon API base URL for --via","http://127.0.0.1:18800").option("--reviews","also promote findings from session-monitor reviews").option("--review-kinds <list>","which review kinds","decisions,warnings,friction,context").option("--failures","also propose lessons from failures that recur across sessions").option("--min-sessions <n>","sessions a failure must recur in for --failures","3").option("--commit","judge and write proposals for review (default: dry-run)",!1).option("--budget <tokens>","max estimated tokens for the judge prompt","60000").action(async e=>{let o=p$(e.since),t=String(e.types).split(",").map(a=>a.trim()).filter(Boolean),n=["user","feedback","project","reference"],s=t.find(a=>!n.includes(a));s&&(console.log(m.red(` Invalid memory type "${s}". Valid: ${n.join(", ")}`)),process.exit(1)),e.commit&&!e.via&&!e.model&&(console.log(m.red(" --commit needs an LLM: pass --via <agentId> or --model <model>")),process.exit(1)),console.log(),console.log(m.bold(" Memory \u2192 Wiki Promotion")),console.log();let i=[];if(e.reviews){let{reviewsToCandidates:a}=await import("./review-candidates-TXX532LY.js"),{default:c}=await import("better-sqlite3"),l=U(process.cwd(),".agentx/db.sqlite");if(!to(l))console.log(m.yellow(` --reviews: no ${l}`));else{let g=new c(l,{readonly:!0});try{let d=g.prepare("SELECT id, session_id, agent, source, updated_at, result FROM session_reviews WHERE status='ready' AND result IS NOT NULL AND updated_at >= ? ORDER BY updated_at DESC").all(Date.now()-(o??6048e5));i=a(d,{kinds:String(e.reviewKinds).split(",").map(p=>p.trim()).filter(Boolean)});let u=i.filter(p=>(p.occurrences??1)>1).length;console.log(m.dim(` ${d.length} review(s) in window \u2192 ${i.length} candidate finding(s), ${u} seen in more than one session`));let f=i[0];f&&(f.occurrences??1)>1&&console.log(m.dim(` most recurrent (${f.occurrences} sessions): ${f.memory.description.slice(0,84)}`))}finally{g.close()}}}if(e.failures){let a=Number(e.minSessions);(!Number.isInteger(a)||a<2)&&(console.log(m.red(` Invalid --min-sessions "${e.minSessions}". Use a whole number of 2 or more.`)),process.exit(1));let{loadFailedTraces:c,failuresToCandidates:l}=await import("./failure-candidates-PBPF45GN.js"),{default:g}=await import("better-sqlite3"),d=U(process.cwd(),".agentx/db.sqlite");if(!to(d))console.log(m.yellow(` --failures: no ${d}`));else{let u=new g(d,{readonly:!0});try{let f=c(u,{since:Date.now()-(o??6048e5)}),p=l(f,{minSessions:a});console.log(m.dim(` ${f.length} failed run(s) in window \u2192 ${p.length} failure(s) seen in ${a}+ sessions`));let y=p[0];y&&console.log(m.dim(` most recurrent (${y.occurrences} sessions, ${y.failure.runs} runs): ${y.memory.description.slice(0,84)}`)),i=[...i,...p]}finally{u.close()}}}let r=await Lc({extraCandidates:i,wikiDir:e.dir?U(e.dir):void 0,memoryRoot:e.memoryDir?U(e.memoryDir):void 0,sinceMs:o,agentFilter:e.agent,types:t,max:Number(e.max)||20,viaAgent:e.via,model:e.model,daemonUrl:e.daemon,commit:e.commit,budgetTokens:Number(e.budget)||void 0,log:a=>console.log(m.dim(` ${a}`))});if(r.candidates.length===0){console.log(m.dim(" Nothing unpromoted in window")),console.log();return}console.log(` ${r.candidates.length} candidate(s) in ${r.clusters.length} cluster(s):`);for(let a of r.clusters){let c=a.candidates[0],l=a.corroboratingAgents.length>1?m.green(` \xD7${a.corroboratingAgents.length} agents`):"";console.log(` ${m.cyan(`[${c.memory.type}]`)} ${c.memory.name}${l} ${m.dim(`(${a.corroboratingAgents.join(", ")}, conf ${a.confidence.toFixed(2)})`)}`),console.log(m.dim(` ${c.memory.description}`))}if(console.log(),r.dryRun){console.log(m.dim(" Dry run \u2014 pass --commit to judge and propose")),console.log();return}for(let a of r.proposed){let c=a.type?m.magenta(`[${a.type}]`)+" ":"",l=`${a.agents.length} agent(s)${a.occurrences>1?`, seen in ${a.occurrences} sessions`:""}`;console.log(` ${m.green("?")} ${c}${a.path}: ${a.title} ${m.dim(`(${l})`)}`),console.log(m.dim(` proposal ${a.id}`))}for(let a of r.skipped)console.log(` ${m.yellow("-")} ${a.stamp} ${m.dim(`\u2014 ${a.reason}`)}`);if(r.gaps.length){console.log(),console.log(m.yellow(` Gaps (${r.gaps.length}):`));for(let a of r.gaps)console.log(m.yellow(` ? ${a}`))}for(let a of r.warnings)console.log(m.dim(` ! ${a}`));for(let a of r.errors)console.log(m.red(` x ${a}`));console.log(),console.log(r.errors.length?m.red(` ${r.proposed.length} proposed, ${r.errors.length} error(s)`):m.green(` ${r.proposed.length} proposed, ${r.skipped.length} skipped`)),r.proposed.length&&console.log(m.dim(" Nothing is in the wiki yet. Review with: agentx wiki proposals list")),console.log(),r.errors.length&&process.exit(1)});var hi=ne.command("proposals").description("review lessons proposed for the shared wiki (list, show, approve, reject)");function yi(e){return e?U(e):U(process.cwd(),".agentx","wiki")}hi.command("list").description("list proposals (pending by default)").option("--all","include approved and rejected").option("--dir <path>","wiki directory (default .agentx/wiki)").action(async e=>{let{listProposals:o}=await import("./proposals-O4B5LD5T.js"),t=o(yi(e.dir),e.all?void 0:"pending");if(t.length===0){console.log(m.dim(e.all?" no proposals":" nothing pending"));return}for(let n of t){let s=n.evidence,i=s.sources.some(l=>l.kind==="failure")?" \xB7 from a recurring failure":"",r=`${s.agents.join(", ")}${s.occurrences>1?` \xB7 seen in ${s.occurrences} sessions`:""} \xB7 ${s.sources.length} source(s)${i}`,a=n.status==="pending"?"":m.dim(` [${n.status}]`),c=n.replaces?m.yellow("update"):m.green("new");console.log(` ${m.cyan(n.id)}${a}`),console.log(` ${c} ${n.article.path}: ${n.article.title}`),console.log(m.dim(` ${r}`))}});hi.command("show").description("the proposed article and the evidence behind it").argument("<id>","proposal id").option("--dir <path>","wiki directory (default .agentx/wiki)").action(async(e,o)=>{let{readProposal:t}=await import("./proposals-O4B5LD5T.js"),n=t(yi(o.dir),e);if(!n){console.error(m.red(` no proposal "${e}"`)),process.exitCode=1;return}console.log(m.bold(` ${n.article.title}`)+m.dim(` \u2192 ${n.article.path} (${n.replaces?"updates an existing article":"new article"}, ${n.status})`)),console.log(),console.log(n.article.content.split(`
468
468
  `).map(s=>` ${s}`).join(`
469
- `)),console.log(),console.log(m.bold(" Evidence"));for(let s of n.evidence.sources){let i=s.author?`${s.author}${s.taskId?` \xB7 task ${s.taskId}`:""}`:s.agentId,r=s.occurrences&&s.occurrences>1?` \xB7 seen in ${s.occurrences} sessions`:"";console.log(` - ${m.cyan(s.kind)} ${s.type}/${s.name} ${m.dim(`(${i}, ${s.updatedAt.slice(0,10)}${r})`)}`),console.log(m.dim(` ${s.description}`)),s.failure&&console.log(m.dim(` failing tool: ${s.failure.tool} \xB7 error: ${s.failure.errorClass} \xB7 ${s.failure.runs} run(s)`)),s.sessions?.length&&console.log(m.dim(` sessions: ${s.sessions.join(", ")}`)),s.tasks?.length&&console.log(m.dim(` runs: ${s.tasks.join(", ")} (agentx trace show <id>)`))}});hi.command("approve").description("write the proposed article into the shared wiki").argument("<id>","proposal id").option("--force","approve even if the article changed since the proposal").option("--dir <path>","wiki directory (default .agentx/wiki)").action(async(e,o)=>{let{approveProposal:t}=await import("./promote-S7SKOKX2.js"),n=t(yi(o.dir),e,{force:o.force});if(!n.ok){console.error(m.red(` ${n.error}`)),process.exitCode=1;return}console.log(m.green(` \u2713 ${n.proposal.article.path} written to the shared wiki`))});hi.command("reject").description("decline a proposal; its sources aren't judged again until they change").argument("<id>","proposal id").option("--reason <text>","why, kept with the decision").option("--dir <path>","wiki directory (default .agentx/wiki)").action(async(e,o)=>{let{rejectProposal:t}=await import("./promote-S7SKOKX2.js"),n=t(yi(o.dir),e,{reason:o.reason});if(!n.ok){console.error(m.red(` ${n.error}`)),process.exitCode=1;return}console.log(m.green(` \u2713 ${e} rejected`))});function p$(e){if(!e)return;let o=/^(\d+)\s*([smhd])$/.exec(e.trim());o||(console.log(m.red(` Invalid --since "${e}". Use "30m", "24h", or "7d".`)),process.exit(1));let t=Number(o[1]),n=o[2];return t*(n==="s"?1e3:n==="m"?6e4:n==="h"?36e5:864e5)}ne.command("ab-test").description("side-by-side comparison: BM25 preload (old) vs agentic query (new) on real task-history messages").option("--dir <path>","wiki directory").option("--agent <id>","which agent to test against (required)").option("--history <path>","task-history root",U(process.cwd(),".agentx/task-history")).option("--n <n>","number of messages to sample (newest first)","10").option("--out <path>","markdown output file (default: stdout)").option("--selector-model <m>","agentic selector model","haiku").option("--synth-model <m>","agentic synthesis model","sonnet").action(async e=>{let{agenticQuery:o}=await import("./query-GOBQ3GL5.js"),{readdirSync:t,readFileSync:n,existsSync:s}=await import("fs"),{resolve:i,join:r}=await import("path"),a=Oe(e.dir),c=e.agent;if(!c){console.log(m.red(" --agent <id> is required"));return}let l=a.getAgentWiki(c),g=parseInt(e.n),d=i(e.history,c);if(!s(d)){console.log(m.yellow(` no task-history at ${d}`));return}let u=[],f=t(d).sort().reverse();for(let w of f){let b=r(d,w),k=[];try{k=t(b).filter($=>$.endsWith(".json")).sort().reverse()}catch{continue}for(let $ of k){if(u.length>=g)break;try{let E=JSON.parse(n(r(b,$),"utf-8")),S=E.message||E.task?.message;typeof S=="string"&&S.trim().length>10&&u.push({id:E.id||$.replace(".json",""),message:S.trim(),ts:E.at||E.timestamp||w})}catch{}}if(u.length>=g)break}if(u.length===0){console.log(m.yellow(` no task messages found under ${d}`));return}console.log(),console.log(m.bold(` A/B harness \u2014 ${u.length} messages from ${c}`)),console.log(m.dim(" OLD: findRelevant() BM25 over title+tags+content, top 3 truncated")),console.log(m.dim(` NEW: agenticQuery() catalog+wikilink walk (selector=${e.selectorModel}, synth=${e.synthModel})`)),console.log();let p=[`# Wiki A/B: ${c}`,"",`_Generated ${new Date().toISOString()} \xB7 ${u.length} messages sampled_`,"","For each message, the OLD BM25 retrieval (what Layer 10 used to preload) is shown alongside the NEW agentic query's selected articles + synthesized answer. Rate each pair on relevance 0\u20132 in the notes column.",""];for(let w=0;w<u.length;w++){let b=u[w];process.stdout.write(m.dim(` [${w+1}/${u.length}] querying... `));let $=l.findRelevant(b.message,c,3).map(S=>`- **${S.meta.title}** [${S.meta.type||"?"}] (${S.path})`).join(`
469
+ `)),console.log(),console.log(m.bold(" Evidence"));for(let s of n.evidence.sources){let i=s.author?`${s.author}${s.taskId?` \xB7 task ${s.taskId}`:""}`:s.agentId,r=s.occurrences&&s.occurrences>1?` \xB7 seen in ${s.occurrences} sessions`:"";console.log(` - ${m.cyan(s.kind)} ${s.type}/${s.name} ${m.dim(`(${i}, ${s.updatedAt.slice(0,10)}${r})`)}`),console.log(m.dim(` ${s.description}`)),s.failure&&console.log(m.dim(` failing tool: ${s.failure.tool} \xB7 error: ${s.failure.errorClass} \xB7 ${s.failure.runs} run(s)`)),s.sessions?.length&&console.log(m.dim(` sessions: ${s.sessions.join(", ")}`)),s.tasks?.length&&console.log(m.dim(` runs: ${s.tasks.join(", ")} (agentx trace show <id>)`))}});hi.command("approve").description("write the proposed article into the shared wiki").argument("<id>","proposal id").option("--force","approve even if the article changed since the proposal").option("--dir <path>","wiki directory (default .agentx/wiki)").action(async(e,o)=>{let{approveProposal:t}=await import("./promote-4VTXBVUC.js"),n=t(yi(o.dir),e,{force:o.force});if(!n.ok){console.error(m.red(` ${n.error}`)),process.exitCode=1;return}console.log(m.green(` \u2713 ${n.proposal.article.path} written to the shared wiki`))});hi.command("reject").description("decline a proposal; its sources aren't judged again until they change").argument("<id>","proposal id").option("--reason <text>","why, kept with the decision").option("--dir <path>","wiki directory (default .agentx/wiki)").action(async(e,o)=>{let{rejectProposal:t}=await import("./promote-4VTXBVUC.js"),n=t(yi(o.dir),e,{reason:o.reason});if(!n.ok){console.error(m.red(` ${n.error}`)),process.exitCode=1;return}console.log(m.green(` \u2713 ${e} rejected`))});function p$(e){if(!e)return;let o=/^(\d+)\s*([smhd])$/.exec(e.trim());o||(console.log(m.red(` Invalid --since "${e}". Use "30m", "24h", or "7d".`)),process.exit(1));let t=Number(o[1]),n=o[2];return t*(n==="s"?1e3:n==="m"?6e4:n==="h"?36e5:864e5)}ne.command("ab-test").description("side-by-side comparison: BM25 preload (old) vs agentic query (new) on real task-history messages").option("--dir <path>","wiki directory").option("--agent <id>","which agent to test against (required)").option("--history <path>","task-history root",U(process.cwd(),".agentx/task-history")).option("--n <n>","number of messages to sample (newest first)","10").option("--out <path>","markdown output file (default: stdout)").option("--selector-model <m>","agentic selector model","haiku").option("--synth-model <m>","agentic synthesis model","sonnet").action(async e=>{let{agenticQuery:o}=await import("./query-B32UDQJS.js"),{readdirSync:t,readFileSync:n,existsSync:s}=await import("fs"),{resolve:i,join:r}=await import("path"),a=Oe(e.dir),c=e.agent;if(!c){console.log(m.red(" --agent <id> is required"));return}let l=a.getAgentWiki(c),g=parseInt(e.n),d=i(e.history,c);if(!s(d)){console.log(m.yellow(` no task-history at ${d}`));return}let u=[],f=t(d).sort().reverse();for(let w of f){let b=r(d,w),k=[];try{k=t(b).filter($=>$.endsWith(".json")).sort().reverse()}catch{continue}for(let $ of k){if(u.length>=g)break;try{let E=JSON.parse(n(r(b,$),"utf-8")),S=E.message||E.task?.message;typeof S=="string"&&S.trim().length>10&&u.push({id:E.id||$.replace(".json",""),message:S.trim(),ts:E.at||E.timestamp||w})}catch{}}if(u.length>=g)break}if(u.length===0){console.log(m.yellow(` no task messages found under ${d}`));return}console.log(),console.log(m.bold(` A/B harness \u2014 ${u.length} messages from ${c}`)),console.log(m.dim(" OLD: findRelevant() BM25 over title+tags+content, top 3 truncated")),console.log(m.dim(` NEW: agenticQuery() catalog+wikilink walk (selector=${e.selectorModel}, synth=${e.synthModel})`)),console.log();let p=[`# Wiki A/B: ${c}`,"",`_Generated ${new Date().toISOString()} \xB7 ${u.length} messages sampled_`,"","For each message, the OLD BM25 retrieval (what Layer 10 used to preload) is shown alongside the NEW agentic query's selected articles + synthesized answer. Rate each pair on relevance 0\u20132 in the notes column.",""];for(let w=0;w<u.length;w++){let b=u[w];process.stdout.write(m.dim(` [${w+1}/${u.length}] querying... `));let $=l.findRelevant(b.message,c,3).map(S=>`- **${S.meta.title}** [${S.meta.type||"?"}] (${S.path})`).join(`
470
470
  `)||"_(none returned)_",E;try{let S=await o(b.message,l,c,{selectorModel:e.selectorModel,synthModel:e.synthModel});if(S.status!=="ok")E=`_(status: ${S.status}${S.error?" \u2014 "+S.error:""})_`;else{let v=S.citations.map(x=>`\`${x.title}\` [${x.type||"?"}]`).join(", ");E=`**Answer:**
471
471
 
472
472
  ${S.answer}
@@ -483,7 +483,7 @@ Q: ${_.q}
483
483
  A: ${_.a}`),"","## Existing articles (use [[Title]] wikilinks when referencing these)",k||"(none yet)","","## Output rules","- Output EXACTLY one markdown file: frontmatter (---) + body. No code fences, no preamble.","- Frontmatter fields in this exact order: title, type, related, tags, owner, access, created, last_updated, sources.",' - `title`: "\u2026"',` - \`type\`: ${d}`,' - `related`: ["Article Title", \u2026] (titles that exist in the catalog above; drop if none)'," - `tags`: 2-4 specific tags, lowercase-kebab \u2014 no dates unless type=event",` - \`owner\`: ${e.agent}`," - `access`: public (unless the content is sensitive)",` - \`created\`: ${new Date().toISOString().slice(0,10)}`,` - \`last_updated\`: ${new Date().toISOString().slice(0,10)}`,` - \`sources\`: ["interview-${new Date().toISOString().slice(0,10)}"]`,"- Body: 20-80 lines, Wikipedia-style, organized by theme (not by question), synthesized (not verbatim Q&A).","- Use [[Title]] inline every time you reference something that has an article in the catalog.","- Do NOT invent facts. If the transcript didn't cover something, skip that sub-topic."].join(`
484
484
  `),E=U(a.baseDir,"_tmp");Do(E,{recursive:!0});let S=U(E,`interview-${t().slice(0,8)}.txt`);At(S,$),console.log(),console.log(m.dim(` Synthesizing draft with ${e.model}...`));let v="";try{let _=`cat '${S}' | claude -p - --output-format json --max-turns 1 --model ${e.model} --disallowedTools "Bash Read Write Edit Glob Grep Agent WebSearch WebFetch NotebookEdit"`,$e=Et(_,{env:Nt({...process.env}),encoding:"utf-8",timeout:18e4,maxBuffer:4*1024*1024});try{let ao=JSON.parse($e);v=String(ao.result||ao.content||"")}catch{v=$e}}catch(_){console.log(m.red(` synthesis failed: ${_.message?.slice(0,200)}`)),c?.close();return}v=v.trim();let x=v.match(/```(?:markdown|md)?\s*\n([\s\S]*?)\n```\s*$/);x&&(v=x[1].trim());let R=v.indexOf("---");R>0&&(v=v.slice(R));let I=v.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!I){console.log(m.red(" LLM output is not a valid frontmatter+body article:")),console.log(v.slice(0,600)),c?.close();return}let C={};for(let _ of I[1].split(`
485
485
  `)){let $e=_.match(/^(\w+):\s*(.+)$/);$e&&(C[$e[1]]=$e[2].trim().replace(/^"(.*)"$/,"$1"))}let M=I[2],H=C.title||g,q=H.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60),fe=`${{person:"people",project:"projects",place:"places",concept:"concepts",event:"events",decision:"decisions",pattern:"patterns"}[d]||d+"s"}/${q}.md`;console.log(),console.log(m.bold(" === Draft preview ===")),console.log(m.dim(` Path: ${fe}`)),console.log(),console.log(v),console.log();let G=await l(` ${m.green("save")} / ${m.yellow("edit (opens $EDITOR)")} / ${m.red("scrap")} ? `);if(c?.close(),G==="scrap"||G==="/abort"){console.log(m.dim(" Discarded."));return}if(!e.commit){console.log(m.dim(" --no-commit: not writing.")),console.log(m.dim(` Draft kept at ${S} (prompt only; no article file)`));return}let Ce=M,Se={title:H,type:C.type||d,related:C.related?C.related.replace(/^\[|\]$/g,"").split(",").map(_=>_.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):void 0,tags:C.tags?C.tags.replace(/^\[|\]$/g,"").split(",").map(_=>_.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):[],owner:e.agent,access:C.access||"public",created:C.created||new Date().toISOString().slice(0,10),lastUpdated:C.last_updated||new Date().toISOString().slice(0,10),sources:[`interview-${new Date().toISOString().slice(0,10)}`]};if(G==="edit"){let _=process.env.EDITOR||"vi",$e=U(E,`draft-${t().slice(0,8)}.md`);At($e,v);try{Et(`${_} '${$e}'`,{stdio:"inherit"});let _i=ts($e,"utf-8").match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(_i){let Lo={};for(let Tn of _i[1].split(`
486
- `)){let Di=Tn.match(/^(\w+):\s*(.+)$/);Di&&(Lo[Di[1]]=Di[2].trim().replace(/^"(.*)"$/,"$1"))}Ce=_i[2],Se={...Se,title:Lo.title||Se.title,type:Lo.type||Se.type,access:Lo.access||Se.access,related:Lo.related?Lo.related.replace(/^\[|\]$/g,"").split(",").map(Tn=>Tn.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):Se.related,tags:Lo.tags?Lo.tags.replace(/^\[|\]$/g,"").split(",").map(Tn=>Tn.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):Se.tags}}}catch(ao){console.log(m.red(` editor failed: ${ao.message}`));return}}if(!a.writeArticle(fe,Se,Ce,e.agent)){console.log(m.red(" write failed (permission?)"));return}a.rebuildIndex(),console.log(m.green(` \u2713 ${fe} saved.`));let oo=a.extractWikilinks(Ce),Ee=new Map;for(let _ of a.listArticles(e.agent))Ee.set(_.meta.title.toLowerCase(),!0);let at=oo.filter(_=>!Ee.has(_.toLowerCase()));if(at.length){console.log(),console.log(m.bold(" Gaps referenced but not yet covered:"));for(let _ of at.slice(0,8))console.log(m.dim(` - ${_}`));console.log(m.dim(` Run \`agentx wiki interview --agent ${e.agent} --topic "<title>"\` for any of these.`))}});ne.command("quiz").description("reverse interview \u2014 ask the wiki questions and patch cited articles with corrections, additions, or links").option("--dir <path>","wiki directory").option("--agent <id>","which agent's wiki to quiz (required)").option("--selector-model <m>","candidate-selection model","haiku").option("--synth-model <m>","answer synthesis model","sonnet").option("--patch-model <m>","article patch model","sonnet").option("--rounds <n>","stop after N rounds","20").option("--script <path>","non-interactive: question line + /verdict line per entry, entries separated by blank lines").option("--no-commit","show proposed patches but don't write").option("--out <path>","write a session transcript as markdown").action(async e=>{let o=await import("node:readline/promises"),{randomUUID:t}=await import("node:crypto"),{agenticQuery:n}=await import("./query-GOBQ3GL5.js");if(!e.agent){console.log(m.red(" --agent <id> is required."));return}let s=Oe(e.dir),i;try{i=s.getAgentWiki(e.agent)}catch(f){console.log(m.red(` can't open wiki for agent "${e.agent}": ${f.message}`));return}let r=null;if(e.script){let p=ts(e.script,"utf-8").split(/\n\s*\n/).map(y=>y.trim()).filter(Boolean);r=[];for(let y of p){let w=y.split(/\r?\n/).filter($=>$.trim());if(w.length<2)continue;let b=w[0].replace(/^Q:\s*/i,"").trim(),k=w.slice(1).join(" ").trim();b&&k&&r.push({q:b,verdict:k})}}let a=r?null:o.createInterface({input:process.stdin,output:process.stdout}),c=async f=>a?(await a.question(f)).trim():"",l=Math.min(parseInt(e.rounds)||20,r?.length??999),g=e.commit!==!1;console.log(),console.log(m.bold(" Wiki Quiz")),console.log(m.dim(` Agent: ${e.agent} \xB7 Rounds: ${l} \xB7 ${g?"commit":"dry-run"} \xB7 ${r?`scripted (${r.length})`:"interactive"}`)),console.log(m.dim(" Verdicts: /ok /correct <note> /add <note> /link <url> /skip /done")),console.log();let d=[],u=0;for(let f=0;f<l;f++){let p,y;if(r){let Y=r[f];if(!Y)break;p=Y.q,y=Y.verdict,console.log(m.cyan(` [${f+1}] Q: `)+p)}else{if(p=await c(m.cyan(` [${f+1}] Q: `)),!p||p==="/done"||p==="/abort")break;y=""}process.stdout.write(m.dim(" querying... "));let w;try{w=await n(p,i,e.agent,{selectorModel:e.selectorModel,synthModel:e.synthModel})}catch(Y){console.log(m.red(`failed: ${Y.message?.slice(0,120)}`));continue}if(console.log(m.dim("done")),w.status!=="ok")console.log(m.yellow(` (status: ${w.status}${w.error?" \u2014 "+w.error:""})`));else{let Y=w.citations.map(fe=>`${fe.title} [${fe.type||"?"}]`).join(" \xB7 ");console.log(),console.log(m.dim(" A: ")+w.answer.replace(/\n/g,`
486
+ `)){let Di=Tn.match(/^(\w+):\s*(.+)$/);Di&&(Lo[Di[1]]=Di[2].trim().replace(/^"(.*)"$/,"$1"))}Ce=_i[2],Se={...Se,title:Lo.title||Se.title,type:Lo.type||Se.type,access:Lo.access||Se.access,related:Lo.related?Lo.related.replace(/^\[|\]$/g,"").split(",").map(Tn=>Tn.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):Se.related,tags:Lo.tags?Lo.tags.replace(/^\[|\]$/g,"").split(",").map(Tn=>Tn.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):Se.tags}}}catch(ao){console.log(m.red(` editor failed: ${ao.message}`));return}}if(!a.writeArticle(fe,Se,Ce,e.agent)){console.log(m.red(" write failed (permission?)"));return}a.rebuildIndex(),console.log(m.green(` \u2713 ${fe} saved.`));let oo=a.extractWikilinks(Ce),Ee=new Map;for(let _ of a.listArticles(e.agent))Ee.set(_.meta.title.toLowerCase(),!0);let at=oo.filter(_=>!Ee.has(_.toLowerCase()));if(at.length){console.log(),console.log(m.bold(" Gaps referenced but not yet covered:"));for(let _ of at.slice(0,8))console.log(m.dim(` - ${_}`));console.log(m.dim(` Run \`agentx wiki interview --agent ${e.agent} --topic "<title>"\` for any of these.`))}});ne.command("quiz").description("reverse interview \u2014 ask the wiki questions and patch cited articles with corrections, additions, or links").option("--dir <path>","wiki directory").option("--agent <id>","which agent's wiki to quiz (required)").option("--selector-model <m>","candidate-selection model","haiku").option("--synth-model <m>","answer synthesis model","sonnet").option("--patch-model <m>","article patch model","sonnet").option("--rounds <n>","stop after N rounds","20").option("--script <path>","non-interactive: question line + /verdict line per entry, entries separated by blank lines").option("--no-commit","show proposed patches but don't write").option("--out <path>","write a session transcript as markdown").action(async e=>{let o=await import("node:readline/promises"),{randomUUID:t}=await import("node:crypto"),{agenticQuery:n}=await import("./query-B32UDQJS.js");if(!e.agent){console.log(m.red(" --agent <id> is required."));return}let s=Oe(e.dir),i;try{i=s.getAgentWiki(e.agent)}catch(f){console.log(m.red(` can't open wiki for agent "${e.agent}": ${f.message}`));return}let r=null;if(e.script){let p=ts(e.script,"utf-8").split(/\n\s*\n/).map(y=>y.trim()).filter(Boolean);r=[];for(let y of p){let w=y.split(/\r?\n/).filter($=>$.trim());if(w.length<2)continue;let b=w[0].replace(/^Q:\s*/i,"").trim(),k=w.slice(1).join(" ").trim();b&&k&&r.push({q:b,verdict:k})}}let a=r?null:o.createInterface({input:process.stdin,output:process.stdout}),c=async f=>a?(await a.question(f)).trim():"",l=Math.min(parseInt(e.rounds)||20,r?.length??999),g=e.commit!==!1;console.log(),console.log(m.bold(" Wiki Quiz")),console.log(m.dim(` Agent: ${e.agent} \xB7 Rounds: ${l} \xB7 ${g?"commit":"dry-run"} \xB7 ${r?`scripted (${r.length})`:"interactive"}`)),console.log(m.dim(" Verdicts: /ok /correct <note> /add <note> /link <url> /skip /done")),console.log();let d=[],u=0;for(let f=0;f<l;f++){let p,y;if(r){let Y=r[f];if(!Y)break;p=Y.q,y=Y.verdict,console.log(m.cyan(` [${f+1}] Q: `)+p)}else{if(p=await c(m.cyan(` [${f+1}] Q: `)),!p||p==="/done"||p==="/abort")break;y=""}process.stdout.write(m.dim(" querying... "));let w;try{w=await n(p,i,e.agent,{selectorModel:e.selectorModel,synthModel:e.synthModel})}catch(Y){console.log(m.red(`failed: ${Y.message?.slice(0,120)}`));continue}if(console.log(m.dim("done")),w.status!=="ok")console.log(m.yellow(` (status: ${w.status}${w.error?" \u2014 "+w.error:""})`));else{let Y=w.citations.map(fe=>`${fe.title} [${fe.type||"?"}]`).join(" \xB7 ");console.log(),console.log(m.dim(" A: ")+w.answer.replace(/\n/g,`
487
487
  `)),console.log(m.dim(" citations: "+Y))}r||(y=await c(m.cyan(" verdict > "))),console.log(m.dim(" verdict: ")+y);let b={q:p,answer:w.answer,citations:w.citations,verdict:y},k=y.match(/^(\/ok|\/correct|\/add|\/link|\/skip)(?:\s+(.+))?$/i);if(!k){console.log(m.yellow(" (verdict not recognised \u2014 treating as /skip)")),d.push(b);continue}let $=k[1].toLowerCase(),E=(k[2]||"").trim();if(d.push(b),$==="/ok"||$==="/skip")continue;if(!E){console.log(m.yellow(` ${$} without note \u2014 skipping.`));continue}let S=w.citations[0];if(!S){console.log(m.yellow(" no cited article to patch."));continue}let v=i.readArticle(S.path);if(!v){console.log(m.red(` can't read ${S.path} to patch.`));continue}console.log(m.dim(` patching ${S.title} (${S.path})...`));let x=f$(v.content,$,E,v.meta.title,v.meta.type),R=U(i.baseDir,"_tmp");Do(R,{recursive:!0});let I=U(R,`quiz-patch-${t().slice(0,8)}.txt`);At(I,x);let C="";try{let Y=`cat '${I}' | claude -p - --output-format json --max-turns 1 --model ${e.patchModel} --disallowedTools "Bash Read Write Edit Glob Grep Agent WebSearch WebFetch NotebookEdit"`,fe=Et(Y,{env:Nt({...process.env}),encoding:"utf-8",timeout:12e4,maxBuffer:4*1024*1024});try{let Ce=JSON.parse(fe);C=String(Ce.result||Ce.content||"")}catch{C=fe}let G=C.trim().match(/```(?:markdown|md)?\s*\n([\s\S]*?)\n```\s*$/);G&&(C=G[1].trim()),C=C.trim()}catch(Y){console.log(m.red(` patch failed: ${Y.message?.slice(0,120)}`));continue}if(!C||C.length<20){console.log(m.yellow(" patch returned nothing usable."));continue}let M=v.content.split(`
488
488
  `).length,H=C.split(`
489
489
  `).length;if(console.log(m.dim(` diff: ${M} \u2192 ${H} lines (${H-M>=0?"+":""}${H-M})`)),!g){console.log(m.dim(" (--no-commit: patch not written)")),b.patched=S.path+" (dry)";continue}if(!i.writeArticle(S.path,{...v.meta,lastUpdated:new Date().toISOString().slice(0,10)},C,e.agent)){console.log(m.red(" write failed (permission?)"));continue}u++,b.patched=S.path,console.log(m.green(` \u2713 patched ${S.path}`))}if(a&&a.close(),u>0&&g&&i.rebuildIndex(),console.log(),console.log(m.bold(` Session done: ${d.length} rounds, ${u} patches applied.`)),e.out){let f=[`# Wiki Quiz \u2014 ${e.agent}`,"",`_Generated ${new Date().toISOString()} \xB7 ${d.length} rounds \xB7 ${u} patches_`,""];for(let p=0;p<d.length;p++){let y=d[p];f.push(`## ${p+1}. Q: ${y.q}`,"",`**A:** ${y.answer}`,"",`**Citations:** ${y.citations.map(w=>`\`${w.title}\``).join(", ")||"_(none)_"}`,"",`**Verdict:** \`${y.verdict}\``+(y.patched?` \u2192 patched \`${y.patched}\``:""),"")}At(e.out,f.join(`
@@ -546,7 +546,7 @@ Output (JSON array, one entry per input article, same order):
546
546
  ...
547
547
  ]`}ne.command("entries").description("list raw entries").option("--dir <path>","wiki directory").option("--agent <id>","filter by agent").action(e=>{let n=Oe(e.dir).getSharedStore().listEntries();e.agent&&(n=n.filter(s=>s.agentId===e.agent)),console.log(),console.log(m.bold(` ${n.length} raw entries`)),console.log();for(let s of n.slice(-20))console.log(` ${m.dim(s.date)} ${m.cyan(s.agentId)} via ${s.source}: ${s.content.slice(0,80)}...`);n.length>20&&console.log(m.dim(` ... showing last 20 of ${n.length}`)),console.log()});ne.command("serve").description("start a local web server to browse agent wikis (local + mesh)").option("--dir <path>","wiki directory").option("--mode <mode>","graph (default, canonical) | unified | flat (legacy, back-compat)","graph").option("--agent <id>","serve only this agent's wiki").option("--port <n>","port number","4200").option("--peer <urls...>","mesh peer URLs to federate").action(async e=>{let o=e.dir||U(process.cwd(),".agentx/wiki"),t=parseInt(e.port),n=e.peer||[];if(n.length===0)try{let{loadDaemonConfig:s}=await import("./config-4XGZYYQP.js");n=(s().mesh?.peers||[]).map(r=>r.url)}catch{}console.log(),console.log(m.bold(" AgentX Wiki Server")),console.log(),console.log(` ${m.green(">")} http://localhost:${t}`),e.agent?console.log(` Agent: ${m.cyan(e.agent)}`):console.log(` Mode: ${m.cyan("Hub")} (all agents)`),n.length>0&&console.log(` Mesh: ${m.cyan(n.length+" peer(s)")} \u2014 ${n.join(", ")}`),console.log(m.dim(` Wiki: ${o}`)),console.log(m.dim(" Press Ctrl+C to stop")),console.log(),ud(o,t,e.agent,n,e.mode)});ne.command("grade").description("grade absorbed articles with the article-quality seat").option("--dir <path>","wiki directory").option("--mode <mode>","graph | unified | flat","graph").option("--agent <id>","grade only this agent's wiki").option("--limit <n>","articles to grade","20").option("--min <n>","only show articles scoring below this","3").option("--fields","also check the required fields for each article's type").option("--type <t>","grade only articles of this type (person, place, project, \u2026)").option("--json").action(async e=>{let{articleQualityQuestionsFor:o,articleQualityState:t,gradeArticle:n,ARTICLE_QUALITY_SEAT:s}=await import("./article-quality-JFJMZWFQ.js"),{fieldQuestions:i,reportFields:r}=await import("./article-fields-PITN4NHA.js"),{askSeat:a}=await import("./seat-LK45MTVI.js"),c=Oe(e.dir,e.mode),l=e.agent?[e.agent]:c.listAgents(),g=parseInt(e.limit),d=parseFloat(e.min),u=[];e:for(let w of l){let b=c.getAgentWiki(w);for(let k of b.listArticles(w)){if(u.length>=g)break e;let $=b.readArticle(k.path);if(!$||e.type&&$.meta.type!==e.type)continue;let E={...o($.meta.type),...e.fields?i($.meta.type):{}},S=await a(s,t({path:k.path,title:$.meta.title,type:$.meta.type,tags:$.meta.tags,body:$.content}),E,{links:[{kind:"article",id:k.path}],features:{agent:w,type:$.meta.type??"?"}});if(!S){console.log(m.yellow(" seat is off or unavailable \u2014 set decisions.seats.article-quality.mode"));return}let v=n(S.answers),x=e.fields?r($.meta.type,S.answers):null;v.completeness>=d&&!(x&&!x.fit)||u.push({agent:w,type:$.meta.type??"?",score:v.completeness.toFixed(2),standsAlone:v.standsAlone.toFixed(2),gap:v.biggestGap,...x?{missing:x.missingCritical.join(",")||"-",cov:`${Math.round(x.coverage*100)}%`}:{},title:$.meta.title.slice(0,44)})}}if(e.json){console.log(JSON.stringify(u,null,2));return}if(u.length===0){console.log(m.green(" no articles below the threshold"));return}u.sort((w,b)=>parseFloat(w.score)-parseFloat(b.score));let f=e.fields?["score","cov","missing","type","gap","agent","title"]:["score","standsAlone","type","gap","agent","title"],p=f.map(w=>Math.max(w.length,...u.map(b=>String(b[w]).length))),y=w=>w.map((b,k)=>String(b).padEnd(p[k])).join(" ");console.log(),console.log(m.bold(y(f)));for(let w of u)console.log(y(f.map(b=>w[b])));if(e.fields){let w=u.filter(b=>b.missing!=="-").length;console.log(m.dim(`
548
548
  ${u.length} article(s) flagged; ${w} missing a required field.`)),console.log(m.dim(" 'missing' is the actionable column \u2014 a named field beats a score."))}else console.log(m.dim(`
549
- ${u.length} article(s) below ${d}. standsAlone is the one that matters:`)),console.log(m.dim(" an article can open with a tidy identity line and still send the reader back to the source."))});ne.command("query <question>").description("agentic wiki query \u2014 walks the catalog + wikilink graph, synthesizes an answer").option("--dir <path>","wiki directory").option("--agent <id>","which agent's wiki to query (default: first one with a catalog)").option("--selector-model <m>","candidate-selection model","haiku").option("--synth-model <m>","synthesis model","sonnet").option("--max-candidates <n>","candidates from selector","3").option("--max-hops <n>","wikilink hops from candidates","2").option("--max-articles <n>","cap on total articles walked","8").option("--json","emit full result as JSON (for A/B harnesses)").option("--trace","print selector + walk trace").action(async(e,o)=>{let{agenticQuery:t}=await import("./query-GOBQ3GL5.js"),n=Oe(o.dir),s=o.agent?[o.agent]:n.listAgents(),i=null;for(let c of s){let l=n.getAgentWiki(c),g=U(l.baseDir,"_index.md");try{if((await import("fs")).existsSync(g)){i=c;break}}catch{}}if(!i){console.log(m.yellow(" No agent has a catalog yet. Run `agentx wiki status` or migrate first."));return}let r=n.getAgentWiki(i),a=await t(e,r,i,{selectorModel:o.selectorModel,synthModel:o.synthModel,maxCandidates:parseInt(o.maxCandidates),maxHops:parseInt(o.maxHops),maxArticles:parseInt(o.maxArticles)});if(o.json){console.log(JSON.stringify(a,null,2));return}if(console.log(),console.log(m.bold(` Q: ${e}`)),console.log(m.dim(` agent: ${i} \xB7 status: ${a.status} \xB7 walked: ${a.walked.length}`)),console.log(),a.status!=="ok"){console.log(m.yellow(` (no answer) ${a.error||a.status}`));return}if(console.log(a.answer),console.log(),a.citations.length){console.log(m.dim(" Citations:"));for(let c of a.citations){let l=c.type?m.magenta(` [${c.type}]`):"";console.log(m.dim(` - ${c.title}${l} (${c.path})`))}console.log()}if(o.trace&&a.trace){if(console.log(m.dim(` selector: ${a.trace.selectorMs}ms synthesis: ${a.trace.synthesisMs}ms`)),console.log(m.dim(` candidates: ${a.candidates.map(c=>c.title).join(" | ")||"(none)"}`)),a.walked.length>a.candidates.length){let c=a.walked.filter(l=>!a.candidates.some(g=>g.path===l.path));console.log(m.dim(` followed: ${c.map(l=>`${l.title}@h${l.hop}`).join(" | ")}`))}console.log()}});ne.command("search <query>").description("search wiki articles").option("--dir <path>","wiki directory").option("--mode <mode>","graph (default, canonical) | unified | flat (legacy, back-compat)","graph").option("--agent <id>","search specific agent's wiki").action(async(e,o)=>{let t=Oe(o.dir,o.mode),n=o.agent?[o.agent]:t.listAgents();console.log();let s=0;for(let i of n){let a=await t.getAgentWiki(i).findRelevantReranked(e,void 0,10);if(a.length>0){console.log(m.bold(` ${m.cyan(i)}:`));for(let c of a)console.log(` ${c.meta.title} [${(c.meta.tags||[]).slice(0,3).join(", ")}]`),console.log(m.dim(` ${c.path} \u2014 ${c.content.slice(0,100)}...`));s+=a.length}}s===0&&console.log(m.dim(" No matching articles")),console.log()});ne.command("backfill-graphpath").description("populate graphPath on existing articles by looking up source-entry classifications").option("--dir <path>","wiki directory").option("--agent <id>","backfill only this agent").option("--dry-run","preview without writing",!1).action(e=>{let o=Oe(e.dir),t=e.agent?[e.agent]:o.listAgents(),n=U(process.cwd(),".agentx/graph");if(!to(n)){console.log(m.red(` No graph store at ${n} \u2014 nothing to backfill against.`));return}let s=new Fo({baseDir:n}),i=s.loadIndex(),r=new Map;for(let[d,u]of Object.entries(i.entries))r.set(d,u.path);if(r.size===0){console.log(m.yellow(" Graph index is empty \u2014 nothing to look up."));return}console.log(m.dim(` Loaded ${r.size} fingerprint -> path entries from .agentx/graph/index.json`));let a=0,c=0,l=0,g=0;for(let d of t){let u=o.getAgentWiki(d),f=u.listArticles(d),p=o.getSharedStore().listEntries(),y=new Map(p.map($=>[$.id,$])),w=0,b=0,k=0;for(let $ of f){if(a++,$.meta.graphPath?.length||!$.meta.sources?.length)continue;w++,c++;let E=new Map;for(let v of $.meta.sources){let x=y.get(v);if(!x)continue;let R=String(x.meta?.sender??""),I=s.fingerprint({text:x.content,channel:x.source,sender:R}),C=r.get(I);if(!C?.length)continue;let M=C.join("/"),H=E.get(M);H?H.n++:E.set(M,{path:C,n:1})}if(E.size===0)continue;b++,l++;let S;for(let v of E.values())(!S||v.n>S.n)&&(S=v);S&&(e.dryRun||(u.writeArticle($.path,{...$.meta,graphPath:S.path},$.content,d),k++,g++))}console.log(` ${m.cyan(d)}: ${m.bold(f.length)} articles \xB7 ${w} eligible \xB7 ${b} matched \xB7 ${m.green(k)} written`)}console.log(),console.log(m.bold(` Total: ${a} articles, ${c} missing graphPath, ${l} matched (${Math.round(l/Math.max(1,c)*100)}%), ${g} written`)),e.dryRun&&console.log(m.dim(" Dry-run \u2014 re-run without --dry-run to commit.")),console.log()});ne.command("sync").description("pull raw entries from mesh peers into local wiki").option("--dir <path>","wiki directory").option("--peer <url>","sync from a specific peer URL (e.g., http://100.64.0.11:19900)").option("--dry-run","show what would be synced without writing").action(async e=>{let t=Oe(e.dir).getSharedStore(),n=[];if(e.peer)n=[e.peer];else try{let{loadDaemonConfig:r}=await import("./config-4XGZYYQP.js");n=(r().mesh?.peers||[]).map(c=>c.url)}catch{console.log(m.red(" No --peer specified and no daemon config found")),console.log(m.dim(" Usage: agentx wiki sync --peer http://100.64.0.11:19900"));return}if(n.length===0){console.log(m.dim(" No mesh peers configured"));return}let s=new Set(t.listEntries().map(r=>r.id)),i=0;for(let r of n){console.log(),console.log(m.bold(` Syncing from ${r}...`));try{let a=await fetch(`${r}/wiki/entries`,{signal:AbortSignal.timeout(12e4)});if(!a.ok){console.log(m.red(` HTTP ${a.status}`));continue}let c=await a.json(),l=c.entries||[],g=c.nodeId||"unknown";console.log(m.dim(` Node: ${g} \u2014 ${l.length} entries`));let d=0;for(let u of l)s.has(u.id)||(e.dryRun||(t.addEntry({id:u.id,date:u.date,agentId:u.agentId,source:`${u.source}@${g}`,sourceContext:u.sourceContext,content:u.content}),s.add(u.id)),d++);d>0?console.log(m.green(` ${d} new entries${e.dryRun?" (dry run)":" synced"}`)):console.log(m.dim(" Already up to date")),i+=d;try{let u=await fetch(`${r}/wiki/agents`,{signal:AbortSignal.timeout(5e3)});if(u.ok){let f=await u.json();for(let p of f.agents||[])p.totalEntries>0&&console.log(m.dim(` ${p.agentId}: ${p.totalEntries} entries, ${p.totalArticles} articles`))}}catch{}}catch(a){a.cause?.code==="ECONNREFUSED"?console.log(m.red(" Connection refused")):console.log(m.red(` ${a.message}`))}}console.log(),i>0&&!e.dryRun?console.log(m.green(` ${i} entries synced.`)):i>0?console.log(m.dim(` ${i} entries would be synced (dry run)`)):console.log(m.dim(" All peers up to date")),console.log()});ne.command("compare").description("compare all wiki compilation modes for an agent").option("--dir <path>","wiki directory").requiredOption("--agent <id>","agent to compare").action(e=>{let o=e.dir||U(process.cwd(),".agentx/wiki"),t=e.agent,s=["flat","graph","unified"].map(c=>{let l=new qi(o,void 0,c),d=l.getAgentWiki(t).rebuildIndex(),u=l.getAgentEntries(t),f=l.getUnabsorbedEntries(t),p=new Set,y=0,w=new Set;for(let k of d.articles){for(let $ of k.tags||[])p.add($);y+=k.tags?.length||0;for(let $ of k.sources||[])w.add($)}let b=new Set(d.articles.map(k=>k.path.includes("/")?k.path.split("/")[0]:"/"));return{mode:c,label:aa(c),articles:d.articles.length,entries:u.length,unabsorbed:f.length,uniqueTags:p.size,avgTags:d.articles.length>0?(y/d.articles.length).toFixed(1):"0",dirs:b.size,coverage:w.size,articleList:d.articles}});console.log(),console.log(m.bold(` Wiki Compare: ${t}`)),console.log(` Raw entries: ${s[0].entries}`),console.log();let i=22;console.log(` ${"".padEnd(20)} ${s.map(c=>c.label.padEnd(i)).join(" ")}`),console.log(` ${"\u2500".repeat(20)} ${s.map(()=>"\u2500".repeat(i)).join(" ")}`);let r=[["Articles",c=>String(c.articles)],["Unabsorbed",c=>String(c.unabsorbed)],["Unique tags",c=>String(c.uniqueTags)],["Avg tags/article",c=>c.avgTags],["Directories",c=>String(c.dirs)],["Entry coverage",c=>`${c.coverage}/${c.entries}`]];for(let[c,l]of r){let g=s.map(d=>l(d).padEnd(i));console.log(` ${c.padEnd(20)} ${g.join(" ")}`)}console.log();let a=(c,l)=>{let g=Math.max(...s.map(u=>u[c])),d=s.filter(u=>u[c]===g).map(u=>u.label);g>0&&console.log(m.dim(` Best ${l}: ${d.join(", ")} (${g})`))};a("uniqueTags","tag richness"),a("articles","article count"),a("coverage","entry coverage"),console.log()});ne.command("export [output]").description("export the entire wiki tree to a .tar.gz").option("--dir <path>","wiki directory to archive (default: .agentx/wiki)").option("--include-raw","also include raw entries (.agentx/wiki/raw/) \u2014 bigger archive").action(async(e,o)=>{let t=o.dir?U(process.cwd(),o.dir):U(process.cwd(),".agentx/wiki");to(t)||(console.log(m.red(` Wiki dir not found: ${t}`)),process.exit(1));let n=new Date().toISOString().slice(0,10),s=e?U(process.cwd(),e):U(process.cwd(),`agentx-wiki-${n}.tar.gz`),i=U(t,".."),r=t.split("/").pop()||"wiki",a=["-C",i,"-czf",s];o.includeRaw||a.push("--exclude="+r+"/raw"),a.push(r),console.log(m.dim(` tar ${a.join(" ")}`));let{spawnSync:c}=await import("child_process"),l=c("tar",a,{stdio:"inherit"});l.status!==0&&(console.log(m.red(` tar exited with ${l.status}`)),process.exit(l.status||1));let{statSync:g}=await import("fs"),d=to(s)?g(s).size:0;console.log(),console.log(m.green(` \u2713 wrote ${s} (${w$(d)})`)),console.log(m.dim(` Restore on another node: agentx wiki import ${s}`)),console.log()});ne.command("gaps").description("what each article still needs, most load-bearing first").option("--dir <path>","wiki directory").option("--mode <mode>","graph | unified | flat","graph").option("--agent <id>","only this agent's wiki").option("--type <t>","only articles of this type").option("--max-tier <tier>","stop at this layer: foundation|pillar|walls|openings|furniture","pillar").option("--limit <n>","articles to check","40").option("--auto","only gaps a system of record can close without asking anyone").option("--ask","queue the gaps that need a person onto the questions list").option("--notify","push the load-bearing ones to notifications.destination").option("--notify-tier <tier>","tier at or above which to push","pillar").option("--unclear","include fields the grader was unsure about").option("--json").action(async e=>{let{fieldQuestions:o,reportFields:t,articleFieldsState:n,nextActions:s,TIER_MEANING:i,ARTICLE_FIELDS_SEAT:r}=await import("./article-fields-PITN4NHA.js"),{askSeat:a}=await import("./seat-LK45MTVI.js"),{QuestionStore:c}=await import("./questions-ZATLU5AW.js"),l=Oe(e.dir,e.mode),g=[],d=e.agent?[e.agent]:l.listAgents(),u=parseInt(e.limit),f=0,p=[];e:for(let v of d){let x=l.getAgentWiki(v);for(let R of x.listArticles(v)){if(f>=u)break e;let I=x.readArticle(R.path);if(!I||e.type&&I.meta.type!==e.type)continue;f++;let C=await a(r,n({title:I.meta.title,type:I.meta.type,body:I.content}),o(I.meta.type),{links:[{kind:"article",id:R.path}],features:{agent:v,type:I.meta.type??"?"}});if(!C){console.log(m.yellow(" seat is off or unavailable \u2014 set decisions.seats.article-fields.mode"));return}let M=t(I.meta.type,C.answers);for(let H of s(M,{maxTier:e.maxTier,includeUnclear:!!e.unclear}))e.auto&&H.needsHuman||(e.ask&&H.needsHuman&&g.push({kind:"field",agentId:v,path:R.path,subject:I.meta.title,field:H.field,tier:H.tier,question:`${I.meta.title} (${I.meta.type??"?"}) \u2014 ${H.label}?`}),p.push({tier:H.tier,need:H.field,how:H.needsHuman?m.yellow("ask"):H.sources.join("/"),uncertain:H.uncertain?"?":"",agent:v,article:I.meta.title.slice(0,40)}))}}let y={added:0,skipped:0};if(e.ask&&g.length>0&&(y=new c(Tt(e.dir)).add(g)),e.json){console.log(JSON.stringify(p,null,2));return}if(p.length===0){console.log(m.green(` ${f} article(s) checked \u2014 nothing missing at or above ${e.maxTier}`));return}let w=["tier","need","how","uncertain","agent","article"],b=v=>String(v).replace(/\u001b\[[0-9;]*m/g,""),k=w.map(v=>Math.max(v.length,...p.map(x=>b(x[v]).length))),$=(v,x)=>String(v)+" ".repeat(Math.max(0,k[x]-b(v).length));console.log(),console.log(m.bold(w.map((v,x)=>$(v,x)).join(" ")));for(let v of p)console.log(w.map((x,R)=>$(v[x],R)).join(" "));let E=p.filter(v=>v.how!==m.yellow("ask")).length;console.log(),console.log(m.dim(` ${p.length} gap(s) across ${f} article(s).`)),console.log(m.dim(` ${E} can be closed by a lookup; ${p.length-E} need a person.`));let S=p[0]?.tier;if(S&&console.log(m.dim(` Start at ${S} \u2014 ${i[S]}.`)),e.ask&&(console.log(m.cyan(` Queued ${y.added} question(s) for a person (${y.skipped} already asked).`)),console.log(m.dim(' agentx wiki questions \xB7 agentx wiki answer <id> "<value>"'))),e.ask&&e.notify&&y.added>0){let{TIER_RANK:v}=await import("./article-fields-PITN4NHA.js"),x=v[e.notifyTier]??v.pillar,R=g.filter(I=>(v[I.tier??"furniture"]??9)<=x);if(R.length===0)console.log(m.dim(` Nothing at or above ${e.notifyTier} \u2014 not interrupting anyone.`));else{let{loadDaemonConfig:I}=await import("./config-4XGZYYQP.js"),C=I(),M=C?.notifications?.destination;if(!M?.channel||!M?.chatId)console.log(m.yellow(" --notify: no notifications.destination configured \u2014 questions are queued but nobody was told."));else{let H=R.slice(0,10).map(G=>`\u2022 ${G.question}`).join(`
549
+ ${u.length} article(s) below ${d}. standsAlone is the one that matters:`)),console.log(m.dim(" an article can open with a tidy identity line and still send the reader back to the source."))});ne.command("query <question>").description("agentic wiki query \u2014 walks the catalog + wikilink graph, synthesizes an answer").option("--dir <path>","wiki directory").option("--agent <id>","which agent's wiki to query (default: first one with a catalog)").option("--selector-model <m>","candidate-selection model","haiku").option("--synth-model <m>","synthesis model","sonnet").option("--max-candidates <n>","candidates from selector","3").option("--max-hops <n>","wikilink hops from candidates","2").option("--max-articles <n>","cap on total articles walked","8").option("--json","emit full result as JSON (for A/B harnesses)").option("--trace","print selector + walk trace").action(async(e,o)=>{let{agenticQuery:t}=await import("./query-B32UDQJS.js"),n=Oe(o.dir),s=o.agent?[o.agent]:n.listAgents(),i=null;for(let c of s){let l=n.getAgentWiki(c),g=U(l.baseDir,"_index.md");try{if((await import("fs")).existsSync(g)){i=c;break}}catch{}}if(!i){console.log(m.yellow(" No agent has a catalog yet. Run `agentx wiki status` or migrate first."));return}let r=n.getAgentWiki(i),a=await t(e,r,i,{selectorModel:o.selectorModel,synthModel:o.synthModel,maxCandidates:parseInt(o.maxCandidates),maxHops:parseInt(o.maxHops),maxArticles:parseInt(o.maxArticles)});if(o.json){console.log(JSON.stringify(a,null,2));return}if(console.log(),console.log(m.bold(` Q: ${e}`)),console.log(m.dim(` agent: ${i} \xB7 status: ${a.status} \xB7 walked: ${a.walked.length}`)),console.log(),a.status!=="ok"){console.log(m.yellow(` (no answer) ${a.error||a.status}`));return}if(console.log(a.answer),console.log(),a.citations.length){console.log(m.dim(" Citations:"));for(let c of a.citations){let l=c.type?m.magenta(` [${c.type}]`):"";console.log(m.dim(` - ${c.title}${l} (${c.path})`))}console.log()}if(o.trace&&a.trace){if(console.log(m.dim(` selector: ${a.trace.selectorMs}ms synthesis: ${a.trace.synthesisMs}ms`)),console.log(m.dim(` candidates: ${a.candidates.map(c=>c.title).join(" | ")||"(none)"}`)),a.walked.length>a.candidates.length){let c=a.walked.filter(l=>!a.candidates.some(g=>g.path===l.path));console.log(m.dim(` followed: ${c.map(l=>`${l.title}@h${l.hop}`).join(" | ")}`))}console.log()}});ne.command("search <query>").description("search wiki articles").option("--dir <path>","wiki directory").option("--mode <mode>","graph (default, canonical) | unified | flat (legacy, back-compat)","graph").option("--agent <id>","search specific agent's wiki").action(async(e,o)=>{let t=Oe(o.dir,o.mode),n=o.agent?[o.agent]:t.listAgents();console.log();let s=0;for(let i of n){let a=await t.getAgentWiki(i).findRelevantReranked(e,void 0,10);if(a.length>0){console.log(m.bold(` ${m.cyan(i)}:`));for(let c of a)console.log(` ${c.meta.title} [${(c.meta.tags||[]).slice(0,3).join(", ")}]`),console.log(m.dim(` ${c.path} \u2014 ${c.content.slice(0,100)}...`));s+=a.length}}s===0&&console.log(m.dim(" No matching articles")),console.log()});ne.command("backfill-graphpath").description("populate graphPath on existing articles by looking up source-entry classifications").option("--dir <path>","wiki directory").option("--agent <id>","backfill only this agent").option("--dry-run","preview without writing",!1).action(e=>{let o=Oe(e.dir),t=e.agent?[e.agent]:o.listAgents(),n=U(process.cwd(),".agentx/graph");if(!to(n)){console.log(m.red(` No graph store at ${n} \u2014 nothing to backfill against.`));return}let s=new Fo({baseDir:n}),i=s.loadIndex(),r=new Map;for(let[d,u]of Object.entries(i.entries))r.set(d,u.path);if(r.size===0){console.log(m.yellow(" Graph index is empty \u2014 nothing to look up."));return}console.log(m.dim(` Loaded ${r.size} fingerprint -> path entries from .agentx/graph/index.json`));let a=0,c=0,l=0,g=0;for(let d of t){let u=o.getAgentWiki(d),f=u.listArticles(d),p=o.getSharedStore().listEntries(),y=new Map(p.map($=>[$.id,$])),w=0,b=0,k=0;for(let $ of f){if(a++,$.meta.graphPath?.length||!$.meta.sources?.length)continue;w++,c++;let E=new Map;for(let v of $.meta.sources){let x=y.get(v);if(!x)continue;let R=String(x.meta?.sender??""),I=s.fingerprint({text:x.content,channel:x.source,sender:R}),C=r.get(I);if(!C?.length)continue;let M=C.join("/"),H=E.get(M);H?H.n++:E.set(M,{path:C,n:1})}if(E.size===0)continue;b++,l++;let S;for(let v of E.values())(!S||v.n>S.n)&&(S=v);S&&(e.dryRun||(u.writeArticle($.path,{...$.meta,graphPath:S.path},$.content,d),k++,g++))}console.log(` ${m.cyan(d)}: ${m.bold(f.length)} articles \xB7 ${w} eligible \xB7 ${b} matched \xB7 ${m.green(k)} written`)}console.log(),console.log(m.bold(` Total: ${a} articles, ${c} missing graphPath, ${l} matched (${Math.round(l/Math.max(1,c)*100)}%), ${g} written`)),e.dryRun&&console.log(m.dim(" Dry-run \u2014 re-run without --dry-run to commit.")),console.log()});ne.command("sync").description("pull raw entries from mesh peers into local wiki").option("--dir <path>","wiki directory").option("--peer <url>","sync from a specific peer URL (e.g., http://100.64.0.11:19900)").option("--dry-run","show what would be synced without writing").action(async e=>{let t=Oe(e.dir).getSharedStore(),n=[];if(e.peer)n=[e.peer];else try{let{loadDaemonConfig:r}=await import("./config-4XGZYYQP.js");n=(r().mesh?.peers||[]).map(c=>c.url)}catch{console.log(m.red(" No --peer specified and no daemon config found")),console.log(m.dim(" Usage: agentx wiki sync --peer http://100.64.0.11:19900"));return}if(n.length===0){console.log(m.dim(" No mesh peers configured"));return}let s=new Set(t.listEntries().map(r=>r.id)),i=0;for(let r of n){console.log(),console.log(m.bold(` Syncing from ${r}...`));try{let a=await fetch(`${r}/wiki/entries`,{signal:AbortSignal.timeout(12e4)});if(!a.ok){console.log(m.red(` HTTP ${a.status}`));continue}let c=await a.json(),l=c.entries||[],g=c.nodeId||"unknown";console.log(m.dim(` Node: ${g} \u2014 ${l.length} entries`));let d=0;for(let u of l)s.has(u.id)||(e.dryRun||(t.addEntry({id:u.id,date:u.date,agentId:u.agentId,source:`${u.source}@${g}`,sourceContext:u.sourceContext,content:u.content}),s.add(u.id)),d++);d>0?console.log(m.green(` ${d} new entries${e.dryRun?" (dry run)":" synced"}`)):console.log(m.dim(" Already up to date")),i+=d;try{let u=await fetch(`${r}/wiki/agents`,{signal:AbortSignal.timeout(5e3)});if(u.ok){let f=await u.json();for(let p of f.agents||[])p.totalEntries>0&&console.log(m.dim(` ${p.agentId}: ${p.totalEntries} entries, ${p.totalArticles} articles`))}}catch{}}catch(a){a.cause?.code==="ECONNREFUSED"?console.log(m.red(" Connection refused")):console.log(m.red(` ${a.message}`))}}console.log(),i>0&&!e.dryRun?console.log(m.green(` ${i} entries synced.`)):i>0?console.log(m.dim(` ${i} entries would be synced (dry run)`)):console.log(m.dim(" All peers up to date")),console.log()});ne.command("compare").description("compare all wiki compilation modes for an agent").option("--dir <path>","wiki directory").requiredOption("--agent <id>","agent to compare").action(e=>{let o=e.dir||U(process.cwd(),".agentx/wiki"),t=e.agent,s=["flat","graph","unified"].map(c=>{let l=new qi(o,void 0,c),d=l.getAgentWiki(t).rebuildIndex(),u=l.getAgentEntries(t),f=l.getUnabsorbedEntries(t),p=new Set,y=0,w=new Set;for(let k of d.articles){for(let $ of k.tags||[])p.add($);y+=k.tags?.length||0;for(let $ of k.sources||[])w.add($)}let b=new Set(d.articles.map(k=>k.path.includes("/")?k.path.split("/")[0]:"/"));return{mode:c,label:aa(c),articles:d.articles.length,entries:u.length,unabsorbed:f.length,uniqueTags:p.size,avgTags:d.articles.length>0?(y/d.articles.length).toFixed(1):"0",dirs:b.size,coverage:w.size,articleList:d.articles}});console.log(),console.log(m.bold(` Wiki Compare: ${t}`)),console.log(` Raw entries: ${s[0].entries}`),console.log();let i=22;console.log(` ${"".padEnd(20)} ${s.map(c=>c.label.padEnd(i)).join(" ")}`),console.log(` ${"\u2500".repeat(20)} ${s.map(()=>"\u2500".repeat(i)).join(" ")}`);let r=[["Articles",c=>String(c.articles)],["Unabsorbed",c=>String(c.unabsorbed)],["Unique tags",c=>String(c.uniqueTags)],["Avg tags/article",c=>c.avgTags],["Directories",c=>String(c.dirs)],["Entry coverage",c=>`${c.coverage}/${c.entries}`]];for(let[c,l]of r){let g=s.map(d=>l(d).padEnd(i));console.log(` ${c.padEnd(20)} ${g.join(" ")}`)}console.log();let a=(c,l)=>{let g=Math.max(...s.map(u=>u[c])),d=s.filter(u=>u[c]===g).map(u=>u.label);g>0&&console.log(m.dim(` Best ${l}: ${d.join(", ")} (${g})`))};a("uniqueTags","tag richness"),a("articles","article count"),a("coverage","entry coverage"),console.log()});ne.command("export [output]").description("export the entire wiki tree to a .tar.gz").option("--dir <path>","wiki directory to archive (default: .agentx/wiki)").option("--include-raw","also include raw entries (.agentx/wiki/raw/) \u2014 bigger archive").action(async(e,o)=>{let t=o.dir?U(process.cwd(),o.dir):U(process.cwd(),".agentx/wiki");to(t)||(console.log(m.red(` Wiki dir not found: ${t}`)),process.exit(1));let n=new Date().toISOString().slice(0,10),s=e?U(process.cwd(),e):U(process.cwd(),`agentx-wiki-${n}.tar.gz`),i=U(t,".."),r=t.split("/").pop()||"wiki",a=["-C",i,"-czf",s];o.includeRaw||a.push("--exclude="+r+"/raw"),a.push(r),console.log(m.dim(` tar ${a.join(" ")}`));let{spawnSync:c}=await import("child_process"),l=c("tar",a,{stdio:"inherit"});l.status!==0&&(console.log(m.red(` tar exited with ${l.status}`)),process.exit(l.status||1));let{statSync:g}=await import("fs"),d=to(s)?g(s).size:0;console.log(),console.log(m.green(` \u2713 wrote ${s} (${w$(d)})`)),console.log(m.dim(` Restore on another node: agentx wiki import ${s}`)),console.log()});ne.command("gaps").description("what each article still needs, most load-bearing first").option("--dir <path>","wiki directory").option("--mode <mode>","graph | unified | flat","graph").option("--agent <id>","only this agent's wiki").option("--type <t>","only articles of this type").option("--max-tier <tier>","stop at this layer: foundation|pillar|walls|openings|furniture","pillar").option("--limit <n>","articles to check","40").option("--auto","only gaps a system of record can close without asking anyone").option("--ask","queue the gaps that need a person onto the questions list").option("--notify","push the load-bearing ones to notifications.destination").option("--notify-tier <tier>","tier at or above which to push","pillar").option("--unclear","include fields the grader was unsure about").option("--json").action(async e=>{let{fieldQuestions:o,reportFields:t,articleFieldsState:n,nextActions:s,TIER_MEANING:i,ARTICLE_FIELDS_SEAT:r}=await import("./article-fields-PITN4NHA.js"),{askSeat:a}=await import("./seat-LK45MTVI.js"),{QuestionStore:c}=await import("./questions-ZATLU5AW.js"),l=Oe(e.dir,e.mode),g=[],d=e.agent?[e.agent]:l.listAgents(),u=parseInt(e.limit),f=0,p=[];e:for(let v of d){let x=l.getAgentWiki(v);for(let R of x.listArticles(v)){if(f>=u)break e;let I=x.readArticle(R.path);if(!I||e.type&&I.meta.type!==e.type)continue;f++;let C=await a(r,n({title:I.meta.title,type:I.meta.type,body:I.content}),o(I.meta.type),{links:[{kind:"article",id:R.path}],features:{agent:v,type:I.meta.type??"?"}});if(!C){console.log(m.yellow(" seat is off or unavailable \u2014 set decisions.seats.article-fields.mode"));return}let M=t(I.meta.type,C.answers);for(let H of s(M,{maxTier:e.maxTier,includeUnclear:!!e.unclear}))e.auto&&H.needsHuman||(e.ask&&H.needsHuman&&g.push({kind:"field",agentId:v,path:R.path,subject:I.meta.title,field:H.field,tier:H.tier,question:`${I.meta.title} (${I.meta.type??"?"}) \u2014 ${H.label}?`}),p.push({tier:H.tier,need:H.field,how:H.needsHuman?m.yellow("ask"):H.sources.join("/"),uncertain:H.uncertain?"?":"",agent:v,article:I.meta.title.slice(0,40)}))}}let y={added:0,skipped:0};if(e.ask&&g.length>0&&(y=new c(Tt(e.dir)).add(g)),e.json){console.log(JSON.stringify(p,null,2));return}if(p.length===0){console.log(m.green(` ${f} article(s) checked \u2014 nothing missing at or above ${e.maxTier}`));return}let w=["tier","need","how","uncertain","agent","article"],b=v=>String(v).replace(/\u001b\[[0-9;]*m/g,""),k=w.map(v=>Math.max(v.length,...p.map(x=>b(x[v]).length))),$=(v,x)=>String(v)+" ".repeat(Math.max(0,k[x]-b(v).length));console.log(),console.log(m.bold(w.map((v,x)=>$(v,x)).join(" ")));for(let v of p)console.log(w.map((x,R)=>$(v[x],R)).join(" "));let E=p.filter(v=>v.how!==m.yellow("ask")).length;console.log(),console.log(m.dim(` ${p.length} gap(s) across ${f} article(s).`)),console.log(m.dim(` ${E} can be closed by a lookup; ${p.length-E} need a person.`));let S=p[0]?.tier;if(S&&console.log(m.dim(` Start at ${S} \u2014 ${i[S]}.`)),e.ask&&(console.log(m.cyan(` Queued ${y.added} question(s) for a person (${y.skipped} already asked).`)),console.log(m.dim(' agentx wiki questions \xB7 agentx wiki answer <id> "<value>"'))),e.ask&&e.notify&&y.added>0){let{TIER_RANK:v}=await import("./article-fields-PITN4NHA.js"),x=v[e.notifyTier]??v.pillar,R=g.filter(I=>(v[I.tier??"furniture"]??9)<=x);if(R.length===0)console.log(m.dim(` Nothing at or above ${e.notifyTier} \u2014 not interrupting anyone.`));else{let{loadDaemonConfig:I}=await import("./config-4XGZYYQP.js"),C=I(),M=C?.notifications?.destination;if(!M?.channel||!M?.chatId)console.log(m.yellow(" --notify: no notifications.destination configured \u2014 questions are queued but nobody was told."));else{let H=R.slice(0,10).map(G=>`\u2022 ${G.question}`).join(`
550
550
  `),q=R.length>10?`
551
551
  \u2026and ${R.length-10} more`:"",Y=`${R.length} wiki gap(s) need you (${e.notifyTier}+):
552
552
  ${H}${q}
@@ -680,7 +680,7 @@ Restart the daemon to activate.
680
680
  dist/
681
681
  *.log
682
682
  .env
683
- `}import{Command as Qb}from"commander";import Pe from"chalk";import{writeFileSync as Zb,mkdirSync as ek,existsSync as Ii,readFileSync as Bp,appendFileSync as Jp}from"fs";import{resolve as Sn,dirname as zp}from"path";import{homedir as ja}from"os";var Yp=new Qb().name("completion").description("generate a shell completion script for agentx").option("-s, --shell <shell>","shell to generate completion for: zsh|bash|fish","zsh").option("-i, --install","install the completion script to a default path for the shell").option("-o, --output <path>","write the script to this path (overrides default install path)").option("-y, --yes","skip confirmation prompts (non-interactive)").action(async e=>{let{buildProgram:o}=await import("./program-IEMICVO3.js"),t=await o(),n=String(e.shell||"zsh").toLowerCase(),s;switch(n){case"zsh":s=nk(t);break;case"bash":s=ck(t);break;case"fish":s=lk(t);break;default:console.error(Pe.red(`unsupported shell: ${n}`)),console.error(Pe.dim("supported: zsh, bash, fish")),process.exit(1)}if(!e.install&&!e.output){process.stdout.write(s);return}let i=e.output?Sn(String(e.output)):ok(n);ek(zp(i),{recursive:!0}),Zb(i,s),console.log(Pe.green(`\u2713 Wrote ${n} completion to:`)),console.log(` ${i}`),console.log(),tk(n,i,!!e.yes)});function ok(e){let o=ja();switch(e){case"zsh":return Sn(o,".zsh","completions","_agentx");case"bash":return Sn(o,".bash_completion.d","agentx.bash");case"fish":return Sn(o,".config","fish","completions","agentx.fish");default:throw new Error(`unsupported shell: ${e}`)}}function tk(e,o,t){if(e==="zsh"){let n=Sn(ja(),".zshrc"),s=zp(o),i=`fpath=(${s} $fpath)`,r="autoload -U compinit && compinit",a=Ii(n)?Bp(n,"utf-8"):"",c=!a.includes(s),l=!/autoload\s+-U\s+compinit/.test(a);if(!c&&!l){console.log(Pe.dim("~/.zshrc already has fpath + compinit wired up. Run `exec zsh` to pick up the new script."));return}if(t&&Ii(n)){let g=["","# agentx completion"];c&&g.push(i),l&&g.push(r),Jp(n,g.join(`
683
+ `}import{Command as Qb}from"commander";import Pe from"chalk";import{writeFileSync as Zb,mkdirSync as ek,existsSync as Ii,readFileSync as Bp,appendFileSync as Jp}from"fs";import{resolve as Sn,dirname as zp}from"path";import{homedir as ja}from"os";var Yp=new Qb().name("completion").description("generate a shell completion script for agentx").option("-s, --shell <shell>","shell to generate completion for: zsh|bash|fish","zsh").option("-i, --install","install the completion script to a default path for the shell").option("-o, --output <path>","write the script to this path (overrides default install path)").option("-y, --yes","skip confirmation prompts (non-interactive)").action(async e=>{let{buildProgram:o}=await import("./program-4IMJEMDM.js"),t=await o(),n=String(e.shell||"zsh").toLowerCase(),s;switch(n){case"zsh":s=nk(t);break;case"bash":s=ck(t);break;case"fish":s=lk(t);break;default:console.error(Pe.red(`unsupported shell: ${n}`)),console.error(Pe.dim("supported: zsh, bash, fish")),process.exit(1)}if(!e.install&&!e.output){process.stdout.write(s);return}let i=e.output?Sn(String(e.output)):ok(n);ek(zp(i),{recursive:!0}),Zb(i,s),console.log(Pe.green(`\u2713 Wrote ${n} completion to:`)),console.log(` ${i}`),console.log(),tk(n,i,!!e.yes)});function ok(e){let o=ja();switch(e){case"zsh":return Sn(o,".zsh","completions","_agentx");case"bash":return Sn(o,".bash_completion.d","agentx.bash");case"fish":return Sn(o,".config","fish","completions","agentx.fish");default:throw new Error(`unsupported shell: ${e}`)}}function tk(e,o,t){if(e==="zsh"){let n=Sn(ja(),".zshrc"),s=zp(o),i=`fpath=(${s} $fpath)`,r="autoload -U compinit && compinit",a=Ii(n)?Bp(n,"utf-8"):"",c=!a.includes(s),l=!/autoload\s+-U\s+compinit/.test(a);if(!c&&!l){console.log(Pe.dim("~/.zshrc already has fpath + compinit wired up. Run `exec zsh` to pick up the new script."));return}if(t&&Ii(n)){let g=["","# agentx completion"];c&&g.push(i),l&&g.push(r),Jp(n,g.join(`
684
684
  `)+`
685
685
  `),console.log(Pe.green("\u2713 Patched ~/.zshrc")),console.log(Pe.dim("Reload your shell: exec zsh"));return}console.log(Pe.dim("Add this to ~/.zshrc if not already present:")),c&&console.log(Pe.cyan(` ${i}`)),l&&console.log(Pe.cyan(` ${r}`)),console.log(),console.log(Pe.dim("Then reload: exec zsh")),console.log(Pe.dim("Or rerun with --yes to auto-patch ~/.zshrc"));return}if(e==="bash"){let n=Sn(ja(),".bashrc"),s=`[ -f "${o}" ] && source "${o}"`;if((Ii(n)?Bp(n,"utf-8"):"").includes(o)){console.log(Pe.dim("~/.bashrc already sources this file. Start a new shell to pick it up."));return}if(t&&Ii(n)){Jp(n,`
686
686
  # agentx completion
@@ -696,4 +696,4 @@ ${dk({...o,category:e.category})}`),g&&a.set(l.id,g)}let c=`https://github.com/$
696
696
  ${t.url}`)}catch(o){console.error(An.red(` ${o.message}`)),process.exitCode=1}});ms.command("draft <file>").description("turn a draft JSON file ({category, title, fields}) into a pre-filled issue form link; '-' reads stdin").requiredOption("--model <model>","the model that wrote the draft").option("--models <pathOrUrl>","model list to read",Ca).action(async(e,o)=>{try{let t=await Ra(o.models);if(!Ia(o.model,t)){console.log(Na(o.model,t)),process.exitCode=1;return}let n=e==="-"?await pk():await mk(e,"utf8"),s=JSON.parse(n),{version:i}=await $s(),r=Qp({...s,fields:s.fields??{}},{model:o.model,version:i??"unknown"});console.log(r)}catch(t){console.error(An.red(` ${t.message}`)),process.exitCode=1}});async function pk(){let e=[];for await(let o of process.stdin)e.push(o);return Buffer.concat(e).toString("utf8")}async function YI(){let e=await $s(),o=new uk().name("agentx").description("self-hosted multi-agent orchestrator \u2014 Telegram, WhatsApp, crons, A2A mesh, wiki knowledge").version(e.version||"1.0.0","-v, --version","display the version number");o.hook("preAction",(t,n)=>{let s=gd(n);md(s)&&dd("cli",s)});for(let t of[Wd,Ud,gn,Jt,zt,lo,Ql,mt,Hs,No,_o,cn,Lm,ot,Js,vp,Ko,mg,pg,vg,Xn,Rg,Mg,dg,Fg,Ug,sm,cm,lm,ro,St,Tp,Un,Go,Yp,ms])o.addCommand(t);for(let t of eu)o.addCommand(t,{hidden:!0});return o.addHelpText("after",()=>{let t=eu.map(n=>n.name()).sort();return["",`Advanced (${t.length}, hidden \u2014 run \`agentx <command> --help\` for any of them):`,fk(t,74," "),""].join(`
697
697
  `)}),o}var eu=[ne,un,it,bo,Jn,sn,Ze,Po,tt,vt,wn,$n,Vo,ze,Kt,di,$p,bp,Io,io,yd,ut,ds,vr,st,Qe,Vt,xr,Si,To,Mo,Mp,Lp,Ap];function fk(e,o,t){let n=[],s="";for(let i of e)s&&s.length+i.length+2>o&&(n.push(t+s),s=""),s+=(s?", ":"")+i;return s&&n.push(t+s),n.join(`
698
698
  `)}export{YI as buildProgram};
699
- //# sourceMappingURL=program-IEMICVO3.js.map
699
+ //# sourceMappingURL=program-4IMJEMDM.js.map
@@ -1,2 +1,2 @@
1
- import{b as a,c as b,d as c,e as d,f as e,g as f,h as g,i as h,j as i,k as j,l as k,m as l,n as m,o as n,p as o,q as p,r as q,s as r,t as s,u as t}from"./chunk-4COYYJJY.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import"./chunk-6W74CHNW.js";import"./chunk-XX7NXI3Y.js";import"./chunk-CECHWYJ2.js";import"./chunk-ILGLEA3I.js";import"./chunk-WPNRDEHW.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-Y5HBYSJW.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{b as DEFAULT_PROMOTE_TYPES,a as PROMOTER_OWNER,c as PROMOTION_LEDGER_FILE,j as appendPromotionLedger,s as approveProposal,n as callPromotionLlm,p as estimateTokens,r as evidenceFor,m as getUnpromotedMemories,k as groupCandidates,h as listAllAgentMemories,d as memoryKey,e as memoryStamp,g as mergeSources,f as parseMemoryStamp,l as parsePromotionResponse,i as readPromotionLedger,t as rejectProposal,o as runPromotion,q as sourceKind};
2
- //# sourceMappingURL=promote-S7SKOKX2.js.map
1
+ import{b as a,c as b,d as c,e as d,f as e,g as f,h as g,i as h,j as i,k as j,l as k,m as l,n as m,o as n,p as o,q as p,r as q,s as r,t as s,u as t}from"./chunk-EVB23EHN.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import"./chunk-6W74CHNW.js";import"./chunk-TZIPWZY6.js";import"./chunk-CECHWYJ2.js";import"./chunk-JVSTKXMI.js";import"./chunk-WPNRDEHW.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-Y5HBYSJW.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{b as DEFAULT_PROMOTE_TYPES,a as PROMOTER_OWNER,c as PROMOTION_LEDGER_FILE,j as appendPromotionLedger,s as approveProposal,n as callPromotionLlm,p as estimateTokens,r as evidenceFor,m as getUnpromotedMemories,k as groupCandidates,h as listAllAgentMemories,d as memoryKey,e as memoryStamp,g as mergeSources,f as parseMemoryStamp,l as parsePromotionResponse,i as readPromotionLedger,t as rejectProposal,o as runPromotion,q as sourceKind};
2
+ //# sourceMappingURL=promote-4VTXBVUC.js.map
@@ -1,2 +1,2 @@
1
- import{a,b,c}from"./chunk-O2RVUM2B.js";import"./chunk-ILGLEA3I.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-Y5HBYSJW.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{b as DEFAULT_GRAPH_WEIGHT,a as agenticQuery,c as rankCatalogPool};
2
- //# sourceMappingURL=query-GOBQ3GL5.js.map
1
+ import{a,b,c}from"./chunk-CSLVHAYV.js";import"./chunk-JVSTKXMI.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-Y5HBYSJW.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{b as DEFAULT_GRAPH_WEIGHT,a as agenticQuery,c as rankCatalogPool};
2
+ //# sourceMappingURL=query-B32UDQJS.js.map
@@ -1,2 +1,2 @@
1
- import{$ as j,S as a,T as b,U as c,V as d,W as e,X as f,Y as g,Z as h,_ as i,aa as k,ba as l,ca as m,da as n}from"./chunk-XTO4GRGN.js";import"./chunk-J3GXZQXY.js";import"./chunk-GLQLCBJS.js";import"./chunk-6W74CHNW.js";import"./chunk-GV7S5BAX.js";import"./chunk-SZDACK6O.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-VGI4EZTP.js";import"./chunk-CYKPDILL.js";import"./chunk-VWTBHLMX.js";import"./chunk-VQM77L54.js";import"./chunk-XX7NXI3Y.js";import"./chunk-36AXN6ZB.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-J3SOEFRE.js";import"./chunk-SIU6STB2.js";import"./chunk-X5C5W3E4.js";import"./chunk-GSX4NK2N.js";import"./chunk-HG6QA6EU.js";import"./chunk-MYVHVJWZ.js";import"./chunk-AV7T3SYT.js";import"./chunk-Y5MFVVTM.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import"./chunk-O2RVUM2B.js";import"./chunk-ILGLEA3I.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-DSYKYZMT.js";import"./chunk-Y5HBYSJW.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{m as AgentRegistry,a as EDIT_TOOL_INSTRUCTION,h as TRACE_STEP_SUMMARY_BYTES,e as buildEntryMeta,f as buildEventDigest,g as buildWikiContext,i as clipForTrace,b as codingInstructions,l as emitTraceStepsFromStreamEvent,k as firstMissingRequiredTool,d as getGlobalRegistry,n as richReplyPrompt,c as setGlobalRegistry,j as tallyToolUses};
2
- //# sourceMappingURL=registry-HUJEORRW.js.map
1
+ import{$ as j,S as a,T as b,U as c,V as d,W as e,X as f,Y as g,Z as h,_ as i,aa as k,ba as l,ca as m,da as n}from"./chunk-QBWJGDKE.js";import"./chunk-J3GXZQXY.js";import"./chunk-GLQLCBJS.js";import"./chunk-6W74CHNW.js";import"./chunk-GV7S5BAX.js";import"./chunk-SZDACK6O.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-VGI4EZTP.js";import"./chunk-CYKPDILL.js";import"./chunk-VWTBHLMX.js";import"./chunk-Z6OPM7EH.js";import"./chunk-TZIPWZY6.js";import"./chunk-36AXN6ZB.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-J3SOEFRE.js";import"./chunk-SIU6STB2.js";import"./chunk-X5C5W3E4.js";import"./chunk-GSX4NK2N.js";import"./chunk-HG6QA6EU.js";import"./chunk-MYVHVJWZ.js";import"./chunk-AV7T3SYT.js";import"./chunk-Y5MFVVTM.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import"./chunk-CSLVHAYV.js";import"./chunk-JVSTKXMI.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-DSYKYZMT.js";import"./chunk-Y5HBYSJW.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{m as AgentRegistry,a as EDIT_TOOL_INSTRUCTION,h as TRACE_STEP_SUMMARY_BYTES,e as buildEntryMeta,f as buildEventDigest,g as buildWikiContext,i as clipForTrace,b as codingInstructions,l as emitTraceStepsFromStreamEvent,k as firstMissingRequiredTool,d as getGlobalRegistry,n as richReplyPrompt,c as setGlobalRegistry,j as tallyToolUses};
2
+ //# sourceMappingURL=registry-GY4X2GZX.js.map
@@ -1,2 +1,2 @@
1
- import"./chunk-VWTBHLMX.js";import{a as b}from"./chunk-VQM77L54.js";import{a}from"./chunk-XX7NXI3Y.js";import"./chunk-CECHWYJ2.js";import{a as c}from"./chunk-O2RVUM2B.js";import"./chunk-ILGLEA3I.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-Y5HBYSJW.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{b as WikiHub,a as WikiStore,c as agenticQuery};
2
- //# sourceMappingURL=wiki-FZHSX4K3.js.map
1
+ import"./chunk-VWTBHLMX.js";import{a as b}from"./chunk-Z6OPM7EH.js";import{a}from"./chunk-TZIPWZY6.js";import"./chunk-CECHWYJ2.js";import{a as c}from"./chunk-CSLVHAYV.js";import"./chunk-JVSTKXMI.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-A35RTVMM.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-2PJKGZWP.js";import"./chunk-7I7IEX4S.js";import"./chunk-Y5HBYSJW.js";import"./chunk-UIBUZ2N3.js";import"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";export{b as WikiHub,a as WikiStore,c as agenticQuery};
2
+ //# sourceMappingURL=wiki-LVYHDK2R.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentix-cli",
3
- "version": "0.114.0",
3
+ "version": "0.114.1",
4
4
  "description": "AI operations layer for small and medium businesses. Routes Telegram, WhatsApp, GitLab, GitHub, crons, webhooks, and mesh tasks to AI agents. Web wizard for operators, CLI for engineers. Self-hosted.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -1,6 +0,0 @@
1
- import{a as O,b as $,c as U,d as T,e as j}from"./chunk-WPNRDEHW.js";import{v as R,y as E,z as W}from"./chunk-A35RTVMM.js";import{a as z,b as C,f as V}from"./chunk-72SZI2UW.js";import{a as B,b as re}from"./chunk-FX3D7YON.js";import{o as J,p as te}from"./chunk-2PJKGZWP.js";V();var be="wiki-rerank",xe=30,se=900;function Se(a){let e=a.excerptChars??se;return{query:a.query,candidates:a.candidates.map(t=>({id:t.id,title:t.title,tags:t.tags?.length?t.tags.join(", "):null,excerpt:ne(t.excerpt,e)}))}}function Ne(a){let e={};for(let t of a)e[t.id]=t.title;return{best:C(e,"Which candidate answers the query?"),answerable:z("Do any of the candidates answer the query?")}}function ke(a,e){let t=a.best,r={};for(let i of e)r[i.id]=t.probabilities[i.id]??0;let n=new Map(e.map((i,s)=>[i.id,s]));return{ranked:[...e.map(i=>i.id)].sort((i,s)=>{let c=r[s]-r[i];return c!==0?c:(n.get(i)??0)-(n.get(s)??0)}),scores:r,answerable:a.answerable.noul,confidence:t.confidence}}function ne(a,e){let t=String(a??"").replace(/\s+/g," ").trim();return t.length>e?t.slice(0,e):t}var x={version:2,levels:[{id:"category",description:"Top-level kind of work. Closed set \u2014 pick the closest fit.",axes:[{name:"kind",type:"enum",values:["code","ops","support","admin","knowledge","social","system"],description:"Which category this work belongs in."}]},{id:"verb",description:"Specific intent \u2014 verb-level only, NOT client/project-bound.",axes:[{name:"name",type:"free",description:"Lower-kebab dot-namespaced verb. Examples: review.merge-request, fix.bug, investigate.error, deploy.staging, deploy.production, rollback.release, spec.feature, triage.issue, document.feature, chat.greeting, chat.support-request, schedule.add, config.change, ingest.contact, transcribe.audio, brief.daily, summarize.thread, plan.work."}]}],leafInput:{name:"input",type:"enum",values:["telegram","whatsapp","slack","discord","gitlab-mr","gitlab-issue","github-issue","github-pr","cron","webhook","mesh","http"],description:"Where the message entered the system."},leafOutput:{name:"output",type:"free",description:"One short sentence describing what the agent is expected to produce. Generic \u2014 refers to the verb's outcome, not the specific client/project (those are on the event metadata already)."}},G=[{category:"code",verb:"review.merge-request",description:"Review a GitLab MR or GitHub PR"},{category:"code",verb:"review.code-change",description:"General code review (snippet, diff)"},{category:"code",verb:"fix.bug",description:"Fix a reported bug"},{category:"code",verb:"implement.feature",description:"Build a new feature"},{category:"code",verb:"investigate.error",description:"Investigate a failing test, exception, pipeline"},{category:"code",verb:"refactor.code",description:"Restructure existing code without behaviour change"},{category:"code",verb:"spec.feature",description:"Write or update a feature spec / RFC"},{category:"code",verb:"triage.issue",description:"Classify, label, or assign an issue"},{category:"code",verb:"answer.code-question",description:"Answer a code-related question"},{category:"ops",verb:"deploy.staging",description:"Deploy to a staging/preview environment"},{category:"ops",verb:"deploy.production",description:"Deploy to production"},{category:"ops",verb:"rollback.release",description:"Roll back a release"},{category:"ops",verb:"investigate.incident",description:"Investigate a production incident"},{category:"ops",verb:"monitor.system",description:"Check system status / metrics"},{category:"ops",verb:"rotate.credential",description:"Rotate a token, key, certificate"},{category:"ops",verb:"audit.security",description:"Review for security issues"},{category:"support",verb:"chat.greeting",description:"A casual hello, no actionable request"},{category:"support",verb:"chat.support-request",description:"End-user / customer asking for help"},{category:"support",verb:"chat.casual",description:"Informal back-and-forth chat"},{category:"support",verb:"answer.question",description:"Answer an open-ended question"},{category:"support",verb:"route.request",description:"Forward a request to the right agent"},{category:"admin",verb:"config.change",description:"Change agentx.json / environment / config"},{category:"admin",verb:"schedule.add",description:"Add a new cron / scheduled task"},{category:"admin",verb:"schedule.remove",description:"Remove or disable a schedule"},{category:"admin",verb:"token.create",description:"Mint a scoped API token"},{category:"admin",verb:"agent.add",description:"Configure a new agent"},{category:"admin",verb:"channel.add",description:"Wire up a new channel"},{category:"knowledge",verb:"document.feature",description:"Write or update documentation"},{category:"knowledge",verb:"summarize.thread",description:"Summarize a long conversation/thread"},{category:"knowledge",verb:"research.topic",description:"Investigate / gather info on a topic"},{category:"knowledge",verb:"wiki.absorb",description:"Roll raw entries into typed wiki articles"},{category:"social",verb:"brief.daily",description:"Compose a daily brief / digest"},{category:"social",verb:"draft.post",description:"Draft a marketing post / announcement"},{category:"social",verb:"report.weekly",description:"Compose a weekly status report"},{category:"system",verb:"classify.intent",description:"Internal: graph-classifier sub-call"}];import{readFileSync as I,writeFileSync as M,appendFileSync as ie,existsSync as S,mkdirSync as _,renameSync as oe,statSync as Q}from"fs";import{resolve as P,dirname as X}from"path";import{createHash as ae}from"crypto";var F=class{baseDir;log;parsed=new Map;constructor(e={}){this.baseDir=e.baseDir??P(process.cwd(),".agentx/graph"),this.log=e.log??console.error.bind(console,"[graph]"),_(this.baseDir,{recursive:!0})}schemaPath(){return P(this.baseDir,"schema.json")}nodesPath(){return P(this.baseDir,"nodes.json")}indexPath(){return P(this.baseDir,"index.json")}classificationsPath(){return P(this.baseDir,"classifications.jsonl")}loadSchema(){let e=this.schemaPath();if(!S(e))return this.saveSchema(x),this.log("seeded starter schema at",e),x;let t=I(e,"utf-8"),r=O.safeParse(JSON.parse(t));if(!r.success)throw new Error(`Invalid ${e}: ${r.error.issues.map(n=>n.message).join("; ")}`);if((r.data.version??1)<(x.version??2)){let n=e.replace(/\.json$/,`.v${r.data.version??1}.bak.json`);try{M(n,t),this.log(`migrated graph schema v${r.data.version??1} -> v${x.version}; old saved at ${n}`)}catch(i){this.log(`could not back up old schema: ${i?.message??i}`)}this.saveSchema(x);let o=this.nodesPath();if(S(o)){let i=o.replace(/\.json$/,".v1.bak.json");try{M(i,I(o,"utf-8")),this.log(`archived v1 nodes.json -> ${i}`)}catch(s){this.log(`could not back up old nodes: ${s?.message??s}`)}try{let s=K();this.saveNodes(s)}catch(s){this.log(`could not seed v2 nodes: ${s?.message??s}`)}}return x}return r.data}saveSchema(e){let t=O.safeParse(e);if(!t.success)throw new Error(`Refusing to save invalid schema: ${t.error.issues.map(r=>r.message).join("; ")}`);Y(this.schemaPath(),t.data)}loadNodes(){let e=this.nodesPath();if(!S(e)){let t=K();return this.saveNodes(t),t}return structuredClone(this.readParsed(e,t=>{let r=T.safeParse(JSON.parse(t));if(!r.success)throw new Error(`Invalid ${e}: ${r.error.issues.map(n=>n.message).join("; ")}`);return r.data}))}saveNodes(e){let t=T.safeParse(e);if(!t.success)throw new Error(`Refusing to save invalid nodes file: ${t.error.issues.map(r=>r.message).join("; ")}`);this.writeParsed(this.nodesPath(),t.data)}readParsed(e,t){let{mtimeMs:r,size:n}=Q(e),o=this.parsed.get(e);if(o&&o.mtimeMs===r&&o.size===n)return o.data;let i=t(I(e,"utf-8"));return this.parsed.set(e,{mtimeMs:r,size:n,data:i}),i}writeParsed(e,t){this.parsed.delete(e),Y(e,t);let{mtimeMs:r,size:n}=Q(e);this.parsed.set(e,{mtimeMs:r,size:n,data:t})}validateNode(e,t,r){let n=t.levels.find(s=>s.id===e.level);if(!n)throw new Error(`Unknown level: "${e.level}"`);let o=n.axes.filter(s=>!s.optional).filter(s=>!(s.name in e.axes));if(o.length)throw new Error(`Node ${e.id} (${e.level}) missing required axes: ${o.map(s=>s.name).join(", ")}`);for(let s of n.axes){let c=e.axes[s.name];if(c!=null){if(s.type==="enum"&&s.values&&!s.values.includes(c))throw new Error(`Node ${e.id}: axis ${s.name}="${c}" not in enum ${JSON.stringify(s.values)}`);if(s.type==="ref"){if(!r.some(l=>l.id===c))throw new Error(`Node ${e.id}: axis ${s.name}="${c}" refers to unknown node`);if(s.refLevel){let l=r.find(h=>h.id===c);if(l.level!==s.refLevel)throw new Error(`Node ${e.id}: axis ${s.name} expected level "${s.refLevel}" but got "${l.level}"`)}}}}let i=t.levels.findIndex(s=>s.id===e.level);if(i===0){if(e.parentId!==null)throw new Error(`Root-level node ${e.id} must have parentId: null`)}else{if(!e.parentId)throw new Error(`Non-root node ${e.id} must have a parentId`);let s=r.find(l=>l.id===e.parentId);if(!s)throw new Error(`Node ${e.id}: parent "${e.parentId}" not found`);let c=t.levels.findIndex(l=>l.id===s.level);if(c<0||c>=i)throw new Error(`Node ${e.id} at level "${e.level}" has parent at level "${s.level}" \u2014 parent must be at a higher level`)}}commitNodesAlongPath(e,t,r,n){let o=[],i=[],s=new Date().toISOString();for(let c=0;c<e.length;c++){let l=e[c],h=this.loadNodes().nodes;if(h.find(p=>p.id===l)){i.push(l);continue}let g=0;for(let p=c-1;p>=0;p--){let y=e[p],N=h.find(w=>w.id===y)||o.find(w=>w.id===y);if(N){g=r.levels.findIndex(w=>w.id===N.level)+1;break}}let m=t[l]??{},d=null;for(let p=g;p<r.levels.length;p++){let y=r.levels[p];if(y.axes.filter(w=>!w.optional).filter(w=>!(w.name in m)).length===0){d=y.id,g=p+1;break}}if(!d&&g<r.levels.length&&(d=r.levels[g].id,g++),!d)throw new Error(`Can't place node ${l} \u2014 no schema level left (cursor=${g}, levels=${r.levels.length})`);let f=null,v=r.levels.findIndex(p=>p.id===d);for(let p=c-1;p>=0;p--){let y=e[p],N=h.find(k=>k.id===y)||o.find(k=>k.id===y);if(!N)continue;let w=r.levels.findIndex(k=>k.id===N.level);if(w>=0&&w<v){f=y;break}}let u={id:l,level:d,parentId:f,axes:m,createdAt:s,createdBy:n};this.addNode(u),o.push(u)}return{added:o,skipped:i}}addNode(e){let t=this.loadSchema(),r=this.loadNodes();if(r.nodes.some(n=>n.id===e.id))throw new Error(`Node id already exists: ${e.id}`);return this.validateNode(e,t,[...r.nodes,e]),r.nodes.push(e),this.saveNodes(r),e}appendClassification(e){let t=$.safeParse(e);if(!t.success){let o=t.error.issues.map(i=>`${i.path.join(".")}: ${i.message}`).join(" \xB7 ");return this.log(`skipped invalid classification \u2014 ${o} \xB7`,`path=${JSON.stringify(e.path)}`,`axes-keys=${JSON.stringify(Object.keys(e.proposedAxes||{}))}`),!1}let r=JSON.stringify(t.data)+`
2
- `,n=this.classificationsPath();return S(n)||_(X(n),{recursive:!0}),ie(n,r),!0}listPendingClassifications(e=200){return this.listByStatus("pending",e)}listAllClassifications(){return this.readAllCollapsed()}listByStatus(e,t=200){return this.readAllCollapsed().filter(n=>n.status===e).slice(0,t)}readAllCollapsed(){let e=this.classificationsPath();if(!S(e))return[];let r=I(e,"utf-8").split(`
3
- `).filter(Boolean),n=new Map;for(let o of r)try{let i=$.safeParse(JSON.parse(o));if(!i.success)continue;n.set(i.data.msgHash,i.data)}catch{}return Array.from(n.values()).sort((o,i)=>o.ts<i.ts?1:-1)}updateClassificationStatus(e,t){let n=this.readAllCollapsed().find(i=>i.msgHash===e);if(!n)return null;let o={...n,status:t.status,ts:new Date().toISOString()};if(t.reviewer||t.reviewReason){let i=` \xB7 ${t.reviewer?`reviewer=${t.reviewer}`:""}${t.reviewReason?` \xB7 ${t.reviewReason}`:""}`;o.preview=((n.preview||"")+i).slice(0,500)}return this.appendClassification(o),o}readRecentClassifications(e=50){let t=this.classificationsPath();if(!S(t))return[];let n=I(t,"utf-8").split(`
4
- `).filter(Boolean),o=[];for(let i=n.length-1;i>=0&&o.length<e;i--)try{let s=$.safeParse(JSON.parse(n[i]));s.success&&o.push(s.data)}catch{}return o}fingerprint(e){let r=[ce(e.text),e.channel??""].join("");return ae("sha256").update(r).digest("hex").slice(0,32)}loadIndex(){return structuredClone(this.index())}saveIndex(e){let t=j.safeParse(e);if(!t.success)throw new Error(`Refusing to save invalid index: ${t.error.issues.map(r=>r.message).join("; ")}`);this.writeParsed(this.indexPath(),t.data)}index(){let e=this.indexPath();return S(e)?this.readParsed(e,t=>{let r=j.safeParse(JSON.parse(t));if(!r.success)throw new Error(`Invalid ${e}: ${r.error.issues.map(n=>n.message).join("; ")}`);return r.data}):{version:1,entries:{}}}getFingerprint(e){let t=this.index().entries[e];return t&&structuredClone(t)}setFingerprint(e,t){let r=U.safeParse({...t,fingerprint:e,updatedAt:new Date().toISOString()});if(!r.success)throw new Error(`Refusing to save invalid index entry: ${r.error.issues.map(o=>o.message).join("; ")}`);let n=this.index();this.writeParsed(this.indexPath(),{...n,entries:{...n.entries,[e]:r.data}})}updateNodeAxes(e,t){let r=this.loadSchema(),n=this.loadNodes(),o=n.nodes.find(s=>s.id===e);if(!o)throw new Error(`Node not found: ${e}`);let i={...o,axes:t};return this.validateNode(i,r,n.nodes.map(s=>s.id===e?i:s)),n.nodes=n.nodes.map(s=>s.id===e?i:s),this.saveNodes(n),i}deleteNode(e){let t=this.loadNodes(),r=t.nodes.find(o=>o.parentId===e);if(r)throw new Error(`Cannot delete "${e}" \u2014 child node "${r.id}" still points to it`);let n=t.nodes.find(o=>Object.values(o.axes).some(i=>i===e));if(n)throw new Error(`Cannot delete "${e}" \u2014 node "${n.id}" references it via an axis`);t.nodes=t.nodes.filter(o=>o.id!==e),this.saveNodes(t)}approveClassification(e){if(this.getFingerprint(e.msgHash))return;let t=this.loadSchema(),r=new Set(this.loadNodes().nodes.map(n=>n.id));for(let n=0;n<e.path.length;n++){let o=e.path[n];if(r.has(o))continue;let i=t.levels[n]?.id;if(!i)break;let s=e.proposedAxes?.[o]??{},c=n===0?null:e.path[n-1];this.addNode({id:o,level:i,parentId:c,axes:s,createdAt:new Date().toISOString(),createdBy:e.agentId}),r.add(o)}this.setFingerprint(e.msgHash,{path:e.path,leaf:e.leaf}),this.appendClassification({...e,status:"approved",ts:new Date().toISOString()})}rejectClassification(e){this.appendClassification({...e,status:"rejected",ts:new Date().toISOString()})}};function Y(a,e){_(X(a),{recursive:!0});let t=`${a}.tmp-${process.pid}`;M(t,JSON.stringify(e,null,2)),oe(t,a)}function K(){let a=new Date().toISOString(),e=[],t=new Set;for(let r of G)t.has(r.category)||(e.push({id:r.category,level:"category",parentId:null,axes:{kind:r.category},createdAt:a,createdBy:"starter"}),t.add(r.category));for(let r of G)e.push({id:r.verb,level:"verb",parentId:r.category,axes:{name:r.verb,...r.description?{description:r.description}:{}},createdAt:a,createdBy:"starter"});return{version:1,nodes:e}}function ce(a){return a.toLowerCase().replace(/https?:\/\/\S+/g," url ").replace(/[@#][\w.\/-]+/g," ref ").replace(/\b[0-9a-f]{7,}\b/g," id ").replace(/\d+/g," num ").replace(/[^\p{L}\p{N}\s]+/gu," ").replace(/\s+/g," ").trim().slice(0,400)}re();te();W();import{createHash as ve}from"crypto";V();W();var A="intent-path",de=.5,le=.3,pe=.45;function ge(a){return{message:me(a.message,2e3),channel:a.channel??null,sender:a.sender??null,agent:a.agent??null}}function Z(a,e){let t={};for(let r of a)t[r.id]=fe(r);return C(t,e)}function ue(a){return{category:Z(a,"Which category of work does this message ask for or report on? Pick the one a reviewer would file it under.")}}function he(a){return{verb:Z(a,"Within that category, which specific action does the message ask for or report on? Prefer the most specific verb that fits; a casual or ambiguous message belongs to the most general one.")}}async function D(a,e,t={}){if(R(A)==="off")return null;let r=e.filter(m=>m.parentId===null);if(r.length<2)return null;let n=ge(a),o={agent:a.agent??"unknown",channel:a.channel??"unknown"},i=a.agent?[{kind:"agent",id:a.agent}]:void 0,s=await E(A,n,ue(r),{incumbent:t.incumbent?.[0]?{category:t.incumbent[0]}:void 0,features:{...o,stage:"category"},links:i});if(!s)return null;let c=s.answers.category,l=c.pMax,h=c.pMax>=de,b=[c.choice],g=e.filter(m=>m.parentId===c.choice);if(g.length>=2){let m=t.incumbent?.[0]===c.choice,d=await E(A,{...n,category:c.choice},he(g),{incumbent:m&&t.incumbent?.[1]?{verb:t.incumbent[1]}:void 0,features:{...o,stage:"verb",category:c.choice},links:i});if(!d)return null;let f=d.answers.verb;h=h&&f.pMax>=le,(f.pMax>=pe||!h)&&(l=Math.min(l,f.pMax),b.push(f.choice))}else g.length===1&&b.push(g[0].id);return{path:b,confidence:l,confident:h,mode:s.mode}}function fe(a){let e=a.axes?.description?.trim()||void 0,t=a.axes?.name?.trim(),r=t&&t!==a.id?t:void 0;return e&&r?`${r}: ${e}`:e??r??null}function me(a,e){return a.length>e?`${a.slice(0,e)}\u2026`:a}var L=class{store;daemonUrl;token;draftAgent;autoApprove;autoApproveStructure;classifierModel;classifierProviderName;providerInstance;log;constructor(e){this.store=e.store,this.daemonUrl=e.daemonUrl.replace(/\/+$/,""),this.token=e.token,this.draftAgent=e.draftAgent,this.autoApprove=e.autoApproveConfidence??1,this.autoApproveStructure=e.autoApproveStructure??"extend-leaves",this.classifierModel=e.classifierModel??"claude-haiku-4-5-20251001",this.classifierProviderName=e.classifierProvider??"claude-code",this.log=e.log??console.error.bind(console,"[classifier]")}getProvider(){return this.providerInstance||(this.providerInstance=J(this.classifierProviderName)),this.providerInstance}async classify(e){let t=this.store.fingerprint({text:e.text,channel:e.channel,sender:e.sender}),r=this.store.getFingerprint(t);if(r)return this.store.appendClassification({ts:new Date().toISOString(),msgHash:t,agentId:e.agentId,channel:e.channel,sender:e.sender,chatId:e.chatId,path:r.path,proposedAxes:{},leaf:r.leaf,source:"cache",status:"approved",preview:e.text.slice(0,200)}),{path:r.path,pathId:H(r.path),pathLabel:q(r.path,this.store.loadNodes().nodes),axes:{},leaf:r.leaf,source:"cache",status:"approved"};let n=this.store.loadSchema(),o=this.store.loadNodes().nodes,i=await this.propose(e,n,o);if(!i)return null;let{path:s,proposedAxes:c,confidence:l,leaf:h}=i;if(s.length===0)return null;let b={ts:new Date().toISOString(),msgHash:t,agentId:e.agentId,channel:e.channel,sender:e.sender,chatId:e.chatId,path:s,proposedAxes:c,leaf:h,source:i.source,status:"pending",confidence:l,preview:e.text.slice(0,200)},g=new Set(o.map(u=>u.id)),m=s.map((u,p)=>g.has(u)?-1:p).filter(u=>u>=0),d=!1;if(this.autoApproveStructure==="any")d=!0;else if(this.autoApproveStructure==="extend-leaves"){let u=m.length===0,p=m.length===1&&m[0]===s.length-1;d=u||p}let f=l!==void 0&&l>=this.autoApprove,v="pending";if(d||f)try{this.commitNewNodes(s,c,n,o,e.sender),this.store.setFingerprint(t,{path:s,leaf:h}),v="approved"}catch(u){this.log("auto-approve failed \u2014 staying pending \xB7",`path=${JSON.stringify(s)}`,`reason=${(u?.message||u).toString().slice(0,200)}`)}return b.status=v,this.store.appendClassification(b),{path:s,pathId:H(s),pathLabel:q(s,this.store.loadNodes().nodes),axes:c,leaf:h,source:i.source,status:v,confidence:l}}async propose(e,t,r){let n=R(A),o={message:e.text,channel:e.channel,sender:e.sender,agent:e.agentId};if(n==="active"){let s=await D(o,r).catch(c=>(this.log("intent-path seat failed:",c?.message||c),null));if(s?.confident)return{path:s.path,proposedAxes:{},leaf:{},confidence:s.confidence,source:"seat"}}let i=await this.proposePath(e,t,r).catch(s=>(this.log("LLM proposal failed:",s?.message||s),null));return n==="shadow"&&i&&D(o,r,{incumbent:i.path}).catch(()=>{}),i?{...i,source:"llm"}:null}async proposePath(e,t,r){let n=r.map(d=>({id:d.id,level:d.level,parentId:d.parentId,axes:d.axes})),o=["You are the intent classifier for AgentX. You answer ONE question:",'"what kind of work does this message describe?" \u2014 verb-level only.',"","IMPORTANT \u2014 what NOT to encode in the path:","- Client / company / project / team names. Those are already on the event"," metadata (project, channel, agentId). Embedding them in the path causes"," duplicate nodes (one per client) for the same verb.","- The specific subject (issue number, file name, person name). Same reason.","- The agent's name or role. Pick the verb the *requester* intended.","","SCHEMA (fixed levels \u2014 pick one node per level):","```json",JSON.stringify(t,null,2),"```","","EXISTING NODES (prefer reusing these; only invent a new node when no","existing one fits):","```json",JSON.stringify(n,null,2),"```","","MESSAGE:","```",e.text.slice(0,2e3),"```",`channel: ${e.channel??"?"}`,`sender: ${e.sender??"?"}`,"","TASK:","1. Classify into 'category' (closed enum): code, ops, support, admin,"," knowledge, social, system. Pick the closest fit.","2. Pick or propose a 'verb' node. Verb ids are dot-namespaced lower-kebab,",' e.g. "review.merge-request", "deploy.staging", "investigate.error",',' "chat.greeting", "fix.bug". Reuse an existing verb when the message is'," the same kind of work as something already classified, even when the"," client / project / subject differs.","","Examples (right vs wrong):",'- "Please review MR #957 on globex/system" \u2192 ["code", "review.merge-request"]',' NOT ["business", "acme", "globex-v2", "review-mr-957-system"]','- "Deploy initech-v2 to staging please" \u2192 ["ops", "deploy.staging"]',' NOT ["business", "acme", "initech-v2", "deploy-initech-v2-to-staging"]','- "Hello Atlas" \u2192 ["support", "chat.greeting"]',"","NODE ID RULES (strict \u2014 invalid ids get dropped):","- lowercase-kebab + dots only: [a-z0-9][a-z0-9._-]*","- no spaces, no uppercase, no Arabic/other non-Latin",'- verb ids should use a "category.specific" or "verb.modifier" shape',"","Return ONE JSON object on one line, no prose, no fences:",' { "path": string[], "proposedAxes": { [nodeId]: { [axisName]: string } }, "leaf": { "input"?: string, "output"?: string }, "confidence": number }',"confidence in [0,1]. Prefer low confidence over guessing."].join(`
5
- `),i=await this.callProvider(o),s=B(i);if(!s||!Array.isArray(s.path))return null;let c=/^[a-z0-9][a-z0-9._-]*$/,l=new Map,h=s.path.filter(d=>typeof d=="string"&&d.length>0).map(d=>{let f=d.trim(),v=ee(f);return f!==v&&l.set(f,v),v}).filter(d=>c.test(d));if(h.length===0)return null;let b={};if(s.proposedAxes&&typeof s.proposedAxes=="object")for(let[d,f]of Object.entries(s.proposedAxes)){if(!f||typeof f!="object")continue;let v=l.get(d)??ee(d);if(!v)continue;let u={};for(let[p,y]of Object.entries(f))typeof y=="string"&&(u[p]=y);!u.name&&d!==v&&(u.name=d.trim()),b[v]=u}let g={};s.leaf&&typeof s.leaf=="object"&&(typeof s.leaf.input=="string"&&(g.input=s.leaf.input),typeof s.leaf.output=="string"&&(g.output=s.leaf.output));let m=typeof s.confidence=="number"?Math.max(0,Math.min(1,s.confidence)):void 0;return{path:h,proposedAxes:b,confidence:m,leaf:g}}commitNewNodes(e,t,r,n,o){this.store.commitNodesAlongPath(e,t,r,o)}async callProvider(e){let t=this.getProvider(),r=new AbortController,n=setTimeout(()=>r.abort(),3e4);try{return(await t.generate([{role:"system",content:"You are a taxonomy classifier. Respond with a single JSON object on one line. No prose, no code fences."},{role:"user",content:e}],{model:this.classifierModel,maxTokens:800,abortSignal:r.signal,bare:!0})).content||""}finally{clearTimeout(n)}}};function ee(a){let e=a.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^[-_]+|[-_]+$/g,"").replace(/-{2,}/g,"-");return e?/^[a-z0-9]/.test(e)?e:`n-${e}`.replace(/[-_]+$/,""):""}function H(a){return ve("sha1").update(a.join("")).digest("hex").slice(0,16)}function q(a,e){return a.map(t=>{let r=e.find(o=>o.id===t);return r&&(r.axes?.name||r.axes?.what)||t}).join(" \u203A ")}function ye(a,e){if(a.length===0||e.length===0)return 0;let t=0;for(let n=0;n<Math.min(a.length,e.length)&&a[n]===e[n];n++)t++;if(t===0)return 0;let r=Math.max(a.length,e.length);return t/r}export{be as a,xe as b,Se as c,Ne as d,ke as e,x as f,F as g,L as h,q as i,ye as j};
6
- //# sourceMappingURL=chunk-ILGLEA3I.js.map