agentix-cli 0.3.0 → 0.4.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-K2YOEOJ5.js +2 -0
- package/dist/chunk-4YCH6IZV.js +2 -0
- package/dist/chunk-AIBBZF4E.js +41 -0
- package/dist/chunk-AIBBZF4E.js.map +1 -0
- package/dist/{chunk-KVWUPUR5.js → chunk-F73GPYCO.js} +4 -4
- package/dist/{chunk-PCAYW54Q.js → chunk-Z4GC5D6D.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{heal-RDZZJXDZ.js → heal-UV5A6B5T.js} +2 -2
- package/dist/index.d.ts +26 -3
- package/dist/index.js +2 -2
- package/dist/loader-6VSM6FSY.js +2 -0
- package/dist/{providers-Q3U3ONJO.js → providers-AVYG63KK.js} +2 -2
- package/package.json +1 -1
- package/dist/agent-CRA5PU6S.js +0 -2
- package/dist/chunk-MDR7SH7F.js +0 -2
- package/dist/chunk-S74N276K.js +0 -35
- package/dist/chunk-S74N276K.js.map +0 -1
- package/dist/loader-RL2LKXIF.js +0 -2
- /package/dist/{agent-CRA5PU6S.js.map → agent-K2YOEOJ5.js.map} +0 -0
- /package/dist/{chunk-MDR7SH7F.js.map → chunk-4YCH6IZV.js.map} +0 -0
- /package/dist/{chunk-KVWUPUR5.js.map → chunk-F73GPYCO.js.map} +0 -0
- /package/dist/{chunk-PCAYW54Q.js.map → chunk-Z4GC5D6D.js.map} +0 -0
- /package/dist/{heal-RDZZJXDZ.js.map → heal-UV5A6B5T.js.map} +0 -0
- /package/dist/{loader-RL2LKXIF.js.map → loader-6VSM6FSY.js.map} +0 -0
- /package/dist/{providers-Q3U3ONJO.js.map → providers-AVYG63KK.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{d as X,g as v,k as c}from"./chunk-
|
|
1
|
+
import{d as X,g as v,k as c}from"./chunk-Z4GC5D6D.js";import{a as Ce,d as fe}from"./chunk-FRFR27IN.js";import{a as _e,b as Pe,c as ge}from"./chunk-SFQUP3BP.js";import{a as de,c as ue,g as me}from"./chunk-MGMZNJCE.js";import{a as F,b as ce,f as pe}from"./chunk-M7HKBG3V.js";import{z as R}from"zod";var Se=R.object({provider:R.enum(["claude-code","claude","openai","ollama","custom"]).default("claude-code"),model:R.string().optional(),apiKey:R.string().optional(),skills:R.array(R.string()).default([]),output:R.object({dir:R.string().default("./generated")}).default({}),context7:R.object({enabled:R.boolean().default(!0),apiKey:R.string().optional()}).default({}),agentic:R.object({maxIterations:R.number().default(20),enabledTools:R.array(R.string()).default(["create_files","ask_user","read_file","search_files","list_directory","run_command","edit_file"]),disabledTools:R.array(R.string()).default([])}).default({})}),pt=["component","page","api","website","document","script","config","skill","media","report","test","workflow","schema","email","diagram","auto"],dt={component:"UI component (any framework)",page:"Full page or screen",api:"API endpoint, route handler, or service",website:"Multi-page website or app",document:"Markdown, documentation, or specification",script:"Standalone script or utility",config:"Configuration file or setup",skill:"Agent skill (SKILL.md format for skills.sh)",media:"Media generation prompt (image/audio/video description)",report:"Analysis report or audit",test:"Test suite, test fixtures, or test data",workflow:"CI/CD pipeline, GitHub Actions, or automation",schema:"Database schema, Zod validators, or GraphQL types",email:"Email template (React Email, MJML, HTML)",diagram:"Mermaid, D2, or PlantUML diagram",auto:"Auto-detect the best output type"};import{existsSync as He,promises as Ke}from"fs";import q from"path";import Ye from"fast-glob";var Te={"prisma/schema.prisma":{type:"prisma",category:"database"},"drizzle/schema.ts":{type:"drizzle",category:"database"},"schema.graphql":{type:"graphql",category:"api"},"schema.gql":{type:"graphql",category:"api"},"openapi.yaml":{type:"openapi",category:"api"},"openapi.json":{type:"openapi",category:"api"},"swagger.yaml":{type:"openapi",category:"api"},"swagger.json":{type:"openapi",category:"api"}};async function Re(o){let e={},t=await Ye.glob("**/*",{cwd:o,deep:4,ignore:["**/node_modules/**","**/dist/**","**/build/**","**/.next/**","**/target/**","**/__pycache__/**","**/vendor/**","**/.git/**"],onlyFiles:!0});for(let[s,i]of Object.entries(Te)){let l=t.find(a=>a.endsWith(s)||a===s);if(l&&i.category==="database"){let a=await K(q.resolve(o,l));if(a){e.database={type:i.type,content:Z(a,3e3),tables:Je(a,i.type)};break}}}for(let[s,i]of Object.entries(Te)){let l=t.find(a=>a.endsWith(s)||a===s);if(l&&i.category==="api"){let a=await K(q.resolve(o,l));if(a){e.api={type:i.type,content:Z(a,3e3)};break}}}if(!e.api){let s=t.find(i=>i.includes("trpc")&&(i.endsWith("router.ts")||i.endsWith("router.js")));if(s){let i=await K(q.resolve(o,s));i&&(e.api={type:"trpc",content:Z(i,3e3)})}}let n=t.find(s=>s===".env.example"||s===".env.local.example"||s===".env.template");if(n){let s=await K(q.resolve(o,n));s&&(e.env=Qe(s))}let r=t.filter(s=>(s.includes("models")||s.includes("types")||s.includes("schemas"))&&(s.endsWith(".ts")||s.endsWith(".py")||s.endsWith(".rs")||s.endsWith(".go")));if(r.length){e.models=[];for(let s of r.slice(0,5)){let i=await K(q.resolve(o,s));i&&e.models.push({path:s,content:Z(i,2e3),type:q.extname(s).slice(1)})}}return e}function Je(o,e){if(e==="prisma"){let t=o.match(/model\s+(\w+)\s*\{/g);return t?t.map(n=>n.replace(/model\s+/,"").replace(/\s*\{/,"")):[]}return[]}function Qe(o){return{variables:o.split(`
|
|
2
2
|
`).filter(n=>n.trim()&&!n.trim().startsWith("#")).map(n=>{let[r]=n.split("="),s=r.trim(),i=n.includes("=")&&n.split("=")[1]?.trim().length>0;return{key:s,required:!i}})}}async function K(o){try{return He(o)?await Ke.readFile(o,"utf8"):null}catch{return null}}function Z(o,e){return o.length<=e?o:o.slice(0,e)+`
|
|
3
3
|
... (truncated)`}function Ae(o){let e=[];if(o.database&&e.push(`## Database Schema (${o.database.type})
|
|
4
4
|
`+(o.database.tables?.length?`Tables: ${o.database.tables.join(", ")}
|
|
@@ -45,7 +45,7 @@ Options: ${n.join(", ")}`),{tool_use_id:e.id,content:"Question sent to user.",fo
|
|
|
45
45
|
`);l.push({role:"assistant",content:w.content+(G?`
|
|
46
46
|
|
|
47
47
|
Files created:
|
|
48
|
-
${G}`:"")}),l.push({role:"user",content:"Continue generating the remaining files. Build on what you've already created. When finished, do not include [CONTINUE] in your response."})}return{files:a,content:p,followUp:g,tokensUsed:x,iterations:b}}function ke(o){return typeof o.generateRaw=="function"}var se=class{queue=[];resolvers=[];closed=!1;push(e){if(this.closed)return;let t=this.resolvers.shift();if(t){t({value:e,done:!1});return}this.queue.push(e)}close(){if(!this.closed){this.closed=!0;for(let e of this.resolvers.splice(0))e({value:void 0,done:!0})}}async next(){return this.queue.length?{value:this.queue.shift(),done:!1}:this.closed?{value:void 0,done:!0}:new Promise(e=>{this.resolvers.push(e)})}async*[Symbol.asyncIterator](){for(;;){let{value:e,done:t}=await this.next();if(t)return;yield e}}};async function qe(o,e,t){let n=Se.parse(t||{}),r=new Y(o);await r.load();let[s,i,l]=await Promise.all([_e(o),Re(o),Ce(o)]),a="";if(n.context7.enabled)try{a=await $e(s,e,n.context7.apiKey)}catch{}let x=r.buildMemoryContext(e),p=be(o);return v.context("memory",x?"loaded":"empty"),v.context("instructions",p?"loaded from project":"none"),{techStack:s,schemas:i,skills:l,docs:a,config:n,memoryContext:x,projectInstructions:p}}async function Ro(o){let{task:e,cwd:t,overwrite:n=!1,dryRun:r=!1,provider:s="claude-code",model:i,apiKey:l,context7:a=!0,interactive:x=!0}=o,p=e;if(c.has("pre:prompt")){let u=await c.execute("pre:prompt",{event:"pre:prompt",task:e,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by pre:prompt hook");u.modified?.task&&(p=String(u.modified.task))}if(c.has("pre:generate")){let u=await c.execute("pre:generate",{event:"pre:generate",task:p,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by pre:generate hook")}F.info("Analyzing project...");let g=await qe(t,p,{provider:s,context7:{enabled:a,apiKey:l}}),b=he(o.outputType,p);F.info(`Output type: ${b}`);let w=fe(g.skills,p,b);w.length&&F.info(`Loaded ${w.length} relevant skill(s): ${w.map(u=>u.skill.frontmatter.name).join(", ")}`);let $=Be(g,b,w.map(u=>u.skill));if(!await pe(l))throw new Error("No credentials configured. Run `agentx model` to set up.");let C=me(s,l),S=i||ce()?.model,O=[...o.sessionMessages||[],{role:"user",content:p}];F.info("Generating...");let M=ke(C),k=o.maxSteps??(M?20:5),h=await xe({provider:C,systemPrompt:$,messages:[{role:"system",content:$},...O],providerOptions:{model:S,maxTokens:8192},cwd:t,maxIterations:k,enabledTools:g.config.agentic.enabledTools.filter(u=>!g.config.agentic.disabledTools.includes(u)),interactive:x,overwrite:n,dryRun:r,onProgress:u=>{u.type==="iteration_start"&&u.iteration>1&&F.info(`Step ${u.iteration}/${k}...`),u.type==="tool_call"&&v.step(0,`Tool: ${u.name}`)}});if(h.tokensUsed){let u=S||"claude-sonnet-4-20250514",L=Math.round(h.tokensUsed*.3),ie=h.tokensUsed-L;X.recordStep(1,u,L,ie)}let{content:j}=h,{followUp:_,tokensUsed:y}=h;if(h.iterations>1&&F.info(`Completed in ${h.iterations} step(s)`),c.has("post:response")){let u=await c.execute("post:response",{event:"post:response",content:j,task:p,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by post:response hook");u.modified?.content&&(j=String(u.modified.content))}if(_&&x)return{files:{written:[],skipped:[],errors:[]},content:j,outputType:b,followUp:_,tokensUsed:y};let U=new Map;for(let u of h.files)U.set(u.path,u);let A=ne(b,g.techStack,o.outputDir),T=await oe(Array.from(U.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:A}),I;if(o.heal!==!1&&!r&&T.written.length>0){let{HealEngine:u}=await import("./heal-
|
|
48
|
+
${G}`:"")}),l.push({role:"user",content:"Continue generating the remaining files. Build on what you've already created. When finished, do not include [CONTINUE] in your response."})}return{files:a,content:p,followUp:g,tokensUsed:x,iterations:b}}function ke(o){return typeof o.generateRaw=="function"}var se=class{queue=[];resolvers=[];closed=!1;push(e){if(this.closed)return;let t=this.resolvers.shift();if(t){t({value:e,done:!1});return}this.queue.push(e)}close(){if(!this.closed){this.closed=!0;for(let e of this.resolvers.splice(0))e({value:void 0,done:!0})}}async next(){return this.queue.length?{value:this.queue.shift(),done:!1}:this.closed?{value:void 0,done:!0}:new Promise(e=>{this.resolvers.push(e)})}async*[Symbol.asyncIterator](){for(;;){let{value:e,done:t}=await this.next();if(t)return;yield e}}};async function qe(o,e,t){let n=Se.parse(t||{}),r=new Y(o);await r.load();let[s,i,l]=await Promise.all([_e(o),Re(o),Ce(o)]),a="";if(n.context7.enabled)try{a=await $e(s,e,n.context7.apiKey)}catch{}let x=r.buildMemoryContext(e),p=be(o);return v.context("memory",x?"loaded":"empty"),v.context("instructions",p?"loaded from project":"none"),{techStack:s,schemas:i,skills:l,docs:a,config:n,memoryContext:x,projectInstructions:p}}async function Ro(o){let{task:e,cwd:t,overwrite:n=!1,dryRun:r=!1,provider:s="claude-code",model:i,apiKey:l,context7:a=!0,interactive:x=!0}=o,p=e;if(c.has("pre:prompt")){let u=await c.execute("pre:prompt",{event:"pre:prompt",task:e,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by pre:prompt hook");u.modified?.task&&(p=String(u.modified.task))}if(c.has("pre:generate")){let u=await c.execute("pre:generate",{event:"pre:generate",task:p,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by pre:generate hook")}F.info("Analyzing project...");let g=await qe(t,p,{provider:s,context7:{enabled:a,apiKey:l}}),b=he(o.outputType,p);F.info(`Output type: ${b}`);let w=fe(g.skills,p,b);w.length&&F.info(`Loaded ${w.length} relevant skill(s): ${w.map(u=>u.skill.frontmatter.name).join(", ")}`);let $=Be(g,b,w.map(u=>u.skill));if(!await pe(l))throw new Error("No credentials configured. Run `agentx model` to set up.");let C=me(s,l),S=i||ce()?.model,O=[...o.sessionMessages||[],{role:"user",content:p}];F.info("Generating...");let M=ke(C),k=o.maxSteps??(M?20:5),h=await xe({provider:C,systemPrompt:$,messages:[{role:"system",content:$},...O],providerOptions:{model:S,maxTokens:8192},cwd:t,maxIterations:k,enabledTools:g.config.agentic.enabledTools.filter(u=>!g.config.agentic.disabledTools.includes(u)),interactive:x,overwrite:n,dryRun:r,onProgress:u=>{u.type==="iteration_start"&&u.iteration>1&&F.info(`Step ${u.iteration}/${k}...`),u.type==="tool_call"&&v.step(0,`Tool: ${u.name}`)}});if(h.tokensUsed){let u=S||"claude-sonnet-4-20250514",L=Math.round(h.tokensUsed*.3),ie=h.tokensUsed-L;X.recordStep(1,u,L,ie)}let{content:j}=h,{followUp:_,tokensUsed:y}=h;if(h.iterations>1&&F.info(`Completed in ${h.iterations} step(s)`),c.has("post:response")){let u=await c.execute("post:response",{event:"post:response",content:j,task:p,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by post:response hook");u.modified?.content&&(j=String(u.modified.content))}if(_&&x)return{files:{written:[],skipped:[],errors:[]},content:j,outputType:b,followUp:_,tokensUsed:y};let U=new Map;for(let u of h.files)U.set(u.path,u);let A=ne(b,g.techStack,o.outputDir),T=await oe(Array.from(U.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:A}),I;if(o.heal!==!1&&!r&&T.written.length>0){let{HealEngine:u}=await import("./heal-UV5A6B5T.js");I=await new u(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(T.written,p),!I.healed&&I.error&&await c.execute("on:error",{event:"on:error",error:new Error(I.error),task:p,cwd:t})}return c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:j,cwd:t}),{files:T,content:j,outputType:b,tokensUsed:y,healResult:I}}async function*Ao(o){let{task:e,cwd:t,overwrite:n=!1,dryRun:r=!1,provider:s="claude-code",model:i,apiKey:l,context7:a=!0,interactive:x=!0}=o,p=e;if(c.has("pre:prompt")){let d=await c.execute("pre:prompt",{event:"pre:prompt",task:e,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by pre:prompt hook"};return}d.modified?.task&&(p=String(d.modified.task))}if(c.has("pre:generate")){let d=await c.execute("pre:generate",{event:"pre:generate",task:p,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by pre:generate hook"};return}}let g=await qe(t,p,{provider:s,context7:{enabled:a,apiKey:l}}),b=he(o.outputType,p);yield{type:"context_ready",outputType:b};let w=fe(g.skills,p,b),$=Be(g,b,w.map(d=>d.skill));if(!await pe(l)){yield{type:"error",error:"No credentials configured. Run `agentx model` to set up."};return}let C=me(s,l),S=i||ce()?.model,O=ke(C),M=o.maxSteps??(O?20:5),k=[...o.sessionMessages||[],{role:"user",content:p}];if(O){let d=new se,P,f,W=(async()=>{try{P=await xe({provider:C,systemPrompt:$,messages:[{role:"system",content:$},...k],providerOptions:{model:S,maxTokens:8192},cwd:t,maxIterations:M,enabledTools:g.config.agentic.enabledTools.filter(m=>!g.config.agentic.disabledTools.includes(m)),interactive:x,overwrite:n,dryRun:r,onProgress:m=>{m.type==="text_delta"&&d.push({type:"text_delta",text:m.text}),m.type==="iteration_start"&&d.push({type:"iteration",iteration:m.iteration}),m.type==="tool_call"&&d.push({type:"tool_call",name:m.name,id:m.id}),m.type==="tool_result"&&d.push({type:"tool_result",name:m.name,id:m.id,is_error:m.is_error}),m.type==="files_created"&&d.push({type:"step_complete",step:0,filesCount:m.files.length})}})}catch(m){f=m}finally{d.close()}})();for await(let m of d)yield m;if(await W,f){yield{type:"error",error:f instanceof Error?f.message:String(f)};return}if(!P){yield{type:"error",error:"Agentic loop failed without a result"};return}yield{type:"done",result:{content:P.content,files:P.files,tokensUsed:P.tokensUsed,followUp:P.followUp}};let{content:E}=P;if(c.has("post:response")){let m=await c.execute("post:response",{event:"post:response",content:E,task:p,cwd:t});if(m.blocked){yield{type:"error",error:m.message||"Blocked by post:response hook"};return}m.modified?.content&&(E=String(m.modified.content))}if(P.followUp&&x){yield{type:"generate_result",result:{files:{written:[],skipped:[],errors:[]},content:E,outputType:b,followUp:P.followUp,tokensUsed:P.tokensUsed}};return}let z=new Map;for(let m of P.files)z.set(m.path,m);let le=ne(b,g.techStack,o.outputDir),V=await oe(Array.from(z.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:le}),H;if(o.heal!==!1&&!r&&V.written.length>0){let{HealEngine:m}=await import("./heal-UV5A6B5T.js");H=await new m(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(V.written,p)}c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:E,cwd:t}),yield{type:"generate_result",result:{files:V,content:E,outputType:b,tokensUsed:P.tokensUsed,healResult:H}};return}let h=[{role:"system",content:$},...k],j=[],_=0,y="",U,A=0;A++,v.step(A,`Starting generation (model: ${S||"default"})`);let T;if(C.stream){let d="",P;for await(let f of C.stream(h,{model:S,maxTokens:8192}))yield f,f.type==="text_delta"&&(d+=f.text),f.type==="done"&&(P=f.result);T=P||{content:d,files:[],tokensUsed:0}}else{let d=await C.generate(h,{model:S,maxTokens:8192});d.content&&(yield{type:"text_delta",text:d.content}),yield{type:"done",result:d},T=d}_+=T.tokensUsed||0,y=T.content;let I=T.tokensUsed||0,u=S||"claude-sonnet-4-20250514",L=Math.round(I*.3),ie=I-L;if(X.recordStep(A,u,L,ie),v.api("generate",u,I),v.step(A,`Generated ${T.files.length} file(s), ${I} tokens`),T.files.length&&j.push(...T.files),T.followUp&&(U=T.followUp),yield{type:"step_complete",step:A,filesCount:T.files.length},!U&&(y.includes("[CONTINUE]")||y.includes("Next, I'll")||y.includes("Now let me")||y.includes("I'll also generate"))&&T.files.length>0){let P=T.files.map(f=>`Created: ${f.path}${f.description?` \u2014 ${f.description}`:""}`).join(`
|
|
49
49
|
`);for(h.push({role:"assistant",content:y+(P?`
|
|
50
50
|
|
|
51
51
|
Files created:
|
|
@@ -53,7 +53,7 @@ ${P}`:"")}),h.push({role:"user",content:"Continue generating the remaining files
|
|
|
53
53
|
`);h.push({role:"assistant",content:f.content+(H?`
|
|
54
54
|
|
|
55
55
|
Files created:
|
|
56
|
-
${H}`:"")}),h.push({role:"user",content:"Continue generating the remaining files. Build on what you've already created. When finished, do not include [CONTINUE] in your response."})}}if(c.has("post:response")){let d=await c.execute("post:response",{event:"post:response",content:y,task:p,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by post:response hook"};return}d.modified?.content&&(y=String(d.modified.content))}if(U&&x){yield{type:"generate_result",result:{files:{written:[],skipped:[],errors:[]},content:y,outputType:b,followUp:U,tokensUsed:_}};return}let ve=new Map;for(let d of j)ve.set(d.path,d);let ze=ne(b,g.techStack,o.outputDir),ae=await oe(Array.from(ve.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:ze}),B;if(o.heal!==!1&&!r&&ae.written.length>0){let{HealEngine:d}=await import("./heal-
|
|
56
|
+
${H}`:"")}),h.push({role:"user",content:"Continue generating the remaining files. Build on what you've already created. When finished, do not include [CONTINUE] in your response."})}}if(c.has("post:response")){let d=await c.execute("post:response",{event:"post:response",content:y,task:p,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by post:response hook"};return}d.modified?.content&&(y=String(d.modified.content))}if(U&&x){yield{type:"generate_result",result:{files:{written:[],skipped:[],errors:[]},content:y,outputType:b,followUp:U,tokensUsed:_}};return}let ve=new Map;for(let d of j)ve.set(d.path,d);let ze=ne(b,g.techStack,o.outputDir),ae=await oe(Array.from(ve.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:ze}),B;if(o.heal!==!1&&!r&&ae.written.length>0){let{HealEngine:d}=await import("./heal-UV5A6B5T.js");B=await new d(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(ae.written,p),!B.healed&&B.error&&await c.execute("on:error",{event:"on:error",error:new Error(B.error),task:p,cwd:t})}c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:y,cwd:t}),yield{type:"generate_result",result:{files:ae,content:y,outputType:b,tokensUsed:_,healResult:B}}}function Be(o,e,t){let n=[];n.push(`You are agentx, an agentic code generation tool. You generate high-quality, production-ready output for any tech stack.
|
|
57
57
|
|
|
58
58
|
Your primary tool is \`create_files\` \u2014 use it to output all generated code, documents, and configs as files.
|
|
59
59
|
If the request is ambiguous or you need critical information to proceed correctly, use \`ask_user\` to ask a clarifying question.
|
|
@@ -103,4 +103,4 @@ ${o.projectInstructions}`),o.memoryContext&&n.push(o.memoryContext),n.push(`# Ou
|
|
|
103
103
|
Generate output appropriate for: ${e}. Use the \`create_files\` tool to output all files.`),n.join(`
|
|
104
104
|
|
|
105
105
|
`)}export{Se as a,pt as b,dt as c,Re as d,Ae as e,$e as f,Ie as g,he as h,Oe as i,Ue as j,ye as k,ee as l,N as m,Y as n,Ne as o,be as p,we as q,Q as r,qe as s,Ro as t,Ao as u};
|
|
106
|
-
//# sourceMappingURL=chunk-
|
|
106
|
+
//# sourceMappingURL=chunk-F73GPYCO.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import{a as c,b as w,d as x}from"./chunk-M7HKBG3V.js";import{z as u}from"zod";var f=["pre:generate","post:generate","pre:file-write","post:file-write","pre:prompt","post:response","pre:command","on:error","pre:tool-call","post:tool-call","pre:channel-message","post:channel-message","pre:a2a-task","pre:cron-run","post:cron-run"],$=["pre:generate","pre:file-write","pre:prompt","post:response","pre:command","pre:tool-call","pre:channel-message","post:channel-message","pre:a2a-task","pre:cron-run"],S=u.object({name:u.string(),type:u.enum(["command","prompt","script"]),command:u.string().optional(),prompt:u.string().optional(),provider:u.enum(["claude-code","claude","openai","ollama","custom"]).optional(),model:u.string().optional(),script:u.string().optional(),priority:u.number().default(100),enabled:u.boolean().default(!0)});var E={"claude-sonnet":{input:3,output:15},"claude-opus":{input:15,output:75},"claude-haiku":{input:.25,output:1.25}};function O(r){let o=r.toLowerCase();return o.includes("opus")?"claude-opus":o.includes("haiku")?"claude-haiku":"claude-sonnet"}var y=class{steps=[];models=new Map;recordStep(o,e,t,n){let s=O(e),i=E[s]||E["claude-sonnet"],p=t/1e6*i.input+n/1e6*i.output;this.steps.push({step:o,model:e,inputTokens:t,outputTokens:n,cost:p,timestamp:Date.now()});let a=this.models.get(e)||{inputTokens:0,outputTokens:0,cost:0,steps:0};a.inputTokens+=t,a.outputTokens+=n,a.cost+=p,a.steps++,this.models.set(e,a)}getSummary(){let o=0,e=0,t=0;for(let s of this.steps)o+=s.inputTokens,e+=s.outputTokens,t+=s.cost;let n={};for(let[s,i]of this.models)n[s]={...i};return{totalInputTokens:o,totalOutputTokens:e,totalTokens:o+e,totalCost:t,steps:[...this.steps],models:n}}reset(){this.steps=[],this.models.clear()}},D=new y;import l from"chalk";var d=!1;function R(r){d=r}function U(){return d}function k(){return new Date().toISOString().slice(11,23)}var g={log(...r){d&&console.log(l.dim(`[${k()}]`),...r)},step(r,o){d&&console.log(l.dim(`[${k()}]`),l.blue(`[step ${r}]`),o)},hook(r,o,e){d&&console.log(l.dim(`[${k()}]`),l.magenta("[hook]"),`${r} (${o}ms) \u2192 ${e}`)},api(r,o,e){if(!d)return;let t=e?` (${e} tokens)`:"";console.log(l.dim(`[${k()}]`),l.yellow("[api]"),`${r} \u2192 ${o}${t}`)},tokens(r,o,e){d&&console.log(l.dim(`[${k()}]`),l.green("[tokens]"),`in: ${r.toLocaleString()}, out: ${o.toLocaleString()}, cost: $${e.toFixed(4)}`)},context(r,o){d&&console.log(l.dim(`[${k()}]`),l.cyan(`[${r}]`),o)}};function j(r,o){let e=[];if(e.push(`# Session: ${r.id}`),e.push(""),e.push(`- **Created**: ${r.createdAt}`),e.push(`- **Updated**: ${r.updatedAt}`),e.push(`- **CWD**: ${r.cwd}`),e.push(`- **Messages**: ${r.messages.length}`),e.push(`- **Tokens**: ${r.tokensUsed.toLocaleString()}`),e.push(""),r.filesGenerated.length){e.push("## Files Generated"),e.push("");for(let t of r.filesGenerated)e.push(`- \`${t}\``);e.push("")}if(r.messages.length){e.push("## Conversation"),e.push("");for(let t of r.messages){if(t.role==="system")continue;let n=t.role==="user"?"**User**":"**Assistant**";e.push(`### ${n}`),e.push(""),t.role,e.push(t.content),e.push("")}}if(o){if(e.push("## Cost Summary"),e.push(""),e.push(`- **Total tokens**: ${o.totalTokens.toLocaleString()}`),e.push(` - Input: ${o.totalInputTokens.toLocaleString()}`),e.push(` - Output: ${o.totalOutputTokens.toLocaleString()}`),e.push(`- **Total cost**: $${o.totalCost.toFixed(4)}`),e.push(""),Object.keys(o.models).length){e.push("### Per Model"),e.push(""),e.push("| Model | Input | Output | Cost | Steps |"),e.push("|-------|-------|--------|------|-------|");for(let[t,n]of Object.entries(o.models))e.push(`| ${t} | ${n.inputTokens.toLocaleString()} | ${n.outputTokens.toLocaleString()} | $${n.cost.toFixed(4)} | ${n.steps} |`);e.push("")}if(o.steps.length){e.push("### Per Step"),e.push(""),e.push("| Step | Model | Input | Output | Cost |"),e.push("|------|-------|-------|--------|------|");for(let t of o.steps)e.push(`| ${t.step} | ${t.model} | ${t.inputTokens.toLocaleString()} | ${t.outputTokens.toLocaleString()} | $${t.cost.toFixed(4)} |`);e.push("")}}return e.join(`
|
|
2
|
-
`)}import{execa as N}from"execa";var h=class{hooks=new Map;register(o,e){if(!e.enabled)return;let t=this.createHandler(e),n={event:o,definition:e,handler:t},s=this.hooks.get(o)||[];s.push(n),s.sort((i,p)=>i.definition.priority-p.definition.priority),this.hooks.set(o,s)}async execute(o,e){let t=this.hooks.get(o);if(!t?.length)return{};let n=$.includes(o),s={};for(let i of t){let p=Date.now();try{let a=await i.handler({...e,...s}),m=Date.now()-p;if(a.modified&&(s={...s,...a.modified}),n&&a.blocked)return g.hook(i.definition.name,m,"blocked"),{blocked:!0,message:a.message||`Blocked by hook: ${i.definition.name}`,modified:s};g.hook(i.definition.name,m,"ok")}catch(a){let m=Date.now()-p;if(g.hook(i.definition.name,m,`error: ${a.message}`),c.warn(`Hook "${i.definition.name}" failed: ${a.message}`),n)return{blocked:!0,message:`Hook "${i.definition.name}" errored: ${a.message}`}}}return{modified:Object.keys(s).length?s:void 0}}has(o){return!!this.hooks.get(o)?.length}clear(){this.hooks.clear()}createHandler(o){switch(o.type){case"command":return this.createCommandHandler(o);case"script":return this.createScriptHandler(o);case"prompt":return this.createPromptHandler(o);default:throw new Error(`Unknown hook type: ${o.type}`)}}createCommandHandler(o){return async e=>{if(!o.command)return{};let t=o.command;t=t.replace(/\{\{(\w+)\}\}/g,(s,i)=>String(e[i]??""));let n=await N("sh",["-c",t],{cwd:e.cwd||process.cwd(),reject:!1,timeout:6e4,env:process.env});return n.exitCode!==0?{blocked:!0,message:n.stderr||n.stdout||`Command hook "${o.name}" failed`}:{}}}createScriptHandler(o){return async e=>{if(!o.script)return{};let n=await import(o.script.startsWith("/")?o.script:`${e.cwd||process.cwd()}/${o.script}`),s=n.default||n.handler||n;return typeof s=="function"?await s(e):{}}}createPromptHandler(o){return async e=>{if(!o.prompt)return{};let t=o.provider||w()?.provider||"claude-code",n=x();if(!n&&t!=="claude-code")return c.warn(`Prompt hook "${o.name}" skipped: no credentials available for provider "${t}"`),{};try{let{createProvider:s}=await import("./providers-
|
|
2
|
+
`)}import{execa as N}from"execa";var h=class{hooks=new Map;register(o,e){if(!e.enabled)return;let t=this.createHandler(e),n={event:o,definition:e,handler:t},s=this.hooks.get(o)||[];s.push(n),s.sort((i,p)=>i.definition.priority-p.definition.priority),this.hooks.set(o,s)}async execute(o,e){let t=this.hooks.get(o);if(!t?.length)return{};let n=$.includes(o),s={};for(let i of t){let p=Date.now();try{let a=await i.handler({...e,...s}),m=Date.now()-p;if(a.modified&&(s={...s,...a.modified}),n&&a.blocked)return g.hook(i.definition.name,m,"blocked"),{blocked:!0,message:a.message||`Blocked by hook: ${i.definition.name}`,modified:s};g.hook(i.definition.name,m,"ok")}catch(a){let m=Date.now()-p;if(g.hook(i.definition.name,m,`error: ${a.message}`),c.warn(`Hook "${i.definition.name}" failed: ${a.message}`),n)return{blocked:!0,message:`Hook "${i.definition.name}" errored: ${a.message}`}}}return{modified:Object.keys(s).length?s:void 0}}has(o){return!!this.hooks.get(o)?.length}clear(){this.hooks.clear()}createHandler(o){switch(o.type){case"command":return this.createCommandHandler(o);case"script":return this.createScriptHandler(o);case"prompt":return this.createPromptHandler(o);default:throw new Error(`Unknown hook type: ${o.type}`)}}createCommandHandler(o){return async e=>{if(!o.command)return{};let t=o.command;t=t.replace(/\{\{(\w+)\}\}/g,(s,i)=>String(e[i]??""));let n=await N("sh",["-c",t],{cwd:e.cwd||process.cwd(),reject:!1,timeout:6e4,env:process.env});return n.exitCode!==0?{blocked:!0,message:n.stderr||n.stdout||`Command hook "${o.name}" failed`}:{}}}createScriptHandler(o){return async e=>{if(!o.script)return{};let n=await import(o.script.startsWith("/")?o.script:`${e.cwd||process.cwd()}/${o.script}`),s=n.default||n.handler||n;return typeof s=="function"?await s(e):{}}}createPromptHandler(o){return async e=>{if(!o.prompt)return{};let t=o.provider||w()?.provider||"claude-code",n=x();if(!n&&t!=="claude-code")return c.warn(`Prompt hook "${o.name}" skipped: no credentials available for provider "${t}"`),{};try{let{createProvider:s}=await import("./providers-AVYG63KK.js"),i=s(t,n?.token),p=o.prompt;p=p.replace(/\{\{(\w+)\}\}/g,(A,C)=>String(e[C]??""));let a=`You are a hook validator for agentx. Analyze the following context and respond with ONLY a JSON object (no markdown, no code fences).
|
|
3
3
|
|
|
4
4
|
Response format:
|
|
5
5
|
{"action": "allow", "message": "optional explanation"}
|
|
@@ -9,4 +9,4 @@ OR
|
|
|
9
9
|
{"action": "allow", "message": "optional", "modified": {"key": "new value"}}
|
|
10
10
|
|
|
11
11
|
The "modified" field is optional and can contain updated values to pass forward.`,v=(await i.generate([{role:"system",content:a},{role:"user",content:p}],{model:o.model,maxTokens:1024})).content.trim().match(/\{[\s\S]*\}/);if(!v)return c.warn(`Prompt hook "${o.name}": LLM response was not valid JSON, allowing`),{};let H=JSON.parse(v[0]);return H.action==="block"?{blocked:!0,message:H.message||`Blocked by prompt hook: ${o.name}`}:H.modified?{modified:H.modified}:{}}catch(s){return c.warn(`Prompt hook "${o.name}" failed: ${s.message}`),{}}}}};import{existsSync as T,readFileSync as P,readdirSync as L}from"fs";import b from"path";function M(r,o){_(r,o),I(r,o)}function _(r,o){let e=b.join(r,"agentx.config.json");if(T(e))try{let t=JSON.parse(P(e,"utf8"));if(!t.hooks)return;for(let[n,s]of Object.entries(t.hooks)){if(!f.includes(n)){c.warn(`Unknown hook event in config: ${n}`);continue}let i=n;if(Array.isArray(s))for(let p of s)try{let a=S.parse(p);o.register(i,a)}catch(a){c.warn(`Invalid hook definition for ${i}: ${a.message}`)}}}catch(t){c.warn(`Failed to load hooks from config: ${t.message}`)}}function I(r,o){let e=b.join(r,".agentx","hooks");if(T(e))try{let t=L(e).filter(n=>n.endsWith(".ts")||n.endsWith(".js")||n.endsWith(".mjs"));for(let n of t){let s=n.replace(/\.(ts|js|mjs)$/,"").split(".");if(s.length<2){c.warn(`Hook file "${n}" should be named <event>.<name>.<ext>`);continue}let i=s[0],p=s.slice(1).join("."),a=i.replace(/-/g,":");if(!f.includes(a)){let m=i.replace("-",":");if(!f.includes(m)){c.warn(`Unknown hook event in filename: ${n}`);continue}o.register(m,{name:p,type:"script",script:b.join(e,n),priority:100,enabled:!0});continue}o.register(a,{name:p,type:"script",script:b.join(e,n),priority:100,enabled:!0})}}catch(t){c.warn(`Failed to load hooks from directory: ${t.message}`)}}var le=new h;export{f as a,$ as b,y as c,D as d,R as e,U as f,g,j as h,h as i,M as j,le as k};
|
|
12
|
-
//# sourceMappingURL=chunk-
|
|
12
|
+
//# sourceMappingURL=chunk-Z4GC5D6D.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{d as N,e as H,p as L,q as z}from"./chunk-
|
|
2
|
+
import{d as N,e as H,p as L,q as z}from"./chunk-AIBBZF4E.js";import"./chunk-Z4GC5D6D.js";import"./chunk-M7HKBG3V.js";import{a as K}from"./chunk-4YCH6IZV.js";import{Command as ne}from"commander";import{Command as X}from"commander";import c from"chalk";var x=new X().name("daemon").description("manage the agentx daemon \u2014 start, stop, status, logs");x.command("start").description("start the daemon (default if no subcommand)").option("-c, --config <path>","path to agentx.json").option("-d, --detach","run in background (detached)").option("--port <port>","override bind port").action(async e=>{if(e.detach){let{spawn:o}=await import("child_process"),s=["dist/cli.js","daemon","start"];e.config&&s.push("-c",e.config),e.port&&s.push("--port",e.port);let t=o("node",s,{detached:!0,stdio:["ignore","ignore","ignore"],cwd:process.cwd()});t.unref();let{writeFileSync:i}=await import("fs");i("/tmp/agentx-daemon.pid",String(t.pid)),console.log(c.green(`Daemon started in background (PID: ${t.pid})`)),console.log(c.dim(" Logs: tail -f /tmp/agentx-daemon.log")),console.log(c.dim(" Stop: agentx daemon stop"));return}await new L(e.config).start()});x.command("stop").description("stop the running daemon").action(async()=>{let{readFileSync:e,existsSync:n}=await import("fs"),o="/tmp/agentx-daemon.pid";n(o)||console.log(c.yellow("No daemon PID file found. Trying to find process..."));try{if(n(o)){let t=parseInt(e(o,"utf-8").trim(),10);process.kill(t,"SIGTERM"),console.log(c.green(`Daemon stopped (PID: ${t})`));return}}catch{}let{execSync:s}=await import("child_process");try{s("pkill -f 'node dist/cli.js daemon'",{stdio:"ignore"}),console.log(c.green("Daemon stopped"))}catch{console.log(c.yellow("No daemon process found"))}});x.command("status").alias("st").description("show daemon status, agents, crons, and mesh").option("-c, --config <path>","path to agentx.json").option("--json","output as JSON").action(async e=>{try{let n=N(e.config),[o,s]=n.node.bind.split(":"),t=`http://${o||"127.0.0.1"}:${s}/health`,l=await(await fetch(t,{signal:AbortSignal.timeout(3e3)})).json();if(e.json){console.log(JSON.stringify(l,null,2));return}console.log(),console.log(c.bold(` ${l.node.name}`)+c.dim(` (${l.node.id})`)),console.log(c.green(" Status: running")+c.dim(` \u2014 uptime ${Q(l.uptime)}`)),console.log(),console.log(c.bold(" Agents:"));for(let r of l.agents){let f=r.active>0?c.yellow(` [${r.active} active]`):"",v=r.errors>0?c.red(` (${r.errors} errors)`):"";console.log(` ${c.cyan(r.name)} ${c.dim(`(${r.tier})`)}${f}${v}`),console.log(c.dim(` ${r.workspace}`))}let d=l.crons.filter(r=>r.enabled);if(l.crons.length){console.log(),console.log(c.bold(` Crons: ${d.length} enabled / ${l.crons.length} total`));for(let r of l.crons){let f=r.enabled?c.green("\u25CF"):c.dim("\u25CB"),v=r.nextRun?c.dim(` next: ${new Date(r.nextRun).toLocaleTimeString()}`):"";console.log(` ${f} ${r.id}${v}`)}}if(l.mesh?.length){console.log(),console.log(c.bold(" Mesh:"));for(let r of l.mesh){let f=r.healthy?c.green("\u25CF"):c.red("\u25CF"),v=r.skills?.length?c.dim(` (${r.skills.length} agents)`):"";console.log(` ${f} ${r.peer} ${c.dim(r.peerUrl)}${v}`)}}console.log()}catch(n){if(n.cause?.code==="ECONNREFUSED"||n.name==="TimeoutError")console.log(c.red(" Daemon is not running")),console.log(c.dim(" Start with: agentx daemon start"));else try{let o=N(e.config),s=H(o);if(console.log(),console.log(c.bold(` ${o.node.name}`)+c.dim(` (${o.node.id})`)),console.log(c.yellow(" Status: stopped")),console.log(c.dim(` ${Object.keys(o.agents).length} agents, ${Object.keys(o.crons).length} crons configured`)),s.length){console.log();for(let t of s)console.log(c.yellow(` \u26A0 ${t}`))}console.log()}catch(o){console.log(c.red(` ${o.message}`))}}});x.command("logs").description("tail daemon logs").option("-n, --lines <n>","number of lines","50").option("-f, --follow","follow log output",!1).action(async e=>{let{execSync:n,spawn:o}=await import("child_process"),s="/tmp/agentx-daemon.log",{existsSync:t}=await import("fs");if(!t(s)){console.log(c.yellow("No log file found at /tmp/agentx-daemon.log"));return}if(e.follow){let i=o("tail",["-f","-n",e.lines,s],{stdio:"inherit"});process.on("SIGINT",()=>{i.kill(),process.exit(0)})}else n(`tail -n ${e.lines} ${s}`,{stdio:"inherit"})});x.command("send <agent> <message...>").description("send a task to an agent via the daemon API").option("-c, --config <path>","path to agentx.json").option("--peer <peer>","send to a mesh peer's agent").option("--json","output raw JSON response").action(async(e,n,o)=>{let s=n.join(" ");try{let t=N(o.config),[i,l]=t.node.bind.split(":"),d=`http://${i||"127.0.0.1"}:${l}`,r,f;o.peer?(r=`${d}/mesh/task`,f={peer:o.peer,message:s,agent:e}):(r=`${d}/task`,f={agent:e,message:s}),console.log(c.dim(` Sending to ${o.peer?`${o.peer}/${e}`:e}...`));let $=await(await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(f)})).json();o.json?console.log(JSON.stringify($,null,2)):$.error?console.log(c.red(` Error: ${$.error}`)):(console.log(),console.log($.content||$.response||"No response"),$.duration&&console.log(c.dim(`
|
|
3
3
|
(${($.duration/1e3).toFixed(1)}s)`)))}catch(t){console.log(c.red(` Failed: ${t.message}`)),console.log(c.dim(" Is the daemon running? Try: agentx daemon status"))}});x.command("deploy <host>").description("deploy agentx to a remote server via rsync").option("-i, --identity <key>","SSH identity file").option("-u, --user <user>","SSH user","clawd").option("-p, --path <path>","remote agentx path","~/agentx").option("--restart","restart remote daemon after deploy",!1).action(async(e,n)=>{let{execSync:o}=await import("child_process"),s=n.identity?`-e "ssh -i ${n.identity}"`:"",t=`${n.user}@${e}:${n.path}/dist/`;console.log(c.dim(` Deploying to ${n.user}@${e}:${n.path}...`));try{if(o(`rsync -avz --delete ${s} dist/ ${t}`,{stdio:"inherit",cwd:process.cwd()}),console.log(c.green(" Deploy complete")),n.restart){console.log(c.dim(" Restarting remote daemon..."));let i=n.identity?`ssh -i ${n.identity}`:"ssh";o(`${i} ${n.user}@${e} "pkill -f 'node dist/cli.js daemon' 2>/dev/null; sleep 2; cd ${n.path} && nohup node dist/cli.js daemon start > /tmp/agentx-daemon.log 2>&1 &"`,{stdio:"inherit"}),console.log(c.green(" Remote daemon restarted"))}}catch(i){console.log(c.red(` Deploy failed: ${i.message}`))}});x.action(async e=>{await new L(e.config).start()});function Q(e){return e<60?`${Math.round(e)}s`:e<3600?`${Math.round(e/60)}m`:e<86400?`${Math.round(e/3600)}h ${Math.round(e%3600/60)}m`:`${Math.round(e/86400)}d ${Math.round(e%86400/3600)}h`}import{Command as V}from"commander";import h from"chalk";import{existsSync as I,readFileSync as Z,writeFileSync as _,mkdirSync as G}from"fs";import{resolve as j}from"path";var q=new V().name("init").description("initialize agentx configuration in the current directory").option("--force","overwrite existing config").action(async e=>{let n=process.cwd(),o=j(n,"agentx.json"),s=j(n,".env"),t=j(n,".agentx/sessions");if(console.log(),console.log(h.bold(" agentx init")),console.log(),I(o)&&!e.force){console.log(h.yellow(" agentx.json already exists. Use --force to overwrite.")),console.log();return}let i=[j(n,"agentx.example.json"),j(n,"node_modules/agentix-cli/agentx.example.json")],l;for(let r of i)if(I(r)){l=Z(r,"utf-8");break}l||(l=JSON.stringify({node:{id:K("os").hostname().toLowerCase().replace(/[^a-z0-9-]/g,"-"),name:K("os").hostname(),bind:"127.0.0.1:18800"},providers:{claude:{apiKey:"${ANTHROPIC_API_KEY}"}},agents:{assistant:{name:"Assistant",workspace:n,tier:"claude-code",model:"claude-sonnet-4-6",mentions:["@assistant","assistant"],maxConcurrent:2,systemPrompt:"You are a helpful assistant.",permissionMode:"default"}},channels:{telegram:{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},whatsapp:{enabled:!1}},crons:{},mesh:{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}}},null,2)),_(o,l),console.log(h.green(" \u2713 Created agentx.json")),I(s)||(_(s,["# AgentX environment variables","# ANTHROPIC_API_KEY=sk-ant-...","# TG_BOT_TOKEN=123456:ABC...","# MESH_TOKEN=your-mesh-secret",""].join(`
|
|
4
4
|
`)),console.log(h.green(" \u2713 Created .env template"))),I(t)||(G(t,{recursive:!0}),console.log(h.green(" \u2713 Created .agentx/sessions/")));let d=j(n,".claude");I(d)||(G(d,{recursive:!0}),console.log(h.green(" \u2713 Created .claude/"))),console.log(),console.log(h.bold(" Next steps:")),console.log(` 1. Edit ${h.cyan("agentx.json")} \u2014 configure agents, channels, crons`),console.log(` 2. Edit ${h.cyan(".env")} \u2014 add API keys and bot tokens`),console.log(` 3. Run ${h.cyan("agentx daemon start")} \u2014 start the daemon`),console.log(` 4. Run ${h.cyan("agentx daemon status")} \u2014 verify everything`),console.log()});import{Command as S}from"commander";import a from"chalk";import k from"prompts";import{readFileSync as R,writeFileSync as B,existsSync as y,mkdirSync as C,cpSync as W,readdirSync as ee}from"fs";import{resolve as m,join as T}from"path";function p(){let e=m(process.cwd(),"agentx.json");if(!y(e))throw new Error("No agentx.json found. Run: agentx init");return JSON.parse(R(e,"utf-8"))}function w(e){B(m(process.cwd(),"agentx.json"),JSON.stringify(e,null,2))}var P=new S().name("agent").description("manage agents \u2014 add, list, remove");P.command("list").alias("ls").description("list configured agents").action(()=>{let e=p();console.log();for(let[n,o]of Object.entries(e.agents||{})){let s=o.mentions?.join(", ")||"";console.log(` ${a.cyan(n)} \u2014 ${o.name} (${o.tier})`),console.log(a.dim(` workspace: ${o.workspace}`)),s&&console.log(a.dim(` mentions: ${s}`))}console.log()});P.command("add").description("add a new agent interactively").action(async()=>{let e=p(),n=await k([{type:"text",name:"id",message:"Agent ID (kebab-case)",validate:d=>/^[a-z0-9-]+$/.test(d)||"Use lowercase, numbers, hyphens"},{type:"text",name:"name",message:"Display name"},{type:"text",name:"workspace",message:"Workspace path",initial:m(process.cwd(),"agents/")},{type:"select",name:"tier",message:"Execution tier",choices:[{title:"claude-code (subscription, full features)",value:"claude-code"},{title:"sdk (API key, programmatic)",value:"sdk"},{title:"orchestrator (any provider)",value:"orchestrator"}]},{type:"text",name:"model",message:"Model",initial:"claude-sonnet-4-6"},{type:"list",name:"mentions",message:"Mention patterns (comma-separated)",separator:","},{type:"number",name:"maxConcurrent",message:"Max concurrent tasks",initial:2},{type:"text",name:"systemPrompt",message:"System prompt"}]);if(!n.id)return;let o=n.workspace.endsWith(n.id)?n.workspace:T(n.workspace,n.id);C(m(o,".claude/skills"),{recursive:!0});let s=`# ${n.name}
|
|
5
5
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a}from"./chunk-X7UN6JAA.js";import"./chunk-SFQUP3BP.js";import"./chunk-MGMZNJCE.js";import"./chunk-M7HKBG3V.js";import"./chunk-
|
|
2
|
-
//# sourceMappingURL=heal-
|
|
1
|
+
import{a}from"./chunk-X7UN6JAA.js";import"./chunk-SFQUP3BP.js";import"./chunk-MGMZNJCE.js";import"./chunk-M7HKBG3V.js";import"./chunk-4YCH6IZV.js";export{a as HealEngine};
|
|
2
|
+
//# sourceMappingURL=heal-UV5A6B5T.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1868,6 +1868,11 @@ interface AgentTask {
|
|
|
1868
1868
|
channel?: string;
|
|
1869
1869
|
sender?: string;
|
|
1870
1870
|
group?: string;
|
|
1871
|
+
/** Attached media file (image, audio, video, document) */
|
|
1872
|
+
mediaPath?: string;
|
|
1873
|
+
mediaType?: string;
|
|
1874
|
+
/** Text of the message being replied to */
|
|
1875
|
+
replyToText?: string;
|
|
1871
1876
|
conversationHistory?: Array<{
|
|
1872
1877
|
role: string;
|
|
1873
1878
|
content: string;
|
|
@@ -1970,7 +1975,13 @@ interface IncomingMessage {
|
|
|
1970
1975
|
};
|
|
1971
1976
|
text: string;
|
|
1972
1977
|
replyTo?: string;
|
|
1978
|
+
replyToText?: string;
|
|
1973
1979
|
timestamp: Date;
|
|
1980
|
+
media?: {
|
|
1981
|
+
path: string;
|
|
1982
|
+
type: string;
|
|
1983
|
+
fileName?: string;
|
|
1984
|
+
};
|
|
1974
1985
|
raw?: unknown;
|
|
1975
1986
|
resolvedAgent?: string;
|
|
1976
1987
|
}
|
|
@@ -2005,6 +2016,7 @@ declare class MessageRouter {
|
|
|
2005
2016
|
private channels;
|
|
2006
2017
|
private hooks?;
|
|
2007
2018
|
private mesh?;
|
|
2019
|
+
private groupLogs;
|
|
2008
2020
|
private log;
|
|
2009
2021
|
constructor(registry: AgentRegistry, config: DaemonConfig, hooks?: HookRegistry, log?: (...args: unknown[]) => void);
|
|
2010
2022
|
setMesh(mesh: A2AMesh): void;
|
|
@@ -2012,11 +2024,13 @@ declare class MessageRouter {
|
|
|
2012
2024
|
startAll(): Promise<void>;
|
|
2013
2025
|
stopAll(): Promise<void>;
|
|
2014
2026
|
private handleMessage;
|
|
2027
|
+
private static readonly MAX_BOT_CHAIN_DEPTH;
|
|
2015
2028
|
/**
|
|
2016
|
-
*
|
|
2017
|
-
*
|
|
2029
|
+
* Bot-to-bot conversation chain.
|
|
2030
|
+
* When an agent's response mentions another agent, route it and continue
|
|
2031
|
+
* the chain if the target agent also mentions someone (up to MAX depth).
|
|
2018
2032
|
*/
|
|
2019
|
-
private
|
|
2033
|
+
private handleBotToBotChain;
|
|
2020
2034
|
private adapterSend;
|
|
2021
2035
|
private adapterEdit;
|
|
2022
2036
|
private adapterReact;
|
|
@@ -2026,6 +2040,15 @@ declare class MessageRouter {
|
|
|
2026
2040
|
* Searches peer agent cards for mention matches.
|
|
2027
2041
|
*/
|
|
2028
2042
|
private handleViaMesh;
|
|
2043
|
+
/**
|
|
2044
|
+
* Log a message in the group conversation history.
|
|
2045
|
+
*/
|
|
2046
|
+
private logGroupMessage;
|
|
2047
|
+
/**
|
|
2048
|
+
* Build group conversation context for an agent.
|
|
2049
|
+
* Returns recent messages from the group so the agent knows what's been discussed.
|
|
2050
|
+
*/
|
|
2051
|
+
private buildGroupContext;
|
|
2029
2052
|
private getAccountForAgent;
|
|
2030
2053
|
private resolveAgent;
|
|
2031
2054
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{a as de,b as pe,c as pt,d as gt,e as mt,f as ut,g as ft,h as ht,i as yt,j as kt,k as wt,l as St,m as vt,n as xt,o as bt,p as Ct,q as Pt}from"./chunk-
|
|
1
|
+
import{a as de,b as pe,c as pt,d as gt,e as mt,f as ut,g as ft,h as ht,i as yt,j as kt,k as wt,l as St,m as vt,n as xt,o as bt,p as Ct,q as Pt}from"./chunk-AIBBZF4E.js";import{a as H}from"./chunk-X7UN6JAA.js";import{a as Me,b as Ee,c as Oe,d as Ke,e as Be,f as We,g as ze,h as te,i as J,j as ot,k as rt,l as it,m as R,n as ne,o as at,p as ct,q as lt,r as dt,s as T,t as b,u as j}from"./chunk-F73GPYCO.js";import{a as Ve,b as Ye,c as Xe,d as F,e as Qe,f as Ze,g as et,h as se,i as tt,j as st,k as nt}from"./chunk-Z4GC5D6D.js";import{a as Z,b as qe,c as _,d as ee}from"./chunk-FRFR27IN.js";import{a as Q,b as x,c as U}from"./chunk-SFQUP3BP.js";import{a as Ne,b as _e,c as Fe,d as Je,e as Ue,f as He,g as G}from"./chunk-MGMZNJCE.js";import{a as m,b as Ie,c as Ge,d as je,e as Le,f as De}from"./chunk-M7HKBG3V.js";import"./chunk-4YCH6IZV.js";import{execa as $t}from"execa";import{existsSync as ge,promises as oe}from"fs";import C from"path";import fe from"node-fetch";async function Rt(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],r=t[1],n=t[2];try{let a=n?`${s}/${r}/${n}`:`${s}/${r}`;await $t("npx",["-y","skills","add",a],{cwd:e,stdio:"pipe"}),m.success(`Installed skill package: ${o}`);let i=C.resolve(e,".skills",`${s}_${r}`);if(ge(i))return await ue(i,o);let c=C.resolve(e,".skills");return ge(c)?await ue(c,o):[]}catch{return m.info(`Fetching skills directly from GitHub: ${s}/${r}`),await Tt(s,r,n,e)}}async function Tt(o,e,t,s){let r=[];try{let n=`https://api.github.com/repos/${o}/${e}/git/trees/main?recursive=1`,a=await fe(n);if(!a.ok)throw new Error(`GitHub API error: ${a.status}`);let c=(await a.json()).tree.filter(l=>l.type==="blob"&&l.path.endsWith("SKILL.md"));if(t){let l=c.find(g=>g.path.includes(`/${t}/`)||g.path===`${t}/SKILL.md`);if(l){let g=await me(o,e,l.path,s);g&&r.push(g)}}else for(let l of c){let g=await me(o,e,l.path,s);g&&r.push(g)}}catch(n){m.error(`Failed to fetch skills from GitHub: ${n.message}`)}return r}async function me(o,e,t,s){try{let r=`https://raw.githubusercontent.com/${o}/${e}/main/${t}`,n=await fe(r);if(!n.ok)return null;let a=await n.text(),i=_(a);if(i){i.source="remote",i.packageId=`${o}/${e}`;let c=C.dirname(t),l=C.resolve(s,".skills",`${o}_${e}`,c);await oe.mkdir(l,{recursive:!0}),await oe.writeFile(C.resolve(l,"SKILL.md"),a),i.path=C.resolve(l,"SKILL.md")}return i}catch{return null}}async function ue(o,e){let t=[],{default:s}=await import("fast-glob"),r=await s.glob("**/SKILL.md",{cwd:o,deep:5});for(let n of r)try{let a=C.resolve(o,n),i=await oe.readFile(a,"utf8"),c=_(i);c&&(c.source="remote",c.path=a,c.packageId=e,t.push(c))}catch{}return t}async function At(o,e,t,s,r){let n=["---",`name: ${o}`,`description: ${e}`];if(s?.length){n.push("tags:");for(let a of s)n.push(` - ${a}`)}if(r?.length){n.push("globs:");for(let a of r)n.push(` - ${a}`)}return n.push("---"),`${n.join(`
|
|
2
2
|
`)}
|
|
3
3
|
|
|
4
|
-
${t}`}async function Mt(o){let{loadLocalSkills:e}=await import("./loader-
|
|
4
|
+
${t}`}async function Mt(o){let{loadLocalSkills:e}=await import("./loader-6VSM6FSY.js");return e(o)}async function Et(o,e,t,s,r){let a=[{role:"system",content:`You are a skill author for the Agent Skills ecosystem (skills.sh).
|
|
5
5
|
You create high-quality SKILL.md files that provide reusable instructions for AI coding agents.
|
|
6
6
|
|
|
7
7
|
A skill is a markdown document with YAML frontmatter that teaches an agent how to perform a specific task.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{e as a,f as b,g as c}from"./chunk-MGMZNJCE.js";import"./chunk-M7HKBG3V.js";import"./chunk-
|
|
2
|
-
//# sourceMappingURL=providers-
|
|
1
|
+
import{e as a,f as b,g as c}from"./chunk-MGMZNJCE.js";import"./chunk-M7HKBG3V.js";import"./chunk-4YCH6IZV.js";export{b as ClaudeCodeProvider,a as ClaudeProvider,c as createProvider};
|
|
2
|
+
//# sourceMappingURL=providers-AVYG63KK.js.map
|
package/package.json
CHANGED
package/dist/agent-CRA5PU6S.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{s as a,t as b,u as c}from"./chunk-KVWUPUR5.js";import"./chunk-PCAYW54Q.js";import"./chunk-FRFR27IN.js";import"./chunk-SFQUP3BP.js";import"./chunk-MGMZNJCE.js";import"./chunk-M7HKBG3V.js";import"./chunk-MDR7SH7F.js";export{a as createAgentContext,b as generate,c as generateStream};
|
|
2
|
-
//# sourceMappingURL=agent-CRA5PU6S.js.map
|
package/dist/chunk-MDR7SH7F.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var d=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+a+'" is not supported')});export{d as a};
|
|
2
|
-
//# sourceMappingURL=chunk-MDR7SH7F.js.map
|
package/dist/chunk-S74N276K.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import{i as X,j as Z}from"./chunk-PCAYW54Q.js";var M=class{baseUrl;token;constructor(e,t){this.baseUrl=e.replace(/\/$/,""),this.token=t}async getAgentCard(){let e=await fetch(`${this.baseUrl}/.well-known/agent-card.json`,{headers:this.headers()});if(!e.ok)throw new Error(`Failed to fetch agent card: ${e.status}`);return e.json()}async sendTask(e,t){let s=await this.rpc("tasks/send",{id:`task-${Date.now().toString(36)}`,message:{role:"user",parts:[{type:"text",text:e}]},metadata:t});if(s.error)throw new Error(`A2A error: ${s.error.message}`);return s.result}async*sendTaskStream(e,t){let s=JSON.stringify({jsonrpc:"2.0",id:1,method:"tasks/sendSubscribe",params:{id:`task-${Date.now().toString(36)}`,message:{role:"user",parts:[{type:"text",text:e}]},metadata:t}}),n=await fetch(this.baseUrl,{method:"POST",headers:{...this.headers(),"Content-Type":"application/json",Accept:"text/event-stream"},body:s});if(!n.ok||!n.body)throw new Error(`A2A stream error: ${n.status}`);let r=n.body.getReader(),i=new TextDecoder,o="";for(;;){let{done:a,value:g}=await r.read();if(a)break;o+=i.decode(g,{stream:!0});let c=o.split(`
|
|
2
|
-
`);o=c.pop()||"";for(let h of c)if(h.startsWith("data: "))try{let u=JSON.parse(h.slice(6));yield{state:u.state,message:u.message?.parts?.[0]?.text,final:u.final}}catch{}}}async getTask(e){let t=await this.rpc("tasks/get",{id:e});if(t.error)throw new Error(`A2A error: ${t.error.message}`);return t.result}async cancelTask(e){let t=await this.rpc("tasks/cancel",{id:e});if(t.error)throw new Error(`A2A error: ${t.error.message}`);return t.result}async rpc(e,t){let s=await fetch(this.baseUrl,{method:"POST",headers:{...this.headers(),"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:Date.now(),method:e,params:t})});if(!s.ok)throw new Error(`A2A HTTP error: ${s.status}`);return s.json()}headers(){let e={};return this.token&&(e.Authorization=`Bearer ${this.token}`),e}};var D=class{peers=new Map;healthTimer;config;log;constructor(e,t=console.error.bind(console,"[mesh]")){this.config=e,this.log=t;for(let s of e.mesh.peers)this.peers.set(s.name,{peer:s,client:new M(s.url,s.token),healthy:!1,agents:[]})}async start(){this.log(`Mesh starting with ${this.peers.size} peer(s)`),await this.discoverAll();let e=this.config.mesh.healthCheck.interval*1e3;this.healthTimer=setInterval(()=>this.discoverAll(),e)}async stop(){this.healthTimer&&clearInterval(this.healthTimer)}async discoverAll(){let e=await Promise.allSettled(Array.from(this.peers.entries()).map(([s,n])=>this.discoverPeer(s,n))),t=Array.from(this.peers.values()).filter(s=>s.healthy).length;this.log(`Discovery complete: ${t}/${this.peers.size} peers healthy`)}async discoverPeer(e,t){let s=this.config.mesh.healthCheck.timeout*1e3;try{let n=new AbortController,r=setTimeout(()=>n.abort(),s),i=await t.client.getAgentCard();clearTimeout(r),t.healthy=!0,t.lastCheck=new Date,t.agentCard=i,t.agents=i.skills||[],this.log(`Peer "${e}" healthy: ${i.name} (${t.agents.length} skills)`)}catch(n){t.healthy=!1,t.lastCheck=new Date,this.log(`Peer "${e}" unreachable: ${n.message}`)}}async sendTask(e,t,s){let n=this.peers.get(e);if(!n)throw new Error(`Unknown peer: ${e}`);if(!n.healthy)throw new Error(`Peer "${e}" is not healthy`);let r=s||n.agents[0]?.id;if(!r)throw new Error(`Peer "${e}" has no agents`);let i=`${n.peer.url}/task`,o={"Content-Type":"application/json"};n.peer.token&&(o.Authorization=`Bearer ${n.peer.token}`);let a=await fetch(i,{method:"POST",headers:o,body:JSON.stringify({agent:r,message:t})});if(!a.ok)throw new Error(`Peer "${e}" /task error: ${a.status}`);let g=await a.json();if(g.error)throw new Error(`Peer "${e}" agent error: ${g.error}`);return g.content||"No response"}findPeerWithSkill(e){for(let t of this.peers.values())if(t.healthy&&t.agents.some(s=>s.id===e))return t}directory(){return Array.from(this.peers.entries()).map(([e,t])=>({peer:e,peerUrl:t.peer.url,healthy:t.healthy,skills:t.agents,lastCheck:t.lastCheck}))}};import{z as d}from"zod";import{readFileSync as ee,existsSync as I}from"fs";import{resolve as P}from"path";function ye(l){let e=P(l,".env");if(!I(e))return;let t=ee(e,"utf-8");for(let s of t.split(`
|
|
3
|
-
`)){let n=s.trim();if(!n||n.startsWith("#"))continue;let r=n.indexOf("=");if(r===-1)continue;let i=n.slice(0,r).trim(),o=n.slice(r+1).trim();process.env[i]||(process.env[i]=o)}}var we=d.object({apiKey:d.string().optional(),defaultModel:d.string().optional(),baseUrl:d.string().optional()}),ke=d.object({name:d.string(),workspace:d.string(),tier:d.enum(["claude-code","sdk","orchestrator"]).default("claude-code"),provider:d.string().optional(),model:d.string().optional(),systemPrompt:d.string().optional(),mentions:d.array(d.string()).default([]),maxConcurrent:d.number().default(1),permissionMode:d.string().default("default")}),ve=d.object({token:d.string(),agentBinding:d.string()}),Ae=d.object({telegram:d.object({enabled:d.boolean().default(!1),accounts:d.record(d.string(),ve).default({}),policy:d.object({dm:d.enum(["pair","block"]).default("pair"),group:d.enum(["mention-required","all"]).default("mention-required")}).default({})}).default({}),whatsapp:d.object({enabled:d.boolean().default(!1),sessionDir:d.string().default(".agentx/whatsapp-sessions"),defaultAgent:d.string().optional(),allowFrom:d.array(d.string()).optional(),routes:d.array(d.object({contact:d.string().optional(),group:d.string().optional(),agent:d.string()})).default([])}).default({}),discord:d.object({enabled:d.boolean().default(!1),token:d.string().optional(),agentBinding:d.string().optional()}).default({})}),$e=d.object({enabled:d.boolean().default(!0),schedule:d.string(),timezone:d.string().default("UTC"),agent:d.string(),prompt:d.string(),timeout:d.number().default(600),model:d.string().optional(),onError:d.enum(["log","notify","disable"]).default("log")}),be=d.object({url:d.string(),name:d.string(),token:d.string().optional()}),xe=d.object({enabled:d.boolean().default(!1),peers:d.array(be).default([]),discovery:d.enum(["static","mdns"]).default("static"),healthCheck:d.object({interval:d.number().default(60),timeout:d.number().default(10)}).default({})}),Se=d.object({node:d.object({id:d.string(),name:d.string(),bind:d.string().default("127.0.0.1:18800")}),providers:d.record(d.string(),we).default({}),agents:d.record(d.string(),ke).default({}),channels:Ae.default({}),crons:d.record(d.string(),$e).default({}),mesh:xe.default({})});function G(l){if(typeof l=="string")return l.replace(/\$\{(\w+)\}/g,(e,t)=>process.env[t]||"");if(Array.isArray(l))return l.map(G);if(l!==null&&typeof l=="object"){let e={};for(let[t,s]of Object.entries(l))e[t]=G(s);return e}return l}function te(l){let e=l?[l]:[P(process.cwd(),"agentx.json"),P(process.cwd(),".agentx/config.json")];ye(process.cwd());let t,s;for(let o of e)if(I(o)){t=ee(o,"utf-8"),s=o;break}if(!t||!s)throw new Error(`No config found. Create agentx.json or .agentx/config.json
|
|
4
|
-
Searched: ${e.join(", ")}`);let n;try{n=JSON.parse(t)}catch(o){throw new Error(`Invalid JSON in ${s}: ${o.message}`)}let r=G(n),i=Se.safeParse(r);if(!i.success){let o=i.error.issues.map(a=>` ${a.path.join(".")}: ${a.message}`).join(`
|
|
5
|
-
`);throw new Error(`Config validation failed (${s}):
|
|
6
|
-
${o}`)}return i.data}function se(l){let e=[];for(let[t,s]of Object.entries(l.agents)){if(!I(s.workspace)){e.push(`Agent "${t}": workspace not found at ${s.workspace}`);continue}if(s.tier==="claude-code"){let i=P(s.workspace,".claude");I(i)||e.push(`Agent "${t}": no .claude/ directory in workspace ${s.workspace}. Claude Code native features (hooks, MCP, skills) won't be available.`)}let n=s.provider||"claude",r=l.providers[n];s.tier!=="claude-code"&&(!r||!r.apiKey)&&e.push(`Agent "${t}": provider "${n}" has no API key configured. Set providers.${n}.apiKey in config or use tier "claude-code" for subscription.`)}for(let[t,s]of Object.entries(l.crons))l.agents[s.agent]||e.push(`Cron "${t}": references unknown agent "${s.agent}"`);if(l.channels.telegram.enabled)for(let[t,s]of Object.entries(l.channels.telegram.accounts))l.agents[s.agentBinding]||e.push(`Telegram account "${t}": references unknown agent "${s.agentBinding}"`);return e}import{execa as Te}from"execa";import{execFile as Ce}from"child_process";function ne(l,e,t){let s=[];if(l.systemPrompt&&s.push(l.systemPrompt),e.context){let n=e.context,r=["","[Environment]"];if(n.channel&&r.push(`Channel: ${n.channel}`),n.group&&r.push(`Group: ${n.group}`),n.sender&&r.push(`Message from: ${n.sender}`),n.myHandle&&r.push(`Your handle on this channel: ${n.myHandle}`),n.peers?.length){r.push(""),r.push("[Team \u2014 other agents you can mention to delegate or collaborate]");for(let i of n.peers){let o=i.handle?` (mention: ${i.handle})`:"",a=i.role?` \u2014 ${i.role}`:"";r.push(`\u2022 ${i.name}${o}${a}`)}r.push(""),r.push("To involve another agent, mention their handle in your response and they will automatically see it and reply.")}s.push(r.join(`
|
|
7
|
-
`))}return t&&(s.push(""),s.push(t)),s.push(""),s.push(e.message),s.join(`
|
|
8
|
-
`)}function re(l,e,t,s){let n=["-p",e,"--output-format",t?"stream-json":"json"];return t&&n.push("--verbose"),s&&n.push("--resume",s),l.model&&n.push("--model",l.model),l.permissionMode==="bypassPermissions"&&n.push("--dangerously-skip-permissions"),n}function Me(l){try{let e=JSON.parse(l);return{text:e.result||e.content||"",sessionId:e.session_id}}catch{return{text:l}}}async function De(l,e,t,s){let n=Date.now(),r=ne(l,e,s?void 0:t),i=re(l,r,!1,s);try{let{stdout:o,stderr:a,exitCode:g}=await new Promise((h,u)=>{let m=Ce("claude",i,{cwd:l.workspace,timeout:6e5,maxBuffer:10485760,env:{...process.env,HOME:process.env.HOME||"/home/"+(process.env.USER||"clawd")}},(f,y,p)=>{h({stdout:y||"",stderr:p||"",exitCode:f?f.code??1:0})})});if(!o&&g!==0)return{content:"",error:(a?.trim()||`Claude Code exited with code ${g}`).slice(0,300),duration:Date.now()-n};let c=Me(o);return{content:c.text,duration:Date.now()-n,claudeSessionId:c.sessionId}}catch(o){return console.error(`[runtime] execFile threw: ${o.message}`),{content:"",error:o.message||"Claude Code failed",duration:Date.now()-n}}}async function Ie(l,e,t,s,n){let r=Date.now(),i=ne(l,e,n?void 0:s),o=re(l,i,!0,n),a="";try{let g=Te("claude",o,{cwd:l.workspace,timeout:6e5,reject:!1,env:process.env,buffer:!1});if(g.stdout){let h="";g.stdout.on("data",u=>{h+=u.toString();let m=h.split(`
|
|
9
|
-
`);h=m.pop()||"";for(let f of m)if(f.trim())try{let y=JSON.parse(f);if(y.type==="assistant"&&y.message?.content){for(let p of y.message.content)if(p.type==="text"&&p.text){let w=p.text.slice(a.length);w&&(a=p.text,t(w,a))}}if(y.type==="content_block_delta"&&y.delta?.text&&(a+=y.delta.text,t(y.delta.text,a)),y.type==="result"&&y.result){let p=(typeof y.result=="string",y.result);if(typeof p=="string"&&p.length>a.length){let w=p.slice(a.length);a=p,w&&t(w,a)}}}catch{f.trim()&&!f.startsWith("{")&&(a+=f+`
|
|
10
|
-
`,t(f+`
|
|
11
|
-
`,a))}})}let c=await g;return!a&&c.stdout&&(a=typeof c.stdout=="string"?c.stdout:""),c.exitCode!==0&&!a?{content:"",error:(typeof c.stderr=="string"?c.stderr:"")||`Claude Code exited with code ${c.exitCode}`,duration:Date.now()-r}:{content:a,duration:Date.now()-r}}catch(g){return{content:a||"",error:g.message,duration:Date.now()-r}}}async function Pe(l,e,t){let s=Date.now();try{let n=await import("@anthropic-ai/claude-agent-sdk"),{query:r}=n,i=l.systemPrompt?`${l.systemPrompt}
|
|
12
|
-
|
|
13
|
-
${e.message}`:e.message,o="",a=r({prompt:i,options:{model:l.model,cwd:l.workspace,permissionMode:"bypassPermissions"}});for await(let g of a)g.type==="result"&&g.subtype==="success"&&(o=g.result||"");return{content:o,duration:Date.now()-s}}catch(n){return{content:"",error:`SDK error: ${n.message}`,duration:Date.now()-s}}}async function Re(l,e,t){let s=Date.now();try{let{generate:n}=await import("./agent-CRA5PU6S.js"),r=l.provider||"claude-code",i=await n({task:e.message,cwd:l.workspace,provider:r,model:l.model,apiKey:t,overwrite:!0,interactive:!1,context7:!1});return{content:i.content||"Done.",tokensUsed:i.tokensUsed,duration:Date.now()-s}}catch(n){return{content:"",error:`Orchestrator error: ${n.message}`,duration:Date.now()-s}}}async function ie(l,e,t,s,n,r){switch(l.tier){case"claude-code":return s?Ie(l,e,s,n,r):De(l,e,n,r);case"sdk":{let i=l.provider||"claude",o=t[i]?.apiKey;return o?Pe(l,e,o):{content:"",error:`No API key for provider "${i}". Configure providers.${i}.apiKey`}}case"orchestrator":{let i=l.provider||"claude-code",o=t[i]?.apiKey;return Re(l,e,o)}default:return{content:"",error:`Unknown tier: ${l.tier}`}}}import{readFileSync as oe,writeFileSync as R,existsSync as _,mkdirSync as K,readdirSync as z,statSync as _e}from"fs";import{resolve as v,join as Ee,relative as E,dirname as je}from"path";var S=class{baseDir;rawDir;log;constructor(e=v(process.cwd(),".agentx/wiki"),t=console.error.bind(console,"[wiki]")){this.baseDir=e,this.rawDir=v(e,"raw/entries"),this.log=t,K(this.rawDir,{recursive:!0}),K(v(e,"raw"),{recursive:!0})}canRead(e,t){return!!(e.access==="public"||e.owner===t||e.access==="shared"&&e.sharedWith?.includes(t))}canWrite(e,t){return e.owner===t}addEntry(e){let t=`${e.date}_${e.id}.md`,s=v(this.rawDir,t),n=["---",`id: ${e.id}`,`date: ${e.date}`,`agent: ${e.agentId}`,`source: ${e.source}`];if(e.sourceContext&&n.push(`context: ${e.sourceContext}`),e.meta)for(let[r,i]of Object.entries(e.meta))n.push(`${r}: ${JSON.stringify(i)}`);return n.push("---","",e.content),R(s,n.join(`
|
|
14
|
-
`)),t}listEntries(e){if(!_(this.rawDir))return[];let t=z(this.rawDir).filter(n=>n.endsWith(".md")).sort(),s=[];for(let n of t){let r=oe(v(this.rawDir,n),"utf-8"),i=this.parseEntry(r,n);i&&(e?.agentId&&i.agentId!==e.agentId||e?.after&&i.date<e.after||e?.before&&i.date>e.before||s.push(i))}return s}parseEntry(e,t){let s=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!s)return null;let n=s[1],r=s[2].trim(),i=o=>n.match(new RegExp(`^${o}:\\s*(.+)$`,"m"))?.[1]?.trim()||"";return{id:i("id")||t.replace(".md",""),date:i("date"),agentId:i("agent"),source:i("source"),sourceContext:i("context")||void 0,content:r}}writeArticle(e,t,s,n){let r=this.readArticle(e);if(r&&!this.canWrite(r.meta,n))return this.log(`Permission denied: "${n}" cannot write "${e}" (owner: ${r.meta.owner})`),!1;let i=v(this.baseDir,e);K(je(i),{recursive:!0});let o=["---",`title: "${t.title}"`,`type: ${t.type}`,`owner: ${t.owner}`,`access: ${t.access}`];return t.sharedWith?.length&&o.push(`shared_with: [${t.sharedWith.map(a=>`"${a}"`).join(", ")}]`),o.push(`created: ${t.created}`,`last_updated: ${t.lastUpdated}`,`related: [${t.related.map(a=>`"${a}"`).join(", ")}]`,`sources: [${t.sources.map(a=>`"${a}"`).join(", ")}]`),t.tags?.length&&o.push(`tags: [${t.tags.map(a=>`"${a}"`).join(", ")}]`),o.push("---","",s),R(i,o.join(`
|
|
15
|
-
`)),!0}readArticle(e){let t=v(this.baseDir,e);if(!_(t))return null;let s=oe(t,"utf-8");return this.parseArticle(s,e)}readArticleAs(e,t){let s=this.readArticle(e);return!s||!this.canRead(s.meta,t)?null:s}parseArticle(e,t){let s=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!s)return null;let n=s[1],r=s[2].trim(),i=a=>n.match(new RegExp(`^${a}:\\s*(.+)$`,"m"))?.[1]?.trim().replace(/^"(.*)"$/,"$1")||"",o=a=>{let g=n.match(new RegExp(`^${a}:\\s*\\[(.*)\\]$`,"m"));return g?g[1].split(",").map(c=>c.trim().replace(/^"(.*)"$/,"$1")).filter(Boolean):[]};return{meta:{title:i("title"),type:i("type"),owner:i("owner"),access:i("access")||"public",sharedWith:o("shared_with"),created:i("created"),lastUpdated:i("last_updated"),related:o("related"),sources:o("sources"),tags:o("tags")},content:r,path:t}}listArticles(e){let t=[];return this.walkDir(this.baseDir,s=>{if(!s.endsWith(".md"))return;let n=E(this.baseDir,s);if(n.startsWith("raw/")||n.startsWith("_"))return;let r=this.readArticle(n);r&&this.canRead(r.meta,e)&&t.push(r)}),t}search(e,t,s=10){let n=e.toLowerCase(),r=[];return this.walkDir(this.baseDir,i=>{if(!i.endsWith(".md"))return;let o=E(this.baseDir,i);if(o.startsWith("raw/")||o.startsWith("_"))return;let a=this.readArticle(o);if(!a||!this.canRead(a.meta,t))return;let g=0,c=a.meta.title.toLowerCase(),h=a.content.toLowerCase();c.includes(n)&&(g+=10),a.meta.tags?.some(m=>m.toLowerCase().includes(n))&&(g+=5);let u=(h.match(new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"))||[]).length;g+=Math.min(u,5),g>0&&r.push({article:a,score:g})}),r.sort((i,o)=>o.score-i.score).slice(0,s).map(i=>i.article)}findRelevant(e,t,s=3){let n=new Set(["the","a","an","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","can","shall","to","of","in","for","on","with","at","by","from","as","into","about","through","and","but","or","not","no","if","then","so","what","how","when","where","who","which","that","this","it","i","you","we","they","he","she","me","my","your","our","their","please","just","also","very","much","some","any","all"]),r=e.toLowerCase().replace(/[^a-z0-9\s@_-]/g," ").split(/\s+/).filter(o=>o.length>2&&!n.has(o));if(r.length===0)return[];let i=new Map;for(let o of r){let a=this.search(o,t,5);for(let g of a){let c=i.get(g.path);c?c.score+=1:i.set(g.path,{article:g,score:1})}}return Array.from(i.values()).sort((o,a)=>a.score-o.score).slice(0,s).map(o=>o.article)}buildContext(e,t=4e3){if(e.length===0)return"";let s=["[Wiki Knowledge]"],n=0;for(let r of e){let i=`
|
|
16
|
-
## ${r.meta.title} (${r.meta.type})`,o=r.content.length>600?r.content.slice(0,600)+"...":r.content,a=i+`
|
|
17
|
-
`+o;if(n+a.length>t)break;s.push(a),n+=a.length}return s.push(`
|
|
18
|
-
[End Wiki Knowledge]`),s.join(`
|
|
19
|
-
`)}rebuildIndex(){let e=[],t=new Map;this.walkDir(this.baseDir,i=>{if(!i.endsWith(".md"))return;let o=E(this.baseDir,i);if(o.startsWith("raw/")||o.startsWith("_"))return;let a=this.readArticle(o);if(!a)return;let g=a.content.match(/\[\[([^\]]+)\]\]/g)||[];for(let h of g){let u=h.replace(/\[\[|\]\]/g,"");t.set(u,(t.get(u)||0)+1)}let c=[a.meta.title.toLowerCase()];a.meta.tags&&c.push(...a.meta.tags.map(h=>h.toLowerCase())),e.push({path:o,title:a.meta.title,type:a.meta.type,owner:a.meta.owner,access:a.meta.access,sharedWith:a.meta.sharedWith,aliases:c,backlinks:t.get(a.meta.title)||0})});let s={articles:e,lastRebuilt:new Date().toISOString()};R(v(this.baseDir,"_index.json"),JSON.stringify(s,null,2));let n=["# Wiki Index","",`Last rebuilt: ${s.lastRebuilt}`,""],r=new Map;for(let i of e){let o=r.get(i.type)||[];o.push(i),r.set(i.type,o)}for(let[i,o]of Array.from(r.entries()).sort()){n.push(`## ${i}`,"");for(let a of o.sort((g,c)=>g.title.localeCompare(c.title))){let g=a.access==="private"?" (private)":a.access==="shared"?" (shared)":"";n.push(`- [${a.title}](${a.path})${g} \u2014 owner: ${a.owner}`)}n.push("")}return R(v(this.baseDir,"WIKI.md"),n.join(`
|
|
20
|
-
`)),this.log(`Index rebuilt: ${e.length} articles`),s}stats(){let e=0,t={},s={},n={};this.walkDir(this.baseDir,i=>{if(!i.endsWith(".md"))return;let o=E(this.baseDir,i);if(o.startsWith("raw/")||o.startsWith("_")||o==="WIKI.md")return;let a=this.readArticle(o);a&&(e++,t[a.meta.type]=(t[a.meta.type]||0)+1,s[a.meta.access]=(s[a.meta.access]||0)+1,n[a.meta.owner]=(n[a.meta.owner]||0)+1)});let r=_(this.rawDir)?z(this.rawDir).filter(i=>i.endsWith(".md")).length:0;return{totalArticles:e,totalEntries:r,articlesByType:t,articlesByAccess:s,articlesByOwner:n}}walkDir(e,t){if(_(e))for(let s of z(e)){let n=Ee(e,s);_e(n).isDirectory()?this.walkDir(n,t):t(n)}}};import{readFileSync as We,writeFileSync as Oe,mkdirSync as Le,existsSync as ae}from"fs";import{resolve as ce}from"path";var Be=12e3,le=30,j=class{sessionsDir;cache=new Map;constructor(e=process.cwd()){this.sessionsDir=ce(e,".agentx/sessions"),ae(this.sessionsDir)||Le(this.sessionsDir,{recursive:!0})}sessionKey(e,t,s){let n=new Date().toISOString().slice(0,10);return`${e}:${t}:${s}:${n}`}sessionFile(e){let t=e.replace(/[^a-zA-Z0-9_:-]/g,"_");return ce(this.sessionsDir,`${t}.json`)}getSession(e,t,s){let n=this.sessionKey(e,t,s);if(this.cache.has(n))return this.cache.get(n);let r=this.sessionFile(n);if(ae(r))try{let a=JSON.parse(We(r,"utf-8"));return this.cache.set(n,a),a}catch{}let i=new Date().toISOString().slice(0,10),o={id:n,agentId:e,channel:t,chatId:s,day:i,messages:[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return this.cache.set(n,o),this.save(o),o}addUserMessage(e,t,s,n,r){let i=this.getSession(e,t,s);i.messages.push({role:"user",name:n,content:r,timestamp:new Date().toISOString()}),this.trim(i),i.updatedAt=new Date().toISOString(),this.save(i)}addAgentMessage(e,t,s,n){let r=this.getSession(e,t,s);r.messages.push({role:"agent",name:e,content:n,timestamp:new Date().toISOString()}),this.trim(r),r.updatedAt=new Date().toISOString(),this.save(r)}getClaudeSessionId(e,t,s){return this.getSession(e,t,s).claudeSessionId}setClaudeSessionId(e,t,s,n){let r=this.getSession(e,t,s);r.claudeSessionId=n,r.updatedAt=new Date().toISOString(),this.save(r)}buildHistoryContext(e,t,s){let n=this.getSession(e,t,s);if(n.messages.length===0)return"";let r=[`[Conversation history for today (${n.day})]`];for(let i of n.messages){let o=i.timestamp.slice(11,16);i.role==="user"?r.push(`[${o}] ${i.name||"User"}: ${i.content}`):r.push(`[${o}] ${i.name||"Agent"}: ${i.content}`)}return r.push("[End of history \u2014 respond to the latest message above]"),r.push(""),r.join(`
|
|
21
|
-
`)}trim(e){e.messages.length>le&&(e.messages=e.messages.slice(-le));let t=e.messages.reduce((s,n)=>s+n.content.length,0);for(;t>Be&&e.messages.length>2;){let s=e.messages.shift();t-=s.content.length}}save(e){try{let t=this.sessionFile(e.id);Oe(t,JSON.stringify(e,null,2))}catch{}}};var W=class{agents=new Map;config;providers={};sessions;wiki;log;constructor(e,t=console.error.bind(console,"[agents]")){this.log=t,this.config=e,this.providers=e.providers,this.sessions=new j,this.wiki=new S;for(let[s,n]of Object.entries(e.agents))this.agents.set(s,{id:s,def:n,activeTasks:0,totalTasks:0,errors:0})}getAgent(e){return this.agents.get(e)?.def}findByMention(e){let t=e.toLowerCase(),s,n=0;for(let[r,i]of this.agents)for(let o of i.def.mentions){let a=o.toLowerCase();t.includes(a)&&a.length>n&&(s=r,n=a.length)}return s}findAllMentioned(e){let t=e.toLowerCase(),s=[];for(let[n,r]of this.agents)for(let i of r.def.mentions)if(t.includes(i.toLowerCase())){s.push(n);break}return s}getChannelHandle(e,t){let s=this.agents.get(e)?.def;if(s)return t==="telegram"?s.mentions.find(n=>n.startsWith("@")):s.mentions[0]}enrichTaskContext(e){let t=e.context?.channel,s=[];for(let[r,i]of this.agents)r!==e.agentId&&s.push({id:r,name:i.def.name,handle:this.getChannelHandle(r,t),role:i.def.systemPrompt?.split(`
|
|
22
|
-
`)[0]?.slice(0,100)});let n=this.getChannelHandle(e.agentId,t);return{...e,context:{...e.context,myHandle:n,peers:s}}}async execute(e,t){let s=this.agents.get(e.agentId);if(!s)return{content:"",error:`Unknown agent: ${e.agentId}`};if(s.activeTasks>=s.def.maxConcurrent)return{content:"",error:`Agent "${e.agentId}" is busy (${s.activeTasks}/${s.def.maxConcurrent} tasks)`};s.activeTasks++,s.totalTasks++,s.lastActive=new Date,this.log(`[${e.agentId}] executing task (${s.activeTasks}/${s.def.maxConcurrent})`);let n=e.context?.channel||"api",r=e.context?.group||e.context?.sender||"default",i=e.context?.sender||"User";this.sessions.addUserMessage(e.agentId,n,r,i,e.message),e=this.enrichTaskContext(e);let o=this.wiki.findRelevant(e.message,e.agentId,3),a=this.wiki.buildContext(o),g=s.def.tier==="claude-code"?this.sessions.getClaudeSessionId(e.agentId,n,r):void 0,c=g?void 0:this.sessions.buildHistoryContext(e.agentId,n,r),h=[a,c].filter(Boolean).join(`
|
|
23
|
-
|
|
24
|
-
`)||void 0;try{let u=await ie(s.def,e,this.providers,t,h,g);if(u.error)s.errors++,this.log(`[${e.agentId}] error: ${u.error}`);else{if(this.sessions.addAgentMessage(e.agentId,n,r,u.content),u.claudeSessionId&&this.sessions.setClaudeSessionId(e.agentId,n,r,u.claudeSessionId),u.content.length>50)try{let m=`${e.agentId}-${Date.now().toString(36)}`;this.wiki.addEntry({id:m,date:new Date().toISOString().slice(0,10),agentId:e.agentId,source:n,sourceContext:e.context?.group||e.context?.sender,content:`User: ${e.message}
|
|
25
|
-
|
|
26
|
-
Agent: ${u.content}`})}catch{}this.log(`[${e.agentId}] completed in ${u.duration}ms`+(u.tokensUsed?` (${u.tokensUsed} tokens)`:""))}return u}catch(u){return s.errors++,this.log(`[${e.agentId}] unexpected error: ${u.message}`),{content:"",error:u.message}}finally{s.activeTasks--}}list(){return Array.from(this.agents.values()).map(e=>({id:e.id,name:e.def.name,tier:e.def.tier,workspace:e.def.workspace,active:e.activeTasks,total:e.totalTasks,errors:e.errors,lastActive:e.lastActive}))}};var O=class{registry;config;channels=new Map;hooks;mesh;log;constructor(e,t,s,n=console.error.bind(console,"[router]")){this.registry=e,this.config=t,this.hooks=s,this.log=n}setMesh(e){this.mesh=e}addChannel(e){this.channels.set(e.name,e),e.onMessage(t=>this.handleMessage(e,t))}async startAll(){for(let[e,t]of this.channels)this.log(`Starting channel: ${e}`),await t.start()}async stopAll(){for(let[e,t]of this.channels)this.log(`Stopping channel: ${e}`),await t.stop()}async handleMessage(e,t){if(this.hooks?.has("pre:channel-message")){let p=await this.hooks.execute("pre:channel-message",{event:"pre:channel-message",channel:t.channel,sender:t.sender.name,text:t.text,group:t.group?.name});if(p.blocked){this.log(`Message blocked by hook: ${p.message}`);return}p.modified?.text&&(t={...t,text:p.modified.text})}let s=this.resolveAgent(t);if(!s)return;if(t.group&&t.channel==="telegram"){let p=this.getAccountForAgent(s);if(p&&p!==t.accountId)return}let n=t.group?.id||t.sender.id,i=this.registry.getAgent(s)?.name||s,o=this.getAccountForAgent(s)||t.accountId;this.log(`Routing [${t.channel}/${t.sender.name}] -> "${i}": ${t.text.slice(0,80)}`),this.adapterReact(e,n,t.id,"\u{1F440}",o);let a=this.startTypingLoop(e,n,o),g=typeof e.editMessage=="function",c,h=0,u=g?async(p,w)=>{let k=Date.now();if(!(k-h<1500))if(c)try{await this.adapterEdit(e,n,c,w,void 0,o),h=k}catch{}else{let x=w.length>20?w:`_${i} is writing..._
|
|
27
|
-
|
|
28
|
-
${w}`;try{c=await this.adapterSend(e,{channel:t.channel,chatId:n,text:x,replyTo:t.id,accountId:o}),h=k}catch{}}}:void 0,m=await this.registry.execute({message:t.text,agentId:s,context:{channel:t.channel,sender:t.sender.name,group:t.group?.name}},u);if(clearInterval(a),m.error){this.log(`Agent error: ${m.error}`);let p=`Error: ${m.error}`;c?await this.adapterEdit(e,n,c,p,"plain",o):await this.adapterSend(e,{channel:t.channel,chatId:n,text:p,replyTo:t.id,parseMode:"plain",accountId:o});return}let f=m.content;if(this.hooks?.has("post:channel-message")){let p=await this.hooks.execute("post:channel-message",{event:"post:channel-message",channel:t.channel,sender:t.sender.name,response:f,agentId:s});if(p.blocked){this.log(`Response blocked by hook: ${p.message}`);return}p.modified?.response&&(f=p.modified.response)}let y;f&&(c?(await this.adapterEdit(e,n,c,f,void 0,o),y=c):y=await this.adapterSend(e,{channel:t.channel,chatId:n,text:f,replyTo:t.id,accountId:o})),f&&y&&this.handleBotToBotMentions(e,t,s,f,y).catch(p=>{this.log(`Bot-to-bot error: ${p.message}`)})}async handleBotToBotMentions(e,t,s,n,r){for(let[i,o]of Object.entries(this.config.agents)){if(i===s||!o.mentions.some(h=>n.toLowerCase().includes(h.toLowerCase())))continue;this.log(`Bot-to-bot: "${s}" mentioned "${i}" \u2014 routing`);let g=t.group?.id||t.sender.id,c=this.getAccountForAgent(i);try{this.adapterReact(e,g,r,"\u{1F440}",c);let h=this.startTypingLoop(e,g,c),u=await this.registry.execute({message:n,agentId:i,context:{channel:t.channel,sender:`agent:${s}`,group:t.group?.name}});clearInterval(h),u.content&&!u.error?await this.adapterSend(e,{channel:t.channel,chatId:g,text:u.content,accountId:c}):u.error&&this.log(`Bot-to-bot "${i}" error: ${u.error}`)}catch(h){this.log(`Bot-to-bot "${i}" failed: ${h.message}`)}break}}async adapterSend(e,t){return e.name==="telegram"&&t.accountId?e.send({...t,parseMode:t.parseMode,accountId:t.accountId}):e.send(t)||""}async adapterEdit(e,t,s,n,r,i){return e.name==="telegram"&&i?e.editMessage(t,s,n,r,i):e.editMessage?.(t,s,n,r)??!1}adapterReact(e,t,s,n,r){e.name==="telegram"&&r?e.react(t,s,n,r):e.react?.(t,s,n)}startTypingLoop(e,t,s){let n=()=>{e.name==="telegram"&&s?e.sendTyping(t,s):e.sendTyping?.(t)};return n(),setInterval(n,4e3)}async handleViaMesh(e,t){if(!this.mesh)return!1;let s=t.text.toLowerCase(),n=this.mesh.directory();for(let r of n)if(r.healthy){for(let i of r.skills)if(s.includes(i.id.toLowerCase())||s.includes(i.name.toLowerCase())){this.log(`Mesh routing [${t.channel}/${t.sender.name}] -> peer "${r.peer}" agent "${i.id}"`);let o=t.group?.id||t.sender.id,a=t.accountId;this.adapterReact(e,o,t.id,"\u{1F440}",a);let g=this.startTypingLoop(e,o,a);try{let c=await this.mesh.sendTask(r.peer,t.text,i.id);if(clearInterval(g),c){let h=`**${i.name}** _(${r.peer})_:
|
|
29
|
-
|
|
30
|
-
`;await this.adapterSend(e,{channel:t.channel,chatId:o,text:h+c,replyTo:t.id,accountId:a})}return!0}catch(c){return clearInterval(g),this.log(`Mesh routing error: ${c.message}`),await this.adapterSend(e,{channel:t.channel,chatId:o,text:`Error from ${r.peer}/${i.name}: ${c.message}`,replyTo:t.id,parseMode:"plain",accountId:a}),!0}}}return!1}getAccountForAgent(e){for(let[t,s]of Object.entries(this.config.channels.telegram.accounts))if(s.agentBinding===e)return t}resolveAgent(e){if(e.resolvedAgent)return e.resolvedAgent;if(!e.group)return e.channel==="telegram"?this.config.channels.telegram.accounts[e.accountId]?.agentBinding:e.channel==="whatsapp"?this.config.channels.whatsapp.defaultAgent:void 0;if(e.channel==="telegram"&&this.config.channels.telegram.policy.group==="mention-required"){let n=this.registry.findByMention(e.text);return n||void 0}let t=this.registry.findByMention(e.text);return t||(e.channel==="telegram"?this.config.channels.telegram.accounts[e.accountId]?.agentBinding:this.config.channels.whatsapp.defaultAgent)}};var Ne=/([_*\[\]()~`>#+=|{}.!\-\\])/g;function A(l){return l.replace(Ne,"\\$1")}function B(l){return l.replace(/([`\\])/g,"\\$1")}function V(l){let e=l.split(`
|
|
31
|
-
`),t=[],s=!1,n="",r=[];for(let i=0;i<e.length;i++){let o=e[i];if(o.trimStart().startsWith("```"))if(s){s=!1;let h=r.join(`
|
|
32
|
-
`);n?t.push("```"+B(n)):t.push("```"),t.push(B(h)),t.push("```");continue}else{s=!0,n=o.trimStart().slice(3).trim(),r=[];continue}if(s){r.push(o);continue}let a=o.match(/^(#{1,6})\s+(.+)$/);if(a){t.push(""),t.push("*"+ge(a[2])+"*");continue}if(/^[-*_]{3,}\s*$/.test(o.trim())){t.push("\u2014\u2014\u2014");continue}if(o.trimStart().startsWith("> ")){let h=o.replace(/^>\s*/,"");t.push(">"+L(h));continue}let g=o.match(/^(\s*)[-*+]\s+(.+)$/);if(g){let h=g[1].length>0?" ":"";t.push(h+"\u2022 "+L(g[2]));continue}let c=o.match(/^(\s*)\d+[.)]\s+(.+)$/);if(c){let h=c[1].length>0?" ":"",u=o.match(/^(\s*)(\d+)/)?.[2]||"1";t.push(h+A(u)+"\\. "+L(c[2]));continue}if(!o.trim()){t.push("");continue}t.push(L(o))}return s&&(t.push("```"),t.push(B(r.join(`
|
|
33
|
-
`))),t.push("```")),t.join(`
|
|
34
|
-
`).trim()}function L(l){let e=[],t=l.replace(/`([^`]+)`/g,(r,i)=>{let o=e.length;return e.push("`"+B(i)+"`"),`\0CODE${o}\0`}),s=[];t=t.replace(/@(\w{5,})/g,(r,i)=>{let o=s.length;return s.push("@"+A(i)),`\0MENTION${o}\0`});let n=[];return t=t.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(r,i,o)=>{let a=n.length;return n.push("["+ge(i)+"]("+o.replace(/([)\\])/g,"\\$1")+")"),`\0LINK${a}\0`}),t=t.replace(/\*\*\*(.+?)\*\*\*/g,(r,i)=>"*_"+A(i)+"_*"),t=t.replace(/\*\*(.+?)\*\*/g,(r,i)=>"*"+A(i)+"*"),t=t.replace(/(?<!\*)\*([^*]+?)\*(?!\*)/g,(r,i)=>"_"+A(i)+"_"),t=t.replace(/(?<!_)_([^_]+?)_(?!_)/g,(r,i)=>"_"+A(i)+"_"),t=t.replace(/~~(.+?)~~/g,(r,i)=>"~"+A(i)+"~"),t=Je(t),t=t.replace(/\x00CODE(\d+)\x00/g,(r,i)=>e[parseInt(i)]),t=t.replace(/\x00MENTION(\d+)\x00/g,(r,i)=>s[parseInt(i)]),t=t.replace(/\x00LINK(\d+)\x00/g,(r,i)=>n[parseInt(i)]),t}function ge(l){return A(l)}function Je(l){return l.split(/(\*[^*]+\*|_[^_]+_|~[^~]+~|\x00\w+\d+\x00)/g).map(t=>/^\*[^*]+\*$/.test(t)||/^_[^_]+_$/.test(t)||/^~[^~]+~$/.test(t)||/^\x00/.test(t)?t:A(t)).join("")}var N=class{name="telegram";accounts;offsets=new Map;handler;polling=!1;log;constructor(e,t=console.error.bind(console,"[telegram]")){this.accounts=new Map(Object.entries(e)),this.log=t}onMessage(e){this.handler=e}async start(){this.polling=!0;let e=Array.from(this.accounts.entries());this.log(`${e.length} Telegram account(s) to start`);for(let t=0;t<e.length;t++){let[s,n]=e[t];this.log(`Starting polling for account "${s}" (${t+1}/${e.length})`);try{let r=await this.apiCall(n.token,"getMe");this.log(`Bot @${r.result?.username} ready (account: ${s})`),this.pollLoop(s,n)}catch(r){this.log(`Failed to verify bot for account "${s}": ${r.message}`)}t<e.length-1&&await new Promise(r=>setTimeout(r,300))}this.log(`All ${e.length} Telegram account(s) started`)}async stop(){this.polling=!1}getTokenForAccount(e){return this.accounts.get(e)?.token}getDefaultToken(){let[,e]=Array.from(this.accounts.entries())[0];return e?.token}resolveToken(e,t){if(t){let s=this.getTokenForAccount(t);if(s)return s}return this.chatAccountMap.get(e)?this.getTokenForAccount(this.chatAccountMap.get(e)):this.getDefaultToken()}chatAccountMap=new Map;async send(e){let t=this.resolveToken(e.chatId,e.accountId);if(!t)return this.log("No telegram token found for sending"),"";let s=4096,n=e.text.length>s?e.text.slice(0,s-3)+"...":e.text,r=e.parseMode==="markdown"||e.parseMode===void 0?V(n):n,i={chat_id:e.chatId,text:r,parse_mode:"MarkdownV2"};e.replyTo&&(i.reply_to_message_id=parseInt(e.replyTo,10)),e.parseMode==="html"?(i.parse_mode="HTML",i.text=n):e.parseMode==="plain"&&(delete i.parse_mode,i.text=n);try{let o=await this.apiCall(t,"sendMessage",i);return String(o.result?.message_id||"")}catch(o){if(i.parse_mode){delete i.parse_mode,i.text=n;let a=await this.apiCall(t,"sendMessage",i);return String(a.result?.message_id||"")}throw o}}async editMessage(e,t,s,n,r){let i=this.resolveToken(e,r);if(!i)return!1;let o=4096,a=s.length>o?s.slice(0,o-3)+"...":s,g=n!=="html"&&n!=="plain"?V(a):a,c={chat_id:e,message_id:parseInt(t,10),text:g,parse_mode:"MarkdownV2"};n==="html"?(c.parse_mode="HTML",c.text=a):n==="plain"&&(delete c.parse_mode,c.text=a);try{return await this.apiCall(i,"editMessageText",c),!0}catch(h){if(h.message?.includes("message is not modified"))return!0;if(c.parse_mode){delete c.parse_mode,c.text=a;try{return await this.apiCall(i,"editMessageText",c),!0}catch{return!1}}return!1}}async react(e,t,s="\u{1F440}",n){let r=this.resolveToken(e,n);if(r)try{await this.apiCall(r,"setMessageReaction",{chat_id:e,message_id:parseInt(t,10),reaction:[{type:"emoji",emoji:s}]})}catch{}}async sendTyping(e,t){let s=this.resolveToken(e,t);if(s)try{await this.apiCall(s,"sendChatAction",{chat_id:e,action:"typing"})}catch{}}async pollLoop(e,t){for(;this.polling;)try{let s=this.offsets.get(e)||0,r=(await this.apiCall(t.token,"getUpdates",{offset:s||void 0,timeout:30,allowed_updates:["message"]})).result||[];for(let i of r)if(this.offsets.set(e,i.update_id+1),i.message?.text&&this.handler){let o=i.message,a={id:String(o.message_id),channel:"telegram",accountId:e,sender:{id:String(o.from.id),name:[o.from.first_name,o.from.last_name].filter(Boolean).join(" "),username:o.from.username},group:o.chat.type!=="private"?{id:String(o.chat.id),name:o.chat.title||""}:void 0,text:o.text,replyTo:o.reply_to_message?String(o.reply_to_message.message_id):void 0,timestamp:new Date(o.date*1e3),raw:i};this.chatAccountMap.set(String(o.chat.id),e),this.handler(a).catch(g=>{this.log(`Error handling message: ${g.message}`)})}}catch(s){this.log(`Poll error (${e}): ${s.message}`),await new Promise(n=>setTimeout(n,5e3))}}async apiCall(e,t,s){let n=`https://api.telegram.org/bot${e}/${t}`,r=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:s?JSON.stringify(s):void 0});if(!r.ok){let i=await r.text();throw new Error(`Telegram API error: ${r.status} ${i}`)}return r.json()}};import{mkdirSync as He}from"fs";import{resolve as Fe}from"path";var J=class{name="whatsapp";sessionDir;defaultAgent;allowFrom;routes;handler;sock=null;sentMessageIds=new Set;log;constructor(e,t=console.error.bind(console,"[whatsapp]")){this.sessionDir=Fe(e.sessionDir),this.defaultAgent=e.defaultAgent,this.allowFrom=e.allowFrom,this.routes=e.routes||[],this.log=t}resolveAgent(e,t,s){for(let n of this.routes){if(n.contact){let r=n.contact.replace(/\+/g,"");if(e.includes(r)||r.includes(e))return n.agent}if(n.group&&(t||s)){let r=n.group.toLowerCase();if(t?.toLowerCase().includes(r)||s?.toLowerCase().includes(r))return n.agent}}return this.defaultAgent}onMessage(e){this.handler=e}async start(){let e,t,s,n;try{n=await import("@whiskeysockets/baileys"),e=n.default||n.makeWASocket,t=n.useMultiFileAuthState,s=n.DisconnectReason}catch{this.log("WhatsApp requires @whiskeysockets/baileys. Install with:"),this.log(" npm install @whiskeysockets/baileys");return}He(this.sessionDir,{recursive:!0});let{state:r,saveCreds:i}=await t(this.sessionDir),o;try{let{version:g}=await n.fetchLatestBaileysVersion();o=g,this.log(`WhatsApp Web version: ${g.join(".")}`)}catch{this.log("Could not fetch WA version, using default")}let a={level:"silent",trace:()=>{},debug:()=>{},info:()=>{},warn:()=>{},fatal:()=>{},error:(...g)=>this.log("WA error:",...g),child:()=>a};this.sock=e({auth:{creds:r.creds,keys:n.makeCacheableSignalKeyStore?n.makeCacheableSignalKeyStore(r.keys,a):r.keys},...o?{version:o}:{},logger:a,printQRInTerminal:!1,browser:["agentx","server","1.0"],syncFullHistory:!1,markOnlineOnConnect:!1}),this.sock.ev.on("creds.update",i),this.sock.ev.on("messaging-history.set",g=>{this.log(`WA history sync: ${g.messages?.length||0} messages, ${g.isLatest?"latest":"partial"}`)}),this.sock.ev.on("connection.update",async g=>{let{connection:c,lastDisconnect:h,qr:u}=g;if(u){this.log("Scan QR code with WhatsApp to connect:");try{let{default:m}=await import("qrcode-terminal");m.generate(u,{small:!0})}catch{this.log(`QR: ${u}`),this.log("Install qrcode-terminal for visual QR: npm install qrcode-terminal")}}if(c==="close"){let m=h?.error?.output?.statusCode;this.log(`WhatsApp connection closed (status: ${m})`),m===515?(this.log("Stream error, reconnecting in 5s..."),setTimeout(()=>this.start(),5e3)):m===s?.loggedOut||m===401?this.log("Logged out. Delete session dir and restart to re-scan QR."):m!==void 0&&(this.log("Reconnecting in 3s..."),setTimeout(()=>this.start(),3e3))}c==="open"&&this.log("WhatsApp connected")}),this.sock.ev.on("messages.upsert",async g=>{if(this.log(`WA messages.upsert: ${g.messages?.length||0} messages, type: ${g.type}`),!!this.handler)for(let c of g.messages||[]){let h=(c.key.remoteJid||"").replace(/@.*/,"").slice(-6),u=!!(c.message?.conversation||c.message?.extendedTextMessage?.text);if(this.log(`WA msg: from=${h} fromMe=${c.key.fromMe} hasText=${u} type=${Object.keys(c.message||{}).join(",")}`),c.key.remoteJid==="status@broadcast")continue;if(c.key.id&&this.sentMessageIds.has(c.key.id)){this.sentMessageIds.delete(c.key.id);continue}if(c.key.fromMe){let b=this.sock?.user,U=c.key.remoteJid||"",C=b?.id?.replace(/:.*/,"")||"",fe=b?.lid?.replace(/:.*/,"")||"",Y=U.replace(/:.*/,"").replace(/@.*/,"");if(!(Y===C||Y===fe))continue}let m=c.message?.conversation||c.message?.extendedTextMessage?.text||c.message?.imageMessage?.caption||c.message?.videoMessage?.caption||"";if(!m)continue;let f=c.key.remoteJid||"",y=f.endsWith("@g.us"),p=f.replace(/@.*$/,""),k=(y?c.key.participant||"":f).replace(/@.*$/,"");if(this.allowFrom?.length&&!c.key.fromMe&&!this.allowFrom.some(U=>{let C=U.replace(/\+/g,"");return k.includes(C)||p.includes(C)}))continue;let x=c.key.fromMe?"me":c.pushName||k,$;if(y&&this.sock)try{$=(await this.sock.groupMetadata(f)).subject}catch{}let Q=this.resolveAgent(k,$,y?f:void 0);if(!Q){this.log(`No route for ${y?`group ${$||f}`:k}, skipping`);continue}let me={id:c.key.id||String(Date.now()),channel:"whatsapp",accountId:"default",sender:{id:c.key.fromMe?(this.sock?.user?.id?.replace(/:.*/,"")||k)+"@s.whatsapp.net":k,name:x,username:k},group:y?{id:f,name:$||f}:void 0,text:m,replyTo:c.message?.extendedTextMessage?.contextInfo?.stanzaId,timestamp:new Date((c.messageTimestamp||0)*1e3),raw:c,resolvedAgent:Q};this.handler(me).catch(b=>{this.log(`Error handling message: ${b.message}`)})}})}async stop(){this.sock&&(this.sock.end(),this.sock=null)}async send(e){if(!this.sock)return this.log("WhatsApp not connected"),"";let t=e.chatId.includes("@")?e.chatId:`${e.chatId}@s.whatsapp.net`;try{let n=(await this.sock.sendMessage(t,{text:e.text}))?.key?.id||"";return n&&this.sentMessageIds.add(n),n}catch(s){return this.log(`Send error: ${s.message}`),""}}async editMessage(e,t,s){if(!this.sock)return!1;let n=e.includes("@")?e:`${e}@s.whatsapp.net`;try{return await this.sock.sendMessage(n,{text:s,edit:{remoteJid:n,id:t,fromMe:!0}}),!0}catch{return!1}}async sendTyping(e){if(!this.sock)return;let t=e.includes("@")?e:`${e}@s.whatsapp.net`;try{await this.sock.sendPresenceUpdate("composing",t)}catch{}}async react(e,t,s="\u{1F440}"){if(!this.sock)return;let n=e.includes("@")?e:`${e}@s.whatsapp.net`;try{await this.sock.sendMessage(n,{react:{text:s,key:{remoteJid:n,id:t}}})}catch{}}};import{writeFileSync as Ue,mkdirSync as de,existsSync as he}from"fs";import{resolve as q}from"path";function T(l,e,t){let s=[];for(let n of l.split(","))if(n==="*")for(let r=e;r<=t;r++)s.push(r);else if(n.includes("/")){let[r,i]=n.split("/"),o=parseInt(i,10),a=r==="*"?e:parseInt(r,10);for(let g=a;g<=t;g+=o)s.push(g)}else if(n.includes("-")){let[r,i]=n.split("-").map(Number);for(let o=r;o<=i;o++)s.push(o)}else s.push(parseInt(n,10));return[...new Set(s)].sort((n,r)=>n-r)}function Ge(l,e,t){let s=l.trim().split(/\s+/);if(s.length!==5)throw new Error(`Invalid cron: ${l}`);let n=T(s[0],0,59),r=T(s[1],0,23),i=T(s[2],1,31),o=T(s[3],1,12),a=T(s[4],0,6),g=new Intl.DateTimeFormat("en-US",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:!1}),c=new Date(e.getTime()+6e4);c.setSeconds(0,0);let h=new Date(c.getTime()+366*24*60*60*1e3);for(;c<h;){let u=g.formatToParts(c),m=x=>parseInt(u.find($=>$.type===x)?.value||"0",10),f=m("minute"),y=m("hour"),p=m("day"),w=m("month"),k=c.getDay();if(n.includes(f)&&r.includes(y)&&i.includes(p)&&o.includes(w)&&a.includes(k))return c;c.setTime(c.getTime()+6e4)}throw new Error(`No next run found for cron "${l}" within 1 year`)}var H=class{jobs=new Map;timers=new Map;registry;hooks;runsDir;running=!1;log;constructor(e,t,s,n=console.error.bind(console,"[cron]")){this.registry=t,this.hooks=s,this.log=n,this.runsDir=q(process.cwd(),".agentx/cron/runs");for(let[r,i]of Object.entries(e.crons))this.jobs.set(r,{id:r,enabled:i.enabled,schedule:i.schedule,timezone:i.timezone,agent:i.agent,prompt:i.prompt,timeout:i.timeout,model:i.model,onError:i.onError,consecutiveErrors:0,totalRuns:0})}async start(){this.running=!0,he(this.runsDir)||de(this.runsDir,{recursive:!0});for(let[e,t]of this.jobs){if(!t.enabled){this.log(`Job "${e}" is disabled, skipping`);continue}this.scheduleNext(e)}this.log(`${this.jobs.size} cron job(s) loaded, ${Array.from(this.jobs.values()).filter(e=>e.enabled).length} enabled`)}async stop(){this.running=!1;for(let e of this.timers.values())clearTimeout(e);this.timers.clear()}scheduleNext(e){let t=this.jobs.get(e);if(!(!t||!t.enabled||!this.running))try{let s=Ge(t.schedule,new Date,t.timezone);t.nextRun=s;let n=s.getTime()-Date.now();this.log(`Job "${e}" next run: ${s.toISOString()} (in ${Math.round(n/1e3)}s)`);let r=setTimeout(()=>this.executeJob(e),n);this.timers.set(e,r)}catch(s){this.log(`Failed to schedule "${e}": ${s.message}`)}}async executeJob(e){let t=this.jobs.get(e);if(!t||!this.running)return;if(this.hooks?.has("pre:cron-run")){let n=await this.hooks.execute("pre:cron-run",{event:"pre:cron-run",jobId:e,agent:t.agent,prompt:t.prompt});if(n.blocked){this.log(`Job "${e}" blocked by hook: ${n.message}`),this.scheduleNext(e);return}}this.log(`Executing job "${e}" -> agent "${t.agent}"`);let s=new Date;t.lastRun=s,t.totalRuns++;try{let n=await this.registry.execute({message:t.prompt,agentId:t.agent,context:{channel:"cron"}}),r={jobId:e,startedAt:s,completedAt:new Date,success:!n.error,response:n.content,error:n.error,duration:n.duration||Date.now()-s.getTime()};n.error?(t.consecutiveErrors++,this.log(`Job "${e}" failed (${t.consecutiveErrors} consecutive): ${n.error}`),t.onError==="disable"&&t.consecutiveErrors>=3&&(t.enabled=!1,this.log(`Job "${e}" disabled after ${t.consecutiveErrors} consecutive errors`))):(t.consecutiveErrors=0,this.log(`Job "${e}" completed in ${r.duration}ms`)),this.logRun(r),this.hooks?.has("post:cron-run")&&await this.hooks.execute("post:cron-run",{event:"post:cron-run",jobId:e,success:r.success,duration:r.duration,error:r.error?new Error(r.error):void 0})}catch(n){t.consecutiveErrors++,this.log(`Job "${e}" threw: ${n.message}`)}this.scheduleNext(e)}logRun(e){try{let t=q(this.runsDir,e.jobId);he(t)||de(t,{recursive:!0});let s=`${e.startedAt.toISOString().replace(/[:.]/g,"-")}.json`;Ue(q(t,s),JSON.stringify(e,null,2))}catch{}}list(){return Array.from(this.jobs.values())}};import{createServer as Ke}from"http";var F=class{name="discord";token;agentBinding;handler;client=null;log;constructor(e,t=console.error.bind(console,"[discord]")){this.token=e.token,this.agentBinding=e.agentBinding,this.log=t}onMessage(e){this.handler=e}async start(){let e;try{e=await import("discord.js")}catch{this.log("Discord requires discord.js. Install with:"),this.log(" npm install discord.js");return}let{Client:t,GatewayIntentBits:s}=e;this.client=new t({intents:[s.Guilds,s.GuildMessages,s.MessageContent,s.DirectMessages]}),this.client.on("ready",()=>{this.log(`Discord connected as ${this.client.user?.tag}`)}),this.client.on("messageCreate",async n=>{if(!this.handler||n.author.bot)return;let r=n.mentions.users.has(this.client.user?.id),i=!n.guild;if(!r&&!i)return;let o=n.content;if(this.client.user&&(o=o.replace(new RegExp(`<@!?${this.client.user.id}>`,"g"),"").trim()),!o)return;let a={id:n.id,channel:"discord",accountId:"default",sender:{id:n.author.id,name:n.author.displayName||n.author.username,username:n.author.username},group:n.guild?{id:n.channelId,name:n.channel?.name||n.channelId}:void 0,text:o,replyTo:n.reference?.messageId,timestamp:n.createdAt,raw:n};this.handler(a).catch(g=>{this.log(`Error handling message: ${g.message}`)})});try{await this.client.login(this.token)}catch(n){this.log(`Discord login failed: ${n.message}`)}}async stop(){this.client&&(this.client.destroy(),this.client=null)}async send(e){if(!this.client)return"";try{let t=await this.client.channels.fetch(e.chatId);return t?.isTextBased()?(await t.send({content:e.text,...e.replyTo?{reply:{messageReference:e.replyTo}}:{}})).id:""}catch(t){return this.log(`Send error: ${t.message}`),""}}async editMessage(e,t,s){if(!this.client)return!1;try{let n=await this.client.channels.fetch(e);return n?.isTextBased()?(await(await n.messages.fetch(t)).edit(s),!0):!1}catch{return!1}}async sendTyping(e){if(this.client)try{let t=await this.client.channels.fetch(e);t?.isTextBased()&&await t.sendTyping()}catch{}}async react(e,t,s="\u{1F440}"){if(this.client)try{let n=await this.client.channels.fetch(e);if(!n?.isTextBased())return;await(await n.messages.fetch(t)).react(s)}catch{}}};var ue=class{config;registry;router;cron;mesh;hooks;httpServer;log;constructor(e){this.log=console.error.bind(console,"[agentx]"),this.log("Loading configuration..."),this.config=te(e);let t=se(this.config);for(let s of t)this.log(` \u26A0 ${s}`);this.hooks=new X,Z(process.cwd(),this.hooks),this.registry=new W(this.config,this.log),this.router=new O(this.registry,this.config,this.hooks,this.log),this.cron=new H(this.config,this.registry,this.hooks,this.log),this.config.mesh.enabled&&(this.mesh=new D(this.config,this.log),this.router.setMesh(this.mesh))}async start(){this.log(""),this.log(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),this.log(" \u2502 agentx daemon \u2502"),this.log(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),this.log(""),this.log(` Node: ${this.config.node.name} (${this.config.node.id})`),this.log(` Bind: ${this.config.node.bind}`),this.log(""),await this.startChannels(),await this.cron.start(),this.mesh&&await this.mesh.start(),await this.startHttpApi(),this.log(""),this.log(" Agents:");for(let t of this.registry.list())this.log(` ${t.id} (${t.tier}) \u2192 ${t.workspace}`);let e=this.cron.list();if(e.length){this.log(""),this.log(" Cron Jobs:");for(let t of e){let s=t.enabled?"enabled":"disabled";this.log(` ${t.id} [${s}] \u2192 ${t.agent} (${t.schedule})`)}}if(this.mesh){this.log(""),this.log(" Mesh Peers:");for(let t of this.mesh.directory()){let s=t.healthy?"\u2713":"\u2717";this.log(` ${s} ${t.peer} (${t.peerUrl})`)}}this.log(""),this.log(" Ready."),this.log(""),process.on("SIGINT",()=>this.stop()),process.on("SIGTERM",()=>this.stop())}async stop(){this.log("Shutting down..."),await this.router.stopAll(),await this.cron.stop(),this.mesh&&await this.mesh.stop(),this.httpServer&&this.httpServer.close(),this.log("Goodbye."),process.exit(0)}async startChannels(){if(this.config.channels.telegram.enabled){let e=this.config.channels.telegram.accounts;if(Object.keys(e).length>0){let t=new N(e,this.log);this.router.addChannel(t),this.log(" Telegram: enabled")}}if(this.config.channels.whatsapp.enabled){let e=new J({sessionDir:this.config.channels.whatsapp.sessionDir,defaultAgent:this.config.channels.whatsapp.defaultAgent,allowFrom:this.config.channels.whatsapp.allowFrom,routes:this.config.channels.whatsapp.routes},this.log);this.router.addChannel(e),this.log(` WhatsApp: enabled (${this.config.channels.whatsapp.routes.length} routes)`)}if(this.config.channels.discord?.enabled&&this.config.channels.discord.token){let e=new F({token:this.config.channels.discord.token,agentBinding:this.config.channels.discord.agentBinding},this.log);this.router.addChannel(e),this.log(" Discord: enabled")}await this.router.startAll()}async startHttpApi(){let[e,t]=this.config.node.bind.split(":"),s=parseInt(t||"18800",10);this.httpServer=Ke(async(n,r)=>{if(r.setHeader("Access-Control-Allow-Origin","*"),r.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),r.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),n.method==="OPTIONS"){r.writeHead(204),r.end();return}await this.handleHttp(n,r)}),this.httpServer.on("error",n=>{n.code==="EADDRINUSE"?(this.log(` ERROR: Port ${s} is already in use. Retrying in 5s...`),setTimeout(()=>{this.httpServer?.close(),this.httpServer?.listen(s,e||"0.0.0.0")},5e3)):this.log(` HTTP error: ${n.message}`)}),this.httpServer.listen(s,e||"0.0.0.0",()=>{this.log(` HTTP API: http://${e||"0.0.0.0"}:${s}`)})}async handleHttp(e,t){let n=new URL(e.url||"/",`http://${e.headers.host||"localhost"}`).pathname;try{switch(`${e.method} ${n}`){case"GET /health":this.json(t,200,{status:"ok",node:this.config.node,uptime:process.uptime(),agents:this.registry.list(),crons:this.cron.list().map(r=>({id:r.id,enabled:r.enabled,nextRun:r.nextRun})),mesh:this.mesh?.directory()||[]});break;case"GET /agents":this.json(t,200,this.registry.list());break;case"GET /crons":this.json(t,200,this.cron.list());break;case"GET /mesh":this.json(t,200,this.mesh?.directory()||[]);break;case"POST /task":{let r=await pe(e);if(!r.agent||!r.message){this.json(t,400,{error:"Missing: agent, message"});return}let i=await this.registry.execute({agentId:r.agent,message:r.message,context:r.context});this.json(t,i.error?500:200,i);break}case"POST /mesh/task":{let r=await pe(e);if(!r.peer||!r.message){this.json(t,400,{error:"Missing: peer, message"});return}if(!this.mesh){this.json(t,400,{error:"Mesh not enabled"});return}let i=await this.mesh.sendTask(r.peer,r.message);this.json(t,200,{response:i});break}case"GET /.well-known/agent-card.json":this.json(t,200,{name:this.config.node.name,description:`AgentX daemon node "${this.config.node.name}"`,url:`http://${this.config.node.bind}`,version:"1.0.0",capabilities:{streaming:!1,pushNotifications:!1,stateTransitionHistory:!1},skills:this.registry.list().map(r=>({id:r.id,name:r.name,description:`Agent "${r.name}" (${r.tier})`,tags:[r.tier]})),defaultInputModes:["text"],defaultOutputModes:["text"]});break;default:this.json(t,404,{error:"Not found",endpoints:["GET /health","GET /agents","GET /crons","GET /mesh","POST /task { agent, message, context? }","POST /mesh/task { peer, message }","GET /.well-known/agent-card.json"]})}}catch(r){this.json(t,500,{error:r.message})}}json(e,t,s){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(s,null,2))}};async function pe(l){return new Promise((e,t)=>{let s="";l.on("data",n=>s+=n.toString()),l.on("end",()=>{try{e(s?JSON.parse(s):{})}catch{e({})}}),l.on("error",t)})}import ze from"path";import Ve from"fs-extra";function Ut(){let l=ze.join("package.json");return Ve.readJSONSync(l)}export{M as a,D as b,Se as c,te as d,se as e,De as f,Pe as g,Re as h,ie as i,S as j,W as k,O as l,N as m,J as n,H as o,ue as p,Ut as q};
|
|
35
|
-
//# sourceMappingURL=chunk-S74N276K.js.map
|