galaxy-code 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.bundle.js +588 -0
- package/package.json +6 -6
- package/dist/app.d.ts +0 -7
- package/dist/app.js +0 -597
- package/dist/auto-updater.d.ts +0 -21
- package/dist/auto-updater.js +0 -144
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -159
- package/dist/cli.min.js +0 -589
- package/dist/connections/claude.d.ts +0 -71
- package/dist/connections/claude.js +0 -303
- package/dist/connections/gemini.d.ts +0 -40
- package/dist/connections/gemini.js +0 -232
- package/dist/connections/index.d.ts +0 -11
- package/dist/connections/index.js +0 -11
- package/dist/connections/ollama.d.ts +0 -37
- package/dist/connections/ollama.js +0 -73
- package/dist/connections/types.d.ts +0 -22
- package/dist/connections/types.js +0 -7
- package/dist/env.d.ts +0 -1
- package/dist/env.js +0 -29
- package/dist/prompts/ba-it-analyzer.d.ts +0 -1
- package/dist/prompts/ba-it-analyzer.js +0 -143
- package/dist/prompts/index.d.ts +0 -11
- package/dist/prompts/index.js +0 -11
- package/dist/prompts/orchestrator.d.ts +0 -8
- package/dist/prompts/orchestrator.js +0 -88
- package/dist/prompts/planning-agent.d.ts +0 -8
- package/dist/prompts/planning-agent.js +0 -195
- package/dist/prompts/universal-agent.d.ts +0 -7
- package/dist/prompts/universal-agent.js +0 -111
- package/dist/providers/agent-selector.d.ts +0 -29
- package/dist/providers/agent-selector.js +0 -84
- package/dist/providers/claude-agent.d.ts +0 -29
- package/dist/providers/claude-agent.js +0 -121
- package/dist/providers/gemini-agent.d.ts +0 -36
- package/dist/providers/gemini-agent.js +0 -168
- package/dist/providers/index.d.ts +0 -12
- package/dist/providers/index.js +0 -12
- package/dist/providers/ollama-agent.d.ts +0 -53
- package/dist/providers/ollama-agent.js +0 -276
- package/dist/providers/orchestrator.d.ts +0 -16
- package/dist/providers/orchestrator.js +0 -76
- package/dist/tools/ba-it-analyzer.d.ts +0 -66
- package/dist/tools/ba-it-analyzer.js +0 -90
- package/dist/tools/code-generate-agent.d.ts +0 -51
- package/dist/tools/code-generate-agent.js +0 -159
- package/dist/tools/command-runner.d.ts +0 -14
- package/dist/tools/command-runner.js +0 -120
- package/dist/tools/document-parser.d.ts +0 -11
- package/dist/tools/document-parser.js +0 -83
- package/dist/tools/file-operations.d.ts +0 -17
- package/dist/tools/file-operations.js +0 -127
- package/dist/tools/galaxy-ui-integration.d.ts +0 -94
- package/dist/tools/galaxy-ui-integration.js +0 -244
- package/dist/tools/git-operations.d.ts +0 -11
- package/dist/tools/git-operations.js +0 -114
- package/dist/tools/index.d.ts +0 -10
- package/dist/tools/index.js +0 -10
- package/dist/tools/planning-agent.d.ts +0 -29
- package/dist/tools/planning-agent.js +0 -134
- package/dist/tools/progress-reporter.d.ts +0 -19
- package/dist/tools/progress-reporter.js +0 -52
- package/dist/tools/registry.d.ts +0 -21
- package/dist/tools/registry.js +0 -695
- package/dist/tools/tool-event-emitter.d.ts +0 -24
- package/dist/tools/tool-event-emitter.js +0 -25
- package/dist/tools/types.d.ts +0 -31
- package/dist/tools/types.js +0 -1
- package/dist/types.d.ts +0 -39
- package/dist/types.js +0 -8
- package/dist/update-checker.d.ts +0 -22
- package/dist/update-checker.js +0 -85
- package/dist/utils/config-manager.d.ts +0 -102
- package/dist/utils/config-manager.js +0 -326
- package/dist/utils/devtools.d.ts +0 -21
- package/dist/utils/devtools.js +0 -61
- package/dist/utils/message-formatters.d.ts +0 -32
- package/dist/utils/message-formatters.js +0 -590
- package/dist/utils/progress-tracker.d.ts +0 -59
- package/dist/utils/progress-tracker.js +0 -213
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var et=Object.defineProperty;var i=(r,e)=>et(r,"name",{value:e,configurable:!0});import mn from"react";import{render as gn}from"ink";import fn from"meow";import{config as tt}from"dotenv";import{fileURLToPath as nt}from"node:url";import{dirname as ot,join as rt}from"node:path";var st=nt(import.meta.url),it=ot(st),at=process.stdout.write,ct=process.stderr.write,lt=console.log,pt=console.info;process.stdout.write=()=>!0;process.stderr.write=()=>!0;console.log=()=>{};console.info=()=>{};tt({path:rt(it,"..",".env"),debug:!1,override:!1});process.stdout.write=at;process.stderr.write=ct;console.log=lt;console.info=pt;import Y from"node:process";import T,{useMemo as Be,useState as F,useEffect as Gt}from"react";import{Box as P,Static as Ft,Text as j,useApp as Rt,useInput as Bt}from"ink";import qt from"ink-text-input";import Ht from"ink-spinner";import Wt from"figlet";import{GoogleGenAI as vt,Type as L}from"@google/genai";import{Ollama as ut}from"ollama";var U=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 ut({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 ke=`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 se=class{static{i(this,"BAITAnalyzer")}ollama=null;model="gpt-oss:120b-cloud";constructor(){}getConnection(){return this.ollama||(this.ollama=new U({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:ke,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 p=n;p<t.length;p++){let c=t[p];if(a){a=!1;continue}if(c==="\\"){a=!0;continue}if(c==='"'&&!a){s=!s;continue}if(!s){if(c==="{")o++;else if(c==="}"&&(o--,o===0))return t.substring(n,p+1)}}return null}};import{exec as dt}from"child_process";import{promisify as mt}from"util";import ie from"fs/promises";import we from"path";var gt=mt(dt),ae=class{static{i(this,"CommandRunner")}async runCommand(e,t,n=18e4){try{let{stdout:o,stderr:s}=await gt(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=we.join(e,"package.json"),n=await ie.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=we.join(e,"package.json"),n=await ie.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=we.join(e,"package.json"),n=await ie.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 ie.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 ft}from"child_process";import{promisify as ht}from"util";var ce=ht(ft),le=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 ce(`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 ce(`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 ce(`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 ce(`which ${t}`,{timeout:1e3}),!0}catch{return!1}},"checkCommand");return{pdf:await e("pdftotext"),docx:await e("pandoc"),xlsx:await e("ssconvert")}}};import D from"fs/promises";import H from"path";import{exec as yt}from"child_process";import{promisify as xt}from"util";import Z from"os";var X=xt(yt),pe=class{static{i(this,"FileOperations")}async readFile(e){try{return await D.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 D.readFile(e,"utf-8")}catch{n=!0}await D.mkdir(H.dirname(e),{recursive:!0}),await D.writeFile(e,t,"utf-8");let s=t.split(`
|
|
148
|
+
`),a=o?o.split(`
|
|
149
|
+
`):[],p=0,c=0;if(n)p=s.length;else{c=a.length,p=s.length;let u=new Set(a),d=new Set(s),y=a.filter(C=>!d.has(C)),h=s.filter(C=>!u.has(C));c=y.length,p=h.length}return{isNewFile:n,oldContent:o,newContent:t,linesAdded:p,linesRemoved:c,path:e}}catch(n){throw new Error(`Failed to write file ${e}: ${n.message}`)}}async listFiles(e,t=!1){try{if(t)if(Z.platform()==="win32"){let n=[],s=i(async a=>{if(!(n.length>=500))try{let p=await D.readdir(a,{withFileTypes:!0});for(let c of p){if(n.length>=500)break;let u=H.join(a,c.name);if(c.isDirectory()){let d=c.name.toLowerCase();if(d==="node_modules"||d===".git"||d==="dist"||d==="build")continue;await s(u)}else{let d=u.toLowerCase();!d.includes("node_modules")&&!d.includes(".git")&&!d.includes("dist")&&!d.includes("build")&&n.push(u)}}}catch{}},"walk");return await s(e),n.slice(0,500)}else{let{stdout:n}=await X(`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 D.readdir(e,{withFileTypes:!0})).filter(o=>o.isFile()).map(o=>H.join(e,o.name))}catch(n){throw new Error(`Failed to list files in ${e}: ${n.message}`)}}async searchFiles(e,t){try{if(Z.platform()==="win32"){let n=[],s=i(async a=>{if(!(n.length>=100))try{let p=await D.readdir(a,{withFileTypes:!0});for(let c of p){if(n.length>=100)break;let u=H.join(a,c.name);if(c.isDirectory()){let d=c.name.toLowerCase();if(d==="node_modules"||d===".git"||d==="dist"||d==="build")continue;await s(u)}else{let d=H.extname(c.name).toLowerCase();if([".ts",".js",".tsx",".jsx",".json"].includes(d))try{(await D.readFile(u,"utf-8")).includes(t)&&n.push(u)}catch{}}}}catch{}},"searchInDirectory");return await s(e),n.slice(0,100)}else{let{stdout:n}=await X(`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 X(`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=Z.tmpdir(),o=H.join(n,`patch-${Date.now()}.patch`);await D.writeFile(o,t),Z.platform()==="win32"?await X(`patch "${e}" < "${o}"`,{timeout:5e3}):await X(`patch "${e}" < "${o}"`,{timeout:5e3}),await D.unlink(o)}catch(n){throw new Error(`Failed to apply patch: ${n.message}`)}}async getFileTree(e){try{if(Z.platform()==="win32"){let n=i(async(s,a=0)=>{if(a>3)return[];let p=[];try{let c=await D.readdir(s,{withFileTypes:!0});for(let u of c){let d=" ".repeat(a),y=u.name.toLowerCase();if(!(y==="node_modules"||y===".git"||y==="dist"||y==="build"||y===".venv"||y==="venv"||y==="ios"||y==="android"||y===".expo"))if(u.isDirectory()){p.push(`${d}${u.name}/`);let h=await n(H.join(s,u.name),a+1);p.push(...h)}else p.push(`${d}${u.name}`)}}catch{}return p},"buildTree");return(await n(e)).join(`
|
|
152
|
+
`)}else{let{stdout:t}=await X(`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 wt}from"child_process";import{promisify as Ct}from"util";var M=Ct(wt),ue=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 Oe=i(()=>`You are a PLANNING AGENT for software development projects.
|
|
153
|
+
|
|
154
|
+
# Working Directory: ${process.cwd()}
|
|
155
|
+
|
|
156
|
+
# Your Role
|
|
157
|
+
Analyze user request and create actionable execution plan with 3-7 steps.
|
|
158
|
+
|
|
159
|
+
# Input
|
|
160
|
+
User Context: Simple description of what to build/implement
|
|
161
|
+
Example: "Create a todo app with Next.js" or "Add authentication to existing app"
|
|
162
|
+
|
|
163
|
+
# Output Schema
|
|
164
|
+
Output ONLY valid JSON (no markdown, no \`\`\`json wrapper):
|
|
165
|
+
|
|
166
|
+
\`\`\`json
|
|
167
|
+
{
|
|
168
|
+
"summary": "Brief plan description",
|
|
169
|
+
"steps": [
|
|
170
|
+
{
|
|
171
|
+
"step": 1,
|
|
172
|
+
"action": "Clear action description",
|
|
173
|
+
"tool": "tool_name",
|
|
174
|
+
"reasoning": "Why this step"
|
|
175
|
+
}
|
|
176
|
+
],
|
|
177
|
+
"estimatedTime": "quick|medium|long"
|
|
178
|
+
}
|
|
179
|
+
\`\`\`
|
|
180
|
+
|
|
181
|
+
# Available Tools
|
|
182
|
+
|
|
183
|
+
**project_init:**
|
|
184
|
+
- command_run: Execute shell commands (npx create-*, npm init, git commands)
|
|
185
|
+
- install_dependencies: Install packages from package.json
|
|
186
|
+
|
|
187
|
+
**code_operations:**
|
|
188
|
+
- file_tree: View project structure
|
|
189
|
+
- file_read: Read file contents
|
|
190
|
+
- file_write: Create/update files
|
|
191
|
+
- file_delete: Remove files
|
|
192
|
+
|
|
193
|
+
**testing:**
|
|
194
|
+
- test_run: Execute test suite (only if System Context: Test Planning=ON)
|
|
195
|
+
|
|
196
|
+
**version_control:**
|
|
197
|
+
- git_commit: Commit changes with conventional message
|
|
198
|
+
|
|
199
|
+
# Planning Strategy
|
|
200
|
+
|
|
201
|
+
## NEW Projects
|
|
202
|
+
\`\`\`
|
|
203
|
+
1. command_run: Initialize project (create-next-app, create-vite, etc.)
|
|
204
|
+
2. install_dependencies: Add required packages
|
|
205
|
+
3. file_write: Core pages/components
|
|
206
|
+
4. file_write: Additional features
|
|
207
|
+
5. test_run: Run tests (if Test Planning=ON)
|
|
208
|
+
6. git_commit: Save implementation
|
|
209
|
+
\`\`\`
|
|
210
|
+
|
|
211
|
+
## ADD Features (Existing)
|
|
212
|
+
\`\`\`
|
|
213
|
+
1. file_tree: Understand structure
|
|
214
|
+
2. file_read: Check existing code (if needed)
|
|
215
|
+
3. install_dependencies: Add new packages (if needed)
|
|
216
|
+
4. file_write: Implement feature
|
|
217
|
+
5. test_run: Verify changes (if Test Planning=ON)
|
|
218
|
+
6. git_commit: Save changes
|
|
219
|
+
\`\`\`
|
|
220
|
+
|
|
221
|
+
# Planning Rules
|
|
222
|
+
|
|
223
|
+
1. **Step Count**: 3-7 steps (balance detail vs simplicity)
|
|
224
|
+
2. **Logical Order**: Setup \u2192 Dependencies \u2192 Implementation \u2192 Testing \u2192 Commit
|
|
225
|
+
3. **System Context** (optional in input):
|
|
226
|
+
- Test Planning=ON \u2192 Include test_run step
|
|
227
|
+
- Test Planning=OFF \u2192 Skip test_run step
|
|
228
|
+
4. **Time Estimates**:
|
|
229
|
+
- quick: 1-3 steps (<30min)
|
|
230
|
+
- medium: 4-6 steps (30min-2h)
|
|
231
|
+
- long: 7+ steps (>2h)
|
|
232
|
+
|
|
233
|
+
# Example 1: NEW Project
|
|
234
|
+
|
|
235
|
+
Input:
|
|
236
|
+
\`\`\`
|
|
237
|
+
User Context: Create a todo app with Next.js and TypeScript
|
|
238
|
+
\`\`\`
|
|
239
|
+
|
|
240
|
+
Output:
|
|
241
|
+
\`\`\`json
|
|
242
|
+
{
|
|
243
|
+
"summary": "Build Next.js todo app with TypeScript",
|
|
244
|
+
"steps": [
|
|
245
|
+
{
|
|
246
|
+
"step": 1,
|
|
247
|
+
"action": "Initialize Next.js project with TypeScript",
|
|
248
|
+
"tool": "command_run",
|
|
249
|
+
"reasoning": "Setup project foundation"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"step": 2,
|
|
253
|
+
"action": "Create TodoList component with CRUD operations",
|
|
254
|
+
"tool": "file_write",
|
|
255
|
+
"reasoning": "Core todo functionality"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"step": 3,
|
|
259
|
+
"action": "Create TodoItem component with state management",
|
|
260
|
+
"tool": "file_write",
|
|
261
|
+
"reasoning": "Individual todo UI and logic"
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"step": 4,
|
|
265
|
+
"action": "Create main page integrating TodoList",
|
|
266
|
+
"tool": "file_write",
|
|
267
|
+
"reasoning": "App entry point"
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"step": 5,
|
|
271
|
+
"action": "Commit changes: 'feat: initial todo app'",
|
|
272
|
+
"tool": "git_commit",
|
|
273
|
+
"reasoning": "Save implementation"
|
|
274
|
+
}
|
|
275
|
+
],
|
|
276
|
+
"estimatedTime": "medium"
|
|
277
|
+
}
|
|
278
|
+
\`\`\`
|
|
279
|
+
|
|
280
|
+
# Example 2: ADD Feature
|
|
281
|
+
|
|
282
|
+
Input:
|
|
283
|
+
\`\`\`
|
|
284
|
+
User Context: Add user authentication to existing Express app
|
|
285
|
+
\`\`\`
|
|
286
|
+
|
|
287
|
+
Output:
|
|
288
|
+
\`\`\`json
|
|
289
|
+
{
|
|
290
|
+
"summary": "Add JWT authentication to Express app",
|
|
291
|
+
"steps": [
|
|
292
|
+
{
|
|
293
|
+
"step": 1,
|
|
294
|
+
"action": "Check existing project structure",
|
|
295
|
+
"tool": "file_tree",
|
|
296
|
+
"reasoning": "Understand current architecture"
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"step": 2,
|
|
300
|
+
"action": "Install JWT and bcrypt packages",
|
|
301
|
+
"tool": "install_dependencies",
|
|
302
|
+
"reasoning": "Required for authentication"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"step": 3,
|
|
306
|
+
"action": "Create User model and authentication routes",
|
|
307
|
+
"tool": "file_write",
|
|
308
|
+
"reasoning": "Backend auth logic"
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"step": 4,
|
|
312
|
+
"action": "Create authentication middleware",
|
|
313
|
+
"tool": "file_write",
|
|
314
|
+
"reasoning": "Route protection"
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"step": 5,
|
|
318
|
+
"action": "Run tests for auth flow",
|
|
319
|
+
"tool": "test_run",
|
|
320
|
+
"reasoning": "Verify implementation (if Test Planning=ON)"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"step": 6,
|
|
324
|
+
"action": "Commit changes: 'feat: add JWT authentication'",
|
|
325
|
+
"tool": "git_commit",
|
|
326
|
+
"reasoning": "Save feature"
|
|
327
|
+
}
|
|
328
|
+
],
|
|
329
|
+
"estimatedTime": "medium"
|
|
330
|
+
}
|
|
331
|
+
\`\`\`
|
|
332
|
+
|
|
333
|
+
# Critical Reminders
|
|
334
|
+
- **JSON Only**: Start with { and end with } (no markdown wrappers)
|
|
335
|
+
- **English Only**: All text fields in English
|
|
336
|
+
- **Be Specific**: Clear action descriptions (not "implement feature", but "Create TodoList component")
|
|
337
|
+
- **Realistic Steps**: Don't over-plan (3-7 steps max)
|
|
338
|
+
- **Tool Correctness**: Use appropriate tool for each step
|
|
339
|
+
- **Test Conditional**: Only include test_run if Test Planning=ON in input`,"planningSystemPrompt");var de=class{static{i(this,"PlanningAgent")}gemini=null;model="gemini-2.5-flash";constructor(){}getConnection(e){if(!this.gemini){let t=process.env.GOOGLE_AI_API_KEY||process.env.GEMINI_API_KEY;if(!t)throw new Error("PlanningAgent requires GOOGLE_AI_API_KEY or GEMINI_API_KEY in environment variables");this.gemini=new W({type:"gemini",model:this.model,apiKey:t},e)}return this.gemini}async generatePlan(e,t){try{let n=`User Context: ${e}`;if(t){let c=t.ba_it_analyze_response.result;n+=`
|
|
340
|
+
|
|
341
|
+
BA Analysis:
|
|
342
|
+
${JSON.stringify({type:c.type,projectName:c.projectName,coreFeatures:c.coreFeatures.map(u=>u.name),technicalStack:c.technicalStack},null,2)}`}let o=Oe(),s=await this.getConnection(o).generate({prompt:n}),a=this.extractJSON(s.text);return a?JSON.parse(a):this.createFallbackPlan(e)}catch{return this.createFallbackPlan(e)}}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 p=n;p<t.length;p++){let c=t[p];if(a){a=!1;continue}if(c==="\\"){a=!0;continue}if(c==='"'&&!a){s=!s;continue}if(!s){if(c==="{")o++;else if(c==="}"&&(o--,o===0))return t.substring(n,p+1)}}return null}createFallbackPlan(e){return{summary:"Basic implementation plan",steps:[{step:1,action:"Check project structure",status:"pending",tool:"file_tree",reasoning:"Understand existing codebase"},{step:2,action:`Implement: ${e}`,status:"pending",tool:"file_write",reasoning:"Create necessary files"},{step:3,action:"Test implementation",status:"pending",tool:"test_run",reasoning:"Verify functionality"}],estimatedTime:"medium"}}};var me=class{static{i(this,"CodeGenerateAgent")}ollama=null;model="qwen3-coder:480b-cloud";constructor(){}getConnection(){return this.ollama||(this.ollama=new U({model:this.model})),this.ollama}async execute(e){try{let t=this.buildSystemPrompt(),n=this.buildUserPrompt(e),o=await this.getConnection().generate({prompt:n,system:t,model:this.model}),s=this.parseActionPlan(o.response);return{step:e.step,featureName:e.featureName,actions:s}}catch{return{step:e.step,featureName:e.featureName,actions:[]}}}buildSystemPrompt(){return`You are an EXPERT CODE GENERATION PLANNER.
|
|
343
|
+
|
|
344
|
+
# Your Mission:
|
|
345
|
+
Generate a detailed action plan for implementing a feature. You do NOT execute - only plan.
|
|
346
|
+
|
|
347
|
+
# Available Actions:
|
|
348
|
+
1. read_file - Read existing file for context
|
|
349
|
+
2. write_file - Create/update a file
|
|
350
|
+
3. run_command - Execute shell command
|
|
351
|
+
4. search_files - Search for pattern in files
|
|
352
|
+
|
|
353
|
+
# Planning Guidelines:
|
|
354
|
+
1. Start by reading relevant existing files
|
|
355
|
+
2. Plan all necessary file writes (components, APIs, types, tests, etc.)
|
|
356
|
+
3. Include dependency installations if needed
|
|
357
|
+
4. Be thorough - include ALL files needed
|
|
358
|
+
|
|
359
|
+
# Code Quality Requirements:
|
|
360
|
+
- Production-ready, no TODOs or placeholders
|
|
361
|
+
- Full file content, not snippets
|
|
362
|
+
- Proper imports and exports
|
|
363
|
+
- Type safety (TypeScript)
|
|
364
|
+
- Error handling
|
|
365
|
+
- Comments for complex logic
|
|
366
|
+
- Follow framework best practices
|
|
367
|
+
|
|
368
|
+
# Output Format (VALID JSON ARRAY):
|
|
369
|
+
[
|
|
370
|
+
{"action": "read_file", "path": "package.json"},
|
|
371
|
+
{"action": "write_file", "path": "components/Feature.tsx", "content": "full content here"},
|
|
372
|
+
{"action": "write_file", "path": "api/feature.ts", "content": "full content here"},
|
|
373
|
+
{"action": "run_command", "command": "npm install new-package"}
|
|
374
|
+
]
|
|
375
|
+
|
|
376
|
+
CRITICAL:
|
|
377
|
+
- Output ONLY the JSON array, nothing else. Start with [ and end with ]
|
|
378
|
+
- Include full file content in "content" field, not placeholders`}buildUserPrompt(e){let t=`# Feature Implementation Plan Request
|
|
379
|
+
|
|
380
|
+
**Feature**: ${e.featureName}
|
|
381
|
+
**Description**: ${e.featureDescription}
|
|
382
|
+
**Priority**: ${e.priority}
|
|
383
|
+
|
|
384
|
+
## Technical Stack:
|
|
385
|
+
${JSON.stringify(e.technicalStack,null,2)}
|
|
386
|
+
`;return e.userStories&&e.userStories.length>0&&(t+=`
|
|
387
|
+
## User Stories:
|
|
388
|
+
`,e.userStories.forEach(n=>{t+=`- As ${n.as}, I want ${n.want}, so that ${n.so}
|
|
389
|
+
`})),e.dataModel&&e.dataModel.length>0&&(t+=`
|
|
390
|
+
## Data Model:
|
|
391
|
+
${JSON.stringify(e.dataModel,null,2)}
|
|
392
|
+
`),e.apiEndpoints&&e.apiEndpoints.length>0&&(t+=`
|
|
393
|
+
## API Endpoints:
|
|
394
|
+
`,e.apiEndpoints.forEach(n=>{t+=`- ${n.method} ${n.path}: ${n.description}
|
|
395
|
+
`})),e.acceptanceCriteria&&e.acceptanceCriteria.length>0&&(t+=`
|
|
396
|
+
## Acceptance Criteria:
|
|
397
|
+
`,e.acceptanceCriteria.forEach((n,o)=>{t+=`${o+1}. ${n}
|
|
398
|
+
`})),t+=`
|
|
399
|
+
## Working Directory: ${process.cwd()}
|
|
400
|
+
|
|
401
|
+
Generate the action plan as JSON array to implement this feature completely.`,t}parseActionPlan(e){let t=e.trim();t=t.replace(/```json\s*/g,""),t=t.replace(/```\s*/g,"");let n=t.indexOf("["),o=t.lastIndexOf("]");if(n===-1||o===-1)return console.warn("Invalid action plan format - no JSON array found"),[];let s=t.substring(n,o+1);try{return JSON.parse(s).filter(p=>p.action==="read_file"||p.action==="write_file"||p.action==="run_command"||p.action==="search_files")}catch(a){return console.warn(`Failed to parse action plan: ${a}`),[]}}};import{EventEmitter as _t}from"events";var Ce=class extends _t{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)}},B=new Ce;var ge=class{static{i(this,"PlanDisplay")}displayPlan(e){B.emitToolExecution({toolName:"plan_display",content:JSON.stringify(e),status:"success"});let t=`\u{1F4CB} Execution Plan: ${e.summary}
|
|
402
|
+
`;return t+=`Estimated Time: ${e.estimatedTime||"medium"}
|
|
403
|
+
|
|
404
|
+
`,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}
|
|
405
|
+
`}),t}updateProgress(e){B.emitToolExecution({toolName:"progress_update",content:JSON.stringify(e),status:"success"});let n=`${e.status==="completed"?"\u2705":e.status==="failed"?"\u274C":e.status==="in-progress"?"\u26A1":"\u23F3"} Step ${e.step}: ${e.status}
|
|
406
|
+
`;return e.message&&(n+=` ${e.message}
|
|
407
|
+
`),e.filesCreated&&e.filesCreated.length>0&&(n+=` \u{1F4DD} Files created: ${e.filesCreated.join(", ")}
|
|
408
|
+
`),e.commandsRun&&e.commandsRun.length>0&&(n+=` \u{1F527} Commands run: ${e.commandsRun.join(", ")}
|
|
409
|
+
`),n}};import{execa as Ne}from"execa";var Tt="https://unpkg.com/galaxy-design@latest/dist/registry.json",ee="https://galaxy-design.vercel.app",fe={data:null,timestamp:0},St=300*1e3;async function he(){let r=Date.now();if(fe.data&&r-fe.timestamp<St)return fe.data;try{let e={Accept:"application/vnd.github.v3.raw"},t=process.env.GITHUB_TOKEN;t&&(e.Authorization=`Bearer ${t}`);let n=await fetch(Tt,{headers:e});if(!n.ok)throw new Error(`Failed to fetch registry: ${n.statusText}`);let o=await n.json();return fe={data:o,timestamp:r},o}catch(e){throw new Error(`Failed to fetch Galaxy UI registry: ${e instanceof Error?e.message:"Unknown error"}`)}}i(he,"fetchRegistry");async function $e(r){let e=await he(),t=Object.entries(e.components).map(([o,s])=>({name:o,description:s.description,category:s.type,docsUrl:`${ee}/components/${o}`})),n=r?.category&&r.category!=="all"?t.filter(o=>o.category===r.category):t;return{total:n.length,components:n}}i($e,"galaxyUIListComponents");async function je(r){let e=await he(),t=r.query.toLowerCase(),n=Object.entries(e.components).map(([o,s])=>{let a=o.toLowerCase().includes(t),p=s.description.toLowerCase().includes(t),c=s.type.toLowerCase().includes(t),u="low";a?u="high":c?u="medium":p&&(u="low");let d=a||p||c;return{name:o,description:s.description,category:s.type,docsUrl:`${ee}/components/${o}`,relevance:u,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(je,"galaxyUISearchComponents");async function De(r){let t=(await he()).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=`${ee}/components/${r.name}`,o=r.framework?`${n}?framework=${r.framework}`:void 0;return{name:r.name,description:t.description,category:t.type,dependencies:t.dependencies||[],peerDependencies:t.peerDependencies||[],docsUrl:n,docsUrlFramework:o,installCommand:`npx galaxy-design add ${r.name}`}}i(De,"galaxyUIGetComponent");async function Me(){let r=await he(),e=new Map;for(let[n,o]of Object.entries(r.components)){let s=o.type;e.has(s)||e.set(s,[]),e.get(s).push(n)}return{categories:Array.from(e.entries()).map(([n,o])=>({name:n,count:o.length,components:o.sort()})).sort((n,o)=>o.count-n.count)}}i(Me,"galaxyUIGetCategories");async function Le(r){try{let e=["galaxy-design","add",...r.components];r.cwd&&e.push("--cwd",r.cwd);let t=await Ne("npx",e,{cwd:r.cwd||process.cwd(),stderr:"pipe",stdout:"pipe"});return{success:!0,message:`Successfully added components: ${r.components.join(", ")}`,output:t.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(Le,"galaxyUIAddComponents");async function Ue(r){try{let e=["galaxy-design@latest","init"];return r?.skipPrompts&&e.push("--yes"),r?.cwd&&e.push("--cwd",r.cwd),{success:!0,message:"Successfully initialized Galaxy UI",output:(await Ne("npx",e,{cwd:r?.cwd||process.cwd(),stderr:"pipe",stdout:"pipe"})).stdout}}catch(e){let t=e;return{success:!1,message:"Failed to initialize Galaxy UI",output:t.stderr||t.stdout||"Unknown error"}}}i(Ue,"galaxyUIInit");function Ge(r){if(r?.component){let t=r.language==="vi"?"/vi":"";return{url:`${ee}${t}/components/${r.component}`,description:`Documentation for ${r.component} component`}}let e=r?.language==="vi"?"/vi":"";return{url:`${ee}${e}`,description:"Galaxy UI CLI Documentation"}}i(Ge,"galaxyUIGetDocsUrl");var $=class{static{i(this,"ToolRegistry")}tools=new Map;fileOps=new pe;gitOps=new ue;commandRunner=new ae;baAnalyzer=new se;documentParser=new le;planningAgent=new de;codeGenerateAgent=new me;planDisplay=new ge;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(`
|
|
410
|
+
`),"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(`
|
|
411
|
+
`)||"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:
|
|
412
|
+
${t.stdout}
|
|
413
|
+
|
|
414
|
+
stderr:
|
|
415
|
+
${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:
|
|
416
|
+
${n.stdout}
|
|
417
|
+
|
|
418
|
+
Errors:
|
|
419
|
+
${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:
|
|
420
|
+
${t.stdout}
|
|
421
|
+
|
|
422
|
+
Errors:
|
|
423
|
+
${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"},tool:{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:"code_generate",description:"Execute feature implementation with integrated tools. Generates code, writes files, runs commands automatically. Uses qwen3-coder:480b-cloud.",inputSchema:{type:"object",properties:{step:{type:"number",description:"Step number from plan"},featureName:{type:"string",description:"Feature name from coreFeatures"},featureDescription:{type:"string",description:"Feature description"},priority:{type:"string",description:"must-have | should-have | nice-to-have"},technicalStack:{type:"object",description:"Tech stack from BA analysis"},userStories:{type:"array",description:"User stories (optional)"},dataModel:{type:"array",description:"Data model entities (optional)"},apiEndpoints:{type:"array",description:"API endpoints (optional)"},acceptanceCriteria:{type:"array",description:"Acceptance criteria (optional)"}},required:["step","featureName","featureDescription","technicalStack"]},execute:i(async e=>await this.codeGenerateAgent.execute({step:e.step,featureName:e.featureName,featureDescription:e.featureDescription,priority:e.priority||"must-have",technicalStack:e.technicalStack,userStories:e.userStories,dataModel:e.dataModel,apiEndpoints:e.apiEndpoints,acceptanceCriteria:e.acceptanceCriteria}),"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 $e(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_search",description:"Search 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 je(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_get_component",description:"Get detailed information about a specific 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 (optional)"}},required:["name"]},execute:i(async e=>{let t=await De(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_categories",description:"Get all Galaxy UI component categories with component counts",inputSchema:{type:"object",properties:{}},execute:i(async()=>{let e=await Me();return JSON.stringify(e,null,2)},"execute")}),this.register({name:"galaxy_ui_add",description:"Add Galaxy UI components to the project. Executes: npx galaxy-design@latest add [components...]",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 Le(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_init",description:"Initialize Galaxy UI in the project. Executes: npx galaxy-design@latest init",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 Ue(e);return JSON.stringify(t,null,2)},"execute")}),this.register({name:"galaxy_ui_docs",description:"Get documentation URL for 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=Ge(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:
|
|
424
|
+
${e.map(n=>this.tools.get(n)).map(n=>`- ${n?.name}: ${n?.description}`).join(`
|
|
425
|
+
`)}
|
|
426
|
+
`}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 B.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 B.emitToolExecution({toolName:e,content:`Error: ${s}`,status:"error",error:s,toolInfo:{toolName:e,args:t}}),o}}},Fe=new $;var Et="gemini-2.5-flash",W=class{static{i(this,"GeminiConnection")}client;apiKey;chatSession;systemInstruction;model;toolsRegistry=Fe;constructor(e,t){this.apiKey=e?.apiKey,this.model=e?.model??"gemini-2.5-flash",this.client=new vt({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:Et,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 p=[];for(let c of o.functionCalls)try{let u=c.name||"unknown",d=c.args||{},y=await this.toolsRegistry.executeTool(u,d),h=typeof y=="string"?y:JSON.stringify(y);t&&t("tool",h,u,{toolName:u,args:d,result:y}),p.push({functionResponse:{name:c.name,response:{result:h}}})}catch(u){let d=u instanceof Error?u.message:String(u);if(t){let y={toolName:c.name||"unknown",args:c.args||{},result:`\u274C Error: ${d}`};t("tool",`\u274C Error: ${d}`,c.name,y)}p.push({functionResponse:{name:c.name,response:{error:d}}})}n=p}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:L.OBJECT,properties:{}};let t={type:L.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:L.STRING,description:""}),t}mapTypeToGemini(e){return{string:L.STRING,number:L.NUMBER,integer:L.INTEGER,boolean:L.BOOLEAN,object:L.OBJECT,array:L.ARRAY}[e.toLowerCase()]||L.STRING}};import At from"@anthropic-ai/sdk";var ye=class{static{i(this,"ClaudeConnection")}client;model;conversationHistory=[];conversationHistoryWithTools=[];systemPrompt;toolsRegistry=new $;constructor(e,t){let n=e?.apiKey;this.client=new At({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(u=>u.type==="text")?.text||"";this.conversationHistoryWithTools.push({role:"assistant",content:a.content});let p=[];for(let c of a.content)if(c.type==="tool_use"){let u=c,d=u.name,y=u.input;if(d==="plan_task"||d==="progress_reporter")try{let h=await this.toolsRegistry.executeTool(d,y),C=typeof h=="string"?h:JSON.stringify(h);p.push({type:"tool_result",tool_use_id:u.id,content:C})}catch(h){let C=h instanceof Error?h.message:String(h);p.push({type:"tool_result",tool_use_id:u.id,content:`Error: ${C}`,is_error:!0})}else try{let h=await this.toolsRegistry.executeTool(d,y),C=typeof h=="string"?h:JSON.stringify(h);if(n){let v=!C.startsWith("\u274C");n("tool",C,d,{success:v,output:C})}p.push({type:"tool_result",tool_use_id:u.id,content:C})}catch(h){let C=h instanceof Error?h.message:String(h);n&&n("tool",`\u274C Error: ${C}`,d,{success:!1,error:C}),p.push({type:"tool_result",tool_use_id:u.id,content:`Error: ${C}`,is_error:!0})}}this.conversationHistoryWithTools.push({role:"user",content:p})}return console.warn(`\u26A0\uFE0F Safety limit (${s}) reached in Claude tool loop.`),"Maximum iteration limit reached. Please try again."}clearToolHistory(){this.conversationHistoryWithTools=[]}};function K(r){return`You are Galaxy AI - software development expert by kevinbui.
|
|
427
|
+
|
|
428
|
+
# Response Language
|
|
429
|
+
**Match user's language exactly** (detect from their input)
|
|
430
|
+
|
|
431
|
+
# Available Tools
|
|
432
|
+
${r}
|
|
433
|
+
|
|
434
|
+
# Planning & Execution Workflow
|
|
435
|
+
|
|
436
|
+
## When to Plan
|
|
437
|
+
Multi-step projects (apps, websites, features with 3+ steps) \u2192 Use planning workflow
|
|
438
|
+
|
|
439
|
+
## Execution Loop
|
|
440
|
+
\`\`\`
|
|
441
|
+
1. Analyze user request and create execution plan
|
|
442
|
+
2. Display plan using plan_display tool
|
|
443
|
+
3. Execute each step with appropriate tools
|
|
444
|
+
4. Update progress using progress_update tool after each step
|
|
445
|
+
5. All steps complete \u2192 Done
|
|
446
|
+
\`\`\`
|
|
447
|
+
|
|
448
|
+
## Plan Display and Progress Update
|
|
449
|
+
**YOU MUST display plan using plan_display tool and update progress using progress_update tool.**
|
|
450
|
+
|
|
451
|
+
Example of CORRECT execution:
|
|
452
|
+
\`\`\`
|
|
453
|
+
Step 1: Display execution plan with plan_display
|
|
454
|
+
Step 2: command_run({command: "npx create-next-app..."})
|
|
455
|
+
Step 3: progress_update({step: 1, status: "completed"})
|
|
456
|
+
Step 4: file_write({path: "components/TodoList.tsx", content: "..."})
|
|
457
|
+
Step 5: progress_update({step: 2, status: "completed"})
|
|
458
|
+
\`\`\`
|
|
459
|
+
|
|
460
|
+
Example of WRONG execution (DO NOT DO THIS):
|
|
461
|
+
\`\`\`
|
|
462
|
+
Step 1: command_run(...) \u274C Missing plan display and progress update
|
|
463
|
+
Step 2: file_write(...) \u274C Missing plan display and progress update
|
|
464
|
+
\`\`\`
|
|
465
|
+
|
|
466
|
+
## Example Flow
|
|
467
|
+
\`\`\`
|
|
468
|
+
User: "Create todo app with Next.js"
|
|
469
|
+
|
|
470
|
+
\u2192 Step 1: Display plan using plan_display tool
|
|
471
|
+
\u2192 Step 2: command_run({command: "npx create-next-app..."})
|
|
472
|
+
\u2192 Step 3: progress_update({step: 1, status: "completed"})
|
|
473
|
+
\u2192 Step 4: file_write({path: "components/TodoList.tsx", content: "..."})
|
|
474
|
+
\u2192 Step 5: progress_update({step: 2, status: "completed"})
|
|
475
|
+
|
|
476
|
+
... repeat for all steps ...
|
|
477
|
+
\`\`\`
|
|
478
|
+
|
|
479
|
+
# Command Execution Rules
|
|
480
|
+
|
|
481
|
+
**Setup commands (create-*, npm init, etc.):**
|
|
482
|
+
1. \u2705 Run ONCE with ALL default flags (--yes, --default, etc.)
|
|
483
|
+
2. \u2705 Check result \u2192 Success? \u2192 STOP \u2192 Continue to file creation
|
|
484
|
+
3. \u274C DON'T retry with different flags
|
|
485
|
+
4. \u274C NEVER use "cd" - working directory managed automatically
|
|
486
|
+
5. \u274C NEVER execute in /tmp or outside project
|
|
487
|
+
|
|
488
|
+
# Workflows
|
|
489
|
+
|
|
490
|
+
## NEW Projects
|
|
491
|
+
\`\`\`
|
|
492
|
+
1. Display plan using plan_display tool
|
|
493
|
+
2. command_run: Setup with ALL flags \u2192 ONCE
|
|
494
|
+
3. file_write: Pages, components, configs
|
|
495
|
+
4. progress_update: After each major step
|
|
496
|
+
5. Done: Complete functional app
|
|
497
|
+
\`\`\`
|
|
498
|
+
|
|
499
|
+
## ADD Features (Existing Project)
|
|
500
|
+
\`\`\`
|
|
501
|
+
1. Display plan using plan_display tool
|
|
502
|
+
2. file_tree: Understand structure
|
|
503
|
+
3. file_read: Check current code
|
|
504
|
+
4. file_write: New/updated files
|
|
505
|
+
5. command_run: Install deps (--yes)
|
|
506
|
+
6. progress_update: After each major step
|
|
507
|
+
7. Done
|
|
508
|
+
\`\`\`
|
|
509
|
+
|
|
510
|
+
# Detection
|
|
511
|
+
- **NEW**: "Create/Build/Make" + project/app/website
|
|
512
|
+
- **FEATURE**: "Add/Fix/Update" + mentions existing/current
|
|
513
|
+
|
|
514
|
+
# Core Rules
|
|
515
|
+
- **Code**: TypeScript preferred, clean, maintainable, error handling
|
|
516
|
+
- **Git** (if enabled): Conventional commits at logical checkpoints
|
|
517
|
+
- **Testing** (if enabled): Run after changes, fix failures
|
|
518
|
+
- **Errors**: Analyze \u2192 Try alternative approach \u2192 Explain
|
|
519
|
+
- **Progress**: ALWAYS display plan and update progress after completing each step
|
|
520
|
+
|
|
521
|
+
Remember: Execute commands ONCE \u2192 Check success \u2192 Build complete app!`}i(K,"buildUniversalAgentPrompt");var te=class{static{i(this,"ClaudeAgent")}connection;toolsRegistry=new $;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=K(t);this.connection=new ye(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"}]
|
|
522
|
+
|
|
523
|
+
${e}`:e;n&&n("user",a);let p=await this.connection.chatWithTools(a,this.getAnthropicTools(),n);return n&&n("assistant",p),{content:p||"(No response)"}}catch(a){if(o<3){let p=Math.pow(2,o)*1e3;return await new Promise(c=>setTimeout(c,p)),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 J=class{static{i(this,"OllamaAgent")}connection;model;toolsRegistry=new $;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","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){this.model=e?.model||"deepseek-v3.1:671b-cloud",this.connection=new U(e);let t=this.toolsRegistry.getToolsContext(this.toolNames);this.systemPrompt=K(t)}getOllamaTools(){return this.toolsRegistry.getToolsByNames(this.toolNames).map(t=>({type:"function",function:{name:t.name,description:t.description,parameters: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"}]
|
|
524
|
+
|
|
525
|
+
${e}`:e;this.conversationHistory.push({role:"user",content:a});let p=await this.connection.chatWithTools({model:this.model,messages:[{role:"system",content:this.systemPrompt},...this.conversationHistory],tools:this.getOllamaTools(),stream:!1}),c=100,u=0;for(;p.message.tool_calls&&u<c;){u++;let y=p.message.tool_calls;this.conversationHistory.push({role:"assistant",content:p.message.content||"",tool_calls:y});for(let h of y){let C=h.function.name,v=h.function.arguments;if(C==="plan_display"||C==="progress_update")try{let _=await this.toolsRegistry.executeTool(C,v),I=typeof _=="string"?_:JSON.stringify(_);this.conversationHistory.push({role:"tool",content:I}),C==="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(_){let I=_ instanceof Error?_.message:String(_);this.conversationHistory.push({role:"tool",content:`Error: ${I}`})}else try{let _=await this.toolsRegistry.executeTool(C,v),I=typeof _=="string"?_:JSON.stringify(_);this.conversationHistory.push({role:"tool",content:I}),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(_){let I=_ instanceof Error?_.message:String(_);this.conversationHistory.push({role:"tool",content:`Error: ${I}`}),this.conversationHistory.push({role:"user",content:'\u26A0\uFE0F MANDATORY: The tool execution failed. You MUST call progress_update with status="failed" for this step.'})}}p=await this.connection.chatWithTools({model:this.model,messages:[{role:"system",content:this.systemPrompt},...this.conversationHistory],tools:this.getOllamaTools(),stream:!1})}u>=c;let d=p.message.content||"";return this.conversationHistory.push({role:"assistant",content:d}),{content:d}}catch{if(o<3)return this.conversationHistory.length>0&&this.conversationHistory[this.conversationHistory.length-1]?.role==="user"&&this.conversationHistory.pop(),await new Promise(p=>setTimeout(p,1e5)),await this.handleUserInput("Continued",t,n,o+1);throw new Error("\u0110ang b\u1ECB l\u1ED7i. H\xE3y th\u1EED l\u1EA1i sau: ")}}clearHistory(){this.conversationHistory=[]}getHistory(){return[...this.conversationHistory]}setModel(e){this.model=e,this.connection=new U({model:e})}getModel(){return this.model}};var ne=class{static{i(this,"GeminiAgent")}connection;toolsRegistry=new $;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=K(t),this.connection=new W(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"}]
|
|
526
|
+
|
|
527
|
+
${e}`:e;this.conversationHistory.push({role:"user",content:a}),n&&n("user",a);let p=i((u,d,y,h)=>{if(n&&u==="tool"&&y){if(y==="plan_display"||y==="progress_update")return;let C=!d.startsWith("\u274C");n("tool",d,y,{success:C,output:h?.result||d})}},"geminiCallback"),c=await this.connection.chat(a,p);return this.conversationHistory.push({role:"assistant",content:c}),n&&n("assistant",c),{content:c||"(No response)"}}catch(a){if(o<3){this.conversationHistory.length>0&&this.conversationHistory[this.conversationHistory.length-1]?.role==="user"&&this.conversationHistory.pop();let p=Math.pow(2,o)*1e3;return await new Promise(c=>setTimeout(c,p)),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 oe from"node:path";import _e from"node:os";import{execSync as Te}from"node:child_process";var Se=class{static{i(this,"ConfigManager")}configPath;config;constructor(){this.configPath=this.getConfigPath(),this.config=this.loadConfig()}getConfigDir(){let e=_e.homedir();switch(_e.platform()){case"darwin":case"linux":return oe.join(e,".galaxy");case"win32":return oe.join(e,"AppData","Local","Galaxy");default:return oe.join(e,".galaxy")}}getConfigPath(){return oe.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:
|
|
528
|
+
1. G\xF5 /config \u0111\u1EC3 m\u1EDF folder c\u1EA5u h\xECnh
|
|
529
|
+
2. Th\xEAm "apiKey": "your-api-key" v\xE0o agent type "manual"
|
|
530
|
+
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:
|
|
531
|
+
1. G\xF5 /config \u0111\u1EC3 m\u1EDF folder c\u1EA5u h\xECnh
|
|
532
|
+
2. Th\xEAm "apiKey": "your-api-key" v\xE0o agent type "claude"
|
|
533
|
+
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:
|
|
534
|
+
1. G\xF5 /config \u0111\u1EC3 m\u1EDF folder c\u1EA5u h\xECnh
|
|
535
|
+
2. Th\xEAm "apiKey": "your-api-key" v\xE0o agent type "gemini"
|
|
536
|
+
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:
|
|
537
|
+
1. G\xF5 /config \u0111\u1EC3 m\u1EDF folder c\u1EA5u h\xECnh
|
|
538
|
+
2. Th\xEAm "apiKey": "your-api-key" v\xE0o agent type "ollama"
|
|
539
|
+
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=oe.dirname(this.configPath);try{let t=_e.platform();t==="darwin"?Te(`open "${e}"`):t==="win32"?Te(`start "" "${e}"`):Te(`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()}},G=new Se;import l from"react";import{Box as S,Text as g}from"ink";var It=i(()=>{let r=process.stdout?.columns;return typeof r=="number"&&Number.isFinite(r)?r:80},"getTerminalWidth"),xe=i((r,e)=>r.length<=e?r:r.slice(0,e-3)+"...","truncateLine");function Pt(r,e){let t=r.split(`
|
|
540
|
+
`),n=e.split(`
|
|
541
|
+
`),o=[],s=0,a=0;for(;s<t.length||a<n.length;){let p=t[s],c=n[a];p===c?(o.push({type:"context",oldLineNum:s+1,newLineNum:a+1,content:p||""}),s++,a++):s<t.length&&p!==void 0&&!n.includes(p)?(o.push({type:"remove",oldLineNum:s+1,content:p||""}),s++):a<n.length&&c!==void 0&&!t.includes(c)?(o.push({type:"add",newLineNum:a+1,content:c||""}),a++):(s<t.length&&(o.push({type:"remove",oldLineNum:s+1,content:p||""}),s++),a<n.length&&(o.push({type:"add",newLineNum:a+1,content:c||""}),a++))}return o}i(Pt,"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 p=a-s;if(p<=e*2)for(let c=s;c<a;c++)r[c]&&t.push(r[c]);else{for(let u=s;u<s+e;u++)r[u]&&t.push(r[u]);let c=p-e*2;t.push({type:"context",content:`... ${c} unchanged lines ...`});for(let u=a-e;u<a;u++)r[u]&&t.push(r[u])}n=a}}return t}i(kt,"compressDiff");function Ot(r){try{let e=JSON.parse(r);if(e.steps&&Array.isArray(e.steps))return l.createElement(S,{flexDirection:"column"},l.createElement(g,{bold:!0,color:"cyan"},"\u{1F4CB} Execution Plan: ",e.summary),e.steps.map((t,n)=>{let o=t.status==="completed"?"\u2705":t.status==="failed"?"\u274C":t.status==="in-progress"?"\u26A1":"\u23F3";return l.createElement(S,{key:n,marginLeft:2},l.createElement(g,{color:t.status==="completed"?"green":t.status==="failed"?"red":"gray"},o," Step ",t.step,": ",t.action))}))}catch{let e=r.split(`
|
|
542
|
+
`),t=[];for(let n of e){let o=n.trim();o.match(/^[☒✓✅-]\s*\[x\]\s*/i)?t.push({completed:!0,text:o.replace(/^[☒✓✅-]\s*\[x\]\s*/i,"")}):o.match(/^[☐-]\s*\[\s*\]\s*/)?t.push({completed:!1,text:o.replace(/^[☐-]\s*\[\s*\]\s*/,"")}):o.match(/^[-*•]\s+/)&&t.push({completed:!1,text:o.replace(/^[-*•]\s+/,"")})}if(t.length>0)return l.createElement(S,{flexDirection:"column"},l.createElement(g,{bold:!0,color:"cyan"},"\u{1F4CB} Execution Plan"),t.map((n,o)=>l.createElement(S,{key:o,marginLeft:2},l.createElement(g,{color:n.completed?"green":"gray"},n.completed?"\u2612":"\u2610"," ",n.text))))}return l.createElement(g,null,r)}i(Ot,"formatTodos");function Nt(r,e){let t=r.split(`
|
|
543
|
+
`),n=[],o=1;for(let s=0;s<t.length;s++){let a=t[s]||"";if(a.startsWith("---")||a.startsWith("+++")){n.push(l.createElement(S,{key:s},l.createElement(g,{bold:!0,color:"cyan"},a)));continue}if(a.startsWith("@@")){n.push(l.createElement(S,{key:s},l.createElement(g,{bold:!0,color:"magenta"},a)));continue}if(a.startsWith("-")){n.push(l.createElement(S,{key:s},l.createElement(g,{dimColor:!0},String(o).padStart(4," ")),l.createElement(g,{color:"red"},` ${a}`))),o++;continue}if(a.startsWith("+")){n.push(l.createElement(S,{key:s},l.createElement(g,{dimColor:!0},String(o).padStart(4," ")),l.createElement(g,{color:"green"},` ${a}`))),o++;continue}n.push(l.createElement(S,{key:s},l.createElement(g,{dimColor:!0},String(o).padStart(4," ")),l.createElement(g,null,` ${a}`))),o++}return l.createElement(S,{flexDirection:"column"},e&&l.createElement(g,{bold:!0,color:"yellow"},`\u{1F4DD} ${e}`),n)}i(Nt,"formatDiff");function $t(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(l.createElement(g,{key:`text-${s}`},r.slice(n,o.index)));let a=o[1]||"text",p=o[2];t.push(l.createElement(S,{key:`code-${s}`,flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1},l.createElement(g,{dimColor:!0},a),l.createElement(g,{color:"cyan"},p))),n=o.index+o[0].length,s++}return n<r.length&&t.push(l.createElement(g,{key:`text-${s}`},r.slice(n))),l.createElement(S,{flexDirection:"column"},t)}i($t,"formatCode");var jt=i((r,e)=>{let t=0,n="current directory";return e?.args?.path&&(n=e?.args.path),r&&(t=r.split(`
|
|
544
|
+
`).filter(s=>{let a=s.trim();return a&&!a.startsWith("Failed")}).length),l.createElement(S,{flexDirection:"column"},l.createElement(g,{bold:!0,color:"cyan"},"\u{1F4C1} LIST DIRECTORY ",l.createElement(g,{color:"gray"},"(",n,")")),l.createElement(S,{marginLeft:1},l.createElement(g,{color:"green"},"\u21B3 Listed ",t," items.")))},"formatFileTree"),Dt=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(`
|
|
545
|
+
`).length),l.createElement(S,{flexDirection:"column"},l.createElement(g,{bold:!0,color:"cyan"},"\u{1F4C4} READ ",l.createElement(g,{color:"gray"},"(",n,")")),l.createElement(S,{marginLeft:1},l.createElement(g,{color:"green"},"\u21B3 Read ",t," lines.")))},"formatFileRead"),Mt=i((r,e)=>{let t="file",n=null;try{n=JSON.parse(r)}catch{e?.args?.content&&(n={isNewFile:!0,newContent:e.args.content,linesAdded:e.args.content.split(`
|
|
546
|
+
`).length,linesRemoved:0,path:e.args.path})}if(!n)return l.createElement(g,{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:p,linesRemoved:c}=n,u=o?`Succeeded. File created. (+${p} added)`:`Succeeded. File edited. (+${p} added, -${c} removed)`,d=It(),y=d-15;if(o){let h=[],C=a.split(`
|
|
547
|
+
`),v=10;return(C.length>v?C.slice(0,v):C).forEach((I,k)=>{let E=xe(I,y);h.push(l.createElement(S,{key:k},l.createElement(g,{dimColor:!0},String(k+1).padStart(4," ")),l.createElement(g,{color:"green"},` + ${E}`)))}),C.length>v&&h.push(l.createElement(S,{key:"truncated"},l.createElement(g,{dimColor:!0},"... (",C.length-v," more lines)"))),l.createElement(S,{flexDirection:"column",width:d-2},l.createElement(g,{bold:!0,color:"cyan"},"\u{1F4DD} APPLY PATCH ",l.createElement(g,{color:"gray"},"(",t,")")),l.createElement(S,{marginLeft:1,marginBottom:1},l.createElement(g,{color:"green"},"\u21B3 ",u)),l.createElement(S,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,paddingY:0,width:d-4},h))}else{let h=Pt(s||"",a),C=kt(h,2),v=[];return C.forEach((_,I)=>{if(_.content.startsWith("...")&&_.content.includes("unchanged"))v.push(l.createElement(S,{key:I},l.createElement(g,{dimColor:!0},_.content)));else if(_.type==="add"){let k=xe(_.content,y);v.push(l.createElement(S,{key:I},l.createElement(g,{dimColor:!0}," ".padStart(4," ")),l.createElement(g,{dimColor:!0},"|"),l.createElement(g,{dimColor:!0},String(_.newLineNum).padStart(4," ")),l.createElement(g,{color:"green"},` + ${k}`)))}else if(_.type==="remove"){let k=xe(_.content,y);v.push(l.createElement(S,{key:I},l.createElement(g,{dimColor:!0},String(_.oldLineNum).padStart(4," ")),l.createElement(g,{dimColor:!0},"|"),l.createElement(g,{dimColor:!0}," ".padStart(4," ")),l.createElement(g,{color:"red"},` - ${k}`)))}else{let k=xe(_.content,y);v.push(l.createElement(S,{key:I},l.createElement(g,{dimColor:!0},String(_.oldLineNum).padStart(4," ")),l.createElement(g,{dimColor:!0},"|"),l.createElement(g,{dimColor:!0},String(_.newLineNum).padStart(4," ")),l.createElement(g,null,` ${k}`)))}}),v.length>30&&(v.splice(30),v.push(l.createElement(S,{key:"truncated"},l.createElement(g,{dimColor:!0},"... (diff truncated for display)")))),l.createElement(S,{flexDirection:"column",width:d-2},l.createElement(g,{bold:!0,color:"cyan"},"\u{1F4DD} APPLY PATCH ",l.createElement(g,{color:"gray"},"(",t,")")),l.createElement(S,{marginLeft:1,marginBottom:1},l.createElement(g,{color:"green"},"\u21B3 ",u)),l.createElement(S,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,paddingY:0,width:d-4},v))}},"formatFileWrite"),Lt=i((r,e)=>{let t=!0,n=0,o="command";if(e?.args?.command&&(o=e.args.command),r){let c=r.match(/stdout:\n([\s\S]*?)\n\nstderr:/),u=r.match(/stderr:\n([\s\S]*)/);if(c&&c[1]&&(n=c[1].split(`
|
|
548
|
+
`).filter(y=>y.trim()).length),u&&u[1]){let d=u[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 l.createElement(S,{flexDirection:"column"},l.createElement(g,{bold:!0,color:"cyan"},"\u26A1 EXECUTE ",l.createElement(g,{color:"gray"},"(",o,")")),l.createElement(S,{marginLeft:1},l.createElement(g,{color:t?"green":"red"},"\u21B3 ",t?"\u2713":"\u2717"," ",t?"Success":"Failed",". Output: ",n," lines.")))},"formatCommandRun"),Ut=i(r=>r?r.replace(/^galaxy:/,""):"","normalizeToolName");function Re(r,e,t){let n=Ut(e),o=typeof r=="string"?r:JSON.stringify(r,null,2);switch(n){case"file_tree":return jt(o,t);case"file_read":return Dt(o,t);case"file_write":return Mt(o,t);case"command_run":return Lt(o,t);case"plan_task":return null;case"progress_reporter":return null;case"plan_display":return null;case"progress_update":return null;case"todos":return Ot(o);case"diff":return Nt(o,e);case"code":return $t(o);default:return l.createElement(g,{wrap:"wrap"},o)}}i(Re,"formatMessage");var qe="0.1.7",Jt=i(()=>{let r=Y.stdout?.columns;return typeof r=="number"&&Number.isFinite(r)?r:80},"getTerminalWidth"),Vt=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"),Xt=i(r=>{let e=Jt(),t=r.model;return[{id:"version",text:qe},{id:"hints",text:"ENTER to send \u2022 \\ + ENTER for a new line "},{id:"cwd",text:`Current folder: ${Y.cwd()}`},{id:"config",text:`Agent=${t} Git=${r.git?"ON":"OFF"} Test=${r.test?"ON":"OFF"}`}].map(o=>({id:o.id,text:Vt(o.text,e-50)}))},"getInforLines"),Kt=Wt.textSync("GALAXY",{font:"Standard",horizontalLayout:"default",verticalLayout:"default"});function be({config:r}){let{exit:e}=Rt(),[t,n]=F(""),[o,s]=F([{id:"banner"},...r.error?[{id:"config-error",author:"system",content:`\u26A0\uFE0F ${r.error}`,timestamp:Date.now()}]:[]]),[a,p]=F(!1),[c,u]=F([]),[d,y]=F([]),[h,C]=F([]),[v,_]=F(-1),[I,k]=F(0),[E,z]=F(r),Qe=Xt(E),Q=Be(()=>{if(E.model==="manual"){let f=E.agent.find(x=>x.type==="manual");return new J({type:"ollama",model:"qwen3-coder:480b-cloud",host:"https://ollama.com",apiKey:f?.apiKey})}let m=E.agent.find(f=>f.type===E.model);if(!m)return null;switch(E.model){case"claude":return new te(m);case"ollama":return new J(m);case"gemini":return new ne(m);default:return null}},[E.model,E.agent]),Ae=Be(()=>[{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"}],[]);Gt(()=>{let m=B.onToolExecution(f=>{if(f.toolName==="plan_display"&&f.status==="success"&&f.toolInfo?.result)try{let w=f.toolInfo.result;if(w.steps&&Array.isArray(w.steps)){let A=w.steps.map((O,R)=>({step:O.step,action:O.action,status:R===0?"in-progress":"pending"}));y(A)}}catch{}if(f.toolName==="progress_update")try{let w=JSON.parse(f.content),A=w.step,O=w.status,R=O==="completed"?"completed":O==="failed"?"failed":"in-progress";y(N=>N.map(V=>V.step===A?{...V,status:R}:O==="completed"&&V.step===A+1&&V.status==="pending"?{...V,status:"in-progress"}:V))}catch{}let x={id:`tool-${Date.now()}-${Math.random()}`,author:"tool",toolName:f.toolName,content:f.content,toolInfo:f.toolInfo,timestamp:f.timestamp};s(w=>[...w,x])});return()=>{m()}},[]);let Ze=i(m=>{let[f,...x]=m.slice(1).split(/\s+/);switch(f){case"exit":b("system","Goodbye!"),e();return;case"help":b("system",["Danh s\xE1ch l\u1EC7nh:",...Ae.map(w=>`${w.command.padEnd(15," ")} ${w.description}`)].join(`
|
|
549
|
+
`));return;case"clear":s([{id:"banner"}]),y([]),Q&&"clearHistory"in Q&&Q.clearHistory(),b("system","\u2705 Cleared conversation and progress");return;case"history":if(h.length===0){b("system","No history yet.");return}{let A=[...h].slice(-10).reverse().map((O,R)=>`${R+1}. ${O.replace(/\n/g," ")}`);b("system",["Recent inputs:",...A].join(`
|
|
550
|
+
`))}return;case"pwd":b("system",`Working directory: ${Y.cwd()}`);return;case"information":{let w=E.model;b("system",["\u{1F4CA} System Information:","Name: Galaxy CLI",`Version: ${qe}`,`Current Project: ${Y.cwd()}`,`Agent Mode: ${w}`,`Git Operations: ${E.git?"ON":"OFF"}`,`Testing: ${E.test?"ON":"OFF"}`].join(`
|
|
551
|
+
`))}return;case"mode":{if(x.length===0){let N=E.model;E.model==="manual"?b("system",`\u{1F916} Agent Mode: ${N}
|
|
552
|
+
|
|
553
|
+
Using Orchestrator Agent with full tool access.`):b("system",`\u{1F916} Agent Mode: ${N}
|
|
554
|
+
|
|
555
|
+
Direct chat mode - no tools available.`);return}let w=x[0]?.toLowerCase()??"",A=["claude","gemini","ollama","manual"];if(!i(N=>A.includes(N),"isValidMode")(w)){b("system",`\u274C Invalid mode: ${w}
|
|
556
|
+
Valid modes: ${A.join(", ")}`);return}if(!E.agent.find(N=>N.type===w)){b("system",`\u274C Agent config for "${w}" not found in config file.
|
|
557
|
+
Please add it using /config command.`);return}z(N=>({...N,model:w})),s([{id:"banner"}]),y([]),b("system",`\u2705 Switched to ${w} mode
|
|
558
|
+
\u{1F504} Conversation cleared`)}return;case"git":if(x.length===0){b("system",`Git operations are currently ${E.git?"ON":"OFF"}`);return}{let w=x[0]?.toLowerCase()??"";w==="true"||w==="on"?(z(A=>({...A,git:!0})),b("system","\u2705 Git operations enabled")):w==="false"||w==="off"?(z(A=>({...A,git:!1})),b("system","\u274C Git operations disabled")):b("system","Usage: /git true|false")}return;case"test":if(x.length===0){b("system",`Testing is currently ${E.test?"ON":"OFF"}`);return}{let w=x[0]?.toLowerCase()??"";w==="true"||w==="on"?(z(A=>({...A,test:!0})),b("system","\u2705 Test planning enabled")):w==="false"||w==="off"?(z(A=>({...A,test:!1})),b("system","\u274C Test planning disabled")):b("system","Usage: /test true|false")}return;case"config":{let w=G.getConfigFilePath();G.openConfigFolder(),b("system",`\u{1F4C2} Config directory opened
|
|
559
|
+
\u{1F4C4} Config file: ${w}`)}return;default:b("system",`Unknown command: /${f}${x.length?" "+x.join(" "):""}`)}},"handleCommand"),Ie=i(async m=>{if(a)return;let f=m.trim();if(f){if(f.startsWith("/")){n(""),Ze(f);return}b("user",f),p(!0),n(""),C(x=>[...x,f]),_(-1);try{let x="";if(!Q)throw new Error("Agent connection not initialized");x=(await Q.handleUserInput(f,{gitEnabled:E.git,testEnabled:E.test},b)).content,x&&b("assistant",x)}catch(x){b("system",`\u274C Error: ${x instanceof Error?x.message:String(x)}`)}finally{p(!1)}}},"handleSubmit");Bt((m,f)=>{if(f.ctrl&&m==="c"&&e(),c.length>0&&t.startsWith("/")){f.upArrow||f.shift&&f.tab?k(x=>(x-1+c.length)%c.length):f.downArrow||f.tab?k(x=>(x+1)%c.length):(f.escape||f.return)&&(u([]),k(0));return}if(h.length>0&&!t.startsWith("/")){if(f.upArrow){let x=v===-1?h.length-1:Math.max(0,v-1);_(x),n(h[x]||"")}else if(f.downArrow){if(v===-1)return;let x=v+1;x>=h.length?(_(-1),n("")):(_(x),n(h[x]||""))}}});let b=i((m,f,x,w)=>{let A={id:`${Date.now()}-${m}-${Math.random().toString(16).slice(2)}`,author:m,content:f,toolName:x,toolInfo:w,timestamp:Date.now()};if(m==="tool"&&x==="plan_display"){let O=f.map((R,N)=>({...R,status:N===0?"in-progress":"pending"}));y(O),E.model}else s(O=>[...O,A])},"appendMessage"),Pe=d.find(m=>m.status==="in-progress");return T.createElement(T.Fragment,null,T.createElement(Ft,{items:o},m=>m.author==="user"?T.createElement(P,{key:m.id,flexDirection:"row",marginTop:1},T.createElement(j,{color:"red"},`> ${m.content}`)):m.author==="assistant"?T.createElement(P,{key:m.id,flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"blue",paddingX:1,paddingY:0},T.createElement(j,null,m.content)):m.author==="tool"?T.createElement(P,{key:m.id,flexDirection:"row",marginTop:1},Re(m.content||"",m.toolName,m.toolInfo)):m.author==="system"?T.createElement(P,{key:m.id,flexDirection:"row",marginTop:1},T.createElement(j,{color:"gray"},`\u2699 ${m.content}`)):T.createElement(P,{borderColor:"cyan",borderStyle:"round",flexDirection:"row",key:"banner-box",width:Y.stdout.columns},T.createElement(P,{flexDirection:"column"},T.createElement(j,{color:"cyan"},Kt)),T.createElement(P,{borderLeft:!0,borderLeftColor:"cyan",flexDirection:"column",marginLeft:2,marginTop:1},Qe.map(f=>T.createElement(j,{key:f.id,dimColor:!0},f.text))))),E.model==="manual"&&d.length>0&&T.createElement(P,{flexDirection:"column",paddingTop:1,paddingBottom:1},Pe&&T.createElement(P,{marginBottom:1},T.createElement(j,{bold:!0,color:"cyan"},"\u26A1 ",Pe.action)),d.map(m=>{let f=m.status==="completed"?"\u2611":m.status==="in-progress"?"\u2699":m.status==="failed"?"\u274C":"\u2610",x=m.status==="completed"?"green":m.status==="in-progress"?"cyan":m.status==="failed"?"red":"gray";return T.createElement(P,{key:m.step},T.createElement(j,{color:x},f," Step ",m.step,": ",m.action))})),T.createElement(P,{flexDirection:"row",paddingTop:1,width:Y.stdout.columns},a?T.createElement(j,null,T.createElement(j,{color:"cyan"},T.createElement(Ht,{type:"dots"}))," Thinking..."):null),T.createElement(P,{borderColor:"green",borderStyle:"round",flexDirection:"column",marginTop:1},T.createElement(P,{alignItems:"center",flexDirection:"row"},T.createElement(j,{color:"green"},"> "),T.createElement(qt,{value:t,showCursor:!a,onChange:a?()=>{}:m=>{if(n(m),m.startsWith("/")){let f=m.toLowerCase(),x=Ae.filter(w=>w.command.toLowerCase().startsWith(f));u(x),k(0)}else u([]),k(0)},onSubmit:a?()=>{}:m=>{if(m.trim().startsWith("/")&&c.length>0){let x=c[I]??c[0];Ie(x?.command||"");return}Ie(m)},placeholder:a?"Processing... (input disabled)":"Type and press Enter to send"}))),c.length>0&&T.createElement(P,{flexDirection:"column",marginTop:1,borderStyle:"round",borderColor:"gray"},c.map((m,f)=>T.createElement(P,{key:m.command,paddingX:1,paddingY:0,flexDirection:"row"},T.createElement(j,{color:f===I?"cyan":void 0},m.command.padEnd(15," ")),T.createElement(j,{dimColor:!0},m.description)))))}i(be,"App");import Yt from"semver";import{readFileSync as zt}from"node:fs";import{fileURLToPath as Qt}from"node:url";import{dirname as Zt,join as en}from"node:path";var tn=Qt(import.meta.url),nn=Zt(tn);function on(){try{let r=en(nn,"../package.json");return JSON.parse(zt(r,"utf-8")).version}catch{return"0.1.0"}}i(on,"getCurrentVersion");async function rn(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(rn,"fetchLatestVersion");async function He(r=3e3){try{let e=on(),t=await rn("galaxy-code",r);if(!t)return null;let n=Yt.gt(t,e);return{hasUpdate:n,currentVersion:e,latestVersion:t,updateAvailable:n}}catch(e){return console.debug("Error checking for update:",e),null}}i(He,"checkForUpdate");function We(r,e){return e.includes(r)}i(We,"shouldSkipVersion");import{execSync as sn,spawn as an}from"node:child_process";import{existsSync as ve,writeFileSync as cn,unlinkSync as ln}from"node:fs";import{tmpdir as Je}from"node:os";import{join as Ve}from"node:path";function pn(){let r=Ve(Je(),"galaxy-code-update.lock");return cn(r,Date.now().toString()),r}i(pn,"createLockFile");function Ee(r){try{ve(r)&&ln(r)}catch{}}i(Ee,"removeLockFile");function un(){let r=Ve(Je(),"galaxy-code-update.lock");if(!ve(r))return!1;try{let e=Number.parseInt(ve(r)?"":"0",10),t=Date.now(),n=300*1e3;return t-e>n?(Ee(r),!1):!0}catch{return!1}}i(un,"isUpdateInProgress");function dn(r){let e=r.message.toLowerCase();return e.includes("eacces")||e.includes("permission")||e.includes("eperm")}i(dn,"isPermissionError");async function Xe(r){if(un())return{success:!1,error:"\u0110ang c\xF3 process kh\xE1c \u0111ang c\u1EADp nh\u1EADt..."};let e=pn();try{let t=`npm install -g galaxy-code@${r}`;return sn(t,{stdio:"pipe",timeout:6e4}),Ee(e),{success:!0,needsRestart:!0}}catch(t){return Ee(e),t instanceof Error?dn(t)?{success:!1,error:`C\u1EA7n quy\u1EC1n admin \u0111\u1EC3 c\u1EADp nh\u1EADt. Vui l\xF2ng ch\u1EA1y:
|
|
560
|
+
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(Xe,"performUpdate");function Ke(){let r=process.argv.slice(2);an("galaxy-code",r,{detached:!0,stdio:"inherit"}).unref(),process.exit(0)}i(Ke,"restartCLI");function Ye(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(Ye,"showUpdateSuccess");function ze(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(ze,"showUpdateError");var re=fn(`
|
|
561
|
+
C\xE1ch s\u1EED d\u1EE5ng
|
|
562
|
+
$ galaxy [t\xF9y ch\u1ECDn]
|
|
563
|
+
|
|
564
|
+
T\xF9y ch\u1ECDn
|
|
565
|
+
--help Hi\u1EC3n th\u1ECB tr\u1EE3 gi\xFAp
|
|
566
|
+
--version Hi\u1EC3n th\u1ECB phi\xEAn b\u1EA3n
|
|
567
|
+
--git B\u1EADt git operations (m\u1EB7c \u0111\u1ECBnh: t\u1EEB config)
|
|
568
|
+
--test B\u1EADt test planning (m\u1EB7c \u0111\u1ECBnh: t\u1EEB config)
|
|
569
|
+
--config Hi\u1EC3n th\u1ECB c\u1EA5u h\xECnh hi\u1EC7n t\u1EA1i
|
|
570
|
+
--reset-config \u0110\u1EB7t l\u1EA1i c\u1EA5u h\xECnh v\u1EC1 m\u1EB7c \u0111\u1ECBnh
|
|
571
|
+
--dev B\u1EADt ch\u1EBF \u0111\u1ED9 ph\xE1t tri\u1EC3n v\u1EDBi DevTools
|
|
572
|
+
--no-auto-update T\u1EAFt auto-update khi kh\u1EDFi \u0111\u1ED9ng
|
|
573
|
+
|
|
574
|
+
V\xED d\u1EE5
|
|
575
|
+
$ galaxy
|
|
576
|
+
$ galaxy --test
|
|
577
|
+
$ galaxy --config
|
|
578
|
+
$ galaxy --reset-config
|
|
579
|
+
$ galaxy --dev # B\u1EADt DevTools
|
|
580
|
+
|
|
581
|
+
C\u1EA5u h\xECnh
|
|
582
|
+
V\u1ECB tr\xED file c\u1EA5u h\xECnh theo h\u1EC7 \u0111i\u1EC1u h\xE0nh:
|
|
583
|
+
- macOS/Linux: ~/.galaxy/config.json
|
|
584
|
+
- Windows: %LOCALAPPDATA%\\Galaxy\\config.json
|
|
585
|
+
|
|
586
|
+
Th\u1EE9 t\u1EF1 \u01B0u ti\xEAn: Tham s\u1ED1 CLI > config.json > m\u1EB7c \u0111\u1ECBnh
|
|
587
|
+
|
|
588
|
+
`,{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 hn(){let r=G.getConfig(),e=r.autoUpdate;if(!e.enabled||!e.checkOnStartup||re.flags.noAutoUpdate)return!1;try{let t=await He(e.timeout);if(!t||!t.hasUpdate||We(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 Xe(t.latestVersion);if(n.success){if(Ye(t.latestVersion),G.updateConfig({...r,autoUpdate:{...e,lastChecked:Date.now(),lastAttemptedVersion:t.latestVersion}}),n.needsRestart)return Ke(),!0}else n.error&&ze(n.error)}catch(t){console.debug("Auto-update failed:",t)}return!1}i(hn,"handleAutoUpdate");(async()=>{if(re.flags.config&&(G.displayConfig(),process.exit(0)),re.flags.resetConfig&&(G.resetConfig(),process.exit(0)),await hn())return;let e=G.getMergedConfig({git:re.flags.git,test:re.flags.test});gn(mn.createElement(be,{config:e}))})();
|