agentix-cli 0.16.0 → 0.18.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/agent-RDVGL2TW.js +2 -0
- package/dist/audit-Z47AQFFD.js +3 -0
- package/dist/audit-Z47AQFFD.js.map +1 -0
- package/dist/board-dashboard-KX2CNOSY.js +7282 -0
- package/dist/board-dashboard-KX2CNOSY.js.map +1 -0
- package/dist/chunk-34NG7UDX.js +11 -0
- package/dist/chunk-34NG7UDX.js.map +1 -0
- package/dist/{chunk-6MKAXEE5.js → chunk-4ITQP3XL.js} +2 -2
- package/dist/{chunk-6MKAXEE5.js.map → chunk-4ITQP3XL.js.map} +1 -1
- package/dist/chunk-53NRX2NA.js +2 -0
- package/dist/chunk-53NRX2NA.js.map +1 -0
- package/dist/chunk-6PPIFDOQ.js +1742 -0
- package/dist/chunk-6PPIFDOQ.js.map +1 -0
- package/dist/chunk-AFRHKA7B.js +2 -0
- package/dist/chunk-AFRHKA7B.js.map +1 -0
- package/dist/chunk-ASSJ4Z6Z.js +164 -0
- package/dist/chunk-ASSJ4Z6Z.js.map +1 -0
- package/dist/chunk-BLUXL6HR.js +854 -0
- package/dist/chunk-BLUXL6HR.js.map +1 -0
- package/dist/chunk-BTAEYL3P.js +72 -0
- package/dist/chunk-BTAEYL3P.js.map +1 -0
- package/dist/chunk-CDNWCYF7.js +2 -0
- package/dist/chunk-CDNWCYF7.js.map +1 -0
- package/dist/chunk-DJEZ2HVU.js +5 -0
- package/dist/chunk-DJEZ2HVU.js.map +1 -0
- package/dist/{chunk-FLOGK2U7.js → chunk-DSCMCVTV.js} +3 -3
- package/dist/chunk-DSCMCVTV.js.map +1 -0
- package/dist/chunk-EW27SCCC.js +2 -0
- package/dist/chunk-EW27SCCC.js.map +1 -0
- package/dist/chunk-HPDHNIA3.js +2 -0
- package/dist/chunk-IM376SD6.js +13 -0
- package/dist/chunk-IM376SD6.js.map +1 -0
- package/dist/chunk-J4WKMKTP.js +5 -0
- package/dist/{chunk-YI2T5QYB.js.map → chunk-J4WKMKTP.js.map} +1 -1
- package/dist/chunk-JGXE2YNV.js +46 -0
- package/dist/chunk-JGXE2YNV.js.map +1 -0
- package/dist/chunk-JXEPJ3YD.js +118 -0
- package/dist/chunk-JXEPJ3YD.js.map +1 -0
- package/dist/chunk-LY7JGDV7.js +6 -0
- package/dist/chunk-LY7JGDV7.js.map +1 -0
- package/dist/chunk-N67JZAXU.js +2 -0
- package/dist/chunk-N67JZAXU.js.map +1 -0
- package/dist/chunk-SR3X25TN.js +3 -0
- package/dist/chunk-SR3X25TN.js.map +1 -0
- package/dist/{chunk-7MBTMCKY.js → chunk-TRQSP67X.js} +2 -2
- package/dist/chunk-U364GNQX.js +719 -0
- package/dist/chunk-U364GNQX.js.map +1 -0
- package/dist/chunk-VJUTQAPJ.js +2 -0
- package/dist/chunk-VJUTQAPJ.js.map +1 -0
- package/dist/{chunk-HI24KAEY.js → chunk-WJXU5F4Z.js} +3 -4
- package/dist/{chunk-HI24KAEY.js.map → chunk-WJXU5F4Z.js.map} +1 -1
- package/dist/{chunk-QZP65I2H.js → chunk-ZE2YFX4K.js} +2 -2
- package/dist/cli.js +1 -320
- package/dist/cli.js.map +1 -1
- package/dist/{compaction-JBZZ7I7Y.js → compaction-S5H6DTOR.js} +6 -6
- package/dist/compaction-S5H6DTOR.js.map +1 -0
- package/dist/config-UOHEG4BW.js +2 -0
- package/dist/config-mutator-KSEBWKJH.js +2 -0
- package/dist/context-planner-2RGHJHSO.js +17 -0
- package/dist/context-planner-2RGHJHSO.js.map +1 -0
- package/dist/debug-TGAP7E7W.js +2 -0
- package/dist/discover-OATU7SHI.js +4 -0
- package/dist/discover-OATU7SHI.js.map +1 -0
- package/dist/editor-chat-FUBQLMAQ.js +137 -0
- package/dist/editor-chat-FUBQLMAQ.js.map +1 -0
- package/dist/heal-YP7QI7D3.js +2 -0
- package/dist/inbox-O5UB3YQN.js +315 -0
- package/dist/inbox-O5UB3YQN.js.map +1 -0
- package/dist/index.d.ts +3390 -1814
- package/dist/index.js +23 -53
- package/dist/index.js.map +1 -1
- package/dist/ingest-whatsapp-C3O5UPBX.js +6 -0
- package/dist/ingest-whatsapp-C3O5UPBX.js.map +1 -0
- package/dist/loader-BGWA7IRY.js +2 -0
- package/dist/loader-LBHKSXBK.js +2 -0
- package/dist/memory-extract-KKPKAOPH.js +2 -0
- package/dist/processes-7W27G3J3.js +256 -0
- package/dist/processes-7W27G3J3.js.map +1 -0
- package/dist/program-2MDELQLX.js +2 -0
- package/dist/providers-WCQSKTNP.js +2 -0
- package/dist/query-FZAL7AQD.js +2 -0
- package/dist/recipes-LZ56TA3X.js +2 -0
- package/dist/registry-ONJSILH4.js +2 -0
- package/dist/scheduler-XRM2RJIV.js +2 -0
- package/dist/slack-D27BE37Q.js +3 -0
- package/dist/slack-D27BE37Q.js.map +1 -0
- package/dist/store-4UCO56K2.js +2 -0
- package/dist/store-4UCO56K2.js.map +1 -0
- package/dist/{subagent-2SJHSSJS.js → subagent-EPOT3QDM.js} +2 -2
- package/dist/task-store-3NUWLYRY.js +2 -0
- package/dist/task-store-3NUWLYRY.js.map +1 -0
- package/dist/telegram-UWV67KWG.js +3 -0
- package/dist/telegram-UWV67KWG.js.map +1 -0
- package/dist/timers-QB4KYNAE.js +2 -0
- package/dist/timers-QB4KYNAE.js.map +1 -0
- package/dist/types-ECMEC5BZ.js +2 -0
- package/dist/types-ECMEC5BZ.js.map +1 -0
- package/dist/types-TTB6DJUE.js +2 -0
- package/dist/types-TTB6DJUE.js.map +1 -0
- package/dist/usage-dashboard-FQGPPABD.js +803 -0
- package/dist/usage-dashboard-FQGPPABD.js.map +1 -0
- package/dist/web/workflow-editor.global.js +1450 -0
- package/dist/web/workflow-editor.global.js.map +1 -0
- package/dist/whatsapp-KJ2NRKKQ.js +3 -0
- package/dist/whatsapp-KJ2NRKKQ.js.map +1 -0
- package/dist/{whatsapp-state-6D6FHHD2.js → whatsapp-state-3ZVQ6MQD.js} +2 -2
- package/dist/{wiki-UDPYFJBL.js → wiki-OUYKM7MB.js} +2 -2
- package/dist/wiki-OUYKM7MB.js.map +1 -0
- package/dist/workspace-setup-6GDBEORT.js +2 -0
- package/dist/workspace-setup-6GDBEORT.js.map +1 -0
- package/package.json +19 -2
- package/dist/agent-BCDPSPKU.js +0 -2
- package/dist/board-dashboard-LA7WW56M.js +0 -5668
- package/dist/board-dashboard-LA7WW56M.js.map +0 -1
- package/dist/chunk-6U2XOQHU.js +0 -7
- package/dist/chunk-6U2XOQHU.js.map +0 -1
- package/dist/chunk-7FJQGD6U.js +0 -6
- package/dist/chunk-7FJQGD6U.js.map +0 -1
- package/dist/chunk-ABDP7TDL.js +0 -71
- package/dist/chunk-ABDP7TDL.js.map +0 -1
- package/dist/chunk-CXY2RYNI.js +0 -11
- package/dist/chunk-CXY2RYNI.js.map +0 -1
- package/dist/chunk-FIOB3MEX.js +0 -2
- package/dist/chunk-FLOGK2U7.js.map +0 -1
- package/dist/chunk-HVC6FJNP.js +0 -108
- package/dist/chunk-HVC6FJNP.js.map +0 -1
- package/dist/chunk-K7BE4E35.js +0 -138
- package/dist/chunk-K7BE4E35.js.map +0 -1
- package/dist/chunk-KXJSLLSQ.js +0 -199
- package/dist/chunk-KXJSLLSQ.js.map +0 -1
- package/dist/chunk-KXZMYLHQ.js +0 -46
- package/dist/chunk-KXZMYLHQ.js.map +0 -1
- package/dist/chunk-M7HKBG3V.js +0 -2
- package/dist/chunk-M7HKBG3V.js.map +0 -1
- package/dist/chunk-MCJUAE6V.js +0 -6
- package/dist/chunk-MCJUAE6V.js.map +0 -1
- package/dist/chunk-RB7265LO.js +0 -12
- package/dist/chunk-RB7265LO.js.map +0 -1
- package/dist/chunk-YI2T5QYB.js +0 -5
- package/dist/compaction-JBZZ7I7Y.js.map +0 -1
- package/dist/config-LN6JEHMF.js +0 -2
- package/dist/config-mutator-24TH7PHM.js +0 -2
- package/dist/debug-3MEUO2P2.js +0 -2
- package/dist/heal-WKY5I4KB.js +0 -2
- package/dist/loader-PTCXLJEX.js +0 -2
- package/dist/memory-extract-AD7KMRPC.js +0 -2
- package/dist/providers-VUIWO3ZK.js +0 -2
- package/dist/query-PKGYE5HR.js +0 -2
- package/dist/registry-ASC2QS5K.js +0 -2
- package/dist/scheduler-A3TQOCKT.js +0 -2
- package/dist/types-OIFU3KSQ.js +0 -2
- package/dist/usage-dashboard-QX3CF6KK.js +0 -404
- package/dist/usage-dashboard-QX3CF6KK.js.map +0 -1
- package/dist/workspace-setup-ZWTT42XT.js +0 -2
- /package/dist/{agent-BCDPSPKU.js.map → agent-RDVGL2TW.js.map} +0 -0
- /package/dist/{chunk-FIOB3MEX.js.map → chunk-HPDHNIA3.js.map} +0 -0
- /package/dist/{chunk-7MBTMCKY.js.map → chunk-TRQSP67X.js.map} +0 -0
- /package/dist/{chunk-QZP65I2H.js.map → chunk-ZE2YFX4K.js.map} +0 -0
- /package/dist/{config-LN6JEHMF.js.map → config-UOHEG4BW.js.map} +0 -0
- /package/dist/{config-mutator-24TH7PHM.js.map → config-mutator-KSEBWKJH.js.map} +0 -0
- /package/dist/{debug-3MEUO2P2.js.map → debug-TGAP7E7W.js.map} +0 -0
- /package/dist/{heal-WKY5I4KB.js.map → heal-YP7QI7D3.js.map} +0 -0
- /package/dist/{loader-PTCXLJEX.js.map → loader-BGWA7IRY.js.map} +0 -0
- /package/dist/{memory-extract-AD7KMRPC.js.map → loader-LBHKSXBK.js.map} +0 -0
- /package/dist/{providers-VUIWO3ZK.js.map → memory-extract-KKPKAOPH.js.map} +0 -0
- /package/dist/{query-PKGYE5HR.js.map → program-2MDELQLX.js.map} +0 -0
- /package/dist/{registry-ASC2QS5K.js.map → providers-WCQSKTNP.js.map} +0 -0
- /package/dist/{scheduler-A3TQOCKT.js.map → query-FZAL7AQD.js.map} +0 -0
- /package/dist/{types-OIFU3KSQ.js.map → recipes-LZ56TA3X.js.map} +0 -0
- /package/dist/{wiki-UDPYFJBL.js.map → registry-ONJSILH4.js.map} +0 -0
- /package/dist/{workspace-setup-ZWTT42XT.js.map → scheduler-XRM2RJIV.js.map} +0 -0
- /package/dist/{subagent-2SJHSSJS.js.map → subagent-EPOT3QDM.js.map} +0 -0
- /package/dist/{whatsapp-state-6D6FHHD2.js.map → whatsapp-state-3ZVQ6MQD.js.map} +0 -0
package/dist/chunk-KXJSLLSQ.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import{f as b,i as $}from"./chunk-7FJQGD6U.js";import{existsSync as g,readFileSync as S,writeFileSync as T,appendFileSync as R,mkdirSync as W}from"fs";import{resolve as c}from"path";import{hostname as j}from"os";$();import{existsSync as v,readFileSync as x,writeFileSync as h,copyFileSync as B}from"fs";import{resolve as y}from"path";function w(e,t={}){let n=t.configPath||y(process.cwd(),"agentx.json");if(!v(n))throw new Error(`agentx.json not found at ${n}`);let a=JSON.parse(x(n,"utf-8")),r=e(a),i=typeof r=="string"?{summary:r}:r,s=JSON.stringify(a,null,2)+`
|
|
2
|
-
`,d=n+".tmp";h(d,s,"utf-8");try{JSON.parse(x(d,"utf-8"))}catch(u){throw new Error(`config did not round-trip cleanly: ${u.message}`)}let l;return t.skipBackup||(l=`${n}.bak.${Date.now()}`,B(n,l)),h(n,s,"utf-8"),t.skipReload||_().catch(()=>{}),{summary:i.summary,payload:i.payload,backupPath:l}}function k(e,t={}){let n=t.configPath||y(process.cwd(),"agentx.json");if(v(n)&&!t.overwrite)throw new Error(`agentx.json already exists at ${n}. Pass overwrite=true to replace it.`);return h(n,JSON.stringify(e,null,2)+`
|
|
3
|
-
`,"utf-8"),{file:n}}async function _(){try{let t=b().dashboard.daemonUrl?.replace(/\/+$/,"")||"http://127.0.0.1:18800";await fetch(`${t}/reload`,{method:"POST"}).catch(()=>null)}catch{}}function C(e=process.cwd()){let t=c(e,"agentx.json");if(!g(t))return{configExists:!1,agentCount:0,channelCount:0};try{let n=JSON.parse(S(t,"utf-8")),a=n.agents?Object.keys(n.agents).length:0,r=n.channels?Object.values(n.channels).filter(i=>i&&i.enabled).length:0;return{configExists:!0,agentCount:a,channelCount:r,nodeName:n.node?.name}}catch{return{configExists:!1,agentCount:0,channelCount:0}}}function F(e,t=process.cwd()){if(!e.nodeName?.trim())throw new Error("Team name is required.");if(!e.agent?.id?.trim())throw new Error("Agent id is required.");if(!/^[a-z0-9][a-z0-9_-]*$/.test(e.agent.id))throw new Error("Agent id must be lowercase (letters, digits, -, _) and start with a letter or digit.");if(!e.agent.name?.trim())throw new Error("Agent name is required.");let n=D(e.agent.triggerWords);if(n.length===0)throw new Error("At least one trigger word is required.");if(e.agent.tier!=="claude-code"&&e.agent.tier!=="sdk")throw new Error("AI engine must be claude-code or sdk.");let a=c(t,"agentx.json"),r=c(t,".env"),i=c(t,"agents",e.agent.id),s=C(t);W(i,{recursive:!0});let d=c(i,"CLAUDE.md");if(!g(d)){let m=e.agent.personality?.trim()||`You are ${e.agent.name}, an assistant on the ${e.nodeName} team.`;T(d,`# ${e.agent.name}
|
|
4
|
-
|
|
5
|
-
${m}
|
|
6
|
-
`)}let l=e.telegram?`TG_${e.agent.id.toUpperCase()}_BOT_TOKEN`:void 0,u;if(s.configExists)u=w(o=>{if(o.node=o.node||{},o.node.name||(o.node.name=e.nodeName),o.node.id||(o.node.id=E(e.nodeName)||"team"),o.node.bind||(o.node.bind="127.0.0.1:18800"),o.node.defaultAgent=o.node.defaultAgent||e.agent.id,o.providers=o.providers||{},o.providers.claude||(o.providers.claude={apiKey:"${ANTHROPIC_API_KEY}"}),o.agents=o.agents||{},o.agents[e.agent.id])throw new Error(`Agent "${e.agent.id}" already exists.`);return o.agents[e.agent.id]=I(e,i,n),e.telegram&&(o.channels=o.channels||{},o.channels.telegram=o.channels.telegram||{enabled:!0,accounts:{},policy:{dm:"pair",group:"mention-required"}},o.channels.telegram.enabled=!0,o.channels.telegram.accounts=o.channels.telegram.accounts||{},o.channels.telegram.accounts[e.telegram.accountId]=z(e,l)),{summary:`added agent "${e.agent.id}"`+(e.telegram?" + telegram account":"")}},{configPath:a}).backupPath;else{let m=U(e,i,n,l);k(m,{configPath:a})}H(r,e,l);let p=[];return(e.anthropicApiKey||!g(c(t,".env")))&&p.push("Double-check the API keys in .env"),e.agent.tier==="claude-code"&&p.push("Run claude --version to confirm Claude Code is installed (needed for the claude-code engine)"),p.push("Start the daemon: agentx daemon start"),p.push("Open the dashboard: http://127.0.0.1:4202"),{summary:s.configExists?`Added agent "${e.agent.id}" to your team.`:`Initialized your team with first agent "${e.agent.id}".`,nextSteps:p,backupPath:u}}function D(e){return(e||"").split(/[,\s]+/).map(t=>t.trim()).filter(Boolean).filter((t,n,a)=>a.indexOf(t)===n)}function E(e){return(e||"").toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"")}function U(e,t,n,a){let i={node:{id:E(e.nodeName)||"team",name:e.nodeName,bind:"127.0.0.1:18800",defaultAgent:e.agent.id},providers:{claude:{apiKey:"${ANTHROPIC_API_KEY}"}},agents:{[e.agent.id]:I(e,t,n)},channels:{},crons:{},mesh:{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},dashboard:{enabled:!0,port:4202,bind:"127.0.0.1",daemonUrl:"http://localhost:18800"},boards:[]};return e.telegram&&a?i.channels.telegram={enabled:!0,accounts:{[e.telegram.accountId]:z(e,a)},policy:{dm:"pair",group:"mention-required"}}:i.channels.telegram={enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},i}function I(e,t,n){let a={name:e.agent.name,workspace:t,tier:e.agent.tier,mentions:n,maxConcurrent:2,permissionMode:"default"};return e.agent.model&&(a.model=e.agent.model),e.agent.personality?.trim()&&(a.systemPrompt=e.agent.personality.trim().slice(0,400)),a}function z(e,t){return{botToken:"${"+t+"}",botUsername:e.telegram?.botUsername||"",agentBinding:e.agent.id}}function H(e,t,n){let a=g(e)?S(e,"utf-8"):"",r=[];if(t.anthropicApiKey&&!a.includes("ANTHROPIC_API_KEY=")&&r.push(`ANTHROPIC_API_KEY=${t.anthropicApiKey}`),t.telegram&&n&&!a.includes(`${n}=`)&&r.push(`${n}=${t.telegram.botToken}`),!g(e)){T(e,[...["# AgentX environment variables","# (Never commit this file \u2014 it contains secrets.)",""],...r,""].join(`
|
|
7
|
-
`));return}if(r.length>0){let i=a.endsWith(`
|
|
8
|
-
`)?"":`
|
|
9
|
-
`;R(e,i+r.join(`
|
|
10
|
-
`)+`
|
|
11
|
-
`)}}function se(e,t){let n=C(),a=K(n);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(a)}async function de(e,t){let n="";await new Promise(r=>{e.on("data",i=>{n+=i}),e.on("end",()=>r())});let a;try{a=JSON.parse(n)}catch{t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid JSON"}));return}try{let r=F(a);t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify(r))}catch(r){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:r.message||"wizard failed"}))}}function K(e){let t=e.configExists?e.agentCount===0?"Add your first agent":"Add another agent":"Set up your team",n=e.nodeName||j().replace(/\.local$/,"");return`<!DOCTYPE html>
|
|
12
|
-
<html lang="en">
|
|
13
|
-
<head>
|
|
14
|
-
<meta charset="utf-8">
|
|
15
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
16
|
-
<title>AgentX \u2014 Setup</title>
|
|
17
|
-
<style>
|
|
18
|
-
:root{--bg:#0b0d14;--card:#151823;--border:#2a2d3a;--text:#e6e8ef;--muted:#8b8fa3;--accent:#6366f1;--green:#22c55e;--red:#ef4444}
|
|
19
|
-
*{box-sizing:border-box}
|
|
20
|
-
html,body{margin:0;min-height:100%;background:var(--bg);color:var(--text);font:14px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
|
|
21
|
-
header{padding:18px 24px;border-bottom:1px solid var(--border);background:#10131c;display:flex;align-items:center;gap:12px}
|
|
22
|
-
header .brand{font-weight:600;color:var(--accent);font-size:15px}
|
|
23
|
-
header .sub{color:var(--muted);font-weight:500}
|
|
24
|
-
.spacer{flex:1}
|
|
25
|
-
a.link{color:var(--muted);text-decoration:none;font-size:13px;padding:4px 10px;border:1px solid var(--border);border-radius:6px}
|
|
26
|
-
a.link:hover{color:var(--accent);border-color:var(--accent)}
|
|
27
|
-
main{max-width:620px;margin:0 auto;padding:32px 22px 60px}
|
|
28
|
-
h1{font-size:24px;margin:0 0 6px}
|
|
29
|
-
.lead{color:var(--muted);margin:0 0 26px}
|
|
30
|
-
section.step{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:20px 22px;margin:14px 0}
|
|
31
|
-
section.step h2{font-size:14px;font-weight:600;margin:0 0 14px;color:var(--text);display:flex;align-items:center;gap:10px}
|
|
32
|
-
section.step h2 .num{background:var(--accent);color:#fff;width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:700}
|
|
33
|
-
label{display:block;margin:10px 0 4px;font-size:12px;color:var(--muted)}
|
|
34
|
-
label .hint{color:var(--muted);font-weight:400;font-size:11px;margin-left:6px}
|
|
35
|
-
input,textarea,select{width:100%;background:#0e1119;color:var(--text);border:1px solid var(--border);border-radius:6px;padding:8px 10px;font:13px/1.4 inherit}
|
|
36
|
-
input:focus,textarea:focus,select:focus{outline:none;border-color:var(--accent)}
|
|
37
|
-
textarea{resize:vertical;min-height:70px;font-family:inherit}
|
|
38
|
-
.row{display:flex;gap:10px}
|
|
39
|
-
.row > *{flex:1}
|
|
40
|
-
.toggle{display:flex;align-items:center;gap:8px;margin:14px 0 4px;font-size:13px;color:var(--text);cursor:pointer}
|
|
41
|
-
.toggle input{width:auto}
|
|
42
|
-
.optional{border-left:2px solid var(--border);padding-left:14px;margin-top:10px;display:none}
|
|
43
|
-
.optional.show{display:block}
|
|
44
|
-
footer.actions{display:flex;gap:10px;padding:20px 0;align-items:center}
|
|
45
|
-
button.primary{background:var(--accent);color:#fff;border:none;border-radius:6px;padding:10px 20px;font-size:14px;font-weight:600;cursor:pointer}
|
|
46
|
-
button.primary:hover{filter:brightness(1.1)}
|
|
47
|
-
button.primary:disabled{opacity:0.5;cursor:not-allowed}
|
|
48
|
-
button.ghost{background:transparent;color:var(--muted);border:1px solid var(--border);border-radius:6px;padding:9px 16px;cursor:pointer}
|
|
49
|
-
.hint-block{font-size:11px;color:var(--muted);margin-top:6px;line-height:1.55}
|
|
50
|
-
.hint-block code{background:#10131c;padding:1px 6px;border-radius:3px;color:var(--text);font-family:ui-monospace,monospace;font-size:11px}
|
|
51
|
-
#msg{margin:14px 0;padding:12px 16px;border-radius:6px;font-size:13px;display:none}
|
|
52
|
-
#msg.ok{display:block;background:rgba(34,197,94,0.12);color:var(--green);border:1px solid rgba(34,197,94,0.3)}
|
|
53
|
-
#msg.err{display:block;background:rgba(239,68,68,0.12);color:var(--red);border:1px solid rgba(239,68,68,0.3)}
|
|
54
|
-
#next-steps{margin-top:12px;padding-left:20px}
|
|
55
|
-
#next-steps li{margin:4px 0}
|
|
56
|
-
#next-steps code{background:#10131c;padding:1px 6px;border-radius:3px;color:var(--text);font-family:ui-monospace,monospace;font-size:12px}
|
|
57
|
-
.config-banner{background:rgba(99,102,241,0.12);border:1px solid rgba(99,102,241,0.3);border-radius:6px;padding:10px 14px;margin-bottom:16px;color:var(--muted);font-size:12px}
|
|
58
|
-
.config-banner b{color:var(--text)}
|
|
59
|
-
</style>
|
|
60
|
-
</head>
|
|
61
|
-
<body>
|
|
62
|
-
<header>
|
|
63
|
-
<div class="brand">AgentX <span class="sub">\xB7 Setup</span></div>
|
|
64
|
-
<div class="spacer"></div>
|
|
65
|
-
<a href="/glossary" class="link">? Glossary</a>
|
|
66
|
-
<a href="/live" class="link">Skip \u2014 open dashboard</a>
|
|
67
|
-
</header>
|
|
68
|
-
<main>
|
|
69
|
-
<h1>${A(t)}</h1>
|
|
70
|
-
<p class="lead">Fill in the basics below. We'll write <code>agentx.json</code>, set up a folder for your first agent, and point you at the next step.</p>
|
|
71
|
-
|
|
72
|
-
${e.configExists?`<div class="config-banner">Existing install: <b>${e.agentCount}</b> agent(s), <b>${e.channelCount}</b> channel(s) already configured. This wizard will add to it.</div>`:""}
|
|
73
|
-
|
|
74
|
-
<div id="msg"></div>
|
|
75
|
-
|
|
76
|
-
<form id="wizard" autocomplete="off">
|
|
77
|
-
<section class="step">
|
|
78
|
-
<h2><span class="num">1</span>Team basics</h2>
|
|
79
|
-
<label>Team name<span class="hint">(what you'd call this AgentX install)</span></label>
|
|
80
|
-
<input name="nodeName" value="${A(n)}" placeholder="My Team" required />
|
|
81
|
-
</section>
|
|
82
|
-
|
|
83
|
-
<section class="step">
|
|
84
|
-
<h2><span class="num">2</span>First agent</h2>
|
|
85
|
-
<div class="row">
|
|
86
|
-
<div>
|
|
87
|
-
<label>Agent name</label>
|
|
88
|
-
<input name="agentName" value="Assistant" placeholder="Support Bot" required />
|
|
89
|
-
</div>
|
|
90
|
-
<div>
|
|
91
|
-
<label>Agent id<span class="hint">(lowercase, no spaces)</span></label>
|
|
92
|
-
<input name="agentId" value="assistant" pattern="[a-z0-9][a-z0-9_-]*" required />
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
<label>Trigger words<span class="hint">(words that activate this agent \u2014 comma or space separated, e.g. <code>@support, support</code>)</span></label>
|
|
96
|
-
<input name="triggerWords" value="@assistant, assistant" required />
|
|
97
|
-
<div class="row">
|
|
98
|
-
<div>
|
|
99
|
-
<label>AI engine</label>
|
|
100
|
-
<select name="tier">
|
|
101
|
-
<option value="claude-code">Claude Code (recommended)</option>
|
|
102
|
-
<option value="sdk">Anthropic API (BYO key)</option>
|
|
103
|
-
</select>
|
|
104
|
-
</div>
|
|
105
|
-
<div>
|
|
106
|
-
<label>Model<span class="hint">(optional)</span></label>
|
|
107
|
-
<input name="model" value="claude-sonnet-4-6" placeholder="claude-sonnet-4-6" />
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
<label>Personality / instructions<span class="hint">(optional \u2014 what this agent does, in plain English)</span></label>
|
|
111
|
-
<textarea name="personality" placeholder="You are a support agent for Acme Co. Answer customer questions about our product, be friendly, keep replies short."></textarea>
|
|
112
|
-
</section>
|
|
113
|
-
|
|
114
|
-
<section class="step">
|
|
115
|
-
<h2><span class="num">3</span>First channel</h2>
|
|
116
|
-
<label class="toggle"><input type="checkbox" id="enableTelegram" /> Connect Telegram now</label>
|
|
117
|
-
<div class="optional" id="telegramFields">
|
|
118
|
-
<label>Account id<span class="hint">(a label you choose \u2014 e.g. <code>support</code>)</span></label>
|
|
119
|
-
<input name="telegramAccountId" value="default" />
|
|
120
|
-
<label>Bot token<span class="hint">(from <a href="https://t.me/BotFather" target="_blank" style="color:var(--accent)">@BotFather</a>)</span></label>
|
|
121
|
-
<input name="telegramBotToken" placeholder="123456:ABCdef..." />
|
|
122
|
-
<label>Bot username<span class="hint">(optional \u2014 e.g. <code>my_support_bot</code>)</span></label>
|
|
123
|
-
<input name="telegramBotUsername" placeholder="my_support_bot" />
|
|
124
|
-
</div>
|
|
125
|
-
</section>
|
|
126
|
-
|
|
127
|
-
<section class="step">
|
|
128
|
-
<h2><span class="num">4</span>Anthropic API key</h2>
|
|
129
|
-
<label>API key<span class="hint">(optional if you'll paste it into <code>.env</code> manually, or if you're only using Claude Code)</span></label>
|
|
130
|
-
<input name="anthropicApiKey" type="password" placeholder="sk-ant-\u2026" autocomplete="off" />
|
|
131
|
-
<div class="hint-block">
|
|
132
|
-
The key is written to <code>.env</code> as <code>ANTHROPIC_API_KEY</code>. AgentX never transmits it \u2014 everything stays on this machine.
|
|
133
|
-
</div>
|
|
134
|
-
</section>
|
|
135
|
-
|
|
136
|
-
<footer class="actions">
|
|
137
|
-
<button type="submit" class="primary" id="submitBtn">Save and continue</button>
|
|
138
|
-
<button type="button" class="ghost" onclick="window.location.href='/live'">Skip, I'll do it later</button>
|
|
139
|
-
</footer>
|
|
140
|
-
</form>
|
|
141
|
-
</main>
|
|
142
|
-
<script>
|
|
143
|
-
document.getElementById('enableTelegram').addEventListener('change', (e) => {
|
|
144
|
-
document.getElementById('telegramFields').classList.toggle('show', e.target.checked);
|
|
145
|
-
});
|
|
146
|
-
document.getElementById('wizard').addEventListener('submit', async (e) => {
|
|
147
|
-
e.preventDefault();
|
|
148
|
-
const f = e.target;
|
|
149
|
-
const msg = document.getElementById('msg');
|
|
150
|
-
const btn = document.getElementById('submitBtn');
|
|
151
|
-
msg.className = ''; msg.style.display = 'none';
|
|
152
|
-
btn.disabled = true; btn.textContent = 'Saving\u2026';
|
|
153
|
-
const telegramEnabled = document.getElementById('enableTelegram').checked;
|
|
154
|
-
const payload = {
|
|
155
|
-
nodeName: f.nodeName.value.trim(),
|
|
156
|
-
agent: {
|
|
157
|
-
id: f.agentId.value.trim(),
|
|
158
|
-
name: f.agentName.value.trim(),
|
|
159
|
-
triggerWords: f.triggerWords.value.trim(),
|
|
160
|
-
tier: f.tier.value,
|
|
161
|
-
model: f.model.value.trim() || undefined,
|
|
162
|
-
personality: f.personality.value.trim() || undefined,
|
|
163
|
-
},
|
|
164
|
-
anthropicApiKey: f.anthropicApiKey.value.trim() || undefined,
|
|
165
|
-
};
|
|
166
|
-
if (telegramEnabled) {
|
|
167
|
-
payload.telegram = {
|
|
168
|
-
accountId: f.telegramAccountId.value.trim() || 'default',
|
|
169
|
-
botToken: f.telegramBotToken.value.trim(),
|
|
170
|
-
botUsername: f.telegramBotUsername.value.trim() || undefined,
|
|
171
|
-
};
|
|
172
|
-
if (!payload.telegram.botToken) {
|
|
173
|
-
msg.className = 'err'; msg.textContent = 'Bot token is required when Telegram is enabled.';
|
|
174
|
-
btn.disabled = false; btn.textContent = 'Save and continue'; return;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
try {
|
|
178
|
-
const r = await fetch('/api/setup', {
|
|
179
|
-
method: 'POST',
|
|
180
|
-
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'agentx-wizard' },
|
|
181
|
-
body: JSON.stringify(payload),
|
|
182
|
-
});
|
|
183
|
-
const data = await r.json();
|
|
184
|
-
if (!r.ok) throw new Error(data.error || ('HTTP ' + r.status));
|
|
185
|
-
const steps = data.nextSteps.map((s) => '<li>' + s.replace(/\`([^\`]+)\`/g, '<code>$1</code>') + '</li>').join('');
|
|
186
|
-
msg.className = 'ok';
|
|
187
|
-
msg.innerHTML = '<b>' + data.summary + '</b><ol id="next-steps">' + steps + '</ol>';
|
|
188
|
-
btn.textContent = 'Done';
|
|
189
|
-
btn.disabled = true;
|
|
190
|
-
} catch (err) {
|
|
191
|
-
msg.className = 'err'; msg.textContent = err.message;
|
|
192
|
-
btn.disabled = false; btn.textContent = 'Save and continue';
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
</script>
|
|
196
|
-
</body>
|
|
197
|
-
</html>`}function A(e){return String(e||"").replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}import{createHash as M,randomBytes as N}from"crypto";import{existsSync as q,mkdirSync as J,readFileSync as L,writeFileSync as Y}from"fs";import{resolve as X,dirname as G}from"path";var f="agx_live_",V=".agentx/tokens.json",P=class{file;constructor(t=process.cwd(),n=V){this.file=X(t,n)}load(){if(!q(this.file))return[];try{return JSON.parse(L(this.file,"utf-8"))}catch{return[]}}save(t){J(G(this.file),{recursive:!0}),Y(this.file,JSON.stringify(t,null,2)+`
|
|
198
|
-
`,"utf-8")}create(t){if(!t.name?.trim())throw new Error("Token name is required.");if(!Array.isArray(t.scopes)||t.scopes.length===0)throw new Error("At least one scope is required.");for(let s of t.scopes)if(!Q(s))throw new Error(`Invalid scope: ${s}`);let n=N(32).toString("hex"),a=f+n,r={id:"tok_"+N(4).toString("hex"),name:t.name.trim(),prefix:f+n.slice(0,4),hash:O(a),scopes:[...t.scopes],createdAt:new Date().toISOString(),expiresAt:t.expiresInDays?new Date(Date.now()+t.expiresInDays*86400*1e3).toISOString():void 0},i=this.load();return i.push(r),this.save(i),{token:a,record:r}}list(){return this.load()}revoke(t){let n=this.load(),a=n.find(r=>r.id===t);return a?(a.revokedAt=new Date().toISOString(),this.save(n),a):null}verify(t){if(!t||!t.startsWith(f))return null;let n=O(t),a=this.load(),r=a.find(d=>d.hash===n);if(!r||r.revokedAt||r.expiresAt&&Date.parse(r.expiresAt)<Date.now())return null;let i=Date.now(),s=r.lastUsedAt?Date.parse(r.lastUsedAt):0;if(i-s>6e4){r.lastUsedAt=new Date(i).toISOString();try{this.save(a)}catch{}}return r}};function ue(e,t){return!!(e.scopes.includes(t)||t.startsWith("agent:")&&e.scopes.includes("agent:*")||t==="dashboard:read"&&e.scopes.includes("dashboard:write"))}function Q(e){return e==="dashboard:read"||e==="dashboard:write"||e==="agent:*"||/^agent:[a-z0-9][a-z0-9_-]*$/.test(e)||e==="mesh:peer"}function O(e){return"sha256:"+M("sha256").update(e).digest("hex")}function me(e){let t=e.headers.authorization,n=Array.isArray(t)?t[0]:t;if(n&&n.toLowerCase().startsWith("bearer "))return n.slice(7).trim();if(e.url)try{let r=new URL(e.url,"http://localhost").searchParams.get("token");if(r)return r}catch{}return null}export{w as a,C as b,se as c,de as d,P as e,ue as f,me as g};
|
|
199
|
-
//# sourceMappingURL=chunk-KXJSLLSQ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/daemon/setup-wizard.ts","../src/daemon/config-mutate.ts","../src/daemon/token-store.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from \"fs\"\nimport { resolve } from \"path\"\nimport { hostname } from \"os\"\nimport type { IncomingMessage, ServerResponse } from \"http\"\nimport { mutateAgentxConfig, writeAgentxConfig } from \"./config-mutate\"\n\n// --- /setup wizard: form-driven first-run experience for non-technical operators ---\n//\n// This is the web equivalent of `agentx init` + `agentx agent add` + `agentx\n// channel add`, collapsed into one page. It writes agentx.json and scaffolds\n// the first agent's workspace so a business operator can go from a blank\n// machine to a working AgentX install without editing JSON.\n//\n// The route lives on the board-dashboard server (port 4202) because that's the\n// surface operators actually open. It talks to the loopback daemon for the\n// post-install restart; the wizard itself never requires a running daemon.\n\nexport interface WizardPayload {\n nodeName: string\n agent: {\n id: string\n name: string\n triggerWords: string // comma/space separated; we normalise on the server\n tier: \"claude-code\" | \"sdk\"\n model?: string\n personality?: string // short free text → CLAUDE.md\n }\n telegram?: {\n accountId: string\n botToken: string\n botUsername?: string\n }\n anthropicApiKey?: string\n}\n\n/**\n * Return the current state of the working directory so the wizard can choose\n * between \"fresh install\" and \"add another\" flows.\n */\nexport function wizardState(baseDir: string = process.cwd()): {\n configExists: boolean\n agentCount: number\n channelCount: number\n nodeName?: string\n} {\n const file = resolve(baseDir, \"agentx.json\")\n if (!existsSync(file)) return { configExists: false, agentCount: 0, channelCount: 0 }\n try {\n const cfg = JSON.parse(readFileSync(file, \"utf-8\"))\n const agents = cfg.agents ? Object.keys(cfg.agents).length : 0\n const channels = cfg.channels\n ? Object.values(cfg.channels).filter((c: any) => c && c.enabled).length\n : 0\n return { configExists: true, agentCount: agents, channelCount: channels, nodeName: cfg.node?.name }\n } catch {\n return { configExists: false, agentCount: 0, channelCount: 0 }\n }\n}\n\n/**\n * Execute the wizard submission. Returns a short human-readable summary of\n * what was written. Throws on validation error — the caller surfaces the\n * message to the user.\n */\nexport function runWizard(payload: WizardPayload, baseDir: string = process.cwd()): {\n summary: string\n nextSteps: string[]\n backupPath?: string\n} {\n // --- validate ---\n if (!payload.nodeName?.trim()) throw new Error(\"Team name is required.\")\n if (!payload.agent?.id?.trim()) throw new Error(\"Agent id is required.\")\n if (!/^[a-z0-9][a-z0-9_-]*$/.test(payload.agent.id)) {\n throw new Error(\"Agent id must be lowercase (letters, digits, -, _) and start with a letter or digit.\")\n }\n if (!payload.agent.name?.trim()) throw new Error(\"Agent name is required.\")\n const mentions = splitMentions(payload.agent.triggerWords)\n if (mentions.length === 0) throw new Error(\"At least one trigger word is required.\")\n if (payload.agent.tier !== \"claude-code\" && payload.agent.tier !== \"sdk\") {\n throw new Error(\"AI engine must be claude-code or sdk.\")\n }\n\n const configPath = resolve(baseDir, \"agentx.json\")\n const envPath = resolve(baseDir, \".env\")\n const workspaceDir = resolve(baseDir, \"agents\", payload.agent.id)\n const state = wizardState(baseDir)\n\n // --- scaffold workspace ---\n mkdirSync(workspaceDir, { recursive: true })\n const claudeMd = resolve(workspaceDir, \"CLAUDE.md\")\n if (!existsSync(claudeMd)) {\n const personality = payload.agent.personality?.trim() || `You are ${payload.agent.name}, an assistant on the ${payload.nodeName} team.`\n writeFileSync(claudeMd, `# ${payload.agent.name}\\n\\n${personality}\\n`)\n }\n\n // --- build / mutate agentx.json ---\n const telegramTokenRef = payload.telegram\n ? `TG_${payload.agent.id.toUpperCase()}_BOT_TOKEN`\n : undefined\n\n let backupPath: string | undefined\n if (!state.configExists) {\n const cfg = buildFreshConfig(payload, workspaceDir, mentions, telegramTokenRef)\n writeAgentxConfig(cfg, { configPath })\n } else {\n const result = mutateAgentxConfig((cfg) => {\n cfg.node = cfg.node || {}\n if (!cfg.node.name) cfg.node.name = payload.nodeName\n if (!cfg.node.id) cfg.node.id = slugify(payload.nodeName) || \"team\"\n if (!cfg.node.bind) cfg.node.bind = \"127.0.0.1:18800\"\n cfg.node.defaultAgent = cfg.node.defaultAgent || payload.agent.id\n\n cfg.providers = cfg.providers || {}\n if (!cfg.providers.claude) cfg.providers.claude = { apiKey: \"${ANTHROPIC_API_KEY}\" }\n\n cfg.agents = cfg.agents || {}\n if (cfg.agents[payload.agent.id]) throw new Error(`Agent \"${payload.agent.id}\" already exists.`)\n cfg.agents[payload.agent.id] = agentBlock(payload, workspaceDir, mentions)\n\n if (payload.telegram) {\n cfg.channels = cfg.channels || {}\n cfg.channels.telegram = cfg.channels.telegram || { enabled: true, accounts: {}, policy: { dm: \"pair\", group: \"mention-required\" } }\n cfg.channels.telegram.enabled = true\n cfg.channels.telegram.accounts = cfg.channels.telegram.accounts || {}\n cfg.channels.telegram.accounts[payload.telegram.accountId] = telegramAccountBlock(payload, telegramTokenRef!)\n }\n\n return { summary: `added agent \"${payload.agent.id}\"` + (payload.telegram ? \" + telegram account\" : \"\") }\n }, { configPath })\n backupPath = result.backupPath\n }\n\n // --- write / append .env ---\n ensureEnvEntries(envPath, payload, telegramTokenRef)\n\n const nextSteps: string[] = []\n if (payload.anthropicApiKey || !existsSync(resolve(baseDir, \".env\"))) {\n nextSteps.push(\"Double-check the API keys in .env\")\n }\n if (payload.agent.tier === \"claude-code\") {\n nextSteps.push(\"Run claude --version to confirm Claude Code is installed (needed for the claude-code engine)\")\n }\n nextSteps.push(\"Start the daemon: agentx daemon start\")\n nextSteps.push(\"Open the dashboard: http://127.0.0.1:4202\")\n\n return {\n summary: state.configExists\n ? `Added agent \"${payload.agent.id}\" to your team.`\n : `Initialized your team with first agent \"${payload.agent.id}\".`,\n nextSteps,\n backupPath,\n }\n}\n\nfunction splitMentions(s: string): string[] {\n return (s || \"\")\n .split(/[,\\s]+/)\n .map((m) => m.trim())\n .filter(Boolean)\n // Normalise: ensure @-prefix entries stay, plain ones are kept as-is.\n .filter((m, i, a) => a.indexOf(m) === i)\n}\n\nfunction slugify(s: string): string {\n return (s || \"\").toLowerCase().replace(/[^a-z0-9-]+/g, \"-\").replace(/^-+|-+$/g, \"\")\n}\n\nfunction buildFreshConfig(payload: WizardPayload, workspaceDir: string, mentions: string[], telegramTokenRef?: string) {\n const id = slugify(payload.nodeName) || \"team\"\n const cfg: any = {\n node: { id, name: payload.nodeName, bind: \"127.0.0.1:18800\", defaultAgent: payload.agent.id },\n providers: { claude: { apiKey: \"${ANTHROPIC_API_KEY}\" } },\n agents: { [payload.agent.id]: agentBlock(payload, workspaceDir, mentions) },\n channels: {},\n crons: {},\n mesh: { enabled: false, peers: [], discovery: \"static\", healthCheck: { interval: 60, timeout: 10 } },\n dashboard: { enabled: true, port: 4202, bind: \"127.0.0.1\", daemonUrl: \"http://localhost:18800\" },\n boards: [],\n }\n if (payload.telegram && telegramTokenRef) {\n cfg.channels.telegram = {\n enabled: true,\n accounts: { [payload.telegram.accountId]: telegramAccountBlock(payload, telegramTokenRef) },\n policy: { dm: \"pair\", group: \"mention-required\" },\n }\n } else {\n cfg.channels.telegram = { enabled: false, accounts: {}, policy: { dm: \"pair\", group: \"mention-required\" } }\n }\n return cfg\n}\n\nfunction agentBlock(payload: WizardPayload, workspaceDir: string, mentions: string[]) {\n const block: any = {\n name: payload.agent.name,\n workspace: workspaceDir,\n tier: payload.agent.tier,\n mentions,\n maxConcurrent: 2,\n permissionMode: \"default\",\n }\n if (payload.agent.model) block.model = payload.agent.model\n if (payload.agent.personality?.trim()) block.systemPrompt = payload.agent.personality.trim().slice(0, 400)\n return block\n}\n\nfunction telegramAccountBlock(payload: WizardPayload, tokenRef: string) {\n return {\n botToken: \"${\" + tokenRef + \"}\",\n botUsername: payload.telegram?.botUsername || \"\",\n agentBinding: payload.agent.id,\n }\n}\n\nfunction ensureEnvEntries(envPath: string, payload: WizardPayload, telegramTokenRef?: string): void {\n const existing = existsSync(envPath) ? readFileSync(envPath, \"utf-8\") : \"\"\n const lines: string[] = []\n\n if (payload.anthropicApiKey && !existing.includes(\"ANTHROPIC_API_KEY=\")) {\n lines.push(`ANTHROPIC_API_KEY=${payload.anthropicApiKey}`)\n }\n if (payload.telegram && telegramTokenRef && !existing.includes(`${telegramTokenRef}=`)) {\n lines.push(`${telegramTokenRef}=${payload.telegram.botToken}`)\n }\n\n if (!existsSync(envPath)) {\n const header = [\n \"# AgentX environment variables\",\n \"# (Never commit this file — it contains secrets.)\",\n \"\",\n ]\n writeFileSync(envPath, [...header, ...lines, \"\"].join(\"\\n\"))\n return\n }\n if (lines.length > 0) {\n const sep = existing.endsWith(\"\\n\") ? \"\" : \"\\n\"\n appendFileSync(envPath, sep + lines.join(\"\\n\") + \"\\n\")\n }\n}\n\n// --- HTTP handlers used by board-dashboard.ts ---\n\nexport function handleWizardGet(_req: IncomingMessage, res: ServerResponse): void {\n const state = wizardState()\n const html = renderWizardHtml(state)\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" })\n res.end(html)\n}\n\nexport async function handleWizardPost(req: IncomingMessage, res: ServerResponse): Promise<void> {\n let raw = \"\"\n await new Promise<void>((ok) => { req.on(\"data\", (c) => { raw += c }); req.on(\"end\", () => ok()) })\n let payload: WizardPayload\n try { payload = JSON.parse(raw) }\n catch { res.writeHead(400, { \"Content-Type\": \"application/json\" }); res.end(JSON.stringify({ error: \"Invalid JSON\" })); return }\n try {\n const result = runWizard(payload)\n res.writeHead(200, { \"Content-Type\": \"application/json\" })\n res.end(JSON.stringify(result))\n } catch (e: any) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" })\n res.end(JSON.stringify({ error: e.message || \"wizard failed\" }))\n }\n}\n\nfunction renderWizardHtml(state: ReturnType<typeof wizardState>): string {\n const heading = state.configExists\n ? (state.agentCount === 0 ? \"Add your first agent\" : \"Add another agent\")\n : \"Set up your team\"\n const defaultNode = state.nodeName || hostname().replace(/\\.local$/, \"\")\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentX — Setup</title>\n<style>\n:root{--bg:#0b0d14;--card:#151823;--border:#2a2d3a;--text:#e6e8ef;--muted:#8b8fa3;--accent:#6366f1;--green:#22c55e;--red:#ef4444}\n*{box-sizing:border-box}\nhtml,body{margin:0;min-height:100%;background:var(--bg);color:var(--text);font:14px/1.5 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}\nheader{padding:18px 24px;border-bottom:1px solid var(--border);background:#10131c;display:flex;align-items:center;gap:12px}\nheader .brand{font-weight:600;color:var(--accent);font-size:15px}\nheader .sub{color:var(--muted);font-weight:500}\n.spacer{flex:1}\na.link{color:var(--muted);text-decoration:none;font-size:13px;padding:4px 10px;border:1px solid var(--border);border-radius:6px}\na.link:hover{color:var(--accent);border-color:var(--accent)}\nmain{max-width:620px;margin:0 auto;padding:32px 22px 60px}\nh1{font-size:24px;margin:0 0 6px}\n.lead{color:var(--muted);margin:0 0 26px}\nsection.step{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:20px 22px;margin:14px 0}\nsection.step h2{font-size:14px;font-weight:600;margin:0 0 14px;color:var(--text);display:flex;align-items:center;gap:10px}\nsection.step h2 .num{background:var(--accent);color:#fff;width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:700}\nlabel{display:block;margin:10px 0 4px;font-size:12px;color:var(--muted)}\nlabel .hint{color:var(--muted);font-weight:400;font-size:11px;margin-left:6px}\ninput,textarea,select{width:100%;background:#0e1119;color:var(--text);border:1px solid var(--border);border-radius:6px;padding:8px 10px;font:13px/1.4 inherit}\ninput:focus,textarea:focus,select:focus{outline:none;border-color:var(--accent)}\ntextarea{resize:vertical;min-height:70px;font-family:inherit}\n.row{display:flex;gap:10px}\n.row > *{flex:1}\n.toggle{display:flex;align-items:center;gap:8px;margin:14px 0 4px;font-size:13px;color:var(--text);cursor:pointer}\n.toggle input{width:auto}\n.optional{border-left:2px solid var(--border);padding-left:14px;margin-top:10px;display:none}\n.optional.show{display:block}\nfooter.actions{display:flex;gap:10px;padding:20px 0;align-items:center}\nbutton.primary{background:var(--accent);color:#fff;border:none;border-radius:6px;padding:10px 20px;font-size:14px;font-weight:600;cursor:pointer}\nbutton.primary:hover{filter:brightness(1.1)}\nbutton.primary:disabled{opacity:0.5;cursor:not-allowed}\nbutton.ghost{background:transparent;color:var(--muted);border:1px solid var(--border);border-radius:6px;padding:9px 16px;cursor:pointer}\n.hint-block{font-size:11px;color:var(--muted);margin-top:6px;line-height:1.55}\n.hint-block code{background:#10131c;padding:1px 6px;border-radius:3px;color:var(--text);font-family:ui-monospace,monospace;font-size:11px}\n#msg{margin:14px 0;padding:12px 16px;border-radius:6px;font-size:13px;display:none}\n#msg.ok{display:block;background:rgba(34,197,94,0.12);color:var(--green);border:1px solid rgba(34,197,94,0.3)}\n#msg.err{display:block;background:rgba(239,68,68,0.12);color:var(--red);border:1px solid rgba(239,68,68,0.3)}\n#next-steps{margin-top:12px;padding-left:20px}\n#next-steps li{margin:4px 0}\n#next-steps code{background:#10131c;padding:1px 6px;border-radius:3px;color:var(--text);font-family:ui-monospace,monospace;font-size:12px}\n.config-banner{background:rgba(99,102,241,0.12);border:1px solid rgba(99,102,241,0.3);border-radius:6px;padding:10px 14px;margin-bottom:16px;color:var(--muted);font-size:12px}\n.config-banner b{color:var(--text)}\n</style>\n</head>\n<body>\n<header>\n <div class=\"brand\">AgentX <span class=\"sub\">· Setup</span></div>\n <div class=\"spacer\"></div>\n <a href=\"/glossary\" class=\"link\">? Glossary</a>\n <a href=\"/live\" class=\"link\">Skip — open dashboard</a>\n</header>\n<main>\n <h1>${escapeHtml(heading)}</h1>\n <p class=\"lead\">Fill in the basics below. We'll write <code>agentx.json</code>, set up a folder for your first agent, and point you at the next step.</p>\n\n ${state.configExists ? `<div class=\"config-banner\">Existing install: <b>${state.agentCount}</b> agent(s), <b>${state.channelCount}</b> channel(s) already configured. This wizard will add to it.</div>` : \"\"}\n\n <div id=\"msg\"></div>\n\n <form id=\"wizard\" autocomplete=\"off\">\n <section class=\"step\">\n <h2><span class=\"num\">1</span>Team basics</h2>\n <label>Team name<span class=\"hint\">(what you'd call this AgentX install)</span></label>\n <input name=\"nodeName\" value=\"${escapeHtml(defaultNode)}\" placeholder=\"My Team\" required />\n </section>\n\n <section class=\"step\">\n <h2><span class=\"num\">2</span>First agent</h2>\n <div class=\"row\">\n <div>\n <label>Agent name</label>\n <input name=\"agentName\" value=\"Assistant\" placeholder=\"Support Bot\" required />\n </div>\n <div>\n <label>Agent id<span class=\"hint\">(lowercase, no spaces)</span></label>\n <input name=\"agentId\" value=\"assistant\" pattern=\"[a-z0-9][a-z0-9_-]*\" required />\n </div>\n </div>\n <label>Trigger words<span class=\"hint\">(words that activate this agent — comma or space separated, e.g. <code>@support, support</code>)</span></label>\n <input name=\"triggerWords\" value=\"@assistant, assistant\" required />\n <div class=\"row\">\n <div>\n <label>AI engine</label>\n <select name=\"tier\">\n <option value=\"claude-code\">Claude Code (recommended)</option>\n <option value=\"sdk\">Anthropic API (BYO key)</option>\n </select>\n </div>\n <div>\n <label>Model<span class=\"hint\">(optional)</span></label>\n <input name=\"model\" value=\"claude-sonnet-4-6\" placeholder=\"claude-sonnet-4-6\" />\n </div>\n </div>\n <label>Personality / instructions<span class=\"hint\">(optional — what this agent does, in plain English)</span></label>\n <textarea name=\"personality\" placeholder=\"You are a support agent for Acme Co. Answer customer questions about our product, be friendly, keep replies short.\"></textarea>\n </section>\n\n <section class=\"step\">\n <h2><span class=\"num\">3</span>First channel</h2>\n <label class=\"toggle\"><input type=\"checkbox\" id=\"enableTelegram\" /> Connect Telegram now</label>\n <div class=\"optional\" id=\"telegramFields\">\n <label>Account id<span class=\"hint\">(a label you choose — e.g. <code>support</code>)</span></label>\n <input name=\"telegramAccountId\" value=\"default\" />\n <label>Bot token<span class=\"hint\">(from <a href=\"https://t.me/BotFather\" target=\"_blank\" style=\"color:var(--accent)\">@BotFather</a>)</span></label>\n <input name=\"telegramBotToken\" placeholder=\"123456:ABCdef...\" />\n <label>Bot username<span class=\"hint\">(optional — e.g. <code>my_support_bot</code>)</span></label>\n <input name=\"telegramBotUsername\" placeholder=\"my_support_bot\" />\n </div>\n </section>\n\n <section class=\"step\">\n <h2><span class=\"num\">4</span>Anthropic API key</h2>\n <label>API key<span class=\"hint\">(optional if you'll paste it into <code>.env</code> manually, or if you're only using Claude Code)</span></label>\n <input name=\"anthropicApiKey\" type=\"password\" placeholder=\"sk-ant-…\" autocomplete=\"off\" />\n <div class=\"hint-block\">\n The key is written to <code>.env</code> as <code>ANTHROPIC_API_KEY</code>. AgentX never transmits it — everything stays on this machine.\n </div>\n </section>\n\n <footer class=\"actions\">\n <button type=\"submit\" class=\"primary\" id=\"submitBtn\">Save and continue</button>\n <button type=\"button\" class=\"ghost\" onclick=\"window.location.href='/live'\">Skip, I'll do it later</button>\n </footer>\n </form>\n</main>\n<script>\ndocument.getElementById('enableTelegram').addEventListener('change', (e) => {\n document.getElementById('telegramFields').classList.toggle('show', e.target.checked);\n});\ndocument.getElementById('wizard').addEventListener('submit', async (e) => {\n e.preventDefault();\n const f = e.target;\n const msg = document.getElementById('msg');\n const btn = document.getElementById('submitBtn');\n msg.className = ''; msg.style.display = 'none';\n btn.disabled = true; btn.textContent = 'Saving…';\n const telegramEnabled = document.getElementById('enableTelegram').checked;\n const payload = {\n nodeName: f.nodeName.value.trim(),\n agent: {\n id: f.agentId.value.trim(),\n name: f.agentName.value.trim(),\n triggerWords: f.triggerWords.value.trim(),\n tier: f.tier.value,\n model: f.model.value.trim() || undefined,\n personality: f.personality.value.trim() || undefined,\n },\n anthropicApiKey: f.anthropicApiKey.value.trim() || undefined,\n };\n if (telegramEnabled) {\n payload.telegram = {\n accountId: f.telegramAccountId.value.trim() || 'default',\n botToken: f.telegramBotToken.value.trim(),\n botUsername: f.telegramBotUsername.value.trim() || undefined,\n };\n if (!payload.telegram.botToken) {\n msg.className = 'err'; msg.textContent = 'Bot token is required when Telegram is enabled.';\n btn.disabled = false; btn.textContent = 'Save and continue'; return;\n }\n }\n try {\n const r = await fetch('/api/setup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'agentx-wizard' },\n body: JSON.stringify(payload),\n });\n const data = await r.json();\n if (!r.ok) throw new Error(data.error || ('HTTP ' + r.status));\n const steps = data.nextSteps.map((s) => '<li>' + s.replace(/\\`([^\\`]+)\\`/g, '<code>$1</code>') + '</li>').join('');\n msg.className = 'ok';\n msg.innerHTML = '<b>' + data.summary + '</b><ol id=\"next-steps\">' + steps + '</ol>';\n btn.textContent = 'Done';\n btn.disabled = true;\n } catch (err) {\n msg.className = 'err'; msg.textContent = err.message;\n btn.disabled = false; btn.textContent = 'Save and continue';\n }\n});\n</script>\n</body>\n</html>`\n}\n\nfunction escapeHtml(s: string): string {\n return String(s || \"\").replace(/[&<>\"']/g, (c) => ({ \"&\": \"&\", \"<\": \"<\", \">\": \">\", '\"': \""\", \"'\": \"'\" }[c] as string))\n}\n","import { existsSync, readFileSync, writeFileSync, copyFileSync } from \"fs\"\nimport { resolve } from \"path\"\nimport { loadDaemonConfig } from \"./config\"\n\n// --- Shared helpers for safe agentx.json mutation ---\n//\n// Multiple CLI commands and the dashboard admin UI all need to read → tweak →\n// write agentx.json without corrupting it on failure. This module owns the\n// atomic-write + backup + best-effort-reload pattern so every caller gets the\n// same guarantees.\n\nexport interface MutateOptions {\n /** Absolute path to the target agentx.json. Defaults to ./agentx.json. */\n configPath?: string\n /** When true, don't write a timestamped backup. Use for operations that are\n * intrinsically reversible (or when the caller already took a snapshot). */\n skipBackup?: boolean\n /** When true, don't POST /reload after writing. Handy in tests. */\n skipReload?: boolean\n}\n\nexport interface MutateResult<T = void> {\n summary: string\n payload?: T\n}\n\n/**\n * Read agentx.json, let the mutator tweak it in-place, then atomically write\n * the result back to disk. The mutator returns a short human-readable summary\n * of what changed and may optionally return a payload for the caller to relay.\n *\n * If the mutator throws, nothing is written. If writing succeeds but the file\n * doesn't round-trip as JSON, we restore from backup and rethrow.\n */\nexport function mutateAgentxConfig<T = void>(\n mutator: (cfg: any) => MutateResult<T> | string,\n opts: MutateOptions = {},\n): { summary: string; payload?: T; backupPath?: string } {\n const file = opts.configPath || resolve(process.cwd(), \"agentx.json\")\n if (!existsSync(file)) throw new Error(`agentx.json not found at ${file}`)\n\n const cfg = JSON.parse(readFileSync(file, \"utf-8\"))\n const raw = mutator(cfg)\n const result: MutateResult<T> = typeof raw === \"string\" ? { summary: raw } : raw\n\n const json = JSON.stringify(cfg, null, 2) + \"\\n\"\n const tmp = file + \".tmp\"\n writeFileSync(tmp, json, \"utf-8\")\n try {\n JSON.parse(readFileSync(tmp, \"utf-8\"))\n } catch (e: any) {\n throw new Error(`config did not round-trip cleanly: ${e.message}`)\n }\n\n let backupPath: string | undefined\n if (!opts.skipBackup) {\n backupPath = `${file}.bak.${Date.now()}`\n copyFileSync(file, backupPath)\n }\n writeFileSync(file, json, \"utf-8\")\n\n if (!opts.skipReload) triggerLocalReload().catch(() => { /* daemon may be off */ })\n\n return { summary: result.summary, payload: result.payload, backupPath }\n}\n\n/**\n * Write a fresh agentx.json from scratch. Used by the setup wizard on a truly\n * empty working directory. Fails if a file already exists (callers must pass\n * the overwrite flag explicitly — we don't want to silently clobber an\n * operator's hand-written config).\n */\nexport function writeAgentxConfig(\n cfg: unknown,\n opts: { configPath?: string; overwrite?: boolean } = {},\n): { file: string } {\n const file = opts.configPath || resolve(process.cwd(), \"agentx.json\")\n if (existsSync(file) && !opts.overwrite) {\n throw new Error(`agentx.json already exists at ${file}. Pass overwrite=true to replace it.`)\n }\n writeFileSync(file, JSON.stringify(cfg, null, 2) + \"\\n\", \"utf-8\")\n return { file }\n}\n\n/**\n * POST to the primary daemon's /reload endpoint so it picks up config changes\n * without a full restart. Silently no-ops if the daemon isn't running.\n */\nasync function triggerLocalReload(): Promise<void> {\n try {\n const cfg = loadDaemonConfig()\n const url = cfg.dashboard.daemonUrl?.replace(/\\/+$/, \"\") || \"http://127.0.0.1:18800\"\n await fetch(`${url}/reload`, { method: \"POST\" }).catch(() => null)\n } catch { /* config didn't load — leave it */ }\n}\n","import { createHash, randomBytes } from \"crypto\"\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\"\nimport { resolve, dirname } from \"path\"\n\n// --- Scoped API tokens ---\n//\n// Tokens let external services (other agentx instances, webhook senders, custom\n// apps) talk to this daemon with explicit scopes instead of sharing a single\n// all-powerful dashboard token.\n//\n// We only ever store the sha256 of each token + its printable prefix. The full\n// token is shown exactly once, at creation time, and the operator copies it.\n// Format: agx_live_<hex(32)> — prefix lets secret-scanners catch leaks.\n//\n// Scopes (string equality; \"agent:*\" grants any agent):\n// dashboard:read — /api/live, /api/agents, /api/task/history\n// dashboard:write — /api/admin/*, config mutation endpoints\n// agent:<id> — /api/public/agents/<id>/messages\n// agent:* — any agent\n// mesh:peer — cross-node mesh (forward-compatible — not enforced yet)\n\nexport const TOKEN_PREFIX = \"agx_live_\"\nconst DEFAULT_FILE = \".agentx/tokens.json\"\n\nexport interface TokenRecord {\n id: string // short public id (shown in lists)\n name: string\n prefix: string // full printable prefix (TOKEN_PREFIX + first-4 chars of body)\n hash: string // sha256 of the full token\n scopes: string[]\n createdAt: string\n expiresAt?: string\n revokedAt?: string\n lastUsedAt?: string\n}\n\nexport class TokenStore {\n private file: string\n\n constructor(baseDir: string = process.cwd(), fileRel: string = DEFAULT_FILE) {\n this.file = resolve(baseDir, fileRel)\n }\n\n private load(): TokenRecord[] {\n if (!existsSync(this.file)) return []\n try { return JSON.parse(readFileSync(this.file, \"utf-8\")) as TokenRecord[] } catch { return [] }\n }\n\n private save(records: TokenRecord[]): void {\n mkdirSync(dirname(this.file), { recursive: true })\n writeFileSync(this.file, JSON.stringify(records, null, 2) + \"\\n\", \"utf-8\")\n }\n\n /**\n * Mint a new token. Returns the full token string AND the record.\n * The full token is the only place the secret is ever exposed — the caller\n * must surface it to the operator immediately; after this call the store only\n * knows the hash.\n */\n create(input: {\n name: string\n scopes: string[]\n expiresInDays?: number\n }): { token: string; record: TokenRecord } {\n if (!input.name?.trim()) throw new Error(\"Token name is required.\")\n if (!Array.isArray(input.scopes) || input.scopes.length === 0) {\n throw new Error(\"At least one scope is required.\")\n }\n for (const s of input.scopes) {\n if (!isValidScope(s)) throw new Error(`Invalid scope: ${s}`)\n }\n const body = randomBytes(32).toString(\"hex\")\n const token = TOKEN_PREFIX + body\n const record: TokenRecord = {\n id: \"tok_\" + randomBytes(4).toString(\"hex\"),\n name: input.name.trim(),\n prefix: TOKEN_PREFIX + body.slice(0, 4),\n hash: hashToken(token),\n scopes: [...input.scopes],\n createdAt: new Date().toISOString(),\n expiresAt: input.expiresInDays\n ? new Date(Date.now() + input.expiresInDays * 86400 * 1000).toISOString()\n : undefined,\n }\n const records = this.load()\n records.push(record)\n this.save(records)\n return { token, record }\n }\n\n list(): TokenRecord[] {\n return this.load()\n }\n\n revoke(id: string): TokenRecord | null {\n const records = this.load()\n const rec = records.find((r) => r.id === id)\n if (!rec) return null\n rec.revokedAt = new Date().toISOString()\n this.save(records)\n return rec\n }\n\n /**\n * Look up a token string. Returns the record on success, null on unknown /\n * revoked / expired. Updates lastUsedAt opportunistically (write-on-success).\n */\n verify(token: string): TokenRecord | null {\n if (!token || !token.startsWith(TOKEN_PREFIX)) return null\n const hash = hashToken(token)\n const records = this.load()\n const rec = records.find((r) => r.hash === hash)\n if (!rec) return null\n if (rec.revokedAt) return null\n if (rec.expiresAt && Date.parse(rec.expiresAt) < Date.now()) return null\n // Throttle lastUsedAt updates to at most once per minute to avoid disk churn.\n const now = Date.now()\n const last = rec.lastUsedAt ? Date.parse(rec.lastUsedAt) : 0\n if (now - last > 60_000) {\n rec.lastUsedAt = new Date(now).toISOString()\n try { this.save(records) } catch { /* best-effort */ }\n }\n return rec\n }\n}\n\n/**\n * Check whether a record has a given required scope. \"agent:<id>\" required\n * matches either itself or \"agent:*\". \"dashboard:write\" implicitly grants\n * \"dashboard:read\" for convenience.\n */\nexport function recordHasScope(record: TokenRecord, required: string): boolean {\n if (record.scopes.includes(required)) return true\n if (required.startsWith(\"agent:\") && record.scopes.includes(\"agent:*\")) return true\n if (required === \"dashboard:read\" && record.scopes.includes(\"dashboard:write\")) return true\n return false\n}\n\nfunction isValidScope(s: string): boolean {\n return (\n s === \"dashboard:read\" ||\n s === \"dashboard:write\" ||\n s === \"agent:*\" ||\n /^agent:[a-z0-9][a-z0-9_-]*$/.test(s) ||\n s === \"mesh:peer\"\n )\n}\n\nexport function hashToken(token: string): string {\n return \"sha256:\" + createHash(\"sha256\").update(token).digest(\"hex\")\n}\n\n/**\n * Extract a bearer token from the request headers. Falls back to the\n * `?token=` query param so EventSource (which can't set headers in most\n * browsers) can still authenticate.\n */\nexport function extractToken(req: { headers: Record<string, string | string[] | undefined>; url?: string }): string | null {\n const auth = req.headers[\"authorization\"]\n const authHeader = Array.isArray(auth) ? auth[0] : auth\n if (authHeader && authHeader.toLowerCase().startsWith(\"bearer \")) {\n return authHeader.slice(7).trim()\n }\n if (req.url) {\n try {\n const u = new URL(req.url, \"http://localhost\")\n const tok = u.searchParams.get(\"token\")\n if (tok) return tok\n } catch { /* */ }\n }\n return null\n}\n"],"mappings":"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","names":["existsSync","readFileSync","writeFileSync","appendFileSync","mkdirSync","resolve","hostname","init_config","existsSync","readFileSync","writeFileSync","copyFileSync","resolve","mutateAgentxConfig","mutator","opts","file","cfg","raw","result","json","tmp","e","backupPath","triggerLocalReload","writeAgentxConfig","url","loadDaemonConfig","wizardState","baseDir","file","resolve","existsSync","cfg","readFileSync","agents","channels","c","runWizard","payload","mentions","splitMentions","configPath","envPath","workspaceDir","state","mkdirSync","claudeMd","personality","writeFileSync","telegramTokenRef","backupPath","mutateAgentxConfig","slugify","agentBlock","telegramAccountBlock","buildFreshConfig","writeAgentxConfig","ensureEnvEntries","nextSteps","s","m","i","block","tokenRef","existing","lines","sep","appendFileSync","handleWizardGet","_req","res","html","renderWizardHtml","handleWizardPost","req","raw","ok","result","e","heading","defaultNode","hostname","escapeHtml","createHash","randomBytes","existsSync","mkdirSync","readFileSync","writeFileSync","resolve","dirname","TOKEN_PREFIX","DEFAULT_FILE","TokenStore","baseDir","fileRel","records","input","isValidScope","body","token","record","hashToken","id","rec","hash","r","now","last","recordHasScope","required","s","extractToken","req","auth","authHeader","tok"]}
|
package/dist/chunk-KXZMYLHQ.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import{b as j,d as M}from"./chunk-M7HKBG3V.js";var q=[{name:"create_files",description:"Create one or more files as output. Use this when you need to generate code, documents, configs, or any file-based output.",input_schema:{type:"object",properties:{files:{type:"array",items:{type:"object",properties:{path:{type:"string",description:"Relative file path from project root (e.g., src/components/Button.tsx)"},content:{type:"string",description:"The full content of the file"},language:{type:"string",description:"Programming language or file type"},description:{type:"string",description:"Brief description of what this file does"}},required:["path","content"]}},summary:{type:"string",description:"Brief summary of all generated files"}},required:["files"]},permission:"file-write"},{name:"ask_user",description:"Ask the user a clarifying question when you need more information to proceed. Use this when the request is ambiguous or you need to confirm important decisions.",input_schema:{type:"object",properties:{question:{type:"string",description:"The question to ask the user"},options:{type:"array",items:{type:"string"},description:"Optional list of choices for the user"}},required:["question"]},permission:"none"},{name:"read_file",description:"Read the contents of a file. Use this to inspect existing code, understand patterns, check implementations, or gather context before generating code.",input_schema:{type:"object",properties:{path:{type:"string",description:"Relative file path from project root"},max_lines:{type:"number",description:"Maximum number of lines to read. Defaults to 500. Use for large files."}},required:["path"]},permission:"file-read"},{name:"search_files",description:"Search for files matching a pattern and optionally search their content with a regex. Use this to find relevant code, understand project structure, or locate specific patterns.",input_schema:{type:"object",properties:{pattern:{type:"string",description:"Glob pattern to match files (e.g., 'src/**/*.ts', '*.json')"},content_regex:{type:"string",description:"Optional regex to search within matched files. Returns matching lines."},max_results:{type:"number",description:"Maximum number of results to return. Default: 50."}},required:["pattern"]},permission:"none"},{name:"list_directory",description:"List files and directories at a given path. Use this to explore project structure.",input_schema:{type:"object",properties:{path:{type:"string",description:"Relative directory path from project root. Defaults to '.' (root)."},recursive:{type:"boolean",description:"List recursively. Default: false."},max_depth:{type:"number",description:"Maximum depth for recursive listing. Default: 3."}}},permission:"none"},{name:"run_command",description:"Execute a shell command. Use this to run build tools, test commands, linters, or inspect the environment. Commands run in the project root directory.",input_schema:{type:"object",properties:{command:{type:"string",description:"The shell command to execute"},timeout:{type:"number",description:"Timeout in milliseconds. Default: 30000 (30 seconds)."}},required:["command"]},permission:"command"},{name:"edit_file",description:"Apply search-and-replace edits to an existing file. Use this for targeted modifications to existing code rather than rewriting entire files.",input_schema:{type:"object",properties:{path:{type:"string",description:"Relative file path from project root"},edits:{type:"array",items:{type:"object",properties:{old_text:{type:"string",description:"The exact text to find in the file"},new_text:{type:"string",description:"The replacement text"}},required:["old_text","new_text"]},description:"List of search/replace pairs to apply in order"}},required:["path","edits"]},permission:"file-write"},{name:"spawn_agent",description:"Spawn a sub-agent to handle a task in the background. The sub-agent runs in its own session and returns results. Use this for parallel research, long-running tasks, or delegating work to a specialized agent.",input_schema:{type:"object",properties:{agent_id:{type:"string",description:"The ID of the agent to spawn (must be a registered agent)"},prompt:{type:"string",description:"The task description for the sub-agent"},timeout_seconds:{type:"number",description:"Maximum time to wait for completion in seconds. Default: 300 (5 minutes)."}},required:["agent_id","prompt"]},permission:"none"}];function K(A){return(A?q.filter(e=>A.includes(e.name)):q).map(({name:e,description:i,input_schema:o})=>({name:e,description:i,input_schema:o}))}function P(){return K(["create_files","ask_user"])}function B(){let A=q.filter(e=>e.name!=="create_files"&&e.name!=="ask_user");if(A.length===0)return"";let t=["# Available Capabilities","In addition to generating files, you have the following capabilities:",""];for(let e of A)t.push(`## ${e.name}`),t.push(e.description),t.push("");return t.join(`
|
|
2
|
-
`)}var H=q.map(A=>A.name);var U="claude-sonnet-4-20250514",L=8192,C=class{name="claude";apiKey;authType="api-key";constructor(t){if(this.apiKey=t||process.env.ANTHROPIC_API_KEY||"",!this.apiKey){let e=M();e&&(this.apiKey=e.token,this.authType=e.authType)}if(!this.apiKey)throw new Error("Anthropic API key required. Run `agentx model` to configure, set ANTHROPIC_API_KEY, or pass --api-key.")}async generate(t,e){let i=e?.model||U,o=e?.maxTokens||L,r=t.find(p=>p.role==="system"),u=t.filter(p=>p.role!=="system").map(p=>({role:p.role,content:p.content})),g={model:i,max_tokens:o,messages:u,tools:P()};r&&(g.system=r.content),e?.temperature!==void 0&&(g.temperature=e.temperature);let h=await this.callApi(g);return this.parseResponse(h)}async generateRaw(t,e,i,o){let r=o?.model||U,u=o?.maxTokens||L,g={model:r,max_tokens:u,system:e,messages:t,tools:i};o?.temperature!==void 0&&(g.temperature=o.temperature);let h=await this.callApi(g);return{content:h.content.map(c=>c.type==="text"?{type:"text",text:c.text||""}:c.type==="tool_use"?{type:"tool_use",id:c.id||"",name:c.name||"",input:c.input||{}}:{type:"text",text:""}),stop_reason:h.stop_reason,usage:h.usage}}async*stream(t,e){let i=e?.model||U,o=e?.maxTokens||L,r=t.find(m=>m.role==="system"),u=t.filter(m=>m.role!=="system").map(m=>({role:m.role,content:m.content})),g={model:i,max_tokens:o,messages:u,stream:!0,tools:P()};r&&(g.system=r.content);let h=this.buildHeaders(),p=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:h,body:JSON.stringify(g)});if(!p.ok){let m=await p.text();yield{type:"error",error:`Anthropic API error (${p.status}): ${m}`};return}let c=p.body?.getReader();if(!c){yield{type:"error",error:"No response body"};return}let d=new TextDecoder,a="",_=[],v="",x,k=0,n=null,y=m=>{let R=(m||"").trim();if(!R||R.includes("```"))return;let b=R.replace(/\r\n/g,`
|
|
3
|
-
`).split(`
|
|
4
|
-
`),w=b.slice(Math.max(0,b.length-20)),l=w.join(`
|
|
5
|
-
`);if(/\b(plan|proposal)\b/i.test(l)&&/(ready for your review|review (the )?plan|requesting plan approval|awaiting approval|waiting for (your )?approval|approve (the )?plan|approval to proceed)/i.test(l))return`The provider is requesting plan approval.
|
|
6
|
-
Reply with:
|
|
7
|
-
- approve
|
|
8
|
-
- revise: <what to change>
|
|
9
|
-
- cancel`;let f=T=>/^(question|clarification|clarify|i need|need more|before i proceed|to proceed|please (confirm|clarify)|which|what|where|when|how|do you)/i.test(T.trim()),F=-1;for(let T=w.length-1;T>=0;T--){let O=w[T].trim();if(O&&(f(O)||O.includes("?"))){F=T;break}}if(F===-1)return;let E=[];for(let T=F;T<w.length&&E.length<8;T++){let O=w[T],N=O.trim();if(E.length>0&&!N||E.length>0&&!/^(options?:|[-*]\s|\d+[\).]\s)/i.test(N)&&!N.includes("?"))break;E.push(O.trimEnd())}let I=E.join(`
|
|
10
|
-
`).trim();if(!(I.length<5))return I.length>800?I.slice(0,800).trimEnd():I};try{for(;;){let{done:m,value:R}=await c.read();if(m)break;a+=d.decode(R,{stream:!0});let b=a.split(`
|
|
11
|
-
`);a=b.pop()||"";for(let w of b){if(!w.startsWith("data: "))continue;let l=w.slice(6).trim();if(l!=="[DONE]")try{let s=JSON.parse(l);if(s.type==="content_block_start"&&s.content_block?.type==="tool_use"){if(n){yield{type:"tool_use_end",name:n.name};try{let f=JSON.parse(n.json||"{}");n.name==="create_files"&&f&&(Array.isArray(f.files)&&_.push(...f.files),typeof f.summary=="string"&&f.summary.trim()&&(v+=`
|
|
12
|
-
${f.summary}`)),n.name==="ask_user"&&f&&typeof f.question=="string"&&f.question.trim()&&(x=f.question,Array.isArray(f.options)&&f.options.length&&(x+=`
|
|
13
|
-
Options: ${f.options.join(", ")}`))}catch{}finally{n=null}}n={name:s.content_block.name,id:s.content_block.id,json:""},yield{type:"tool_use_start",name:s.content_block.name,id:s.content_block.id}}if(s.type==="content_block_delta"&&(s.delta?.type==="text_delta"&&(v+=s.delta.text,yield{type:"text_delta",text:s.delta.text}),s.delta?.type==="input_json_delta"&&(n&&(n.json+=s.delta.partial_json||""),yield{type:"tool_use_delta",json:s.delta.partial_json})),s.type==="content_block_stop"&&n){yield{type:"tool_use_end",name:n.name};try{let f=JSON.parse(n.json||"{}");n.name==="create_files"&&f&&(Array.isArray(f.files)&&_.push(...f.files),typeof f.summary=="string"&&f.summary.trim()&&(v+=`
|
|
14
|
-
${f.summary}`)),n.name==="ask_user"&&f&&typeof f.question=="string"&&f.question.trim()&&(x=f.question,Array.isArray(f.options)&&f.options.length&&(x+=`
|
|
15
|
-
Options: ${f.options.join(", ")}`))}catch{}finally{n=null}}s.type==="message_delta"&&s.usage&&(k=(s.usage.input_tokens||0)+(s.usage.output_tokens||0)),s.type}catch{}}}}finally{c.releaseLock()}if(n){yield{type:"tool_use_end",name:n.name};try{let m=JSON.parse(n.json||"{}");n.name==="create_files"&&m&&(Array.isArray(m.files)&&_.push(...m.files),typeof m.summary=="string"&&m.summary.trim()&&(v+=`
|
|
16
|
-
${m.summary}`)),n.name==="ask_user"&&m&&typeof m.question=="string"&&m.question.trim()&&(x=m.question,Array.isArray(m.options)&&m.options.length&&(x+=`
|
|
17
|
-
Options: ${m.options.join(", ")}`))}catch{}n=null}!x&&_.length===0&&(x=y(v)),yield{type:"done",result:{content:v,files:_,followUp:x,tokensUsed:k}}}buildHeaders(){let t={"Content-Type":"application/json","anthropic-version":"2023-06-01"};return this.authType==="oauth"?(t.Authorization=`Bearer ${this.apiKey}`,t["anthropic-beta"]="claude-code-20250219,oauth-2025-04-20",t["user-agent"]="claude-cli/2.1.2 (external, cli)",t["x-app"]="cli",t["anthropic-dangerous-direct-browser-access"]="true"):t["x-api-key"]=this.apiKey,t}async callApi(t){let e=this.buildHeaders(),i=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:e,body:JSON.stringify(t)});if(!i.ok){let o=await i.text();throw new Error(`Anthropic API error (${i.status}): ${o}`)}return await i.json()}parseResponse(t){let e=[],i="",o;for(let r of t.content)if(r.type==="text"&&(i+=r.text||""),r.type==="tool_use"){if(r.name==="create_files"&&r.input){let u=r.input;e.push(...u.files||[]),u.summary&&(i+=`
|
|
18
|
-
${u.summary}`)}if(r.name==="ask_user"&&r.input){let u=r.input;o=u.question,u.options?.length&&(o+=`
|
|
19
|
-
Options: ${u.options.join(", ")}`)}}return{content:i,files:e,followUp:o,tokensUsed:t.usage.input_tokens+t.usage.output_tokens}}};import{execa as D}from"execa";var S="claude-sonnet-4-20250514",$=8192,J={"claude-sonnet-4-20250514":"sonnet","claude-opus-4-20250514":"opus","claude-haiku-4-20250514":"haiku"},G=class{name="claude-code";credential;constructor(){let t=j();if(t){this.credential={type:t.authType,token:t.token};return}let e=M();if(!e)throw new Error(`No Claude credentials found.
|
|
20
|
-
Options:
|
|
21
|
-
1. Run \`agentx model\` to configure credentials
|
|
22
|
-
2. Set ANTHROPIC_API_KEY environment variable
|
|
23
|
-
3. Set ANTHROPIC_OAUTH_TOKEN environment variable`);this.credential={type:e.authType,token:e.token}}async generate(t,e){return this.credential.type==="oauth"?this.generateViaCli(t,e):this.generateViaApi(t,e)}async generateRaw(t,e,i,o){if(this.credential.type==="oauth")throw new Error("generateRaw() not available for OAuth/CLI mode");let r=o?.model||S,u=o?.maxTokens||$,g={model:r,max_tokens:u,system:e,messages:t,tools:i};o?.temperature!==void 0&&(g.temperature=o.temperature);let h={"Content-Type":"application/json","anthropic-version":"2023-06-01","x-api-key":this.credential.token},p=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:h,body:JSON.stringify(g)});if(!p.ok){let a=await p.text();throw new Error(`Anthropic API error (${p.status}): ${a}`)}let c=await p.json();return{content:c.content.map(a=>a.type==="text"?{type:"text",text:a.text||""}:a.type==="tool_use"?{type:"tool_use",id:a.id||"",name:a.name||"",input:a.input||{}}:{type:"text",text:""}),stop_reason:c.stop_reason,usage:c.usage}}get supportsAgenticLoop(){return this.credential.type==="api-key"}async generateViaCli(t,e){let i=e?.model||j()?.model||S,o=J[i]||i,r=t.find(a=>a.role==="system"),g=t.filter(a=>a.role==="user").map(a=>a.content).join(`
|
|
24
|
-
|
|
25
|
-
`),h=["-p","--output-format","json","--model",o,"--dangerously-skip-permissions"];r&&h.push("--append-system-prompt",r.content),h.push(g);let p={...process.env};delete p.ANTHROPIC_API_KEY,delete p.ANTHROPIC_API_KEY_OLD;let c=await D("claude",h,{env:p,extendEnv:!1,reject:!1,timeout:3e5,stdin:"ignore"});if(c.exitCode!==0){let a=c.stderr||c.stdout||"Claude CLI failed";throw new Error(`Claude CLI error: ${a}`)}let d=c.stdout.trim();try{let a=JSON.parse(d);if(a.is_error&&a.result)throw new Error(a.result)}catch(a){if(a.message&&!a.message.includes("JSON"))throw a}return this.parseCliOutput(d)}async generateViaApi(t,e){let i=e?.model||S,o=e?.maxTokens||$,r=t.find(d=>d.role==="system"),u=t.filter(d=>d.role!=="system").map(d=>({role:d.role,content:d.content})),g={model:i,max_tokens:o,messages:u,tools:P()};r&&(g.system=r.content),e?.temperature!==void 0&&(g.temperature=e.temperature);let h={"Content-Type":"application/json","anthropic-version":"2023-06-01","x-api-key":this.credential.token},p=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:h,body:JSON.stringify(g)});if(!p.ok){let d=await p.text();throw new Error(`Anthropic API error (${p.status}): ${d}`)}let c=await p.json();return this.parseApiResponse(c)}async*stream(t,e){this.credential.type==="oauth"?yield*this.streamViaCli(t,e):yield*this.streamViaApi(t,e)}async*streamViaCli(t,e){let i=e?.model||j()?.model||S,o=J[i]||i,r=t.find(n=>n.role==="system"),g=t.filter(n=>n.role==="user").map(n=>n.content).join(`
|
|
26
|
-
|
|
27
|
-
`),h=["-p","--output-format","stream-json","--model",o,"--dangerously-skip-permissions"];r&&h.push("--append-system-prompt",r.content),h.push(g);let p={...process.env};delete p.ANTHROPIC_API_KEY,delete p.ANTHROPIC_API_KEY_OLD;let c=D("claude",h,{env:p,extendEnv:!1,reject:!1,timeout:3e5,stdin:"ignore"}),d="",a="",_;if(c.stderr&&c.stderr.on("data",n=>{a+=Buffer.isBuffer(n)?n.toString("utf8"):String(n)}),c.stdout){let n=new TextDecoder,y=c.stdout;for await(let m of y){let b=(typeof m=="string"?m:n.decode(m,{stream:!0})).split(`
|
|
28
|
-
`).filter(Boolean);for(let w of b)try{let l=JSON.parse(w);if(l.type==="error"){_=String(l.error||l.message||"Claude CLI error");continue}if(l.is_error&&(l.result||l.message)){_=String(l.result||l.message);continue}l.type==="assistant"&&l.message?(d+=l.message,yield{type:"text_delta",text:l.message}):l.type==="result"&&(d=l.result||d)}catch{d+=w,yield{type:"text_delta",text:w}}}}let v=await c;if(v.exitCode!==0&&!_&&(_=(a||v.stderr||v.stdout||"Claude CLI failed").toString().trim()),_){yield{type:"error",error:`Claude CLI error: ${_}`};return}let x=this.extractFilesFromText(d),k=x.length===0?this.inferFollowUpFromText(d):void 0;yield{type:"done",result:{content:d,files:x,followUp:k,tokensUsed:0}}}async*streamViaApi(t,e){let i=e?.model||S,o=e?.maxTokens||$,r=t.find(y=>y.role==="system"),u=t.filter(y=>y.role!=="system").map(y=>({role:y.role,content:y.content})),g={model:i,max_tokens:o,messages:u,tools:P(),stream:!0};r&&(g.system=r.content);let h={"Content-Type":"application/json","anthropic-version":"2023-06-01","x-api-key":this.credential.token},p=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:h,body:JSON.stringify(g)});if(!p.ok){let y=await p.text();yield{type:"error",error:`Anthropic API error (${p.status}): ${y}`};return}let c=p.body?.getReader();if(!c){yield{type:"error",error:"No response body"};return}let d=new TextDecoder,a="",_="",v=0,x=[],k,n=null;try{for(;;){let{done:y,value:m}=await c.read();if(y)break;a+=d.decode(m,{stream:!0});let R=a.split(`
|
|
29
|
-
`);a=R.pop()||"";for(let b of R){if(!b.startsWith("data: "))continue;let w=b.slice(6).trim();if(w!=="[DONE]")try{let l=JSON.parse(w);if(l.type==="content_block_start"&&l.content_block?.type==="tool_use"){if(n){yield{type:"tool_use_end",name:n.name};try{let s=JSON.parse(n.json||"{}");n.name==="create_files"&&s&&(Array.isArray(s.files)&&x.push(...s.files),typeof s.summary=="string"&&s.summary.trim()&&(_+=`
|
|
30
|
-
${s.summary}`)),n.name==="ask_user"&&s&&typeof s.question=="string"&&s.question.trim()&&(k=s.question,Array.isArray(s.options)&&s.options.length&&(k+=`
|
|
31
|
-
Options: ${s.options.join(", ")}`))}catch{}finally{n=null}}n={name:l.content_block.name,id:l.content_block.id,json:""},yield{type:"tool_use_start",name:n.name,id:n.id}}if(l.type==="content_block_delta"&&l.delta?.type==="text_delta"&&(_+=l.delta.text,yield{type:"text_delta",text:l.delta.text}),l.type==="content_block_delta"&&l.delta?.type==="input_json_delta"&&(n&&(n.json+=l.delta.partial_json||""),yield{type:"tool_use_delta",json:l.delta.partial_json}),l.type==="content_block_stop"&&n){yield{type:"tool_use_end",name:n.name};try{let s=JSON.parse(n.json||"{}");n.name==="create_files"&&s&&(Array.isArray(s.files)&&x.push(...s.files),typeof s.summary=="string"&&s.summary.trim()&&(_+=`
|
|
32
|
-
${s.summary}`)),n.name==="ask_user"&&s&&typeof s.question=="string"&&s.question.trim()&&(k=s.question,Array.isArray(s.options)&&s.options.length&&(k+=`
|
|
33
|
-
Options: ${s.options.join(", ")}`))}catch{}finally{n=null}}l.type==="message_delta"&&l.usage&&(v=(l.usage.input_tokens||0)+(l.usage.output_tokens||0))}catch{}}}}finally{c.releaseLock()}if(n){yield{type:"tool_use_end",name:n.name};try{let y=JSON.parse(n.json||"{}");n.name==="create_files"&&y&&(Array.isArray(y.files)&&x.push(...y.files),typeof y.summary=="string"&&y.summary.trim()&&(_+=`
|
|
34
|
-
${y.summary}`)),n.name==="ask_user"&&y&&typeof y.question=="string"&&y.question.trim()&&(k=y.question,Array.isArray(y.options)&&y.options.length&&(k+=`
|
|
35
|
-
Options: ${y.options.join(", ")}`))}catch{}n=null}x.length===0&&x.push(...this.extractFilesFromText(_)),!k&&x.length===0&&(k=this.inferFollowUpFromText(_)),yield{type:"done",result:{content:_,files:x,followUp:k,tokensUsed:v}}}parseCliOutput(t){let e;try{e=JSON.parse(t)}catch{let u=this.inferFollowUpFromText(t.trim());return{content:t.trim(),files:[],followUp:u,tokensUsed:0}}let i=e.result||e.text||e.content||"",o=this.extractFilesFromText(i),r=o.length===0?this.inferFollowUpFromText(i):void 0;return{content:i,files:o,followUp:r,tokensUsed:e.usage?(e.usage.input_tokens||0)+(e.usage.output_tokens||0):0}}extractFilesFromText(t){let e=[],i=/```[\w]*\s*([\w/._-]+\.\w+)\n([\s\S]*?)```/g,o;for(;(o=i.exec(t))!==null;){let r=o[1],u=o[2];r&&u&&e.push({path:r,content:u.trimEnd()})}return e}inferFollowUpFromText(t){let e=(t||"").trim();if(!e||e.includes("```"))return;let i=e.replace(/\r\n/g,`
|
|
36
|
-
`).split(`
|
|
37
|
-
`),o=i.slice(Math.max(0,i.length-20)),r=o.join(`
|
|
38
|
-
`);if(/\b(plan|proposal)\b/i.test(r)&&/(ready for your review|review (the )?plan|requesting plan approval|awaiting approval|waiting for (your )?approval|approve (the )?plan|approval to proceed)/i.test(r))return`The provider is requesting plan approval.
|
|
39
|
-
Reply with:
|
|
40
|
-
- approve
|
|
41
|
-
- revise: <what to change>
|
|
42
|
-
- cancel`;let g=d=>/^(question|clarification|clarify|i need|need more|before i proceed|to proceed|please (confirm|clarify)|which|what|where|when|how|do you)/i.test(d.trim()),h=-1;for(let d=o.length-1;d>=0;d--){let a=o[d].trim();if(a&&(g(a)||a.includes("?"))){h=d;break}}if(h===-1)return;let p=[];for(let d=h;d<o.length&&p.length<8;d++){let a=o[d],_=a.trim();if(p.length>0&&!_||p.length>0&&!/^(options?:|[-*]\s|\d+[\).]\s)/i.test(_)&&!_.includes("?"))break;p.push(a.trimEnd())}let c=p.join(`
|
|
43
|
-
`).trim();if(!(c.length<5))return c.length>800?c.slice(0,800).trimEnd():c}parseApiResponse(t){let e=[],i="",o;for(let r of t.content)if(r.type==="text"&&(i+=r.text||""),r.type==="tool_use"){if(r.name==="create_files"&&r.input){let u=r.input;e.push(...u.files||[]),u.summary&&(i+=`
|
|
44
|
-
${u.summary}`)}if(r.name==="ask_user"&&r.input){let u=r.input;o=u.question,u.options?.length&&(o+=`
|
|
45
|
-
Options: ${u.options.join(", ")}`)}}return{content:i,files:e,followUp:o,tokensUsed:t.usage.input_tokens+t.usage.output_tokens}}};function se(A="claude-code",t){let e=A;if(A==="claude-code"&&!t){let i=j();i&&(e=i.provider)}switch(e){case"claude-code":return new G;case"claude":return new C(t);case"openai":throw new Error("OpenAI provider coming soon. Set provider to 'claude-code' or contribute at github.com/anis-marrouchi/agentx");case"ollama":throw new Error("Ollama provider coming soon. Set provider to 'claude-code' or contribute at github.com/anis-marrouchi/agentx");default:throw new Error(`Unknown provider: ${e}. Supported: claude-code, claude`)}}export{K as a,P as b,B as c,H as d,C as e,G as f,se as g};
|
|
46
|
-
//# sourceMappingURL=chunk-KXZMYLHQ.js.map
|