galaxy-code 0.1.6 → 0.1.8

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.
Files changed (81) hide show
  1. package/dist/cli.bundle.js +317 -0
  2. package/package.json +6 -6
  3. package/dist/app.d.ts +0 -7
  4. package/dist/app.js +0 -597
  5. package/dist/auto-updater.d.ts +0 -21
  6. package/dist/auto-updater.js +0 -144
  7. package/dist/cli.d.ts +0 -2
  8. package/dist/cli.js +0 -159
  9. package/dist/cli.min.js +0 -589
  10. package/dist/connections/claude.d.ts +0 -71
  11. package/dist/connections/claude.js +0 -303
  12. package/dist/connections/gemini.d.ts +0 -40
  13. package/dist/connections/gemini.js +0 -232
  14. package/dist/connections/index.d.ts +0 -11
  15. package/dist/connections/index.js +0 -11
  16. package/dist/connections/ollama.d.ts +0 -37
  17. package/dist/connections/ollama.js +0 -73
  18. package/dist/connections/types.d.ts +0 -22
  19. package/dist/connections/types.js +0 -7
  20. package/dist/env.d.ts +0 -1
  21. package/dist/env.js +0 -29
  22. package/dist/prompts/ba-it-analyzer.d.ts +0 -1
  23. package/dist/prompts/ba-it-analyzer.js +0 -143
  24. package/dist/prompts/index.d.ts +0 -11
  25. package/dist/prompts/index.js +0 -11
  26. package/dist/prompts/orchestrator.d.ts +0 -8
  27. package/dist/prompts/orchestrator.js +0 -88
  28. package/dist/prompts/planning-agent.d.ts +0 -8
  29. package/dist/prompts/planning-agent.js +0 -195
  30. package/dist/prompts/universal-agent.d.ts +0 -7
  31. package/dist/prompts/universal-agent.js +0 -111
  32. package/dist/providers/agent-selector.d.ts +0 -29
  33. package/dist/providers/agent-selector.js +0 -84
  34. package/dist/providers/claude-agent.d.ts +0 -29
  35. package/dist/providers/claude-agent.js +0 -121
  36. package/dist/providers/gemini-agent.d.ts +0 -36
  37. package/dist/providers/gemini-agent.js +0 -168
  38. package/dist/providers/index.d.ts +0 -12
  39. package/dist/providers/index.js +0 -12
  40. package/dist/providers/ollama-agent.d.ts +0 -53
  41. package/dist/providers/ollama-agent.js +0 -276
  42. package/dist/providers/orchestrator.d.ts +0 -16
  43. package/dist/providers/orchestrator.js +0 -76
  44. package/dist/tools/ba-it-analyzer.d.ts +0 -66
  45. package/dist/tools/ba-it-analyzer.js +0 -90
  46. package/dist/tools/code-generate-agent.d.ts +0 -51
  47. package/dist/tools/code-generate-agent.js +0 -159
  48. package/dist/tools/command-runner.d.ts +0 -14
  49. package/dist/tools/command-runner.js +0 -120
  50. package/dist/tools/document-parser.d.ts +0 -11
  51. package/dist/tools/document-parser.js +0 -83
  52. package/dist/tools/file-operations.d.ts +0 -17
  53. package/dist/tools/file-operations.js +0 -127
  54. package/dist/tools/galaxy-ui-integration.d.ts +0 -94
  55. package/dist/tools/galaxy-ui-integration.js +0 -244
  56. package/dist/tools/git-operations.d.ts +0 -11
  57. package/dist/tools/git-operations.js +0 -114
  58. package/dist/tools/index.d.ts +0 -10
  59. package/dist/tools/index.js +0 -10
  60. package/dist/tools/planning-agent.d.ts +0 -29
  61. package/dist/tools/planning-agent.js +0 -134
  62. package/dist/tools/progress-reporter.d.ts +0 -19
  63. package/dist/tools/progress-reporter.js +0 -52
  64. package/dist/tools/registry.d.ts +0 -21
  65. package/dist/tools/registry.js +0 -695
  66. package/dist/tools/tool-event-emitter.d.ts +0 -24
  67. package/dist/tools/tool-event-emitter.js +0 -25
  68. package/dist/tools/types.d.ts +0 -31
  69. package/dist/tools/types.js +0 -1
  70. package/dist/types.d.ts +0 -39
  71. package/dist/types.js +0 -8
  72. package/dist/update-checker.d.ts +0 -22
  73. package/dist/update-checker.js +0 -85
  74. package/dist/utils/config-manager.d.ts +0 -102
  75. package/dist/utils/config-manager.js +0 -326
  76. package/dist/utils/devtools.d.ts +0 -21
  77. package/dist/utils/devtools.js +0 -61
  78. package/dist/utils/message-formatters.d.ts +0 -32
  79. package/dist/utils/message-formatters.js +0 -590
  80. package/dist/utils/progress-tracker.d.ts +0 -59
  81. package/dist/utils/progress-tracker.js +0 -213
