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