galaxy-code 0.1.2 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +1 -1
- package/dist/app.js +5 -5
- package/dist/cli.js +4 -4
- package/dist/connections/claude.d.ts +71 -0
- package/dist/connections/claude.js +303 -0
- package/dist/connections/gemini.d.ts +40 -0
- package/dist/connections/gemini.js +232 -0
- package/dist/connections/index.d.ts +11 -0
- package/dist/connections/index.js +11 -0
- package/dist/connections/ollama.d.ts +37 -0
- package/dist/connections/ollama.js +73 -0
- package/dist/connections/types.d.ts +22 -0
- package/dist/connections/types.js +7 -0
- package/dist/node_modules/@workspace/agent-core/providers/agent-selector.d.ts.map +1 -1
- package/dist/node_modules/@workspace/agent-core/providers/agent-selector.js +18 -18
- package/dist/node_modules/@workspace/agent-core/providers/agent-selector.js.map +1 -1
- package/dist/prompts/ba-it-analyzer.d.ts +1 -0
- package/dist/prompts/ba-it-analyzer.js +143 -0
- package/dist/prompts/index.d.ts +11 -0
- package/dist/prompts/index.js +11 -0
- package/dist/prompts/orchestrator.d.ts +8 -0
- package/dist/prompts/orchestrator.js +88 -0
- package/dist/prompts/planning-agent.d.ts +8 -0
- package/dist/prompts/planning-agent.js +195 -0
- package/dist/prompts/universal-agent.d.ts +7 -0
- package/dist/prompts/universal-agent.js +111 -0
- package/dist/providers/agent-selector.d.ts +29 -0
- package/dist/providers/agent-selector.js +84 -0
- package/dist/providers/claude-agent.d.ts +29 -0
- package/dist/providers/claude-agent.js +121 -0
- package/dist/providers/gemini-agent.d.ts +36 -0
- package/dist/providers/gemini-agent.js +168 -0
- package/dist/providers/index.d.ts +12 -0
- package/dist/providers/index.js +12 -0
- package/dist/providers/ollama-agent.d.ts +53 -0
- package/dist/providers/ollama-agent.js +276 -0
- package/dist/providers/orchestrator.d.ts +16 -0
- package/dist/providers/orchestrator.js +76 -0
- package/dist/tools/ba-it-analyzer.d.ts +66 -0
- package/dist/tools/ba-it-analyzer.js +90 -0
- package/dist/tools/code-generate-agent.d.ts +51 -0
- package/dist/tools/code-generate-agent.js +159 -0
- package/dist/tools/command-runner.d.ts +14 -0
- package/dist/tools/command-runner.js +120 -0
- package/dist/tools/document-parser.d.ts +11 -0
- package/dist/tools/document-parser.js +83 -0
- package/dist/tools/file-operations.d.ts +17 -0
- package/dist/tools/file-operations.js +127 -0
- package/dist/tools/galaxy-ui-integration.d.ts +94 -0
- package/dist/tools/galaxy-ui-integration.js +244 -0
- package/dist/tools/git-operations.d.ts +11 -0
- package/dist/tools/git-operations.js +114 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.js +10 -0
- package/dist/tools/planning-agent.d.ts +29 -0
- package/dist/tools/planning-agent.js +134 -0
- package/dist/tools/progress-reporter.d.ts +19 -0
- package/dist/tools/progress-reporter.js +52 -0
- package/dist/tools/registry.d.ts +21 -0
- package/dist/tools/registry.js +695 -0
- package/dist/tools/tool-event-emitter.d.ts +24 -0
- package/dist/tools/tool-event-emitter.js +25 -0
- package/dist/tools/types.d.ts +31 -0
- package/dist/tools/types.js +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/utils/config-manager.d.ts +102 -0
- package/dist/utils/config-manager.js +326 -0
- package/dist/utils/devtools.d.ts +21 -0
- package/dist/utils/devtools.js +61 -0
- package/dist/utils/message-formatters.d.ts +32 -0
- package/dist/utils/message-formatters.js +590 -0
- package/dist/utils/progress-tracker.d.ts +59 -0
- package/dist/utils/progress-tracker.js +213 -0
- package/package.json +3 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Event Emitter
|
|
3
|
+
* Central event system for tool execution tracking
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
export interface ToolExecutionEvent {
|
|
7
|
+
toolName: string;
|
|
8
|
+
content: string;
|
|
9
|
+
timestamp?: number;
|
|
10
|
+
status?: 'start' | 'success' | 'error';
|
|
11
|
+
error?: string;
|
|
12
|
+
toolInfo?: {
|
|
13
|
+
toolName: string;
|
|
14
|
+
args?: any;
|
|
15
|
+
result?: any;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
declare class ToolEventEmitter extends EventEmitter {
|
|
19
|
+
constructor();
|
|
20
|
+
emitToolExecution(event: ToolExecutionEvent): void;
|
|
21
|
+
onToolExecution(callback: (event: ToolExecutionEvent) => void): () => void;
|
|
22
|
+
}
|
|
23
|
+
export declare const toolEventEmitter: ToolEventEmitter;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Event Emitter
|
|
3
|
+
* Central event system for tool execution tracking
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
class ToolEventEmitter extends EventEmitter {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.setMaxListeners(100); // Increase for multiple listeners
|
|
10
|
+
}
|
|
11
|
+
emitToolExecution(event) {
|
|
12
|
+
const enrichedEvent = {
|
|
13
|
+
...event,
|
|
14
|
+
timestamp: Date.now(),
|
|
15
|
+
};
|
|
16
|
+
this.emit('tool-execution', enrichedEvent);
|
|
17
|
+
}
|
|
18
|
+
onToolExecution(callback) {
|
|
19
|
+
this.on('tool-execution', callback);
|
|
20
|
+
// Return unsubscribe function
|
|
21
|
+
return () => this.off('tool-execution', callback);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Singleton instance
|
|
25
|
+
export const toolEventEmitter = new ToolEventEmitter();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Bùi Trọng Hiếu
|
|
3
|
+
* @email kevinbui210191@gmail.com
|
|
4
|
+
* @create 2024-10-08
|
|
5
|
+
* @modify 2024-10-08
|
|
6
|
+
* @desc Shared typing for MCP-style tools.
|
|
7
|
+
*/
|
|
8
|
+
export type ToolInputSchema = {
|
|
9
|
+
readonly type: 'object';
|
|
10
|
+
readonly properties: Record<string, {
|
|
11
|
+
readonly type: 'string' | 'number' | 'boolean' | 'array' | 'object';
|
|
12
|
+
readonly description?: string;
|
|
13
|
+
readonly default?: string | boolean | number | Array<any> | object;
|
|
14
|
+
readonly items?: {
|
|
15
|
+
readonly type?: 'string' | 'number' | 'boolean' | 'object';
|
|
16
|
+
readonly properties?: Record<string, any>;
|
|
17
|
+
};
|
|
18
|
+
}>;
|
|
19
|
+
readonly required?: readonly string[];
|
|
20
|
+
};
|
|
21
|
+
export type ToolExecutionContext = {
|
|
22
|
+
readonly abortSignal?: AbortSignal;
|
|
23
|
+
};
|
|
24
|
+
export type Tool<Input, Output> = {
|
|
25
|
+
readonly name: string;
|
|
26
|
+
readonly description: string;
|
|
27
|
+
readonly inputSchema: ToolInputSchema;
|
|
28
|
+
readonly execute: (input: Input, context: ToolExecutionContext) => Promise<Output>;
|
|
29
|
+
};
|
|
30
|
+
export type InferToolInput<T extends Tool<unknown, unknown>> = T extends Tool<infer Input, unknown> ? Input : never;
|
|
31
|
+
export type InferToolOutput<T extends Tool<unknown, unknown>> = T extends Tool<unknown, infer Output> ? Output : never;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @modify 2025-10-21
|
|
6
6
|
* @desc Type definitions for Galaxy Code
|
|
7
7
|
*/
|
|
8
|
-
import
|
|
8
|
+
import { ToolExecutionInfo } from './connections/types.js';
|
|
9
9
|
export type MessageAuthor = 'user' | 'assistant' | 'system' | 'tool' | 'plan';
|
|
10
10
|
export interface ConversationMessage {
|
|
11
11
|
id: string;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export type AgentType = 'claude' | 'gemini' | 'ollama' | 'manual';
|
|
2
|
+
export interface AgentConfig {
|
|
3
|
+
model?: string;
|
|
4
|
+
type: AgentType;
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
host?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface AutoUpdateConfig {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
checkOnStartup: boolean;
|
|
11
|
+
silent: boolean;
|
|
12
|
+
maxAttempts: number;
|
|
13
|
+
timeout: number;
|
|
14
|
+
skipVersions: string[];
|
|
15
|
+
lastChecked: number | null;
|
|
16
|
+
lastAttemptedVersion: string | null;
|
|
17
|
+
}
|
|
18
|
+
export interface GalaxyConfig {
|
|
19
|
+
agent: AgentConfig[];
|
|
20
|
+
git: boolean;
|
|
21
|
+
test: boolean;
|
|
22
|
+
autoUpdate: AutoUpdateConfig;
|
|
23
|
+
}
|
|
24
|
+
export interface CLIFlags {
|
|
25
|
+
git?: boolean;
|
|
26
|
+
test?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface MergedConfig {
|
|
29
|
+
model: AgentType;
|
|
30
|
+
git: boolean;
|
|
31
|
+
test: boolean;
|
|
32
|
+
agent: AgentConfig[];
|
|
33
|
+
error?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare class ConfigManager {
|
|
36
|
+
private configPath;
|
|
37
|
+
private config;
|
|
38
|
+
constructor();
|
|
39
|
+
/**
|
|
40
|
+
* Get config directory path based on OS
|
|
41
|
+
*/
|
|
42
|
+
private getConfigDir;
|
|
43
|
+
/**
|
|
44
|
+
* Get full config file path
|
|
45
|
+
*/
|
|
46
|
+
private getConfigPath;
|
|
47
|
+
/**
|
|
48
|
+
* Get default configuration
|
|
49
|
+
*/
|
|
50
|
+
private getDefaultConfig;
|
|
51
|
+
/**
|
|
52
|
+
* Load configuration from file or create default
|
|
53
|
+
*/
|
|
54
|
+
private loadConfig;
|
|
55
|
+
/**
|
|
56
|
+
* Validate and merge config with defaults
|
|
57
|
+
*/
|
|
58
|
+
private validateConfig;
|
|
59
|
+
/**
|
|
60
|
+
* Create default config file
|
|
61
|
+
*/
|
|
62
|
+
private createDefaultConfig;
|
|
63
|
+
/**
|
|
64
|
+
* Save current config to file
|
|
65
|
+
*/
|
|
66
|
+
saveConfig(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Get merged config with CLI flags priority
|
|
69
|
+
* Priority: CLI flags > config.json > defaults
|
|
70
|
+
* Returns: { model: AgentType, git: boolean, test: boolean }
|
|
71
|
+
*/
|
|
72
|
+
getMergedConfig(cliFlags?: CLIFlags): MergedConfig;
|
|
73
|
+
/**
|
|
74
|
+
* Validate agent configuration
|
|
75
|
+
*/
|
|
76
|
+
private validateAgent;
|
|
77
|
+
/**
|
|
78
|
+
* Update config values
|
|
79
|
+
*/
|
|
80
|
+
updateConfig(updates: Partial<GalaxyConfig>): void;
|
|
81
|
+
/**
|
|
82
|
+
* Get current config
|
|
83
|
+
*/
|
|
84
|
+
getConfig(): GalaxyConfig;
|
|
85
|
+
/**
|
|
86
|
+
* Get config file path
|
|
87
|
+
*/
|
|
88
|
+
getConfigFilePath(): string;
|
|
89
|
+
/**
|
|
90
|
+
* Reset config to defaults
|
|
91
|
+
*/
|
|
92
|
+
resetConfig(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Open config folder in file explorer
|
|
95
|
+
*/
|
|
96
|
+
openConfigFolder(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Display current config and open config folder
|
|
99
|
+
*/
|
|
100
|
+
displayConfig(): void;
|
|
101
|
+
}
|
|
102
|
+
export declare const configManager: ConfigManager;
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Bùi Trọng Hiếu
|
|
3
|
+
* @email kevinbui210191@gmail.com
|
|
4
|
+
* @create 2024-10-13
|
|
5
|
+
* @desc Configuration manager for Galaxy CLI
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import os from 'node:os';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
export class ConfigManager {
|
|
12
|
+
constructor() {
|
|
13
|
+
Object.defineProperty(this, "configPath", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true,
|
|
17
|
+
value: void 0
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(this, "config", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: void 0
|
|
24
|
+
});
|
|
25
|
+
this.configPath = this.getConfigPath();
|
|
26
|
+
this.config = this.loadConfig();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get config directory path based on OS
|
|
30
|
+
*/
|
|
31
|
+
getConfigDir() {
|
|
32
|
+
const homeDir = os.homedir();
|
|
33
|
+
const platform = os.platform();
|
|
34
|
+
switch (platform) {
|
|
35
|
+
case 'darwin': // macOS
|
|
36
|
+
case 'linux':
|
|
37
|
+
return path.join(homeDir, '.galaxy');
|
|
38
|
+
case 'win32': // Windows
|
|
39
|
+
return path.join(homeDir, 'AppData', 'Local', 'Galaxy');
|
|
40
|
+
default:
|
|
41
|
+
return path.join(homeDir, '.galaxy');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get full config file path
|
|
46
|
+
*/
|
|
47
|
+
getConfigPath() {
|
|
48
|
+
return path.join(this.getConfigDir(), 'config.json');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get default configuration
|
|
52
|
+
*/
|
|
53
|
+
getDefaultConfig() {
|
|
54
|
+
return {
|
|
55
|
+
agent: [
|
|
56
|
+
{
|
|
57
|
+
type: 'manual',
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
git: true,
|
|
61
|
+
test: true,
|
|
62
|
+
autoUpdate: {
|
|
63
|
+
enabled: true,
|
|
64
|
+
checkOnStartup: true,
|
|
65
|
+
silent: false,
|
|
66
|
+
maxAttempts: 3,
|
|
67
|
+
timeout: 3000,
|
|
68
|
+
skipVersions: [],
|
|
69
|
+
lastChecked: null,
|
|
70
|
+
lastAttemptedVersion: null,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Load configuration from file or create default
|
|
76
|
+
*/
|
|
77
|
+
loadConfig() {
|
|
78
|
+
try {
|
|
79
|
+
// Check if config file exists
|
|
80
|
+
if (!fs.existsSync(this.configPath)) {
|
|
81
|
+
console.log('📝 Creating default config at:', this.configPath);
|
|
82
|
+
return this.createDefaultConfig();
|
|
83
|
+
}
|
|
84
|
+
// Read and parse config file
|
|
85
|
+
const configData = fs.readFileSync(this.configPath, 'utf-8');
|
|
86
|
+
const config = JSON.parse(configData);
|
|
87
|
+
// Validate config structure
|
|
88
|
+
return this.validateConfig(config);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.warn('⚠️ Failed to load config, using defaults:', error instanceof Error ? error.message : String(error));
|
|
92
|
+
return this.getDefaultConfig();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validate and merge config with defaults
|
|
97
|
+
*/
|
|
98
|
+
validateConfig(config) {
|
|
99
|
+
const defaults = this.getDefaultConfig();
|
|
100
|
+
// Ensure agent is always an array
|
|
101
|
+
let agent = defaults.agent;
|
|
102
|
+
if (config.agent && Array.isArray(config.agent)) {
|
|
103
|
+
agent = config.agent;
|
|
104
|
+
}
|
|
105
|
+
// Merge autoUpdate config with defaults
|
|
106
|
+
const autoUpdate = {
|
|
107
|
+
...defaults.autoUpdate,
|
|
108
|
+
...(config.autoUpdate || {}),
|
|
109
|
+
};
|
|
110
|
+
return {
|
|
111
|
+
agent: agent,
|
|
112
|
+
git: config.git ?? defaults.git,
|
|
113
|
+
test: config.test ?? defaults.test,
|
|
114
|
+
autoUpdate,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Create default config file
|
|
119
|
+
*/
|
|
120
|
+
createDefaultConfig() {
|
|
121
|
+
const config = this.getDefaultConfig();
|
|
122
|
+
try {
|
|
123
|
+
// Ensure config directory exists
|
|
124
|
+
const configDir = this.getConfigDir();
|
|
125
|
+
if (!fs.existsSync(configDir)) {
|
|
126
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
// Write default config
|
|
129
|
+
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
130
|
+
console.log('✅ Created default config file');
|
|
131
|
+
console.log('📁 Location:', this.configPath);
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log('You can customize settings by editing this file.');
|
|
134
|
+
console.log('');
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
console.error('❌ Failed to create config file:', error instanceof Error ? error.message : String(error));
|
|
138
|
+
}
|
|
139
|
+
return config;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Save current config to file
|
|
143
|
+
*/
|
|
144
|
+
saveConfig() {
|
|
145
|
+
try {
|
|
146
|
+
const configDir = this.getConfigDir();
|
|
147
|
+
if (!fs.existsSync(configDir)) {
|
|
148
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
149
|
+
}
|
|
150
|
+
fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2), 'utf-8');
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error('❌ Failed to save config:', error instanceof Error ? error.message : String(error));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get merged config with CLI flags priority
|
|
158
|
+
* Priority: CLI flags > config.json > defaults
|
|
159
|
+
* Returns: { model: AgentType, git: boolean, test: boolean }
|
|
160
|
+
*/
|
|
161
|
+
getMergedConfig(cliFlags = {}) {
|
|
162
|
+
// Check if agent is array and not empty
|
|
163
|
+
if (!this.config.agent || !Array.isArray(this.config.agent) || this.config.agent.length === 0) {
|
|
164
|
+
return {
|
|
165
|
+
model: 'manual',
|
|
166
|
+
git: cliFlags.git ?? this.config.git,
|
|
167
|
+
test: cliFlags.test ?? this.config.test,
|
|
168
|
+
agent: [],
|
|
169
|
+
error: 'Hiện tại chưa có agent nào được cấu hình. Vui lòng gõ "galaxy --config" để xem file config và thêm agent.',
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
// Find manual agent first, otherwise get first agent
|
|
173
|
+
let primaryAgent = this.config.agent.find(a => a.type === 'manual') ?? this.config.agent[0];
|
|
174
|
+
// Check if primaryAgent is defined
|
|
175
|
+
if (!primaryAgent) {
|
|
176
|
+
return {
|
|
177
|
+
model: 'manual',
|
|
178
|
+
git: cliFlags.git ?? this.config.git,
|
|
179
|
+
test: cliFlags.test ?? this.config.test,
|
|
180
|
+
agent: this.config.agent,
|
|
181
|
+
error: 'Không tìm thấy agent hợp lệ. Vui lòng kiểm tra lại file cấu hình.',
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
// Validate agent configuration
|
|
185
|
+
const validation = this.validateAgent(primaryAgent);
|
|
186
|
+
if (validation.error) {
|
|
187
|
+
return {
|
|
188
|
+
model: primaryAgent.type,
|
|
189
|
+
git: cliFlags.git ?? this.config.git,
|
|
190
|
+
test: cliFlags.test ?? this.config.test,
|
|
191
|
+
agent: this.config.agent,
|
|
192
|
+
error: validation.error,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
model: primaryAgent.type,
|
|
197
|
+
git: cliFlags.git ?? this.config.git,
|
|
198
|
+
test: cliFlags.test ?? this.config.test,
|
|
199
|
+
agent: this.config.agent,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Validate agent configuration
|
|
204
|
+
*/
|
|
205
|
+
validateAgent(agent) {
|
|
206
|
+
// Manual mode uses Ollama cloud, needs apiKey
|
|
207
|
+
if (agent.type === 'manual') {
|
|
208
|
+
if (!agent.apiKey) {
|
|
209
|
+
return {
|
|
210
|
+
valid: false,
|
|
211
|
+
error: `Mode Manual cần API Key. Vui lòng:\n1. Gõ /config để mở folder cấu hình\n2. Thêm "apiKey": "your-api-key" vào agent type "manual"\n3. Thoát CLI và vào lại để nhận API Key.`,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return { valid: true };
|
|
215
|
+
}
|
|
216
|
+
// Claude needs apiKey
|
|
217
|
+
if (agent.type === 'claude') {
|
|
218
|
+
if (!agent.apiKey) {
|
|
219
|
+
return {
|
|
220
|
+
valid: false,
|
|
221
|
+
error: `Hiện tại bạn chưa thêm apikey cho model ${agent.type}. Vui lòng:\n1. Gõ /config để mở folder cấu hình\n2. Thêm "apiKey": "your-api-key" vào agent type "claude"\n3. Thoát CLI và vào lại để nhận API Key.`,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Gemini needs apiKey
|
|
226
|
+
if (agent.type === 'gemini') {
|
|
227
|
+
if (!agent.apiKey) {
|
|
228
|
+
return {
|
|
229
|
+
valid: false,
|
|
230
|
+
error: `Hiện tại bạn chưa thêm apikey cho model ${agent.type}. Vui lòng:\n1. Gõ /config để mở folder cấu hình\n2. Thêm "apiKey": "your-api-key" vào agent type "gemini"\n3. Thoát CLI và vào lại để nhận API Key.`,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Ollama needs host and apiKey
|
|
235
|
+
if (agent.type === 'ollama') {
|
|
236
|
+
if (!agent.host) {
|
|
237
|
+
return {
|
|
238
|
+
valid: false,
|
|
239
|
+
error: `Hiện tại bạn chưa cài đặt host cho Ollama. Vui lòng gõ "galaxy --config" để xem file config và thêm host (ví dụ: "http://localhost:11434").`,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
// Check if using cloud host
|
|
243
|
+
if ((agent.host === 'https://ollama.com' || agent.host.includes('ollama.com')) &&
|
|
244
|
+
!agent.apiKey) {
|
|
245
|
+
return {
|
|
246
|
+
valid: false,
|
|
247
|
+
error: `Hiện tại bạn chưa thêm apikey cho model ollama. Vui lòng:\n1. Gõ /config để mở folder cấu hình\n2. Thêm "apiKey": "your-api-key" vào agent type "ollama"\n3. Thoát CLI và vào lại để nhận API Key.`,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { valid: true };
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Update config values
|
|
255
|
+
*/
|
|
256
|
+
updateConfig(updates) {
|
|
257
|
+
this.config = { ...this.config, ...updates };
|
|
258
|
+
this.saveConfig();
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Get current config
|
|
262
|
+
*/
|
|
263
|
+
getConfig() {
|
|
264
|
+
return { ...this.config };
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get config file path
|
|
268
|
+
*/
|
|
269
|
+
getConfigFilePath() {
|
|
270
|
+
return this.configPath;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Reset config to defaults
|
|
274
|
+
*/
|
|
275
|
+
resetConfig() {
|
|
276
|
+
this.config = this.getDefaultConfig();
|
|
277
|
+
this.saveConfig();
|
|
278
|
+
console.log('✅ Config reset to defaults');
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Open config folder in file explorer
|
|
282
|
+
*/
|
|
283
|
+
openConfigFolder() {
|
|
284
|
+
const configDir = path.dirname(this.configPath);
|
|
285
|
+
try {
|
|
286
|
+
const platform = os.platform();
|
|
287
|
+
if (platform === 'darwin') {
|
|
288
|
+
execSync(`open "${configDir}"`);
|
|
289
|
+
}
|
|
290
|
+
else if (platform === 'win32') {
|
|
291
|
+
execSync(`start "" "${configDir}"`);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
// Linux
|
|
295
|
+
execSync(`xdg-open "${configDir}"`);
|
|
296
|
+
}
|
|
297
|
+
console.log('✅ Opened config folder');
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
console.log('❌ Could not open folder automatically. Please open it manually.');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Display current config and open config folder
|
|
305
|
+
*/
|
|
306
|
+
displayConfig() {
|
|
307
|
+
console.log('');
|
|
308
|
+
console.log('📊 Current Galaxy Configuration:');
|
|
309
|
+
console.log('━'.repeat(50));
|
|
310
|
+
console.log('📁 Config file:', this.configPath);
|
|
311
|
+
console.log('');
|
|
312
|
+
console.log('Settings:');
|
|
313
|
+
console.log(' Agents:');
|
|
314
|
+
this.config.agent.forEach((agent, index) => {
|
|
315
|
+
console.log(` ${index + 1}. Type: ${agent.type}${agent.model ? ` | Model: ${agent.model}` : ''}`);
|
|
316
|
+
});
|
|
317
|
+
console.log(' Git:', this.config.git ? 'ON' : 'OFF');
|
|
318
|
+
console.log(' Test:', this.config.test ? 'ON' : 'OFF');
|
|
319
|
+
console.log('━'.repeat(50));
|
|
320
|
+
console.log('');
|
|
321
|
+
// Open config folder
|
|
322
|
+
this.openConfigFolder();
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// Singleton instance
|
|
326
|
+
export const configManager = new ConfigManager();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Bùi Trọng Hiếu
|
|
3
|
+
* @email kevinbui210191@gmail.com
|
|
4
|
+
* @create 2024-10-13
|
|
5
|
+
* @modify 2024-10-13
|
|
6
|
+
* @desc React DevTools integration for development
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Initialize React DevTools connection for debugging
|
|
10
|
+
* Only runs in development mode
|
|
11
|
+
*
|
|
12
|
+
* Note: react-devtools-core requires browser globals that don't exist in Node.js
|
|
13
|
+
* This may not work reliably in terminal environments
|
|
14
|
+
*/
|
|
15
|
+
export declare function initDevTools(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Display component for DevTools status
|
|
18
|
+
*/
|
|
19
|
+
export declare function DevToolsStatus({ connected }: {
|
|
20
|
+
connected: boolean;
|
|
21
|
+
}): "🔧 DevTools Đã Kết Nối" | "⚠️ DevTools Chưa Kết Nối" | null;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Bùi Trọng Hiếu
|
|
3
|
+
* @email kevinbui210191@gmail.com
|
|
4
|
+
* @create 2024-10-13
|
|
5
|
+
* @modify 2024-10-13
|
|
6
|
+
* @desc React DevTools integration for development
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Initialize React DevTools connection for debugging
|
|
10
|
+
* Only runs in development mode
|
|
11
|
+
*
|
|
12
|
+
* Note: react-devtools-core requires browser globals that don't exist in Node.js
|
|
13
|
+
* This may not work reliably in terminal environments
|
|
14
|
+
*/
|
|
15
|
+
export async function initDevTools() {
|
|
16
|
+
if (process.env['NODE_ENV'] !== 'development') {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
// Polyfill browser globals for react-devtools-core
|
|
21
|
+
if (typeof globalThis.self === 'undefined') {
|
|
22
|
+
// @ts-ignore - Adding browser global to Node.js
|
|
23
|
+
globalThis.self = globalThis;
|
|
24
|
+
}
|
|
25
|
+
if (typeof globalThis.window === 'undefined') {
|
|
26
|
+
// @ts-ignore - Adding browser global to Node.js
|
|
27
|
+
globalThis.window = globalThis;
|
|
28
|
+
}
|
|
29
|
+
// Dynamic import to avoid bundling in production
|
|
30
|
+
// @ts-expect-error - react-devtools-core doesn't have type definitions
|
|
31
|
+
const devTools = await import('react-devtools-core');
|
|
32
|
+
const { connectToDevTools } = devTools;
|
|
33
|
+
connectToDevTools({
|
|
34
|
+
host: 'localhost',
|
|
35
|
+
port: 8097,
|
|
36
|
+
useHttps: false,
|
|
37
|
+
retryDelay: 1000,
|
|
38
|
+
});
|
|
39
|
+
console.log('✅ React DevTools: Đã kết nối tới localhost:8097');
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
// Silently ignore DevTools errors - it's optional
|
|
43
|
+
// Users can still use the app without DevTools
|
|
44
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
45
|
+
if (message.includes('Cannot find module')) {
|
|
46
|
+
console.log('💡 DevTools không khả dụng (chưa cài đặt react-devtools-core)');
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.log('💡 DevTools không khả dụng (không hỗ trợ trong môi trường này)');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Display component for DevTools status
|
|
55
|
+
*/
|
|
56
|
+
export function DevToolsStatus({ connected }) {
|
|
57
|
+
if (process.env['NODE_ENV'] !== 'development') {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return connected ? '🔧 DevTools Đã Kết Nối' : '⚠️ DevTools Chưa Kết Nối';
|
|
61
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Bùi Trọng Hiếu
|
|
3
|
+
* @email kevinbui210191@gmail.com
|
|
4
|
+
* @create 2025-01-10
|
|
5
|
+
* @desc Message formatters for rich tool output display
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import type { ToolExecutionInfo } from '../connections/types.js';
|
|
9
|
+
export interface FormattedMessage {
|
|
10
|
+
type: 'plain' | 'todos' | 'diff' | 'code';
|
|
11
|
+
content: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parse tool result to detect format type
|
|
15
|
+
*/
|
|
16
|
+
export declare function detectMessageType(content: string, toolName?: string): FormattedMessage['type'];
|
|
17
|
+
/**
|
|
18
|
+
* Format todo list output from plan_task
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatTodos(content: string): React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Format git-style diff output for file operations
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatDiff(content: string, filePath?: string): React.ReactNode;
|
|
25
|
+
/**
|
|
26
|
+
* Format code blocks
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatCode(content: string): React.ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* Main formatter dispatcher
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatMessage(content: string | object | any[], toolName?: string, toolInfo?: ToolExecutionInfo): React.ReactNode;
|