agentix-cli 0.2.0 → 0.3.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/README.md +192 -107
- package/dist/agent-CRA5PU6S.js +2 -0
- package/dist/chunk-KVWUPUR5.js +106 -0
- package/dist/chunk-KVWUPUR5.js.map +1 -0
- package/dist/chunk-M7HKBG3V.js +2 -0
- package/dist/chunk-M7HKBG3V.js.map +1 -0
- package/dist/chunk-MDR7SH7F.js +2 -0
- package/dist/chunk-MGMZNJCE.js +46 -0
- package/dist/chunk-MGMZNJCE.js.map +1 -0
- package/dist/chunk-PCAYW54Q.js +12 -0
- package/dist/chunk-PCAYW54Q.js.map +1 -0
- package/dist/chunk-S74N276K.js +35 -0
- package/dist/chunk-S74N276K.js.map +1 -0
- package/dist/{chunk-6PVFYFUE.js → chunk-X7UN6JAA.js} +2 -2
- package/dist/{chunk-6PVFYFUE.js.map → chunk-X7UN6JAA.js.map} +1 -1
- package/dist/cli.js +9 -155
- package/dist/cli.js.map +1 -1
- package/dist/heal-RDZZJXDZ.js +2 -0
- package/dist/index.d.ts +239 -8
- package/dist/index.js +85 -1
- package/dist/index.js.map +1 -1
- package/dist/loader-RL2LKXIF.js +2 -0
- package/dist/providers-Q3U3ONJO.js +2 -0
- package/dist/providers-Q3U3ONJO.js.map +1 -0
- package/package.json +3 -1
- package/dist/agent-AI6DUEPU.js +0 -2
- package/dist/chunk-FUYKPFUV.js +0 -46
- package/dist/chunk-FUYKPFUV.js.map +0 -1
- package/dist/chunk-NZ6W33BD.js +0 -116
- package/dist/chunk-NZ6W33BD.js.map +0 -1
- package/dist/chunk-THMHQELC.js +0 -106
- package/dist/chunk-THMHQELC.js.map +0 -1
- package/dist/heal-MJLBETRV.js +0 -2
- package/dist/loader-PHU6STSZ.js +0 -2
- package/dist/providers-MPYTYJVB.js +0 -2
- /package/dist/{agent-AI6DUEPU.js.map → agent-CRA5PU6S.js.map} +0 -0
- /package/dist/{heal-MJLBETRV.js.map → chunk-MDR7SH7F.js.map} +0 -0
- /package/dist/{loader-PHU6STSZ.js.map → heal-RDZZJXDZ.js.map} +0 -0
- /package/dist/{providers-MPYTYJVB.js.map → loader-RL2LKXIF.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,157 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
3
|
-
`).
|
|
4
|
-
`)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
`).map(n=>n.length?e+n:n).join(`
|
|
9
|
-
`)
|
|
10
|
-
`).
|
|
11
|
-
`),n=[];for(let r of e){let i=r.trimEnd();if(/^\s*#{1,6}\s+/.test(i)){let s=i.replace(/^\s*#{1,6}\s+/,"");n.push(I.bold(fe(s)));continue}if(/^\s*([-*_]\s*){3,}$/.test(i)){n.push(I.dim("\u2500".repeat(40)));continue}if(/^\s*>\s?/.test(i)){n.push(I.dim("\u2502 ")+fe(i.replace(/^\s*>\s?/,"")));continue}n.push(fe(i))}return n.join(`
|
|
12
|
-
`)}function ie(o){let e=(o||"").replace(/\r\n/g,`
|
|
13
|
-
`);if(!e.trim())return"";let n=e.split(/```/g);if(n.length===1)return Be(e);let r=[];for(let i=0;i<n.length;i++){let s=n[i];if(!(i%2===1)){r.push(Be(s));continue}let p=s.indexOf(`
|
|
14
|
-
`),f=p===-1?s.trim():s.slice(0,p).trim(),g=p===-1?"":s.slice(p+1),a=f?I.dim("```"+f):I.dim("```"),m=I.dim("```"),w=I.dim(ft(g.replace(/\s+$/g,""),""));r.push([a,w,m].filter(Boolean).join(`
|
|
15
|
-
`))}return r.join(`
|
|
16
|
-
`).replace(/^\n+|\n+$/g,"")}var yt=T.object({task:T.string().optional(),type:T.string().default("auto"),output:T.string().optional(),overwrite:T.boolean().default(!1),dryRun:T.boolean().default(!1),provider:T.enum(["claude-code","claude","openai","ollama","custom"]).default("claude-code"),model:T.string().optional(),apiKey:T.string().optional(),cwd:T.string(),noContext7:T.boolean().default(!1),yes:T.boolean().default(!1)}),We=new ht().name("generate").aliases(["gen","g"]).description("generate anything using AI \u2014 components, pages, APIs, docs, skills, and more").argument("[task...]","describe what you want to generate").option("-t, --type <type>",`output type: ${ce.join(", ")}`,"auto").option("-o, --output <dir>","output directory").option("--overwrite","overwrite existing files",!1).option("--dry-run","preview without writing files",!1).option("-p, --provider <provider>","AI provider (claude-code, claude, openai, ollama)","claude-code").option("-m, --model <model>","model to use").option("--api-key <key>","API key for the provider").option("-c, --cwd <cwd>","working directory",process.cwd()).option("--no-context7","disable Context7 documentation lookup").option("--max-steps <n>","max agentic loop steps for complex generation (default: 5)","5").option("-y, --yes","skip confirmation prompts",!1).option("--debug","enable debug mode with verbose logging",!1).option("--no-tui","disable interactive TUI output").option("--mode <mode>","permission mode (default, acceptEdits, plan, yolo)","yolo").option("--heal","verify generated code and auto-fix errors").option("--no-heal","skip verification after generation").option("--test-cmd <cmd>","test command for heal verification").option("--build-cmd <cmd>","build command for heal verification").action(async(o,e)=>{try{let n=o?.length?o.join(" "):e.task;e.debug&&_(!0),e.mode&&H.setMode(e.mode);let r=ut.resolve(e.cwd);if(gt(r)||(t.error(`The path ${r} does not exist.`),process.exit(1)),!n){let m=await ge({type:"text",name:"task",message:"What would you like to generate?",validate:w=>w.trim()?!0:"Please describe what to generate"});m.task||(t.warn("No task provided. Exiting."),process.exit(0)),n=m.task}if(e.type==="auto"&&!e.yes){let{type:m}=await ge({type:"select",name:"type",message:"Output type (or auto-detect)",choices:[{title:"Auto-detect",value:"auto"},...ce.filter(w=>w!=="auto").map(w=>({title:`${w} \u2014 ${Ce[w]}`,value:w}))],initial:0});m!==void 0&&(e.type=m)}let i=yt.parse({task:n,...e,apiKey:e.apiKey,noContext7:!e.context7}),s=parseInt(e.maxSteps||"5",10),d=!!e.tui&&!!process.stdout.isTTY&&!e.debug,p=!d&&!e.debug?wt("Waiting for provider...").start():void 0,f=d?new J({task:n,provider:i.provider,model:i.model,cwd:r,outputDir:i.output,outputType:i.type,maxSteps:s,overwrite:i.overwrite,dryRun:i.dryRun}):void 0;d||(t.break(),t.info(`Task: ${E.bold(n)}`),t.info(`Provider: ${E.bold(i.provider)}`),i.type!=="auto"&&t.info(`Type: ${E.bold(i.type)}`),i.output&&t.info(`Output: ${E.bold(i.output)}`),i.dryRun&&t.warn("Dry run mode \u2014 no files will be written"),t.break()),f?.start();let g,a;for await(let m of de({task:n,outputType:i.type,outputDir:i.output,overwrite:i.overwrite,dryRun:i.dryRun,provider:i.provider,model:i.model,apiKey:i.apiKey,cwd:r,context7:!i.noContext7,interactive:!i.yes,maxSteps:s,heal:e.heal,healConfig:e.testCmd||e.buildCmd?{testCommand:e.testCmd,buildCommand:e.buildCmd}:void 0}))f?.onEvent(m),d||(m.type==="context_ready"&&p&&(p.text="Generating..."),m.type==="context_ready"?(t.info("Analyzing project... done"),t.info(`Output type: ${m.outputType}`)):m.type==="iteration"?t.info(`Step ${m.iteration}/${s}...`):m.type==="tool_call"?t.info(`Tool: ${m.name}`):m.type==="tool_result"?t.info(`Tool result: ${m.name}${m.is_error?" (error)":""}`):m.type==="error"&&t.error(m.error)),m.type==="generate_result"&&(g=m.result),m.type==="error"&&(a=m.error);if(p?.stop(),f?.stop(),a)throw new Error(a);if(!g)throw new Error("Generation finished without a result");if(g.followUp){if(t.break(),t.info(E.yellow("The agent needs more information:")),t.break(),g.content){let w=process.stdout.isTTY?ie(g.content):g.content;console.log(w),t.break()}console.log(process.stdout.isTTY?ie(g.followUp):g.followUp),t.break();let{answer:m}=await ge({type:"text",name:"answer",message:"Your answer:"});if(m){let w=`${n}
|
|
17
|
-
|
|
18
|
-
Previous agent output (for context):
|
|
19
|
-
${g.content||""}
|
|
20
|
-
|
|
21
|
-
User response: ${m}
|
|
22
|
-
|
|
23
|
-
If the above was a plan awaiting approval and the user approved, proceed to implementation now using create_files (do not ask for approval again).`,R=d?new J({task:w,provider:i.provider,model:i.model,cwd:r,outputDir:i.output,outputType:i.type,maxSteps:s,overwrite:i.overwrite,dryRun:i.dryRun}):void 0;R?.start();let j,N;for await(let M of de({task:w,outputType:i.type,outputDir:i.output,overwrite:i.overwrite,dryRun:i.dryRun,provider:i.provider,model:i.model,apiKey:i.apiKey,cwd:r,context7:!i.noContext7,interactive:!1,maxSteps:s,heal:e.heal,healConfig:e.testCmd||e.buildCmd?{testCommand:e.testCmd,buildCommand:e.buildCmd}:void 0}))R?.onEvent(M),M.type==="generate_result"&&(j=M.result),M.type==="error"&&(N=M.error);if(R?.stop(),N)throw new Error(N);if(!j)throw new Error("Generation finished without a result");Ye(j)}}else Ye(g)}catch(n){u(n)}});function Ye(o){if(t.break(),o.content){let e=process.stdout.isTTY?ie(o.content):o.content;console.log(e),t.break()}if(o.files.written.length){t.success(`Created ${o.files.written.length} file(s):`);for(let e of o.files.written)console.log(` ${E.green("+")} ${e}`)}if(o.files.skipped.length){t.warn(`Skipped ${o.files.skipped.length} existing file(s):`);for(let e of o.files.skipped)console.log(` ${E.yellow("~")} ${e} (use --overwrite)`)}if(o.files.errors.length){t.error(`Failed ${o.files.errors.length} file(s):`);for(let e of o.files.errors)console.log(` ${E.red("x")} ${e}`)}if(o.healResult&&(t.break(),o.healResult.healed?o.healResult.attempts===0?t.success("Verification passed \u2014 generated code is clean"):t.success(`Auto-healed in ${o.healResult.attempts} attempt(s)`+(o.healResult.filesChanged?.length?` (fixed: ${o.healResult.filesChanged.join(", ")})`:"")):o.healResult.error&&(t.error(`Verification failed after ${o.healResult.attempts} attempt(s):`),console.log(E.dim(` ${o.healResult.error.split(`
|
|
24
|
-
`).slice(0,3).join(`
|
|
25
|
-
`)}`)))),o.tokensUsed){t.break();let e=V.getSummary();if(e.steps.length>1){t.info(`Tokens used: ${o.tokensUsed} across ${e.steps.length} steps`);for(let n of e.steps)t.info(` Step ${n.step}: ${(n.inputTokens+n.outputTokens).toLocaleString()} tokens ($${n.cost.toFixed(4)})`);t.info(` Total cost: $${e.totalCost.toFixed(4)}`)}else t.info(`Tokens used: ${o.tokensUsed} ($${e.totalCost.toFixed(4)})`)}}import{existsSync as kt,promises as ue}from"fs";import ne from"path";import v from"chalk";import{Command as bt}from"commander";import he from"ora";import we from"prompts";import vt from"fast-glob";var qe=new bt().name("evolve").aliases(["ev","transform"]).description("modify existing code using AI \u2014 add features, refactor, migrate patterns").argument("[task...]","describe the transformation to apply").option("-g, --glob <pattern>","glob pattern for files to evolve (e.g., src/components/**/*.tsx)").option("--max-files <n>","maximum number of files to process","10").option("-p, --provider <provider>","AI provider (claude-code, claude)","claude-code").option("-m, --model <model>","model to use").option("--api-key <key>","API key").option("-c, --cwd <cwd>","working directory",process.cwd()).option("--no-context7","disable Context7 doc lookup").option("-y, --yes","apply all changes without confirmation",!1).option("--dry-run","show proposed changes without writing",!1).option("--debug","enable debug mode with verbose logging",!1).option("--mode <mode>","permission mode (default, acceptEdits, plan, yolo)").option("--heal","verify generated code and auto-fix errors").option("--no-heal","skip verification after applying changes").option("--test-cmd <cmd>","test command for heal verification").option("--build-cmd <cmd>","build command for heal verification").action(async(o,e)=>{try{let n=o?.length?o.join(" "):void 0,r=ne.resolve(e.cwd);if(kt(r)||(t.error(`The path ${r} does not exist.`),process.exit(1)),e.debug&&_(!0),e.mode&&H.setMode(e.mode),!n){let l=await we({type:"text",name:"task",message:"Describe the transformation to apply:",validate:y=>y.trim()?!0:"Please describe the transformation"});l.task||(t.warn("No task provided. Exiting."),process.exit(0)),n=l.task}let i=n;if(x.has("pre:prompt")){let l=await x.execute("pre:prompt",{event:"pre:prompt",task:i,cwd:r});l.blocked&&(t.error(l.message||"Blocked by pre:prompt hook"),process.exit(1)),l.modified?.task&&(i=String(l.modified.task))}if(x.has("pre:generate")){let l=await x.execute("pre:generate",{event:"pre:generate",task:i,cwd:r});l.blocked&&(t.error(l.message||"Blocked by pre:generate hook"),process.exit(1))}let s=e.glob;if(!s){let l=await we({type:"text",name:"glob",message:"File pattern to evolve (glob):",initial:"src/**/*.{ts,tsx,js,jsx}",validate:y=>y.trim()?!0:"Pattern is required"});l.glob||(t.warn("No pattern provided. Exiting."),process.exit(0)),s=l.glob}let d=await vt.glob(s,{cwd:r,ignore:["**/node_modules/**","**/dist/**","**/build/**","**/.next/**","**/target/**","**/.git/**"],onlyFiles:!0}),p=parseInt(e.maxFiles,10);d.length||(t.warn(`No files matched pattern: ${s}`),process.exit(0));let f=d.slice(0,p);d.length>p&&t.warn(`Found ${d.length} files, processing first ${p}. Use --max-files to increase.`),t.break(),t.info(`Task: ${v.bold(i)}`),t.info(`Files: ${v.bold(String(f.length))} matching ${v.dim(s)}`),t.break();let g=he("Reading files and analyzing project...").start(),a=[];for(let l of f){let y=ne.resolve(r,l),b=await ue.readFile(y,"utf8");a.push({path:l,content:b})}let m=await te(r,i,{provider:e.provider,context7:{enabled:e.context7!==!1}}),w=Pe(m.skills,i,void 0);w.length&&ee.context("skills",`${w.length} matched for evolve`),g.text="Generating transformations...";let R=$t(m,w.map(l=>l.skill)),j=a.map(l=>`## File: ${l.path}
|
|
26
|
-
\`\`\`
|
|
27
|
-
${Ct(l.content,4e3)}
|
|
28
|
-
\`\`\``).join(`
|
|
29
|
-
|
|
30
|
-
`),N=`# Transformation Task
|
|
31
|
-
${i}
|
|
32
|
-
|
|
33
|
-
# Files to Transform
|
|
34
|
-
${j}
|
|
35
|
-
|
|
36
|
-
Transform these files according to the task. For each file that needs changes, use \`create_files\` with the complete updated file content. Only include files that actually need changes \u2014 skip files that don't need modification.`;await Z(e.apiKey)||(t.error("No credentials configured. Run `agentx model` to set up."),process.exit(1));let Q=e.provider,ae=U(Q,e.apiKey),D=e.model||X()?.model,rt=[{role:"system",content:R},{role:"user",content:N}];ee.step(1,`Starting evolve generation (model: ${D||"default"})`);let C=await ae.generate(rt,{model:D,maxTokens:16384}),le=C.tokensUsed||0,ve=D||"claude-sonnet-4-20250514",$e=Math.round(le*.3),st=le-$e;if(V.recordStep(1,ve,$e,st),ee.api("evolve",ve,le),g.stop(),C.followUp){t.break(),t.info(v.yellow("The agent needs more information:")),t.break(),console.log(C.followUp),t.break();return}if(!C.files.length){t.info("No changes proposed."),C.content&&(t.break(),console.log(C.content));return}let W=[];for(let l of C.files){let y=a.find(b=>b.path===l.path);W.push({path:l.path,original:y?.content||"",proposed:l.content,description:l.description})}t.break(),console.log(v.bold(` ${W.length} file(s) with proposed changes:`)),t.break(),C.content&&(console.log(v.dim(C.content)),t.break());let P=[];for(let l of W){console.log(v.bold.cyan(` ${l.path}`)),l.description&&console.log(v.dim(` ${l.description}`)),t.break();let y=xt(l.original,l.proposed);for(let b of y.slice(0,40))b.startsWith("+")?console.log(v.green(` ${b}`)):b.startsWith("-")?console.log(v.red(` ${b}`)):console.log(v.dim(` ${b}`));if(y.length>40&&console.log(v.dim(` ... ${y.length-40} more lines`)),t.break(),e.yes||e.dryRun)P.push(l);else{let{action:b}=await we({type:"select",name:"action",message:`${l.path}`,choices:[{title:"Accept",value:"accept"},{title:"Skip",value:"skip"},{title:"Accept all remaining",value:"accept-all"},{title:"Quit",value:"quit"}]});if(b==="accept")P.push(l);else if(b==="accept-all"){P.push(l);let S=W.slice(W.indexOf(l)+1);P.push(...S);break}else if(b==="quit")break}}if(!P.length){t.info("No changes applied.");return}if(e.dryRun){t.break(),t.success(`Dry run: ${P.length} file(s) would be modified:`);for(let l of P)console.log(` ${v.green("~")} ${l.path}`);return}let at=he("Applying changes...").start(),xe=0,L=0,q=[];for(let l of P){if(x.has("pre:file-write")){let y=await x.execute("pre:file-write",{event:"pre:file-write",file:l.path,fileContent:l.proposed,cwd:r});if(y.blocked){t.warn(`Skipped ${l.path}: ${y.message||"blocked by hook"}`);continue}}try{let y=ne.resolve(r,l.path),b=ne.dirname(y);await ue.mkdir(b,{recursive:!0}),await ue.writeFile(y,l.proposed,"utf8"),xe++,q.push(l.path),x.has("post:file-write")&&await x.execute("post:file-write",{event:"post:file-write",file:l.path,cwd:r})}catch(y){t.error(`Failed to write ${l.path}: ${y.message}`),L++}}at.stop(),t.break(),t.success(`Applied ${xe} change(s):`);for(let l of P)q.includes(l.path)&&console.log(` ${v.green("~")} ${l.path}`);L&&t.error(`${L} file(s) failed to write.`);try{let l=new Re(r);await l.load(),await l.recordGeneration({type:"evolution",task:i,files:q,success:L===0,error:L>0?`${L} file(s) failed to write`:void 0,context:{techStack:m.techStack.languages.map(String),frameworks:m.techStack.frameworks.map(String),skillsUsed:w.map(y=>y.skill.frontmatter.name)}})}catch{}if(e.heal!==!1&&q.length>0){let{HealEngine:l}=await import("./heal-MJLBETRV.js"),y=new l(r,{enabled:!0,testCommand:e.testCmd,buildCommand:e.buildCmd,maxAttempts:3,provider:Q,model:D,apiKey:e.apiKey}),b=he("Verifying changes...").start(),S=await y.detectAndHeal(q,i);b.stop(),S.healed?S.attempts===0?t.success("Verification passed \u2014 changes are clean"):t.success(`Auto-healed in ${S.attempts} attempt(s)`+(S.filesChanged.length?` (fixed: ${S.filesChanged.join(", ")})`:"")):S.error&&(t.error(`Verification failed after ${S.attempts} attempt(s):`),console.log(v.dim(` ${S.error.split(`
|
|
37
|
-
`).slice(0,3).join(`
|
|
38
|
-
`)}`)),await x.execute("on:error",{event:"on:error",error:new Error(S.error),task:i,cwd:r}))}if(x.has("post:generate")&&await x.execute("post:generate",{event:"post:generate",task:i,content:C.content,cwd:r}),C.tokensUsed){t.break();let l=V.getSummary();t.info(`Tokens used: ${C.tokensUsed} ($${l.totalCost.toFixed(4)})`)}}catch(n){u(n)}});function $t(o,e){let n=[];n.push(`You are agentx evolve, an agentic code transformation tool. You modify existing code according to user instructions.
|
|
39
|
-
|
|
40
|
-
Your primary tool is \`create_files\` \u2014 use it to output the COMPLETE updated content of each file that needs changes.
|
|
41
|
-
If the request is ambiguous, use \`ask_user\` to ask a clarifying question.
|
|
42
|
-
|
|
43
|
-
CRITICAL RULES:
|
|
44
|
-
- Output the FULL file content for each changed file (not just the diff)
|
|
45
|
-
- Keep the file path exactly as given \u2014 do not rename files unless explicitly asked
|
|
46
|
-
- Preserve existing code patterns, naming conventions, and style
|
|
47
|
-
- Only modify what's necessary for the transformation
|
|
48
|
-
- Do NOT remove unrelated code or comments
|
|
49
|
-
- Do NOT add unrelated features or "improvements"
|
|
50
|
-
- Include all existing imports \u2014 do not accidentally drop them
|
|
51
|
-
- If a file doesn't need changes, do NOT include it in the output`),n.push(`# Project Tech Stack
|
|
52
|
-
${Ie(o.techStack)}`);let r=Object.keys(o.techStack.dependencies).slice(0,20);r.length&&n.push(`# Key Dependencies
|
|
53
|
-
${r.join(", ")}`);let i=Ae(o.schemas);return i&&n.push(`# Project Schemas
|
|
54
|
-
${i}`),e.length&&n.push(`# Active Skills
|
|
55
|
-
`+e.map(s=>`## ${s.frontmatter.name}
|
|
56
|
-
${s.frontmatter.description}
|
|
57
|
-
|
|
58
|
-
${s.instructions}`).join(`
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
`)),o.docs&&n.push(o.docs),o.projectInstructions&&n.push(`# Project Instructions
|
|
63
|
-
${o.projectInstructions}`),o.memoryContext&&n.push(o.memoryContext),n.join(`
|
|
64
|
-
|
|
65
|
-
`)}function xt(o,e){let n=o.split(`
|
|
66
|
-
`),r=e.split(`
|
|
67
|
-
`),i=[],s=Math.max(n.length,r.length),d=[],p=-10;for(let f=0;f<s;f++){let g=f<n.length?n[f]:void 0,a=f<r.length?r[f]:void 0;g===a?f-p<=2?i.push(` ${g}`):(d.push(` ${g}`),d.length>2&&d.shift()):(f-p>3&&i.length>0&&i.push(" ..."),i.push(...d),d=[],g!==void 0&&a!==void 0?(i.push(`-${g}`),i.push(`+${a}`)):g!==void 0?i.push(`-${g}`):a!==void 0&&i.push(`+${a}`),p=f)}return i}function Ct(o,e){return o.length<=e?o:o.slice(0,e)+`
|
|
68
|
-
// ... (truncated)`}import{existsSync as Tt,promises as St}from"fs";import Ve from"path";import $ from"chalk";import{Command as It}from"commander";import At from"ora";import re from"prompts";var K=[{name:"saas-starter",description:"Full-stack SaaS starter with auth, billing, dashboard, and landing page",prompt:`Create a full-stack SaaS starter project with:
|
|
69
|
-
1. Authentication (sign up, sign in, forgot password, email verification)
|
|
70
|
-
2. Billing integration with Stripe (pricing page, checkout, subscription management, webhooks)
|
|
71
|
-
3. Dashboard with sidebar navigation, user profile, settings page
|
|
72
|
-
4. Landing page with hero, features, pricing, testimonials, FAQ, footer
|
|
73
|
-
5. Database schema for users, subscriptions, teams
|
|
74
|
-
6. API routes for all CRUD operations
|
|
75
|
-
7. Middleware for auth protection
|
|
76
|
-
8. Environment variables template`,skills:[],outputType:"website",tags:["saas","auth","billing","stripe","dashboard"]},{name:"api-service",description:"REST API service with auth, validation, error handling, and tests",prompt:`Create a REST API service with:
|
|
77
|
-
1. Project structure with routes, controllers, middleware, models, utils
|
|
78
|
-
2. Authentication middleware (JWT)
|
|
79
|
-
3. Input validation using the project's validation library
|
|
80
|
-
4. Centralized error handling with proper HTTP status codes
|
|
81
|
-
5. Health check endpoint
|
|
82
|
-
6. CRUD endpoints for a sample resource
|
|
83
|
-
7. Request logging middleware
|
|
84
|
-
8. Rate limiting
|
|
85
|
-
9. Environment configuration
|
|
86
|
-
10. Test suite for all endpoints`,skills:[],outputType:"api",tags:["api","rest","backend","auth","jwt"]},{name:"cli-tool",description:"CLI application with commands, flags, interactive prompts, and config",prompt:`Create a CLI tool with:
|
|
87
|
-
1. Command framework setup (commander or similar)
|
|
88
|
-
2. Multiple subcommands with flags and arguments
|
|
89
|
-
3. Interactive prompts for user input
|
|
90
|
-
4. Configuration file support (read/write)
|
|
91
|
-
5. Colored output and spinners
|
|
92
|
-
6. Help text and version command
|
|
93
|
-
7. Error handling with friendly messages
|
|
94
|
-
8. A sample command that demonstrates all features`,skills:[],outputType:"script",tags:["cli","tool","command-line"]},{name:"component-library",description:"UI component library with Storybook, tests, and documentation",prompt:`Create a UI component library with:
|
|
95
|
-
1. Button, Input, Card, Modal, Dropdown, Alert, Badge, Avatar components
|
|
96
|
-
2. Consistent theming system (colors, typography, spacing)
|
|
97
|
-
3. All components are accessible (ARIA, keyboard navigation)
|
|
98
|
-
4. Component props are typed and documented
|
|
99
|
-
5. Each component has unit tests
|
|
100
|
-
6. Storybook stories for each component
|
|
101
|
-
7. Export barrel file
|
|
102
|
-
8. Package.json configured for publishing`,skills:[],outputType:"component",tags:["components","ui","library","storybook"]},{name:"fullstack-app",description:"Full-stack application with database, API, UI, and deployment config",prompt:`Create a full-stack application with:
|
|
103
|
-
1. Database schema with models for a practical app (e.g., task management)
|
|
104
|
-
2. API layer with CRUD operations for all models
|
|
105
|
-
3. Frontend pages: home, list view, detail view, create/edit forms
|
|
106
|
-
4. Authentication flow (login, register, protected routes)
|
|
107
|
-
5. Form validation on client and server
|
|
108
|
-
6. Loading states and error handling in the UI
|
|
109
|
-
7. Docker configuration for development
|
|
110
|
-
8. CI/CD workflow for GitHub Actions
|
|
111
|
-
9. Environment configuration template`,skills:[],outputType:"website",tags:["fullstack","app","database","auth"]},{name:"mobile-app",description:"Mobile application with navigation, screens, and native features",prompt:`Create a mobile application with:
|
|
112
|
-
1. Navigation setup (tab navigation + stack navigation)
|
|
113
|
-
2. Screens: Home, Profile, Settings, List, Detail
|
|
114
|
-
3. Authentication flow (login, register)
|
|
115
|
-
4. Theme system with dark mode support
|
|
116
|
-
5. State management setup
|
|
117
|
-
6. API client configuration
|
|
118
|
-
7. Common components (Button, Card, Input, Header)
|
|
119
|
-
8. App configuration and assets setup`,skills:[],outputType:"page",tags:["mobile","react-native","expo","flutter"]},{name:"chrome-extension",description:"Browser extension with popup, content script, background worker, and options",prompt:`Create a browser extension (Chrome/Firefox compatible) with:
|
|
120
|
-
1. manifest.json (Manifest V3)
|
|
121
|
-
2. Popup page with UI
|
|
122
|
-
3. Content script that modifies web pages
|
|
123
|
-
4. Background service worker for event handling
|
|
124
|
-
5. Options/settings page
|
|
125
|
-
6. Storage management for user preferences
|
|
126
|
-
7. Message passing between popup, content script, and background
|
|
127
|
-
8. Icons and assets structure
|
|
128
|
-
9. Build script`,skills:[],outputType:"website",tags:["extension","chrome","browser","plugin"]},{name:"data-pipeline",description:"Data processing pipeline with ingestion, transformation, and output stages",prompt:`Create a data processing pipeline with:
|
|
129
|
-
1. Data ingestion from multiple sources (file, API, database)
|
|
130
|
-
2. Transformation stage with configurable processors
|
|
131
|
-
3. Validation and error handling at each stage
|
|
132
|
-
4. Output to multiple destinations (file, database, API)
|
|
133
|
-
5. Logging and monitoring
|
|
134
|
-
6. Configuration file for pipeline definition
|
|
135
|
-
7. CLI runner with progress reporting
|
|
136
|
-
8. Test suite with sample data
|
|
137
|
-
9. Docker configuration`,skills:[],outputType:"script",tags:["data","pipeline","etl","processing"]}],ze=new It().name("create").description("scaffold a new project from a template using AI").argument("[name]","project name").option("-t, --template <template>",`template to use: ${K.map(o=>o.name).join(", ")}`).option("-p, --provider <provider>","AI provider (claude-code, claude)","claude-code").option("-m, --model <model>","model to use").option("--api-key <key>","API key").option("-c, --cwd <cwd>","parent directory",process.cwd()).option("--list","list available templates",!1).option("-y, --yes","skip confirmation prompts",!1).action(async(o,e)=>{try{if(e.list){t.break(),console.log($.bold(" Available templates:")),t.break();for(let d of K)console.log(` ${$.green(d.name)}`),console.log(` ${$.dim(d.description)}`),console.log(` ${$.dim("tags:")} ${d.tags.map(p=>$.cyan(p)).join(", ")}`),t.break();return}if(!o){let d=await re({type:"text",name:"name",message:"Project name:",validate:p=>p.trim()?/^[a-z0-9-_.]+$/.test(p.trim())?!0:"Use lowercase letters, numbers, hyphens, dots, or underscores":"Name is required"});d.name||(t.warn("No name provided. Exiting."),process.exit(0)),o=d.name}let n;if(e.template)n=K.find(d=>d.name===e.template),n||(t.error(`Template "${e.template}" not found. Available: ${K.map(d=>d.name).join(", ")}`),t.info(`Run ${$.green("agentx create --list")} to see all templates.`),process.exit(1));else{let{selected:d}=await re({type:"select",name:"selected",message:"Choose a template:",choices:[...K.map(p=>({title:`${p.name} \u2014 ${p.description}`,value:p.name})),{title:"Custom \u2014 describe your own project",value:"_custom"}]});if(d||(t.warn("No template selected. Exiting."),process.exit(0)),d==="_custom"){let{description:p}=await re({type:"text",name:"description",message:"Describe the project you want to create:",validate:f=>f.trim()?!0:"Description is required"});p||(t.warn("No description provided. Exiting."),process.exit(0)),n={name:"custom",description:p,prompt:p,skills:[],outputType:"website",tags:[]}}else n=K.find(p=>p.name===d)}let r=Ve.resolve(e.cwd,o);if(Tt(r)){if(!e.yes){let{overwrite:d}=await re({type:"confirm",name:"overwrite",message:`Directory "${o}" already exists. Continue?`,initial:!1});if(!d){t.info("Cancelled.");return}}}else await St.mkdir(r,{recursive:!0});t.break(),t.info(`Project: ${$.bold(o)}`),t.info(`Template: ${$.bold(n.name)}`),t.info(`Directory: ${$.dim(r)}`),t.break();let i=At("Generating project from template...").start(),s=await je({task:`Create a new project called "${o}" in the current directory.
|
|
138
|
-
|
|
139
|
-
${n.prompt}
|
|
140
|
-
|
|
141
|
-
Generate all files relative to the project root. Include a README.md explaining the project and how to get started.`,outputType:n.outputType,cwd:r,overwrite:!0,dryRun:!1,provider:e.provider,model:e.model,apiKey:e.apiKey,context7:!0,interactive:!1,maxSteps:5});if(i.stop(),t.break(),s.content&&(console.log(s.content),t.break()),s.files.written.length){t.success(`Created ${s.files.written.length} file(s) in ${$.bold(o)}/`);for(let d of s.files.written){let p=Ve.relative(r,d);console.log(` ${$.green("+")} ${p}`)}}if(s.files.errors.length){t.error(`${s.files.errors.length} file(s) failed:`);for(let d of s.files.errors)console.log(` ${$.red("x")} ${d}`)}t.break(),t.info("Next steps:"),console.log(` ${$.green("cd")} ${o}`),console.log(` ${$.green("agentx inspect")} \u2014 see what was generated`),console.log(` ${$.green("agentx evolve")} \u2014 modify and extend`),t.break(),s.tokensUsed&&t.info(`Tokens used: ${s.tokensUsed}`)}catch(n){u(n)}});import{existsSync as Je,promises as Pt}from"fs";import Qe from"path";import ye from"chalk";import{Command as Et}from"commander";var Xe=new Et().name("run").description("start the agentx runtime \u2014 an intelligent framework that receives requests, learns, auto-heals, and self-enhances").option("--port <port>","server port","3170").option("--host <host>","server host","0.0.0.0").option("-p, --provider <provider>","AI provider (claude-code, claude)","claude-code").option("-m, --model <model>","model to use").option("--api-key <key>","API key").option("-c, --cwd <cwd>","working directory",process.cwd()).option("--no-memory","disable memory/learning").option("--no-heal","disable auto-heal").option("--no-enhance","disable self-enhancement").option("--test-cmd <cmd>","test command for auto-heal").option("--build-cmd <cmd>","build command for auto-heal").option("--no-cors","disable CORS").action(async o=>{try{let e=Qe.resolve(o.cwd);Je(e)||(t.error(`The path ${e} does not exist.`),process.exit(1));let n=Qe.resolve(e,"agentx.config.json"),r={};if(Je(n))try{let d=await Pt.readFile(n,"utf8");r=JSON.parse(d),t.info(`Loaded config from ${ye.dim("agentx.config.json")}`)}catch{t.warn("Failed to parse agentx.config.json, using defaults")}let i={port:parseInt(o.port,10)||r.port,host:o.host||r.host,provider:o.provider||r.provider,model:o.model||r.model,apiKey:o.apiKey||r.apiKey,cwd:e,memory:{enabled:o.memory!==!1&&r.memory?.enabled!==!1},heal:{enabled:o.heal!==!1&&r.heal?.enabled!==!1,testCommand:o.testCmd||r.heal?.testCommand,buildCommand:o.buildCmd||r.heal?.buildCommand},enhance:{enabled:o.enhance!==!1&&r.enhance?.enabled!==!1,autoSkills:r.enhance?.autoSkills!==!1},cors:o.cors!==!1};console.log(""),console.log(ye.bold.cyan(" \u2591\u2591\u2591 agentx runtime \u2591\u2591\u2591")),console.log(ye.dim(" the intelligent framework")),console.log(""),await new Oe(i).start()}catch(e){u(e)}});import{existsSync as Rt}from"fs";import jt from"path";import c from"chalk";import{Command as Mt}from"commander";import Dt from"ora";var Ze=new Mt().name("inspect").aliases(["info","ctx"]).description("show what the agent knows about your project \u2014 tech stack, schemas, skills, and more").option("-c, --cwd <cwd>","working directory",process.cwd()).option("--json","output as JSON",!1).option("--verbose","show full schema and model contents",!1).action(async o=>{try{let e=jt.resolve(o.cwd);Rt(e)||(t.error(`The path ${e} does not exist.`),process.exit(1));let n=Dt("Analyzing project...").start(),r=await te(e,"inspect",{context7:{enabled:!1}});if(n.stop(),o.json){console.log(JSON.stringify({techStack:r.techStack,schemas:r.schemas,skills:r.skills.map(a=>({name:a.frontmatter.name,description:a.frontmatter.description,source:a.source,tags:a.frontmatter.tags}))},null,2));return}t.break(),console.log(c.bold.cyan(" agentx inspect")),console.log(c.dim(` ${e}`)),t.break();let{techStack:i}=r;if(i.languages.length){console.log(c.bold(" Languages"));for(let a of i.languages)console.log(` ${c.green("\u25CF")} ${a.name}${a.version?c.dim(` ${a.version}`):""}${a.configFile?c.dim(` (${a.configFile})`):""}`);t.break()}if(i.frameworks.length){console.log(c.bold(" Frameworks"));for(let a of i.frameworks){let m=a.type==="frontend"?c.blue:a.type==="backend"?c.yellow:a.type==="fullstack"?c.magenta:a.type==="mobile"?c.green:c.dim;console.log(` ${c.green("\u25CF")} ${a.name}${a.version?c.dim(` @${a.version}`):""} ${m(`[${a.type}]`)}`)}t.break()}if(i.packageManager&&(console.log(c.bold(" Package Manager")),console.log(` ${c.green("\u25CF")} ${i.packageManager}`),t.break()),i.databases.length){console.log(c.bold(" Databases"));for(let a of i.databases)console.log(` ${c.green("\u25CF")} ${a}`);t.break()}if(i.styling.length){console.log(c.bold(" Styling"));for(let a of i.styling)console.log(` ${c.green("\u25CF")} ${a}`);t.break()}if(i.testing.length){console.log(c.bold(" Testing"));for(let a of i.testing)console.log(` ${c.green("\u25CF")} ${a}`);t.break()}if(i.deployment.length){console.log(c.bold(" Deployment"));for(let a of i.deployment)console.log(` ${c.green("\u25CF")} ${a}`);t.break()}i.monorepo&&(console.log(c.bold(" Monorepo")),console.log(` ${c.green("\u25CF")} yes`),t.break());let{schemas:s}=r,d=s.database||s.api||s.env||s.models?.length;if(d){if(console.log(c.bold(" Schemas Detected")),s.database&&(console.log(` ${c.green("\u25CF")} Database: ${c.cyan(s.database.type)}${s.database.tables?.length?c.dim(` (${s.database.tables.length} tables: ${s.database.tables.slice(0,5).join(", ")}${s.database.tables.length>5?"...":""})`):""}`),o.verbose&&s.database.content)){console.log(c.dim(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));for(let a of s.database.content.split(`
|
|
142
|
-
`).slice(0,20))console.log(c.dim(` \u2502 ${a}`));console.log(c.dim(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"))}s.api&&console.log(` ${c.green("\u25CF")} API: ${c.cyan(s.api.type)}`),s.env&&console.log(` ${c.green("\u25CF")} Environment: ${c.cyan(`${s.env.variables.length} variables`)}${s.env.variables.filter(a=>a.required).length?c.dim(` (${s.env.variables.filter(a=>a.required).length} required)`):""}`),s.models?.length&&console.log(` ${c.green("\u25CF")} Models: ${c.cyan(`${s.models.length} file(s)`)} ${c.dim(s.models.map(a=>a.path).join(", "))}`),t.break()}if(r.skills.length){console.log(c.bold(" Skills"));for(let a of r.skills){let m=a.source==="remote"?c.blue(`[${a.packageId||"remote"}]`):a.source==="generated"?c.magenta("[generated]"):c.dim("[local]");console.log(` ${c.green("\u25CF")} ${a.frontmatter.name} ${m}`),console.log(` ${c.dim(a.frontmatter.description)}`)}t.break()}else console.log(c.bold(" Skills")),console.log(` ${c.dim("none installed")} \u2014 run ${c.green("agentx skill install <owner/repo>")} or ${c.green("agentx skill create <name>")}`),t.break();let p=Object.keys(i.dependencies).length,f=Object.keys(i.devDependencies).length;if(p||f){if(console.log(c.bold(" Dependencies")),console.log(` ${c.green("\u25CF")} ${p} dependencies, ${f} devDependencies`),o.verbose){let a=Object.entries(i.dependencies).slice(0,15);for(let[m,w]of a)console.log(` ${c.dim(m)} ${c.dim(w)}`);p>15&&console.log(c.dim(` ... and ${p-15} more`))}t.break()}let g=[];i.languages.length&&g.push(`${i.languages.length} lang(s)`),i.frameworks.length&&g.push(`${i.frameworks.length} framework(s)`),d&&g.push("schemas detected"),r.skills.length&&g.push(`${r.skills.length} skill(s)`),console.log(c.dim(` Summary: ${g.join(" \xB7 ")}`)),t.break()}catch(e){u(e)}});import{existsSync as Nt,promises as et}from"fs";import G from"path";import k from"chalk";import{Command as Ot}from"commander";import tt from"ora";import ke from"prompts";var B=new Ot().name("skill").description("manage agent skills \u2014 install, create, list, and generate");B.command("install").aliases(["add","i"]).description("install a skill package from skills.sh or GitHub").argument("<package>","skill package (e.g., intellectronica/agent-skills)").option("-c, --cwd <cwd>","working directory",process.cwd()).action(async(o,e)=>{try{let n=G.resolve(e.cwd),r=tt(`Installing skill: ${o}`).start(),i=await Me(o,n);if(r.stop(),i.length){t.success(`Installed ${i.length} skill(s):`);for(let s of i)console.log(` ${k.green("+")} ${s.frontmatter.name} \u2014 ${s.frontmatter.description}`)}else t.warn("No skills found in the package.")}catch(n){u(n)}});B.command("list").aliases(["ls"]).description("list installed skills").option("-c, --cwd <cwd>","working directory",process.cwd()).action(async o=>{try{let e=G.resolve(o.cwd),n=await pe(e);if(!n.length){t.info("No skills installed. Install one with:"),console.log(` ${k.green("agentx skill install")} ${k.dim("<owner/repo>")}`);return}t.info(`Found ${n.length} skill(s):`),t.break();for(let r of n){let i=r.source==="remote"?k.blue(`[${r.packageId}]`):r.source==="generated"?k.magenta("[generated]"):k.dim("[local]");console.log(` ${k.bold(r.frontmatter.name)} ${i}`),console.log(` ${k.dim(r.frontmatter.description)}`),r.frontmatter.tags?.length&&console.log(` ${k.dim("tags:")} ${r.frontmatter.tags.map(s=>k.cyan(s)).join(", ")}`),r.path&&console.log(` ${k.dim("path:")} ${r.path}`),t.break()}}catch(e){u(e)}});B.command("create").description("create a new skill interactively or from a description").argument("[name]","skill name").option("-d, --description <desc>","skill description").option("--tags <tags>","comma-separated tags").option("-p, --provider <provider>","AI provider for generation (claude-code, claude)","claude-code").option("-m, --model <model>","model to use").option("--api-key <key>","API key").option("-c, --cwd <cwd>","working directory",process.cwd()).option("--no-ai","create a blank skill template without AI").action(async(o,e)=>{try{let n=G.resolve(e.cwd);if(!o){let f=await ke({type:"text",name:"name",message:"Skill name:",validate:g=>g.trim()?/^[a-z0-9-]+$/.test(g.trim())?!0:"Use lowercase letters, numbers, and hyphens only":"Name is required"});f.name||(t.warn("No name provided. Exiting."),process.exit(0)),o=f.name}let r=e.description;if(!r){let f=await ke({type:"text",name:"description",message:"Skill description:",validate:g=>g.trim()?!0:"Description is required"});f.description||(t.warn("No description provided. Exiting."),process.exit(0)),r=f.description}let i=e.tags?e.tags.split(",").map(f=>f.trim()):void 0,s=G.resolve(n,".skills",o),d=G.resolve(s,"SKILL.md");if(Nt(d)){let{overwrite:f}=await ke({type:"confirm",name:"overwrite",message:`Skill "${o}" already exists. Overwrite?`,initial:!1});if(!f){t.info("Skipped.");return}}let p;if(e.ai===!1)p=await De(o,r,`# ${o}
|
|
143
|
-
|
|
144
|
-
## Instructions
|
|
145
|
-
|
|
146
|
-
Add your skill instructions here.
|
|
147
|
-
|
|
148
|
-
## Examples
|
|
149
|
-
|
|
150
|
-
Add examples here.`,i);else{await Z(e.apiKey)||(t.error("No credentials configured. Run `agentx model` to set up."),process.exit(1));let g=tt("Detecting tech stack...").start(),a=await Se(n);g.text="Generating skill with AI...";let m=U(e.provider,e.apiKey),w=await Ne(m,o,r,a,{tags:i});g.stop(),p=w.content}await et.mkdir(s,{recursive:!0}),await et.writeFile(d,p,"utf8"),t.success(`Created skill: ${d}`),t.break(),t.info("The skill will be automatically loaded for future generations."),t.info(`To share it, push to GitHub and others can install with: ${k.green("agentx skill install <your-username>/<your-repo>")}`)}catch(n){u(n)}});B.command("inspect").description("show details of an installed skill").argument("<name>","skill name").option("-c, --cwd <cwd>","working directory",process.cwd()).action(async(o,e)=>{try{let n=G.resolve(e.cwd),i=(await pe(n)).find(s=>s.frontmatter.name===o||s.path?.includes(o));if(!i){t.error(`Skill "${o}" not found.`),t.info(`Run ${k.green("agentx skill list")} to see installed skills.`);return}console.log(k.bold(`
|
|
151
|
-
${i.frontmatter.name}`)),console.log(` ${i.frontmatter.description}`),t.break(),i.frontmatter.tags?.length&&console.log(` ${k.dim("Tags:")} ${i.frontmatter.tags.join(", ")}`),i.packageId&&console.log(` ${k.dim("Package:")} ${i.packageId}`),i.path&&console.log(` ${k.dim("Path:")} ${i.path}`),t.break(),console.log(k.dim(" --- Instructions ---")),t.break(),console.log(i.instructions.split(`
|
|
152
|
-
`).map(s=>` ${s}`).join(`
|
|
153
|
-
`)),t.break()}catch(n){u(n)}});import be from"chalk";import{Command as Ft}from"commander";var ot=new Ft().name("serve").description("run agentx as an MCP server for AI editors (Claude Code, Cursor, Windsurf, etc.)").option("--stdio","use stdio transport (default)",!0).option("-c, --cwd <cwd>","working directory",process.cwd()).action(async o=>{try{o.stdio!==!1?await Fe():(t.error("Only stdio transport is currently supported."),t.info(`Usage: ${be.green("agentx serve --stdio")} or configure in your MCP client.`),t.break(),t.info("Add to Claude Code:"),t.info(be.dim(" claude mcp add agentx -- npx agentx serve --stdio")),t.break(),t.info("Add to Cursor/MCP config:"),t.info(be.dim(JSON.stringify({mcpServers:{agentx:{command:"npx",args:["agentx","serve","--stdio"]}}},null,2))))}catch(e){u(e)}});import F from"chalk";import{Command as Lt}from"commander";var Ut=[{id:"claude-sonnet-4-20250514",label:"anthropic/claude-sonnet-4",hint:"Claude Sonnet 4 \xB7 ctx 200k \xB7 recommended"},{id:"claude-opus-4-20250514",label:"anthropic/claude-opus-4-5",hint:"Claude Opus 4.5 \xB7 ctx 200k \xB7 reasoning"},{id:"claude-haiku-4-20250514",label:"anthropic/claude-haiku-4",hint:"Claude Haiku 4 \xB7 ctx 200k \xB7 fast"}],se=new Lt().name("model").description("configure AI provider, credentials, and model");se.command("setup",{isDefault:!0}).description("interactively configure provider and model").action(async()=>{try{await Te()||process.exit(0)}catch(o){u(o)}});se.command("show").description("display current provider and model configuration").action(async()=>{try{let o=X();o||(t.warn("No configuration found. Run `agentx model` to set up."),process.exit(0));let e=Ut.find(n=>n.id===o.model)?.label||o.model;console.log(F.bold(`
|
|
154
|
-
Current configuration:`)),console.log(` Provider: ${F.cyan("anthropic")} (${o.authType})`),console.log(` Model: ${F.cyan(e)}`),console.log(` Token: ${F.dim(_t(o.token))}`),console.log(` File: ${F.dim("~/.agentx/auth.json")}`),process.env.ANTHROPIC_API_KEY&&console.log(F.yellow(`
|
|
155
|
-
Note: ANTHROPIC_API_KEY env var is set (takes priority)`)),process.env.ANTHROPIC_OAUTH_TOKEN&&console.log(F.yellow(`
|
|
156
|
-
Note: ANTHROPIC_OAUTH_TOKEN env var is set (takes priority)`)),console.log()}catch(o){u(o)}});function _t(o){return o.length<12?"***":o.slice(0,10)+"..."+o.slice(-4)}import{Command as Ht}from"commander";import A from"chalk";import Kt from"ora";var Y=new Ht().name("git").description("AI-powered git operations");Y.command("status").alias("s").description("show git status with summary").option("-c, --cwd <cwd>","working directory",process.cwd()).action(async o=>{try{let e=new z(o.cwd);await e.isRepo()||(t.error("Not a git repository"),process.exit(1));let n=await e.status();if(t.break(),t.info(`Branch: ${A.bold(n.branch)}`),t.break(),n.isClean){t.success("Working tree clean");return}if(n.staged.length){t.success(`Staged (${n.staged.length}):`);for(let r of n.staged)console.log(` ${A.green("+")} ${r}`)}if(n.modified.length){t.warn(`Modified (${n.modified.length}):`);for(let r of n.modified)console.log(` ${A.yellow("~")} ${r}`)}if(n.untracked.length){console.log(A.dim(`Untracked (${n.untracked.length}):`));for(let r of n.untracked)console.log(` ${A.dim("?")} ${r}`)}if(n.deleted.length){t.error(`Deleted (${n.deleted.length}):`);for(let r of n.deleted)console.log(` ${A.red("-")} ${r}`)}t.break()}catch(e){u(e)}});Y.command("commit").alias("c").description("create an AI-generated commit message and commit").option("-m, --message <message>","use a custom commit message").option("-a, --all","stage all changes before committing",!1).option("--ai","generate commit message with AI",!0).option("-c, --cwd <cwd>","working directory",process.cwd()).action(async o=>{try{let e=new z(o.cwd);await e.isRepo()||(t.error("Not a git repository"),process.exit(1)),o.all&&await e.addAll(),(await e.status()).staged.length===0&&(t.warn("Nothing staged to commit. Use --all to stage everything."),process.exit(0));let r=o.message;if(!r)if(o.ai){let s=Kt("Generating commit message...").start();try{let d=U();r=await e.generateCommitMessage(d),s.stop(),t.info(`Message: ${A.bold(r)}`)}catch{s.stop(),r=await e.generateCommitMessage(),t.info(`Message: ${A.bold(r)}`)}}else r=await e.generateCommitMessage();let i=await e.commit(r);t.break(),t.success(`[${i.hash}] ${i.message} (${i.filesChanged} file(s))`)}catch(e){u(e)}});Y.command("diff").alias("d").description("show diff of changes").option("-s, --staged","show staged changes",!1).option("-c, --cwd <cwd>","working directory",process.cwd()).action(async o=>{try{let n=await new z(o.cwd).diff(o.staged);if(!n.trim()){t.info(o.staged?"No staged changes":"No changes");return}console.log(n)}catch(e){u(e)}});Y.command("log").alias("l").description("show recent commits").option("-n, --count <n>","number of commits to show","10").option("-c, --cwd <cwd>","working directory",process.cwd()).action(async o=>{try{let n=await new z(o.cwd).log(parseInt(o.count));if(!n.length){t.info("No commits yet");return}t.break();for(let r of n)console.log(`${A.yellow(r.shortHash)} ${r.message} ${A.dim(`\u2014 ${r.author}`)}`);t.break()}catch(e){u(e)}});import{Command as Gt}from"commander";var it=new Gt().name("a2a").description("start an A2A (Agent-to-Agent) protocol server for external agent integration").option("--port <port>","server port","3171").option("--host <host>","server host","0.0.0.0").option("-p, --provider <provider>","AI provider","claude-code").option("-m, --model <model>","model to use").option("--api-key <key>","API key for the provider").option("-c, --cwd <cwd>","working directory",process.cwd()).option("--no-cors","disable CORS headers").action(async o=>{await new _e({port:parseInt(o.port,10),host:o.host,provider:o.provider,model:o.model,apiKey:o.apiKey,cwd:o.cwd,cors:o.cors!==!1}).start()});import{Command as Bt}from"commander";var nt=new Bt().name("daemon").description("start the agentx daemon \u2014 channels, crons, agents, and mesh").option("-c, --config <path>","path to agentx.json config file").action(async o=>{await new He(o.config).start()});import{Command as Yt}from"commander";process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));async function Wt(){let o=await oe(),e=process.cwd();Ee(e,x);let n=new Yt().name("agentx").description("the AI coding agent \u2014 generate, evolve, chat, and manage your codebase with AI").version(o.version||"1.0.0","-v, --version","display the version number");n.addCommand(Ge).addCommand(We).addCommand(qe).addCommand(Y).addCommand(ze).addCommand(Xe).addCommand(Ze).addCommand(B).addCommand(ot).addCommand(se).addCommand(it).addCommand(nt),process.argv.slice(2).length===0&&process.stdin.isTTY&&process.argv.push("chat"),n.parse()}Wt();
|
|
2
|
+
import{d as N,e as H,p as L,q as z}from"./chunk-S74N276K.js";import"./chunk-PCAYW54Q.js";import"./chunk-M7HKBG3V.js";import{a as K}from"./chunk-MDR7SH7F.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
|
+
(${($.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
|
+
`)),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
|
+
|
|
6
|
+
${n.systemPrompt}
|
|
7
|
+
`;B(m(o,"CLAUDE.md"),s),B(m(o,".claude/settings.json"),JSON.stringify({permissions:{allow:["Bash(git *)","Bash(curl *)","Bash(node *)","Read","Write","Edit","Glob","Grep","WebFetch","WebSearch"]}},null,2));let t=m(process.cwd(),"src/wiki/SKILL.md"),i=m(__dirname,"../wiki/SKILL.md"),l=y(t)?t:i;y(l)&&(C(m(o,".claude/skills/wiki"),{recursive:!0}),W(l,m(o,".claude/skills/wiki/SKILL.md"))),e.agents=e.agents||{},e.agents[n.id]={name:n.name,workspace:o,tier:n.tier,model:n.model,mentions:n.mentions?.map(d=>d.trim()).filter(Boolean)||[],maxConcurrent:n.maxConcurrent,systemPrompt:n.systemPrompt,permissionMode:"default"},w(e),console.log(a.green(`
|
|
8
|
+
Agent "${n.id}" added`)),console.log(a.dim(` Workspace: ${o}`)),console.log(a.dim(" Wiki skill installed")),console.log(a.dim(" CLAUDE.md + settings.json created")),console.log()});P.command("remove <id>").alias("rm").description("remove an agent from config (keeps workspace)").action(e=>{let n=p();if(!n.agents?.[e]){console.log(a.red(` Agent "${e}" not found`));return}delete n.agents[e],w(n),console.log(a.green(` Agent "${e}" removed from config (workspace preserved)`))});var M=new S().name("channel").description("manage channels \u2014 add telegram/whatsapp/discord, list");M.command("list").alias("ls").description("list configured channels and bindings").action(()=>{let e=p();console.log();let n=e.channels?.telegram;if(n?.enabled){console.log(a.bold(" Telegram:"));for(let[t,i]of Object.entries(n.accounts||{}))console.log(` ${a.cyan(t)} -> agent: ${i.agentBinding}`)}else console.log(a.dim(" Telegram: disabled"));let o=e.channels?.whatsapp;if(o?.enabled){console.log(a.bold(" WhatsApp:")),console.log(` default agent: ${o.defaultAgent||"(none)"}`),console.log(` session: ${o.sessionDir||".agentx/whatsapp-sessions"}`);for(let t of o.routes||[]){let i=t.contact?`contact ${t.contact}`:`group "${t.group}"`;console.log(` ${i} -> agent: ${t.agent}`)}}else console.log(a.dim(" WhatsApp: disabled"));let s=e.channels?.discord;s?.enabled?(console.log(a.bold(" Discord:")),console.log(` agent: ${s.agentBinding||"(none)"}`)):console.log(a.dim(" Discord: disabled")),console.log()});M.command("add").description("add a channel (telegram, whatsapp, or discord)").action(async()=>{let e=p(),n=Object.keys(e.agents||{});if(!n.length){console.log(a.red(" No agents configured. Run: agentx agent add"));return}let o=n.map(t=>({title:`${t} (${e.agents[t].name})`,value:t})),{channelType:s}=await k({type:"select",name:"channelType",message:"Channel type",choices:[{title:"Telegram \u2014 bot via BotFather token",value:"telegram"},{title:"WhatsApp \u2014 link via QR code (self-chat or contacts)",value:"whatsapp"},{title:"Discord \u2014 bot via Discord developer portal",value:"discord"}]});if(s){if(e.channels=e.channels||{},s==="telegram"){let t=await k([{type:"text",name:"accountName",message:"Account name (e.g. 'default', 'devops')"},{type:"text",name:"token",message:"Bot token (from @BotFather)"},{type:"select",name:"agentBinding",message:"Bind to agent",choices:o}]);if(!t.accountName||!t.token)return;try{let l=await(await fetch(`https://api.telegram.org/bot${t.token}/getMe`)).json();if(!l.ok)throw new Error(l.description);console.log(a.green(` Bot verified: @${l.result.username}`));let d=`@${l.result.username}`,r=e.agents[t.agentBinding].mentions||[];r.includes(d)||(r.push(d,l.result.username),e.agents[t.agentBinding].mentions=r)}catch(i){console.log(a.red(` Invalid token: ${i.message}`));return}e.channels.telegram=e.channels.telegram||{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},e.channels.telegram.enabled=!0,e.channels.telegram.accounts[t.accountName]={token:t.token,agentBinding:t.agentBinding},w(e),console.log(a.green(` Telegram "${t.accountName}" added -> ${t.agentBinding}`))}if(s==="whatsapp"){let t=await k([{type:"select",name:"defaultAgent",message:"Default agent for WhatsApp messages",choices:o},{type:"text",name:"sessionDir",message:"Session directory",initial:".agentx/whatsapp-sessions"},{type:"confirm",name:"addRoute",message:"Add a contact/group route?",initial:!0}]);if(!t.defaultAgent)return;let i=[],l=t.addRoute;for(;l;){let d=await k([{type:"select",name:"type",message:"Route type",choices:[{title:"Contact (phone number)",value:"contact"},{title:"Group (name match)",value:"group"}]},{type:"text",name:"value",message:r=>r==="contact"?"Phone number (e.g. +21624309128)":"Group name (partial match)"},{type:"select",name:"agent",message:"Route to agent",choices:o},{type:"confirm",name:"more",message:"Add another route?",initial:!1}]);d.value&&d.agent&&i.push({[d.type]:d.value,agent:d.agent}),l=d.more}e.channels.whatsapp={enabled:!0,sessionDir:t.sessionDir,defaultAgent:t.defaultAgent,routes:i},w(e),C(m(process.cwd(),t.sessionDir),{recursive:!0}),console.log(a.green(` WhatsApp enabled (${i.length} routes, default: ${t.defaultAgent})`)),console.log(a.dim(" Start daemon to scan QR code: agentx daemon start"))}if(s==="discord"){let t=await k([{type:"text",name:"token",message:"Discord bot token (from developer portal)"},{type:"select",name:"agentBinding",message:"Bind to agent",choices:o}]);if(!t.token)return;e.channels.discord={enabled:!0,token:t.token,agentBinding:t.agentBinding},w(e),console.log(a.green(` Discord added -> ${t.agentBinding}`))}console.log(a.dim(" Restart daemon to apply: agentx daemon stop && agentx daemon start")),console.log()}});var A=new S().name("cron").description("manage cron jobs \u2014 add, list, enable, disable");A.command("list").alias("ls").description("list cron jobs").action(()=>{let e=p();console.log();for(let[n,o]of Object.entries(e.crons||{})){let s=o.enabled?a.green("\u25CF"):a.dim("\u25CB");console.log(` ${s} ${a.cyan(n)} \u2014 ${o.schedule} (${o.timezone})`),console.log(a.dim(` agent: ${o.agent} | timeout: ${o.timeout}s`))}Object.keys(e.crons||{}).length||console.log(a.dim(" No cron jobs configured")),console.log()});A.command("add").description("add a cron job").action(async()=>{let e=p(),n=Object.keys(e.agents||{}),o=await k([{type:"text",name:"id",message:"Job ID (kebab-case)"},{type:"text",name:"schedule",message:"Cron expression (e.g. '0 9 * * *')"},{type:"text",name:"timezone",message:"Timezone",initial:"UTC"},{type:"select",name:"agent",message:"Agent",choices:n.map(s=>({title:s,value:s}))},{type:"text",name:"prompt",message:"Task prompt"},{type:"number",name:"timeout",message:"Timeout (seconds)",initial:600},{type:"confirm",name:"enabled",message:"Enable now?",initial:!1}]);!o.id||!o.schedule||(e.crons=e.crons||{},e.crons[o.id]={enabled:o.enabled,schedule:o.schedule,timezone:o.timezone,agent:o.agent,prompt:o.prompt,timeout:o.timeout,onError:"log"},w(e),console.log(a.green(` Cron "${o.id}" added (${o.enabled?"enabled":"disabled"})`)),console.log())});A.command("enable <id>").description("enable a cron job").action(e=>{let n=p();if(!n.crons?.[e]){console.log(a.red(` Cron "${e}" not found`));return}n.crons[e].enabled=!0,w(n),console.log(a.green(` Cron "${e}" enabled`))});A.command("disable <id>").description("disable a cron job").action(e=>{let n=p();if(!n.crons?.[e]){console.log(a.red(` Cron "${e}" not found`));return}n.crons[e].enabled=!1,w(n),console.log(a.green(` Cron "${e}" disabled`))});var O=new S().name("mesh").description("manage mesh peers \u2014 add, list, remove");O.command("list").alias("ls").description("list mesh peers").action(async()=>{let e=p();if(console.log(),!e.mesh?.enabled)console.log(a.dim(" Mesh: disabled"));else{console.log(a.bold(" Mesh peers:"));for(let n of e.mesh.peers||[]){let o=a.red("unreachable");try{let t=await(await fetch(`${n.url}/health`,{signal:AbortSignal.timeout(3e3)})).json();o=a.green(`healthy \u2014 ${t.agents?.length||0} agents`)}catch{}console.log(` ${a.cyan(n.name)} ${a.dim(n.url)} ${o}`)}}console.log()});O.command("add").description("add a mesh peer (another agentx server)").action(async()=>{let e=p(),n=await k([{type:"text",name:"name",message:"Peer name (e.g. 'server-2')"},{type:"text",name:"url",message:"Peer URL (e.g. 'http://100.67.108.119:18800')"},{type:"text",name:"token",message:"Auth token (optional, press enter to skip)"}]);if(!(!n.name||!n.url)){try{let s=await(await fetch(`${n.url}/.well-known/agent-card.json`,{signal:AbortSignal.timeout(5e3)})).json();console.log(a.green(` Connected: ${s.name} (${s.skills?.length||0} agents)`))}catch{console.log(a.yellow(" Could not reach peer (adding anyway)"))}e.mesh=e.mesh||{enabled:!1,peers:[],discovery:"static",healthCheck:{interval:60,timeout:10}},e.mesh.enabled=!0,e.mesh.peers=e.mesh.peers||[],e.mesh.peers.push({url:n.url,name:n.name,...n.token?{token:n.token}:{}}),w(e),console.log(a.green(` Peer "${n.name}" added`)),console.log()}});O.command("remove <name>").alias("rm").description("remove a mesh peer").action(e=>{let n=p();n.mesh?.peers&&(n.mesh.peers=n.mesh.peers.filter(o=>o.name!==e),n.mesh.peers.length===0&&(n.mesh.enabled=!1),w(n),console.log(a.green(` Peer "${e}" removed`)))});var E=new S().name("skill").description("manage skills \u2014 add to agent(s), list");E.command("add <skillPath>").description("add a skill to agent(s)").option("-a, --agent <agents...>","target agent ID(s)").option("--all","add to all agents").action(async(e,n)=>{let o=p(),s=m(e);if(!y(s)){console.log(a.red(` Skill not found: ${s}`));return}let t=y(T(s,"SKILL.md"))?s.split("/").pop():s.replace(/\/SKILL\.md$/,"").split("/").pop(),i;if(n.all)i=Object.keys(o.agents||{});else if(n.agent)i=n.agent;else{let l=Object.keys(o.agents||{});i=(await k({type:"multiselect",name:"agents",message:"Install to which agents?",choices:l.map(r=>({title:`${r} (${o.agents[r].name})`,value:r}))})).agents||[]}for(let l of i){let d=o.agents[l];if(!d){console.log(a.yellow(` Agent "${l}" not found, skipping`));continue}let r=m(d.workspace,".claude/skills",t);C(r,{recursive:!0}),y(T(s,"SKILL.md"))?W(s,r,{recursive:!0}):s.endsWith(".md")&&W(s,T(r,"SKILL.md")),console.log(a.green(` ${t} -> ${l} (${d.workspace})`))}console.log()});E.command("list").alias("ls").description("list skills per agent").action(()=>{let e=p();console.log();for(let[n,o]of Object.entries(e.agents||{})){let s=m(o.workspace,".claude/skills"),t=y(s)?ee(s).filter(i=>!i.startsWith(".")):[];console.log(` ${a.cyan(n)}: ${t.length?t.join(", "):a.dim("(none)")}`)}console.log()});var U=new S().name("hook").description("manage hooks \u2014 add to agent workspace");U.command("add <agent>").description("add a hook to an agent's workspace settings").action(async e=>{let o=p().agents?.[e];if(!o){console.log(a.red(` Agent "${e}" not found`));return}let s=m(o.workspace,".claude/settings.json"),t=y(s)?JSON.parse(R(s,"utf-8")):{},i=await k([{type:"select",name:"event",message:"Hook event",choices:[{title:"PreToolUse \u2014 before any tool runs",value:"PreToolUse"},{title:"PostToolUse \u2014 after any tool runs",value:"PostToolUse"},{title:"SessionStart \u2014 when session begins",value:"SessionStart"},{title:"Notification \u2014 on notifications",value:"Notification"},{title:"Stop \u2014 before session stops",value:"Stop"}]},{type:"select",name:"type",message:"Hook type",choices:[{title:"command \u2014 run a shell command",value:"command"},{title:"http \u2014 POST to a URL",value:"http"}]},{type:"text",name:"value",message:r=>r==="command"?"Shell command":"URL"},{type:"text",name:"matcher",message:"Matcher regex (optional, e.g. 'Bash' to match tool)"}]);if(!i.event||!i.value)return;t.hooks=t.hooks||{},t.hooks[i.event]=t.hooks[i.event]||[];let d={hooks:[{type:i.type,...i.type==="command"?{command:i.value}:{url:i.value}}]};i.matcher&&(d.matcher=i.matcher),t.hooks[i.event].push(d),C(m(o.workspace,".claude"),{recursive:!0}),B(s,JSON.stringify(t,null,2)),console.log(a.green(` Hook added to ${e}: ${i.event} -> ${i.type}`)),console.log()});var F=new S().name("migrate").description("import configuration from OpenClaw or other tools");F.command("openclaw [configPath]").description("import agents, channels, and crons from OpenClaw config").option("--dry-run","show what would be imported without writing").action(async(e,n)=>{let o=[e,m(process.env.HOME||"",".openclaw/openclaw.json"),m(process.env.HOME||"",".openclaw/clawdbot.json")].filter(Boolean),s;for(let g of o)if(g&&y(g)){s=g;break}if(!s){console.log(a.red(" OpenClaw config not found. Pass the path: agentx migrate openclaw /path/to/config.json"));return}console.log(a.dim(` Reading: ${s}`));let t=JSON.parse(R(s,"utf-8")),i=y(m(process.cwd(),"agentx.json"))?p():{node:{id:"imported",name:"Imported",bind:"127.0.0.1:18800"},providers:{},agents:{},channels:{telegram:{enabled:!1,accounts:{},policy:{dm:"pair",group:"mention-required"}},whatsapp:{enabled:!1}},crons:{},mesh:{enabled:!1,peers:[]}},l=t.agents?.list||[],d=t.bindings||[],r={};for(let g of d)g.match?.channel==="telegram"&&(r[g.match.accountId]=g.agentId);l.find(g=>g.id==="main"||g.default)&&(r.default="main");let f=0;for(let g of l){if(g.workspace?.startsWith("/data"))continue;let b=g.id.replace(/-agent$/,"").replace(/^main$/,"atlas"),u=g.groupChat?.mentionPatterns||[];u.some(D=>D===b)||u.push(b),i.agents[b]={name:g.name,workspace:g.workspace,tier:"claude-code",model:"claude-sonnet-4-6",mentions:u,maxConcurrent:g.id==="main"?2:1,systemPrompt:`You are ${g.name} on AgentX.`,permissionMode:"bypassPermissions"},f++,n.dryRun||C(m(g.workspace,".claude/skills"),{recursive:!0})}console.log(` ${a.green(f)} agents imported`);let v=t.channels?.telegram?.accounts||{},$=0;for(let[g,b]of Object.entries(v)){if(!b.botToken)continue;let D=r[g]?.replace(/-agent$/,"").replace(/^main$/,"atlas")||"atlas";i.channels.telegram.accounts[g]={token:b.botToken,agentBinding:D},i.channels.telegram.enabled=!0,$++}console.log(` ${a.green($)} Telegram accounts imported`);let J=m(s,"../cron/jobs.json");if(y(J)){let g=JSON.parse(R(J,"utf-8")),b=0;for(let u of g.jobs||[]){let D=u.name||u.id,Y=u.agentId?.replace(/-agent$/,"").replace(/^main$/,"atlas")||"atlas";i.crons[D]={enabled:u.enabled||!1,schedule:u.schedule?.expr||"0 9 * * *",timezone:u.schedule?.tz||"UTC",agent:Y,prompt:u.payload?.message||"",timeout:u.payload?.timeoutSeconds||600,onError:"log"},b++}console.log(` ${a.green(b)} cron jobs imported`)}n.dryRun?(console.log(a.yellow(`
|
|
9
|
+
Dry run \u2014 nothing written`)),console.log(JSON.stringify(i,null,2))):(w(i),console.log(a.green(`
|
|
10
|
+
Migration complete! Review agentx.json and run: agentx daemon start`))),console.log()});process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));async function oe(){let e=await z(),n=new ne().name("agentx").description("self-hosted multi-agent orchestrator \u2014 Telegram, WhatsApp, crons, A2A mesh, wiki knowledge").version(e.version||"1.0.0","-v, --version","display the version number");if(n.addCommand(x).addCommand(q).addCommand(P).addCommand(M).addCommand(A).addCommand(O).addCommand(E).addCommand(U).addCommand(F),process.argv.slice(2).length===0){n.outputHelp();return}n.parse()}oe();
|
|
157
11
|
//# sourceMappingURL=cli.js.map
|