agentix-cli 0.45.0 → 0.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-BCZRXLZ6.js → agent-YC3VJVPK.js} +2 -2
- package/dist/{chunk-CQRSSVWG.js → chunk-3FIS6JD3.js} +2 -2
- package/dist/{chunk-Z7LNSHG3.js → chunk-3RKIBJG6.js} +47 -47
- package/dist/{chunk-Z7LNSHG3.js.map → chunk-3RKIBJG6.js.map} +1 -1
- package/dist/{chunk-DYSVG6T3.js → chunk-KZYNQRQQ.js} +4 -4
- package/dist/{chunk-3RCFDI52.js → chunk-MDAC3PKR.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/dist/{program-4RO4NCBU.js → program-WLPVWTAT.js} +2 -2
- package/dist/{registry-OUJ6HT5D.js → registry-EESWAPMR.js} +2 -2
- package/package.json +1 -1
- /package/dist/{agent-BCZRXLZ6.js.map → agent-YC3VJVPK.js.map} +0 -0
- /package/dist/{chunk-CQRSSVWG.js.map → chunk-3FIS6JD3.js.map} +0 -0
- /package/dist/{chunk-DYSVG6T3.js.map → chunk-KZYNQRQQ.js.map} +0 -0
- /package/dist/{chunk-3RCFDI52.js.map → chunk-MDAC3PKR.js.map} +0 -0
- /package/dist/{program-4RO4NCBU.js.map → program-WLPVWTAT.js.map} +0 -0
- /package/dist/{registry-OUJ6HT5D.js.map → registry-EESWAPMR.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as ba,b as On,g as $a}from"./chunk-7A7RC3R4.js";import{b as pa}from"./chunk-YQVR2HQS.js";import{a as _o,b as ma,f as An,i as Rs,j as ya,l as wa}from"./chunk-SAFAI4AV.js";import{a as ua,c as fa,d as ha}from"./chunk-2TJ5L7CB.js";import{a as vs,b as hr,c as xs,g as yr,h as wr,j as br,k as $r,m as kr,n as vr,o as xr}from"./chunk-WLVQDEOT.js";import{a as tt}from"./chunk-GV7S5BAX.js";import{e as ar}from"./chunk-GSX4NK2N.js";import{c as cr}from"./chunk-SZDACK6O.js";import{$ as da,A as Kr,B as st,C as yo,D as Xr,E as As,F as Os,G as Qr,H as Zr,I as Pt,J as vn,K as ea,L as oa,M as ta,N as na,O as it,P as sa,Q as ia,R as ke,S as xn,T as Mt,U as Ts,V as ra,W as Sn,X as En,Y as la,Z as Cs,_ as Ns,a as Sr,aa as ga,b as Er,h as jr,i as Ir,j as Dt,k as yn,l as Cr,m as Nr,n as Rr,o as Dr,p as Wr,q as Br,r as Jr,s as Gr,t as Hr,u as zr,v as Yr,w as Vr,x as _t,y as Es,z as kn}from"./chunk-
|
|
1
|
+
import{a as ba,b as On,g as $a}from"./chunk-7A7RC3R4.js";import{b as pa}from"./chunk-YQVR2HQS.js";import{a as _o,b as ma,f as An,i as Rs,j as ya,l as wa}from"./chunk-SAFAI4AV.js";import{a as ua,c as fa,d as ha}from"./chunk-2TJ5L7CB.js";import{a as vs,b as hr,c as xs,g as yr,h as wr,j as br,k as $r,m as kr,n as vr,o as xr}from"./chunk-WLVQDEOT.js";import{a as tt}from"./chunk-GV7S5BAX.js";import{e as ar}from"./chunk-GSX4NK2N.js";import{c as cr}from"./chunk-SZDACK6O.js";import{$ as da,A as Kr,B as st,C as yo,D as Xr,E as As,F as Os,G as Qr,H as Zr,I as Pt,J as vn,K as ea,L as oa,M as ta,N as na,O as it,P as sa,Q as ia,R as ke,S as xn,T as Mt,U as Ts,V as ra,W as Sn,X as En,Y as la,Z as Cs,_ as Ns,a as Sr,aa as ga,b as Er,h as jr,i as Ir,j as Dt,k as yn,l as Cr,m as Nr,n as Rr,o as Dr,p as Wr,q as Br,r as Jr,s as Gr,t as Hr,u as zr,v as Yr,w as Vr,x as _t,y as Es,z as kn}from"./chunk-MDAC3PKR.js";import{A as js,B as ca,C as Is,k as Ss,l as wn,m as bn,n as _r,o as Pr,p as Mr,q as Lr,r as Fr,u as $n,v as Ur,w as qr,z as aa}from"./chunk-MX5GCR7Y.js";import{a as Ar,d as Or,e as Tr}from"./chunk-V5FZJUK4.js";import{F as ur,P as fr,h as tr,q as nr,s as Nt,u as Zo,w as bs,x as ir,z as ho}from"./chunk-3RKIBJG6.js";import{b as et,c as fn,d as hn,e as ot,f as rr,g as Do,h as Rt}from"./chunk-TCJ3SMOF.js";import{d as ks,f as mr}from"./chunk-VMDA2SX2.js";import{a as or}from"./chunk-QLTM3F7M.js";import{a as sr,e as gr}from"./chunk-BIFJSQB5.js";import{f as lr,g as dr,h as $s}from"./chunk-76Z4VHDX.js";import{b as fe,c as Ee,d as nt,e as pr}from"./chunk-NSYY5NCR.js";import{h as er}from"./chunk-DWADWDMU.js";import{b as fo,d as un,f as ws}from"./chunk-MTVRYTLL.js";import{b as Qo,d as Zi}from"./chunk-2GIDVZ4H.js";import{a as ys,b as qi,c as td,d as mn,e as Wi,f as zi,g as sd,h as Yi,i as id,m as Xo,n as Ki,o as Xi,s as Qi,v as Ze,w as Ct}from"./chunk-6HMZ5TTM.js";import{a as ro,b as Ko,e as Ji,f as It}from"./chunk-F4HZTZHW.js";import{a as Vi,b as rd}from"./chunk-AJONZWLT.js";import{a as io,b as od}from"./chunk-L2WSPY6S.js";import{k as Bi,l as _,m as pn,o as me}from"./chunk-QJANPP4C.js";import{g as Gi,k as Hi,l as nd}from"./chunk-BH3GTCZ6.js";import{a as ed}from"./chunk-FIOB3MEX.js";import{Command as ad}from"commander";var ka=new ad().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 Er({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()});me();import{Command as cd}from"commander";import{execFileSync as ao}from"node:child_process";import{cpSync as va,existsSync as Ps,mkdirSync as Ds,mkdtempSync as ld,readFileSync as dd,rmSync as gd,writeFileSync as xa}from"node:fs";import{dirname as _s,join as Ce,resolve as Sa}from"node:path";import{homedir as Tn,release as md,tmpdir as pd}from"node:os";import{fileURLToPath as ud}from"node:url";import{setTimeout as fd}from"node:timers/promises";function jn(){let e=_r(process.platform,process.arch,md());if(e)throw new Error(e)}function Lt(){return`gui/${process.getuid()}/${Ss}`}function rt(){return Ce(Tn(),"Library/LaunchAgents",`${Ss}.plist`)}async function Ea(){try{ao("launchctl",["bootout",Lt()],{stdio:"pipe"})}catch{}for(let e=0;e<30;e++){try{ao("launchctl",["print",Lt()],{stdio:"pipe"})}catch{return}await fd(200)}throw new Error("The desktop login service did not stop. Retry agentx desktop stop before installing.")}function Aa(){if(!Ps(rt()))throw new Error("Run agentx desktop install first.");let e=!0;try{ao("launchctl",["print",Lt()],{stdio:"pipe"})}catch{e=!1}e||ao("launchctl",["bootstrap",`gui/${process.getuid()}`,rt()],{stdio:"pipe"}),ao("launchctl",["kickstart",Lt()],{stdio:"pipe"})}function hd(){let e=_s(ud(import.meta.url));for(let o of[Sa(e,".."),Sa(e,"../.."),process.cwd()])try{if(JSON.parse(dd(Ce(o,"package.json"),"utf8")).name==="agentix-cli"&&Ps(Ce(o,"apps/mac-voice/build.sh")))return o}catch{}throw new Error("Desktop sources are missing from this installation. Update AgentX to a release containing apps/mac-voice and apps/mac-helper.")}var at=new cd("desktop").description("install and control the macOS desktop assistant");at.command("install").description("build, install, and start voice and computer-use helpers at login").option("--agent <id>","agent to use (defaults to the first configured agent)").option("--dry-run","show the installation plan without building or changing login items").action(async e=>{jn();let o=_(),t=Pr(o.agents,e.agent),n=o.dashboard?.daemonUrl||`http://${o.node.bind.replace(/^0\.0\.0\.0:/,"127.0.0.1:")}`,s=hd(),i=Ce(Tn(),"Applications");if(console.log(`Desktop assistant \u2192 ${Ce(i,wn)}
|
|
2
2
|
Computer-use helper \u2192 ${Ce(i,bn)}
|
|
3
3
|
Agent \u2192 ${t}
|
|
4
4
|
Daemon \u2192 ${n}
|
|
@@ -379,7 +379,7 @@ return aid ?? null`}function _m(e,o){if(e.kind==="path"){let s=e.pts,i=s[Math.fl
|
|
|
379
379
|
settings \u2014 without this an attached production identity would be less
|
|
380
380
|
guarded than a spawned one.)`))):console.log(L.yellow(" ! Guard hook skipped. An attached production identity will run unguarded.")),console.log(),console.log(`Next: ${L.cyan("agentx attach <agent>")} inside a Claude Code session.`)}catch(o){console.error(L.red(`Install failed: ${o?.message??o}`)),process.exit(1)}});Go.command("uninstall").description("remove the attach hooks from ~/.claude/settings.json").option("--path <file>","settings file to patch (default: ~/.claude/settings.json)").option("--remove-guard","also remove the PreToolUse guard hook").action(e=>{try{let o=Ca({path:e.path,keepGuard:!e.removeGuard});console.log(o.changed?`${L.green("\u2713")} Removed attach hooks from ${L.gray(o.path)} (${o.events.join(", ")})`:`${L.gray("Nothing to remove.")}`),e.removeGuard||console.log(L.gray(" PreToolUse guard left in place \u2014 pass --remove-guard to drop it too."))}catch(o){console.error(L.red(`Uninstall failed: ${o?.message??o}`)),process.exit(1)}});me();import{Command as yp}from"commander";import he from"chalk";var Kn=new yp().name("process").description("inspect / rotate persistent claude processes (--persistentProcess agents)");function Hc(e){let o=typeof e.node=="string"?e.node:"",t=typeof e.token=="string"?e.token:"";if(!o||!t)try{let n=_(e.config);o||(o=n.dashboard?.daemonUrl||""),t||(t=n.dashboard?.token||"")}catch{}return o||(o="http://localhost:18800"),{baseUrl:o.replace(/\/+$/,""),token:t}}function zc(e,o){let t={};return e&&(t.Authorization=`Bearer ${e}`),o&&(t["Content-Type"]=o),t}function Gc(e){let o=Math.round((Date.now()-e)/1e3);return o<60?`${o}s`:o<3600?`${Math.round(o/60)}m`:o<86400?`${Math.round(o/3600)}h`:`${Math.round(o/86400)}d`}function wp(e){return e==="busy"?he.magenta:e==="warm-hot"?he.green:e==="warm-cold"?he.cyan:e==="idle"?he.yellow:e==="dead"?he.red:he.dim}Kn.command("list").description("list every live persistent claude process").option("-c, --config <path>","daemon config file").option("--node <url>","daemon URL (defaults to dashboard.daemonUrl)").option("--token <token>","bearer token (defaults to dashboard.token)").option("--json","emit JSON").action(async e=>{let{baseUrl:o,token:t}=Hc(e),n;try{n=await fetch(`${o}/api/processes`,{headers:zc(t)})}catch(r){console.log(he.red(` could not reach daemon at ${o}: ${r.message||r}`)),process.exit(1)}if(n.status===503){console.log(he.dim(` daemon at ${o} has no agents with persistentProcess: true`));return}n.ok||(console.log(he.red(` HTTP ${n.status} from ${o}/processes`)),process.exit(1));let i=(await n.json()).processes??[];if(e.json){console.log(JSON.stringify(i,null,2));return}if(i.length===0){console.log(he.dim(" (no processes)"));return}for(let r of i){let a=wp(r.state)(r.state.padEnd(9)),c=Gc(r.spawnedAt),l=r.lastTurnAt?Gc(r.lastTurnAt)+" ago":"\u2014",g=r.lastInputTokens?he.dim(`last_in=${r.lastInputTokens} tok`):"",d=r.claudeSessionId?he.dim(`sess=${r.claudeSessionId.slice(0,8)}\u2026`):he.dim("sess=\u2014"),u=r.pendingTaskId?he.cyan(`task=${String(r.pendingTaskId).slice(0,12)}`):"";console.log(`${a} ${he.bold(r.key.agentId)}${he.dim(":"+r.key.channel+":"+r.key.chatId)} ${he.dim("\xB7")} pid=${r.pid??"?"} age=${c} turn#${r.turnCount} last=${l} ${d} ${g} ${u}`),r.deadReason&&console.log(` ${he.red("dead:")} ${r.deadReason}`)}});Kn.command("kill <agentId> <channel> <chatId>").description("force-kill one persistent process (the next dispatch will spawn fresh)").option("-c, --config <path>","daemon config file").option("--node <url>","daemon URL (defaults to dashboard.daemonUrl)").option("--token <token>","bearer token (defaults to dashboard.token)").option("-r, --reason <reason>","kill reason (recorded on the dead-process snapshot)","operator-cli").action(async(e,o,t,n)=>{let{baseUrl:s,token:i}=Hc(n),r;try{r=await fetch(`${s}/api/processes/kill`,{method:"POST",headers:zc(i,"application/json"),body:JSON.stringify({agentId:e,channel:o,chatId:t,reason:n.reason})})}catch(a){console.log(he.red(` could not reach daemon at ${s}: ${a.message||a}`)),process.exit(1)}if(r.status===503){console.log(he.dim(" daemon has no persistent-process registry"));return}if(!r.ok){let a=`HTTP ${r.status}`;try{let c=await r.json();c.error&&(a+=` \u2014 ${c.error}`)}catch{}console.log(he.red(` ${a}`)),process.exit(1)}console.log(he.green(` killed ${e}:${o}:${t}`))});import{Command as bp}from"commander";import Re from"chalk";import{existsSync as di,rmSync as $p}from"fs";import{resolve as gi}from"path";var ht=new bp().name("rag").description("manage per-agent lexical (BM25) RAG indexes (improvement plan #7)");ht.command("add <agentId>").description("build or refresh an agent's lexical index from one or more globs").argument("<globs...>","glob patterns relative to cwd (e.g. './docs/**/*.md')").option("-v, --verbose","log each indexed file").action(async(e,o,t)=>{o.length===0&&(console.log(Re.red(` No globs provided. Example: agentx rag add ${e} './docs/**/*.md'`)),process.exit(1));let n=!!t.verbose,s=Date.now(),i=await lr(e,o,{verbose:n}),r=Date.now()-s;console.log(Re.green(` \u2713 indexed ${i.docs} doc(s) for ${Re.bold(e)} in ${r}ms`)),console.log(Re.dim(` \u2192 ${i.path}`))});ht.command("list").description("list every agent's index, sizes, paths").option("-c, --cwd <path>","search root",process.cwd()).action(async e=>{let o=gi(e.cwd,".agentx","rag");if(!di(o)){console.log(Re.dim(" (no indexes yet \u2014 try `agentx rag add <agentId> <glob>`)"));return}let{readdirSync:t}=await import("fs"),n=t(o).filter(s=>di(gi(o,s,"index.json")));if(n.length===0){console.log(Re.dim(" (no indexes)"));return}for(let s of n.sort()){let i=$s(s);console.log(` ${Re.bold(s)} ${i.docs} doc(s) ${Re.dim(i.path)}`)}});ht.command("search <agentId> <query>").description("query an agent's index \u2014 useful for debugging recall before the agent calls rag.lexical").option("-k, --k <n>","top-k results","5").option("--json","emit JSON").action((e,o,t)=>{let n=parseInt(t.k,10)||5,s=dr(e,o,{k:n});if(t.json){console.log(JSON.stringify(s,null,2));return}if(s.length===0){let i=$s(e);i.exists?console.log(Re.dim(` (no hits in ${i.docs} indexed docs)`)):console.log(Re.red(` no index for ${e} \u2014 run \`agentx rag add ${e} <glob>\` first`));return}for(let i of s)console.log(` ${Re.bold(i.title)} ${Re.dim(`(${i.score.toFixed(2)})`)}`),console.log(` ${Re.dim(i.path)}`),console.log(` ${Re.dim(i.snippet.slice(0,200))}`)});ht.command("clear <agentId>").description("delete an agent's index").action(e=>{let o=gi(process.cwd(),".agentx","rag",e);if(!di(o)){console.log(Re.dim(` no index for ${e} \u2014 nothing to clear`));return}$p(o,{recursive:!0,force:!0}),console.log(Re.green(` \u2713 cleared index for ${e}`))});me();import{Command as kp}from"commander";import K from"chalk";import yt from"prompts";var Ho=new kp().name("backlog").description("manage the local backlog used by business workSource=backlog");function Xt(e){let o=_(e),t=o.business?.workSource,n=t?.type==="backlog"?t.path:".agentx/backlog.md";return{config:o,storePath:n,store:new aa(n)}}function vp(e){return e?K.cyan(`${e.type}:${e.project}#${e.iid}`):K.dim("manual")}function xp(e){return{todo:K.gray("todo"),doing:K.yellow("doing"),blocked:K.red("blocked"),done:K.green("done")}[e]}Ho.command("list",{isDefault:!0}).description("list backlog items").option("--status <status>","filter by status (todo|doing|blocked|done)").option("--assignee <agent>","filter by assignee").option("--source <type>","filter by source.type (gitlab|github|manual)").option("-c, --config <path>","config path").action(async e=>{let{store:o}=Xt(e.config),t=o.list();if(e.status&&(t=t.filter(n=>n.status===e.status)),e.assignee&&(t=t.filter(n=>n.assignee===e.assignee)),e.source&&(t=t.filter(n=>e.source==="manual"?!n.source:n.source?.type===e.source)),!t.length){console.log(K.dim(" (no items)"));return}console.log();for(let n of t){let s=n.assignee?K.magenta(`@${n.assignee}`):K.dim("unassigned");console.log(` ${xp(n.status).padEnd(7)} ${vp(n.source)} ${s} ${n.title}`),n.source?.url&&console.log(K.dim(` ${n.source.url}`))}console.log(),console.log(K.dim(` ${t.length} item${t.length===1?"":"s"} \u2014 ${o.jsonPath()}`))});Ho.command("claim <id> <agent>").description("assign an item to an agent and set status=doing").option("-c, --config <path>","config path").action(async(e,o,t)=>{let n=Xt(t.config);n.store.findById(e)||(console.error(K.red(` item ${e} not found`)),process.exit(1));let i=n.store.update(e,{assignee:o,status:"doing"});if(console.log(K.green(` claimed: ${i.title} -> ${o}`)),i.source){let r=ca([o],i.source,n.config),a=await Is(i,{assigneeUsernames:r,addLabels:["Doing"],removeLabels:["To Do"]},n.config,(...c)=>console.log(K.dim(" sync:"),...c));console.log(a.ok?K.dim(` synced -> ${a.url??i.source.type}`):K.yellow(` sync failed: ${a.error}`))}});Ho.command("done <id>").description("mark an item as done; closes the upstream issue if linked").option("--note <text>","comment to post upstream").option("--close","also close the upstream issue (default: only labels change)",!1).option("-c, --config <path>","config path").action(async(e,o)=>{let t=Xt(o.config);t.store.findById(e)||(console.error(K.red(` item ${e} not found`)),process.exit(1));let s=t.store.update(e,{status:"done"});if(console.log(K.green(` done: ${s.title}`)),s.source){let i=await Is(s,{addLabels:["Done"],removeLabels:["Doing"],state:o.close?"closed":void 0,note:o.note},t.config,(...r)=>console.log(K.dim(" sync:"),...r));console.log(i.ok?K.dim(` synced -> ${i.url??s.source.type}`):K.yellow(` sync failed: ${i.error}`))}});Ho.command("remove <id>").description("remove an item from the local backlog (does NOT touch upstream)").option("-c, --config <path>","config path").action(async(e,o)=>{let{store:t}=Xt(o.config);t.remove(e)||(console.error(K.red(` item ${e} not found`)),process.exit(1)),console.log(K.green(` removed ${e}`))});Ho.command("import").description("import open issues from gitlab/github into the backlog (interactive)").option("--source <type>","source type (gitlab|github)").option("--project <id>","project id (group/repo for gitlab, owner/repo for github)").option("--assignee <agent>","assign all imported items to this agentId").option("-c, --config <path>","config path").action(async e=>{let o=Xt(e.config),t=!!o.config.channels.gitlab?.token,n=!!o.config.channels.github?.token;!t&&!n&&(console.error(K.red(" no source configured \u2014 set channels.gitlab.token or channels.github.token in agentx.json")),process.exit(1));let s=e.source;if(!s){let y=[t&&{title:"GitLab",value:"gitlab"},n&&{title:"GitHub",value:"github"}].filter(Boolean);if(s=(await yt({type:"select",name:"source",message:"Source",choices:y})).source,!s)return}s==="gitlab"&&!t&&(console.error(K.red(" channels.gitlab.token not configured")),process.exit(1)),s==="github"&&!n&&(console.error(K.red(" channels.github.token not configured")),process.exit(1));let i=e.project;if(!i){let y=s==="gitlab"?Ep(o.config):Ap(o.config);y.length?(i=(await yt({type:"autocomplete",name:"project",message:"Project (type to filter, or pick + then Enter for custom)",choices:[...y.map(b=>({title:b,value:b})),{title:"(custom \u2014 type below)",value:"__CUSTOM__"}]})).project,i==="__CUSTOM__"&&(i=(await yt({type:"text",name:"p",message:s==="gitlab"?"Group/path":"owner/repo"})).p)):i=(await yt({type:"text",name:"p",message:s==="gitlab"?"Group/path":"owner/repo"})).p}if(!i)return;let a=((await yt({type:"text",name:"search",message:"Search filter (optional \u2014 leave empty for all open)"})).search||"").trim();console.log(K.dim(` fetching open issues from ${s}:${i}${a?` (search: ${a})`:""}\u2026`));let c=s==="gitlab"?await Op(o.config,i,a):await Tp(o.config,i,a);if(!c.length){console.log(K.yellow(" no open issues matched"));return}console.log(K.dim(` ${c.length} open issue${c.length===1?"":"s"}`));let l=i,g=new Set(o.store.list().map(y=>y.id)),d=c.map(y=>{let k=js({type:s,project:l,iid:y.iid,url:y.url}),b=g.has(k),S=y.labels.length?` [${y.labels.slice(0,3).join(",")}]`:"";return{title:`#${y.iid} ${y.title}${S}${b?K.dim(" (already imported)"):""}`,value:y,disabled:b}}),f=(await yt({type:"autocompleteMultiselect",name:"selected",message:"Pick issues to import (space to toggle, Enter to confirm)",instructions:!1,choices:d,min:1})).selected||[];if(!f.length){console.log(K.dim(" nothing selected"));return}let p=f.map(y=>{let k={type:s,host:s==="gitlab"?Sp(o.config):void 0,project:l,iid:y.iid,url:y.url};return{id:js(k),title:y.title,description:y.description,assignee:e.assignee||y.assignee,labels:y.labels,milestone:y.milestone,status:"todo",source:k,importedAt:new Date().toISOString()}}),w=o.store.addMany(p);console.log(K.green(` imported ${w.length} item${w.length===1?"":"s"}`));for(let y of w)console.log(K.dim(` ${y.id} \u2014 ${y.title}`))});function Sp(e){let o=e.channels.gitlab?.host;if(o)return o.replace(/^https?:\/\//,"").replace(/\/+$/,"")}function Ep(e){let o=new Set;for(let n of e.channels.gitlab?.routes??[])n.project&&n.project!=="*"&&o.add(n.project);let t=e.business?.workSource;if(t?.type==="gitlab")for(let n of t.projects??[])o.add(n);for(let n of e.business?.projects??[])n?.id&&n.id.includes("/")&&o.add(n.id);return[...o].sort()}function Ap(e){let o=new Set;for(let t of e.channels.github?.routes??[])t.repo&&t.repo!=="*"&&o.add(t.repo);return[...o].sort()}async function Op(e,o,t){let n=e.channels.gitlab,s=new URLSearchParams({state:"opened",scope:"all",per_page:"100",order_by:"updated_at",sort:"desc"});t&&s.set("search",t);let i=await fetch(`${n.host}/api/v4/projects/${encodeURIComponent(o)}/issues?${s}`,{headers:{"PRIVATE-TOKEN":n.token}});if(!i.ok)throw new Error(`GitLab ${i.status}: ${await i.text().catch(()=>"")}`);let r=await i.json();return Array.isArray(r)?r.map(a=>({iid:a.iid,title:a.title,description:a.description||void 0,labels:Array.isArray(a.labels)?a.labels.map(c=>typeof c=="string"?c:c.name):[],milestone:a.milestone?.title||void 0,assignee:a.assignee?.username||a.assignees?.[0]?.username||void 0,url:a.web_url})):[]}async function Tp(e,o,t){let s={Authorization:`Bearer ${e.channels.github.token}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28"},i;if(t){let c=`repo:${o} is:issue is:open ${t}`;i=`https://api.github.com/search/issues?q=${encodeURIComponent(c)}&per_page=100&sort=updated&order=desc`;let l=await fetch(i,{headers:s});if(!l.ok)throw new Error(`GitHub ${l.status}: ${await l.text().catch(()=>"")}`);return((await l.json()).items??[]).map(Yc)}i=`https://api.github.com/repos/${o}/issues?state=open&per_page=100&sort=updated&direction=desc`;let r=await fetch(i,{headers:s});if(!r.ok)throw new Error(`GitHub ${r.status}: ${await r.text().catch(()=>"")}`);let a=await r.json();return Array.isArray(a)?a.filter(c=>!c.pull_request).map(Yc):[]}function Yc(e){return{iid:e.number,title:e.title,description:e.body||void 0,labels:Array.isArray(e.labels)?e.labels.map(o=>typeof o=="string"?o:o.name):[],milestone:e.milestone?.title||void 0,assignee:e.assignee?.login||e.assignees?.[0]?.login||void 0,url:e.html_url}}import{Command as jp}from"commander";import q from"chalk";import{existsSync as Ip,readFileSync as Cp}from"fs";import{resolve as Np}from"path";import Rp from"prompts";me();function Vc(e){let o=e||Np(process.cwd(),"agentx.json");return Ip(o)||(console.log(q.red(` No config at ${o}. Run: agentx init`)),process.exit(1)),JSON.parse(Cp(o,"utf-8"))}async function Dp(e,o){if(!e)return;if(e==="me"){let n=o?.notifications?.destination;if(n?.channel&&n?.chatId)return{channel:n.channel,chatId:n.chatId,accountId:n.accountId};console.log(q.yellow(" --notify me: no notifications.destination set yet."));let{channel:s,chatId:i,accountId:r}=await Rp([{type:"text",name:"channel",message:"Destination channel (telegram/whatsapp):"},{type:"text",name:"chatId",message:"Destination chatId:"},{type:"text",name:"accountId",message:"Account id (optional):"}]);return!s||!i?void 0:{channel:s,chatId:i,accountId:r||void 0}}let t=e.split(":");if(t.length>=2)return{channel:t[0],chatId:t[1],accountId:t[2]};console.log(q.red(` Unrecognized --notify value: ${e} (use "me" or "channel:chatId[:account]")`))}var go=new jp().name("schedule").description('schedule agents with natural-language cron: "every morning at 9" --agent devops --do "Post standup"');go.argument("[when]",'natural-language schedule, e.g. "every morning at 9"').option("--agent <id>","agent to run").option("--do <prompt>","prompt to run at each tick (required unless --id exists)").option("--id <name>","explicit cron id (default: auto-slug of <when>-<agent>)").option("--notify <target>",'"me" (use notifications.destination) or "channel:chatId[:accountId]"').option("--on-error <modes>",'comma list of "log|notify|disable" (default: log; notify implies "notify")').option("--timezone <tz>",`IANA timezone (default: ${xs})`,xs).option("--timeout <seconds>","max run time","600").option("--model <model>","override model").option("--disabled","create but leave disabled").option("--dry-run","print what would be written without writing").action(async(e,o)=>{if(!e){go.help();return}o.agent||(console.log(q.red(' --agent is required. Try: agentx schedule "every morning at 9" --agent devops --do "..."')),process.exit(1)),!o.do&&!o.id&&(console.log(q.red(' --do "<prompt>" is required')),process.exit(1));let t=vs(e);t||(console.log(q.red(` Couldn't parse: "${e}"`)),console.log(q.dim(' Try: "every morning at 9", "weekdays at 6pm", "every 15 minutes",')),console.log(q.dim(' "every monday at 10am", "1st of every month at noon",')),console.log(q.dim(' "daily at 9:30am", "every hour", "hourly"')),process.exit(1));let n=Vc(o.config),s=Bi(n);n.agents?.[o.agent]||(console.log(q.red(` Agent "${o.agent}" not found in agentx.json`)),console.log(q.dim(` Available: ${Object.keys(n.agents||{}).join(", ")||"(none)"}`)),process.exit(1));let i=await Dp(o.notify,s),r=o.id||hr(t.matched,o.agent),a=wr({parsed:t,agent:o.agent,prompt:o.do,timezone:o.timezone,timeout:parseInt(o.timeout,10),model:o.model,notify:i,onError:yr(o.onError),enabled:!o.disabled}),c=a.onError,l=await fe(d=>Ee(d,`crons.${r}`,a),{configPath:o.config,dryRun:!!o.dryRun});l.success||(console.log(q.red(` \u2717 ${l.error}`)),process.exit(1));let g=o.dryRun?"would add":"Added";console.log(q.green(` \u2713 ${g} cron ${q.cyan(r)}`)),console.log(q.dim(` Schedule: ${t.cron} (${t.human}, ${o.timezone})`)),console.log(q.dim(` Agent: ${o.agent}`)),i&&console.log(q.dim(` Notify: ${i.channel} ${i.chatId}`)),c.length&&console.log(q.dim(` On error: ${c.join(", ")}`)),!o.dryRun&&l.reloaded&&console.log(q.dim(" Daemon hot-reloaded."))});go.command("list").alias("ls").description("list all scheduled jobs with human-readable descriptions").option("-c, --config <path>","path to agentx.json").action(async e=>{let t=Vc(e.config).crons||{},n=Object.entries(t);if(!n.length){console.log(q.dim(" No scheduled jobs"));return}console.log();for(let[s,i]of n){let r=i.approval?q.yellow("\u25D0"):i.enabled?q.green("\u25CF"):q.dim("\u25CB"),a=i.schedule;try{a=(await import("cronstrue")).default.toString(i.schedule,{use24HourTimeFormat:!1})}catch{}if(console.log(` ${r} ${q.cyan(s.padEnd(32))} ${q.dim(i.schedule.padEnd(14))} ${q.dim("\u2192")} ${i.agent}`),console.log(q.dim(` ${a} (${i.timezone||"UTC"})`)),i.notify&&console.log(q.dim(` notify: ${i.notify.channel} ${i.notify.chatId}`)),i.createdBy&&console.log(q.dim(` created by agent: ${i.createdBy}`)),i.approval){let c=i.timezone||"UTC",l=$r(br(i.schedule,c),c);console.log(q.yellow(` pending ${i.approval.action} approval (requested by ${i.approval.requestedBy}); next fire: ${l}`)),console.log(q.dim(` agentx schedule approve ${s} | agentx schedule reject ${s}`))}}console.log()});for(let[e,o]of[["on",!0],["off",!1]])go.command(`${e} <id>`).description(`${o?"enable":"disable"} a scheduled job`).action(async t=>{let n=await xr(t,o);n.success||(console.log(q.red(` \u2717 ${n.error}`)),process.exit(1)),console.log(q.green(` \u2713 ${t} ${o?"enabled":"disabled"}`)),n.reloaded&&console.log(q.dim(" Daemon hot-reloaded."))});go.command("remove <id>").alias("rm").description("remove a scheduled job").action(async e=>{let o=await fe(t=>{if(!nt(t,`crons.${e}`))throw new Error(`cron "${e}" not found`);pr(t,`crons.${e}`)});o.success||(console.log(q.red(` \u2717 ${o.error}`)),process.exit(1)),console.log(q.green(` \u2713 ${e} removed`)),o.reloaded&&console.log(q.dim(" Daemon hot-reloaded."))});for(let[e,o,t]of[["approve",kr,"approve an agent's pending create/delete request (enables or removes the job)"],["reject",vr,"reject an agent's pending create/delete request (drops the request)"]])go.command(`${e} <id>`).description(t).option("-c, --config <path>","path to agentx.json").action(async(n,s)=>{let i=await o(n,{configPath:s.config});i.success||(console.log(q.red(` \u2717 ${i.message}`)),process.exit(1)),console.log(q.green(` \u2713 ${i.message}`)),i.result?.reloaded&&console.log(q.dim(" Daemon hot-reloaded."))});go.command("parse <when...>").description("preview a natural-language parse without writing anything").action(e=>{let o=e.join(" "),t=vs(o);t||(console.log(q.red(` \u2717 could not parse: "${o}"`)),process.exit(1)),console.log(q.green(` "${o}"`)),console.log(q.dim(` \u2192 ${t.cron}`)),console.log(q.dim(` \u2192 ${t.human}`))});import{Command as nu}from"commander";import wt from"chalk";import Z from"chalk";import Zt from"prompts";import{readFileSync as _p,writeFileSync as Pp,existsSync as Mp}from"fs";import{resolve as Kc}from"path";var Lp=/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;function Fp(e){let o=e.trim();return o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'")?o.slice(1,-1):o}function mi(e){return/[\s#"'\\]/.test(e)||e===""?JSON.stringify(e):e}function Xc(e=".env"){let o=Kc(e);if(!Mp(o))return[];let t=_p(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(Lp);i?n.push({kind:"kv",key:i[1],value:Fp(i[2]),raw:s}):n.push({kind:"comment",raw:s})}return n.length&&n[n.length-1].kind==="blank"&&n.pop(),n}function Up(e){return e.map(o=>o.kind==="kv"?`${o.key}=${mi(o.value)}`:o.raw).join(`
|
|
381
381
|
`)+`
|
|
382
|
-
`}function Qt(e,o,t=".env"){let n=Kc(t),s=Xc(n),i=s.findIndex(r=>r.kind==="kv"&&r.key===e);i>=0?s[i]={kind:"kv",key:e,value:o,raw:`${e}=${mi(o)}`}:(s.length&&s[s.length-1].kind!=="blank"&&s.push({kind:"blank",raw:""}),s.push({kind:"kv",key:e,value:o,raw:`${e}=${mi(o)}`})),Pp(n,Up(s))}function pi(e,o=".env"){return Xc(o).find(s=>s.kind==="kv"&&s.key===e)?.value}var Qc="https://t.me/BotFather";async function qp(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 Wp(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 Zc(e={}){console.log(),console.log(Z.bold(" Connect Telegram")),console.log(),console.log(Z.dim(` 1. Open ${Qc}`)),console.log(Z.dim(" /newbot (or /mybots \u2192 pick existing \u2192 API Token)")),console.log(Z.dim(" 2. Copy the HTTP API token \u2014 looks like 123456789:ABCdef...")),console.log();let{openBrowser:o}=await Zt({type:"confirm",name:"openBrowser",message:"Open BotFather in your browser?",initial:!0});if(o)try{let{spawn:b}=await import("child_process"),S=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";b(S,[Qc],{stdio:"ignore",detached:!0}).unref()}catch{}let{token:t}=await Zt({type:"password",name:"token",message:"Paste the bot token from BotFather:",validate:b=>/^\d+:[A-Za-z0-9_-]{20,}$/.test(b.trim())||"That doesn't look like a Telegram token"});t||(console.log(Z.red(" Aborted")),process.exit(1)),process.stdout.write(" Verifying token... ");let n=await qp(t.trim());n||(console.log(Z.red("\u2717 invalid or revoked")),process.exit(1)),console.log(Z.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(Z.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(Z.red(" No agents configured. Run: agentx agent add")),process.exit(1));let g=e.agent;g||(g=(await Zt({type:"select",name:"agent",message:"Bind this bot to which agent?",choices:l.map(S=>({title:S,value:S})),initial:0})).agent),g||(console.log(Z.red(" Aborted")),process.exit(1));let d=c.channels?.telegram?.accounts||{},u=e.account||g;d[u]&&d[u].agentBinding!==g&&(u=(await Zt({type:"text",name:"account",message:`Account "${u}" is already in use. Pick a different label:`,initial:`${g}-2`,validate:S=>/^[a-z0-9-]+$/i.test(S)||"lowercase letters, digits, hyphens only"})).account),u||(console.log(Z.red(" Aborted")),process.exit(1));let f=`TG_${u.toUpperCase().replace(/-/g,"_")}_BOT_TOKEN`;Qt(f,t.trim()),process.env[f]=t.trim();let p=await fe(b=>{Ee(b,"channels.telegram.enabled",!0),Ee(b,`channels.telegram.accounts.${u}`,{token:`\${${f}}`,agentBinding:g});let S=nt(b,`agents.${g}.mentions`)||[],A=`@${n.username}`;S.includes(A)||(S.push(A),Ee(b,`agents.${g}.mentions`,S))},{configPath:e.configPath});if(p.success||(console.log(Z.red(` \u2717 ${p.error}`)),process.exit(1)),console.log(),console.log(Z.green(` \u2713 Bot @${n.username} bound to agent "${g}"`)),console.log(Z.dim(` Token stored in .env as ${f}`)),console.log(Z.dim(` Mentions updated to include @${n.username}`)),p.reloaded?console.log(Z.dim(" Daemon hot-reloaded.")):console.log(Z.dim(" Start the daemon to begin polling (agentx daemon start)")),e.skipChatCapture)return;console.log();let{capture:w}=await Zt({type:"confirm",name:"capture",message:"Listen for a message so we can set this as your default --notify target?",initial:!0});if(!w)return;console.log(),console.log(Z.dim(` Send any message to @${n.username} from the chat you want to use.`)),console.log(Z.dim(" Waiting up to 90s..."));let y=await Wp(t.trim(),9e4);if(!y){console.log(Z.yellow(" No message received \u2014 skipping. You can set it later with:")),console.log(Z.dim(" agentx config set notifications.destination.channel telegram")),console.log(Z.dim(" agentx config set notifications.destination.chatId <chatId>")),console.log(Z.dim(` agentx config set notifications.destination.accountId ${u}`));return}let k=await fe(b=>{Ee(b,"notifications.destination",{channel:"telegram",chatId:String(y.chatId),accountId:u})},{configPath:e.configPath});if(!k.success){console.log(Z.red(` \u2717 failed to save destination: ${k.error}`));return}console.log(Z.green(" \u2713 Default --notify target set")),console.log(Z.dim(` Chat: ${y.chatTitle||y.chatId} (from ${y.from})`)),console.log(Z.dim(" From now on, --notify me resolves to this chat.")),k.reloaded&&console.log(Z.dim(" Daemon hot-reloaded."))}import ye from"chalk";import ui from"prompts";import{existsSync as hi,mkdirSync as Bp,readdirSync as Jp,readFileSync as el}from"fs";import{resolve as fi}from"path";var Gp=".agentx/whatsapp-sessions";function Hp(){let e=fi(process.cwd(),".agentx/daemon.pid");if(!hi(e))return!1;try{let o=parseInt(el(e,"utf-8").trim(),10);return o?(process.kill(o,0),!0):!1}catch{return!1}}function zp(e){if(!hi(e))return!1;try{return Jp(e).some(o=>o.includes("creds")||o.endsWith(".json"))}catch{return!1}}async function Yp(e,o){let t;try{t=await import("@whiskeysockets/baileys")}catch{return o(ye.red(" WhatsApp pairing needs @whiskeysockets/baileys.")),o(ye.red(" Install with: pnpm add @whiskeysockets/baileys (or npm install)")),!1}let{makeWASocket:n,useMultiFileAuthState:s}=t.default||t;Bp(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(ye.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(ye.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(ye.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(ye.red(" \u2717 Authorization failed \u2014 rescan required")),g(!1))})})}async function ol(e={}){if(console.log(),console.log(ye.bold(" Connect WhatsApp")),console.log(),Hp()){console.log(ye.yellow(" \u26A0 The daemon is running. Stop it first so pairing can open a fresh Baileys session:")),console.log(ye.dim(" agentx daemon stop")),console.log();let{cont:l}=await ui({type:"confirm",name:"cont",message:"Continue anyway? (expect errors)",initial:!1});l||(console.log(ye.red(" Aborted")),process.exit(1))}let o=e.configPath||fi(process.cwd(),"agentx.json");hi(o)||(console.log(ye.red(` No agentx.json at ${o}. Run: agentx init`)),process.exit(1));let t=JSON.parse(el(o,"utf-8")),n=e.sessionDir||t.channels?.whatsapp?.sessionDir||Gp,s=fi(process.cwd(),n),i=Object.keys(t.agents||{});i.length===0&&(console.log(ye.red(" No agents configured. Run: agentx agent add")),process.exit(1));let r=e.agent;r||(r=(await ui({type:"select",name:"agent",message:"Default agent for incoming messages:",choices:i.map(g=>({title:g,value:g})),initial:0})).agent),r||(console.log(ye.red(" Aborted")),process.exit(1));let a=!e.skipPair;if(zp(s)&&a){let{keep:l}=await ui({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(ye.dim(" Keeping existing session \u2014 skipping QR pair."))}a&&(await Yp(s,g=>console.log(g))||(console.log(ye.red(" Pairing failed. You can retry with `agentx connect whatsapp`.")),process.exit(1)));let c=await fe(l=>{Ee(l,"channels.whatsapp.enabled",!0),Ee(l,"channels.whatsapp.sessionDir",n),Ee(l,"channels.whatsapp.defaultAgent",r)},{configPath:e.configPath});c.success||(console.log(ye.red(` \u2717 ${c.error}`)),process.exit(1)),console.log(),console.log(ye.green(` \u2713 WhatsApp bound to agent "${r}"`)),console.log(ye.dim(` Session: ${n}`)),console.log(ye.dim(" Start the daemon to begin receiving:")),console.log(ye.dim(" agentx daemon start")),console.log(ye.dim(" Add routes later with:")),console.log(ye.dim(` agentx config set channels.whatsapp.routes '[{"contact":"+1234567890","agent":"${r}"}]'`)),console.log()}import{randomBytes as Vp}from"crypto";import ve from"chalk";import tl from"prompts";var Xn="agentx-mesh:",Qn="//join/";function Kp(e){return Buffer.from(e,"utf-8").toString("base64url")}function Xp(e){return Buffer.from(e,"base64url").toString("utf-8")}function Qp(e){return`${Xn}${Qn}${Kp(JSON.stringify(e))}`}function Zp(e){if(!e.startsWith(`${Xn}${Qn}`))throw new Error(`Not a mesh invite link \u2014 expected ${Xn}${Qn}\u2026`);let o=e.slice(Xn.length+Qn.length),t=JSON.parse(Xp(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 eu(){return Vp(32).toString("hex")}function ou(e){let o=e?.node?.bind||"127.0.0.1:18800",[t,n]=o.split(":");return`http://${t}:${n}`}function tu(e){return e?.node?.name||e?.node?.id||"node"}async function nl(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(ve.red(` No agentx.json at ${s}. Run: agentx init`)),process.exit(1));let i=JSON.parse(o(s,"utf-8")),r=pi("MESH_TOKEN");r||(r=eu(),Qt("MESH_TOKEN",r),console.log(ve.dim(" Generated new MESH_TOKEN (32 bytes) and saved to .env")));let a=e.url||ou(i);if((a.includes("0.0.0.0")||a.includes("127.0.0.1")||a.includes("localhost"))&&!e.url){let{url:d}=await tl({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(ve.red(" Aborted")),process.exit(1)),a=d}let l=await fe(d=>{Ee(d,"mesh.enabled",!0)},{configPath:e.configPath});l.success||(console.log(ve.red(` \u2717 ${l.error}`)),process.exit(1));let g=Qp({url:a,token:r,name:tu(i),version:1});console.log(),console.log(ve.bold(" Mesh invite")),console.log(),console.log(` ${ve.cyan(g)}`),console.log(),console.log(ve.dim(" Run on the other node:")),console.log(ve.dim(` agentx connect mesh join "${g}"`)),console.log(),console.log(ve.yellow(" Share over a trusted channel only \u2014 whoever holds this link can join your mesh.")),console.log()}async function sl(e,o={}){let t;try{t=Zp(e)}catch(i){console.log(ve.red(` \u2717 ${i.message}`)),process.exit(1)}let n=pi("MESH_TOKEN");if(n&&n!==t.token){let{overwrite:i}=await tl({type:"confirm",name:"overwrite",message:"A different MESH_TOKEN already exists in .env. Overwrite with the invite's token?",initial:!1});i||(console.log(ve.red(" Aborted (keeping existing .env)")),process.exit(1))}Qt("MESH_TOKEN",t.token);let s=await fe(i=>{Ee(i,"mesh.enabled",!0);let r=nt(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),Ee(i,"mesh.peers",r)},{configPath:o.configPath});s.success||(console.log(ve.red(` \u2717 ${s.error}`)),process.exit(1)),console.log(ve.green(" \u2713 Joined mesh")),console.log(ve.dim(` Peer: ${t.name} @ ${t.url}`)),console.log(ve.dim(" Shared token stored in .env as MESH_TOKEN")),s.reloaded?console.log(ve.dim(" Daemon hot-reloaded.")):console.log(ve.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(ve.dim(` Reachable \u2014 ${t.name} exposes ${a} agents`))}else console.log(ve.yellow(` Peer returned HTTP ${i.status} \u2014 double-check the URL`))}catch(i){console.log(ve.yellow(` Could not reach ${t.url} right now (${i?.cause?.code||i.message}) \u2014 verify VPN / Tailscale when the peer daemon is up`))}}var bt=new nu().name("connect").description("connect a channel or mesh peer \u2014 no manual file editing required");bt.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 Zc({agent:e.agent,account:e.account,configPath:e.config,skipChatCapture:!!e.skipChatCapture})});bt.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 ol({agent:e.agent,sessionDir:e.sessionDir,skipPair:!!e.skipPair,configPath:e.config})});var il=bt.command("mesh").description("mesh invite + join \u2014 replaces manual MESH_TOKEN copy-paste");il.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 nl({url:e.url,configPath:e.config})});il.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 sl(e,{configPath:o.config})});bt.action(()=>{console.log(),console.log(wt.bold(" agentx connect \u2014 which channel?")),console.log(),console.log(` ${wt.cyan("agentx connect telegram")} \u2014 pair a Telegram bot`),console.log(` ${wt.cyan("agentx connect whatsapp")} \u2014 pair WhatsApp via QR`),console.log(` ${wt.cyan("agentx connect mesh invite")} \u2014 emit a mesh join link for another node`),console.log(` ${wt.cyan("agentx connect mesh join <link>")} \u2014 accept a mesh invite`),console.log(),console.log(wt.dim(" GitLab connect is the next slice.")),console.log()});me();import{Command as su}from"commander";import ge from"chalk";var en=new su().name("usage").description("token usage analysis and reporting");en.command("today",{isDefault:!0}).description("show today's token usage").action(async()=>{try{let e=_(),[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(ge.bold(" Token Usage (last 7 days)")),console.log(),s.totalTasks===0){console.log(ge.dim(" No tasks recorded yet")),console.log();return}let i=a=>a.toLocaleString();console.log(` Total: ${ge.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: ${ge.red(String(s.totalErrors))}`),console.log(),console.log(ge.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(` ${ge.cyan(a)}: ${l} tokens (${c.tasks} tasks) ${ge.dim(g)}`)}console.log()}catch(e){e.cause?.code==="ECONNREFUSED"?console.log(ge.red(" Daemon not running. Start with: agentx daemon start")):console.log(ge.red(` ${e.message}`))}});en.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(ge.red(` Script not found: ${s}`)),console.log(ge.dim(" The token analyzer script should be at scripts/token-report.py"));return}console.log(ge.dim(" Analyzing Claude Code sessions..."));try{o(`SINCE_DAYS=${e.days} python3 "${s}"`,{stdio:"inherit"})}catch{console.log(ge.red(" Analysis failed. Is Python 3 installed?"))}});en.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-UREILT2E.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-4RO4NCBU.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(ge.bold(` Never used in the last ${e.days} days (${g.length}/${c.length})`)),console.log();for(let d of g)console.log(` ${ge.dim("\xB7")} ${d}`);console.log(),console.log(ge.dim(" Zero use is necessary but not sufficient to remove a surface \u2014")),console.log(ge.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(ge.dim(` No surface usage recorded in the last ${e.days} days.`)),console.log(ge.dim(" Counting starts once this build has been running for a while.")),console.log();return}console.log(),console.log(ge.bold(` Surface usage \u2014 last ${e.days} days`)),console.log();let s="";for(let i of n){i.kind!==s&&(console.log(ge.dim(` ${i.kind==="cli"?"CLI commands":"Dashboard pages"}`)),s=i.kind);let r=String(i.count).padStart(6),a=ge.dim(`${i.days}d`);console.log(` ${ge.cyan(r)} ${i.name.padEnd(28)} ${a}`)}console.log(),console.log(ge.dim(` ${n.length} surface(s) with recorded use. See --unused for the rest.`)),console.log()});import{Command as iu}from"commander";import we from"chalk";import{resolve as ru}from"path";me();var Ao=new iu().name("board").description("kanban board dashboard \u2014 visual work view over configured sources");Ao.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{Zi(ru(process.cwd(),".env"))}catch{}let o=au(e.port,e.bind),{startBoardDashboard:t}=await import("./board-dashboard-U5YP4HWE.js");t(o)}catch(o){console.log(we.red(` ${o.message}`)),process.env.DEBUG&&o.stack&&console.log(we.dim(o.stack)),process.exit(1)}});function au(e,o){try{let t=_();return e&&(t.dashboard.port=parseInt(e,10)),o&&(t.dashboard.bind=o),t}catch{return console.log(we.yellow(" No agentx.json found \u2014 starting dashboard in setup-only mode.")),console.log(we.dim(" Visit http://127.0.0.1:"+(e||"4202")+` to run the wizard.
|
|
382
|
+
`}function Qt(e,o,t=".env"){let n=Kc(t),s=Xc(n),i=s.findIndex(r=>r.kind==="kv"&&r.key===e);i>=0?s[i]={kind:"kv",key:e,value:o,raw:`${e}=${mi(o)}`}:(s.length&&s[s.length-1].kind!=="blank"&&s.push({kind:"blank",raw:""}),s.push({kind:"kv",key:e,value:o,raw:`${e}=${mi(o)}`})),Pp(n,Up(s))}function pi(e,o=".env"){return Xc(o).find(s=>s.kind==="kv"&&s.key===e)?.value}var Qc="https://t.me/BotFather";async function qp(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 Wp(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 Zc(e={}){console.log(),console.log(Z.bold(" Connect Telegram")),console.log(),console.log(Z.dim(` 1. Open ${Qc}`)),console.log(Z.dim(" /newbot (or /mybots \u2192 pick existing \u2192 API Token)")),console.log(Z.dim(" 2. Copy the HTTP API token \u2014 looks like 123456789:ABCdef...")),console.log();let{openBrowser:o}=await Zt({type:"confirm",name:"openBrowser",message:"Open BotFather in your browser?",initial:!0});if(o)try{let{spawn:b}=await import("child_process"),S=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";b(S,[Qc],{stdio:"ignore",detached:!0}).unref()}catch{}let{token:t}=await Zt({type:"password",name:"token",message:"Paste the bot token from BotFather:",validate:b=>/^\d+:[A-Za-z0-9_-]{20,}$/.test(b.trim())||"That doesn't look like a Telegram token"});t||(console.log(Z.red(" Aborted")),process.exit(1)),process.stdout.write(" Verifying token... ");let n=await qp(t.trim());n||(console.log(Z.red("\u2717 invalid or revoked")),process.exit(1)),console.log(Z.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(Z.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(Z.red(" No agents configured. Run: agentx agent add")),process.exit(1));let g=e.agent;g||(g=(await Zt({type:"select",name:"agent",message:"Bind this bot to which agent?",choices:l.map(S=>({title:S,value:S})),initial:0})).agent),g||(console.log(Z.red(" Aborted")),process.exit(1));let d=c.channels?.telegram?.accounts||{},u=e.account||g;d[u]&&d[u].agentBinding!==g&&(u=(await Zt({type:"text",name:"account",message:`Account "${u}" is already in use. Pick a different label:`,initial:`${g}-2`,validate:S=>/^[a-z0-9-]+$/i.test(S)||"lowercase letters, digits, hyphens only"})).account),u||(console.log(Z.red(" Aborted")),process.exit(1));let f=`TG_${u.toUpperCase().replace(/-/g,"_")}_BOT_TOKEN`;Qt(f,t.trim()),process.env[f]=t.trim();let p=await fe(b=>{Ee(b,"channels.telegram.enabled",!0),Ee(b,`channels.telegram.accounts.${u}`,{token:`\${${f}}`,agentBinding:g});let S=nt(b,`agents.${g}.mentions`)||[],A=`@${n.username}`;S.includes(A)||(S.push(A),Ee(b,`agents.${g}.mentions`,S))},{configPath:e.configPath});if(p.success||(console.log(Z.red(` \u2717 ${p.error}`)),process.exit(1)),console.log(),console.log(Z.green(` \u2713 Bot @${n.username} bound to agent "${g}"`)),console.log(Z.dim(` Token stored in .env as ${f}`)),console.log(Z.dim(` Mentions updated to include @${n.username}`)),p.reloaded?console.log(Z.dim(" Daemon hot-reloaded.")):console.log(Z.dim(" Start the daemon to begin polling (agentx daemon start)")),e.skipChatCapture)return;console.log();let{capture:w}=await Zt({type:"confirm",name:"capture",message:"Listen for a message so we can set this as your default --notify target?",initial:!0});if(!w)return;console.log(),console.log(Z.dim(` Send any message to @${n.username} from the chat you want to use.`)),console.log(Z.dim(" Waiting up to 90s..."));let y=await Wp(t.trim(),9e4);if(!y){console.log(Z.yellow(" No message received \u2014 skipping. You can set it later with:")),console.log(Z.dim(" agentx config set notifications.destination.channel telegram")),console.log(Z.dim(" agentx config set notifications.destination.chatId <chatId>")),console.log(Z.dim(` agentx config set notifications.destination.accountId ${u}`));return}let k=await fe(b=>{Ee(b,"notifications.destination",{channel:"telegram",chatId:String(y.chatId),accountId:u})},{configPath:e.configPath});if(!k.success){console.log(Z.red(` \u2717 failed to save destination: ${k.error}`));return}console.log(Z.green(" \u2713 Default --notify target set")),console.log(Z.dim(` Chat: ${y.chatTitle||y.chatId} (from ${y.from})`)),console.log(Z.dim(" From now on, --notify me resolves to this chat.")),k.reloaded&&console.log(Z.dim(" Daemon hot-reloaded."))}import ye from"chalk";import ui from"prompts";import{existsSync as hi,mkdirSync as Bp,readdirSync as Jp,readFileSync as el}from"fs";import{resolve as fi}from"path";var Gp=".agentx/whatsapp-sessions";function Hp(){let e=fi(process.cwd(),".agentx/daemon.pid");if(!hi(e))return!1;try{let o=parseInt(el(e,"utf-8").trim(),10);return o?(process.kill(o,0),!0):!1}catch{return!1}}function zp(e){if(!hi(e))return!1;try{return Jp(e).some(o=>o.includes("creds")||o.endsWith(".json"))}catch{return!1}}async function Yp(e,o){let t;try{t=await import("@whiskeysockets/baileys")}catch{return o(ye.red(" WhatsApp pairing needs @whiskeysockets/baileys.")),o(ye.red(" Install with: pnpm add @whiskeysockets/baileys (or npm install)")),!1}let{makeWASocket:n,useMultiFileAuthState:s}=t.default||t;Bp(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(ye.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(ye.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(ye.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(ye.red(" \u2717 Authorization failed \u2014 rescan required")),g(!1))})})}async function ol(e={}){if(console.log(),console.log(ye.bold(" Connect WhatsApp")),console.log(),Hp()){console.log(ye.yellow(" \u26A0 The daemon is running. Stop it first so pairing can open a fresh Baileys session:")),console.log(ye.dim(" agentx daemon stop")),console.log();let{cont:l}=await ui({type:"confirm",name:"cont",message:"Continue anyway? (expect errors)",initial:!1});l||(console.log(ye.red(" Aborted")),process.exit(1))}let o=e.configPath||fi(process.cwd(),"agentx.json");hi(o)||(console.log(ye.red(` No agentx.json at ${o}. Run: agentx init`)),process.exit(1));let t=JSON.parse(el(o,"utf-8")),n=e.sessionDir||t.channels?.whatsapp?.sessionDir||Gp,s=fi(process.cwd(),n),i=Object.keys(t.agents||{});i.length===0&&(console.log(ye.red(" No agents configured. Run: agentx agent add")),process.exit(1));let r=e.agent;r||(r=(await ui({type:"select",name:"agent",message:"Default agent for incoming messages:",choices:i.map(g=>({title:g,value:g})),initial:0})).agent),r||(console.log(ye.red(" Aborted")),process.exit(1));let a=!e.skipPair;if(zp(s)&&a){let{keep:l}=await ui({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(ye.dim(" Keeping existing session \u2014 skipping QR pair."))}a&&(await Yp(s,g=>console.log(g))||(console.log(ye.red(" Pairing failed. You can retry with `agentx connect whatsapp`.")),process.exit(1)));let c=await fe(l=>{Ee(l,"channels.whatsapp.enabled",!0),Ee(l,"channels.whatsapp.sessionDir",n),Ee(l,"channels.whatsapp.defaultAgent",r)},{configPath:e.configPath});c.success||(console.log(ye.red(` \u2717 ${c.error}`)),process.exit(1)),console.log(),console.log(ye.green(` \u2713 WhatsApp bound to agent "${r}"`)),console.log(ye.dim(` Session: ${n}`)),console.log(ye.dim(" Start the daemon to begin receiving:")),console.log(ye.dim(" agentx daemon start")),console.log(ye.dim(" Add routes later with:")),console.log(ye.dim(` agentx config set channels.whatsapp.routes '[{"contact":"+1234567890","agent":"${r}"}]'`)),console.log()}import{randomBytes as Vp}from"crypto";import ve from"chalk";import tl from"prompts";var Xn="agentx-mesh:",Qn="//join/";function Kp(e){return Buffer.from(e,"utf-8").toString("base64url")}function Xp(e){return Buffer.from(e,"base64url").toString("utf-8")}function Qp(e){return`${Xn}${Qn}${Kp(JSON.stringify(e))}`}function Zp(e){if(!e.startsWith(`${Xn}${Qn}`))throw new Error(`Not a mesh invite link \u2014 expected ${Xn}${Qn}\u2026`);let o=e.slice(Xn.length+Qn.length),t=JSON.parse(Xp(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 eu(){return Vp(32).toString("hex")}function ou(e){let o=e?.node?.bind||"127.0.0.1:18800",[t,n]=o.split(":");return`http://${t}:${n}`}function tu(e){return e?.node?.name||e?.node?.id||"node"}async function nl(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(ve.red(` No agentx.json at ${s}. Run: agentx init`)),process.exit(1));let i=JSON.parse(o(s,"utf-8")),r=pi("MESH_TOKEN");r||(r=eu(),Qt("MESH_TOKEN",r),console.log(ve.dim(" Generated new MESH_TOKEN (32 bytes) and saved to .env")));let a=e.url||ou(i);if((a.includes("0.0.0.0")||a.includes("127.0.0.1")||a.includes("localhost"))&&!e.url){let{url:d}=await tl({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(ve.red(" Aborted")),process.exit(1)),a=d}let l=await fe(d=>{Ee(d,"mesh.enabled",!0)},{configPath:e.configPath});l.success||(console.log(ve.red(` \u2717 ${l.error}`)),process.exit(1));let g=Qp({url:a,token:r,name:tu(i),version:1});console.log(),console.log(ve.bold(" Mesh invite")),console.log(),console.log(` ${ve.cyan(g)}`),console.log(),console.log(ve.dim(" Run on the other node:")),console.log(ve.dim(` agentx connect mesh join "${g}"`)),console.log(),console.log(ve.yellow(" Share over a trusted channel only \u2014 whoever holds this link can join your mesh.")),console.log()}async function sl(e,o={}){let t;try{t=Zp(e)}catch(i){console.log(ve.red(` \u2717 ${i.message}`)),process.exit(1)}let n=pi("MESH_TOKEN");if(n&&n!==t.token){let{overwrite:i}=await tl({type:"confirm",name:"overwrite",message:"A different MESH_TOKEN already exists in .env. Overwrite with the invite's token?",initial:!1});i||(console.log(ve.red(" Aborted (keeping existing .env)")),process.exit(1))}Qt("MESH_TOKEN",t.token);let s=await fe(i=>{Ee(i,"mesh.enabled",!0);let r=nt(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),Ee(i,"mesh.peers",r)},{configPath:o.configPath});s.success||(console.log(ve.red(` \u2717 ${s.error}`)),process.exit(1)),console.log(ve.green(" \u2713 Joined mesh")),console.log(ve.dim(` Peer: ${t.name} @ ${t.url}`)),console.log(ve.dim(" Shared token stored in .env as MESH_TOKEN")),s.reloaded?console.log(ve.dim(" Daemon hot-reloaded.")):console.log(ve.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(ve.dim(` Reachable \u2014 ${t.name} exposes ${a} agents`))}else console.log(ve.yellow(` Peer returned HTTP ${i.status} \u2014 double-check the URL`))}catch(i){console.log(ve.yellow(` Could not reach ${t.url} right now (${i?.cause?.code||i.message}) \u2014 verify VPN / Tailscale when the peer daemon is up`))}}var bt=new nu().name("connect").description("connect a channel or mesh peer \u2014 no manual file editing required");bt.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 Zc({agent:e.agent,account:e.account,configPath:e.config,skipChatCapture:!!e.skipChatCapture})});bt.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 ol({agent:e.agent,sessionDir:e.sessionDir,skipPair:!!e.skipPair,configPath:e.config})});var il=bt.command("mesh").description("mesh invite + join \u2014 replaces manual MESH_TOKEN copy-paste");il.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 nl({url:e.url,configPath:e.config})});il.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 sl(e,{configPath:o.config})});bt.action(()=>{console.log(),console.log(wt.bold(" agentx connect \u2014 which channel?")),console.log(),console.log(` ${wt.cyan("agentx connect telegram")} \u2014 pair a Telegram bot`),console.log(` ${wt.cyan("agentx connect whatsapp")} \u2014 pair WhatsApp via QR`),console.log(` ${wt.cyan("agentx connect mesh invite")} \u2014 emit a mesh join link for another node`),console.log(` ${wt.cyan("agentx connect mesh join <link>")} \u2014 accept a mesh invite`),console.log(),console.log(wt.dim(" GitLab connect is the next slice.")),console.log()});me();import{Command as su}from"commander";import ge from"chalk";var en=new su().name("usage").description("token usage analysis and reporting");en.command("today",{isDefault:!0}).description("show today's token usage").action(async()=>{try{let e=_(),[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(ge.bold(" Token Usage (last 7 days)")),console.log(),s.totalTasks===0){console.log(ge.dim(" No tasks recorded yet")),console.log();return}let i=a=>a.toLocaleString();console.log(` Total: ${ge.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: ${ge.red(String(s.totalErrors))}`),console.log(),console.log(ge.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(` ${ge.cyan(a)}: ${l} tokens (${c.tasks} tasks) ${ge.dim(g)}`)}console.log()}catch(e){e.cause?.code==="ECONNREFUSED"?console.log(ge.red(" Daemon not running. Start with: agentx daemon start")):console.log(ge.red(` ${e.message}`))}});en.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(ge.red(` Script not found: ${s}`)),console.log(ge.dim(" The token analyzer script should be at scripts/token-report.py"));return}console.log(ge.dim(" Analyzing Claude Code sessions..."));try{o(`SINCE_DAYS=${e.days} python3 "${s}"`,{stdio:"inherit"})}catch{console.log(ge.red(" Analysis failed. Is Python 3 installed?"))}});en.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-UREILT2E.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-WLPVWTAT.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(ge.bold(` Never used in the last ${e.days} days (${g.length}/${c.length})`)),console.log();for(let d of g)console.log(` ${ge.dim("\xB7")} ${d}`);console.log(),console.log(ge.dim(" Zero use is necessary but not sufficient to remove a surface \u2014")),console.log(ge.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(ge.dim(` No surface usage recorded in the last ${e.days} days.`)),console.log(ge.dim(" Counting starts once this build has been running for a while.")),console.log();return}console.log(),console.log(ge.bold(` Surface usage \u2014 last ${e.days} days`)),console.log();let s="";for(let i of n){i.kind!==s&&(console.log(ge.dim(` ${i.kind==="cli"?"CLI commands":"Dashboard pages"}`)),s=i.kind);let r=String(i.count).padStart(6),a=ge.dim(`${i.days}d`);console.log(` ${ge.cyan(r)} ${i.name.padEnd(28)} ${a}`)}console.log(),console.log(ge.dim(` ${n.length} surface(s) with recorded use. See --unused for the rest.`)),console.log()});import{Command as iu}from"commander";import we from"chalk";import{resolve as ru}from"path";me();var Ao=new iu().name("board").description("kanban board dashboard \u2014 visual work view over configured sources");Ao.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{Zi(ru(process.cwd(),".env"))}catch{}let o=au(e.port,e.bind),{startBoardDashboard:t}=await import("./board-dashboard-U5YP4HWE.js");t(o)}catch(o){console.log(we.red(` ${o.message}`)),process.env.DEBUG&&o.stack&&console.log(we.dim(o.stack)),process.exit(1)}});function au(e,o){try{let t=_();return e&&(t.dashboard.port=parseInt(e,10)),o&&(t.dashboard.bind=o),t}catch{return console.log(we.yellow(" No agentx.json found \u2014 starting dashboard in setup-only mode.")),console.log(we.dim(" Visit http://127.0.0.1:"+(e||"4202")+` to run the wizard.
|
|
383
383
|
`)),{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}}}}Ao.command("list").description("list configured boards").action(()=>{try{let e=_();if(!e.boards?.length){console.log(we.dim(`
|
|
384
384
|
No boards configured.
|
|
385
385
|
`));return}console.log();for(let o of e.boards){console.log(` ${we.cyan(o.id)} \u2014 ${o.name}`);let t=o.source;console.log(we.dim(` source: ${t.type}${t.projects?" ("+t.projects.join(", ")+")":""}`)),o.primaryToolLabel&&console.log(we.dim(` primary label: ${o.primaryToolLabel}`)),console.log(we.dim(` window: ${o.timeRangeDays} days`))}console.log()}catch(e){console.log(we.red(` ${e.message}`)),process.exit(1)}});Ao.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{on(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(we.red(` ${t.message}`)),process.exit(1)}});Ao.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{on(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(we.red(` ${t.message}`)),process.exit(1)}});var yi=Ao.command("column").description("manage a board's columns (add / remove / edit / list)");yi.command("list <boardId>").description("list columns on a board, in order").action(e=>{try{let t=(JSON.parse(ed("fs").readFileSync("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(we.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(` ${we.cyan(s.id.padEnd(12))} ${s.title.padEnd(14)} ${we.dim(i)}`)}}catch(o){console.log(we.red(` ${o.message}`)),process.exit(1)}});yi.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{on(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(we.red(` ${n.message}`)),process.exit(1)}});yi.command("remove <boardId> <columnId>").alias("rm").description("remove a column from a board").action((e,o)=>{try{on(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(we.red(` ${t.message}`)),process.exit(1)}});Ao.command("remove <id>").alias("rm").description("remove a board from agentx.json").action(e=>{try{on(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(we.red(` ${o.message}`)),process.exit(1)}});function on(e){let{summary:o,backupPath:t}=_o(n=>e(n));console.log(we.green(`
|
|
@@ -600,7 +600,7 @@ Restart the daemon to activate.
|
|
|
600
600
|
dist/
|
|
601
601
|
*.log
|
|
602
602
|
.env
|
|
603
|
-
`}import{Command as Ff}from"commander";import je from"chalk";import{writeFileSync as Uf,mkdirSync as qf,existsSync as us,readFileSync as Hl,appendFileSync as zl}from"fs";import{resolve as Tt,dirname as Kl}from"path";import{homedir as Fi}from"os";var Xl=new Ff().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-
|
|
603
|
+
`}import{Command as Ff}from"commander";import je from"chalk";import{writeFileSync as Uf,mkdirSync as qf,existsSync as us,readFileSync as Hl,appendFileSync as zl}from"fs";import{resolve as Tt,dirname as Kl}from"path";import{homedir as Fi}from"os";var Xl=new Ff().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-WLPVWTAT.js"),t=await o(),n=String(e.shell||"zsh").toLowerCase(),s;switch(n){case"zsh":s=Jf(t);break;case"bash":s=Vf(t);break;case"fish":s=Kf(t);break;default:console.error(je.red(`unsupported shell: ${n}`)),console.error(je.dim("supported: zsh, bash, fish")),process.exit(1)}if(!e.install&&!e.output){process.stdout.write(s);return}let i=e.output?Tt(String(e.output)):Wf(n);qf(Kl(i),{recursive:!0}),Uf(i,s),console.log(je.green(`\u2713 Wrote ${n} completion to:`)),console.log(` ${i}`),console.log(),Bf(n,i,!!e.yes)});function Wf(e){let o=Fi();switch(e){case"zsh":return Tt(o,".zsh","completions","_agentx");case"bash":return Tt(o,".bash_completion.d","agentx.bash");case"fish":return Tt(o,".config","fish","completions","agentx.fish");default:throw new Error(`unsupported shell: ${e}`)}}function Bf(e,o,t){if(e==="zsh"){let n=Tt(Fi(),".zshrc"),s=Kl(o),i=`fpath=(${s} $fpath)`,r="autoload -U compinit && compinit",a=us(n)?Hl(n,"utf-8"):"",c=!a.includes(s),l=!/autoload\s+-U\s+compinit/.test(a);if(!c&&!l){console.log(je.dim("~/.zshrc already has fpath + compinit wired up. Run `exec zsh` to pick up the new script."));return}if(t&&us(n)){let g=["","# agentx completion"];c&&g.push(i),l&&g.push(r),zl(n,g.join(`
|
|
604
604
|
`)+`
|
|
605
605
|
`),console.log(je.green("\u2713 Patched ~/.zshrc")),console.log(je.dim("Reload your shell: exec zsh"));return}console.log(je.dim("Add this to ~/.zshrc if not already present:")),c&&console.log(je.cyan(` ${i}`)),l&&console.log(je.cyan(` ${r}`)),console.log(),console.log(je.dim("Then reload: exec zsh")),console.log(je.dim("Or rerun with --yes to auto-patch ~/.zshrc"));return}if(e==="bash"){let n=Tt(Fi(),".bashrc"),s=`[ -f "${o}" ] && source "${o}"`;if((us(n)?Hl(n,"utf-8"):"").includes(o)){console.log(je.dim("~/.bashrc already sources this file. Start a new shell to pick it up."));return}if(t&&us(n)){zl(n,`
|
|
606
606
|
# agentx completion
|
|
@@ -611,4 +611,4 @@ ${s}
|
|
|
611
611
|
`)}function Ui(e){return String(e||"").replace(/\r?\n/g," ").replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Li(e,o){let t=e.short?e.short.replace(/^-/,""):"",n=e.long?e.long.replace(/^--/,""):"";if(!t&&!n)return null;let s=Ui(e.description||""),r=["complete -c agentx",o.map(a=>`-n "${a}"`).join(" ")];return t&&r.push(`-s ${t}`),n&&r.push(`-l ${n}`),r.push(`-d "${s}"`),r.join(" ")}async function NS(){let e=await ga(),o=new Xf().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=fa(n);ha(s)&&ua("cli",s)});for(let t of[Ua,Ma,bt,at,eo,pa,Mo,Pn,go,Go,_n,Cl,So,Xa,rc,hc,bc,$c,Mc,qc,Wc,Vn,en,Pl,Wt,$o,Xl])o.addCommand(t);for(let t of Zl)o.addCommand(t,{hidden:!0});return o.addHelpText("after",()=>{let t=Zl.map(n=>n.name()).sort();return["",`Advanced (${t.length}, hidden \u2014 run \`agentx <command> --help\` for any of them):`,Qf(t,74," "),""].join(`
|
|
612
612
|
`)}),o}var Zl=[ee,$t,Io,Qe,Jt,ht,qe,po,Ao,Ho,St,Et,xo,Le,Gt,Kn,jl,co,gt,ka,Lo,dn,Ws,jo,dt,Bs,rs,Oo,Co,ql,Bl,_l];function Qf(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(`
|
|
613
613
|
`)}export{NS as a};
|
|
614
|
-
//# sourceMappingURL=chunk-
|
|
614
|
+
//# sourceMappingURL=chunk-KZYNQRQQ.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{E as no,F as so,a as Vi,b as Vn,f as zn,g as zi,h as Ki,j as Xi,s as Zi,t as Kn,u as Xn,v as He,x as qn,y as eo}from"./chunk-MX5GCR7Y.js";import{c as Bi,f as Wi,g as Ji}from"./chunk-V5FZJUK4.js";import{q as Yi,r as Qi}from"./chunk-3SCPRYJB.js";import{a as to}from"./chunk-V7FYSZSV.js";import{a as qi}from"./chunk-ZVP6GB4G.js";import{A as Oi,B as Di,C as ji,D as Ni,E as Li,G as Ui,P as Fi,a as qr,b as Yr,c as Ln,d as Zr,e as si,f as ri,g as Ge,i as Fn,j as Gn,k as di,r as hi,t as Hn,u as pt,v as Q,x as mi,y as q,z as Pi}from"./chunk-Z7LNSHG3.js";import{a as pi,g as yi,h as wi,j as Ri,k as Ci,l as Mi,n as _i}from"./chunk-TCJ3SMOF.js";import{a as xi,b as Ai,c as Wn,d as mt,e as Ii,f as ft}from"./chunk-VMDA2SX2.js";import{a as ii,b as oi,c as ai,d as Un,e as ci,f as li}from"./chunk-QLTM3F7M.js";import{A as Gi,B as yt,C as Hi,h as Br,n as Wr,o as On}from"./chunk-CQRSSVWG.js";import{b as Fr}from"./chunk-SFQUP3BP.js";import{b as K,c as Z,d as Ti,e as oe,f as ae,g as Ei,k as Jn}from"./chunk-BIFJSQB5.js";import{a as bi,b as Bn,c as ki,d as vi,e as Si,i as $i}from"./chunk-76Z4VHDX.js";import{b as fi}from"./chunk-W4YR2RO2.js";import{d as ei,e as ti,j as ni}from"./chunk-DWADWDMU.js";import{e as gi}from"./chunk-MTVRYTLL.js";import{b as ui}from"./chunk-64P4QHSZ.js";import{b as Qr}from"./chunk-2GIDVZ4H.js";import{d as Jr,e as sd,m as zr,n as od,o as Kr,t as Xr,v as xe,w as ht}from"./chunk-6HMZ5TTM.js";import{a as fe,b as Fe,f as Nn}from"./chunk-F4HZTZHW.js";import{a as Dn,b as nd}from"./chunk-ZTEU5JVQ.js";import{a as gt,b as td}from"./chunk-L2WSPY6S.js";import{a as Gr,d as Hr}from"./chunk-VDMYBPYB.js";import{e as me}from"./chunk-DSYKYZMT.js";import{h as rd,l as jn,m as Vr,o as id}from"./chunk-QJANPP4C.js";import{e as Te}from"./chunk-FIOB3MEX.js";import{existsSync as ad,readFileSync as cd}from"fs";import{resolve as ld}from"path";var dd={name:"agentx",version:"0.1.0"},ud="2024-11-05",gd={tools:{},elicitation:{form:{}}},hd=0;async function ro(i,e){let t=++hd;return ye({jsonrpc:"2.0",id:`elicit-${t}`,method:"elicitation/create",params:{mode:"form",message:i,requestedSchema:e}}),new Promise(n=>{Be.set(`elicit-${t}`,s=>{s?.action==="accept"&&s.content?n(s.content):n(null)}),setTimeout(()=>{Be.has(`elicit-${t}`)&&(Be.delete(`elicit-${t}`),n(null))},6e4)})}var Be=new Map,pd="http://localhost:19900",Yn;function md(){if(process.env.AGENTX_DAEMON_URL)return process.env.AGENTX_DAEMON_URL;for(let i of["agentx.json",".agentx/config.json"])try{let e=ld(process.cwd(),i);if(!ad(e))continue;let t=JSON.parse(cd(e,"utf-8"))?.node?.bind;if(typeof t!="string"||!t.includes(":"))continue;{let n=t.lastIndexOf(":"),s=t.slice(0,n),r=t.slice(n+1),o=!s||s==="0.0.0.0"||s==="::"||s==="*"?"127.0.0.1":s;if(r)return`http://${o}:${r}`}}catch{}return pd}function J(){return Yn===void 0&&(Yn=md()),Yn}var fd=/\x1B\[[0-9;]*[A-Za-z]/g;function Ae(i){return i.replace(fd,"")}var yd=[{name:"agentx_generate",description:"Generate code, components, pages, APIs, documents, tests, workflows, schemas, emails, diagrams, and more using AI. Understands the project's tech stack, schemas, and skills automatically.",inputSchema:{type:"object",properties:{task:{type:"string",description:"Describe what to generate (e.g., 'a responsive pricing card', 'REST API for users', 'GitHub Actions CI pipeline')"},type:{type:"string",description:"Output type: component, page, api, website, document, script, config, skill, media, report, test, workflow, schema, email, diagram, auto",default:"auto"},output_dir:{type:"string",description:"Optional output directory (relative to project root)"},cwd:{type:"string",description:"Project working directory (defaults to current directory)"}},required:["task"]}},{name:"agentx_inspect",description:"Analyze a project and return its tech stack, frameworks, databases, schemas, installed skills, and dependencies. Use this to understand a project before generating code.",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Project working directory (defaults to current directory)"}}}},{name:"agentx_skill_match",description:"Find installed skills that are relevant to a given task description. Returns matched skills with relevance scores.",inputSchema:{type:"object",properties:{task:{type:"string",description:"The task to match skills against"},cwd:{type:"string",description:"Project working directory"}},required:["task"]}},{name:"agentx_detect_output_type",description:"Auto-detect the best output type for a given task description based on keyword analysis.",inputSchema:{type:"object",properties:{task:{type:"string",description:"The task description to analyze"}},required:["task"]}},{name:"agentx_channel_reply",description:"Reply to a channel (GitLab issue/MR comment, GitHub issue/PR comment, Telegram/WhatsApp message). PREFER THIS over raw curl/glab/HTTP \u2014 it auto-applies agent identity from agentMappings, the cascade-prevention marker, intent-ledger audit, and a 60s body-hash dedupe so an accidental retry within the window is a no-op. Returns the posted message id. For agent-to-agent delegation use agentx_send_agent. For arbitrary outbound sends use agentx_send.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Channel name. gitlab | github | telegram | whatsapp | discord | slack"},chatId:{type:"string",description:"Stable chat id you received in this task's context. GitLab: 'org/repo:issue:123' or 'org/repo:merge_request:123'. GitHub: 'org/repo:issue:123' or 'org/repo:pull:123'. Telegram: numeric. WhatsApp: '+phone@s.whatsapp.net'."},text:{type:"string",description:"Reply body. Markdown for gitlab/github/discord; plain for sms/whatsapp."},agentId:{type:"string",description:"Optional posting identity. Defaults to channel-adapter resolution from agentMappings."},accountId:{type:"string",description:"Multi-account adapters (telegram) need this when the chat is reachable from more than one bot."},replyTo:{type:"string",description:"Optional reply-to message id for threaded channels."},idempotencyKey:{type:"string",description:"Optional explicit dedupe key. When omitted, a body hash is used. Use a stable key for 'overwrite my last status update' patterns."}},required:["channel","chatId","text"]}},{name:"agentx_channel_label",description:"Add and/or remove labels on a GitLab issue or merge_request through the canonical adapter (per-agent token, ledger). Use this instead of curl when changing labels on the entity that triggered the current task.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Currently 'gitlab'.",default:"gitlab"},project:{type:"string",description:"GitLab project path \u2014 'org/repo'."},kind:{type:"string",description:"'issue' or 'merge_request'."},iid:{type:"string",description:"Numeric iid as a string."},add:{type:"array",items:{type:"string"},description:"Labels to add."},remove:{type:"array",items:{type:"string"},description:"Labels to remove."},agentId:{type:"string",description:"Optional posting identity."}},required:["project","kind","iid"]}},{name:"agentx_send",description:"Low-level outbound send when you ALREADY have a channel-native chatId (Telegram numeric chat id, GitLab 'group/project:issue:123', WhatsApp '+phone@s.whatsapp.net'). For sending to another agent by name, use agentx_send_agent instead. For sending to a human contact by name, use agentx_send_contact instead.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Target channel: telegram, whatsapp, gitlab, discord"},chatId:{type:"string",description:'Chat ID. Telegram: numeric ("-1001234567890"). GitLab: "group/project:issue:123". WhatsApp: "+phone@s.whatsapp.net".'},text:{type:"string",description:"Message text to send"},agentId:{type:"string",description:"Agent ID to send as (determines bot account on Telegram, GitLab token, etc.)"}},required:["channel","chatId","text"]}},{name:"agentx_send_agent",description:"Send a message to ANOTHER AGENT by exact agentId \u2014 uses the AgentX A2A mesh (or local registry when the agent lives on this daemon). This is the deterministic path for agent-to-agent communication; it never falls through to a contact lookup, so an unknown agentId returns 404 with the list of known agents instead of silently sending to a similarly-named human. Use this when the target is a registered agent.",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Exact agentId of the target agent (e.g. 'peer', 'atlas'). Must match an agent in this daemon's registry or in a healthy mesh peer's directory."},text:{type:"string",description:"Message to send to the target agent"},senderAgentId:{type:"string",description:"Optional. The agentId on whose behalf this call is being made. Recorded in route_traces and (with A2A protocolVersion >= 2) validated by the receiving daemon."}},required:["agentId","text"]}},{name:"agentx_recent",description:"Read the most recent messages from a chat across ALL agents that have sessions for it. Returns inbound + each agent's replies in chronological order, so you can see what's actually been said in a Telegram chat / GitLab thread / WhatsApp DM regardless of which agent recorded it. Use this BEFORE speculating about what was sent \u2014 the cx/devops/marketing thread on 2026-04-29 about a Marketing/CX bot mixup would have been resolved in one call instead of three agents speculating. Bounded by sinceISO (default: last 24h) and limit (default: 30, max: 200).",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Channel name. Examples: telegram, whatsapp, gitlab, github, discord, cron, api, a2a."},chatId:{type:"string",description:'Channel-native chat id. Telegram: numeric (e.g. "1816212449" for a DM, "-1001234567890" for a group). GitLab: "group/project:issue:123". WhatsApp: "+phone@s.whatsapp.net".'},sinceISO:{type:"string",description:"Optional ISO timestamp lower bound. Defaults to 24h ago."},limit:{type:"number",description:"Optional cap on returned messages. Default 30, max 200."}},required:["channel","chatId"]}},{name:"agentx_send_contact",description:"Send a message to a HUMAN CONTACT by name. Resolves through .agentx/contacts.json (id \u2192 exact alias \u2192 fuzzy substring). Refuses fuzzy matches without confirmed:true so the agent must ask the user to disambiguate before sending. Refuses when the name also matches a registered agent (use agentx_send_agent for those). Use this when the target is a person, not a bot.",inputSchema:{type:"object",properties:{contactName:{type:"string",description:"Free-form contact name. Tried as id first, then alias, then fuzzy substring."},text:{type:"string",description:"Message to send to the contact"},channel:{type:"string",description:"Optional explicit channel (telegram | whatsapp | gitlab | discord). Defaults to the first channel configured for the contact."},confirmed:{type:"boolean",description:"Pass true ONLY after the user has confirmed a fuzzy match. Without it, fuzzy matches return 409 with the candidate so you can ask the user."},agentId:{type:"string",description:"Optional agent identity used for the outbound send (determines bot account / token)."}},required:["contactName","text"]}},{name:"agentx_task",description:"Send a task to a specific agent on the daemon. The agent processes it and returns a response. Use to delegate work to specialized agents.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID to send the task to"},message:{type:"string",description:"Task message for the agent"},senderAgentId:{type:"string",description:"Optional caller agent id. Defaults to AGENTX_AGENT_ID when the MCP server was launched by an AgentX runtime."},freshSession:{type:"boolean",description:"Start the target agent with a clean AgentX-side conversation. Defaults to true for agent-to-agent delegation."},chatId:{type:"string",description:"Optional stable chat/session id for this delegated task. Omit for a one-off isolated delegation."}},required:["agent","message"]}},{name:"agentx_agents",description:"List all agents registered on the daemon with their status (active tasks, total tasks, errors, tier).",inputSchema:{type:"object",properties:{}}},{name:"agentx_health",description:"Get the daemon health status including node info, agents, crons, mesh peers, and uptime.",inputSchema:{type:"object",properties:{}}},{name:"agentx_attach_next",description:"Take the next message queued for the agent identity THIS session is attached to (attach mode). Returns the message plus who sent it and on which channel, or nothing when the inbox is empty. After calling this, just answer normally \u2014 your reply is captured automatically and sent back to the channel. Use when the user runs /inbox or asks you to check for waiting messages.",inputSchema:{type:"object",properties:{}}},{name:"agentx_attach_answer",description:"Explicitly answer the message currently claimed by this session (attach mode). Usually unnecessary \u2014 replying normally after agentx_attach_next is captured automatically. Use this only when your reply to the channel should differ from what you told the user in the terminal.",inputSchema:{type:"object",properties:{text:{type:"string",description:"The reply to send back to the channel, verbatim."}},required:["text"]}},{name:"agentx_crons",description:"List cron jobs and their health. Shows healthy, failing, disabled counts and per-job status with consecutive error counts.",inputSchema:{type:"object",properties:{}}},{name:"agentx_schedule",description:"Manage recurring routines (schedules) in plain English. Actions: list, create, pause, resume, delete. create and delete are REQUESTS: nothing takes effect until the operator approves (the operator is sent the parsed cron and next fire time). Tell the user it is pending approval. You can pause/resume/delete only routines you created, unless you are an admin agent. Example: {action:'create', when:'every monday at 10am', prompt:'Check the open invoices and summarise'}.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list","create","pause","resume","delete"],description:"What to do. Default: list."},id:{type:"string",description:"Schedule id. Required for pause/resume/delete; optional for create (auto-generated)."},when:{type:"string",description:"create: plain-English timing, e.g. 'every monday at 10am', 'weekdays at 6pm', 'every 15 minutes', '1st of every month at noon'."},prompt:{type:"string",description:"create: what the agent should do at each run."},agent:{type:"string",description:"create: agent that runs the routine. Default: you."},timezone:{type:"string",description:"create: IANA timezone. Default: the node's schedule default."},notify:{type:"string",description:"create: where results/failures go. 'here' (default: the current chat), 'none', or 'channel:chatId'."},mine:{type:"boolean",description:"list: only routines you created."},channel:{type:"string",description:"Current chat's channel, from your task context. Used as the default notify target when the runtime didn't provide it."},chatId:{type:"string",description:"Current chat id, from your task context."},accountId:{type:"string",description:"Optional bot account for multi-account channels."},callerAgentId:{type:"string",description:"Your agent id. Ignored when the AgentX runtime already identifies you (AGENTX_AGENT_ID)."}}}},{name:"agentx_debug",description:"Toggle debug mode on the daemon. Enable verbose logging for specific categories (webhook, agent, channel, cron, mesh, context, memory, all) or disable it.",inputSchema:{type:"object",properties:{action:{type:"string",description:'"on", "off", or "status"',default:"status"},categories:{type:"string",description:'Comma-separated categories to enable (e.g. "webhook,agent"). Only used with action=on.'}}}},{name:"agentx_wiki_query",description:"Query the agentx institutional wiki: a cross-agent knowledge base organized by article type (person, project, place, concept, event, decision, pattern). Use this BEFORE grep/memory-search when the question is about who / what happened / what we decided / how we do something. The query walks the catalog + wikilink graph and returns a synthesized answer with citations.",inputSchema:{type:"object",properties:{question:{type:"string",description:"The question to answer from the wiki, in natural language."},agent:{type:"string",description:"Which agent's wiki to query (default: first agent with a catalog). Each agent has its own wiki dir under .agentx/wiki/agents/<id>/"},wiki_dir:{type:"string",description:"Wiki root dir (default: <cwd>/.agentx/wiki)."},max_hops:{type:"number",description:"Wikilink hops from candidates (default 2, max 3).",default:2}},required:["question"]}},{name:"agentx_wiki_patch",description:"Edit a single wiki article via an LLM-applied instruction and write the result. Use this for targeted fixes, additions, or clarifications to an existing article when you already know what's wrong. For brand-new articles, use `agentx_wiki_interview` instead.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID whose wiki owns the article (required)."},title_or_path:{type:"string",description:"Article title (case-insensitive) or relative path like 'people/alex.md'."},instruction:{type:"string",description:"Plain-English edit instruction (e.g. 'Add a section on the KSA Supabase rollout'). The LLM makes the minimum edit that satisfies it."},model:{type:"string",description:"Claude model for the patch (default: sonnet).",default:"sonnet"},dry_run:{type:"boolean",description:"Preview the patched body without writing.",default:!1}},required:["agent","title_or_path","instruction"]}},{name:"agentx_wiki_interview",description:"Run a scripted wiki interview \u2014 synthesize ONE typed article from a list of Q&A answers, and save it. Non-interactive: caller supplies the answers upfront. Use for capturing tacit knowledge (person/project/decision/pattern/...) that never hit a channel. For editing an existing article, use `agentx_wiki_patch`.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID that will own the new article (required)."},topic:{type:"string",description:"What the article is about \u2014 e.g. 'Globex deployment procedure', 'Jane Doe', 'DemoSite KSA migration'."},type:{type:"string",description:"Article type: person | project | place | concept | event | decision | pattern"},answers:{type:"array",description:"Answers to the type-specific question bank (one per question, in order). Empty string = skip that question. Final entry is typically 'save'.",items:{type:"string"}},model:{type:"string",description:"Synthesis model (default: sonnet).",default:"sonnet"},commit:{type:"boolean",description:"Write the article (true) or just preview (false).",default:!0}},required:["agent","topic","type","answers"]}},{name:"agentx_graph_review",description:"Triage pending intent-graph classifications via the configured review agent. The review agent sees each pending classification, may call `wiki query` for institutional context, and decides approve/reject/skip. Structural changes (new org, new unit) gate here; leaf additions auto-approve without this step.",inputSchema:{type:"object",properties:{max:{type:"number",description:"Cap reviews this run (default 20).",default:20},dry_run:{type:"boolean",description:"Show decisions but don't apply approvals/rejections.",default:!1},agent:{type:"string",description:"Override the review agent (defaults to graph.reviewAgent or graph.draftAgent)."}}}}];async function wd(i,e){let t=e.cwd||process.cwd();switch(i){case"agentx_generate":{let n=e.task,s=e.type||"auto",r=e.output_dir,o=await yt({task:n,outputType:s,outputDir:r,cwd:t,overwrite:!0,dryRun:!1,context7:!0,interactive:!1,maxSteps:5}),a=[];return o.content&&a.push(o.content),o.files.written.length&&a.push(`
|
|
1
|
+
import{E as no,F as so,a as Vi,b as Vn,f as zn,g as zi,h as Ki,j as Xi,s as Zi,t as Kn,u as Xn,v as He,x as qn,y as eo}from"./chunk-MX5GCR7Y.js";import{c as Bi,f as Wi,g as Ji}from"./chunk-V5FZJUK4.js";import{q as Yi,r as Qi}from"./chunk-3SCPRYJB.js";import{a as to}from"./chunk-V7FYSZSV.js";import{a as qi}from"./chunk-ZVP6GB4G.js";import{A as Oi,B as Di,C as ji,D as Ni,E as Li,G as Ui,P as Fi,a as qr,b as Yr,c as Ln,d as Zr,e as si,f as ri,g as Ge,i as Fn,j as Gn,k as di,r as hi,t as Hn,u as pt,v as Q,x as mi,y as q,z as Pi}from"./chunk-3RKIBJG6.js";import{a as pi,g as yi,h as wi,j as Ri,k as Ci,l as Mi,n as _i}from"./chunk-TCJ3SMOF.js";import{a as xi,b as Ai,c as Wn,d as mt,e as Ii,f as ft}from"./chunk-VMDA2SX2.js";import{a as ii,b as oi,c as ai,d as Un,e as ci,f as li}from"./chunk-QLTM3F7M.js";import{A as Gi,B as yt,C as Hi,h as Br,n as Wr,o as On}from"./chunk-3FIS6JD3.js";import{b as Fr}from"./chunk-SFQUP3BP.js";import{b as K,c as Z,d as Ti,e as oe,f as ae,g as Ei,k as Jn}from"./chunk-BIFJSQB5.js";import{a as bi,b as Bn,c as ki,d as vi,e as Si,i as $i}from"./chunk-76Z4VHDX.js";import{b as fi}from"./chunk-W4YR2RO2.js";import{d as ei,e as ti,j as ni}from"./chunk-DWADWDMU.js";import{e as gi}from"./chunk-MTVRYTLL.js";import{b as ui}from"./chunk-64P4QHSZ.js";import{b as Qr}from"./chunk-2GIDVZ4H.js";import{d as Jr,e as sd,m as zr,n as od,o as Kr,t as Xr,v as xe,w as ht}from"./chunk-6HMZ5TTM.js";import{a as fe,b as Fe,f as Nn}from"./chunk-F4HZTZHW.js";import{a as Dn,b as nd}from"./chunk-ZTEU5JVQ.js";import{a as gt,b as td}from"./chunk-L2WSPY6S.js";import{a as Gr,d as Hr}from"./chunk-VDMYBPYB.js";import{e as me}from"./chunk-DSYKYZMT.js";import{h as rd,l as jn,m as Vr,o as id}from"./chunk-QJANPP4C.js";import{e as Te}from"./chunk-FIOB3MEX.js";import{existsSync as ad,readFileSync as cd}from"fs";import{resolve as ld}from"path";var dd={name:"agentx",version:"0.1.0"},ud="2024-11-05",gd={tools:{},elicitation:{form:{}}},hd=0;async function ro(i,e){let t=++hd;return ye({jsonrpc:"2.0",id:`elicit-${t}`,method:"elicitation/create",params:{mode:"form",message:i,requestedSchema:e}}),new Promise(n=>{Be.set(`elicit-${t}`,s=>{s?.action==="accept"&&s.content?n(s.content):n(null)}),setTimeout(()=>{Be.has(`elicit-${t}`)&&(Be.delete(`elicit-${t}`),n(null))},6e4)})}var Be=new Map,pd="http://localhost:19900",Yn;function md(){if(process.env.AGENTX_DAEMON_URL)return process.env.AGENTX_DAEMON_URL;for(let i of["agentx.json",".agentx/config.json"])try{let e=ld(process.cwd(),i);if(!ad(e))continue;let t=JSON.parse(cd(e,"utf-8"))?.node?.bind;if(typeof t!="string"||!t.includes(":"))continue;{let n=t.lastIndexOf(":"),s=t.slice(0,n),r=t.slice(n+1),o=!s||s==="0.0.0.0"||s==="::"||s==="*"?"127.0.0.1":s;if(r)return`http://${o}:${r}`}}catch{}return pd}function J(){return Yn===void 0&&(Yn=md()),Yn}var fd=/\x1B\[[0-9;]*[A-Za-z]/g;function Ae(i){return i.replace(fd,"")}var yd=[{name:"agentx_generate",description:"Generate code, components, pages, APIs, documents, tests, workflows, schemas, emails, diagrams, and more using AI. Understands the project's tech stack, schemas, and skills automatically.",inputSchema:{type:"object",properties:{task:{type:"string",description:"Describe what to generate (e.g., 'a responsive pricing card', 'REST API for users', 'GitHub Actions CI pipeline')"},type:{type:"string",description:"Output type: component, page, api, website, document, script, config, skill, media, report, test, workflow, schema, email, diagram, auto",default:"auto"},output_dir:{type:"string",description:"Optional output directory (relative to project root)"},cwd:{type:"string",description:"Project working directory (defaults to current directory)"}},required:["task"]}},{name:"agentx_inspect",description:"Analyze a project and return its tech stack, frameworks, databases, schemas, installed skills, and dependencies. Use this to understand a project before generating code.",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Project working directory (defaults to current directory)"}}}},{name:"agentx_skill_match",description:"Find installed skills that are relevant to a given task description. Returns matched skills with relevance scores.",inputSchema:{type:"object",properties:{task:{type:"string",description:"The task to match skills against"},cwd:{type:"string",description:"Project working directory"}},required:["task"]}},{name:"agentx_detect_output_type",description:"Auto-detect the best output type for a given task description based on keyword analysis.",inputSchema:{type:"object",properties:{task:{type:"string",description:"The task description to analyze"}},required:["task"]}},{name:"agentx_channel_reply",description:"Reply to a channel (GitLab issue/MR comment, GitHub issue/PR comment, Telegram/WhatsApp message). PREFER THIS over raw curl/glab/HTTP \u2014 it auto-applies agent identity from agentMappings, the cascade-prevention marker, intent-ledger audit, and a 60s body-hash dedupe so an accidental retry within the window is a no-op. Returns the posted message id. For agent-to-agent delegation use agentx_send_agent. For arbitrary outbound sends use agentx_send.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Channel name. gitlab | github | telegram | whatsapp | discord | slack"},chatId:{type:"string",description:"Stable chat id you received in this task's context. GitLab: 'org/repo:issue:123' or 'org/repo:merge_request:123'. GitHub: 'org/repo:issue:123' or 'org/repo:pull:123'. Telegram: numeric. WhatsApp: '+phone@s.whatsapp.net'."},text:{type:"string",description:"Reply body. Markdown for gitlab/github/discord; plain for sms/whatsapp."},agentId:{type:"string",description:"Optional posting identity. Defaults to channel-adapter resolution from agentMappings."},accountId:{type:"string",description:"Multi-account adapters (telegram) need this when the chat is reachable from more than one bot."},replyTo:{type:"string",description:"Optional reply-to message id for threaded channels."},idempotencyKey:{type:"string",description:"Optional explicit dedupe key. When omitted, a body hash is used. Use a stable key for 'overwrite my last status update' patterns."}},required:["channel","chatId","text"]}},{name:"agentx_channel_label",description:"Add and/or remove labels on a GitLab issue or merge_request through the canonical adapter (per-agent token, ledger). Use this instead of curl when changing labels on the entity that triggered the current task.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Currently 'gitlab'.",default:"gitlab"},project:{type:"string",description:"GitLab project path \u2014 'org/repo'."},kind:{type:"string",description:"'issue' or 'merge_request'."},iid:{type:"string",description:"Numeric iid as a string."},add:{type:"array",items:{type:"string"},description:"Labels to add."},remove:{type:"array",items:{type:"string"},description:"Labels to remove."},agentId:{type:"string",description:"Optional posting identity."}},required:["project","kind","iid"]}},{name:"agentx_send",description:"Low-level outbound send when you ALREADY have a channel-native chatId (Telegram numeric chat id, GitLab 'group/project:issue:123', WhatsApp '+phone@s.whatsapp.net'). For sending to another agent by name, use agentx_send_agent instead. For sending to a human contact by name, use agentx_send_contact instead.",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Target channel: telegram, whatsapp, gitlab, discord"},chatId:{type:"string",description:'Chat ID. Telegram: numeric ("-1001234567890"). GitLab: "group/project:issue:123". WhatsApp: "+phone@s.whatsapp.net".'},text:{type:"string",description:"Message text to send"},agentId:{type:"string",description:"Agent ID to send as (determines bot account on Telegram, GitLab token, etc.)"}},required:["channel","chatId","text"]}},{name:"agentx_send_agent",description:"Send a message to ANOTHER AGENT by exact agentId \u2014 uses the AgentX A2A mesh (or local registry when the agent lives on this daemon). This is the deterministic path for agent-to-agent communication; it never falls through to a contact lookup, so an unknown agentId returns 404 with the list of known agents instead of silently sending to a similarly-named human. Use this when the target is a registered agent.",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Exact agentId of the target agent (e.g. 'peer', 'atlas'). Must match an agent in this daemon's registry or in a healthy mesh peer's directory."},text:{type:"string",description:"Message to send to the target agent"},senderAgentId:{type:"string",description:"Optional. The agentId on whose behalf this call is being made. Recorded in route_traces and (with A2A protocolVersion >= 2) validated by the receiving daemon."}},required:["agentId","text"]}},{name:"agentx_recent",description:"Read the most recent messages from a chat across ALL agents that have sessions for it. Returns inbound + each agent's replies in chronological order, so you can see what's actually been said in a Telegram chat / GitLab thread / WhatsApp DM regardless of which agent recorded it. Use this BEFORE speculating about what was sent \u2014 the cx/devops/marketing thread on 2026-04-29 about a Marketing/CX bot mixup would have been resolved in one call instead of three agents speculating. Bounded by sinceISO (default: last 24h) and limit (default: 30, max: 200).",inputSchema:{type:"object",properties:{channel:{type:"string",description:"Channel name. Examples: telegram, whatsapp, gitlab, github, discord, cron, api, a2a."},chatId:{type:"string",description:'Channel-native chat id. Telegram: numeric (e.g. "1816212449" for a DM, "-1001234567890" for a group). GitLab: "group/project:issue:123". WhatsApp: "+phone@s.whatsapp.net".'},sinceISO:{type:"string",description:"Optional ISO timestamp lower bound. Defaults to 24h ago."},limit:{type:"number",description:"Optional cap on returned messages. Default 30, max 200."}},required:["channel","chatId"]}},{name:"agentx_send_contact",description:"Send a message to a HUMAN CONTACT by name. Resolves through .agentx/contacts.json (id \u2192 exact alias \u2192 fuzzy substring). Refuses fuzzy matches without confirmed:true so the agent must ask the user to disambiguate before sending. Refuses when the name also matches a registered agent (use agentx_send_agent for those). Use this when the target is a person, not a bot.",inputSchema:{type:"object",properties:{contactName:{type:"string",description:"Free-form contact name. Tried as id first, then alias, then fuzzy substring."},text:{type:"string",description:"Message to send to the contact"},channel:{type:"string",description:"Optional explicit channel (telegram | whatsapp | gitlab | discord). Defaults to the first channel configured for the contact."},confirmed:{type:"boolean",description:"Pass true ONLY after the user has confirmed a fuzzy match. Without it, fuzzy matches return 409 with the candidate so you can ask the user."},agentId:{type:"string",description:"Optional agent identity used for the outbound send (determines bot account / token)."}},required:["contactName","text"]}},{name:"agentx_task",description:"Send a task to a specific agent on the daemon. The agent processes it and returns a response. Use to delegate work to specialized agents.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID to send the task to"},message:{type:"string",description:"Task message for the agent"},senderAgentId:{type:"string",description:"Optional caller agent id. Defaults to AGENTX_AGENT_ID when the MCP server was launched by an AgentX runtime."},freshSession:{type:"boolean",description:"Start the target agent with a clean AgentX-side conversation. Defaults to true for agent-to-agent delegation."},chatId:{type:"string",description:"Optional stable chat/session id for this delegated task. Omit for a one-off isolated delegation."}},required:["agent","message"]}},{name:"agentx_agents",description:"List all agents registered on the daemon with their status (active tasks, total tasks, errors, tier).",inputSchema:{type:"object",properties:{}}},{name:"agentx_health",description:"Get the daemon health status including node info, agents, crons, mesh peers, and uptime.",inputSchema:{type:"object",properties:{}}},{name:"agentx_attach_next",description:"Take the next message queued for the agent identity THIS session is attached to (attach mode). Returns the message plus who sent it and on which channel, or nothing when the inbox is empty. After calling this, just answer normally \u2014 your reply is captured automatically and sent back to the channel. Use when the user runs /inbox or asks you to check for waiting messages.",inputSchema:{type:"object",properties:{}}},{name:"agentx_attach_answer",description:"Explicitly answer the message currently claimed by this session (attach mode). Usually unnecessary \u2014 replying normally after agentx_attach_next is captured automatically. Use this only when your reply to the channel should differ from what you told the user in the terminal.",inputSchema:{type:"object",properties:{text:{type:"string",description:"The reply to send back to the channel, verbatim."}},required:["text"]}},{name:"agentx_crons",description:"List cron jobs and their health. Shows healthy, failing, disabled counts and per-job status with consecutive error counts.",inputSchema:{type:"object",properties:{}}},{name:"agentx_schedule",description:"Manage recurring routines (schedules) in plain English. Actions: list, create, pause, resume, delete. create and delete are REQUESTS: nothing takes effect until the operator approves (the operator is sent the parsed cron and next fire time). Tell the user it is pending approval. You can pause/resume/delete only routines you created, unless you are an admin agent. Example: {action:'create', when:'every monday at 10am', prompt:'Check the open invoices and summarise'}.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list","create","pause","resume","delete"],description:"What to do. Default: list."},id:{type:"string",description:"Schedule id. Required for pause/resume/delete; optional for create (auto-generated)."},when:{type:"string",description:"create: plain-English timing, e.g. 'every monday at 10am', 'weekdays at 6pm', 'every 15 minutes', '1st of every month at noon'."},prompt:{type:"string",description:"create: what the agent should do at each run."},agent:{type:"string",description:"create: agent that runs the routine. Default: you."},timezone:{type:"string",description:"create: IANA timezone. Default: the node's schedule default."},notify:{type:"string",description:"create: where results/failures go. 'here' (default: the current chat), 'none', or 'channel:chatId'."},mine:{type:"boolean",description:"list: only routines you created."},channel:{type:"string",description:"Current chat's channel, from your task context. Used as the default notify target when the runtime didn't provide it."},chatId:{type:"string",description:"Current chat id, from your task context."},accountId:{type:"string",description:"Optional bot account for multi-account channels."},callerAgentId:{type:"string",description:"Your agent id. Ignored when the AgentX runtime already identifies you (AGENTX_AGENT_ID)."}}}},{name:"agentx_debug",description:"Toggle debug mode on the daemon. Enable verbose logging for specific categories (webhook, agent, channel, cron, mesh, context, memory, all) or disable it.",inputSchema:{type:"object",properties:{action:{type:"string",description:'"on", "off", or "status"',default:"status"},categories:{type:"string",description:'Comma-separated categories to enable (e.g. "webhook,agent"). Only used with action=on.'}}}},{name:"agentx_wiki_query",description:"Query the agentx institutional wiki: a cross-agent knowledge base organized by article type (person, project, place, concept, event, decision, pattern). Use this BEFORE grep/memory-search when the question is about who / what happened / what we decided / how we do something. The query walks the catalog + wikilink graph and returns a synthesized answer with citations.",inputSchema:{type:"object",properties:{question:{type:"string",description:"The question to answer from the wiki, in natural language."},agent:{type:"string",description:"Which agent's wiki to query (default: first agent with a catalog). Each agent has its own wiki dir under .agentx/wiki/agents/<id>/"},wiki_dir:{type:"string",description:"Wiki root dir (default: <cwd>/.agentx/wiki)."},max_hops:{type:"number",description:"Wikilink hops from candidates (default 2, max 3).",default:2}},required:["question"]}},{name:"agentx_wiki_patch",description:"Edit a single wiki article via an LLM-applied instruction and write the result. Use this for targeted fixes, additions, or clarifications to an existing article when you already know what's wrong. For brand-new articles, use `agentx_wiki_interview` instead.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID whose wiki owns the article (required)."},title_or_path:{type:"string",description:"Article title (case-insensitive) or relative path like 'people/alex.md'."},instruction:{type:"string",description:"Plain-English edit instruction (e.g. 'Add a section on the KSA Supabase rollout'). The LLM makes the minimum edit that satisfies it."},model:{type:"string",description:"Claude model for the patch (default: sonnet).",default:"sonnet"},dry_run:{type:"boolean",description:"Preview the patched body without writing.",default:!1}},required:["agent","title_or_path","instruction"]}},{name:"agentx_wiki_interview",description:"Run a scripted wiki interview \u2014 synthesize ONE typed article from a list of Q&A answers, and save it. Non-interactive: caller supplies the answers upfront. Use for capturing tacit knowledge (person/project/decision/pattern/...) that never hit a channel. For editing an existing article, use `agentx_wiki_patch`.",inputSchema:{type:"object",properties:{agent:{type:"string",description:"Agent ID that will own the new article (required)."},topic:{type:"string",description:"What the article is about \u2014 e.g. 'Globex deployment procedure', 'Jane Doe', 'DemoSite KSA migration'."},type:{type:"string",description:"Article type: person | project | place | concept | event | decision | pattern"},answers:{type:"array",description:"Answers to the type-specific question bank (one per question, in order). Empty string = skip that question. Final entry is typically 'save'.",items:{type:"string"}},model:{type:"string",description:"Synthesis model (default: sonnet).",default:"sonnet"},commit:{type:"boolean",description:"Write the article (true) or just preview (false).",default:!0}},required:["agent","topic","type","answers"]}},{name:"agentx_graph_review",description:"Triage pending intent-graph classifications via the configured review agent. The review agent sees each pending classification, may call `wiki query` for institutional context, and decides approve/reject/skip. Structural changes (new org, new unit) gate here; leaf additions auto-approve without this step.",inputSchema:{type:"object",properties:{max:{type:"number",description:"Cap reviews this run (default 20).",default:20},dry_run:{type:"boolean",description:"Show decisions but don't apply approvals/rejections.",default:!1},agent:{type:"string",description:"Override the review agent (defaults to graph.reviewAgent or graph.draftAgent)."}}}}];async function wd(i,e){let t=e.cwd||process.cwd();switch(i){case"agentx_generate":{let n=e.task,s=e.type||"auto",r=e.output_dir,o=await yt({task:n,outputType:s,outputDir:r,cwd:t,overwrite:!0,dryRun:!1,context7:!0,interactive:!1,maxSteps:5}),a=[];return o.content&&a.push(o.content),o.files.written.length&&a.push(`
|
|
2
2
|
Created ${o.files.written.length} file(s):
|
|
3
3
|
${o.files.written.map(l=>` - ${l}`).join(`
|
|
4
4
|
`)}`),o.files.skipped.length&&a.push(`
|
|
@@ -1332,4 +1332,4 @@ data: ${JSON.stringify(A)}
|
|
|
1332
1332
|
`)}catch{}},I=setInterval(()=>{try{t.write(`: ping
|
|
1333
1333
|
|
|
1334
1334
|
`)}catch{}},15e3);I.unref?.();try{for await(let C of this.mesh.sendTaskStream(h.peer,h.message,h.agent,{context:h.context}))x(C.event,C.data)}catch(C){x("error",{error:C?.message??String(C)})}finally{clearInterval(I);try{t.end()}catch{}}break}let b=h.context,$=typeof h.senderAgentId=="string"?h.senderAgentId:void 0;if(h.async===!0){let x=b?.channel,I=b?.chatId;if(!x||!I){this.json(t,400,{error:"async requires context.channel and context.chatId \u2014 there is no route back otherwise"});return}let C=`mesh-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;this.json(t,202,{accepted:!0,taskId:C,deliverTo:`${x}:${I}`,note:"result will be delivered to the originating chat when the peer finishes"});let A=h.peer,P=h.agent,O=this.mesh;(async()=>{let _=Date.now(),N;try{N=await O.sendTask(A,h.message,P,{context:b,senderAgentId:$}),this.log(`[mesh/task async ${C}] ${A}/${P??"default"} finished in ${Date.now()-_}ms`)}catch(L){N=`Delegation to ${A}/${P??"default"} failed: ${L?.message??L}`,this.log(`[mesh/task async ${C}] failed: ${L?.message??L}`)}try{await this.router.sendOutbound({channel:x,chatId:I,text:N,agentId:b?.agentId??$,accountId:b?.accountId})}catch(L){this.log(`[mesh/task async ${C}] delivery failed: ${L?.message??L}`)}})();break}let v=await this.mesh.sendTask(h.peer,h.message,h.agent,{context:b,senderAgentId:$});this.json(t,200,{response:v});break}case"POST /webrtc/signal/out":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let p=await G(e);if(!p.kind||!p.callId||!p.from||!p.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let y=await this.webrtc.handleOutgoing(p);this.json(t,y.ok?200:400,y);break}case"POST /webrtc/signal":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let p=await G(e);if(!p.kind||!p.callId||!p.from||!p.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let y=this.webrtc.handleIncoming(p);this.json(t,y.ok?200:400,y);break}case"POST /webrtc/bot/invite":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled (channels.webrtc.bot.enabled=false)"});return}let h=await G(e),p=h.callId,y=h.target,b=h.agentId||this.config.channels.webrtc?.bot.defaultAgentId;if(!p||!y||!b){this.json(t,400,{error:"Missing: callId, target, agentId (or defaultAgentId in config)"});return}let $=await this.botManager.invite({callId:p,target:y,agentId:b});this.json(t,$.ok?200:500,$);break}case"GET /webrtc/bots":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled"});return}this.json(t,200,{active:this.botManager.active()});break}case"GET /webrtc/history":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled"});return}this.json(t,200,{active:this.botManager.active(),history:this.botManager.history()});break}case"GET /webrtc/config":{let h=this.config.channels.webrtc;if(!h?.enabled){this.json(t,404,{error:"WebRTC signaling not enabled"});return}this.json(t,200,{localName:this.config.node.name,iceServers:[...h.stunServers.map(p=>({urls:p})),...h.turnServers],peers:this.mesh?.directory().map(p=>({name:p.peer,healthy:p.healthy}))||[]});break}case"GET /.well-known/agent-card.json":this.json(t,200,{name:this.config.node.name,description:`AgentX daemon node "${this.config.node.name}"`,url:`http://${this.config.node.bind}`,version:"1.0.0",capabilities:{streaming:!1,pushNotifications:!1,stateTransitionHistory:!1},skills:this.registry.list().map(h=>{let p=this.config.agents[h.id]||{},y=typeof p.description=="string"&&p.description.trim()||nf(p.systemPrompt)||`Agent "${h.name}" (${h.tier})`,b=Array.isArray(p.mentions)?p.mentions.slice(0,4):[];return{id:h.id,name:h.name,description:y,tags:[h.tier,...b]}}),channels:this.router.getChannelNames(),defaultInputModes:["text"],defaultOutputModes:["text"]});break;case"GET /wiki/agents":{let h=this.registry.getWikiHub();this.json(t,200,{nodeId:this.config.node.id,agents:h.summary()});break}case"GET /wiki/entries":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent")||void 0,y=n.searchParams.get("after")||void 0,b=p?h.getAgentEntries(p):h.getSharedStore().listEntries({after:y});this.json(t,200,{nodeId:this.config.node.id,count:b.length,entries:b.map($=>({id:$.id,date:$.date,agentId:$.agentId,source:$.source,sourceContext:$.sourceContext,content:$.content}))});break}case"GET /wiki/articles":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent");if(!p){this.json(t,400,{error:"?agent= required"});break}let b=h.getAgentWiki(p).rebuildIndex();this.json(t,200,{nodeId:this.config.node.id,agentId:p,articles:b.articles});break}case"GET /wiki/article":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent"),y=n.searchParams.get("path");if(!p||!y){this.json(t,400,{error:"?agent= and ?path= required"});break}let $=h.getAgentWiki(p).readArticle(y);if(!$){this.json(t,404,{error:"Article not found"});break}this.json(t,200,{nodeId:this.config.node.id,agentId:p,path:$.path,title:$.meta.title,tags:$.meta.tags,owner:$.meta.owner,created:$.meta.created,lastUpdated:$.meta.lastUpdated,sources:$.meta.sources,content:$.content});break}case"GET /graph/schema":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,schema:h.loadSchema()});break}case"GET /graph/nodes":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,...h.loadNodes()});break}case"GET /graph/classifications":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}let p=n.searchParams.get("status")||"approved",y=Math.max(1,Math.min(1e3,parseInt(n.searchParams.get("limit")||"200",10)||200)),b=h.listByStatus(p,y);this.json(t,200,{nodeId:this.config.node.id,status:p,count:b.length,classifications:b});break}default:this.json(t,404,{error:"Not found",endpoints:["GET /health","GET /agents","GET /crons","GET /routines \u2014 schedules + cron/hook workflows with staleness flags","GET /mesh","GET /wiki/agents","GET /wiki/entries[?agent=X&after=YYYY-MM-DD]","GET /wiki/articles?agent=X","GET /graph/schema","GET /graph/nodes","GET /graph/classifications[?status=approved|pending|rejected&limit=N]","POST /task { agent, message, context?, freshSession?: bool }","GET /agents/:id \u2014 resolved agent config (permission, tier, model, persistentProcess, toolUseRequired)","POST /agents/:id/selftest { message? } \u2014 canary probe; runs a fresh-session task and reports {ok, durationMs, tokens, billedModel}","GET /traces[?agentId=&channel=&chatId=&workflowRunId=&status=&since=&until=&limit=]","GET /traces/:taskId \u2014 full per-task execution trace (steps + tokens)","GET /api/processes \u2014 live persistent claude processes (JSON)","POST /api/processes/kill { agentId, channel, chatId, reason? }","GET /api/actions/builtin \u2014 list shipped built-in typed actions","POST /api/actions/builtin/:name \u2014 run a built-in with JSON body input","POST /mesh/task { peer, message }","POST /webhook/:agentId[/:source] \u2014 webhook callback","POST /reload \u2014 re-read agentx.json (hot-swaps crons)","GET /.well-known/agent-card.json","GET /call \u2014 browser UI for P2P A/V calls (requires channels.webrtc.enabled)","GET /webrtc/config \u2014 ICE servers + peer directory for the call page","GET /webrtc/events?callId=&as= \u2014 SSE stream of signaling events","POST /webrtc/signal/out \u2014 browser-originated signal, forwarded to remote peer","POST /webrtc/signal \u2014 remote-peer-originated signal, fanned out to local browser","POST /webrtc/bot/invite { callId, target, agentId } \u2014 spawn a transcribing bot peer for a call","GET /webrtc/bots \u2014 active bot sessions"]})}}catch(r){this.json(t,500,{error:r.message})}}async handleOpenAICompat(e,t,n){let s=await G(e);await ra(e,t,n,s,{execute:(r,o,a,l)=>this.registry.execute(r,o,a,l),agentIds:Object.keys(this.config.agents),cancel:(r,o,a,l)=>{let c=this.registry.list().find(d=>d.id===r)?.runningTasks.filter(d=>d.channel===o&&d.chatId===a)||[];for(let d of c)this.registry.cancelRunningTask(d.id,l)},log:r=>this.log(r)})}json(e,t,n){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(n,null,2))}resolveGitlabTokenForAgent(e){if(!e)return{token:this.config.channels.gitlab?.token,source:"global"};let t=(this.config.channels.gitlab?.agentMappings||[]).find(s=>s.agentId===e);if(t?.token)return{token:t.token,source:"agentMappings"};let n=wc(this.config,e,"gitlab-user","tokenEnv");return n.status==="ok"&&n.value?{token:n.value,source:`integrations(${n.envVar})`}:this.config.channels.gitlab?.token?{token:this.config.channels.gitlab.token,source:"global"}:{token:void 0,source:n.status}}resolveTodayUsage(){let e=Ha();if(e==="json")return this.registry.getTodayUsage();let t=Ga(this.db);return e==="sqlite"||Object.keys(t.agents).length>0?t:this.registry.getTodayUsage()}installAgentMemorySurface(){let e=parseInt(this.config.node.bind.split(":")[1]||"18800",10);for(let t of this.registry.list()){let n=t.workspace;if(!(!n||!Ue(n)))try{let s=te(n,".claude","skills");Yl(s,{recursive:!0});let r=te(s,vc);if(!Ue(r))Nr(r,Fs(e)),this.log(` memory-skill: installed remember.md \u2192 ${t.id}`);else{let o=$c(ut(r,"utf-8"),e);o&&(Nr(r,o),this.log(` memory-skill: updated remember.md \u2192 ${t.id}`))}this.agentMemory.syncToWorkspace(t.id,n)}catch(s){this.log(` memory-skill: ${t.id} install failed \u2014 ${s?.message??s}`)}}}installAgentMcpConfig(){for(let[e,t]of Object.entries(this.config.agents)){let n=t.workspace;if(!n||!Ue(n))continue;let s=ei(t);try{switch(kc(n,s)){case"installed":this.log(` mcp: installed ${Object.keys(s).length} server(s) \u2192 ${e}`);break;case"updated":this.log(` mcp: updated .mcp.json (${Object.keys(s).length} server(s)) \u2192 ${e}`);break;case"removed":this.log(` mcp: removed managed .mcp.json (config now empty) \u2192 ${e}`);break;case"skipped-operator-owned":Object.keys(s).length>0&&this.log(` mcp: ${e} has operator-owned .mcp.json \u2014 skipping (delete file or marker to let agentx manage)`);break;case"noop":break}}catch(r){this.log(` mcp: ${e} install failed \u2014 ${r?.message??r}`)}}}workspaceFor(e){for(let t of this.registry.list())if(t.id===e)return t.workspace;return null}handleMemoryApi(e,t,n,s){return hc(e,t,n,s,{mem:this.agentMemory,workspaceFor:r=>this.workspaceFor(r),runningTaskOwner:r=>this.registry.runningTaskOwner(r)})}async handleWorkflowEvent(e,t){if(!this.workflowDispatcher){this.json(t,503,{error:"workflow engine not enabled on this node"});return}let n;try{n=await X(e)}catch(l){this.json(t,400,{error:"invalid JSON body",message:l.message});return}let s=n?.payload??n,r=s?.event,o=s?.entityRef;if(!r?.id||!o?.backend||!o?.id){this.json(t,400,{error:"missing event or entityRef"});return}let a=n?.kind;try{if(a==="trigger"&&s.trigger){let g=typeof n?.fromPeer=="string"?n.fromPeer:"unknown";this.log(`[workflows/mesh] received trigger from "${g}" source="${s.trigger.source}" chat="${s.trigger.chat??"*"}"`);let w=await this.workflowDispatcher.dispatch({trigger:s.trigger,entityRef:o,event:r,fromRemote:{peer:g}});this.log(`[workflows/mesh] dispatched broadcast: matched=${w.claimed.length} ${w.claimed.length?`(${w.claimed.map(m=>m.id).join(", ")})`:"[none \u2014 no workflow with mesh.allowRemote matched]"}`),this.json(t,202,{ok:!0,mode:"trigger-broadcast",matched:w.claimed.map(m=>m.id)});return}let d=(s.workflowId?this.workflowStore?.get(s.workflowId):null)?.nodes.find(g=>g.type.startsWith("trigger."))?.config??{},u={source:String(d.source??"hook"),project:d.filter?.project,repo:d.filter?.repo,chat:d.filter?.chat,labels:d.filter?.labels};await this.workflowDispatcher.dispatch({trigger:u,entityRef:o,event:r}),this.json(t,202,{ok:!0})}catch(l){this.log(`[workflows] /workflow/event failed: ${l.message}`),this.json(t,500,{error:l.message})}}async handleChannelSend(e,t){let n;try{n=await X(e)}catch(l){this.json(t,400,{error:"invalid JSON body",message:l.message});return}let s=String(n?.channel??""),r=String(n?.chatId??""),o=String(n?.text??"");if(!s||!r||!o){this.json(t,400,{error:"channel, chatId, and text are required"});return}if(!this.router.getChannel(s)){this.json(t,404,{error:`channel "${s}" not hosted on this node`});return}try{let l=await this.router.sendOutbound({channel:s,chatId:r,text:o,accountId:typeof n.accountId=="string"?n.accountId:void 0,parseMode:typeof n.parseMode=="string"?n.parseMode:void 0,replyTo:typeof n.replyTo=="string"?n.replyTo:void 0});this.json(t,200,{ok:!0,messageId:l??null})}catch(l){this.log(`[mesh] /channel/send "${s}" failed: ${l.message}`),this.json(t,500,{error:l.message})}}async handleChannelChats(e,t,n={}){let s=new Set,r=[],o=[],a=(c,d)=>{let u=0;for(let g of c)!g.id||s.has(g.id)||(s.add(g.id),r.push({...g,source:d}),u++);u>0&&o.push(`${d}:${u}`)},l=this.router.getChannel(t);if(l?.listKnownChats)try{a(l.listKnownChats(),"local")}catch{}else if(l?.listChats)try{a(l.listChats().map(c=>({id:c.jid,name:c.name,kind:c.isGroup?"group":"dm"})),"local")}catch{}if(!n.localOnly&&this.mesh){let c=this.mesh.directory().filter(d=>d.healthy&&d.channels?.includes(t));await Promise.allSettled(c.map(async d=>{try{let u=await fetch(`${d.peerUrl}/channels/${encodeURIComponent(t)}/chats?local=1`,{headers:this.mesh.authHeaders(d.peer),signal:AbortSignal.timeout(5e3)});if(!u.ok)return;let g=await u.json();Array.isArray(g.chats)&&a(g.chats.map(w=>({id:w.id,name:w.name,kind:w.kind??"dm",accountId:w.accountId})),`mesh:${d.peer}`)}catch{}}))}this.json(e,200,{channel:t,source:o.join(", ")||"none",chats:r})}async handleWorkflowManualRun(e,t,n){if(!this.workflowDispatcher||!this.workflowStore){this.json(t,503,{error:"workflow engine not enabled on this node"});return}let s=this.workflowStore.get(n);if(!s){this.json(t,404,{error:`unknown workflow "${n}"`});return}let r=s.nodes.find(m=>m.type.startsWith("trigger."));if(!r){this.json(t,400,{error:`workflow "${n}" has no trigger node`});return}let o;try{o=await X(e)}catch{o={}}let a=!!o?.force,l=o?.payload||{};if(r.type!=="trigger.manual"&&!a){this.json(t,409,{error:`workflow "${n}" trigger is "${r.type}"`,hint:'pass { "force": true } to fire anyway with a synthesized event (for testing)'});return}let c=r.config??{},d=a?String(c.source??"manual"):"manual",u=String(l.entityId||l.chatId||`manual-${Date.now().toString(36)}`),g={backend:a&&c.source?"channel":"manual",id:u},w=`manual:${n}:${u}:${Date.now()}`;try{let f=(await this.workflowDispatcher.dispatch({trigger:a?{source:d,project:c.filter?.project,repo:c.filter?.repo,chat:c.filter?.chat,labels:c.filter?.labels}:{source:"manual"},entityRef:g,event:{id:w,payload:l}})).runs[0]?.id;this.json(t,f?200:202,{ok:!0,runId:f,entityRef:g,source:d,force:a})}catch(m){this.log(`[workflows] manual run "${n}" failed: ${m.message}`),this.json(t,500,{error:m.message})}}},Lr=Ur;Te(Lr,"MESH_PROTECTED_PATHS",new Set(["/task","/ask","/mesh/task","/mesh/inbox/send","/workflow/event","/workflow/transition","/channel/send","/webrtc/signal","/gitlab/react","/gitlab/send-note","/gitlab/log-time","/github/send-comment"]));function nf(i){if(typeof i!="string")return"";let e=i.trim();if(!e)return"";let t=e.match(/^[^.!?\n]+[.!?]?/),n=(t?t[0]:e).trim();return n.length>140?n.slice(0,137)+"\u2026":n}function X(i){return new Promise((e,t)=>{let n="";i.setEncoding("utf8"),i.on("data",s=>{n+=s}),i.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(s){t(s)}}),i.on("error",t)})}function Ql(i){let e=i;return e=e.replace(/```[\s\S]*?```/g,". "),e=e.replace(/`[^`]*`/g,""),e=e.replace(/\*\*(.*?)\*\*/g,"$1"),e=e.replace(/__(.*?)__/g,"$1"),e=e.replace(/\*([^*]+)\*/g,"$1"),e=e.replace(/_([^_]+)_/g,"$1"),e=e.replace(/~~(.*?)~~/g,"$1"),e=e.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),e=e.replace(/!\[([^\]]*)\]\([^)]+\)/g,"image$1 "),e=e.replace(/^#{1,6}\s+/gm,""),e=e.replace(/^[\s]*[-*+]\s+/gm,". "),e=e.replace(/^[\s]*\d+\.\s+/gm,". "),e=e.replace(/^[-=_]{3,}$/gm,""),e=e.replace(/^>\s*/gm,""),e=e.replace(/https?:\/\/\S+/g,"link"),e=e.replace(/\/\w+(\/\w+)+/g,t=>t.split("/").filter(Boolean).join(" slash ")),e=e.replace(/&/g," and "),e=e.replace(/@/g," at "),e=e.replace(/=>/g," returns "),e=e.replace(/->/g," to "),e=e.replace(/\|/g," or "),e=e.replace(/\be\.g\./gi,"for example"),e=e.replace(/\bi\.e\./gi,"that is"),e=e.replace(/\betc\./gi,"etcetera"),e=e.replace(/\bvs\.?\b/gi,"versus"),e=e.replace(/\n{2,}/g,". "),e=e.replace(/\n/g," "),e=e.replace(/\s+/g," "),e=e.replace(/\.\s*\./g,"."),e=e.replace(/\s+([.,!?])/g,"$1"),e=e.trim().replace(/^[.,:;]+\s*/,""),e.length>800&&(e=e.slice(0,800).replace(/\s+\S*$/,"")+"..."),e}function sf(i,e){let t=["model","workspace","tier","permissionMode","mcpServers"],n=new Set,s=new Set([...Object.keys(i),...Object.keys(e)]);for(let r of s){let o=i[r],a=e[r];if(!o||!a){n.add("add/remove");continue}for(let l of t)JSON.stringify(o[l])!==JSON.stringify(a[l])&&n.add(`${r}.${l}`)}return Array.from(n).slice(0,6)}async function G(i){return new Promise((e,t)=>{let n="";i.on("data",s=>n+=s.toString()),i.on("end",()=>{try{e(n?JSON.parse(n):{})}catch{e({})}}),i.on("error",t)})}td();function bT(i){typeof i=="string"&&(gt.error(i),process.exit(1)),i instanceof Error&&(gt.error(i.message),process.exit(1)),gt.error("Something went wrong. Please try again."),process.exit(1)}import Pn from"path";import Zl from"fs-extra";import{fileURLToPath as rf}from"url";function TT(){let i=[];try{let e=Pn.dirname(rf(import.meta.url));e&&(i.push(Pn.resolve(e,"..","package.json")),i.push(Pn.resolve(e,"package.json")))}catch{}i.push(Pn.resolve(process.cwd(),"package.json"));for(let e of i)try{if(Zl.existsSync(e)){let t=Zl.readJSONSync(e);if(t&&t.name)return t}}catch{}return{name:"agentix-cli",version:"0.0.0"}}export{pf as a,Qn as b,we as c,We as d,ze as e,ve as f,At as g,Bw as h,Yw as i,kg as j,vg as k,Ma as l,Me as m,_e as n,de as o,Eb as p,Ua as q,Ms as r,Kt as s,tt as t,Lc as u,ip as v,bv as w,it as x,Zt as y,rr as z,ir as A,nn as B,Bp as C,$e as D,on as E,cr as F,lr as G,ot as H,dr as I,cn as J,hl as K,un as L,ct as M,mn as N,bl as O,wr as P,ie as Q,he as R,Il as S,Rl as T,Cl as U,El as V,kn as W,bn as X,En as Y,ql as Z,Lr as _,bT as $,TT as aa};
|
|
1335
|
-
//# sourceMappingURL=chunk-
|
|
1335
|
+
//# sourceMappingURL=chunk-MDAC3PKR.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as s}from"./chunk-
|
|
2
|
+
import{a as s}from"./chunk-KZYNQRQQ.js";import"./chunk-7A7RC3R4.js";import"./chunk-YQVR2HQS.js";import"./chunk-SAFAI4AV.js";import"./chunk-2TJ5L7CB.js";import"./chunk-7CVJ4JOE.js";import"./chunk-WLVQDEOT.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-SZDACK6O.js";import"./chunk-MDAC3PKR.js";import"./chunk-MX5GCR7Y.js";import"./chunk-V5FZJUK4.js";import"./chunk-3SCPRYJB.js";import"./chunk-V7FYSZSV.js";import"./chunk-ZVP6GB4G.js";import"./chunk-3RKIBJG6.js";import"./chunk-TCJ3SMOF.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import"./chunk-3FIS6JD3.js";import"./chunk-SFQUP3BP.js";import"./chunk-BIFJSQB5.js";import"./chunk-WPMX3VGI.js";import"./chunk-K33GIBSE.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-NSYY5NCR.js";import"./chunk-ICZPZYYR.js";import"./chunk-DWADWDMU.js";import"./chunk-CQR6C5FU.js";import"./chunk-VWTBHLMX.js";import"./chunk-MTVRYTLL.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TNFOGJWZ.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import"./chunk-6HMZ5TTM.js";import"./chunk-F4HZTZHW.js";import"./chunk-AJONZWLT.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-QOYAX2FT.js";import"./chunk-LCIREYTD.js";import"./chunk-L2WSPY6S.js";import"./chunk-VDMYBPYB.js";import"./chunk-DSYKYZMT.js";import"./chunk-QJANPP4C.js";import"./chunk-BH3GTCZ6.js";import"./chunk-FIOB3MEX.js";process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));async function o(){let r=await s();if(process.argv.slice(2).length===0){r.outputHelp();return}r.parse()}o();
|
|
3
3
|
//# sourceMappingURL=cli.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -7500,7 +7500,9 @@ declare class MemoryStore {
|
|
|
7500
7500
|
* Injected into heartbeat context so the agent proactively recalls facts.
|
|
7501
7501
|
*/
|
|
7502
7502
|
buildRecallContext(agentId: string): string;
|
|
7503
|
-
/** Facts waiting for an operator's review, oldest first.
|
|
7503
|
+
/** Facts waiting for an operator's review, oldest first. Includes
|
|
7504
|
+
* external facts stored before review existed: they have no review
|
|
7505
|
+
* state, and are kept out of prompts all the same. */
|
|
7504
7506
|
held(agentId: string): MemoryFact[];
|
|
7505
7507
|
/** Approve or reject a fact. Returns false when the id is unknown. */
|
|
7506
7508
|
review(agentId: string, id: string, decision: "approved" | "rejected", by?: string): boolean;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as L}from"./chunk-W5C2GDNC.js";import{$ as Tt,_ as bt,a as St,aa as Mt,b as kt,c as vt,d as xt,e as $t,f as Ct,g as Pt}from"./chunk-
|
|
1
|
+
import{a as L}from"./chunk-W5C2GDNC.js";import{$ as Tt,_ as bt,a as St,aa as Mt,b as kt,c as vt,d as xt,e as $t,f as Ct,g as Pt}from"./chunk-MDAC3PKR.js";import"./chunk-MX5GCR7Y.js";import"./chunk-V5FZJUK4.js";import"./chunk-3SCPRYJB.js";import"./chunk-V7FYSZSV.js";import"./chunk-ZVP6GB4G.js";import{P as yt,l as lt,m as ct,n as dt,o as mt,p as pt}from"./chunk-3RKIBJG6.js";import"./chunk-TCJ3SMOF.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import{A as D,B as z,C as V,a as ye,b as we,c as Se,d as Ae,e as Ie,f as Oe,g as Ne,h as He,i as je,j as Ue,k as _e,l as I,m as q,n as Be,o as qe,p as Ye,q as O,r as ze,s as Ve,t as Xe,u as x,v as Y,w as Qe,x as Ze,y as et,z as wt}from"./chunk-3FIS6JD3.js";import{a as B,b as M,c as F}from"./chunk-SFQUP3BP.js";import{k as ut}from"./chunk-BIFJSQB5.js";import"./chunk-WPMX3VGI.js";import"./chunk-K33GIBSE.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-NSYY5NCR.js";import"./chunk-ICZPZYYR.js";import"./chunk-DWADWDMU.js";import"./chunk-CQR6C5FU.js";import"./chunk-VWTBHLMX.js";import{a as gt,b as ft,e as ht}from"./chunk-MTVRYTLL.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TNFOGJWZ.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import{j as it,k as rt,l as at}from"./chunk-6HMZ5TTM.js";import"./chunk-F4HZTZHW.js";import"./chunk-AJONZWLT.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-QOYAX2FT.js";import{a as ke,b as ve,c as xe,d as $e,e as Ce,f as Pe,g as be,h as Te,i as Me,j as Re,l as Ee,m as Ge,o as T,p as W}from"./chunk-LCIREYTD.js";import{a as m,b as G}from"./chunk-L2WSPY6S.js";import{a as Fe,b as Le,c as A,d as De}from"./chunk-VDMYBPYB.js";import{a as Ke,b as Je,e as We}from"./chunk-DSYKYZMT.js";import{j as tt,l as st,m as ot,o as nt}from"./chunk-QJANPP4C.js";import"./chunk-BH3GTCZ6.js";import"./chunk-FIOB3MEX.js";W();G();import{execa as Rt}from"execa";import{existsSync as se,promises as X}from"fs";import S from"path";import ie from"node-fetch";async function Et(o,e){let t=o.split("/");if(t.length<2)throw new Error(`Invalid skill package ID: ${o}. Expected format: owner/repo`);let s=t[0],i=t[1],n=t[2];try{let a=n?`${s}/${i}/${n}`:`${s}/${i}`;await Rt("npx",["-y","skills","add",a],{cwd:e,stdio:"pipe"}),m.success(`Installed skill package: ${o}`);let r=S.resolve(e,".skills",`${s}_${i}`);if(se(r))return await ne(r,o);let d=S.resolve(e,".skills");return se(d)?await ne(d,o):[]}catch{return m.info(`Fetching skills directly from GitHub: ${s}/${i}`),await Gt(s,i,n,e)}}async function Gt(o,e,t,s){let i=[];try{let n=`https://api.github.com/repos/${o}/${e}/git/trees/main?recursive=1`,a=await ie(n);if(!a.ok)throw new Error(`GitHub API error: ${a.status}`);let d=(await a.json()).tree.filter(p=>p.type==="blob"&&p.path.endsWith("SKILL.md"));if(t){let p=d.find(f=>f.path.includes(`/${t}/`)||f.path===`${t}/SKILL.md`);if(p){let f=await oe(o,e,p.path,s);f&&i.push(f)}}else for(let p of d){let f=await oe(o,e,p.path,s);f&&i.push(f)}}catch(n){m.error(`Failed to fetch skills from GitHub: ${n.message}`)}return i}async function oe(o,e,t,s){try{let i=`https://raw.githubusercontent.com/${o}/${e}/main/${t}`,n=await ie(i);if(!n.ok)return null;let a=await n.text(),r=A(a);if(r){r.source="remote",r.packageId=`${o}/${e}`;let d=S.dirname(t),p=S.resolve(s,".skills",`${o}_${e}`,d);await X.mkdir(p,{recursive:!0}),await X.writeFile(S.resolve(p,"SKILL.md"),a),r.path=S.resolve(p,"SKILL.md")}return r}catch{return null}}async function ne(o,e){let t=[],{default:s}=await import("fast-glob"),i=await s.glob("**/SKILL.md",{cwd:o,deep:5});for(let n of i)try{let a=S.resolve(o,n),r=await X.readFile(a,"utf8"),d=A(r);d&&(d.source="remote",d.path=a,d.packageId=e,t.push(d))}catch{}return t}async function At(o,e,t,s,i){let n=["---",`name: ${o}`,`description: ${e}`];if(s?.length){n.push("tags:");for(let a of s)n.push(` - ${a}`)}if(i?.length){n.push("globs:");for(let a of i)n.push(` - ${a}`)}return n.push("---"),`${n.join(`
|
|
2
2
|
`)}
|
|
3
3
|
|
|
4
4
|
${t}`}async function It(o){let{loadLocalSkills:e}=await import("./loader-BOKE5M5S.js");return e(o)}async function Ot(o,e,t,s,i){let a=[{role:"system",content:`You are a skill author for the Agent Skills ecosystem (skills.sh).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=program-
|
|
1
|
+
import{a}from"./chunk-KZYNQRQQ.js";import"./chunk-7A7RC3R4.js";import"./chunk-YQVR2HQS.js";import"./chunk-SAFAI4AV.js";import"./chunk-2TJ5L7CB.js";import"./chunk-7CVJ4JOE.js";import"./chunk-WLVQDEOT.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-SZDACK6O.js";import"./chunk-MDAC3PKR.js";import"./chunk-MX5GCR7Y.js";import"./chunk-V5FZJUK4.js";import"./chunk-3SCPRYJB.js";import"./chunk-V7FYSZSV.js";import"./chunk-ZVP6GB4G.js";import"./chunk-3RKIBJG6.js";import"./chunk-TCJ3SMOF.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import"./chunk-3FIS6JD3.js";import"./chunk-SFQUP3BP.js";import"./chunk-BIFJSQB5.js";import"./chunk-WPMX3VGI.js";import"./chunk-K33GIBSE.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-NSYY5NCR.js";import"./chunk-ICZPZYYR.js";import"./chunk-DWADWDMU.js";import"./chunk-CQR6C5FU.js";import"./chunk-VWTBHLMX.js";import"./chunk-MTVRYTLL.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TNFOGJWZ.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import"./chunk-6HMZ5TTM.js";import"./chunk-F4HZTZHW.js";import"./chunk-AJONZWLT.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-QOYAX2FT.js";import"./chunk-LCIREYTD.js";import"./chunk-L2WSPY6S.js";import"./chunk-VDMYBPYB.js";import"./chunk-DSYKYZMT.js";import"./chunk-QJANPP4C.js";import"./chunk-BH3GTCZ6.js";import"./chunk-FIOB3MEX.js";export{a as buildProgram};
|
|
2
|
+
//# sourceMappingURL=program-WLPVWTAT.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{G as a,H as b,I as c,J as d,K as e,L as f,M as g,N as h,O as i,P as j}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=registry-
|
|
1
|
+
import{G as a,H as b,I as c,J as d,K as e,L as f,M as g,N as h,O as i,P as j}from"./chunk-3RKIBJG6.js";import"./chunk-TCJ3SMOF.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import"./chunk-BIFJSQB5.js";import"./chunk-WPMX3VGI.js";import"./chunk-K33GIBSE.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-NSYY5NCR.js";import"./chunk-ICZPZYYR.js";import"./chunk-DWADWDMU.js";import"./chunk-CQR6C5FU.js";import"./chunk-VWTBHLMX.js";import"./chunk-MTVRYTLL.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-TNFOGJWZ.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import"./chunk-6HMZ5TTM.js";import"./chunk-F4HZTZHW.js";import"./chunk-AJONZWLT.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-QOYAX2FT.js";import"./chunk-LCIREYTD.js";import"./chunk-L2WSPY6S.js";import"./chunk-DSYKYZMT.js";import"./chunk-QJANPP4C.js";import"./chunk-BH3GTCZ6.js";import"./chunk-FIOB3MEX.js";export{j as AgentRegistry,e as TRACE_STEP_SUMMARY_BYTES,c as buildEntryMeta,d as buildWikiContext,f as clipForTrace,i as emitTraceStepsFromStreamEvent,h as firstMissingRequiredTool,b as getGlobalRegistry,a as setGlobalRegistry,g as tallyToolUses};
|
|
2
|
+
//# sourceMappingURL=registry-EESWAPMR.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentix-cli",
|
|
3
|
-
"version": "0.45.
|
|
3
|
+
"version": "0.45.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": {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|