antigravity-ide 3.5.54 → 3.5.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cli/create.js +300 -251
  2. package/package.json +1 -1
package/cli/create.js CHANGED
@@ -11,214 +11,263 @@ const { getProjectConfig, getSkillsForCategories } = require('./prompts');
11
11
  const gradient = require('gradient-string');
12
12
 
13
13
  async function createProject(projectName, options) {
14
- try {
15
- // Determine target directory
16
- const isCurrentDir = !projectName || projectName === '.';
17
- const targetName = isCurrentDir ? path.basename(process.cwd()) : projectName;
18
-
19
- // Get configuration (pass targetName if specifically provided/determined as CWD target)
20
- // If isCurrentDir is true, we pass '.' to prompts to tell it to skip the name question
21
- const config = await getProjectConfig(options.skipPrompts, isCurrentDir ? targetName : projectName);
22
-
23
- // Resolve final project path
24
- const projectPath = isCurrentDir ? process.cwd() : path.resolve(process.cwd(), config.projectName);
25
- const finalProjectName = config.projectName;
26
-
27
- // Check if directory exists (only if NOT current dir)
28
- if (!isCurrentDir && fs.existsSync(projectPath)) {
29
- console.error(chalk.red(`\n❌ Directory "${finalProjectName}" already exists.\n`));
30
- process.exit(1);
14
+ try {
15
+ // Determine target directory
16
+ const isCurrentDir = !projectName || projectName === '.';
17
+ const targetName = isCurrentDir ? path.basename(process.cwd()) : projectName;
18
+
19
+ // Get configuration (pass targetName if specifically provided/determined as CWD target)
20
+ // If isCurrentDir is true, we pass '.' to prompts to tell it to skip the name question
21
+ const config = await getProjectConfig(options.skipPrompts, isCurrentDir ? targetName : projectName);
22
+
23
+ // Resolve final project path
24
+ const projectPath = isCurrentDir ? process.cwd() : path.resolve(process.cwd(), config.projectName);
25
+ const finalProjectName = config.projectName;
26
+
27
+ // Check if directory exists (only if NOT current dir)
28
+ if (!isCurrentDir && fs.existsSync(projectPath)) {
29
+ console.error(chalk.red(`\n❌ Directory "${finalProjectName}" already exists.\n`));
30
+ process.exit(1);
31
+ }
32
+
33
+ console.log('\n');
34
+ console.log(gradient.cristal('━'.repeat(60)));
35
+ console.log(chalk.bold(' 📦 Creating Google Antigravity Project'));
36
+ console.log(gradient.cristal('━'.repeat(60)));
37
+ console.log('');
38
+
39
+ // Create project directory
40
+ const spinner = ora('Creating project structure...').start();
41
+ fs.mkdirSync(projectPath, { recursive: true });
42
+
43
+ // Copy base structure
44
+ await copyBaseStructure(projectPath, config);
45
+ spinner.succeed('Project structure created');
46
+
47
+ // Copy selected skills
48
+ if (config.template !== 'minimal' && config.skillCategories?.length > 0) {
49
+ spinner.start('Installing selected skills...');
50
+ await copySkills(projectPath, config.skillCategories, config.engineMode);
51
+ spinner.succeed(`Installed ${config.skillCategories.length} skill categories`);
52
+ }
53
+
54
+ // Copy workflows
55
+ if (config.workflows?.length > 0) {
56
+ spinner.start('Setting up workflows...');
57
+ await copyWorkflows(projectPath, config.workflows);
58
+ spinner.succeed(`Configured ${config.workflows.length} workflows`);
59
+ }
60
+
61
+
62
+
63
+ // Generate configuration files
64
+ spinner.start('Generating configuration files...');
65
+ await generateConfigs(projectPath, config);
66
+ spinner.succeed('Configuration files created');
67
+
68
+ // Initialize git
69
+ spinner.start('Initializing git repository...');
70
+ try {
71
+ execSync('git init', { cwd: projectPath, stdio: 'ignore' });
72
+ spinner.succeed('Git repository initialized');
73
+ } catch (error) {
74
+ spinner.warn('Git initialization skipped (git not found)');
75
+ }
76
+
77
+ // Print success message
78
+ printSuccessMessage(finalProjectName, config);
79
+
80
+ } catch (error) {
81
+ console.error(chalk.red('\n❌ Error creating project:'), error.message);
82
+ process.exit(1);
31
83
  }
84
+ }
32
85
 
33
- console.log('\n');
34
- console.log(gradient.cristal('━'.repeat(60)));
35
- console.log(chalk.bold(' 📦 Creating Google Antigravity Project'));
36
- console.log(gradient.cristal('━'.repeat(60)));
37
- console.log('');
86
+ // Helper to handle core file conflicts (auto-create backup if exists)
87
+ function handleCoreFileConflict(filePath, fileName) {
88
+ if (!fs.existsSync(filePath)) {
89
+ return { shouldWrite: true, targetPath: filePath };
90
+ }
38
91
 
39
- // Create project directory
40
- const spinner = ora('Creating project structure...').start();
41
- fs.mkdirSync(projectPath, { recursive: true });
92
+ // File exists - create backup with .new extension
93
+ const dir = path.dirname(filePath);
94
+ const ext = path.extname(fileName);
95
+ const base = path.basename(fileName, ext);
96
+ const newPath = path.join(dir, `${base}.new${ext}`);
97
+ return { shouldWrite: true, targetPath: newPath, isBackup: true };
98
+ }
42
99
 
43
- // Copy base structure
44
- await copyBaseStructure(projectPath, config);
45
- spinner.succeed('Project structure created');
100
+ // Helper to determine file filter based on engine mode
101
+ function getEngineFilter(engineMode) {
102
+ return (src, dest) => {
103
+ // If mode is 'standard' (Node.js focus), exclude Python files
104
+ if (engineMode === 'standard') {
105
+ const lowerSrc = src.toLowerCase();
106
+ // Exclude Python source, compiled files, and package configs
107
+ if (lowerSrc.endsWith('.py') ||
108
+ lowerSrc.endsWith('.pyc') ||
109
+ lowerSrc.endsWith('requirements.txt') ||
110
+ lowerSrc.endsWith('pipfile') ||
111
+ lowerSrc.endsWith('pyproject.toml') ||
112
+ lowerSrc.includes('__pycache__') ||
113
+ lowerSrc.includes('venv/') ||
114
+ lowerSrc.includes('.venv/')) {
115
+ return false;
116
+ }
117
+ }
118
+ // 'advanced' mode (or others) includes everything
119
+ return true;
120
+ };
121
+ }
46
122
 
47
- // Copy selected skills
48
- if (config.template !== 'minimal' && config.skillCategories?.length > 0) {
49
- spinner.start('Installing selected skills...');
50
- await copySkills(projectPath, config.skillCategories, config.engineMode);
51
- spinner.succeed(`Installed ${config.skillCategories.length} skill categories`);
52
- }
123
+ async function copyBaseStructure(projectPath, config) {
124
+ const sourceAgentDir = path.join(__dirname, '..', '.agent');
125
+ const destAgentDir = path.join(projectPath, '.agent');
126
+ const filter = getEngineFilter(config.engineMode);
53
127
 
54
- // Copy workflows
55
- if (config.workflows?.length > 0) {
56
- spinner.start('Setting up workflows...');
57
- await copyWorkflows(projectPath, config.workflows);
58
- spinner.succeed(`Configured ${config.workflows.length} workflows`);
59
- }
128
+ // Create base .agent directory
129
+ fs.mkdirSync(destAgentDir, { recursive: true });
60
130
 
131
+ // Copy all subdirectories from .agent (except skills, which are handled separately)
132
+ if (fs.existsSync(sourceAgentDir)) {
133
+ const entries = fs.readdirSync(sourceAgentDir, { withFileTypes: true });
61
134
 
135
+ for (const entry of entries) {
136
+ if (entry.name === 'skills' || entry.name === 'GEMINI.md' || entry.name === 'START_HERE.md') {
137
+ continue; // Handle these separately
138
+ }
62
139
 
63
- // Generate configuration files
64
- spinner.start('Generating configuration files...');
65
- await generateConfigs(projectPath, config);
66
- spinner.succeed('Configuration files created');
140
+ const sourceEntryPath = path.join(sourceAgentDir, entry.name);
141
+ const destEntryPath = path.join(destAgentDir, entry.name);
67
142
 
68
- // Initialize git
69
- spinner.start('Initializing git repository...');
70
- try {
71
- execSync('git init', { cwd: projectPath, stdio: 'ignore' });
72
- spinner.succeed('Git repository initialized');
73
- } catch (error) {
74
- spinner.warn('Git initialization skipped (git not found)');
143
+ await fs.copy(sourceEntryPath, destEntryPath, { filter });
144
+ }
75
145
  }
76
146
 
77
- // Print success message
78
- printSuccessMessage(finalProjectName, config);
147
+ // Ensure 'skills' dir exists even if empty
148
+ fs.mkdirSync(path.join(destAgentDir, 'skills'), { recursive: true });
79
149
 
80
- } catch (error) {
81
- console.error(chalk.red('\n❌ Error creating project:'), error.message);
82
- process.exit(1);
83
- }
84
- }
150
+ // Copy GEMINI.md based on rules (core file - auto backup if exists)
151
+ const geminiPath = path.join(destAgentDir, 'GEMINI.md');
152
+ const geminiDecision = handleCoreFileConflict(geminiPath, 'GEMINI.md');
85
153
 
86
- // Helper to determine file filter based on engine mode
87
- function getEngineFilter(engineMode) {
88
- return (src, dest) => {
89
- // If mode is 'standard' (Node.js focus), exclude Python files
90
- if (engineMode === 'standard') {
91
- const lowerSrc = src.toLowerCase();
92
- // Exclude Python source, compiled files, and package configs
93
- if (lowerSrc.endsWith('.py') ||
94
- lowerSrc.endsWith('.pyc') ||
95
- lowerSrc.endsWith('requirements.txt') ||
96
- lowerSrc.endsWith('pipfile') ||
97
- lowerSrc.endsWith('pyproject.toml') ||
98
- lowerSrc.includes('__pycache__') ||
99
- lowerSrc.includes('venv/') ||
100
- lowerSrc.includes('.venv/')) {
101
- return false;
102
- }
103
- }
104
- // 'advanced' mode (or others) includes everything
105
- return true;
106
- };
107
- }
154
+ if (geminiDecision.shouldWrite) {
155
+ const geminiContent = generateGeminiMd(config.rules, config.language, config.industryDomain, config.agentName);
156
+ fs.writeFileSync(geminiDecision.targetPath, geminiContent);
108
157
 
109
- async function copyBaseStructure(projectPath, config) {
110
- const sourceAgentDir = path.join(__dirname, '..', '.agent');
111
- const destAgentDir = path.join(projectPath, '.agent');
112
- const filter = getEngineFilter(config.engineMode);
113
-
114
- // Create base .agent directory
115
- fs.mkdirSync(destAgentDir, { recursive: true });
116
-
117
- // Copy all subdirectories from .agent (except skills, which are handled separately)
118
- if (fs.existsSync(sourceAgentDir)) {
119
- const entries = fs.readdirSync(sourceAgentDir, { withFileTypes: true });
120
-
121
- for (const entry of entries) {
122
- if (entry.name === 'skills' || entry.name === 'GEMINI.md' || entry.name === 'START_HERE.md') {
123
- continue; // Handle these separately
124
- }
125
-
126
- const sourceEntryPath = path.join(sourceAgentDir, entry.name);
127
- const destEntryPath = path.join(destAgentDir, entry.name);
128
-
129
- await fs.copy(sourceEntryPath, destEntryPath, { filter });
158
+ if (geminiDecision.isBackup) {
159
+ console.log(chalk.yellow(` ℹ️ GEMINI.md exists, created ${path.basename(geminiDecision.targetPath)}`));
160
+ } else {
161
+ console.log(chalk.green(' Created GEMINI.md'));
162
+ }
130
163
  }
131
- }
132
-
133
- // Ensure 'skills' dir exists even if empty
134
- fs.mkdirSync(path.join(destAgentDir, 'skills'), { recursive: true });
135
-
136
- // Copy GEMINI.md based on rules
137
- const geminiContent = generateGeminiMd(config.rules, config.language, config.industryDomain, config.agentName);
138
- fs.writeFileSync(path.join(destAgentDir, 'GEMINI.md'), geminiContent);
139
-
140
- // Copy START_HERE.md (onboarding guide)
141
- const startHereSource = path.join(sourceAgentDir, 'START_HERE.md');
142
- if (fs.existsSync(startHereSource)) {
143
- fs.copyFileSync(startHereSource, path.join(destAgentDir, 'START_HERE.md'));
144
- }
145
-
146
- // Copy basic files (README, .gitignore)
147
- const files = ['README.md', '.gitignore'];
148
- const rootDir = path.join(__dirname, '..');
149
-
150
- files.forEach(file => {
151
- const source = path.join(rootDir, file);
152
- const dest = path.join(projectPath, file);
153
- if (fs.existsSync(source)) {
154
- fs.copyFileSync(source, dest);
164
+
165
+ // Copy START_HERE.md (core file - auto backup if exists)
166
+ const startHereSource = path.join(sourceAgentDir, 'START_HERE.md');
167
+ const startHereDest = path.join(destAgentDir, 'START_HERE.md');
168
+
169
+ if (fs.existsSync(startHereSource)) {
170
+ const startHereDecision = handleCoreFileConflict(startHereDest, 'START_HERE.md');
171
+
172
+ if (startHereDecision.shouldWrite) {
173
+ fs.copyFileSync(startHereSource, startHereDecision.targetPath);
174
+
175
+ if (startHereDecision.isBackup) {
176
+ console.log(chalk.yellow(` ℹ️ START_HERE.md exists, created ${path.basename(startHereDecision.targetPath)}`));
177
+ } else {
178
+ console.log(chalk.green(' ✓ Created START_HERE.md'));
179
+ }
180
+ }
155
181
  }
156
- });
182
+
183
+ // Copy basic files (README, .gitignore) - only if they don't exist
184
+ const files = ['README.md', '.gitignore'];
185
+ const rootDir = path.join(__dirname, '..');
186
+
187
+ files.forEach(file => {
188
+ const source = path.join(rootDir, file);
189
+ const dest = path.join(projectPath, file);
190
+ if (fs.existsSync(source) && !fs.existsSync(dest)) {
191
+ fs.copyFileSync(source, dest);
192
+ console.log(chalk.green(` ✓ Created ${file}`));
193
+ } else if (fs.existsSync(dest)) {
194
+ console.log(chalk.yellow(` ℹ️ Skipped ${file} (already exists)`));
195
+ }
196
+ });
157
197
  }
158
198
 
159
199
  async function copySkills(projectPath, categories, engineMode) {
160
- const skillsSourceDir = path.join(__dirname, '..', '.agent', 'skills');
161
- const skillsDestDir = path.join(projectPath, '.agent', 'skills');
162
- const filter = getEngineFilter(engineMode);
163
-
164
- // Check if source directory exists
165
- if (!fs.existsSync(skillsSourceDir)) {
166
- console.warn(chalk.yellow(`\n⚠️ Warning: Skills directory not found at ${skillsSourceDir}`));
167
- console.warn(' The .agent folder might be missing from the package.');
168
- return;
169
- }
170
-
171
- const selectedSkills = getSkillsForCategories(categories);
172
-
173
- for (const skill of selectedSkills) {
174
- const skillPath = path.join(skillsSourceDir, skill);
175
- if (fs.existsSync(skillPath)) {
176
- const destPath = path.join(skillsDestDir, skill);
177
- await fs.copy(skillPath, destPath, { filter });
178
- } else {
179
- // Optional: Warn about missing specific skills if needed
200
+ const skillsSourceDir = path.join(__dirname, '..', '.agent', 'skills');
201
+ const skillsDestDir = path.join(projectPath, '.agent', 'skills');
202
+ const filter = getEngineFilter(engineMode);
203
+
204
+ // Check if source directory exists
205
+ if (!fs.existsSync(skillsSourceDir)) {
206
+ console.warn(chalk.yellow(`\n⚠️ Warning: Skills directory not found at ${skillsSourceDir}`));
207
+ console.warn(' The .agent folder might be missing from the package.');
208
+ return;
209
+ }
210
+
211
+ const selectedSkills = getSkillsForCategories(categories);
212
+
213
+ for (const skill of selectedSkills) {
214
+ const skillPath = path.join(skillsSourceDir, skill);
215
+ if (fs.existsSync(skillPath)) {
216
+ const destPath = path.join(skillsDestDir, skill);
217
+ await fs.copy(skillPath, destPath, { filter });
218
+ } else {
219
+ // Optional: Warn about missing specific skills if needed
220
+ }
180
221
  }
181
- }
182
222
  }
183
223
 
184
224
  async function copyWorkflows(projectPath, workflows) {
185
- const workflowsSourceDir = path.join(__dirname, '..', '.agent', 'workflows');
186
- const workflowsDestDir = path.join(projectPath, '.agent', 'workflows');
187
-
188
- for (const workflow of workflows) {
189
- const workflowFile = `${workflow}.md`;
190
- const source = path.join(workflowsSourceDir, workflowFile);
191
- if (fs.existsSync(source)) {
192
- await fs.copy(source, path.join(workflowsDestDir, workflowFile));
225
+ const workflowsSourceDir = path.join(__dirname, '..', '.agent', 'workflows');
226
+ const workflowsDestDir = path.join(projectPath, '.agent', 'workflows');
227
+
228
+ for (const workflow of workflows) {
229
+ const workflowFile = `${workflow}.md`;
230
+ const source = path.join(workflowsSourceDir, workflowFile);
231
+ if (fs.existsSync(source)) {
232
+ await fs.copy(source, path.join(workflowsDestDir, workflowFile));
233
+ }
193
234
  }
194
- }
195
235
  }
196
236
 
197
237
 
198
238
 
199
239
  async function generateConfigs(projectPath, config) {
200
- // Generate package.json
201
- const packageJson = {
202
- name: config.projectName,
203
- version: '1.0.0',
204
- description: 'AI Agent project powered by Google Antigravity',
205
- private: true,
206
- scripts: {
207
- dev: 'echo "No dev server configured"',
208
- build: 'echo "No build script"'
209
- },
210
- keywords: ['ai', 'agent', 'google-antigravity'],
211
- author: '',
212
- license: 'MIT'
213
- };
214
-
215
- fs.writeFileSync(
216
- path.join(projectPath, 'package.json'),
217
- JSON.stringify(packageJson, null, 2)
218
- );
219
-
220
- // Generate .editorconfig
221
- const editorConfig = `root = true
240
+ // Generate package.json only if it doesn't exist
241
+ const packageJsonPath = path.join(projectPath, 'package.json');
242
+
243
+ if (!fs.existsSync(packageJsonPath)) {
244
+ const packageJson = {
245
+ name: config.projectName,
246
+ version: '1.0.0',
247
+ description: 'AI Agent project powered by Google Antigravity',
248
+ private: true,
249
+ scripts: {
250
+ dev: 'echo "No dev server configured"',
251
+ build: 'echo "No build script"'
252
+ },
253
+ keywords: ['ai', 'agent', 'google-antigravity'],
254
+ author: '',
255
+ license: 'MIT'
256
+ };
257
+
258
+ fs.writeFileSync(
259
+ packageJsonPath,
260
+ JSON.stringify(packageJson, null, 2)
261
+ );
262
+ console.log(chalk.green(' ✓ Created package.json'));
263
+ } else {
264
+ console.log(chalk.yellow(' ℹ️ Skipped package.json (already exists)'));
265
+ }
266
+
267
+ // Generate .editorconfig only if it doesn't exist
268
+ const editorconfigPath = path.join(projectPath, '.editorconfig');
269
+ if (!fs.existsSync(editorconfigPath)) {
270
+ const editorConfig = `root = true
222
271
 
223
272
  [*]
224
273
  charset = utf-8
@@ -243,39 +292,39 @@ bin/* text eol=lf
243
292
  }
244
293
 
245
294
  function generateGeminiMd(rules, language = 'en', industry = 'other', agentName = 'Antigravity') {
246
- const strictness = {
247
- strict: {
248
- autoRun: 'false',
249
- confirmLevel: 'Ask before every file modification and command execution'
250
- },
251
- balanced: {
252
- autoRun: 'true for safe read operations',
253
- confirmLevel: 'Ask before destructive operations'
254
- },
255
- flexible: {
256
- autoRun: 'true',
257
- confirmLevel: 'Minimal confirmation, high autonomy'
258
- }
259
- };
260
-
261
- const config = strictness[rules] || strictness.balanced;
262
- const isVi = language === 'vi';
263
-
264
- // Define Industry Focus strings
265
- const industryMap = {
266
- finance: isVi ? 'Tài chính & Fintech (An toàn, Chính xác)' : 'Finance & Fintech (Security, Precision)',
267
- education: isVi ? 'Giáo dục & EdTech (Trực quan, Giải thích)' : 'Education & EdTech (Intuitive, Explanatory)',
268
- fnb: isVi ? 'F&B & Nhà hàng (Tốc độ, Tiện lợi)' : 'F&B & Restaurant (Speed, Convenience)',
269
- personal: isVi ? 'Cá nhân & Portfolio (Sáng tạo, Cá nhân hóa)' : 'Personal & Portfolio (Creative, Personalized)',
270
- healthcare: isVi ? 'Y tế & Sức khỏe (Bảo mật, Tin cậy)' : 'Healthcare & HealthTech (Privacy, Reliability)',
271
- logistics: isVi ? 'Vận tải & Logistics (Hiệu quả, Real-time)' : 'Logistics & Supply Chain (Efficiency, Real-time)',
272
- other: isVi ? 'Phát triển chung' : 'General Development',
273
- other: isVi ? 'Phát triển chung' : 'General Development'
274
- };
275
-
276
- const industryFocus = industryMap[industry] || industryMap.other;
277
-
278
- const contentEn = `---
295
+ const strictness = {
296
+ strict: {
297
+ autoRun: 'false',
298
+ confirmLevel: 'Ask before every file modification and command execution'
299
+ },
300
+ balanced: {
301
+ autoRun: 'true for safe read operations',
302
+ confirmLevel: 'Ask before destructive operations'
303
+ },
304
+ flexible: {
305
+ autoRun: 'true',
306
+ confirmLevel: 'Minimal confirmation, high autonomy'
307
+ }
308
+ };
309
+
310
+ const config = strictness[rules] || strictness.balanced;
311
+ const isVi = language === 'vi';
312
+
313
+ // Define Industry Focus strings
314
+ const industryMap = {
315
+ finance: isVi ? 'Tài chính & Fintech (An toàn, Chính xác)' : 'Finance & Fintech (Security, Precision)',
316
+ education: isVi ? 'Giáo dục & EdTech (Trực quan, Giải thích)' : 'Education & EdTech (Intuitive, Explanatory)',
317
+ fnb: isVi ? 'F&B & Nhà hàng (Tốc độ, Tiện lợi)' : 'F&B & Restaurant (Speed, Convenience)',
318
+ personal: isVi ? 'Cá nhân & Portfolio (Sáng tạo, Cá nhân hóa)' : 'Personal & Portfolio (Creative, Personalized)',
319
+ healthcare: isVi ? 'Y tế & Sức khỏe (Bảo mật, Tin cậy)' : 'Healthcare & HealthTech (Privacy, Reliability)',
320
+ logistics: isVi ? 'Vận tải & Logistics (Hiệu quả, Real-time)' : 'Logistics & Supply Chain (Efficiency, Real-time)',
321
+ other: isVi ? 'Phát triển chung' : 'General Development',
322
+ other: isVi ? 'Phát triển chung' : 'General Development'
323
+ };
324
+
325
+ const industryFocus = industryMap[industry] || industryMap.other;
326
+
327
+ const contentEn = `---
279
328
  trigger: always_on
280
329
  ---
281
330
 
@@ -335,7 +384,7 @@ Add your project-specific instructions here.
335
384
  *Generated by Google Antigravity*
336
385
  `;
337
386
 
338
- const contentVi = `---
387
+ const contentVi = `---
339
388
  trigger: always_on
340
389
  ---
341
390
 
@@ -399,48 +448,48 @@ Thêm các hướng dẫn cụ thể cho dự án của bạn tại đây.
399
448
  *Được tạo bởi Google Antigravity*
400
449
  `;
401
450
 
402
- return isVi ? contentVi : contentEn;
451
+ return isVi ? contentVi : contentEn;
403
452
  }
404
453
 
405
454
  function printSuccessMessage(projectName, config) {
406
- console.log('\n');
407
- console.log(gradient.rainbow('━'.repeat(60)));
408
- console.log(gradient.morning.multiline(' ✓ SUCCESS! Project Ready'));
409
- console.log(gradient.rainbow('━'.repeat(60)));
410
-
411
- // Concise config display
412
- console.log('');
413
- console.log(chalk.bold('📋 Config'));
414
- console.log(chalk.gray(' Project: ') + gradient.cristal(projectName));
415
- console.log(chalk.gray(' Template: ') + chalk.cyan(config.template));
416
- console.log(chalk.gray(' Skills: ') + chalk.cyan(config.skillCategories?.join(', ') || 'none'));
417
-
418
- // AI Activation Instructions (NEW)
419
- console.log('');
420
- console.log(gradient.pastel('━'.repeat(60)));
421
- console.log(chalk.bold.cyan(config.language === 'vi' ? '🤖 Kích hoạt AI Agent' : '🤖 AI Agent Activation'));
422
- console.log('');
423
-
424
- if (config.language === 'vi') {
425
- console.log(chalk.gray(' 1. Mở dự án: ') + chalk.white(`cd ${projectName}`));
426
- console.log(chalk.gray(' 2. Mở khung chat: ') + chalk.white('(Claude, Gemini, v.v...)'));
427
- console.log(chalk.gray(' 3. Kích hoạt: ') + chalk.green('Đọc nội dung .agent/GEMINI.md'));
428
- } else {
429
- console.log(chalk.gray(' 1. Open project: ') + chalk.white(`cd ${projectName}`));
430
- console.log(chalk.gray(' 2. Open AI chat: ') + chalk.white('(Claude, Gemini, etc.)'));
431
- console.log(chalk.gray(' 3. Activate: ') + chalk.green('Read .agent/START_HERE.md'));
432
- }
433
-
434
- // Stats Display
435
- console.log('');
436
- console.log(gradient.pastel(' ✨ Installed: ') + chalk.white('20+ Master Skills') + chalk.gray(' • ') + chalk.white('15+ Agents') + chalk.gray(' • ') + chalk.white('13 Shared Modules'));
437
-
438
- console.log('');
439
- console.log(chalk.dim(config.language === 'vi' ? ' AI sẽ tự động tải các kỹ năng và quy tắc.' : ' The AI will load all skills and rules automatically.'));
440
- console.log(gradient.pastel('━'.repeat(60)));
441
- console.log('');
442
- console.log(chalk.gray(' Developed with 💡 by Dokhacgiakhoa'));
443
- console.log('');
455
+ console.log('\n');
456
+ console.log(gradient.rainbow('━'.repeat(60)));
457
+ console.log(gradient.morning.multiline(' ✓ SUCCESS! Project Ready'));
458
+ console.log(gradient.rainbow('━'.repeat(60)));
459
+
460
+ // Concise config display
461
+ console.log('');
462
+ console.log(chalk.bold('📋 Config'));
463
+ console.log(chalk.gray(' Project: ') + gradient.cristal(projectName));
464
+ console.log(chalk.gray(' Template: ') + chalk.cyan(config.template));
465
+ console.log(chalk.gray(' Skills: ') + chalk.cyan(config.skillCategories?.join(', ') || 'none'));
466
+
467
+ // AI Activation Instructions (NEW)
468
+ console.log('');
469
+ console.log(gradient.pastel('━'.repeat(60)));
470
+ console.log(chalk.bold.cyan(config.language === 'vi' ? '🤖 Kích hoạt AI Agent' : '🤖 AI Agent Activation'));
471
+ console.log('');
472
+
473
+ if (config.language === 'vi') {
474
+ console.log(chalk.gray(' 1. Mở dự án: ') + chalk.white(`cd ${projectName}`));
475
+ console.log(chalk.gray(' 2. Mở khung chat: ') + chalk.white('(Claude, Gemini, v.v...)'));
476
+ console.log(chalk.gray(' 3. Kích hoạt: ') + chalk.green('Đọc nội dung .agent/GEMINI.md'));
477
+ } else {
478
+ console.log(chalk.gray(' 1. Open project: ') + chalk.white(`cd ${projectName}`));
479
+ console.log(chalk.gray(' 2. Open AI chat: ') + chalk.white('(Claude, Gemini, etc.)'));
480
+ console.log(chalk.gray(' 3. Activate: ') + chalk.green('Read .agent/START_HERE.md'));
481
+ }
482
+
483
+ // Stats Display
484
+ console.log('');
485
+ console.log(gradient.pastel(' ✨ Installed: ') + chalk.white('20+ Master Skills') + chalk.gray(' • ') + chalk.white('15+ Agents') + chalk.gray(' • ') + chalk.white('13 Shared Modules'));
486
+
487
+ console.log('');
488
+ console.log(chalk.dim(config.language === 'vi' ? ' AI sẽ tự động tải các kỹ năng và quy tắc.' : ' The AI will load all skills and rules automatically.'));
489
+ console.log(gradient.pastel('━'.repeat(60)));
490
+ console.log('');
491
+ console.log(chalk.gray(' Developed with 💡 by Dokhacgiakhoa'));
492
+ console.log('');
444
493
  }
445
494
 
446
495
  module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antigravity-ide",
3
- "version": "3.5.54",
3
+ "version": "3.5.55",
4
4
  "description": "The Ultimate AI Agent Brain - Rules, Skills, and Workflows",
5
5
  "main": "cli/index.js",
6
6
  "bin": {