@@ -0,0 +1,317 @@
1
+ #!/usr/bin/env node
2
+ var xt=Object.defineProperty;var i=(r,e)=>xt(r,"name",{value:e,configurable:!0});import Nn from"react";import{render as $n}from"ink";import Dn from"meow";import{config as wt}from"dotenv";import{fileURLToPath as Ct}from"node:url";import{dirname as Tt,join as bt}from"node:path";var Et=Ct(import.meta.url),vt=Tt(Et),_t=process.stdout.write,St=process.stderr.write,At=console.log,It=console.info;process.stdout.write=()=>!0;process.stderr.write=()=>!0;console.log=()=>{};console.info=()=>{};wt({path:bt(vt,"..",".env"),debug:!1,override:!1});process.stdout.write=_t;process.stderr.write=St;console.log=At;console.info=It;import ne from"node:process";import _,{useMemo as it,useState as B,useEffect as rn}from"react";import{Box as N,Static as sn,Text as j,useApp as an,useInput as cn}from"ink";import ln from"ink-text-input";import pn from"ink-spinner";import un from"figlet";import{GoogleGenAI as Ht,Type as F}from"@google/genai";import{Ollama as kt}from"ollama";var W=class{static{i(this,"OllamaConnection")}ollama;model="deepseek-v3.1:671b-cloud";constructor(e){this.model=e?.model??this.model;let t=e?.host??"https://ollama.com",n=t==="https://ollama.com"||t.includes("ollama.com"),o=e?.apiKey;this.ollama=new kt({host:t,headers:n?{Authorization:"Bearer "+o}:{}})}async generate(e){return await this.ollama.generate({model:e.model||this.model,prompt:e.prompt,system:e.system,stream:!1})}async chat(e){return(await this.ollama.chat({model:this.model,messages:[{role:"user",content:e}],stream:!1})).message.content}async chatWithTools(e){return await this.ollama.chat({model:e.model,messages:e.messages,tools:e.tools,stream:!1})}};var Ge=`You are an EXPERT BUSINESS ANALYST for IT projects.
3
+
4
+ # Your Role:
5
+ Analyze user requests and create COMPREHENSIVE project specifications including:
6
+ 1. Type: create_project (new) or update_project (add feature to existing)
7
+ 2. Core Features (must-have vs nice-to-have)
8
+ 3. Technical Stack recommendations
9
+ 4. User Stories with acceptance criteria
10
+ 5. Data Model (entities, attributes, relationships)
11
+ 6. API endpoints for backend systems
12
+ 7. Complexity + time estimate
13
+ 8. Best practices & recommendations
14
+ 9. Clarification questions
15
+
16
+ # Language Rule:
17
+ **ALWAYS respond in ENGLISH** regardless of user's input language.
18
+ - All field values (descriptions, names, recommendations, etc.) MUST be in English
19
+ - This ensures consistent output format for downstream tools (planning, code generation)
20
+
21
+ # Output Format (VALID JSON - ALL content in English):
22
+ {
23
+ "type": "create_project | update_project",
24
+ "projectName": "Project name",
25
+ "projectType": "web-app | mobile-app | api | full-stack | desktop-app",
26
+ "description": "Brief summary",
27
+ "coreFeatures": [
28
+ {
29
+ "name": "Feature name",
30
+ "description": "Description",
31
+ "priority": "must-have | should-have | nice-to-have",
32
+ "userStory": "As a [user], I want [feature] so that [benefit]",
33
+ "acceptanceCriteria": ["Criterion 1", "Criterion 2"]
34
+ }
35
+ ],
36
+ "technicalStack": {
37
+ "frontend": ["React", "TypeScript"],
38
+ "backend": ["Node.js", "Express"],
39
+ "database": ["PostgreSQL"],
40
+ "thirdParty": ["Stripe"]
41
+ },
42
+ "userStories": [
43
+ {
44
+ "as": "role",
45
+ "iWant": "feature",
46
+ "soThat": "benefit",
47
+ "acceptanceCriteria": ["Given [context], when [action], then [result]"]
48
+ }
49
+ ],
50
+ "dataModel": [
51
+ {
52
+ "name": "Entity",
53
+ "description": "Purpose",
54
+ "attributes": ["id", "name", "createdAt"],
55
+ "relationships": ["User has many Orders"]
56
+ }
57
+ ],
58
+ "apiEndpoints": [
59
+ {
60
+ "method": "GET | POST | PUT | DELETE",
61
+ "path": "/api/resource",
62
+ "description": "Purpose",
63
+ "response": "{ data: [] }"
64
+ }
65
+ ],
66
+ "estimatedComplexity": "simple | medium | complex",
67
+ "estimatedTime": "1-2 weeks | 2-4 weeks | 1-3 months",
68
+ "recommendations": ["Recommendation with reasoning"],
69
+ "questionsForUser": ["Clarification question"]
70
+ }
71
+
72
+ # Example:
73
+
74
+ User: "Create an online phone store"
75
+
76
+ {
77
+ "type": "create_project",
78
+ "projectName": "Phone Store E-Commerce",
79
+ "projectType": "full-stack",
80
+ "description": "E-commerce platform for selling phones with product catalog, cart, checkout, and order management",
81
+ "coreFeatures": [
82
+ {
83
+ "name": "Product Catalog",
84
+ "description": "Display phones with images, prices, specs. Filter by brand, price, features. Search by name.",
85
+ "priority": "must-have",
86
+ "userStory": "As a customer, I want to browse phones with filters to find suitable products",
87
+ "acceptanceCriteria": ["Grid/list view", "Filter by brand/price", "Real-time search", "Pagination"]
88
+ },
89
+ {
90
+ "name": "Shopping Cart",
91
+ "description": "Add products, update quantity, remove items, calculate total",
92
+ "priority": "must-have",
93
+ "userStory": "As a customer, I want to manage my cart to buy multiple products",
94
+ "acceptanceCriteria": ["Add to cart", "Update quantity", "Remove items", "Calculate total"]
95
+ }
96
+ ],
97
+ "technicalStack": {
98
+ "frontend": ["Next.js", "TypeScript", "Tailwind"],
99
+ "backend": ["Node.js", "Express"],
100
+ "database": ["PostgreSQL", "Redis"],
101
+ "thirdParty": ["Stripe"]
102
+ },
103
+ "userStories": [
104
+ {
105
+ "as": "customer",
106
+ "iWant": "filter products by brand",
107
+ "soThat": "find phones quickly",
108
+ "acceptanceCriteria": ["Given home page, when filter 'Samsung', then show Samsung phones"]
109
+ }
110
+ ],
111
+ "dataModel": [
112
+ {
113
+ "name": "Product",
114
+ "description": "Phone product",
115
+ "attributes": ["id", "name", "brand", "price", "stock"],
116
+ "relationships": ["Product has many OrderItems"]
117
+ }
118
+ ],
119
+ "apiEndpoints": [
120
+ {
121
+ "method": "GET",
122
+ "path": "/api/products",
123
+ "description": "Get product list",
124
+ "response": "{ products: Product[] }"
125
+ }
126
+ ],
127
+ "estimatedComplexity": "complex",
128
+ "estimatedTime": "2-4 weeks",
129
+ "recommendations": [
130
+ "Use Next.js App Router for SSR and SEO",
131
+ "Implement Redis caching for product listing"
132
+ ],
133
+ "questionsForUser": [
134
+ "Online payment (Stripe) or COD only?",
135
+ "Multi-language support needed?"
136
+ ]
137
+ }
138
+
139
+ CRITICAL:
140
+ - VALID JSON ONLY (no markdown)
141
+ - COMPREHENSIVE MVP features
142
+ - Use user's language throughout
143
+ - SPECIFIC technical recommendations
144
+ - Realistic feature prioritization`;var me=class{static{i(this,"BAITAnalyzer")}ollama=null;model="gpt-oss:120b-cloud";constructor(){}getConnection(){return this.ollama||(this.ollama=new W({model:this.model})),this.ollama}async analyze(e,t){let n=`User Request: ${e}`;t&&(n+=`
145
+
146
+ Additional Context:
147
+ ${t}`);let o=await this.getConnection().generate({prompt:n,system:Ge,model:this.model}),s=this.extractJSON(o.response);if(!s)throw new Error("Failed to extract JSON from BA analysis response");return JSON.parse(s)}extractJSON(e){let t=e.trim();t=t.replace(/```json\s*/g,""),t=t.replace(/```\s*/g,"");let n=t.indexOf("{");if(n===-1)return null;let o=0,s=!1,a=!1;for(let l=n;l<t.length;l++){let u=t[l];if(a){a=!1;continue}if(u==="\\"){a=!0;continue}if(u==='"'&&!a){s=!s;continue}if(!s){if(u==="{")o++;else if(u==="}"&&(o--,o===0))return t.substring(n,l+1)}}return null}};import{exec as Pt}from"child_process";import{promisify as Ot}from"util";import de from"fs/promises";import _e from"path";var Nt=Ot(Pt),ge=class{static{i(this,"CommandRunner")}async runCommand(e,t,n=18e4){try{let{stdout:o,stderr:s}=await Nt(e,{cwd:t,timeout:n,maxBuffer:10485760});return{stdout:o,stderr:s,exitCode:0,command:e}}catch(o){return{stdout:o.stdout||"",stderr:o.stderr||o.message,exitCode:o.code||1,command:e}}}async detectTestCommand(e){try{let t=_e.join(e,"package.json"),n=await de.readFile(t,"utf-8"),o=JSON.parse(n);if(o.scripts?.test)return o.scripts.test;let s=await this.detectPackageManager(e);return s==="bun"?"bun test":s==="pnpm"?"pnpm test":s==="yarn"?"yarn test":"npm test"}catch{return null}}async detectDevCommand(e){try{let t=_e.join(e,"package.json"),n=await de.readFile(t,"utf-8"),o=JSON.parse(n);if(o.scripts?.dev)return o.scripts.dev;if(o.scripts?.start)return o.scripts.start;let s=await this.detectPackageManager(e);return s==="bun"?"bun run dev":s==="pnpm"?"pnpm dev":s==="yarn"?"yarn dev":"npm run dev"}catch{return null}}async detectBuildCommand(e){try{let t=_e.join(e,"package.json"),n=await de.readFile(t,"utf-8");if(JSON.parse(n).scripts?.build){let s=await this.detectPackageManager(e);return s==="bun"?"bun run build":s==="pnpm"?"pnpm build":s==="yarn"?"yarn build":"npm run build"}return null}catch{return null}}async detectPackageManager(e){try{let t=await de.readdir(e);return t.includes("bun.lockb")?"bun":t.includes("pnpm-lock.yaml")?"pnpm":t.includes("yarn.lock")?"yarn":"npm"}catch{return"bun"}}async installDependencies(e){let t=await this.detectPackageManager(e),n=t==="npm"?"npm install":t==="yarn"?"yarn install":t==="pnpm"?"pnpm install":"bun install";return this.runCommand(n,e,18e4)}};import{exec as $t}from"child_process";import{promisify as Dt}from"util";var fe=Dt($t),ye=class{static{i(this,"DocumentParser")}async parseDocument(e,t){try{switch(t){case"pdf":return await this.parsePDF(e);case"docx":return await this.parseDOCX(e);case"xlsx":return await this.parseXLSX(e);default:throw new Error(`Unsupported document type: ${t}`)}}catch(n){return`Failed to parse document: ${n.message}`}}async parsePDF(e){try{let{stdout:t}=await fe(`pdftotext "${e}" -`,{timeout:3e4,maxBuffer:10485760});return t||"No text content found in PDF"}catch(t){if(t.message.includes("command not found"))return"PDF parsing requires pdftotext (install: apt-get install poppler-utils)";throw t}}async parseDOCX(e){try{let{stdout:t}=await fe(`pandoc "${e}" -t plain`,{timeout:3e4,maxBuffer:10485760});return t||"No text content found in DOCX"}catch(t){if(t.message.includes("command not found"))return"DOCX parsing requires pandoc (install: apt-get install pandoc)";throw t}}async parseXLSX(e){try{let{stdout:t}=await fe(`ssconvert "${e}" fd://1`,{timeout:3e4,maxBuffer:10485760});return t||"No content found in XLSX"}catch(t){if(t.message.includes("command not found"))return"XLSX parsing requires ssconvert (install: apt-get install gnumeric)";throw t}}async checkDependencies(){let e=i(async t=>{try{return await fe(`which ${t}`,{timeout:1e3}),!0}catch{return!1}},"checkCommand");return{pdf:await e("pdftotext"),docx:await e("pandoc"),xlsx:await e("ssconvert")}}};import G from"fs/promises";import J from"path";import{exec as Ut}from"child_process";import{promisify as Lt}from"util";import se from"os";var Y=Lt(Ut),he=class{static{i(this,"FileOperations")}async readFile(e){try{return await G.readFile(e,"utf-8")}catch(t){throw new Error(`Failed to read file ${e}: ${t.message}`)}}async writeFile(e,t){try{let n=!1,o;try{o=await G.readFile(e,"utf-8")}catch{n=!0}await G.mkdir(J.dirname(e),{recursive:!0}),await G.writeFile(e,t,"utf-8");let s=t.split(`
148
+ `),a=o?o.split(`
149
+ `):[],l=0,u=0;if(n)l=s.length;else{u=a.length,l=s.length;let m=new Set(a),d=new Set(s),w=a.filter(E=>!d.has(E)),h=s.filter(E=>!m.has(E));u=w.length,l=h.length}return{isNewFile:n,oldContent:o,newContent:t,linesAdded:l,linesRemoved:u,path:e}}catch(n){throw new Error(`Failed to write file ${e}: ${n.message}`)}}async listFiles(e,t=!1){try{if(t)if(se.platform()==="win32"){let n=[],s=i(async a=>{if(!(n.length>=500))try{let l=await G.readdir(a,{withFileTypes:!0});for(let u of l){if(n.length>=500)break;let m=J.join(a,u.name);if(u.isDirectory()){let d=u.name.toLowerCase();if(d==="node_modules"||d===".git"||d==="dist"||d==="build")continue;await s(m)}else{let d=m.toLowerCase();!d.includes("node_modules")&&!d.includes(".git")&&!d.includes("dist")&&!d.includes("build")&&n.push(m)}}}catch{}},"walk");return await s(e),n.slice(0,500)}else{let{stdout:n}=await Y(`find "${e}" -type f -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" -not -path "*/build/*" | head -500`,{timeout:1e4});return n.trim().split(`
150
+ `).filter(Boolean)}else return(await G.readdir(e,{withFileTypes:!0})).filter(o=>o.isFile()).map(o=>J.join(e,o.name))}catch(n){throw new Error(`Failed to list files in ${e}: ${n.message}`)}}async searchFiles(e,t){try{if(se.platform()==="win32"){let n=[],s=i(async a=>{if(!(n.length>=100))try{let l=await G.readdir(a,{withFileTypes:!0});for(let u of l){if(n.length>=100)break;let m=J.join(a,u.name);if(u.isDirectory()){let d=u.name.toLowerCase();if(d==="node_modules"||d===".git"||d==="dist"||d==="build")continue;await s(m)}else{let d=J.extname(u.name).toLowerCase();if([".ts",".js",".tsx",".jsx",".json"].includes(d))try{(await G.readFile(m,"utf-8")).includes(t)&&n.push(m)}catch{}}}}catch{}},"searchInDirectory");return await s(e),n.slice(0,100)}else{let{stdout:n}=await Y(`grep -r "${t}" "${e}" --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" --include="*.json" --exclude-dir="node_modules" --exclude-dir=".git" --exclude-dir="dist" -l | head -100`,{timeout:1e4});return n.trim().split(`
151
+ `).filter(Boolean)}}catch{return[]}}async getFileDiff(e){try{let{stdout:t}=await Y(`git diff "${e}"`,{timeout:5e3});return t||"No changes"}catch(t){return`Not a git repository or file doesn't exist: ${t.message}`}}async applyPatch(e,t){try{let n=se.tmpdir(),o=J.join(n,`patch-${Date.now()}.patch`);await G.writeFile(o,t),se.platform()==="win32"?await Y(`patch "${e}" < "${o}"`,{timeout:5e3}):await Y(`patch "${e}" < "${o}"`,{timeout:5e3}),await G.unlink(o)}catch(n){throw new Error(`Failed to apply patch: ${n.message}`)}}async getFileTree(e){try{if(se.platform()==="win32"){let n=i(async(s,a=0)=>{if(a>3)return[];let l=[];try{let u=await G.readdir(s,{withFileTypes:!0});for(let m of u){let d=" ".repeat(a),w=m.name.toLowerCase();if(!(w==="node_modules"||w===".git"||w==="dist"||w==="build"||w===".venv"||w==="venv"||w==="ios"||w==="android"||w===".expo"))if(m.isDirectory()){l.push(`${d}${m.name}/`);let h=await n(J.join(s,m.name),a+1);l.push(...h)}else l.push(`${d}${m.name}`)}}catch{}return l},"buildTree");return(await n(e)).join(`
152
+ `)}else{let{stdout:t}=await Y(`tree -L 3 -I "node_modules|.git|dist|build|.venv|venv|ios|android|.expo" -a --charset ascii "${e}" 2>/dev/null || find "${e}" -maxdepth 3 -not -path "*/node_modules/*" -not -path "*/.git/*" | head -500`,{timeout:2e4});return t}}catch(t){return`Failed to generate file tree: ${t.message}`}}};import{exec as jt}from"child_process";import{promisify as Gt}from"util";var M=Gt(jt),xe=class{static{i(this,"GitOperations")}async getStatus(e){try{let{stdout:t}=await M("git status --short",{cwd:e,timeout:5e3});return t||"Working tree clean"}catch(t){return`Not a git repository: ${t.message}`}}async commit(e,t){try{await M("git add .",{cwd:e,timeout:5e3});let{stdout:n}=await M(`git commit -m "${t.replace(/"/g,'\\"')}"`,{cwd:e,timeout:1e4});return n}catch(n){return`Commit failed: ${n.message}`}}async push(e,t="origin",n){try{let o=n?` ${n}`:"",{stdout:s}=await M(`git push ${t}${o}`,{cwd:e,timeout:3e4});return s}catch(o){return`Push failed: ${o.message}`}}async pull(e,t="origin",n){try{let o=n?` ${n}`:"",{stdout:s}=await M(`git pull ${t}${o}`,{cwd:e,timeout:3e4});return s}catch(o){return`Pull failed: ${o.message}`}}async getDiff(e,t){try{let n=t?` "${t}"`:"",{stdout:o}=await M(`git diff${n}`,{cwd:e,timeout:1e4});return o||"No changes"}catch(n){return`Diff failed: ${n.message}`}}async getLog(e,t=10){try{let{stdout:n}=await M(`git log --oneline -${t}`,{cwd:e,timeout:5e3});return n}catch(n){return`Log failed: ${n.message}`}}async listBranches(e){try{let{stdout:t}=await M("git branch -a",{cwd:e,timeout:5e3});return t}catch(t){return`Branch list failed: ${t.message}`}}async createBranch(e,t){try{let{stdout:n}=await M(`git checkout -b "${t}"`,{cwd:e,timeout:5e3});return n}catch(n){return`Branch creation failed: ${n.message}`}}async switchBranch(e,t){try{let{stdout:n}=await M(`git checkout "${t}"`,{cwd:e,timeout:5e3});return n}catch(n){return`Branch switch failed: ${n.message}`}}};var we=class{static{i(this,"PlanDisplay")}displayPlan(e){let t=`\u{1F4CB} Execution Plan: ${e.summary}
153
+ `;return t+=`Estimated Time: ${e.estimatedTime||"medium"}
154
+
155
+ `,e.steps.forEach(n=>{let o=n.status==="completed"?"\u2705":n.status==="failed"?"\u274C":n.status==="in-progress"?"\u26A1":"\u23F3";t+=`${o} Step ${n.step}: ${n.action}
156
+ `}),t}updateProgress(e){let n=`${e.status==="completed"?"\u2705":e.status==="failed"?"\u274C":e.status==="in-progress"?"\u26A1":"\u23F3"} Step ${e.step}: ${e.status}
157
+ `;return e.message&&(n+=` ${e.message}
158
+ `),e.filesCreated&&e.filesCreated.length>0&&(n+=` \u{1F4DD} Files created: ${e.filesCreated.join(", ")}
159
+ `),e.commandsRun&&e.commandsRun.length>0&&(n+=` \u{1F527} Commands run: ${e.commandsRun.join(", ")}
160
+ `),n}};import{execa as Me}from"execa";import{existsSync as ie}from"node:fs";import{join as Q,resolve as Z,isAbsolute as Fe}from"node:path";var Mt="https://unpkg.com/galaxy-design@latest/dist/registry.json",ae="https://galaxy-design.vercel.app",Ce={data:null,timestamp:0},Ft=300*1e3;function Se(r){return ie(Q(r,"yarn.lock"))?"yarn":ie(Q(r,"pnpm-lock.yaml"))?"pnpm":ie(Q(r,"bun.lockb"))?"bun":(ie(Q(r,"package-lock.json")),"npm")}i(Se,"detectPackageManager");function Ae(r){switch(r){case"yarn":return"yarn";case"bun":return"bunx";case"pnpm":return"pnpm";default:return"npx"}}i(Ae,"getPackageManagerExecCommand");function ee(r){let e=r;for(;e!=="/"&&e!==".";){if(ie(Q(e,"package.json")))return e;let t=Q(e,"..");if(t===e)break;e=t}return r}i(ee,"findProjectRoot");async function Te(){let r=Date.now();if(Ce.data&&r-Ce.timestamp<Ft)return Ce.data;try{let e={Accept:"application/vnd.github.v3.raw"},t=process.env.GITHUB_TOKEN;t&&(e.Authorization=`Bearer ${t}`);let n=await fetch(Mt,{headers:e});if(!n.ok)throw new Error(`Failed to fetch registry: ${n.statusText}`);let o=await n.json();return Ce={data:o,timestamp:r},o}catch(e){throw new Error(`Failed to fetch Galaxy UI registry: ${e instanceof Error?e.message:"Unknown error"}`)}}i(Te,"fetchRegistry");async function Re(r){let e=await Te(),t=Object.entries(e.components).map(([o,s])=>({name:o,description:s.description,category:s.type,docsUrl:`${ae}/components/${o}`})),n=r?.category&&r.category!=="all"?t.filter(o=>o.category===r.category):t;return{total:n.length,components:n}}i(Re,"galaxyUIListComponents");async function Be(r){let e=await Te(),t=r.query.toLowerCase(),n=Object.entries(e.components).map(([o,s])=>{let a=o.toLowerCase().includes(t),l=s.description.toLowerCase().includes(t),u=s.type.toLowerCase().includes(t),m="low";a?m="high":u?m="medium":l&&(m="low");let d=a||l||u;return{name:o,description:s.description,category:s.type,docsUrl:`${ae}/components/${o}`,relevance:m,isMatch:d}}).filter(o=>o.isMatch).sort((o,s)=>{let a={high:0,medium:1,low:2};return a[o.relevance]-a[s.relevance]});return{total:n.length,components:n}}i(Be,"galaxyUISearchComponents");async function He(r){let t=(await Te()).components[r.name];if(!t)throw new Error(`Component "${r.name}" not found. Use galaxy_ui_list_components or galaxy_ui_search_components to find available components.`);let n=`${ae}/components/${r.name}`,o=r.framework?`${n}?framework=${r.framework}`:void 0,s=r.cwd?ee(r.cwd)||r.cwd:ee(process.cwd())||process.cwd(),a=Se(s),l=Ae(a);return{name:r.name,description:t.description,category:t.type,dependencies:t.dependencies||[],peerDependencies:t.peerDependencies||[],docsUrl:n,docsUrlFramework:o,installCommand:`${l} galaxy-design add ${r.name}`}}i(He,"galaxyUIGetComponent");async function qe(r){let e=await Te(),t=new Map;for(let[o,s]of Object.entries(e.components)){let a=s.type;t.has(a)||t.set(a,[]),t.get(a).push(o)}return{categories:Array.from(t.entries()).map(([o,s])=>({name:o,count:s.length,components:s.sort()})).sort((o,s)=>s.count-o.count)}}i(qe,"galaxyUIGetCategories");async function We(r){try{let e=r.cwd?ee(r.cwd)||r.cwd:ee(process.cwd())||process.cwd(),t=Se(e),n=Ae(t),o=["galaxy-design","add",...r.components];if(r.cwd){let a=Fe(r.cwd)?Z(r.cwd):Z(process.cwd(),r.cwd),l=Z(e);a!==l&&o.push("--cwd",r.cwd)}let s=await Me(n,o,{cwd:e,stderr:"pipe",stdout:"pipe"});return{success:!0,message:`Successfully added components: ${r.components.join(", ")}`,output:s.stdout}}catch(e){let t=e;return{success:!1,message:`Failed to add components: ${r.components.join(", ")}`,output:t.stderr||t.stdout||"Unknown error"}}}i(We,"galaxyUIAddComponents");async function Je(r){try{let e=r?.cwd?ee(r.cwd)||r.cwd:ee(process.cwd())||process.cwd(),t=Se(e),n=Ae(t),o=["galaxy-design@latest","init","--yes"];if(r?.cwd){let a=Fe(r.cwd)?Z(r.cwd):Z(process.cwd(),r.cwd),l=Z(e);a!==l&&o.push("--cwd",r.cwd)}r?.skipPrompts&&o.push("--skip-prompts");let s=await Me(n,o,{cwd:e,stderr:"pipe",stdout:"pipe"});return{success:!0,message:`Successfully initialized Galaxy UI with ${t}`,output:s.stdout}}catch(e){let t=e;return{success:!1,message:"Failed to initialize Galaxy UI",output:t.stderr||t.stdout||"Unknown error"}}}i(Je,"galaxyUIInit");function Xe(r){if(r?.component){let t=r.language==="vi"?"/vi":"";return{url:`${ae}${t}/components/${r.component}`,description:`Documentation for ${r.component} component`}}let e=r?.language==="vi"?"/vi":"";return{url:`${ae}${e}`,description:"Galaxy UI CLI Documentation"}}i(Xe,"galaxyUIGetDocsUrl");import{existsSync as Ve,readFileSync as Ke}from"node:fs";import{join as ze}from"node:path";var be=class{static{i(this,"GalaxyDesignChecker")}async checkIntegration(e){try{let t=ze(e,"components.json");if(!Ve(t))return{isIntegrated:!1,error:"components.json file not found"};let n=Ke(t,"utf-8"),o=JSON.parse(n);if(!o.framework)return{isIntegrated:!1,error:"framework field not found in components.json"};let s=o.components?Object.keys(o.components):[];return{isIntegrated:!0,framework:o.framework,components:s}}catch(t){return{isIntegrated:!1,error:t instanceof Error?t.message:"Unknown error"}}}async getComponentDetails(e){try{let t=ze(e,"components.json");if(!Ve(t))return{components:[],total:0};let n=Ke(t,"utf-8"),o=JSON.parse(n);if(!o.components)return{components:[],total:0};let s=Object.entries(o.components).map(([a,l])=>({name:a,version:l.version,path:l.path}));return{components:s,total:s.length}}catch{return{components:[],total:0}}}};import{EventEmitter as Bt}from"events";var Ie=class extends Bt{static{i(this,"ToolEventEmitter")}constructor(){super(),this.setMaxListeners(100)}emitToolExecution(e){let t={...e,timestamp:Date.now()};this.emit("tool-execution",t)}onToolExecution(e){return this.on("tool-execution",e),()=>this.off("tool-execution",e)}},X=new Ie;var L=class{static{i(this,"ToolRegistry")}tools=new Map;fileOps=new he;gitOps=new xe;commandRunner=new ge;baAnalyzer=new me;documentParser=new ye;galaxyDesignChecker=new be;planDisplay=new we;constructor(){this.registerAllTools()}registerAllTools(){this.register({name:"file_read",description:"Read content of a file",inputSchema:{type:"object",properties:{path:{type:"string",description:"File path to read"}},required:["path"]},execute:i(async e=>await this.fileOps.readFile(e.path),"execute")}),this.register({name:"file_write",description:"Write content to a file (creates directories if needed)",inputSchema:{type:"object",properties:{path:{type:"string",description:"File path to write"},content:{type:"string",description:"Content to write"}},required:["path","content"]},execute:i(async e=>{let t=await this.fileOps.writeFile(e.path,e.content);return JSON.stringify(t)},"execute")}),this.register({name:"file_list",description:"List files in a directory",inputSchema:{type:"object",properties:{path:{type:"string",description:"Directory path"},recursive:{type:"boolean",description:"Recursive listing",default:!1}},required:["path"]},execute:i(async e=>(await this.fileOps.listFiles(e.path,e.recursive)).join(`
161
+ `),"execute")}),this.register({name:"file_search",description:"Search for pattern in files",inputSchema:{type:"object",properties:{path:{type:"string",description:"Directory to search in"},pattern:{type:"string",description:"Pattern to search for"}},required:["path","pattern"]},execute:i(async e=>(await this.fileOps.searchFiles(e.path,e.pattern)).join(`
162
+ `)||"No matches found","execute")}),this.register({name:"file_tree",description:"Get file tree structure of a directory",inputSchema:{type:"object",properties:{path:{type:"string",description:"Directory path"}},required:["path"]},execute:i(async e=>await this.fileOps.getFileTree(e.path),"execute")}),this.register({name:"git_status",description:"Get git status of repository",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Working directory"}},required:["cwd"]},execute:i(async e=>await this.gitOps.getStatus(e.cwd||process.cwd()),"execute")}),this.register({name:"git_commit",description:"Commit changes with message",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Working directory"},message:{type:"string",description:"Commit message"}},required:["cwd","message"]},execute:i(async e=>await this.gitOps.commit(e.cwd||process.cwd(),e.message),"execute")}),this.register({name:"git_push",description:"Push commits to remote",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Working directory"},remote:{type:"string",description:"Remote name",default:"origin"},branch:{type:"string",description:"Branch name (optional)"}},required:["cwd"]},execute:i(async e=>await this.gitOps.push(e.cwd||process.cwd(),e.remote||"origin",e.branch),"execute")}),this.register({name:"git_pull",description:"Pull changes from remote",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Working directory"},remote:{type:"string",description:"Remote name",default:"origin"},branch:{type:"string",description:"Branch name (optional)"}},required:["cwd"]},execute:i(async e=>await this.gitOps.pull(e.cwd||process.cwd(),e.remote||"origin",e.branch),"execute")}),this.register({name:"git_diff",description:"Show git diff",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Working directory"},file:{type:"string",description:"Specific file (optional)"}},required:["cwd"]},execute:i(async e=>await this.gitOps.getDiff(e.cwd||process.cwd(),e.file),"execute")}),this.register({name:"git_log",description:"Show git commit history",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Working directory"},limit:{type:"number",description:"Number of commits",default:10}},required:["cwd"]},execute:i(async e=>await this.gitOps.getLog(e.cwd||process.cwd(),e.limit||10),"execute")}),this.register({name:"git_branches",description:"List all branches",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Working directory"}},required:["cwd"]},execute:i(async e=>await this.gitOps.listBranches(e.cwd||process.cwd()),"execute")}),this.register({name:"command_run",description:"Run a shell command",inputSchema:{type:"object",properties:{command:{type:"string",description:"Command to execute"},cwd:{type:"string",description:"Working directory"},timeout:{type:"number",description:"Timeout in ms",default:6e4}},required:["command","cwd"]},execute:i(async e=>{let t=await this.commandRunner.runCommand(e.command,e.cwd||process.cwd(),e.timeout||6e4);return`stdout:
163
+ ${t.stdout}
164
+
165
+ stderr:
166
+ ${t.stderr}`},"execute")}),this.register({name:"test_run",description:"Run tests in project",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Project directory"},command:{type:"string",description:"Custom test command (optional)"}},required:["cwd"]},execute:i(async e=>{let t=e.command||await this.commandRunner.detectTestCommand(e.cwd||process.cwd());if(!t)return"No test command found";let n=await this.commandRunner.runCommand(t,e.cwd||process.cwd(),12e4);return`Test Output:
167
+ ${n.stdout}
168
+
169
+ Errors:
170
+ ${n.stderr}`},"execute")}),this.register({name:"install_dependencies",description:"Install project dependencies (auto-detects package manager)",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Project directory"}},required:["cwd"]},execute:i(async e=>{let t=await this.commandRunner.installDependencies(e.cwd||process.cwd());return`Installation Output:
171
+ ${t.stdout}
172
+
173
+ Errors:
174
+ ${t.stderr}`},"execute")}),this.register({name:"ba_it_analyze",description:"Business Analyst for IT projects. Analyzes user requirements and creates comprehensive project specifications with features, tech stack, user stories, data model, and recommendations.",inputSchema:{type:"object",properties:{userRequest:{type:"string",description:"User's project request or requirement"},context:{type:"string",description:"Additional context about the project (optional)"}},required:["userRequest"]},execute:i(async e=>await this.baAnalyzer.analyze(e.userRequest,e.context),"execute")}),this.register({name:"document_parse",description:"Parse document and extract text. Supports: pdf, docx, xlsx (auto-detected from file extension)",inputSchema:{type:"object",properties:{path:{type:"string",description:"Document file path"},type:{type:"string",description:"Type: pdf, docx, xlsx (optional, auto-detected)"}},required:["path"]},execute:i(async e=>{let t=e.type?.toLowerCase();if(!t){let n=e.path.split(".").pop()?.toLowerCase();t=(n==="doc"?"docx":n==="xls"?"xlsx":n)||"docx"}return["pdf","docx","xlsx"].includes(t||"")?await this.documentParser.parseDocument(e.path,t):`Error: Unsupported document type "${t}". Supported: PDF, DOCX, XLSX`},"execute")}),this.register({name:"plan_display",description:"Display execution plans and progress updates. Emits events via EventEmitter for UI tracking.",inputSchema:{type:"object",properties:{summary:{type:"string",description:"Plan summary"},steps:{type:"array",description:"Plan steps",items:{type:"object",properties:{step:{type:"number"},action:{type:"string"},status:{type:"string"},reasoning:{type:"string"}},required:["step","action","status"]}},estimatedTime:{type:"string",description:"Estimated time: quick|medium|long"}},required:["summary","steps"]},execute:i(async e=>this.planDisplay.displayPlan(e),"execute")}),this.register({name:"progress_update",description:"Update progress for execution steps. Emits events via EventEmitter for UI tracking.",inputSchema:{type:"object",properties:{step:{type:"number",description:"Step number"},status:{type:"string",description:"Step status: pending, in-progress, completed, failed"},message:{type:"string",description:"Optional status message"},filesCreated:{type:"array",description:"List of files created in this step",items:{type:"string"}},commandsRun:{type:"array",description:"List of commands executed in this step",items:{type:"string"}}},required:["step","status"]},execute:i(async e=>this.planDisplay.updateProgress(e),"execute")}),this.register({name:"galaxy_design_check",description:"Check if Galaxy Design (Galaxy UI) is integrated in the project. Verifies components.json file and framework field.",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Project directory"}},required:["cwd"]},execute:i(async e=>{let t=await this.galaxyDesignChecker.checkIntegration(e.cwd||process.cwd());return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_design_component_details",description:"Get detailed information about integrated Galaxy Design (Galaxy UI) components.",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Project directory"}},required:["cwd"]},execute:i(async e=>{let t=await this.galaxyDesignChecker.getComponentDetails(e.cwd||process.cwd());return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_list",description:"List all Galaxy UI components. Optional filter by category: form, layout, navigation, interactive, overlay, data-display, utility",inputSchema:{type:"object",properties:{category:{type:"string",description:"Filter by category: form, layout, navigation, interactive, overlay, data-display, utility, all"}}},execute:i(async e=>{let t=await Re(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_search",description:"Search Galaxy Desgin (Galaxy UI) components by keyword in name, description, or category",inputSchema:{type:"object",properties:{query:{type:"string",description:"Search query"}},required:["query"]},execute:i(async e=>{let t=await Be(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_get_component",description:"Get detailed information about a specific Galaxy Desgin (Galaxy UI) component including dependencies, docs URL, and install command",inputSchema:{type:"object",properties:{name:{type:"string",description:"Component name"},framework:{type:"string",description:"Framework: vue, react, angular, flutter, react native"}},required:["name"]},execute:i(async e=>{let t=await He(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_categories",description:"Get all Galaxy Desgin (Galaxy UI) component categories with component counts",inputSchema:{type:"object",properties:{}},execute:i(async()=>{let e=await qe();return JSON.stringify(e,null,2)},"execute")}),this.register({name:"galaxy_ui_add",description:"Add Galaxy Desgin (Galaxy UI) components to the project. Automatically detects and uses the project's package manager (npm, yarn, bun, pnpm)",inputSchema:{type:"object",properties:{components:{type:"array",description:"Array of component names to add",items:{type:"string"}},cwd:{type:"string",description:"Working directory (optional)"}},required:["components"]},execute:i(async e=>{let t=await We(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_init",description:"Initialize Galaxy Desgin (Galaxy UI) in the project. Automatically detects and uses the project's package manager (npm, yarn, bun, pnpm). Also automatically installs Tailwind CSS v3 dependencies.",inputSchema:{type:"object",properties:{cwd:{type:"string",description:"Working directory (optional)"},skipPrompts:{type:"boolean",description:"Skip prompts and use defaults (optional)"}}},execute:i(async e=>{let t=await Je(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_docs",description:"Get documentation URL for Galaxy Desgin (Galaxy UI) components or main documentation",inputSchema:{type:"object",properties:{component:{type:"string",description:"Component name (optional)"},language:{type:"string",description:"Language: en or vi (optional)"}}},execute:i(async e=>{let t=Xe(e);return JSON.stringify(t,null,2)},"execute")})}register(e){if(this.tools.has(e.name))throw new Error(`Tool with name "${e.name}" is already registered.`);this.tools.set(e.name,e)}get(e){return this.tools.get(e)}list(){return[...this.tools.values()]}getToolsContext(e){return`Available Tools:
175
+ ${e.map(n=>this.tools.get(n)).map(n=>`- ${n?.name}: ${n?.description}`).join(`
176
+ `)}
177
+ `}getToolsByNames(e){return e?.map(t=>this.tools.get(t)).filter(t=>t!==void 0)||[...this.tools.values()]}async executeTool(e,t){let n=this.tools.get(e);if(!n)throw new Error(`Tool "${e}" not found in registry`);try{let o={},s=await n.execute(t,o),a=typeof s=="string"?s:JSON.stringify(s);return X.emitToolExecution({toolName:e,content:a,status:"success",toolInfo:{toolName:e,args:t,result:s}}),s}catch(o){let s=o instanceof Error?o.message:String(o);throw X.emitToolExecution({toolName:e,content:`Error: ${s}`,status:"error",error:s,toolInfo:{toolName:e,args:t}}),o}}},Ye=new L;var qt="gemini-2.5-flash",V=class{static{i(this,"GeminiConnection")}client;apiKey;chatSession;systemInstruction;model;toolsRegistry=Ye;constructor(e,t){this.apiKey=e?.apiKey,this.model=e?.model??"gemini-2.5-flash",this.client=new Ht({apiKey:this.apiKey}),this.systemInstruction=t,this.initChat()}initChat(){this.chatSession=this.client.chats.create({model:this.model,config:{systemInstruction:this.systemInstruction,tools:[{functionDeclarations:this.getToolDeclarations()}],temperature:.7,thinkingConfig:{thinkingBudget:0}}})}async generate(e){let t=await this.client.models.generateContent({model:qt,contents:e.prompt});return{text:t.text??"",raw:t}}async chat(e,t){if(!this.chatSession)throw new Error("Chat session is not initialized.");let n=e,o,s=0,a=15;for(;n&&s<a;)if(s++,o=await this.chatSession.sendMessage({message:n}),o.functionCalls&&o.functionCalls.length>0){let l=[];for(let u of o.functionCalls)try{let m=u.name||"unknown",d=u.args||{},w=await this.toolsRegistry.executeTool(m,d),h=typeof w=="string"?w:JSON.stringify(w);t&&t("tool",h,m,{toolName:m,args:d,result:w}),l.push({functionResponse:{name:u.name,response:{result:h}}})}catch(m){let d=m instanceof Error?m.message:String(m);if(t){let w={toolName:u.name||"unknown",args:u.args||{},result:`\u274C Error: ${d}`};t("tool",`\u274C Error: ${d}`,u.name,w)}l.push({functionResponse:{name:u.name,response:{error:d}}})}n=l}else return o.text??"";if(s>=a)throw console.warn(`\u26A0\uFE0F Max iterations (${a}) reached. This may indicate:`),console.warn(" - Too many sequential tool calls"),console.warn(" - AI stuck in a reasoning loop"),console.warn(" - Consider reviewing system prompt or tool definitions"),new Error(`Max iterations (${a}) reached`);return""}getToolDeclarations(){return this.toolsRegistry.list().map(t=>this.convertToFunctionDeclaration(t))}convertToFunctionDeclaration(e){return{name:e.name,description:e.description,parameters:this.convertSchemaToGeminiSchema(e.inputSchema)}}convertSchemaToGeminiSchema(e){if(!e)return{type:F.OBJECT,properties:{}};let t={type:F.OBJECT,properties:{}};if(e.properties){t.properties={};for(let[n,o]of Object.entries(e.properties)){let s=o;t.properties[n]=this.convertPropertyToGeminiSchema(s)}}return e.required&&(t.required=e.required),t}convertPropertyToGeminiSchema(e){let t={type:this.mapTypeToGemini(e.type),description:e.description||""};if(e.type==="object"&&e.properties){t.properties={};for(let[n,o]of Object.entries(e.properties))t.properties[n]=this.convertPropertyToGeminiSchema(o);e.required&&(t.required=e.required)}return e.type==="array"&&(e.items&&typeof e.items=="object"?t.items=this.convertPropertyToGeminiSchema(e.items):t.items={type:F.STRING,description:""}),t}mapTypeToGemini(e){return{string:F.STRING,number:F.NUMBER,integer:F.INTEGER,boolean:F.BOOLEAN,object:F.OBJECT,array:F.ARRAY}[e.toLowerCase()]||F.STRING}};import Wt from"@anthropic-ai/sdk";var Ee=class{static{i(this,"ClaudeConnection")}client;model;conversationHistory=[];conversationHistoryWithTools=[];systemPrompt;toolsRegistry=new L;constructor(e,t){let n=e?.apiKey;this.client=new Wt({apiKey:n}),this.model=e?.model||"claude-sonnet-4.5-20250929",this.systemPrompt=t}async chat(e){this.conversationHistory.push({role:"user",content:e});try{let t=await this.client.messages.create({model:this.model,max_tokens:8192,system:this.systemPrompt,messages:this.conversationHistory}),n=t.content[0]?.type==="text"?t.content[0].text:"";return this.conversationHistory.push({role:"assistant",content:n}),n}catch(t){throw console.error("Claude API Error:",t),t}}async*chatStream(e){this.conversationHistory.push({role:"user",content:e});try{let t=await this.client.messages.create({model:this.model,max_tokens:8192,system:this.systemPrompt,messages:this.conversationHistory,stream:!0}),n="";for await(let o of t)if(o.type==="content_block_delta"&&o.delta.type==="text_delta"){let s=o.delta.text||"";n+=s,yield s}this.conversationHistory.push({role:"assistant",content:n})}catch(t){throw console.error("Claude Stream Error:",t),t}}async generate(e,t){try{let n=await this.client.messages.create({model:this.model,max_tokens:8192,system:t||this.systemPrompt,messages:[{role:"user",content:e}]});return n.content[0]?.type==="text"?n.content[0].text:""}catch(n){throw console.error("Claude Generate Error:",n),n}}clearHistory(){this.conversationHistory=[]}getHistory(){return[...this.conversationHistory]}setSystemPrompt(e){this.systemPrompt=e}getModel(){return this.model}setModel(e){this.model=e}async chatWithTools(e,t,n){this.conversationHistoryWithTools.push({role:"user",content:e});let o=0,s=100;for(;o<s;){o++;let a=await this.client.messages.create({model:this.model,max_tokens:8192,system:this.systemPrompt,messages:this.conversationHistoryWithTools,tools:t});if(a.stop_reason!=="tool_use")return this.conversationHistoryWithTools.push({role:"assistant",content:a.content}),a.content.find(m=>m.type==="text")?.text||"";this.conversationHistoryWithTools.push({role:"assistant",content:a.content});let l=[];for(let u of a.content)if(u.type==="tool_use"){let m=u,d=m.name,w=m.input;if(d==="plan_task"||d==="progress_reporter")try{let h=await this.toolsRegistry.executeTool(d,w),E=typeof h=="string"?h:JSON.stringify(h);l.push({type:"tool_result",tool_use_id:m.id,content:E})}catch(h){let E=h instanceof Error?h.message:String(h);l.push({type:"tool_result",tool_use_id:m.id,content:`Error: ${E}`,is_error:!0})}else try{let h=await this.toolsRegistry.executeTool(d,w),E=typeof h=="string"?h:JSON.stringify(h);if(n){let I=!E.startsWith("\u274C");n("tool",E,d,{success:I,output:E})}l.push({type:"tool_result",tool_use_id:m.id,content:E})}catch(h){let E=h instanceof Error?h.message:String(h);n&&n("tool",`\u274C Error: ${E}`,d,{success:!1,error:E}),l.push({type:"tool_result",tool_use_id:m.id,content:`Error: ${E}`,is_error:!0})}}this.conversationHistoryWithTools.push({role:"user",content:l})}return console.warn(`\u26A0\uFE0F Safety limit (${s}) reached in Claude tool loop.`),"Maximum iteration limit reached. Please try again."}clearToolHistory(){this.conversationHistoryWithTools=[]}};function te(r){return`You are Galaxy AI - software development expert by kevinbui.
178
+
179
+ # Response Language
180
+ **Match user's language exactly** (detect from their input)
181
+
182
+ # Available Tools
183
+ ${r}
184
+
185
+ # Planning & Execution Workflow
186
+
187
+ ## Always Plan First
188
+ For every task, ALWAYS create and display an execution plan before starting implementation.
189
+
190
+ ## Execution Loop
191
+ \`\`\`
192
+ 1. Analyze user request and create execution plan
193
+ 2. Display plan using plan_display tool
194
+ 3. Execute each step with appropriate tools
195
+ 4. Update progress using progress_update tool AFTER completing each PLAN STEP
196
+ 5. All steps complete \u2192 Done
197
+ \`\`\`
198
+
199
+ ## Plan Display and Progress Update
200
+ **YOU MUST always display plan using plan_display tool and update progress using progress_update tool.**
201
+
202
+ ### When to call progress_update:
203
+ - \u2705 Call progress_update ONCE after completing ALL tools for a PLAN STEP
204
+ - \u274C DO NOT call progress_update after each individual tool
205
+ - \u2705 Each progress_update corresponds to exactly ONE plan step
206
+
207
+ # Galaxy Design (Galaxy UI) Integration Rules
208
+
209
+ When user requests Galaxy Design (Galaxy UI) integration:
210
+ - \u2705 ALWAYS use Galaxy UI tools for integration and component management
211
+ - \u274C NEVER use direct npm/yarn commands like "npm install @galaxy-design/react"
212
+ - For NEW projects: Call galaxy_ui_init \u2192 galaxy_ui_categories \u2192 galaxy_ui_list \u2192 galaxy_ui_add
213
+ - For EXISTING projects: Check integration with galaxy_design_check \u2192 Use appropriate Galaxy UI tools
214
+
215
+ # Core Rules
216
+ - **Plan First**: ALWAYS create and display execution plan before implementation
217
+ - **Progress Tracking**: Call progress_update ONCE per PLAN STEP (not per tool)
218
+ - **Code Quality**: TypeScript preferred, clean, maintainable, error handling
219
+ - **Git** (if enabled): Conventional commits at logical checkpoints
220
+ - **Testing** (if enabled): Run after changes, fix failures
221
+ - **Error Handling**: Analyze \u2192 Try alternative approach \u2192 Explain
222
+
223
+ Remember: Plan first \u2192 Execute step by step \u2192 Track progress per plan step \u2192 Build complete app!
224
+ `}i(te,"buildUniversalAgentPrompt");var ce=class{static{i(this,"ClaudeAgent")}connection;toolsRegistry=new L;toolNames=["file_read","file_write","file_tree","file_list","file_search","git_status","git_commit","git_push","git_pull","git_diff","git_log","git_branches","command_run","install_dependencies","test_run","document_parse","plan_display","progress_update","galaxy_ui_list","galaxy_ui_search","galaxy_ui_get_component","galaxy_ui_categories","galaxy_ui_add","galaxy_ui_init","galaxy_ui_docs"];constructor(e){let t=this.toolsRegistry.getToolsContext(this.toolNames),n=te(t);this.connection=new Ee(e,n)}getAnthropicTools(){return this.toolsRegistry.getToolsByNames(this.toolNames).map(t=>({name:t.name,description:t.description,input_schema:t.inputSchema}))}async handleUserInput(e,t,n,o=0){try{let a=t?`[System Context: Git=${t.gitEnabled?"ON":"OFF"}, Test Planning=${t.testEnabled?"ON":"OFF"}]
225
+
226
+ ${e}`:e;n&&n("user",a);let l=await this.connection.chatWithTools(a,this.getAnthropicTools(),n);return n&&n("assistant",l),{content:l||"(No response)"}}catch(a){if(o<3){let l=Math.pow(2,o)*1e3;return await new Promise(u=>setTimeout(u,l)),await this.handleUserInput("Continued",t,n,o+1)}throw new Error(`Agent failed after 3 retries: ${a instanceof Error?a.message:String(a)}`)}}clearHistory(){this.connection.clearHistory(),this.connection.clearToolHistory()}};var K=class{static{i(this,"OllamaAgent")}connection;model;toolsRegistry=new L;conversationHistory=[];systemPrompt;config;TOKEN_LIMIT=262144;TOKEN_THRESHOLD=.8;DEFAULT_GEMINI_API_KEY="AIzaSyBUHDmR-RkEqqQTGofX92hXeXeULxBUHGw";toolNames=["file_read","file_write","file_tree","file_list","file_search","git_status","git_commit","git_push","git_pull","git_diff","git_log","git_branches","command_run","install_dependencies","test_run","plan_display","progress_update","galaxy_ui_list","galaxy_ui_search","galaxy_ui_get_component","galaxy_ui_categories","galaxy_ui_add","galaxy_ui_init","galaxy_ui_docs","galaxy_design_check"];constructor(e){this.config=e,this.model=e?.model||"deepseek-v3.1:671b-cloud",this.connection=new W(e);let t=this.toolsRegistry.getToolsContext(this.toolNames);this.systemPrompt=te(t)}getOllamaTools(){return this.toolsRegistry.getToolsByNames(this.toolNames).map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.inputSchema}}))}async summarizeContext(){try{let e=this.conversationHistory.filter(u=>u.role==="user"),t=e.length>0?e[e.length-1]?.content:"Unknown request",n=this.extractCurrentPlan(),o=`
227
+ Please summarize the following conversation context for an AI coding assistant. Be concise but comprehensive.
228
+
229
+ Latest user request: ${t}
230
+
231
+ Current execution plan:
232
+ ${n}
233
+
234
+ Work progress so far:
235
+ ${this.extractWorkProgress()}
236
+
237
+ Current task status:
238
+ ${this.extractCurrentStatus()}
239
+
240
+ Please provide a concise summary that includes:
241
+ 1. Latest user request
242
+ 2. Current execution plan with step details
243
+ 3. What has been accomplished so far
244
+ 4. Current task in progress
245
+ 5. Next steps needed
246
+
247
+ Keep it under 500 words and focus on the most important technical details.
248
+ `,s={apiKey:this.DEFAULT_GEMINI_API_KEY,model:"gemini-2.5-flash",type:"gemini"};return(await new V(s).generate({prompt:o})).text}catch{return this.simpleSummarize()}}simpleSummarize(){return"Previous conversation context (summarized due to length). Recent activity includes planning and progress updates."}extractCurrentPlan(){let e=this.conversationHistory.filter(o=>typeof o.content=="string"&&o.content.includes("plan_display")).slice(-1);if(e.length===0)return"No plan has been displayed yet.";let t=e[0],n=typeof t?.content=="string"?t.content:JSON.stringify(t?.content);try{let o=n.match(/\{.*\}/s);if(o){let s=JSON.parse(o[0]);if(s.steps&&Array.isArray(s.steps))return s.steps.map(a=>`Step ${a.step}: ${a.action} [${a.status||"pending"}]`).join(`
249
+ `)}}catch{return`Plan details: ${n.substring(0,200)}...`}return`Plan details: ${n.substring(0,200)}...`}extractWorkProgress(){let e=this.conversationHistory.filter(t=>t.role==="tool").slice(-5);return e.length===0?"No work progress recorded yet.":e.map((t,n)=>{let o=typeof t.content=="string"?t.content:JSON.stringify(t.content),s=o.length>100?o.substring(0,100)+"...":o;return`${n+1}. ${s}`}).join(`
250
+ `)}extractCurrentStatus(){let e=this.conversationHistory.filter(s=>typeof s.content=="string"&&s.content.includes("plan_display")).slice(-1),t=this.conversationHistory.filter(s=>typeof s.content=="string"&&s.content.includes("progress_update")).slice(-3),n=e.length>0?"Plan has been displayed.":"No plan displayed yet.",o=t.length>0?`Recent progress updates: ${t.length} updates`:"No progress updates yet.";return`${n} ${o}`}async handleUserInput(e,t,n,o=0){try{let a=t?`[System Context: Git=${t.gitEnabled?"ON":"OFF"}, Test Planning=${t.testEnabled?"ON":"OFF"}]
251
+
252
+ ${e}`:e;this.conversationHistory.push({role:"user",content:a});let l=await this.connection.chatWithTools({model:this.model,messages:[{role:"system",content:this.systemPrompt},...this.conversationHistory],tools:this.getOllamaTools(),stream:!1}),u=1e3,m=0;for(;l.message.tool_calls&&m<u;){l.message.content!==""&&X.emitToolExecution({toolName:"assistant_response",content:JSON.stringify(l.message.content),status:"success",toolInfo:{toolName:"assistant_response"}}),m++;let w=l.message.tool_calls;this.conversationHistory.push({role:"assistant",content:l.message.content||"",tool_calls:w});for(let h of w){let E=h.function.name,I=h.function.arguments;if(E==="plan_display"||E==="progress_update")try{let v=await this.toolsRegistry.executeTool(E,I),O=typeof v=="string"?v:JSON.stringify(v);this.conversationHistory.push({role:"tool",content:O}),E==="plan_display"&&this.conversationHistory.push({role:"user",content:'\u26A0\uFE0F CRITICAL: Now execute EACH step in the plan. After completing EACH step, you MUST call progress_update({step: N, status: "completed"|"failed"}). Start with step 1.'})}catch(v){let O=v instanceof Error?v.message:String(v);this.conversationHistory.push({role:"tool",content:`Error: ${O}`})}else try{let v=await this.toolsRegistry.executeTool(E,I),O=typeof v=="string"?v:JSON.stringify(v);this.conversationHistory.push({role:"tool",content:O}),this.conversationHistory.push({role:"user",content:"\u26A0\uFE0F MANDATORY: If the tool you just executed was part of a plan step, you MUST immediately call progress_update with the step number and status (completed/failed). Do NOT skip this step."})}catch(v){let O=v instanceof Error?v.message:String(v);this.conversationHistory.push({role:"tool",content:`Error: ${O}`}),this.conversationHistory.push({role:"user",content:'\u26A0\uFE0F MANDATORY: The tool execution failed. You MUST call progress_update with status="failed" for this step.'})}}l=await this.connection.chatWithTools({model:this.model,messages:[{role:"system",content:this.systemPrompt},...this.conversationHistory],tools:this.getOllamaTools(),stream:!1})}let d=l.message.content||"";return this.conversationHistory.push({role:"assistant",content:d}),{content:d}}catch(a){if(this.isTokenLimitError(a))try{let l=await this.summarizeContext();if(this.clearHistory(),this.conversationHistory.push({role:"system",content:`Previous conversation context summary due to token limit: ${l}
253
+
254
+ Please continue with the user's request based on this context.`}),o<3)return await this.handleUserInput(e,t,n,o+1)}catch(l){console.error("Failed to summarize context:",l)}if(o<3)return this.conversationHistory.length>0&&this.conversationHistory[this.conversationHistory.length-1]?.role==="user"&&this.conversationHistory.pop(),await new Promise(l=>setTimeout(l,1e5)),await this.handleUserInput(e,t,n,o+1);throw new Error(`\u0110ang b\u1ECB l\u1ED7i. H\xE3y th\u1EED l\u1EA1i sau: ${a instanceof Error?a.message:String(a)}`)}}isTokenLimitError(e){if(!e)return!1;if(e.status_code===400&&typeof e.message=="string"&&e.message.includes("prompt too long"))return!0;if(typeof e=="string")try{let n=JSON.parse(e);return n.status_code===400&&typeof n.message=="string"&&n.message.includes("prompt too long")}catch{}let t=e instanceof Error?e.message:String(e);return t.includes("prompt too long")||t.includes("token limit")}clearHistory(){this.conversationHistory=[]}getHistory(){return[...this.conversationHistory]}setModel(e){this.model=e,this.connection=new W({model:e})}getModel(){return this.model}};var le=class{static{i(this,"GeminiAgent")}connection;toolsRegistry=new L;conversationHistory=[];systemPrompt;toolNames=["file_read","file_write","file_tree","file_list","file_search","git_status","git_commit","git_push","git_pull","git_diff","git_log","git_branches","command_run","install_dependencies","test_run","document_parse","plan_display","progress_update","galaxy_ui_list","galaxy_ui_search","galaxy_ui_get_component","galaxy_ui_categories","galaxy_ui_add","galaxy_ui_init","galaxy_ui_docs"];constructor(e){let t=this.toolsRegistry.getToolsContext(this.toolNames);this.systemPrompt=te(t),this.connection=new V(e,this.systemPrompt)}async handleUserInput(e,t,n,o=0){try{let a=t?`[System Context: Git=${t.gitEnabled?"ON":"OFF"}, Test Planning=${t.testEnabled?"ON":"OFF"}]
255
+
256
+ ${e}`:e;this.conversationHistory.push({role:"user",content:a}),n&&n("user",a);let l=i((m,d,w,h)=>{if(n&&m==="tool"&&w){if(w==="plan_display"||w==="progress_update")return;let E=!d.startsWith("\u274C");n("tool",d,w,{success:E,output:h?.result||d})}},"geminiCallback"),u=await this.connection.chat(a,l);return this.conversationHistory.push({role:"assistant",content:u}),n&&n("assistant",u),{content:u||"(No response)"}}catch(a){if(o<3){this.conversationHistory.length>0&&this.conversationHistory[this.conversationHistory.length-1]?.role==="user"&&this.conversationHistory.pop();let l=Math.pow(2,o)*1e3;return await new Promise(u=>setTimeout(u,l)),await this.handleUserInput("Continued",t,n,o+1)}throw new Error(`Agent failed after 3 retries: ${a instanceof Error?a.message:String(a)}`)}}clearHistory(){this.conversationHistory=[],"clearHistory"in this.connection&&typeof this.connection.clearHistory=="function"&&this.connection.clearHistory()}getHistory(){return[...this.conversationHistory]}};import q from"node:fs";import pe from"node:path";import ke from"node:os";import{execSync as Pe}from"node:child_process";var Oe=class{static{i(this,"ConfigManager")}configPath;config;constructor(){this.configPath=this.getConfigPath(),this.config=this.loadConfig()}getConfigDir(){let e=ke.homedir();switch(ke.platform()){case"darwin":case"linux":return pe.join(e,".galaxy");case"win32":return pe.join(e,"AppData","Local","Galaxy");default:return pe.join(e,".galaxy")}}getConfigPath(){return pe.join(this.getConfigDir(),"config.json")}getDefaultConfig(){return{agent:[{type:"manual"}],git:!0,test:!0,autoUpdate:{enabled:!0,checkOnStartup:!0,silent:!1,maxAttempts:3,timeout:3e3,skipVersions:[],lastChecked:null,lastAttemptedVersion:null}}}loadConfig(){try{if(!q.existsSync(this.configPath))return console.log("\u{1F4DD} Creating default config at:",this.configPath),this.createDefaultConfig();let e=q.readFileSync(this.configPath,"utf-8"),t=JSON.parse(e);return this.validateConfig(t)}catch(e){return console.warn("\u26A0\uFE0F Failed to load config, using defaults:",e instanceof Error?e.message:String(e)),this.getDefaultConfig()}}validateConfig(e){let t=this.getDefaultConfig(),n=t.agent;e.agent&&Array.isArray(e.agent)&&(n=e.agent);let o={...t.autoUpdate,...e.autoUpdate||{}};return{agent:n,git:e.git??t.git,test:e.test??t.test,autoUpdate:o}}createDefaultConfig(){let e=this.getDefaultConfig();try{let t=this.getConfigDir();q.existsSync(t)||q.mkdirSync(t,{recursive:!0}),q.writeFileSync(this.configPath,JSON.stringify(e,null,2),"utf-8"),console.log("\u2705 Created default config file"),console.log("\u{1F4C1} Location:",this.configPath),console.log(""),console.log("You can customize settings by editing this file."),console.log("")}catch(t){console.error("\u274C Failed to create config file:",t instanceof Error?t.message:String(t))}return e}saveConfig(){try{let e=this.getConfigDir();q.existsSync(e)||q.mkdirSync(e,{recursive:!0}),q.writeFileSync(this.configPath,JSON.stringify(this.config,null,2),"utf-8")}catch(e){console.error("\u274C Failed to save config:",e instanceof Error?e.message:String(e))}}getMergedConfig(e={}){if(!this.config.agent||!Array.isArray(this.config.agent)||this.config.agent.length===0)return{model:"manual",git:e.git??this.config.git,test:e.test??this.config.test,agent:[],error:'Hi\u1EC7n t\u1EA1i ch\u01B0a c\xF3 agent n\xE0o \u0111\u01B0\u1EE3c c\u1EA5u h\xECnh. Vui l\xF2ng g\xF5 "galaxy --config" \u0111\u1EC3 xem file config v\xE0 th\xEAm agent.'};let t=this.config.agent.find(o=>o.type==="manual")??this.config.agent[0];if(!t)return{model:"manual",git:e.git??this.config.git,test:e.test??this.config.test,agent:this.config.agent,error:"Kh\xF4ng t\xECm th\u1EA5y agent h\u1EE3p l\u1EC7. Vui l\xF2ng ki\u1EC3m tra l\u1EA1i file c\u1EA5u h\xECnh."};let n=this.validateAgent(t);return n.error?{model:t.type,git:e.git??this.config.git,test:e.test??this.config.test,agent:this.config.agent,error:n.error}:{model:t.type,git:e.git??this.config.git,test:e.test??this.config.test,agent:this.config.agent}}validateAgent(e){if(e.type==="manual")return e.apiKey?{valid:!0}:{valid:!1,error:`Mode Manual c\u1EA7n API Key. Vui l\xF2ng:
257
+ 1. G\xF5 /config \u0111\u1EC3 m\u1EDF folder c\u1EA5u h\xECnh
258
+ 2. Th\xEAm "apiKey": "your-api-key" v\xE0o agent type "manual"
259
+ 3. Tho\xE1t CLI v\xE0 v\xE0o l\u1EA1i \u0111\u1EC3 nh\u1EADn API Key.`};if(e.type==="claude"&&!e.apiKey)return{valid:!1,error:`Hi\u1EC7n t\u1EA1i b\u1EA1n ch\u01B0a th\xEAm apikey cho model ${e.type}. Vui l\xF2ng:
260
+ 1. G\xF5 /config \u0111\u1EC3 m\u1EDF folder c\u1EA5u h\xECnh
261
+ 2. Th\xEAm "apiKey": "your-api-key" v\xE0o agent type "claude"
262
+ 3. Tho\xE1t CLI v\xE0 v\xE0o l\u1EA1i \u0111\u1EC3 nh\u1EADn API Key.`};if(e.type==="gemini"&&!e.apiKey)return{valid:!1,error:`Hi\u1EC7n t\u1EA1i b\u1EA1n ch\u01B0a th\xEAm apikey cho model ${e.type}. Vui l\xF2ng:
263
+ 1. G\xF5 /config \u0111\u1EC3 m\u1EDF folder c\u1EA5u h\xECnh
264
+ 2. Th\xEAm "apiKey": "your-api-key" v\xE0o agent type "gemini"
265
+ 3. Tho\xE1t CLI v\xE0 v\xE0o l\u1EA1i \u0111\u1EC3 nh\u1EADn API Key.`};if(e.type==="ollama"){if(!e.host)return{valid:!1,error:'Hi\u1EC7n t\u1EA1i b\u1EA1n ch\u01B0a c\xE0i \u0111\u1EB7t host cho Ollama. Vui l\xF2ng g\xF5 "galaxy --config" \u0111\u1EC3 xem file config v\xE0 th\xEAm host (v\xED d\u1EE5: "http://localhost:11434").'};if((e.host==="https://ollama.com"||e.host.includes("ollama.com"))&&!e.apiKey)return{valid:!1,error:`Hi\u1EC7n t\u1EA1i b\u1EA1n ch\u01B0a th\xEAm apikey cho model ollama. Vui l\xF2ng:
266
+ 1. G\xF5 /config \u0111\u1EC3 m\u1EDF folder c\u1EA5u h\xECnh
267
+ 2. Th\xEAm "apiKey": "your-api-key" v\xE0o agent type "ollama"
268
+ 3. Tho\xE1t CLI v\xE0 v\xE0o l\u1EA1i \u0111\u1EC3 nh\u1EADn API Key.`}}return{valid:!0}}updateConfig(e){this.config={...this.config,...e},this.saveConfig()}getConfig(){return{...this.config}}getConfigFilePath(){return this.configPath}resetConfig(){this.config=this.getDefaultConfig(),this.saveConfig(),console.log("\u2705 Config reset to defaults")}openConfigFolder(){let e=pe.dirname(this.configPath);try{let t=ke.platform();t==="darwin"?Pe(`open "${e}"`):t==="win32"?Pe(`start "" "${e}"`):Pe(`xdg-open "${e}"`),console.log("\u2705 Opened config folder")}catch{console.log("\u274C Could not open folder automatically. Please open it manually.")}}displayConfig(){console.log(""),console.log("\u{1F4CA} Current Galaxy Configuration:"),console.log("\u2501".repeat(50)),console.log("\u{1F4C1} Config file:",this.configPath),console.log(""),console.log("Settings:"),console.log(" Agents:"),this.config.agent.forEach((e,t)=>{console.log(` ${t+1}. Type: ${e.type}${e.model?` | Model: ${e.model}`:""}`)}),console.log(" Git:",this.config.git?"ON":"OFF"),console.log(" Test:",this.config.test?"ON":"OFF"),console.log("\u2501".repeat(50)),console.log(""),this.openConfigFolder()}},R=new Oe;import p from"react";import{Box as S,Text as y}from"ink";import c from"react";import{Box as b,Text as g}from"ink";function Qe(r){try{let e=JSON.parse(r);if(!e.components||!Array.isArray(e.components))return c.createElement(g,null,r);let t={};e.components.forEach(o=>{let s=o.category||"uncategorized";t[s]||(t[s]=[]),t[s].push(o)});let n=Object.entries(t);return c.createElement(b,{flexDirection:"column"},c.createElement(g,{bold:!0,color:"cyan"},"\u{1F4E6} Galaxy UI Components ",c.createElement(g,{color:"gray"},`(${e.total} total)`)),n.map(([o,s])=>c.createElement(b,{key:o,flexDirection:"column",marginTop:1},c.createElement(g,{bold:!0,color:"yellow"},o," ",c.createElement(g,{color:"gray"},`(${s.length})`)),c.createElement(b,{flexDirection:"column",marginLeft:2},s.map((a,l)=>c.createElement(b,{key:l,marginBottom:0},c.createElement(g,{color:"green"},"\u2022"),c.createElement(g,{color:"white",bold:!0}," ",a.name),c.createElement(g,{color:"gray"},` - ${a.description}`)))))))}catch{return c.createElement(g,null,r)}}i(Qe,"formatGalaxyUIListComponents");function Ze(r){try{let e=JSON.parse(r);return!e.components||!Array.isArray(e.components)?c.createElement(g,null,r):c.createElement(b,{flexDirection:"column"},c.createElement(g,{bold:!0,color:"cyan"},"\u{1F50D} Galaxy UI Search Results ",c.createElement(g,{color:"gray"},`(${e.total} found)`)),c.createElement(b,{flexDirection:"column",marginTop:1},e.components.map((t,n)=>{let o=t.relevance==="high"?"green":t.relevance==="medium"?"yellow":"gray";return c.createElement(b,{key:n,flexDirection:"column",marginBottom:1},c.createElement(b,null,c.createElement(g,{color:o},`[${t.relevance.toUpperCase()}]`),c.createElement(g,{color:"white",bold:!0}," ",t.name),c.createElement(g,{color:"gray"},` (${t.category})`)),c.createElement(b,{marginLeft:2},c.createElement(g,{color:"gray"},t.description)),c.createElement(b,{marginLeft:2},c.createElement(g,{color:"blue",dimColor:!0},t.docsUrl)))})))}catch{return c.createElement(g,null,r)}}i(Ze,"formatGalaxyUISearchComponents");function et(r){try{let e=JSON.parse(r);return c.createElement(b,{flexDirection:"column"},c.createElement(g,{bold:!0,color:"cyan"},"\u{1F4C4} Component Details: ",c.createElement(g,{color:"white"},e.name)),c.createElement(b,{marginTop:1,flexDirection:"column"},c.createElement(b,null,c.createElement(g,{color:"yellow"},"Category: "),c.createElement(g,{color:"white"},e.category)),c.createElement(b,{marginTop:1},c.createElement(g,{color:"yellow"},"Description: "),c.createElement(g,{color:"white"},e.description)),e.dependencies&&e.dependencies.length>0&&c.createElement(b,{marginTop:1,flexDirection:"column"},c.createElement(g,{color:"yellow"},"Dependencies:"),c.createElement(b,{marginLeft:2,flexDirection:"column"},e.dependencies.map((t,n)=>c.createElement(g,{key:n,color:"green"},`+ ${t}`)))),e.peerDependencies&&e.peerDependencies.length>0&&c.createElement(b,{marginTop:1,flexDirection:"column"},c.createElement(g,{color:"yellow"},"Peer Dependencies:"),c.createElement(b,{marginLeft:2,flexDirection:"column"},e.peerDependencies.map((t,n)=>c.createElement(g,{key:n,color:"blue"},`~ ${t}`)))),c.createElement(b,{marginTop:1},c.createElement(g,{color:"yellow"},"Install Command: "),c.createElement(g,{color:"white"},e.installCommand)),c.createElement(b,{marginTop:1,flexDirection:"column"},c.createElement(g,{color:"yellow"},"Documentation:"),c.createElement(b,{marginLeft:2},e.docsUrlFramework?c.createElement(b,{flexDirection:"column"},c.createElement(g,{color:"blue",dimColor:!0},e.docsUrl),c.createElement(g,{color:"blue",dimColor:!0},e.docsUrlFramework)):c.createElement(g,{color:"blue",dimColor:!0},e.docsUrl)))))}catch{return c.createElement(g,null,r)}}i(et,"formatGalaxyUIGetComponent");function tt(r){try{let e=JSON.parse(r);return!e.categories||!Array.isArray(e.categories)?c.createElement(g,null,r):c.createElement(b,{flexDirection:"column"},c.createElement(g,{bold:!0,color:"cyan"},"\u{1F4C2} Galaxy UI Categories"),c.createElement(b,{flexDirection:"column",marginTop:1},e.categories.map((t,n)=>c.createElement(b,{key:n,marginBottom:1},c.createElement(g,{color:"white",bold:!0},t.name),c.createElement(g,{color:"gray"},` (${t.count} components)`),c.createElement(b,{marginLeft:2,flexDirection:"column",marginTop:0},t.components.map((o,s)=>c.createElement(g,{key:s,color:"green"},`\u2022 ${o}`)))))))}catch{return c.createElement(g,null,r)}}i(tt,"formatGalaxyUIGetCategories");function nt(r){try{let e=JSON.parse(r),t=e.success?"green":"red",n=e.success?"\u2705":"\u274C";return c.createElement(b,{flexDirection:"column"},c.createElement(g,{bold:!0,color:"cyan"},"\u{1F4E5} Add Galaxy UI Components"),c.createElement(b,{marginTop:1},c.createElement(g,{color:t},`${n} ${e.message}`)),e.output&&c.createElement(b,{marginTop:1,flexDirection:"column"},c.createElement(g,{color:"yellow"},"Output:"),c.createElement(b,{borderStyle:"round",borderColor:"gray",paddingX:1,marginLeft:2,flexDirection:"column"},c.createElement(g,{color:"white"},e.output))))}catch{return c.createElement(g,null,r)}}i(nt,"formatGalaxyUIAddComponents");function ot(r){try{let e=JSON.parse(r),t=e.success?"green":"red",n=e.success?"\u2705":"\u274C";return c.createElement(b,{flexDirection:"column"},c.createElement(g,{bold:!0,color:"cyan"},"\u{1F680} Initialize Galaxy UI"),c.createElement(b,{marginTop:1},c.createElement(g,{color:t},`${n} ${e.message}`)),e.output&&c.createElement(b,{marginTop:1,flexDirection:"column"},c.createElement(g,{color:"yellow"},"Output:"),c.createElement(b,{borderStyle:"round",borderColor:"gray",paddingX:1,marginLeft:2,flexDirection:"column"},c.createElement(g,{color:"white"},e.output))))}catch{return c.createElement(g,null,r)}}i(ot,"formatGalaxyUIInit");function rt(r){try{let e=JSON.parse(r);return c.createElement(b,{flexDirection:"column"},c.createElement(g,{bold:!0,color:"cyan"},"\u{1F4D8} Galaxy UI Documentation"),c.createElement(b,{marginTop:1},c.createElement(g,{color:"yellow"},"Description: "),c.createElement(g,{color:"white"},e.description)),c.createElement(b,{marginTop:1},c.createElement(g,{color:"yellow"},"URL: "),c.createElement(g,{color:"blue",dimColor:!0},e.url)))}catch{return c.createElement(g,null,r)}}i(rt,"formatGalaxyUIGetDocsUrl");var Jt=i(()=>{let r=process.stdout?.columns;return typeof r=="number"&&Number.isFinite(r)?r:80},"getTerminalWidth"),ve=i((r,e)=>r.length<=e?r:r.slice(0,e-3)+"...","truncateLine");var Xt=i((r="")=>{let e=r.replaceAll(/\"/g,"").split("\\n");return p.createElement(S,{flexDirection:"column"},e.map((t,n)=>p.createElement(y,{key:n},t)))},"formatTextWithNewlines");function Vt(r,e){let t=r.split(`
269
+ `),n=e.split(`
270
+ `),o=[],s=0,a=0;for(;s<t.length||a<n.length;){let l=t[s],u=n[a];l===u?(o.push({type:"context",oldLineNum:s+1,newLineNum:a+1,content:l||""}),s++,a++):s<t.length&&l!==void 0&&!n.includes(l)?(o.push({type:"remove",oldLineNum:s+1,content:l||""}),s++):a<n.length&&u!==void 0&&!t.includes(u)?(o.push({type:"add",newLineNum:a+1,content:u||""}),a++):(s<t.length&&(o.push({type:"remove",oldLineNum:s+1,content:l||""}),s++),a<n.length&&(o.push({type:"add",newLineNum:a+1,content:u||""}),a++))}return o}i(Vt,"generateDiff");function Kt(r,e=2){let t=[],n=0;for(;n<r.length;){let o=r[n];if(o&&o.type!=="context")t.push(o),n++;else{let s=n,a=n;for(;a<r.length&&r[a]?.type==="context";)a++;let l=a-s;if(l<=e*2)for(let u=s;u<a;u++)r[u]&&t.push(r[u]);else{for(let m=s;m<s+e;m++)r[m]&&t.push(r[m]);let u=l-e*2;t.push({type:"context",content:`... ${u} unchanged lines ...`});for(let m=a-e;m<a;m++)r[m]&&t.push(r[m])}n=a}}return t}i(Kt,"compressDiff");function zt(r,e){let t=r.split(`
271
+ `),n=[],o=1;for(let s=0;s<t.length;s++){let a=t[s]||"";if(a.startsWith("---")||a.startsWith("+++")){n.push(p.createElement(S,{key:s},p.createElement(y,{bold:!0,color:"cyan"},a)));continue}if(a.startsWith("@@")){n.push(p.createElement(S,{key:s},p.createElement(y,{bold:!0,color:"magenta"},a)));continue}if(a.startsWith("-")){n.push(p.createElement(S,{key:s},p.createElement(y,{dimColor:!0},String(o).padStart(4," ")),p.createElement(y,{color:"red"},` ${a}`))),o++;continue}if(a.startsWith("+")){n.push(p.createElement(S,{key:s},p.createElement(y,{dimColor:!0},String(o).padStart(4," ")),p.createElement(y,{color:"green"},` ${a}`))),o++;continue}n.push(p.createElement(S,{key:s},p.createElement(y,{dimColor:!0},String(o).padStart(4," ")),p.createElement(y,null,` ${a}`))),o++}return p.createElement(S,{flexDirection:"column"},e&&p.createElement(y,{bold:!0,color:"yellow"},`\u{1F4DD} ${e}`),n)}i(zt,"formatDiff");function Yt(r){let e=/```(\w+)?\n([\s\S]*?)```/g,t=[],n=0,o,s=0;for(;(o=e.exec(r))!==null;){o.index>n&&t.push(p.createElement(y,{key:`text-${s}`},r.slice(n,o.index)));let a=o[1]||"text",l=o[2];t.push(p.createElement(S,{key:`code-${s}`,flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1},p.createElement(y,{dimColor:!0},a),p.createElement(y,{color:"cyan"},l))),n=o.index+o[0].length,s++}return n<r.length&&t.push(p.createElement(y,{key:`text-${s}`},r.slice(n))),p.createElement(S,{flexDirection:"column"},t)}i(Yt,"formatCode");var Qt=i((r,e)=>{let t=0,n="current directory";return e?.args?.path&&(n=e?.args.path),r&&(t=r.split(`
272
+ `).filter(s=>{let a=s.trim();return a&&!a.startsWith("Failed")}).length),p.createElement(S,{flexDirection:"column"},p.createElement(y,{bold:!0,color:"cyan"},"\u{1F4C1} LIST DIRECTORY ",p.createElement(y,{color:"gray"},"(",n,")")),p.createElement(S,{marginLeft:1},p.createElement(y,{color:"green"},"\u21B3 Listed ",t," items.")))},"formatFileTree"),Zt=i(r=>{let e=r.split(`
273
+ `).filter(t=>t.trim()!=="");return p.createElement(S,{flexDirection:"column"},p.createElement(y,{bold:!0,color:"yellow"},"\u{1F4C4} File List Results:"),e.map((t,n)=>p.createElement(S,{key:n,marginLeft:2},p.createElement(y,{color:"green"},"\u{1F4C4} ",t))))},"formatFileListAsPlanning"),en=i((r,e)=>{let t=0,n="file";if(e?.args?.path){let o=e.args.path.split("/");n=o[o.length-1]||e.args.path}return r&&(t=r.split(`
274
+ `).length),p.createElement(S,{flexDirection:"column"},p.createElement(y,{bold:!0,color:"cyan"},"\u{1F4C4} READ ",p.createElement(y,{color:"gray"},"(",n,")")),p.createElement(S,{marginLeft:1},p.createElement(y,{color:"green"},"\u21B3 Read ",t," lines.")))},"formatFileRead"),tn=i((r,e)=>{let t="file",n=null;try{n=JSON.parse(r)}catch{if(e?.args?.content){let h=typeof e.args.content=="string"?e.args.content:JSON.stringify(e.args.content);n={isNewFile:!0,newContent:h,linesAdded:h.split(`
275
+ `).length,linesRemoved:0,path:e.args.path}}}if(!n)return p.createElement(y,{wrap:"wrap"},r);if(n.path){let h=n.path.split("/");t=h[h.length-1]||n.path}let{isNewFile:o,oldContent:s,newContent:a,linesAdded:l,linesRemoved:u}=n,m=o?`Succeeded. File created. (+${l} added)`:`Succeeded. File edited. (+${l} added, -${u} removed)`,d=Jt(),w=d-15;if(o){let h=[],E=a.split(`
276
+ `),I=10;return(E.length>I?E.slice(0,I):E).forEach((O,$)=>{let k=ve(O,w);h.push(p.createElement(S,{key:$},p.createElement(y,{dimColor:!0},String($+1).padStart(4," ")),p.createElement(y,{color:"green"},` + ${k}`)))}),E.length>I&&h.push(p.createElement(S,{key:"truncated"},p.createElement(y,{dimColor:!0},"... (",E.length-I," more lines)"))),p.createElement(S,{flexDirection:"column",width:d-2},p.createElement(y,{bold:!0,color:"cyan"},"\u{1F4DD} APPLY PATCH ",p.createElement(y,{color:"gray"},"(",t,")")),p.createElement(S,{marginLeft:1,marginBottom:1},p.createElement(y,{color:"green"},"\u21B3 ",m)),p.createElement(S,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,paddingY:0,width:d-4},h))}else{let h=Vt(s||"",a),E=Kt(h,2),I=[];return E.forEach((v,O)=>{if(v.content.startsWith("...")&&v.content.includes("unchanged"))I.push(p.createElement(S,{key:O},p.createElement(y,{dimColor:!0},v.content)));else if(v.type==="add"){let $=ve(v.content,w);I.push(p.createElement(S,{key:O},p.createElement(y,{dimColor:!0}," ".padStart(4," ")),p.createElement(y,{dimColor:!0},"|"),p.createElement(y,{dimColor:!0},String(v.newLineNum).padStart(4," ")),p.createElement(y,{color:"green"},` + ${$}`)))}else if(v.type==="remove"){let $=ve(v.content,w);I.push(p.createElement(S,{key:O},p.createElement(y,{dimColor:!0},String(v.oldLineNum).padStart(4," ")),p.createElement(y,{dimColor:!0},"|"),p.createElement(y,{dimColor:!0}," ".padStart(4," ")),p.createElement(y,{color:"red"},` - ${$}`)))}else{let $=ve(v.content,w);I.push(p.createElement(S,{key:O},p.createElement(y,{dimColor:!0},String(v.oldLineNum).padStart(4," ")),p.createElement(y,{dimColor:!0},"|"),p.createElement(y,{dimColor:!0},String(v.newLineNum).padStart(4," ")),p.createElement(y,null,` ${$}`)))}}),I.length>30&&(I.splice(30),I.push(p.createElement(S,{key:"truncated"},p.createElement(y,{dimColor:!0},"... (diff truncated for display)")))),p.createElement(S,{flexDirection:"column",width:d-2},p.createElement(y,{bold:!0,color:"cyan"},"\u{1F4DD} APPLY PATCH ",p.createElement(y,{color:"gray"},"(",t,")")),p.createElement(S,{marginLeft:1,marginBottom:1},p.createElement(y,{color:"green"},"\u21B3 ",m)),p.createElement(S,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,paddingY:0,width:d-4},I))}},"formatFileWrite"),nn=i((r,e)=>{let t=!0,n=0,o="command";if(e?.args?.command&&(o=e.args.command),r){let u=r.match(/stdout:\n([\s\S]*?)\n\nstderr:/),m=r.match(/stderr:\n([\s\S]*)/);if(u&&u[1]&&(n=u[1].split(`
277
+ `).filter(w=>w.trim()).length),m&&m[1]){let d=m[1].trim();d&&d.toLowerCase().includes("error")&&(t=!1)}(r.toLowerCase().includes("command not found")||r.toLowerCase().includes("no such file")||r.toLowerCase().includes("permission denied"))&&(t=!1)}return p.createElement(S,{flexDirection:"column"},p.createElement(y,{bold:!0,color:"cyan"},"\u26A1 EXECUTE ",p.createElement(y,{color:"gray"},"(",o,")")),p.createElement(S,{marginLeft:1},p.createElement(y,{color:t?"green":"red"},"\u21B3 ",t?"\u2713":"\u2717"," ",t?"Success":"Failed",". Output: ",n," lines.")))},"formatCommandRun"),on=i(r=>r?r.replace(/^galaxy:/,""):"","normalizeToolName");function st(r,e,t){let n=on(e),o=typeof r=="string"?r:JSON.stringify(r,null,2);switch(n){case"file_tree":return Qt(o,t);case"file_list":return Zt(o,t);case"file_read":return en(o,t);case"file_write":return tn(o,t);case"command_run":return nn(o,t);case"plan_task":return null;case"progress_reporter":return null;case"plan_display":return null;case"progress_update":return null;case"galaxy_ui_list":return Qe(o);case"galaxy_ui_search":return Ze(o);case"galaxy_ui_get_component":return et(o);case"galaxy_ui_categories":return tt(o);case"galaxy_ui_add":return nt(o);case"galaxy_ui_init":return ot(o);case"galaxy_ui_docs":return rt(o);case"diff":return zt(o,e);case"code":return Yt(o);case"assistant_response":return Xt(o);default:return null}}i(st,"formatMessage");var at="0.1.8",mn=i(()=>{let r=ne.stdout?.columns;return typeof r=="number"&&Number.isFinite(r)?r:80},"getTerminalWidth"),dn=i((r,e)=>{let t=r.replace(/\s+$/u,"");if(!t)return"";let n=Math.max(0,Math.floor((e-t.length)/2));return`${" ".repeat(n)}${t}`},"centerLine"),gn=i(r=>{let e=mn(),t=r.model;return[{id:"version",text:at},{id:"hints",text:"ENTER to send \u2022 \\ + ENTER for a new line "},{id:"cwd",text:`Current folder: ${ne.cwd()}`},{id:"config",text:`Agent=${t} Git=${r.git?"ON":"OFF"} Test=${r.test?"ON":"OFF"}`}].map(o=>({id:o.id,text:dn(o.text,e-50)}))},"getInforLines"),fn=un.textSync("GALAXY",{font:"Standard",horizontalLayout:"default",verticalLayout:"default"});function Ne({config:r}){let{exit:e}=an(),[t,n]=B(""),[o,s]=B([{id:"banner"},...r.error?[{id:"config-error",author:"system",content:`\u26A0\uFE0F ${r.error}`,timestamp:Date.now()}]:[]]),[a,l]=B(!1),[u,m]=B([]),[d,w]=B([]),[h,E]=B([]),[I,v]=B(-1),[O,$]=B(0),[k,oe]=B(r),yt=gn(k),re=it(()=>{if(k.model==="manual"){let x=k.agent.find(C=>C.type==="manual");return new K({type:"ollama",model:"qwen3-coder:480b-cloud",host:"https://ollama.com",apiKey:x?.apiKey})}let f=k.agent.find(x=>x.type===k.model);if(!f)return null;switch(k.model){case"claude":return new ce(f);case"ollama":return new K(f);case"gemini":return new le(f);default:return null}},[k.model,k.agent]),Ue=it(()=>[{command:"/help",description:"Hi\u1EC3n th\u1ECB danh s\xE1ch l\u1EC7nh"},{command:"/exit",description:"Tho\xE1t kh\u1ECFi Galaxy CLI"},{command:"/clear",description:"X\xF3a l\u1ECBch s\u1EED h\u1ED9i tho\u1EA1i hi\u1EC7n t\u1EA1i"},{command:"/history",description:"Xem danh s\xE1ch 10 input g\u1EA7n nh\u1EA5t"},{command:"/pwd",description:"Hi\u1EC3n th\u1ECB th\u01B0 m\u1EE5c l\xE0m vi\u1EC7c hi\u1EC7n t\u1EA1i"},{command:"/information",description:"Hi\u1EC3n th\u1ECB th\xF4ng tin h\u1EC7 th\u1ED1ng"},{command:"/git",description:"B\u1EADt/t\u1EAFt git operations (/git true|false)"},{command:"/test",description:"B\u1EADt/t\u1EAFt test planning (/test true|false)"},{command:"/mode",description:"Ch\u1ECDn agent mode (/mode claude|gemini|ollama|manual)"},{command:"/config",description:"M\u1EDF th\u01B0 m\u1EE5c ch\u1EE9a file c\u1EA5u h\xECnh"}],[]);rn(()=>{let f=X.onToolExecution(x=>{if(x.toolName==="plan_display")try{let T=x.toolInfo.args;if(T.steps&&Array.isArray(T.steps)){let P=T.steps.map((D,H)=>({step:D.step,action:D.action,status:H===0?"in-progress":"pending"}));w(P)}}catch{}if(x.toolName==="progress_update")try{let T=x.toolInfo.args,P=T.step,D=T.status,H=D==="completed"?"completed":D==="failed"?"failed":"in-progress";w(U=>U.map(z=>z.step===P?{...z,status:H}:D==="completed"&&z.step===P+1&&z.status==="pending"?{...z,status:"in-progress"}:z))}catch{}let C={id:`tool-${Date.now()}-${Math.random()}`,author:"tool",toolName:x.toolName,content:x.content,toolInfo:x.toolInfo,timestamp:x.timestamp};s(T=>[...T,C])});return()=>{f()}},[]);let ht=i(f=>{let[x,...C]=f.slice(1).split(/\s+/);switch(x){case"exit":A("system","Goodbye!"),e();return;case"help":A("system",["Danh s\xE1ch l\u1EC7nh:",...Ue.map(T=>`${T.command.padEnd(15," ")} ${T.description}`)].join(`
278
+ `));return;case"clear":s([{id:"banner"}]),w([]),re&&"clearHistory"in re&&re.clearHistory(),A("system","\u2705 Cleared conversation and progress");return;case"history":if(h.length===0){A("system","No history yet.");return}{let P=[...h].slice(-10).reverse().map((D,H)=>`${H+1}. ${D.replace(/\n/g," ")}`);A("system",["Recent inputs:",...P].join(`
279
+ `))}return;case"pwd":A("system",`Working directory: ${ne.cwd()}`);return;case"information":{let T=k.model;A("system",["\u{1F4CA} System Information:","Name: Galaxy CLI",`Version: ${at}`,`Current Project: ${ne.cwd()}`,`Agent Mode: ${T}`,`Git Operations: ${k.git?"ON":"OFF"}`,`Testing: ${k.test?"ON":"OFF"}`].join(`
280
+ `))}return;case"mode":{if(C.length===0){let U=k.model;k.model==="manual"?A("system",`\u{1F916} Agent Mode: ${U}
281
+
282
+ Using Orchestrator Agent with full tool access.`):A("system",`\u{1F916} Agent Mode: ${U}
283
+
284
+ Direct chat mode - no tools available.`);return}let T=C[0]?.toLowerCase()??"",P=["claude","gemini","ollama","manual"];if(!i(U=>P.includes(U),"isValidMode")(T)){A("system",`\u274C Invalid mode: ${T}
285
+ Valid modes: ${P.join(", ")}`);return}if(!k.agent.find(U=>U.type===T)){A("system",`\u274C Agent config for "${T}" not found in config file.
286
+ Please add it using /config command.`);return}oe(U=>({...U,model:T})),s([{id:"banner"}]),w([]),A("system",`\u2705 Switched to ${T} mode
287
+ \u{1F504} Conversation cleared`)}return;case"git":if(C.length===0){A("system",`Git operations are currently ${k.git?"ON":"OFF"}`);return}{let T=C[0]?.toLowerCase()??"";T==="true"||T==="on"?(oe(P=>({...P,git:!0})),A("system","\u2705 Git operations enabled")):T==="false"||T==="off"?(oe(P=>({...P,git:!1})),A("system","\u274C Git operations disabled")):A("system","Usage: /git true|false")}return;case"test":if(C.length===0){A("system",`Testing is currently ${k.test?"ON":"OFF"}`);return}{let T=C[0]?.toLowerCase()??"";T==="true"||T==="on"?(oe(P=>({...P,test:!0})),A("system","\u2705 Test planning enabled")):T==="false"||T==="off"?(oe(P=>({...P,test:!1})),A("system","\u274C Test planning disabled")):A("system","Usage: /test true|false")}return;case"config":{let T=R.getConfigFilePath();R.openConfigFolder(),A("system",`\u{1F4C2} Config directory opened
288
+ \u{1F4C4} Config file: ${T}`)}return;default:A("system",`Unknown command: /${x}${C.length?" "+C.join(" "):""}`)}},"handleCommand"),Le=i(async f=>{if(a)return;let x=f.trim();if(x){if(x.startsWith("/")){n(""),ht(x);return}A("user",x),l(!0),n(""),E(C=>[...C,x]),v(-1);try{let C="";if(!re)throw new Error("Agent connection not initialized");C=(await re.handleUserInput(x,{gitEnabled:k.git,testEnabled:k.test},A)).content,d.every(P=>P.status==="completed")&&A("planing","Planning completed.","plan_display",{args:d}),C&&(w([]),A("assistant",C))}catch(C){A("system",`\u274C Error: ${C instanceof Error?C.message:String(C)}`)}finally{l(!1)}}},"handleSubmit");cn((f,x)=>{if(x.ctrl&&f==="c"&&e(),u.length>0&&t.startsWith("/")){x.upArrow||x.shift&&x.tab?$(C=>(C-1+u.length)%u.length):x.downArrow||x.tab?$(C=>(C+1)%u.length):(x.escape||x.return)&&(m([]),$(0));return}if(h.length>0&&!t.startsWith("/")){if(x.upArrow){let C=I===-1?h.length-1:Math.max(0,I-1);v(C),n(h[C]||"")}else if(x.downArrow){if(I===-1)return;let C=I+1;C>=h.length?(v(-1),n("")):(v(C),n(h[C]||""))}}});let A=i((f,x,C,T)=>{let P={id:`${Date.now()}-${f}-${Math.random().toString(16).slice(2)}`,author:f,content:x,toolName:C,toolInfo:T,timestamp:Date.now()};if(f==="tool"&&C==="plan_display"){let D=x.map((H,U)=>({...H,status:U===0?"in-progress":"pending"}));w(D)}else s(D=>[...D,P])},"appendMessage"),je=d.find(f=>f.status==="in-progress");return _.createElement(_.Fragment,null,_.createElement(sn,{items:o},f=>f.author==="user"?_.createElement(N,{key:f.id,flexDirection:"row",marginTop:1},_.createElement(j,{color:"red"},`> ${f.content}`)):f.author==="assistant"?_.createElement(N,{key:f.id,flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"blue",paddingX:1,paddingY:0},_.createElement(j,null,f.content)):f.author==="tool"?_.createElement(N,{key:f.id,flexDirection:"row",marginTop:1},st(f.content||"",f.toolName,f.toolInfo)):f.author==="system"?_.createElement(N,{key:f.id,flexDirection:"row",marginTop:1},_.createElement(j,{color:"gray"},`\u2699 ${f.content}`)):_.createElement(N,{borderColor:"cyan",borderStyle:"round",flexDirection:"row",key:"banner-box",width:ne.stdout.columns},_.createElement(N,{flexDirection:"column"},_.createElement(j,{color:"cyan"},fn)),_.createElement(N,{borderLeft:!0,borderLeftColor:"cyan",flexDirection:"column",marginLeft:2,marginTop:1},yt.map(x=>_.createElement(j,{key:x.id,dimColor:!0},x.text))))),k.model==="manual"&&d.length>0&&_.createElement(N,{flexDirection:"column",paddingTop:1,paddingBottom:1},je&&_.createElement(N,{marginBottom:1},_.createElement(j,{bold:!0,color:"cyan"},"\u26A1 ",je.action)),d.map(f=>{let x=f.status==="completed"?"\u2611":f.status==="in-progress"?"\u2699":f.status==="failed"?"\u274C":"\u2610",C=f.status==="completed"?"green":f.status==="in-progress"?"cyan":f.status==="failed"?"red":"gray";return _.createElement(N,{key:f.step},_.createElement(j,{color:C},x," Step ",f.step,": ",f.action))})),_.createElement(N,{flexDirection:"row",paddingTop:1,width:ne.stdout.columns},a?_.createElement(j,null,_.createElement(j,{color:"cyan"},_.createElement(pn,{type:"dots"}))," Thinking..."):null),_.createElement(N,{borderColor:"green",borderStyle:"round",flexDirection:"column",marginTop:1},_.createElement(N,{alignItems:"center",flexDirection:"row"},_.createElement(j,{color:"green"},"> "),_.createElement(ln,{value:t,showCursor:!a,onChange:a?()=>{}:f=>{if(n(f),f.startsWith("/")){let x=f.toLowerCase(),C=Ue.filter(T=>T.command.toLowerCase().startsWith(x));m(C),$(0)}else m([]),$(0)},onSubmit:a?()=>{}:f=>{if(f.trim().startsWith("/")&&u.length>0){let C=u[O]??u[0];Le(C?.command||"");return}Le(f)},placeholder:a?"Processing... (input disabled)":"Type and press Enter to send"}))),u.length>0&&_.createElement(N,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray"},u.map((f,x)=>_.createElement(N,{key:f.command,paddingX:1,paddingY:0,flexDirection:"row"},_.createElement(j,{color:x===O?"cyan":void 0},f.command.padEnd(15," ")),_.createElement(j,{dimColor:!0},f.description)))))}i(Ne,"App");import yn from"semver";import{readFileSync as hn}from"node:fs";import{fileURLToPath as xn}from"node:url";import{dirname as wn,join as Cn}from"node:path";var Tn=xn(import.meta.url),bn=wn(Tn);function En(){try{let r=Cn(bn,"../package.json");return JSON.parse(hn(r,"utf-8")).version}catch{return"0.1.0"}}i(En,"getCurrentVersion");async function vn(r="galaxy-code",e=3e3){try{let t=new AbortController,n=setTimeout(()=>{t.abort()},e),o=await fetch(`https://registry.npmjs.org/${r}/latest`,{signal:t.signal,headers:{Accept:"application/json"}});return clearTimeout(n),o.ok?(await o.json()).version:null}catch(t){return t instanceof Error&&t.name!=="AbortError"&&console.debug("Failed to fetch latest version:",t.message),null}}i(vn,"fetchLatestVersion");async function ct(r=3e3){try{let e=En(),t=await vn("galaxy-code",r);if(!t)return null;let n=yn.gt(t,e);return{hasUpdate:n,currentVersion:e,latestVersion:t,updateAvailable:n}}catch(e){return console.debug("Error checking for update:",e),null}}i(ct,"checkForUpdate");function lt(r,e){return e.includes(r)}i(lt,"shouldSkipVersion");import{execSync as _n,spawn as Sn}from"node:child_process";import{existsSync as $e,writeFileSync as An,unlinkSync as In}from"node:fs";import{tmpdir as pt}from"node:os";import{join as ut}from"node:path";function kn(){let r=ut(pt(),"galaxy-code-update.lock");return An(r,Date.now().toString()),r}i(kn,"createLockFile");function De(r){try{$e(r)&&In(r)}catch{}}i(De,"removeLockFile");function Pn(){let r=ut(pt(),"galaxy-code-update.lock");if(!$e(r))return!1;try{let e=Number.parseInt($e(r)?"":"0",10),t=Date.now(),n=300*1e3;return t-e>n?(De(r),!1):!0}catch{return!1}}i(Pn,"isUpdateInProgress");function On(r){let e=r.message.toLowerCase();return e.includes("eacces")||e.includes("permission")||e.includes("eperm")}i(On,"isPermissionError");async function mt(r){if(Pn())return{success:!1,error:"\u0110ang c\xF3 process kh\xE1c \u0111ang c\u1EADp nh\u1EADt..."};let e=kn();try{let t=`npm install -g galaxy-code@${r}`;return _n(t,{stdio:"pipe",timeout:6e4}),De(e),{success:!0,needsRestart:!0}}catch(t){return De(e),t instanceof Error?On(t)?{success:!1,error:`C\u1EA7n quy\u1EC1n admin \u0111\u1EC3 c\u1EADp nh\u1EADt. Vui l\xF2ng ch\u1EA1y:
289
+ sudo npm install -g galaxy-code@${r}`}:{success:!1,error:`C\u1EADp nh\u1EADt th\u1EA5t b\u1EA1i: ${t.message}`}:{success:!1,error:"C\u1EADp nh\u1EADt th\u1EA5t b\u1EA1i v\u1EDBi l\u1ED7i kh\xF4ng x\xE1c \u0111\u1ECBnh"}}}i(mt,"performUpdate");function dt(){let r=process.argv.slice(2);Sn("galaxy-code",r,{detached:!0,stdio:"inherit"}).unref(),process.exit(0)}i(dt,"restartCLI");function gt(r){console.log(""),console.log(`\u2705 \u0110\xE3 c\u1EADp nh\u1EADt l\xEAn phi\xEAn b\u1EA3n ${r} th\xE0nh c\xF4ng!`),console.log("")}i(gt,"showUpdateSuccess");function ft(r){console.log(""),console.log("\u26A0\uFE0F Kh\xF4ng th\u1EC3 c\u1EADp nh\u1EADt t\u1EF1 \u0111\u1ED9ng"),console.log(r),console.log(""),console.log("\u0110ang ti\u1EBFp t\u1EE5c v\u1EDBi phi\xEAn b\u1EA3n hi\u1EC7n t\u1EA1i..."),console.log("")}i(ft,"showUpdateError");var ue=Dn(`
290
+ C\xE1ch s\u1EED d\u1EE5ng
291
+ $ galaxy [t\xF9y ch\u1ECDn]
292
+
293
+ T\xF9y ch\u1ECDn
294
+ --help Hi\u1EC3n th\u1ECB tr\u1EE3 gi\xFAp
295
+ --version Hi\u1EC3n th\u1ECB phi\xEAn b\u1EA3n
296
+ --git B\u1EADt git operations (m\u1EB7c \u0111\u1ECBnh: t\u1EEB config)
297
+ --test B\u1EADt test planning (m\u1EB7c \u0111\u1ECBnh: t\u1EEB config)
298
+ --config Hi\u1EC3n th\u1ECB c\u1EA5u h\xECnh hi\u1EC7n t\u1EA1i
299
+ --reset-config \u0110\u1EB7t l\u1EA1i c\u1EA5u h\xECnh v\u1EC1 m\u1EB7c \u0111\u1ECBnh
300
+ --dev B\u1EADt ch\u1EBF \u0111\u1ED9 ph\xE1t tri\u1EC3n v\u1EDBi DevTools
301
+ --no-auto-update T\u1EAFt auto-update khi kh\u1EDFi \u0111\u1ED9ng
302
+
303
+ V\xED d\u1EE5
304
+ $ galaxy
305
+ $ galaxy --test
306
+ $ galaxy --config
307
+ $ galaxy --reset-config
308
+ $ galaxy --dev # B\u1EADt DevTools
309
+
310
+ C\u1EA5u h\xECnh
311
+ V\u1ECB tr\xED file c\u1EA5u h\xECnh theo h\u1EC7 \u0111i\u1EC1u h\xE0nh:
312
+ - macOS/Linux: ~/.galaxy/config.json
313
+ - Windows: %LOCALAPPDATA%\\Galaxy\\config.json
314
+
315
+ Th\u1EE9 t\u1EF1 \u01B0u ti\xEAn: Tham s\u1ED1 CLI > config.json > m\u1EB7c \u0111\u1ECBnh
316
+
317
+ `,{importMeta:import.meta,flags:{git:{type:"boolean"},test:{type:"boolean"},config:{type:"boolean",default:!1},resetConfig:{type:"boolean",default:!1},dev:{type:"boolean",default:!1},noAutoUpdate:{type:"boolean",default:!1}}});async function Un(){let r=R.getConfig(),e=r.autoUpdate;if(!e.enabled||!e.checkOnStartup||ue.flags.noAutoUpdate)return!1;try{let t=await ct(e.timeout);if(!t||!t.hasUpdate||lt(t.latestVersion,e.skipVersions))return!1;e.silent||(console.log(""),console.log(`\u{1F680} Ph\xE1t hi\u1EC7n phi\xEAn b\u1EA3n m\u1EDBi ${t.latestVersion}, \u0111ang c\u1EADp nh\u1EADt...`),console.log(""));let n=await mt(t.latestVersion);if(n.success){if(gt(t.latestVersion),R.updateConfig({...r,autoUpdate:{...e,lastChecked:Date.now(),lastAttemptedVersion:t.latestVersion}}),n.needsRestart)return dt(),!0}else n.error&&ft(n.error)}catch(t){console.debug("Auto-update failed:",t)}return!1}i(Un,"handleAutoUpdate");(async()=>{if(ue.flags.config&&(R.displayConfig(),process.exit(0)),ue.flags.resetConfig&&(R.resetConfig(),process.exit(0)),await Un())return;let e=R.getMergedConfig({git:ue.flags.git,test:ue.flags.test});$n(Nn.createElement(Ne,{config:e}))})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "galaxy-code",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "license": "MIT",
5
5
  "description": "Galaxy Code - AI-powered coding assistant with MCP integration",
6
6
  "author": "Galaxy Agent <galaxy.ai.dev@gmail.com> (https://github.com/galaxy-agent)",
@@ -18,14 +18,15 @@
18
18
  "galaxy"
19
19
  ],
20
20
  "bin": {
21
- "galaxy-code": "./dist/cli.min.js"
21
+ "galaxy-code": "./dist/cli.bundle.js"
22
22
  },
23
23
  "type": "module",
24
24
  "engines": {
25
25
  "node": ">=18.14.1"
26
26
  },
27
27
  "scripts": {
28
- "build": "tsc && node scripts/build-minified.js",
28
+ "build": "node scripts/build-single-bundle.js",
29
+ "build:old": "tsc && node scripts/build-minified.js",
29
30
  "build:tsc": "tsc",
30
31
  "build:min": "node scripts/build-minified.js",
31
32
  "build:bundle": "node scripts/build-bundle.js",
@@ -34,13 +35,12 @@
34
35
  "docs:dev": "cd docs && astro dev",
35
36
  "docs:build": "cd docs && astro build",
36
37
  "devtools": "react-devtools",
37
- "debug": "npm run build && NODE_ENV=development node dist/cli.min.js --dev",
38
+ "debug": "npm run build && NODE_ENV=development node dist/cli.bundle.js --dev",
38
39
  "prepublish": "npm run build",
39
40
  "publish:npm": "node scripts/publish-npm.js"
40
41
  },
41
42
  "files": [
42
- "dist",
43
- "dist/node_modules",
43
+ "dist/cli.bundle.js",
44
44
  "README.md",
45
45
  "LICENSE"
46
46
  ],
package/dist/app.d.ts DELETED
@@ -1,7 +0,0 @@
1
- import React from 'react';
2
- import { MergedConfig } from './utils/config-manager.js';
3
- interface AppProps {
4
- config: MergedConfig;
5
- }
6
- export default function App({ config }: AppProps): React.JSX.Element;
7
- export {};