agentix-cli 0.32.0 → 0.33.0
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/{board-dashboard-LL3YVODL.js → board-dashboard-XYB7M5BH.js} +34 -34
- package/dist/board-dashboard-XYB7M5BH.js.map +1 -0
- package/dist/{chunk-WFIBOAXN.js → chunk-UEP7IRBD.js} +119 -119
- package/dist/chunk-UEP7IRBD.js.map +1 -0
- package/dist/{chunk-H57XXGMF.js → chunk-WZD3OS7T.js} +4 -4
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-7ULXLTD6.js → program-PK5R7GIC.js} +2 -2
- package/dist/web/activity-graph.global.js +11 -11
- package/dist/web/activity-graph.global.js.map +1 -1
- package/package.json +1 -1
- package/dist/board-dashboard-LL3YVODL.js.map +0 -1
- package/dist/chunk-WFIBOAXN.js.map +0 -1
- /package/dist/{chunk-H57XXGMF.js.map → chunk-WZD3OS7T.js.map} +0 -0
- /package/dist/{program-7ULXLTD6.js.map → program-PK5R7GIC.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as yr,b as nn,g as wr}from"./chunk-4CR463C6.js";import{b as mr}from"./chunk-G5MFPNGJ.js";import{a as Yo,b as gr,f as tn,j as fr}from"./chunk-B2XTYYXV.js";import{a as pr,c as ur,d as hr}from"./chunk-2TJ5L7CB.js";import{a as zo}from"./chunk-GV7S5BAX.js";import{e as Ci}from"./chunk-GSX4NK2N.js";import{c as ji}from"./chunk-SZDACK6O.js";import{A as ts,B as ns,C as lr,D as dr,a as Ui,b as Fi,h as Ji,i as Hi,j as kt,k as on,l as Gi,m as zi,n as Yi,o as Ki,p as Xi,q as Vi,r as Qi,s as Zi,t as er,u as or,v as tr,w as nr,x as sr,y as ir,z as cr}from"./chunk-
|
|
1
|
+
import{a as yr,b as nn,g as wr}from"./chunk-4CR463C6.js";import{b as mr}from"./chunk-G5MFPNGJ.js";import{a as Yo,b as gr,f as tn,j as fr}from"./chunk-B2XTYYXV.js";import{a as pr,c as ur,d as hr}from"./chunk-2TJ5L7CB.js";import{a as zo}from"./chunk-GV7S5BAX.js";import{e as Ci}from"./chunk-GSX4NK2N.js";import{c as ji}from"./chunk-SZDACK6O.js";import{A as ts,B as ns,C as lr,D as dr,a as Ui,b as Fi,h as Ji,i as Hi,j as kt,k as on,l as Gi,m as zi,n as Yi,o as Ki,p as Xi,q as Vi,r as Qi,s as Zi,t as er,u as or,v as tr,w as nr,x as sr,y as ir,z as cr}from"./chunk-UEP7IRBD.js";import{i as rr,j as es,k as ar,l as os}from"./chunk-F6CNF7V3.js";import{a as qi,d as Wi,e as Bi}from"./chunk-GWQIMAJ7.js";import{J as Mi,m as Ei,o as Jo,q as Vn,r as Oi,t as lo,z as Li}from"./chunk-6VQKHMEQ.js";import{b as Ho,c as Zt,d as en,e as Go,f as Ii,g as Ao,h as $t}from"./chunk-5FEQI22L.js";import{d as Zn,f as Di}from"./chunk-VMDA2SX2.js";import{a as _i}from"./chunk-QLTM3F7M.js";import{a as Ai,e as Ni}from"./chunk-A4YR3PQY.js";import{f as Ri,g as Ti,h as Qn}from"./chunk-76Z4VHDX.js";import{a as de,b as we,c as Oo,d as Pi}from"./chunk-JWKIFAXA.js";import{h as Si}from"./chunk-DWADWDMU.js";import{b as co,d as Qt,f as Xn}from"./chunk-MFVI5FOM.js";import{b as Bo,d as xi}from"./chunk-2GIDVZ4H.js";import{a as Kn,b as gi,c as Wc,d as Xt,e as mi,f as yi,g as Jc,h as wi,i as Hc,m as Wo,n as $i,o as ki,s as vi,v as Ye,w as bt}from"./chunk-2DBGOCCW.js";import{a as bi,b as Gc}from"./chunk-AJONZWLT.js";import{a as to,b as qo,e as ui,f as wt}from"./chunk-F4HZTZHW.js";import{a as oo,b as qc}from"./chunk-L2WSPY6S.js";import{f as pi,g as F,h as Vt,j as Ae}from"./chunk-2DMVKLLE.js";import{g as hi,k as fi,l as Bc}from"./chunk-BH3GTCZ6.js";import{a as Fc}from"./chunk-FIOB3MEX.js";import{Command as zc}from"commander";var br=new zc().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 Fi({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()});Ae();import{Command as Kc}from"commander";import{execFileSync as no}from"node:child_process";import{cpSync as Er,existsSync as cs,mkdirSync as rs,mkdtempSync as Xc,readFileSync as Vc,rmSync as Qc,writeFileSync as Ar}from"node:fs";import{dirname as as,join as Ie,resolve as Or}from"node:path";import{homedir as an,release as Zc,tmpdir as el}from"node:os";import{fileURLToPath as ol}from"node:url";import{setTimeout as tl}from"node:timers/promises";import{existsSync as Yc}from"node:fs";import{join as $r}from"node:path";var sn="tn.acme.agentx.voice",rn="AgentX Desktop.app",vt="AgentX Helper.app";function kr(e,o,t){return e!=="darwin"||o!=="arm64"||Number(t.split(".")[0])<23?"AgentX Desktop currently requires Apple Silicon and macOS 14 or newer.":null}function vr(e,o){if(o&&!Object.hasOwn(e,o))throw new Error(`Unknown agent: ${o}. Run agentx agent list.`);let t=o||Object.keys(e)[0];if(!t)throw new Error("No agents configured. Run agentx setup first.");return t}function ss(e){return`'${e.replace(/'/g,"'\\''")}'`}function xr(e){let o=n=>n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),t={AGENTX_VOICE_AGENT:e.agent,AGENTX_DAEMON_URL:e.url,AGENTX_MAC_HELPER:e.helper,AGENTX_PASTE_COMMAND:`cd ${ss(e.cwd)} && ${ss(e.node)} ${ss(e.cli)} paste`};return`<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
3
|
<plist version="1.0"><dict>
|
|
4
4
|
<key>Label</key><string>${sn}</string>
|
|
@@ -318,7 +318,7 @@ ${n}`:n,a=await fetch(`${rg}/send`,{method:"POST",headers:{"Content-Type":"appli
|
|
|
318
318
|
settings \u2014 without this an attached production identity would be less
|
|
319
319
|
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)}});Do.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=_r({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)}});Ae();import{Command as Ig}from"commander";import pe from"chalk";var On=new Ig().name("process").description("inspect / rotate persistent claude processes (--persistentProcess agents)");function Ra(e){let o=typeof e.node=="string"?e.node:"",t=typeof e.token=="string"?e.token:"";if(!o||!t)try{let n=F(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 Ta(e,o){let t={};return e&&(t.Authorization=`Bearer ${e}`),o&&(t["Content-Type"]=o),t}function ja(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 Cg(e){return e==="busy"?pe.magenta:e==="warm-hot"?pe.green:e==="warm-cold"?pe.cyan:e==="idle"?pe.yellow:e==="dead"?pe.red:pe.dim}On.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}=Ra(e),n;try{n=await fetch(`${o}/api/processes`,{headers:Ta(t)})}catch(r){console.log(pe.red(` could not reach daemon at ${o}: ${r.message||r}`)),process.exit(1)}if(n.status===503){console.log(pe.dim(` daemon at ${o} has no agents with persistentProcess: true`));return}n.ok||(console.log(pe.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(pe.dim(" (no processes)"));return}for(let r of i){let a=Cg(r.state)(r.state.padEnd(9)),c=ja(r.spawnedAt),l=r.lastTurnAt?ja(r.lastTurnAt)+" ago":"\u2014",d=r.lastInputTokens?pe.dim(`last_in=${r.lastInputTokens} tok`):"",g=r.claudeSessionId?pe.dim(`sess=${r.claudeSessionId.slice(0,8)}\u2026`):pe.dim("sess=\u2014"),p=r.pendingTaskId?pe.cyan(`task=${String(r.pendingTaskId).slice(0,12)}`):"";console.log(`${a} ${pe.bold(r.key.agentId)}${pe.dim(":"+r.key.channel+":"+r.key.chatId)} ${pe.dim("\xB7")} pid=${r.pid??"?"} age=${c} turn#${r.turnCount} last=${l} ${g} ${d} ${p}`),r.deadReason&&console.log(` ${pe.red("dead:")} ${r.deadReason}`)}});On.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}=Ra(n),r;try{r=await fetch(`${s}/api/processes/kill`,{method:"POST",headers:Ta(i,"application/json"),body:JSON.stringify({agentId:e,channel:o,chatId:t,reason:n.reason})})}catch(a){console.log(pe.red(` could not reach daemon at ${s}: ${a.message||a}`)),process.exit(1)}if(r.status===503){console.log(pe.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(pe.red(` ${a}`)),process.exit(1)}console.log(pe.green(` killed ${e}:${o}:${t}`))});import{Command as jg}from"commander";import je from"chalk";import{existsSync as Ns,rmSync as Rg}from"fs";import{resolve as _s}from"path";var nt=new jg().name("rag").description("manage per-agent lexical (BM25) RAG indexes (improvement plan #7)");nt.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(je.red(` No globs provided. Example: agentx rag add ${e} './docs/**/*.md'`)),process.exit(1));let n=!!t.verbose,s=Date.now(),i=await Ri(e,o,{verbose:n}),r=Date.now()-s;console.log(je.green(` \u2713 indexed ${i.docs} doc(s) for ${je.bold(e)} in ${r}ms`)),console.log(je.dim(` \u2192 ${i.path}`))});nt.command("list").description("list every agent's index, sizes, paths").option("-c, --cwd <path>","search root",process.cwd()).action(async e=>{let o=_s(e.cwd,".agentx","rag");if(!Ns(o)){console.log(je.dim(" (no indexes yet \u2014 try `agentx rag add <agentId> <glob>`)"));return}let{readdirSync:t}=await import("fs"),n=t(o).filter(s=>Ns(_s(o,s,"index.json")));if(n.length===0){console.log(je.dim(" (no indexes)"));return}for(let s of n.sort()){let i=Qn(s);console.log(` ${je.bold(s)} ${i.docs} doc(s) ${je.dim(i.path)}`)}});nt.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=Ti(e,o,{k:n});if(t.json){console.log(JSON.stringify(s,null,2));return}if(s.length===0){let i=Qn(e);i.exists?console.log(je.dim(` (no hits in ${i.docs} indexed docs)`)):console.log(je.red(` no index for ${e} \u2014 run \`agentx rag add ${e} <glob>\` first`));return}for(let i of s)console.log(` ${je.bold(i.title)} ${je.dim(`(${i.score.toFixed(2)})`)}`),console.log(` ${je.dim(i.path)}`),console.log(` ${je.dim(i.snippet.slice(0,200))}`)});nt.command("clear <agentId>").description("delete an agent's index").action(e=>{let o=_s(process.cwd(),".agentx","rag",e);if(!Ns(o)){console.log(je.dim(` no index for ${e} \u2014 nothing to clear`));return}Rg(o,{recursive:!0,force:!0}),console.log(je.green(` \u2713 cleared index for ${e}`))});Ae();import{Command as Tg}from"commander";import X from"chalk";import st from"prompts";var Po=new Tg().name("backlog").description("manage the local backlog used by business workSource=backlog");function Lt(e){let o=F(e),t=o.business?.workSource,n=t?.type==="backlog"?t.path:".agentx/backlog.md";return{config:o,storePath:n,store:new rr(n)}}function Ng(e){return e?X.cyan(`${e.type}:${e.project}#${e.iid}`):X.dim("manual")}function _g(e){return{todo:X.gray("todo"),doing:X.yellow("doing"),blocked:X.red("blocked"),done:X.green("done")}[e]}Po.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}=Lt(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(X.dim(" (no items)"));return}console.log();for(let n of t){let s=n.assignee?X.magenta(`@${n.assignee}`):X.dim("unassigned");console.log(` ${_g(n.status).padEnd(7)} ${Ng(n.source)} ${s} ${n.title}`),n.source?.url&&console.log(X.dim(` ${n.source.url}`))}console.log(),console.log(X.dim(` ${t.length} item${t.length===1?"":"s"} \u2014 ${o.jsonPath()}`))});Po.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=Lt(t.config);n.store.findById(e)||(console.error(X.red(` item ${e} not found`)),process.exit(1));let i=n.store.update(e,{assignee:o,status:"doing"});if(console.log(X.green(` claimed: ${i.title} -> ${o}`)),i.source){let r=ar([o],i.source,n.config),a=await os(i,{assigneeUsernames:r,addLabels:["Doing"],removeLabels:["To Do"]},n.config,(...c)=>console.log(X.dim(" sync:"),...c));console.log(a.ok?X.dim(` synced -> ${a.url??i.source.type}`):X.yellow(` sync failed: ${a.error}`))}});Po.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=Lt(o.config);t.store.findById(e)||(console.error(X.red(` item ${e} not found`)),process.exit(1));let s=t.store.update(e,{status:"done"});if(console.log(X.green(` done: ${s.title}`)),s.source){let i=await os(s,{addLabels:["Done"],removeLabels:["Doing"],state:o.close?"closed":void 0,note:o.note},t.config,(...r)=>console.log(X.dim(" sync:"),...r));console.log(i.ok?X.dim(` synced -> ${i.url??s.source.type}`):X.yellow(` sync failed: ${i.error}`))}});Po.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}=Lt(o.config);t.remove(e)||(console.error(X.red(` item ${e} not found`)),process.exit(1)),console.log(X.green(` removed ${e}`))});Po.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=Lt(e.config),t=!!o.config.channels.gitlab?.token,n=!!o.config.channels.github?.token;!t&&!n&&(console.error(X.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 st({type:"select",name:"source",message:"Source",choices:y})).source,!s)return}s==="gitlab"&&!t&&(console.error(X.red(" channels.gitlab.token not configured")),process.exit(1)),s==="github"&&!n&&(console.error(X.red(" channels.github.token not configured")),process.exit(1));let i=e.project;if(!i){let y=s==="gitlab"?Pg(o.config):Lg(o.config);y.length?(i=(await st({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 st({type:"text",name:"p",message:s==="gitlab"?"Group/path":"owner/repo"})).p)):i=(await st({type:"text",name:"p",message:s==="gitlab"?"Group/path":"owner/repo"})).p}if(!i)return;let a=((await st({type:"text",name:"search",message:"Search filter (optional \u2014 leave empty for all open)"})).search||"").trim();console.log(X.dim(` fetching open issues from ${s}:${i}${a?` (search: ${a})`:""}\u2026`));let c=s==="gitlab"?await Mg(o.config,i,a):await Ug(o.config,i,a);if(!c.length){console.log(X.yellow(" no open issues matched"));return}console.log(X.dim(` ${c.length} open issue${c.length===1?"":"s"}`));let l=i,d=new Set(o.store.list().map(y=>y.id)),g=c.map(y=>{let $=es({type:s,project:l,iid:y.iid,url:y.url}),b=d.has($),v=y.labels.length?` [${y.labels.slice(0,3).join(",")}]`:"";return{title:`#${y.iid} ${y.title}${v}${b?X.dim(" (already imported)"):""}`,value:y,disabled:b}}),u=(await st({type:"autocompleteMultiselect",name:"selected",message:"Pick issues to import (space to toggle, Enter to confirm)",instructions:!1,choices:g,min:1})).selected||[];if(!u.length){console.log(X.dim(" nothing selected"));return}let h=u.map(y=>{let $={type:s,host:s==="gitlab"?Dg(o.config):void 0,project:l,iid:y.iid,url:y.url};return{id:es($),title:y.title,description:y.description,assignee:e.assignee||y.assignee,labels:y.labels,milestone:y.milestone,status:"todo",source:$,importedAt:new Date().toISOString()}}),w=o.store.addMany(h);console.log(X.green(` imported ${w.length} item${w.length===1?"":"s"}`));for(let y of w)console.log(X.dim(` ${y.id} \u2014 ${y.title}`))});function Dg(e){let o=e.channels.gitlab?.host;if(o)return o.replace(/^https?:\/\//,"").replace(/\/+$/,"")}function Pg(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 Lg(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 Mg(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 Ug(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(Na)}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(Na):[]}function Na(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 Wg}from"commander";import z from"chalk";import{existsSync as Bg,readFileSync as Jg}from"fs";import{resolve as Hg}from"path";import Gg from"prompts";Ae();import Fg from"cronstrue";var Ds={sun:0,sunday:0,mon:1,monday:1,tue:2,tuesday:2,tues:2,wed:3,wednesday:3,thu:4,thursday:4,thurs:4,fri:5,friday:5,sat:6,saturday:6},In={morning:{h:9,m:0},afternoon:{h:14,m:0},evening:{h:18,m:0},night:{h:22,m:0},noon:{h:12,m:0},midnight:{h:0,m:0}};function eo(e){try{return Fg.toString(e,{use24HourTimeFormat:!1})}catch{return e}}function qg(e){if(/\b(noon|midday)\b/.test(e))return In.noon;if(/\bmidnight\b/.test(e))return In.midnight;let o=e.match(/\b(?:at|by|@)\s*(\d{1,2})(?::(\d{2}))?\s*(am|pm)?\b/);if(o){let t=parseInt(o[1],10),n=o[2]?parseInt(o[2],10):0,s=o[3];return s==="pm"&&t<12&&(t+=12),s==="am"&&t===12&&(t=0),t>23||n>59?null:{h:t,m:n}}return null}function Ps(e){let o=e.trim().toLowerCase();if(!o)return null;let t;if(t=o.match(/\bevery\s+(\d+)\s*(minutes|mins|m)\b/)){let g=parseInt(t[1],10);return g<1||g>59?null:{cron:`*/${g} * * * *`,human:eo(`*/${g} * * * *`),matched:t[0]}}if(/\bevery\s+minute\b/.test(o))return{cron:"* * * * *",human:eo("* * * * *"),matched:"every minute"};if(t=o.match(/\bevery\s+(\d+)\s*(hours|hrs|h)\b/)){let g=parseInt(t[1],10);return g<1||g>23?null:{cron:`0 */${g} * * *`,human:eo(`0 */${g} * * *`),matched:t[0]}}if(/\b(every hour|hourly)\b/.test(o))return{cron:"0 * * * *",human:eo("0 * * * *"),matched:"every hour"};let n=qg(o),s=null;for(let[g,p]of Object.entries(In))if(!(g==="noon"||g==="midnight")&&new RegExp(`\\b(every\\s+)?${g}s?\\b`).test(o)){s=p;break}let i=n||s,r=o.match(/\b(first|1st|2nd|3rd|last|(\d+)(?:st|nd|rd|th)?)\s+(day\s+)?of\s+(every|each|the)\s+month\b/);if(r){let g=r[1],p=1;if(g==="last"||(/^\d+(st|nd|rd|th)?$/.test(g)?p=parseInt(g,10):g==="first"||g==="1st"?p=1:g==="2nd"?p=2:g==="3rd"&&(p=3),p<1||p>31))return null;let u=i||{h:9,m:0},h=`${u.m} ${u.h} ${p} * *`;return{cron:h,human:eo(h),matched:r[0]}}let a=[],c=Object.keys(Ds).join("|"),l=new RegExp(`\\b(?:every|on|each|by)\\s+((?:${c})s?(?:\\s*(?:,|and|&)\\s*(?:${c})s?)*)\\b`),d=o.match(l);if(d){let g=d[1];for(let p of Object.keys(Ds))if(new RegExp(`\\b${p}s?\\b`).test(g)){let u=Ds[p];a.includes(u)||a.push(u)}}if(a.length){let g=i||{h:9,m:0};a.sort((h,w)=>h-w);let p=a.join(","),u=`${g.m} ${g.h} * * ${p}`;return{cron:u,human:eo(u),matched:`on ${p}`}}if(/\b(weekday|workday|business day)s?\b/.test(o)){let g=i||{h:9,m:0},p=`${g.m} ${g.h} * * 1-5`;return{cron:p,human:eo(p),matched:"weekdays"}}if(/\bweekends?\b/.test(o)){let g=i||{h:9,m:0},p=`${g.m} ${g.h} * * 0,6`;return{cron:p,human:eo(p),matched:"weekends"}}if(/\b(every day|daily|each day)\b/.test(o)||s){let g=i||{h:9,m:0},p=`${g.m} ${g.h} * * *`;return{cron:p,human:eo(p),matched:s&&Object.entries(In).find(([,u])=>u===s)?.[0]||"daily"}}if(n){let g=`${n.m} ${n.h} * * *`;return{cron:g,human:eo(g),matched:`at ${n.h}:${String(n.m).padStart(2,"0")}`}}return null}function _a(e,o){return`${e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40)||"job"}-${o}`}function Da(e){let o=e||Hg(process.cwd(),"agentx.json");return Bg(o)||(console.log(z.red(` No config at ${o}. Run: agentx init`)),process.exit(1)),JSON.parse(Jg(o,"utf-8"))}function zg(e){return e?e.split(",").map(o=>o.trim().toLowerCase()).filter(o=>o==="log"||o==="notify"||o==="disable"):["log"]}async function Yg(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(z.yellow(" --notify me: no notifications.destination set yet."));let{channel:s,chatId:i,accountId:r}=await Gg([{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(z.red(` Unrecognized --notify value: ${e} (use "me" or "channel:chatId[:account]")`))}var bo=new Wg().name("schedule").description('schedule agents with natural-language cron: "every morning at 9" --agent devops --do "Post standup"');bo.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: Africa/Tunis)","Africa/Tunis").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){bo.help();return}o.agent||(console.log(z.red(' --agent is required. Try: agentx schedule "every morning at 9" --agent devops --do "..."')),process.exit(1)),!o.do&&!o.id&&(console.log(z.red(' --do "<prompt>" is required')),process.exit(1));let t=Ps(e);t||(console.log(z.red(` Couldn't parse: "${e}"`)),console.log(z.dim(' Try: "every morning at 9", "weekdays at 6pm", "every 15 minutes",')),console.log(z.dim(' "every monday at 10am", "1st of every month at noon",')),console.log(z.dim(' "daily at 9:30am", "every hour", "hourly"')),process.exit(1));let n=Da(o.config),s=pi(n);n.agents?.[o.agent]||(console.log(z.red(` Agent "${o.agent}" not found in agentx.json`)),console.log(z.dim(` Available: ${Object.keys(n.agents||{}).join(", ")||"(none)"}`)),process.exit(1));let i=zg(o.onError),r=await Yg(o.notify,s);r&&!i.includes("notify")&&i.push("notify");let a=o.id||_a(t.matched,o.agent),c={enabled:!o.disabled,schedule:t.cron,timezone:o.timezone,agent:o.agent,prompt:o.do,timeout:parseInt(o.timeout,10),onError:i};o.model&&(c.model=o.model),r&&(c.notify=r);let l=await de(g=>we(g,`crons.${a}`,c),{configPath:o.config,dryRun:!!o.dryRun});l.success||(console.log(z.red(` \u2717 ${l.error}`)),process.exit(1));let d=o.dryRun?"would add":"Added";console.log(z.green(` \u2713 ${d} cron ${z.cyan(a)}`)),console.log(z.dim(` Schedule: ${t.cron} (${t.human}, ${o.timezone})`)),console.log(z.dim(` Agent: ${o.agent}`)),r&&console.log(z.dim(` Notify: ${r.channel} ${r.chatId}`)),i.length&&console.log(z.dim(` On error: ${i.join(", ")}`)),!o.dryRun&&l.reloaded&&console.log(z.dim(" Daemon hot-reloaded."))});bo.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=Da(e.config).crons||{},n=Object.entries(t);if(!n.length){console.log(z.dim(" No scheduled jobs"));return}console.log();for(let[s,i]of n){let r=i.enabled?z.green("\u25CF"):z.dim("\u25CB"),a=i.schedule;try{a=(await import("cronstrue")).default.toString(i.schedule,{use24HourTimeFormat:!1})}catch{}console.log(` ${r} ${z.cyan(s.padEnd(32))} ${z.dim(i.schedule.padEnd(14))} ${z.dim("\u2192")} ${i.agent}`),console.log(z.dim(` ${a} (${i.timezone||"UTC"})`)),i.notify&&console.log(z.dim(` notify: ${i.notify.channel} ${i.notify.chatId}`))}console.log()});for(let[e,o]of[["on",!0],["off",!1]])bo.command(`${e} <id>`).description(`${o?"enable":"disable"} a scheduled job`).action(async t=>{let n=await de(s=>{if(!Oo(s,`crons.${t}`))throw new Error(`cron "${t}" not found`);we(s,`crons.${t}.enabled`,o)});n.success||(console.log(z.red(` \u2717 ${n.error}`)),process.exit(1)),console.log(z.green(` \u2713 ${t} ${o?"enabled":"disabled"}`)),n.reloaded&&console.log(z.dim(" Daemon hot-reloaded."))});bo.command("remove <id>").alias("rm").description("remove a scheduled job").action(async e=>{let o=await de(t=>{if(!Oo(t,`crons.${e}`))throw new Error(`cron "${e}" not found`);Pi(t,`crons.${e}`)});o.success||(console.log(z.red(` \u2717 ${o.error}`)),process.exit(1)),console.log(z.green(` \u2713 ${e} removed`)),o.reloaded&&console.log(z.dim(" Daemon hot-reloaded."))});bo.command("parse <when...>").description("preview a natural-language parse without writing anything").action(e=>{let o=e.join(" "),t=Ps(o);t||(console.log(z.red(` \u2717 could not parse: "${o}"`)),process.exit(1)),console.log(z.green(` "${o}"`)),console.log(z.dim(` \u2192 ${t.cron}`)),console.log(z.dim(` \u2192 ${t.human}`))});import{Command as ym}from"commander";import it from"chalk";import Q from"chalk";import Ut from"prompts";import{readFileSync as Kg,writeFileSync as Xg,existsSync as Vg}from"fs";import{resolve as Pa}from"path";var Qg=/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;function Zg(e){let o=e.trim();return o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'")?o.slice(1,-1):o}function Ls(e){return/[\s#"'\\]/.test(e)||e===""?JSON.stringify(e):e}function La(e=".env"){let o=Pa(e);if(!Vg(o))return[];let t=Kg(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(Qg);i?n.push({kind:"kv",key:i[1],value:Zg(i[2]),raw:s}):n.push({kind:"comment",raw:s})}return n.length&&n[n.length-1].kind==="blank"&&n.pop(),n}function em(e){return e.map(o=>o.kind==="kv"?`${o.key}=${Ls(o.value)}`:o.raw).join(`
|
|
320
320
|
`)+`
|
|
321
|
-
`}function Mt(e,o,t=".env"){let n=Pa(t),s=La(n),i=s.findIndex(r=>r.kind==="kv"&&r.key===e);i>=0?s[i]={kind:"kv",key:e,value:o,raw:`${e}=${Ls(o)}`}:(s.length&&s[s.length-1].kind!=="blank"&&s.push({kind:"blank",raw:""}),s.push({kind:"kv",key:e,value:o,raw:`${e}=${Ls(o)}`})),Xg(n,em(s))}function Ms(e,o=".env"){return La(o).find(s=>s.kind==="kv"&&s.key===e)?.value}var Ma="https://t.me/BotFather";async function om(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 tm(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 Ua(e={}){console.log(),console.log(Q.bold(" Connect Telegram")),console.log(),console.log(Q.dim(` 1. Open ${Ma}`)),console.log(Q.dim(" /newbot (or /mybots \u2192 pick existing \u2192 API Token)")),console.log(Q.dim(" 2. Copy the HTTP API token \u2014 looks like 123456789:ABCdef...")),console.log();let{openBrowser:o}=await Ut({type:"confirm",name:"openBrowser",message:"Open BotFather in your browser?",initial:!0});if(o)try{let{spawn:b}=await import("child_process"),v=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";b(v,[Ma],{stdio:"ignore",detached:!0}).unref()}catch{}let{token:t}=await Ut({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(Q.red(" Aborted")),process.exit(1)),process.stdout.write(" Verifying token... ");let n=await om(t.trim());n||(console.log(Q.red("\u2717 invalid or revoked")),process.exit(1)),console.log(Q.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(Q.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(Q.red(" No agents configured. Run: agentx agent add")),process.exit(1));let d=e.agent;d||(d=(await Ut({type:"select",name:"agent",message:"Bind this bot to which agent?",choices:l.map(v=>({title:v,value:v})),initial:0})).agent),d||(console.log(Q.red(" Aborted")),process.exit(1));let g=c.channels?.telegram?.accounts||{},p=e.account||d;g[p]&&g[p].agentBinding!==d&&(p=(await Ut({type:"text",name:"account",message:`Account "${p}" is already in use. Pick a different label:`,initial:`${d}-2`,validate:v=>/^[a-z0-9-]+$/i.test(v)||"lowercase letters, digits, hyphens only"})).account),p||(console.log(Q.red(" Aborted")),process.exit(1));let u=`TG_${p.toUpperCase().replace(/-/g,"_")}_BOT_TOKEN`;Mt(u,t.trim()),process.env[u]=t.trim();let h=await de(b=>{we(b,"channels.telegram.enabled",!0),we(b,`channels.telegram.accounts.${p}`,{token:`\${${u}}`,agentBinding:d});let v=Oo(b,`agents.${d}.mentions`)||[],A=`@${n.username}`;v.includes(A)||(v.push(A),we(b,`agents.${d}.mentions`,v))},{configPath:e.configPath});if(h.success||(console.log(Q.red(` \u2717 ${h.error}`)),process.exit(1)),console.log(),console.log(Q.green(` \u2713 Bot @${n.username} bound to agent "${d}"`)),console.log(Q.dim(` Token stored in .env as ${u}`)),console.log(Q.dim(` Mentions updated to include @${n.username}`)),h.reloaded?console.log(Q.dim(" Daemon hot-reloaded.")):console.log(Q.dim(" Start the daemon to begin polling (agentx daemon start)")),e.skipChatCapture)return;console.log();let{capture:w}=await Ut({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(Q.dim(` Send any message to @${n.username} from the chat you want to use.`)),console.log(Q.dim(" Waiting up to 90s..."));let y=await tm(t.trim(),9e4);if(!y){console.log(Q.yellow(" No message received \u2014 skipping. You can set it later with:")),console.log(Q.dim(" agentx config set notifications.destination.channel telegram")),console.log(Q.dim(" agentx config set notifications.destination.chatId <chatId>")),console.log(Q.dim(` agentx config set notifications.destination.accountId ${p}`));return}let $=await de(b=>{we(b,"notifications.destination",{channel:"telegram",chatId:String(y.chatId),accountId:p})},{configPath:e.configPath});if(!$.success){console.log(Q.red(` \u2717 failed to save destination: ${$.error}`));return}console.log(Q.green(" \u2713 Default --notify target set")),console.log(Q.dim(` Chat: ${y.chatTitle||y.chatId} (from ${y.from})`)),console.log(Q.dim(" From now on, --notify me resolves to this chat.")),$.reloaded&&console.log(Q.dim(" Daemon hot-reloaded."))}import ue from"chalk";import Us from"prompts";import{existsSync as qs,mkdirSync as nm,readdirSync as sm,readFileSync as Fa}from"fs";import{resolve as Fs}from"path";var im=".agentx/whatsapp-sessions";function rm(){let e=Fs(process.cwd(),".agentx/daemon.pid");if(!qs(e))return!1;try{let o=parseInt(Fa(e,"utf-8").trim(),10);return o?(process.kill(o,0),!0):!1}catch{return!1}}function am(e){if(!qs(e))return!1;try{return sm(e).some(o=>o.includes("creds")||o.endsWith(".json"))}catch{return!1}}async function cm(e,o){let t;try{t=await import("@whiskeysockets/baileys")}catch{return o(ue.red(" WhatsApp pairing needs @whiskeysockets/baileys.")),o(ue.red(" Install with: pnpm add @whiskeysockets/baileys (or npm install)")),!1}let{makeWASocket:n,useMultiFileAuthState:s}=t.default||t;nm(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(d=>{let p=setTimeout(()=>{o(ue.yellow(" Timed out waiting for scan (2min)."));try{l.end(void 0)}catch{}d(!1)},12e4);l.ev.on("connection.update",async u=>{if(u.qr){o(ue.dim(" Scan this QR with WhatsApp \u2192 Linked devices \u2192 Link a device:")),o("");try{let{default:h}=await import("qrcode-terminal");h.generate(u.qr,{small:!0})}catch{o(` QR: ${u.qr}`)}o("")}if(u.connection==="open"){clearTimeout(p),o(ue.green(" \u2713 Paired"));try{l.end(void 0)}catch{}d(!0)}u.connection==="close"&&!u.qr&&u.lastDisconnect?.error?.output?.statusCode===401&&(clearTimeout(p),o(ue.red(" \u2717 Authorization failed \u2014 rescan required")),d(!1))})})}async function qa(e={}){if(console.log(),console.log(ue.bold(" Connect WhatsApp")),console.log(),rm()){console.log(ue.yellow(" \u26A0 The daemon is running. Stop it first so pairing can open a fresh Baileys session:")),console.log(ue.dim(" agentx daemon stop")),console.log();let{cont:l}=await Us({type:"confirm",name:"cont",message:"Continue anyway? (expect errors)",initial:!1});l||(console.log(ue.red(" Aborted")),process.exit(1))}let o=e.configPath||Fs(process.cwd(),"agentx.json");qs(o)||(console.log(ue.red(` No agentx.json at ${o}. Run: agentx init`)),process.exit(1));let t=JSON.parse(Fa(o,"utf-8")),n=e.sessionDir||t.channels?.whatsapp?.sessionDir||im,s=Fs(process.cwd(),n),i=Object.keys(t.agents||{});i.length===0&&(console.log(ue.red(" No agents configured. Run: agentx agent add")),process.exit(1));let r=e.agent;r||(r=(await Us({type:"select",name:"agent",message:"Default agent for incoming messages:",choices:i.map(d=>({title:d,value:d})),initial:0})).agent),r||(console.log(ue.red(" Aborted")),process.exit(1));let a=!e.skipPair;if(am(s)&&a){let{keep:l}=await Us({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(ue.dim(" Keeping existing session \u2014 skipping QR pair."))}a&&(await cm(s,d=>console.log(d))||(console.log(ue.red(" Pairing failed. You can retry with `agentx connect whatsapp`.")),process.exit(1)));let c=await de(l=>{we(l,"channels.whatsapp.enabled",!0),we(l,"channels.whatsapp.sessionDir",n),we(l,"channels.whatsapp.defaultAgent",r)},{configPath:e.configPath});c.success||(console.log(ue.red(` \u2717 ${c.error}`)),process.exit(1)),console.log(),console.log(ue.green(` \u2713 WhatsApp bound to agent "${r}"`)),console.log(ue.dim(` Session: ${n}`)),console.log(ue.dim(" Start the daemon to begin receiving:")),console.log(ue.dim(" agentx daemon start")),console.log(ue.dim(" Add routes later with:")),console.log(ue.dim(` agentx config set channels.whatsapp.routes '[{"contact":"+1234567890","agent":"${r}"}]'`)),console.log()}import{randomBytes as lm}from"crypto";import be from"chalk";import Wa from"prompts";var Cn="agentx-mesh:",jn="//join/";function dm(e){return Buffer.from(e,"utf-8").toString("base64url")}function gm(e){return Buffer.from(e,"base64url").toString("utf-8")}function mm(e){return`${Cn}${jn}${dm(JSON.stringify(e))}`}function pm(e){if(!e.startsWith(`${Cn}${jn}`))throw new Error(`Not a mesh invite link \u2014 expected ${Cn}${jn}\u2026`);let o=e.slice(Cn.length+jn.length),t=JSON.parse(gm(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 um(){return lm(32).toString("hex")}function hm(e){let o=e?.node?.bind||"127.0.0.1:18800",[t,n]=o.split(":");return`http://${t}:${n}`}function fm(e){return e?.node?.name||e?.node?.id||"node"}async function Ba(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(be.red(` No agentx.json at ${s}. Run: agentx init`)),process.exit(1));let i=JSON.parse(o(s,"utf-8")),r=Ms("MESH_TOKEN");r||(r=um(),Mt("MESH_TOKEN",r),console.log(be.dim(" Generated new MESH_TOKEN (32 bytes) and saved to .env")));let a=e.url||hm(i);if((a.includes("0.0.0.0")||a.includes("127.0.0.1")||a.includes("localhost"))&&!e.url){let{url:g}=await Wa({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:p=>/^https?:\/\//.test(p)||"must start with http:// or https://"});g||(console.log(be.red(" Aborted")),process.exit(1)),a=g}let l=await de(g=>{we(g,"mesh.enabled",!0)},{configPath:e.configPath});l.success||(console.log(be.red(` \u2717 ${l.error}`)),process.exit(1));let d=mm({url:a,token:r,name:fm(i),version:1});console.log(),console.log(be.bold(" Mesh invite")),console.log(),console.log(` ${be.cyan(d)}`),console.log(),console.log(be.dim(" Run on the other node:")),console.log(be.dim(` agentx connect mesh join "${d}"`)),console.log(),console.log(be.yellow(" Share over a trusted channel only \u2014 whoever holds this link can join your mesh.")),console.log()}async function Ja(e,o={}){let t;try{t=pm(e)}catch(i){console.log(be.red(` \u2717 ${i.message}`)),process.exit(1)}let n=Ms("MESH_TOKEN");if(n&&n!==t.token){let{overwrite:i}=await Wa({type:"confirm",name:"overwrite",message:"A different MESH_TOKEN already exists in .env. Overwrite with the invite's token?",initial:!1});i||(console.log(be.red(" Aborted (keeping existing .env)")),process.exit(1))}Mt("MESH_TOKEN",t.token);let s=await de(i=>{we(i,"mesh.enabled",!0);let r=Oo(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),we(i,"mesh.peers",r)},{configPath:o.configPath});s.success||(console.log(be.red(` \u2717 ${s.error}`)),process.exit(1)),console.log(be.green(" \u2713 Joined mesh")),console.log(be.dim(` Peer: ${t.name} @ ${t.url}`)),console.log(be.dim(" Shared token stored in .env as MESH_TOKEN")),s.reloaded?console.log(be.dim(" Daemon hot-reloaded.")):console.log(be.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(be.dim(` Reachable \u2014 ${t.name} exposes ${a} agents`))}else console.log(be.yellow(` Peer returned HTTP ${i.status} \u2014 double-check the URL`))}catch(i){console.log(be.yellow(` Could not reach ${t.url} right now (${i?.cause?.code||i.message}) \u2014 verify VPN / Tailscale when the peer daemon is up`))}}var rt=new ym().name("connect").description("connect a channel or mesh peer \u2014 no manual file editing required");rt.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 Ua({agent:e.agent,account:e.account,configPath:e.config,skipChatCapture:!!e.skipChatCapture})});rt.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 qa({agent:e.agent,sessionDir:e.sessionDir,skipPair:!!e.skipPair,configPath:e.config})});var Ha=rt.command("mesh").description("mesh invite + join \u2014 replaces manual MESH_TOKEN copy-paste");Ha.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 Ba({url:e.url,configPath:e.config})});Ha.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 Ja(e,{configPath:o.config})});rt.action(()=>{console.log(),console.log(it.bold(" agentx connect \u2014 which channel?")),console.log(),console.log(` ${it.cyan("agentx connect telegram")} \u2014 pair a Telegram bot`),console.log(` ${it.cyan("agentx connect whatsapp")} \u2014 pair WhatsApp via QR`),console.log(` ${it.cyan("agentx connect mesh invite")} \u2014 emit a mesh join link for another node`),console.log(` ${it.cyan("agentx connect mesh join <link>")} \u2014 accept a mesh invite`),console.log(),console.log(it.dim(" GitLab connect is the next slice.")),console.log()});Ae();import{Command as wm}from"commander";import le from"chalk";var Ft=new wm().name("usage").description("token usage analysis and reporting");Ft.command("today",{isDefault:!0}).description("show today's token usage").action(async()=>{try{let e=F(),[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(le.bold(" Token Usage (last 7 days)")),console.log(),s.totalTasks===0){console.log(le.dim(" No tasks recorded yet")),console.log();return}let i=a=>a.toLocaleString();console.log(` Total: ${le.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: ${le.red(String(s.totalErrors))}`),console.log(),console.log(le.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),d=c.avgDuration?`${(c.avgDuration/1e3).toFixed(1)}s avg`:"";console.log(` ${le.cyan(a)}: ${l} tokens (${c.tasks} tasks) ${le.dim(d)}`)}console.log()}catch(e){e.cause?.code==="ECONNREFUSED"?console.log(le.red(" Daemon not running. Start with: agentx daemon start")):console.log(le.red(` ${e.message}`))}});Ft.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(le.red(` Script not found: ${s}`)),console.log(le.dim(" The token analyzer script should be at scripts/token-report.py"));return}console.log(le.dim(" Analyzing Claude Code sessions..."));try{o(`SINCE_DAYS=${e.days} python3 "${s}"`,{stdio:"inherit"})}catch{console.log(le.red(" Analysis failed. Is Python 3 installed?"))}});Ft.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-7ULXLTD6.js"),r=await i(),a=new Set(n.filter(g=>g.kind==="cli").map(g=>g.name)),c=[],l=(g,p)=>{for(let u of g.commands??[]){let h=p?`${p} ${u.name()}`:u.name();c.push(h),l(u,h)}};l(r,"");let d=c.filter(g=>!a.has(g)).sort();if(e.json){console.log(JSON.stringify({windowDays:Number(e.days)||30,unused:d},null,2));return}console.log(),console.log(le.bold(` Never used in the last ${e.days} days (${d.length}/${c.length})`)),console.log();for(let g of d)console.log(` ${le.dim("\xB7")} ${g}`);console.log(),console.log(le.dim(" Zero use is necessary but not sufficient to remove a surface \u2014")),console.log(le.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(le.dim(` No surface usage recorded in the last ${e.days} days.`)),console.log(le.dim(" Counting starts once this build has been running for a while.")),console.log();return}console.log(),console.log(le.bold(` Surface usage \u2014 last ${e.days} days`)),console.log();let s="";for(let i of n){i.kind!==s&&(console.log(le.dim(` ${i.kind==="cli"?"CLI commands":"Dashboard pages"}`)),s=i.kind);let r=String(i.count).padStart(6),a=le.dim(`${i.days}d`);console.log(` ${le.cyan(r)} ${i.name.padEnd(28)} ${a}`)}console.log(),console.log(le.dim(` ${n.length} surface(s) with recorded use. See --unused for the rest.`)),console.log()});import{Command as bm}from"commander";import he from"chalk";import{resolve as $m}from"path";Ae();var $o=new bm().name("board").description("kanban board dashboard \u2014 visual work view over configured sources");$o.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{xi($m(process.cwd(),".env"))}catch{}let o=km(e.port,e.bind),{startBoardDashboard:t}=await import("./board-dashboard-LL3YVODL.js");t(o)}catch(o){console.log(he.red(` ${o.message}`)),process.env.DEBUG&&o.stack&&console.log(he.dim(o.stack)),process.exit(1)}});function km(e,o){try{let t=F();return e&&(t.dashboard.port=parseInt(e,10)),o&&(t.dashboard.bind=o),t}catch{return console.log(he.yellow(" No agentx.json found \u2014 starting dashboard in setup-only mode.")),console.log(he.dim(" Visit http://127.0.0.1:"+(e||"4202")+` to run the wizard.
|
|
321
|
+
`}function Mt(e,o,t=".env"){let n=Pa(t),s=La(n),i=s.findIndex(r=>r.kind==="kv"&&r.key===e);i>=0?s[i]={kind:"kv",key:e,value:o,raw:`${e}=${Ls(o)}`}:(s.length&&s[s.length-1].kind!=="blank"&&s.push({kind:"blank",raw:""}),s.push({kind:"kv",key:e,value:o,raw:`${e}=${Ls(o)}`})),Xg(n,em(s))}function Ms(e,o=".env"){return La(o).find(s=>s.kind==="kv"&&s.key===e)?.value}var Ma="https://t.me/BotFather";async function om(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 tm(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 Ua(e={}){console.log(),console.log(Q.bold(" Connect Telegram")),console.log(),console.log(Q.dim(` 1. Open ${Ma}`)),console.log(Q.dim(" /newbot (or /mybots \u2192 pick existing \u2192 API Token)")),console.log(Q.dim(" 2. Copy the HTTP API token \u2014 looks like 123456789:ABCdef...")),console.log();let{openBrowser:o}=await Ut({type:"confirm",name:"openBrowser",message:"Open BotFather in your browser?",initial:!0});if(o)try{let{spawn:b}=await import("child_process"),v=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";b(v,[Ma],{stdio:"ignore",detached:!0}).unref()}catch{}let{token:t}=await Ut({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(Q.red(" Aborted")),process.exit(1)),process.stdout.write(" Verifying token... ");let n=await om(t.trim());n||(console.log(Q.red("\u2717 invalid or revoked")),process.exit(1)),console.log(Q.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(Q.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(Q.red(" No agents configured. Run: agentx agent add")),process.exit(1));let d=e.agent;d||(d=(await Ut({type:"select",name:"agent",message:"Bind this bot to which agent?",choices:l.map(v=>({title:v,value:v})),initial:0})).agent),d||(console.log(Q.red(" Aborted")),process.exit(1));let g=c.channels?.telegram?.accounts||{},p=e.account||d;g[p]&&g[p].agentBinding!==d&&(p=(await Ut({type:"text",name:"account",message:`Account "${p}" is already in use. Pick a different label:`,initial:`${d}-2`,validate:v=>/^[a-z0-9-]+$/i.test(v)||"lowercase letters, digits, hyphens only"})).account),p||(console.log(Q.red(" Aborted")),process.exit(1));let u=`TG_${p.toUpperCase().replace(/-/g,"_")}_BOT_TOKEN`;Mt(u,t.trim()),process.env[u]=t.trim();let h=await de(b=>{we(b,"channels.telegram.enabled",!0),we(b,`channels.telegram.accounts.${p}`,{token:`\${${u}}`,agentBinding:d});let v=Oo(b,`agents.${d}.mentions`)||[],A=`@${n.username}`;v.includes(A)||(v.push(A),we(b,`agents.${d}.mentions`,v))},{configPath:e.configPath});if(h.success||(console.log(Q.red(` \u2717 ${h.error}`)),process.exit(1)),console.log(),console.log(Q.green(` \u2713 Bot @${n.username} bound to agent "${d}"`)),console.log(Q.dim(` Token stored in .env as ${u}`)),console.log(Q.dim(` Mentions updated to include @${n.username}`)),h.reloaded?console.log(Q.dim(" Daemon hot-reloaded.")):console.log(Q.dim(" Start the daemon to begin polling (agentx daemon start)")),e.skipChatCapture)return;console.log();let{capture:w}=await Ut({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(Q.dim(` Send any message to @${n.username} from the chat you want to use.`)),console.log(Q.dim(" Waiting up to 90s..."));let y=await tm(t.trim(),9e4);if(!y){console.log(Q.yellow(" No message received \u2014 skipping. You can set it later with:")),console.log(Q.dim(" agentx config set notifications.destination.channel telegram")),console.log(Q.dim(" agentx config set notifications.destination.chatId <chatId>")),console.log(Q.dim(` agentx config set notifications.destination.accountId ${p}`));return}let $=await de(b=>{we(b,"notifications.destination",{channel:"telegram",chatId:String(y.chatId),accountId:p})},{configPath:e.configPath});if(!$.success){console.log(Q.red(` \u2717 failed to save destination: ${$.error}`));return}console.log(Q.green(" \u2713 Default --notify target set")),console.log(Q.dim(` Chat: ${y.chatTitle||y.chatId} (from ${y.from})`)),console.log(Q.dim(" From now on, --notify me resolves to this chat.")),$.reloaded&&console.log(Q.dim(" Daemon hot-reloaded."))}import ue from"chalk";import Us from"prompts";import{existsSync as qs,mkdirSync as nm,readdirSync as sm,readFileSync as Fa}from"fs";import{resolve as Fs}from"path";var im=".agentx/whatsapp-sessions";function rm(){let e=Fs(process.cwd(),".agentx/daemon.pid");if(!qs(e))return!1;try{let o=parseInt(Fa(e,"utf-8").trim(),10);return o?(process.kill(o,0),!0):!1}catch{return!1}}function am(e){if(!qs(e))return!1;try{return sm(e).some(o=>o.includes("creds")||o.endsWith(".json"))}catch{return!1}}async function cm(e,o){let t;try{t=await import("@whiskeysockets/baileys")}catch{return o(ue.red(" WhatsApp pairing needs @whiskeysockets/baileys.")),o(ue.red(" Install with: pnpm add @whiskeysockets/baileys (or npm install)")),!1}let{makeWASocket:n,useMultiFileAuthState:s}=t.default||t;nm(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(d=>{let p=setTimeout(()=>{o(ue.yellow(" Timed out waiting for scan (2min)."));try{l.end(void 0)}catch{}d(!1)},12e4);l.ev.on("connection.update",async u=>{if(u.qr){o(ue.dim(" Scan this QR with WhatsApp \u2192 Linked devices \u2192 Link a device:")),o("");try{let{default:h}=await import("qrcode-terminal");h.generate(u.qr,{small:!0})}catch{o(` QR: ${u.qr}`)}o("")}if(u.connection==="open"){clearTimeout(p),o(ue.green(" \u2713 Paired"));try{l.end(void 0)}catch{}d(!0)}u.connection==="close"&&!u.qr&&u.lastDisconnect?.error?.output?.statusCode===401&&(clearTimeout(p),o(ue.red(" \u2717 Authorization failed \u2014 rescan required")),d(!1))})})}async function qa(e={}){if(console.log(),console.log(ue.bold(" Connect WhatsApp")),console.log(),rm()){console.log(ue.yellow(" \u26A0 The daemon is running. Stop it first so pairing can open a fresh Baileys session:")),console.log(ue.dim(" agentx daemon stop")),console.log();let{cont:l}=await Us({type:"confirm",name:"cont",message:"Continue anyway? (expect errors)",initial:!1});l||(console.log(ue.red(" Aborted")),process.exit(1))}let o=e.configPath||Fs(process.cwd(),"agentx.json");qs(o)||(console.log(ue.red(` No agentx.json at ${o}. Run: agentx init`)),process.exit(1));let t=JSON.parse(Fa(o,"utf-8")),n=e.sessionDir||t.channels?.whatsapp?.sessionDir||im,s=Fs(process.cwd(),n),i=Object.keys(t.agents||{});i.length===0&&(console.log(ue.red(" No agents configured. Run: agentx agent add")),process.exit(1));let r=e.agent;r||(r=(await Us({type:"select",name:"agent",message:"Default agent for incoming messages:",choices:i.map(d=>({title:d,value:d})),initial:0})).agent),r||(console.log(ue.red(" Aborted")),process.exit(1));let a=!e.skipPair;if(am(s)&&a){let{keep:l}=await Us({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(ue.dim(" Keeping existing session \u2014 skipping QR pair."))}a&&(await cm(s,d=>console.log(d))||(console.log(ue.red(" Pairing failed. You can retry with `agentx connect whatsapp`.")),process.exit(1)));let c=await de(l=>{we(l,"channels.whatsapp.enabled",!0),we(l,"channels.whatsapp.sessionDir",n),we(l,"channels.whatsapp.defaultAgent",r)},{configPath:e.configPath});c.success||(console.log(ue.red(` \u2717 ${c.error}`)),process.exit(1)),console.log(),console.log(ue.green(` \u2713 WhatsApp bound to agent "${r}"`)),console.log(ue.dim(` Session: ${n}`)),console.log(ue.dim(" Start the daemon to begin receiving:")),console.log(ue.dim(" agentx daemon start")),console.log(ue.dim(" Add routes later with:")),console.log(ue.dim(` agentx config set channels.whatsapp.routes '[{"contact":"+1234567890","agent":"${r}"}]'`)),console.log()}import{randomBytes as lm}from"crypto";import be from"chalk";import Wa from"prompts";var Cn="agentx-mesh:",jn="//join/";function dm(e){return Buffer.from(e,"utf-8").toString("base64url")}function gm(e){return Buffer.from(e,"base64url").toString("utf-8")}function mm(e){return`${Cn}${jn}${dm(JSON.stringify(e))}`}function pm(e){if(!e.startsWith(`${Cn}${jn}`))throw new Error(`Not a mesh invite link \u2014 expected ${Cn}${jn}\u2026`);let o=e.slice(Cn.length+jn.length),t=JSON.parse(gm(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 um(){return lm(32).toString("hex")}function hm(e){let o=e?.node?.bind||"127.0.0.1:18800",[t,n]=o.split(":");return`http://${t}:${n}`}function fm(e){return e?.node?.name||e?.node?.id||"node"}async function Ba(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(be.red(` No agentx.json at ${s}. Run: agentx init`)),process.exit(1));let i=JSON.parse(o(s,"utf-8")),r=Ms("MESH_TOKEN");r||(r=um(),Mt("MESH_TOKEN",r),console.log(be.dim(" Generated new MESH_TOKEN (32 bytes) and saved to .env")));let a=e.url||hm(i);if((a.includes("0.0.0.0")||a.includes("127.0.0.1")||a.includes("localhost"))&&!e.url){let{url:g}=await Wa({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:p=>/^https?:\/\//.test(p)||"must start with http:// or https://"});g||(console.log(be.red(" Aborted")),process.exit(1)),a=g}let l=await de(g=>{we(g,"mesh.enabled",!0)},{configPath:e.configPath});l.success||(console.log(be.red(` \u2717 ${l.error}`)),process.exit(1));let d=mm({url:a,token:r,name:fm(i),version:1});console.log(),console.log(be.bold(" Mesh invite")),console.log(),console.log(` ${be.cyan(d)}`),console.log(),console.log(be.dim(" Run on the other node:")),console.log(be.dim(` agentx connect mesh join "${d}"`)),console.log(),console.log(be.yellow(" Share over a trusted channel only \u2014 whoever holds this link can join your mesh.")),console.log()}async function Ja(e,o={}){let t;try{t=pm(e)}catch(i){console.log(be.red(` \u2717 ${i.message}`)),process.exit(1)}let n=Ms("MESH_TOKEN");if(n&&n!==t.token){let{overwrite:i}=await Wa({type:"confirm",name:"overwrite",message:"A different MESH_TOKEN already exists in .env. Overwrite with the invite's token?",initial:!1});i||(console.log(be.red(" Aborted (keeping existing .env)")),process.exit(1))}Mt("MESH_TOKEN",t.token);let s=await de(i=>{we(i,"mesh.enabled",!0);let r=Oo(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),we(i,"mesh.peers",r)},{configPath:o.configPath});s.success||(console.log(be.red(` \u2717 ${s.error}`)),process.exit(1)),console.log(be.green(" \u2713 Joined mesh")),console.log(be.dim(` Peer: ${t.name} @ ${t.url}`)),console.log(be.dim(" Shared token stored in .env as MESH_TOKEN")),s.reloaded?console.log(be.dim(" Daemon hot-reloaded.")):console.log(be.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(be.dim(` Reachable \u2014 ${t.name} exposes ${a} agents`))}else console.log(be.yellow(` Peer returned HTTP ${i.status} \u2014 double-check the URL`))}catch(i){console.log(be.yellow(` Could not reach ${t.url} right now (${i?.cause?.code||i.message}) \u2014 verify VPN / Tailscale when the peer daemon is up`))}}var rt=new ym().name("connect").description("connect a channel or mesh peer \u2014 no manual file editing required");rt.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 Ua({agent:e.agent,account:e.account,configPath:e.config,skipChatCapture:!!e.skipChatCapture})});rt.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 qa({agent:e.agent,sessionDir:e.sessionDir,skipPair:!!e.skipPair,configPath:e.config})});var Ha=rt.command("mesh").description("mesh invite + join \u2014 replaces manual MESH_TOKEN copy-paste");Ha.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 Ba({url:e.url,configPath:e.config})});Ha.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 Ja(e,{configPath:o.config})});rt.action(()=>{console.log(),console.log(it.bold(" agentx connect \u2014 which channel?")),console.log(),console.log(` ${it.cyan("agentx connect telegram")} \u2014 pair a Telegram bot`),console.log(` ${it.cyan("agentx connect whatsapp")} \u2014 pair WhatsApp via QR`),console.log(` ${it.cyan("agentx connect mesh invite")} \u2014 emit a mesh join link for another node`),console.log(` ${it.cyan("agentx connect mesh join <link>")} \u2014 accept a mesh invite`),console.log(),console.log(it.dim(" GitLab connect is the next slice.")),console.log()});Ae();import{Command as wm}from"commander";import le from"chalk";var Ft=new wm().name("usage").description("token usage analysis and reporting");Ft.command("today",{isDefault:!0}).description("show today's token usage").action(async()=>{try{let e=F(),[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(le.bold(" Token Usage (last 7 days)")),console.log(),s.totalTasks===0){console.log(le.dim(" No tasks recorded yet")),console.log();return}let i=a=>a.toLocaleString();console.log(` Total: ${le.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: ${le.red(String(s.totalErrors))}`),console.log(),console.log(le.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),d=c.avgDuration?`${(c.avgDuration/1e3).toFixed(1)}s avg`:"";console.log(` ${le.cyan(a)}: ${l} tokens (${c.tasks} tasks) ${le.dim(d)}`)}console.log()}catch(e){e.cause?.code==="ECONNREFUSED"?console.log(le.red(" Daemon not running. Start with: agentx daemon start")):console.log(le.red(` ${e.message}`))}});Ft.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(le.red(` Script not found: ${s}`)),console.log(le.dim(" The token analyzer script should be at scripts/token-report.py"));return}console.log(le.dim(" Analyzing Claude Code sessions..."));try{o(`SINCE_DAYS=${e.days} python3 "${s}"`,{stdio:"inherit"})}catch{console.log(le.red(" Analysis failed. Is Python 3 installed?"))}});Ft.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-PK5R7GIC.js"),r=await i(),a=new Set(n.filter(g=>g.kind==="cli").map(g=>g.name)),c=[],l=(g,p)=>{for(let u of g.commands??[]){let h=p?`${p} ${u.name()}`:u.name();c.push(h),l(u,h)}};l(r,"");let d=c.filter(g=>!a.has(g)).sort();if(e.json){console.log(JSON.stringify({windowDays:Number(e.days)||30,unused:d},null,2));return}console.log(),console.log(le.bold(` Never used in the last ${e.days} days (${d.length}/${c.length})`)),console.log();for(let g of d)console.log(` ${le.dim("\xB7")} ${g}`);console.log(),console.log(le.dim(" Zero use is necessary but not sufficient to remove a surface \u2014")),console.log(le.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(le.dim(` No surface usage recorded in the last ${e.days} days.`)),console.log(le.dim(" Counting starts once this build has been running for a while.")),console.log();return}console.log(),console.log(le.bold(` Surface usage \u2014 last ${e.days} days`)),console.log();let s="";for(let i of n){i.kind!==s&&(console.log(le.dim(` ${i.kind==="cli"?"CLI commands":"Dashboard pages"}`)),s=i.kind);let r=String(i.count).padStart(6),a=le.dim(`${i.days}d`);console.log(` ${le.cyan(r)} ${i.name.padEnd(28)} ${a}`)}console.log(),console.log(le.dim(` ${n.length} surface(s) with recorded use. See --unused for the rest.`)),console.log()});import{Command as bm}from"commander";import he from"chalk";import{resolve as $m}from"path";Ae();var $o=new bm().name("board").description("kanban board dashboard \u2014 visual work view over configured sources");$o.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{xi($m(process.cwd(),".env"))}catch{}let o=km(e.port,e.bind),{startBoardDashboard:t}=await import("./board-dashboard-XYB7M5BH.js");t(o)}catch(o){console.log(he.red(` ${o.message}`)),process.env.DEBUG&&o.stack&&console.log(he.dim(o.stack)),process.exit(1)}});function km(e,o){try{let t=F();return e&&(t.dashboard.port=parseInt(e,10)),o&&(t.dashboard.bind=o),t}catch{return console.log(he.yellow(" No agentx.json found \u2014 starting dashboard in setup-only mode.")),console.log(he.dim(" Visit http://127.0.0.1:"+(e||"4202")+` to run the wizard.
|
|
322
322
|
`)),{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}}}}$o.command("list").description("list configured boards").action(()=>{try{let e=F();if(!e.boards?.length){console.log(he.dim(`
|
|
323
323
|
No boards configured.
|
|
324
324
|
`));return}console.log();for(let o of e.boards){console.log(` ${he.cyan(o.id)} \u2014 ${o.name}`);let t=o.source;console.log(he.dim(` source: ${t.type}${t.projects?" ("+t.projects.join(", ")+")":""}`)),o.primaryToolLabel&&console.log(he.dim(` primary label: ${o.primaryToolLabel}`)),console.log(he.dim(` window: ${o.timeRangeDays} days`))}console.log()}catch(e){console.log(he.red(` ${e.message}`)),process.exit(1)}});$o.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{qt(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(he.red(` ${t.message}`)),process.exit(1)}});$o.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{qt(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(he.red(` ${t.message}`)),process.exit(1)}});var Ws=$o.command("column").description("manage a board's columns (add / remove / edit / list)");Ws.command("list <boardId>").description("list columns on a board, in order").action(e=>{try{let t=(JSON.parse(Fc("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(he.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(` ${he.cyan(s.id.padEnd(12))} ${s.title.padEnd(14)} ${he.dim(i)}`)}}catch(o){console.log(he.red(` ${o.message}`)),process.exit(1)}});Ws.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{qt(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(he.red(` ${n.message}`)),process.exit(1)}});Ws.command("remove <boardId> <columnId>").alias("rm").description("remove a column from a board").action((e,o)=>{try{qt(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(he.red(` ${t.message}`)),process.exit(1)}});$o.command("remove <id>").alias("rm").description("remove a board from agentx.json").action(e=>{try{qt(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(he.red(` ${o.message}`)),process.exit(1)}});function qt(e){let{summary:o,backupPath:t}=Yo(n=>e(n));console.log(he.green(`
|
|
@@ -536,7 +536,7 @@ Restart the daemon to activate.
|
|
|
536
536
|
dist/
|
|
537
537
|
*.log
|
|
538
538
|
.env
|
|
539
|
-
`}import{Command as Yp}from"commander";import Ee from"chalk";import{writeFileSync as Kp,mkdirSync as Xp,existsSync as Gn,readFileSync as Tc,appendFileSync as Nc}from"fs";import{resolve as ft,dirname as Pc}from"path";import{homedir as li}from"os";var Lc=new Yp().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-
|
|
539
|
+
`}import{Command as Yp}from"commander";import Ee from"chalk";import{writeFileSync as Kp,mkdirSync as Xp,existsSync as Gn,readFileSync as Tc,appendFileSync as Nc}from"fs";import{resolve as ft,dirname as Pc}from"path";import{homedir as li}from"os";var Lc=new Yp().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-PK5R7GIC.js"),t=await o(),n=String(e.shell||"zsh").toLowerCase(),s;switch(n){case"zsh":s=Zp(t);break;case"bash":s=su(t);break;case"fish":s=iu(t);break;default:console.error(Ee.red(`unsupported shell: ${n}`)),console.error(Ee.dim("supported: zsh, bash, fish")),process.exit(1)}if(!e.install&&!e.output){process.stdout.write(s);return}let i=e.output?ft(String(e.output)):Vp(n);Xp(Pc(i),{recursive:!0}),Kp(i,s),console.log(Ee.green(`\u2713 Wrote ${n} completion to:`)),console.log(` ${i}`),console.log(),Qp(n,i,!!e.yes)});function Vp(e){let o=li();switch(e){case"zsh":return ft(o,".zsh","completions","_agentx");case"bash":return ft(o,".bash_completion.d","agentx.bash");case"fish":return ft(o,".config","fish","completions","agentx.fish");default:throw new Error(`unsupported shell: ${e}`)}}function Qp(e,o,t){if(e==="zsh"){let n=ft(li(),".zshrc"),s=Pc(o),i=`fpath=(${s} $fpath)`,r="autoload -U compinit && compinit",a=Gn(n)?Tc(n,"utf-8"):"",c=!a.includes(s),l=!/autoload\s+-U\s+compinit/.test(a);if(!c&&!l){console.log(Ee.dim("~/.zshrc already has fpath + compinit wired up. Run `exec zsh` to pick up the new script."));return}if(t&&Gn(n)){let d=["","# agentx completion"];c&&d.push(i),l&&d.push(r),Nc(n,d.join(`
|
|
540
540
|
`)+`
|
|
541
541
|
`),console.log(Ee.green("\u2713 Patched ~/.zshrc")),console.log(Ee.dim("Reload your shell: exec zsh"));return}console.log(Ee.dim("Add this to ~/.zshrc if not already present:")),c&&console.log(Ee.cyan(` ${i}`)),l&&console.log(Ee.cyan(` ${r}`)),console.log(),console.log(Ee.dim("Then reload: exec zsh")),console.log(Ee.dim("Or rerun with --yes to auto-patch ~/.zshrc"));return}if(e==="bash"){let n=ft(li(),".bashrc"),s=`[ -f "${o}" ] && source "${o}"`;if((Gn(n)?Tc(n,"utf-8"):"").includes(o)){console.log(Ee.dim("~/.bashrc already sources this file. Start a new shell to pick it up."));return}if(t&&Gn(n)){Nc(n,`
|
|
542
542
|
# agentx completion
|
|
@@ -547,4 +547,4 @@ ${s}
|
|
|
547
547
|
`)}function di(e){return String(e||"").replace(/\r?\n/g," ").replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function ci(e,o){let t=e.short?e.short.replace(/^-/,""):"",n=e.long?e.long.replace(/^--/,""):"";if(!t&&!n)return null;let s=di(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 Fv(){let e=await dr(),o=new ru().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=ur(n);hr(s)&&pr("cli",s)});for(let t of[Br,Fr,rt,Xo,Ke,mr,Co,hn,bo,Do,un,yc,yo,ta,ga,ka,Sa,Ea,Ia,Ft,vc,Ot,po,Lc])o.addCommand(t);for(let t of Uc)o.addCommand(t,{hidden:!0});return o.addHelpText("after",()=>{let t=Uc.map(n=>n.name()).sort();return["",`Advanced (${t.length}, hidden \u2014 run \`agentx <command> --help\` for any of them):`,au(t,74," "),""].join(`
|
|
548
548
|
`)}),o}var Uc=[Z,at,Fo,ze,Ct,nt,Le,ro,$o,Po,gt,mt,fo,De,jt,On,hc,so,et,br,jo,Yt,us,vo,Zo,hs,Un,pt,xo,Oc,Cc,kc];function au(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(`
|
|
549
549
|
`)}export{Fv as a};
|
|
550
|
-
//# sourceMappingURL=chunk-
|
|
550
|
+
//# sourceMappingURL=chunk-WZD3OS7T.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-WZD3OS7T.js";import"./chunk-4CR463C6.js";import"./chunk-G5MFPNGJ.js";import"./chunk-B2XTYYXV.js";import"./chunk-2TJ5L7CB.js";import"./chunk-7CVJ4JOE.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-SZDACK6O.js";import"./chunk-UEP7IRBD.js";import"./chunk-F6CNF7V3.js";import"./chunk-GWQIMAJ7.js";import"./chunk-V7FYSZSV.js";import"./chunk-ZVP6GB4G.js";import"./chunk-6VQKHMEQ.js";import"./chunk-5FEQI22L.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import"./chunk-A4YR3PQY.js";import"./chunk-K6E7WJ7O.js";import"./chunk-SFQUP3BP.js";import"./chunk-3SCPRYJB.js";import"./chunk-WPMX3VGI.js";import"./chunk-K33GIBSE.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-JWKIFAXA.js";import"./chunk-W3YGESNK.js";import"./chunk-DWADWDMU.js";import"./chunk-77OV7346.js";import"./chunk-VWTBHLMX.js";import"./chunk-MFVI5FOM.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-JGJE5Y2J.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import"./chunk-2DBGOCCW.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-AJONZWLT.js";import"./chunk-F4HZTZHW.js";import"./chunk-QOYAX2FT.js";import"./chunk-LCIREYTD.js";import"./chunk-L2WSPY6S.js";import"./chunk-VDMYBPYB.js";import"./chunk-DSYKYZMT.js";import"./chunk-2DMVKLLE.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.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as L}from"./chunk-W5C2GDNC.js";import{B as bt,C as Tt,D as Mt,a as St,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{B as bt,C as Tt,D as Mt,a as St,b as kt,c as vt,d as xt,e as $t,f as Ct,g as Pt}from"./chunk-UEP7IRBD.js";import"./chunk-F6CNF7V3.js";import"./chunk-GWQIMAJ7.js";import"./chunk-V7FYSZSV.js";import"./chunk-ZVP6GB4G.js";import{J as yt,h as lt,i as ct,j as dt,k as mt,l as pt}from"./chunk-6VQKHMEQ.js";import"./chunk-5FEQI22L.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import{h as ut}from"./chunk-A4YR3PQY.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-K6E7WJ7O.js";import{a as B,b as M,c as F}from"./chunk-SFQUP3BP.js";import"./chunk-3SCPRYJB.js";import"./chunk-WPMX3VGI.js";import"./chunk-K33GIBSE.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-JWKIFAXA.js";import"./chunk-W3YGESNK.js";import"./chunk-DWADWDMU.js";import"./chunk-77OV7346.js";import"./chunk-VWTBHLMX.js";import{a as gt,b as ft,e as ht}from"./chunk-MFVI5FOM.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-JGJE5Y2J.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import{j as it,k as rt,l as at}from"./chunk-2DBGOCCW.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-AJONZWLT.js";import"./chunk-F4HZTZHW.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{e as tt,g as st,h as ot,j as nt}from"./chunk-2DMVKLLE.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-WZD3OS7T.js";import"./chunk-4CR463C6.js";import"./chunk-G5MFPNGJ.js";import"./chunk-B2XTYYXV.js";import"./chunk-2TJ5L7CB.js";import"./chunk-7CVJ4JOE.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-SZDACK6O.js";import"./chunk-UEP7IRBD.js";import"./chunk-F6CNF7V3.js";import"./chunk-GWQIMAJ7.js";import"./chunk-V7FYSZSV.js";import"./chunk-ZVP6GB4G.js";import"./chunk-6VQKHMEQ.js";import"./chunk-5FEQI22L.js";import"./chunk-VMDA2SX2.js";import"./chunk-QLTM3F7M.js";import"./chunk-A4YR3PQY.js";import"./chunk-K6E7WJ7O.js";import"./chunk-SFQUP3BP.js";import"./chunk-3SCPRYJB.js";import"./chunk-WPMX3VGI.js";import"./chunk-K33GIBSE.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-JWKIFAXA.js";import"./chunk-W3YGESNK.js";import"./chunk-DWADWDMU.js";import"./chunk-77OV7346.js";import"./chunk-VWTBHLMX.js";import"./chunk-MFVI5FOM.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-JGJE5Y2J.js";import"./chunk-AJ5RMU7X.js";import"./chunk-2GIDVZ4H.js";import"./chunk-2DBGOCCW.js";import"./chunk-ZTEU5JVQ.js";import"./chunk-AJONZWLT.js";import"./chunk-F4HZTZHW.js";import"./chunk-QOYAX2FT.js";import"./chunk-LCIREYTD.js";import"./chunk-L2WSPY6S.js";import"./chunk-VDMYBPYB.js";import"./chunk-DSYKYZMT.js";import"./chunk-2DMVKLLE.js";import"./chunk-BH3GTCZ6.js";import"./chunk-FIOB3MEX.js";export{a as buildProgram};
|
|
2
|
+
//# sourceMappingURL=program-PK5R7GIC.js.map
|