@jaguilar87/gaia-ops 1.3.3 β 1.3.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/CHANGELOG.md +50 -0
- package/README.en.md +14 -12
- package/README.md +4 -1
- package/bin/gaia-init.js +205 -46
- package/package.json +9 -2
- package/hooks/__pycache__/post_tool_use.cpython-312.pyc +0 -0
- package/hooks/__pycache__/pre_kubectl_security.cpython-312.pyc +0 -0
- package/hooks/__pycache__/pre_tool_use.cpython-312.pyc +0 -0
- package/hooks/__pycache__/session_start.cpython-312.pyc +0 -0
- package/hooks/__pycache__/subagent_stop.cpython-312.pyc +0 -0
- package/tools/__pycache__/agent_router.cpython-312.pyc +0 -0
- package/tools/__pycache__/approval_gate.cpython-312.pyc +0 -0
- package/tools/__pycache__/clarify_engine.cpython-312.pyc +0 -0
- package/tools/__pycache__/clarify_patterns.cpython-312.pyc +0 -0
- package/tools/__pycache__/commit_validator.cpython-312.pyc +0 -0
- package/tools/__pycache__/context_provider.cpython-312.pyc +0 -0
- package/tools/__pycache__/context_section_reader.cpython-312.pyc +0 -0
- package/tools/__pycache__/routing_dashboard.cpython-312.pyc +0 -0
- package/tools/__pycache__/routing_feedback.cpython-312.pyc +0 -0
- package/tools/__pycache__/semantic_matcher.cpython-312.pyc +0 -0
- package/tools/__pycache__/task_manager.cpython-312.pyc +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.3.5] - 2025-11-10
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Smart Installer Flow:** Project context repo now asked FIRST, with auto-population of all config
|
|
14
|
+
- **Input Sanitization:** Handles "git clone <url>" pastes automatically (extracts just URL)
|
|
15
|
+
- **Auto-Configuration:** Parses project-context.json and pre-fills all wizard questions
|
|
16
|
+
- **Better Error Messages:** Clear troubleshooting tips for git clone failures (SSH keys, access, URL)
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- **Wizard Question Order:** Project context moved from last to first question
|
|
20
|
+
- **User Experience:** Reduced manual input when project context exists
|
|
21
|
+
- **Clone Strategy:** Validates project context early, then sets up in final location
|
|
22
|
+
- **Error Handling:** Installation continues even if project context clone fails
|
|
23
|
+
|
|
24
|
+
### Improved
|
|
25
|
+
- Eliminates typos and configuration errors by pre-filling from existing context
|
|
26
|
+
- Saves time for users with existing project-context repos
|
|
27
|
+
- Better guidance when git operations fail
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## [1.3.4] - 2025-11-10
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- **Installer:** Removed incorrect AGENTS.md symlink creation in project root during installation
|
|
35
|
+
- **Documentation:** AGENTS.md now only accessible via `.claude/config/AGENTS.md` as intended
|
|
36
|
+
- **Package Quality:** Excluded Python cache files (`__pycache__/`) from published package
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- **README.md:** Updated project structure documentation to reflect correct AGENTS.md location
|
|
40
|
+
- **README.en.md:** Updated project structure and corrected package references
|
|
41
|
+
- **Package Size:** Reduced from 911.7 kB (93 files) to 660.7 kB (77 files) - 27% reduction
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
- **Package Metadata:** Added `homepage` and `bugs` fields to package.json for better npm discovery
|
|
45
|
+
- **Badges:** Added npm version, license, and Node.js version badges to README files
|
|
46
|
+
- **CI/CD:** Created GitHub Actions workflow for automated npm publishing
|
|
47
|
+
- **.npmignore:** Added file to exclude development artifacts from package
|
|
48
|
+
- **Cleanup Script:** Added `npm run clean` to remove Python cache files automatically
|
|
49
|
+
- **Pre-publish Hook:** Added `prepublishOnly` script for automatic cleanup before publishing
|
|
50
|
+
|
|
51
|
+
### Package Quality Improvements
|
|
52
|
+
- Better npm package metadata for discoverability
|
|
53
|
+
- Professional badges in documentation
|
|
54
|
+
- Automated publishing workflow
|
|
55
|
+
- Cleaner package distribution (no cache files)
|
|
56
|
+
- Improved documentation consistency
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
10
60
|
## [2.1.0] - 2025-11-07
|
|
11
61
|
|
|
12
62
|
### Changed
|
package/README.en.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @jaguilar87/gaia-ops
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@jaguilar87/gaia-ops)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
3
7
|
**[πͺπΈ VersiΓ³n en espaΓ±ol](README.md)**
|
|
4
8
|
|
|
5
9
|
Multi-agent orchestration system for Claude Code - DevOps automation toolkit.
|
|
@@ -127,26 +131,24 @@ After installation:
|
|
|
127
131
|
|
|
128
132
|
```
|
|
129
133
|
your-project/
|
|
130
|
-
βββ .claude/ # Symlinked to node_modules/@
|
|
131
|
-
β βββ agents/ β node_modules/@
|
|
132
|
-
β βββ tools/ β node_modules/@
|
|
133
|
-
β βββ hooks/ β node_modules/@
|
|
134
|
-
β βββ commands/ β node_modules/@
|
|
135
|
-
β βββ
|
|
136
|
-
β βββ templates/ β node_modules/@
|
|
137
|
-
β βββ
|
|
138
|
-
β βββ CHANGELOG.md β node_modules/@aaxis/claude-agents/CHANGELOG.md
|
|
134
|
+
βββ .claude/ # Symlinked to node_modules/@jaguilar87/gaia-ops/
|
|
135
|
+
β βββ agents/ β node_modules/@jaguilar87/gaia-ops/agents/
|
|
136
|
+
β βββ tools/ β node_modules/@jaguilar87/gaia-ops/tools/
|
|
137
|
+
β βββ hooks/ β node_modules/@jaguilar87/gaia-ops/hooks/
|
|
138
|
+
β βββ commands/ β node_modules/@jaguilar87/gaia-ops/commands/
|
|
139
|
+
β βββ config/ β node_modules/@jaguilar87/gaia-ops/config/
|
|
140
|
+
β βββ templates/ β node_modules/@jaguilar87/gaia-ops/templates/
|
|
141
|
+
β βββ CHANGELOG.md β node_modules/@jaguilar87/gaia-ops/CHANGELOG.md
|
|
139
142
|
β βββ logs/ # Project-specific (NOT symlinked)
|
|
140
143
|
β βββ tests/ # Project-specific (NOT symlinked)
|
|
141
144
|
β βββ project-context.json # Project-specific (NOT symlinked)
|
|
142
145
|
βββ CLAUDE.md # Generated from template
|
|
143
|
-
βββ AGENTS.md β node_modules/@aaxis/claude-agents/AGENTS.md
|
|
144
146
|
βββ gitops/ # Your GitOps manifests
|
|
145
147
|
βββ terraform/ # Your Terraform code
|
|
146
148
|
βββ app-services/ # Your application code
|
|
147
149
|
βββ node_modules/
|
|
148
|
-
β βββ @
|
|
149
|
-
β βββ
|
|
150
|
+
β βββ @jaguilar87/
|
|
151
|
+
β βββ gaia-ops/ # This package
|
|
150
152
|
βββ package.json
|
|
151
153
|
```
|
|
152
154
|
|
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @jaguilar87/gaia-ops
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@jaguilar87/gaia-ops)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
3
7
|
**[πΊπΈ English version](README.en.md)**
|
|
4
8
|
|
|
5
9
|
Sistema de orquestaciΓ³n multi-agente para Claude Code - Toolkit de automatizaciΓ³n DevOps.
|
|
@@ -139,7 +143,6 @@ tu-proyecto/
|
|
|
139
143
|
β βββ tests/ # EspecΓfico del proyecto (NO symlink)
|
|
140
144
|
β βββ project-context.json # EspecΓfico del proyecto (NO symlink)
|
|
141
145
|
βββ CLAUDE.md # Generado desde template
|
|
142
|
-
βββ AGENTS.md β node_modules/@jaguilar87/gaia-ops/AGENTS.md
|
|
143
146
|
βββ gitops/ # Tus manifiestos GitOps
|
|
144
147
|
βββ terraform/ # Tu cΓ³digo Terraform
|
|
145
148
|
βββ app-services/ # Tu cΓ³digo de aplicaciΓ³n
|
package/bin/gaia-init.js
CHANGED
|
@@ -254,6 +254,81 @@ function validateConfiguration(config, nonInteractive) {
|
|
|
254
254
|
// Interactive prompts
|
|
255
255
|
// ============================================================================
|
|
256
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Sanitize git repo URL input
|
|
259
|
+
* Handles cases where user pastes "git clone <url>" instead of just "<url>"
|
|
260
|
+
*/
|
|
261
|
+
function sanitizeGitUrl(input) {
|
|
262
|
+
if (!input || typeof input !== 'string') return '';
|
|
263
|
+
|
|
264
|
+
// Trim whitespace
|
|
265
|
+
let sanitized = input.trim();
|
|
266
|
+
|
|
267
|
+
// Remove "git clone" prefix if present
|
|
268
|
+
if (sanitized.toLowerCase().startsWith('git clone ')) {
|
|
269
|
+
sanitized = sanitized.substring('git clone '.length).trim();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Remove quotes if present
|
|
273
|
+
sanitized = sanitized.replace(/^["']|["']$/g, '');
|
|
274
|
+
|
|
275
|
+
return sanitized;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Try to clone project context repo early and parse config
|
|
280
|
+
* Returns parsed config or null if clone fails
|
|
281
|
+
*/
|
|
282
|
+
async function tryCloneProjectContext(repoUrl) {
|
|
283
|
+
if (!repoUrl || repoUrl.trim() === '') {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const sanitizedUrl = sanitizeGitUrl(repoUrl);
|
|
288
|
+
|
|
289
|
+
const spinner = ora('Cloning project context repository...').start();
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
const tempDir = join(CWD, '.claude-temp-context');
|
|
293
|
+
|
|
294
|
+
// Remove temp dir if exists
|
|
295
|
+
if (existsSync(tempDir)) {
|
|
296
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Clone to temp directory
|
|
300
|
+
await execAsync(`git clone ${sanitizedUrl} ${tempDir}`, { timeout: 30000 });
|
|
301
|
+
|
|
302
|
+
// Try to read project-context.json
|
|
303
|
+
const contextPath = join(tempDir, 'project-context.json');
|
|
304
|
+
|
|
305
|
+
if (existsSync(contextPath)) {
|
|
306
|
+
const contextData = JSON.parse(await fs.readFile(contextPath, 'utf-8'));
|
|
307
|
+
|
|
308
|
+
// Clean up temp dir
|
|
309
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
310
|
+
|
|
311
|
+
spinner.succeed('Project context loaded successfully');
|
|
312
|
+
console.log(chalk.green(' β Auto-populated configuration from project context\n'));
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
contextData,
|
|
316
|
+
repoUrl: sanitizedUrl
|
|
317
|
+
};
|
|
318
|
+
} else {
|
|
319
|
+
// No project-context.json found
|
|
320
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
321
|
+
spinner.warn('Repository cloned but no project-context.json found');
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
} catch (error) {
|
|
325
|
+
spinner.fail('Failed to clone project context repository');
|
|
326
|
+
console.log(chalk.yellow(`\nβ οΈ Error: ${error.message}`));
|
|
327
|
+
console.log(chalk.gray(' Continuing with manual configuration...\n'));
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
257
332
|
/**
|
|
258
333
|
* Present interactive wizard to user
|
|
259
334
|
*/
|
|
@@ -276,32 +351,79 @@ async function runInteractiveWizard(detected) {
|
|
|
276
351
|
|
|
277
352
|
console.log(chalk.gray('This wizard will set up the Gaia-Ops agent system for your project.\n'));
|
|
278
353
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
console.log(chalk.
|
|
283
|
-
console.log(chalk.gray('
|
|
354
|
+
// =========================================================================
|
|
355
|
+
// STEP 1: Ask for project context repo first (if available)
|
|
356
|
+
// =========================================================================
|
|
357
|
+
console.log(chalk.yellow('π Project Context (Optional but Recommended)'));
|
|
358
|
+
console.log(chalk.gray('If you have a project context repo, we can auto-populate your configuration.\n'));
|
|
359
|
+
|
|
360
|
+
const contextQuestion = await prompts({
|
|
361
|
+
type: 'text',
|
|
362
|
+
name: 'projectContextRepo',
|
|
363
|
+
message: 'π¦ Project context Git repo (e.g., git@bitbucket.org:org/context.git):',
|
|
364
|
+
initial: ''
|
|
365
|
+
}, {
|
|
366
|
+
onCancel: () => {
|
|
367
|
+
console.log(chalk.yellow('\nβ οΈ Installation cancelled by user\n'));
|
|
368
|
+
process.exit(0);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// Try to clone and parse project context
|
|
373
|
+
let projectContext = null;
|
|
374
|
+
if (contextQuestion.projectContextRepo) {
|
|
375
|
+
projectContext = await tryCloneProjectContext(contextQuestion.projectContextRepo);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Extract defaults from project context if available
|
|
379
|
+
const defaults = projectContext ? {
|
|
380
|
+
gitops: projectContext.contextData.paths?.gitops || detected.gitops || './gitops',
|
|
381
|
+
terraform: projectContext.contextData.paths?.terraform || detected.terraform || './terraform',
|
|
382
|
+
appServices: projectContext.contextData.paths?.app_services || detected.appServices || './app-services',
|
|
383
|
+
cloudProvider: projectContext.contextData.sections?.project_details?.cloud_provider || 'gcp',
|
|
384
|
+
gcpProjectId: projectContext.contextData.sections?.project_details?.project_id || projectContext.contextData.metadata?.project_id || '',
|
|
385
|
+
awsAccountId: projectContext.contextData.sections?.project_details?.aws_account || projectContext.contextData.metadata?.aws_account || '',
|
|
386
|
+
region: projectContext.contextData.sections?.project_details?.region || projectContext.contextData.metadata?.primary_region || 'us-central1',
|
|
387
|
+
clusterName: projectContext.contextData.sections?.project_details?.cluster_name || '',
|
|
388
|
+
repoUrl: projectContext?.repoUrl || contextQuestion.projectContextRepo
|
|
389
|
+
} : {
|
|
390
|
+
gitops: detected.gitops || './gitops',
|
|
391
|
+
terraform: detected.terraform || './terraform',
|
|
392
|
+
appServices: detected.appServices || './app-services',
|
|
393
|
+
cloudProvider: 'gcp',
|
|
394
|
+
gcpProjectId: '',
|
|
395
|
+
awsAccountId: '',
|
|
396
|
+
region: 'us-central1',
|
|
397
|
+
clusterName: '',
|
|
398
|
+
repoUrl: contextQuestion.projectContextRepo
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// =========================================================================
|
|
402
|
+
// STEP 2: Ask remaining questions (with smart defaults from context)
|
|
403
|
+
// =========================================================================
|
|
404
|
+
console.log(chalk.yellow('\nπ Directory Configuration'));
|
|
405
|
+
console.log(chalk.gray('Verify or adjust the following paths:\n'));
|
|
284
406
|
|
|
285
407
|
const questions = [
|
|
286
408
|
{
|
|
287
409
|
type: 'text',
|
|
288
410
|
name: 'gitops',
|
|
289
411
|
message: 'π¦ GitOps directory:',
|
|
290
|
-
initial:
|
|
412
|
+
initial: defaults.gitops,
|
|
291
413
|
validate: value => value.trim().length > 0
|
|
292
414
|
},
|
|
293
415
|
{
|
|
294
416
|
type: 'text',
|
|
295
417
|
name: 'terraform',
|
|
296
418
|
message: 'π§ Terraform directory:',
|
|
297
|
-
initial:
|
|
419
|
+
initial: defaults.terraform,
|
|
298
420
|
validate: value => value.trim().length > 0
|
|
299
421
|
},
|
|
300
422
|
{
|
|
301
423
|
type: 'text',
|
|
302
424
|
name: 'appServices',
|
|
303
425
|
message: 'π App Services directory:',
|
|
304
|
-
initial:
|
|
426
|
+
initial: defaults.appServices,
|
|
305
427
|
validate: value => value.trim().length > 0
|
|
306
428
|
},
|
|
307
429
|
{
|
|
@@ -313,31 +435,34 @@ async function runInteractiveWizard(detected) {
|
|
|
313
435
|
{ title: 'AWS (Amazon Web Services)', value: 'aws' },
|
|
314
436
|
{ title: 'Multi-cloud (AWS + GCP)', value: 'multi-cloud' }
|
|
315
437
|
],
|
|
316
|
-
initial: 0
|
|
438
|
+
initial: defaults.cloudProvider === 'gcp' ? 0 : defaults.cloudProvider === 'aws' ? 1 : 2
|
|
317
439
|
},
|
|
318
440
|
{
|
|
319
441
|
type: (prev, values) => ['gcp', 'multi-cloud'].includes(values.cloudProvider) ? 'text' : null,
|
|
320
442
|
name: 'gcpProjectId',
|
|
321
443
|
message: 'π GCP Project ID (e.g., aaxis-rnd-non-prod):',
|
|
444
|
+
initial: defaults.gcpProjectId,
|
|
322
445
|
validate: value => value.trim().length > 0
|
|
323
446
|
},
|
|
324
447
|
{
|
|
325
448
|
type: (prev, values) => ['aws', 'multi-cloud'].includes(values.cloudProvider) ? 'text' : null,
|
|
326
449
|
name: 'awsAccountId',
|
|
327
450
|
message: 'π AWS Account ID (e.g., 929914624686):',
|
|
451
|
+
initial: defaults.awsAccountId,
|
|
328
452
|
validate: value => value.trim().length > 0
|
|
329
453
|
},
|
|
330
454
|
{
|
|
331
455
|
type: 'text',
|
|
332
456
|
name: 'region',
|
|
333
457
|
message: 'π Primary Region (e.g., us-central1 for GCP, us-east-1 for AWS):',
|
|
334
|
-
initial:
|
|
458
|
+
initial: defaults.region,
|
|
335
459
|
validate: value => value.trim().length > 0
|
|
336
460
|
},
|
|
337
461
|
{
|
|
338
462
|
type: 'text',
|
|
339
463
|
name: 'clusterName',
|
|
340
464
|
message: 'βΈοΈ Cluster Name (e.g., rnd-gke-nonprod or digital-eks-prod):',
|
|
465
|
+
initial: defaults.clusterName,
|
|
341
466
|
validate: value => value.trim().length > 0
|
|
342
467
|
},
|
|
343
468
|
{
|
|
@@ -345,12 +470,6 @@ async function runInteractiveWizard(detected) {
|
|
|
345
470
|
name: 'installClaudeCode',
|
|
346
471
|
message: 'π₯ Install Claude Code if not present?',
|
|
347
472
|
initial: true
|
|
348
|
-
},
|
|
349
|
-
{
|
|
350
|
-
type: 'text',
|
|
351
|
-
name: 'projectContextRepo',
|
|
352
|
-
message: 'π Project context Git repo (optional, e.g., git@bitbucket.org:org/context.git):',
|
|
353
|
-
initial: ''
|
|
354
473
|
}
|
|
355
474
|
];
|
|
356
475
|
|
|
@@ -367,6 +486,10 @@ async function runInteractiveWizard(detected) {
|
|
|
367
486
|
process.exit(0);
|
|
368
487
|
}
|
|
369
488
|
|
|
489
|
+
// Add project context info to responses
|
|
490
|
+
responses.projectContextRepo = defaults.repoUrl;
|
|
491
|
+
responses.projectContextAlreadyCloned = !!projectContext;
|
|
492
|
+
|
|
370
493
|
return responses;
|
|
371
494
|
}
|
|
372
495
|
|
|
@@ -496,27 +619,13 @@ async function generateClaudeMd(config) {
|
|
|
496
619
|
|
|
497
620
|
/**
|
|
498
621
|
* Generate AGENTS.md symlink
|
|
622
|
+
* NOTE: AGENTS.md is already available at .claude/config/AGENTS.md via the config/ symlink
|
|
623
|
+
* No need to create a separate symlink in the project root
|
|
499
624
|
*/
|
|
500
625
|
async function generateAgentsMd() {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const agentsMdLink = join(CWD, 'AGENTS.md');
|
|
505
|
-
const packagePath = join(CWD, 'node_modules', '@jaguilar87', 'gaia-ops', 'config', 'AGENTS.md');
|
|
506
|
-
const relativePath = relative(CWD, packagePath);
|
|
507
|
-
|
|
508
|
-
// Remove existing if present
|
|
509
|
-
if (existsSync(agentsMdLink)) {
|
|
510
|
-
await fs.unlink(agentsMdLink);
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
await fs.symlink(relativePath, agentsMdLink);
|
|
514
|
-
|
|
515
|
-
spinner.succeed('AGENTS.md symlink created');
|
|
516
|
-
} catch (error) {
|
|
517
|
-
spinner.fail('Failed to create AGENTS.md symlink');
|
|
518
|
-
throw error;
|
|
519
|
-
}
|
|
626
|
+
// AGENTS.md is accessible via .claude/config/AGENTS.md (symlinked directory)
|
|
627
|
+
// No action needed - keeping function for backward compatibility
|
|
628
|
+
return Promise.resolve();
|
|
520
629
|
}
|
|
521
630
|
|
|
522
631
|
/**
|
|
@@ -712,13 +821,58 @@ async function installClaudeAgentsPackage() {
|
|
|
712
821
|
|
|
713
822
|
/**
|
|
714
823
|
* Clone project context repository (optional)
|
|
824
|
+
* If already cloned during wizard, skip clone and just set it up in final location
|
|
715
825
|
*/
|
|
716
|
-
async function cloneProjectContextRepo(repoUrl) {
|
|
826
|
+
async function cloneProjectContextRepo(repoUrl, alreadyCloned = false) {
|
|
717
827
|
if (!repoUrl || repoUrl.trim() === '') {
|
|
718
828
|
console.log(chalk.gray('\nβ Skipping project context repo clone (not provided)\n'));
|
|
719
829
|
return;
|
|
720
830
|
}
|
|
721
831
|
|
|
832
|
+
const sanitizedUrl = sanitizeGitUrl(repoUrl);
|
|
833
|
+
|
|
834
|
+
if (alreadyCloned) {
|
|
835
|
+
// Context was already cloned during wizard, just re-clone to final location
|
|
836
|
+
const spinner = ora('Setting up project context...').start();
|
|
837
|
+
|
|
838
|
+
try {
|
|
839
|
+
const projectContextDir = join(CWD, '.claude', 'project-context');
|
|
840
|
+
|
|
841
|
+
// Remove the generated project-context.json as it will be replaced by the cloned repo
|
|
842
|
+
const generatedFile = join(projectContextDir, 'project-context.json');
|
|
843
|
+
if (existsSync(generatedFile)) {
|
|
844
|
+
await fs.unlink(generatedFile);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// Clone fresh to final location (we already validated it works)
|
|
848
|
+
const tempDir = `${projectContextDir}-temp`;
|
|
849
|
+
await execAsync(`git clone ${sanitizedUrl} ${tempDir}`, { timeout: 30000 });
|
|
850
|
+
|
|
851
|
+
// Move contents from temp to project-context
|
|
852
|
+
const files = await fs.readdir(tempDir);
|
|
853
|
+
for (const file of files) {
|
|
854
|
+
const src = join(tempDir, file);
|
|
855
|
+
const dest = join(projectContextDir, file);
|
|
856
|
+
await fs.rename(src, dest);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// Remove temp directory
|
|
860
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
861
|
+
|
|
862
|
+
spinner.succeed('Project context repository configured');
|
|
863
|
+
console.log(chalk.green(` β Location: .claude/project-context/\n`));
|
|
864
|
+
} catch (error) {
|
|
865
|
+
spinner.fail('Failed to setup project context repository');
|
|
866
|
+
console.log(chalk.yellow(`\nβ οΈ You can clone it manually with:`));
|
|
867
|
+
console.log(chalk.gray(` cd .claude`));
|
|
868
|
+
console.log(chalk.gray(` rm -rf project-context`));
|
|
869
|
+
console.log(chalk.gray(` git clone ${sanitizedUrl} project-context\n`));
|
|
870
|
+
// Don't throw - allow installation to continue
|
|
871
|
+
}
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// Not cloned yet during wizard, try to clone now
|
|
722
876
|
const spinner = ora('Cloning project context repository...').start();
|
|
723
877
|
|
|
724
878
|
try {
|
|
@@ -730,11 +884,11 @@ async function cloneProjectContextRepo(repoUrl) {
|
|
|
730
884
|
await fs.unlink(generatedFile);
|
|
731
885
|
}
|
|
732
886
|
|
|
733
|
-
// Clone repo
|
|
734
|
-
|
|
887
|
+
// Clone repo
|
|
888
|
+
const tempDir = `${projectContextDir}-temp`;
|
|
889
|
+
await execAsync(`git clone ${sanitizedUrl} ${tempDir}`, { timeout: 30000 });
|
|
735
890
|
|
|
736
891
|
// Move contents from temp to project-context
|
|
737
|
-
const tempDir = `${projectContextDir}-temp`;
|
|
738
892
|
const files = await fs.readdir(tempDir);
|
|
739
893
|
for (const file of files) {
|
|
740
894
|
const src = join(tempDir, file);
|
|
@@ -743,17 +897,22 @@ async function cloneProjectContextRepo(repoUrl) {
|
|
|
743
897
|
}
|
|
744
898
|
|
|
745
899
|
// Remove temp directory
|
|
746
|
-
await fs.
|
|
900
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
747
901
|
|
|
748
902
|
spinner.succeed('Project context repository cloned');
|
|
749
|
-
console.log(chalk.green(` β Cloned from: ${
|
|
903
|
+
console.log(chalk.green(` β Cloned from: ${sanitizedUrl}`));
|
|
750
904
|
console.log(chalk.gray(` β Location: .claude/project-context/\n`));
|
|
751
905
|
} catch (error) {
|
|
752
906
|
spinner.fail('Failed to clone project context repository');
|
|
753
|
-
console.log(chalk.yellow(`\nβ οΈ
|
|
754
|
-
console.log(chalk.gray(
|
|
755
|
-
console.log(chalk.gray(
|
|
756
|
-
console.log(chalk.gray(
|
|
907
|
+
console.log(chalk.yellow(`\nβ οΈ Error: ${error.message}`));
|
|
908
|
+
console.log(chalk.gray('\n Common issues:'));
|
|
909
|
+
console.log(chalk.gray(' β’ Check SSH keys are configured: ssh -T git@bitbucket.org'));
|
|
910
|
+
console.log(chalk.gray(' β’ Verify repository URL is correct'));
|
|
911
|
+
console.log(chalk.gray(' β’ Ensure you have access to the repository\n'));
|
|
912
|
+
console.log(chalk.yellow(` You can clone it manually later with:`));
|
|
913
|
+
console.log(chalk.gray(` cd .claude`));
|
|
914
|
+
console.log(chalk.gray(` rm -rf project-context`));
|
|
915
|
+
console.log(chalk.gray(` git clone ${sanitizedUrl} project-context\n`));
|
|
757
916
|
// Don't throw - allow installation to continue
|
|
758
917
|
}
|
|
759
918
|
}
|
|
@@ -828,7 +987,7 @@ async function main() {
|
|
|
828
987
|
|
|
829
988
|
// Step 10: Clone project context repository (optional)
|
|
830
989
|
if (config.projectContextRepo) {
|
|
831
|
-
await cloneProjectContextRepo(config.projectContextRepo);
|
|
990
|
+
await cloneProjectContextRepo(config.projectContextRepo, config.projectContextAlreadyCloned);
|
|
832
991
|
}
|
|
833
992
|
|
|
834
993
|
// Success message
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jaguilar87/gaia-ops",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"description": "Multi-agent orchestration system for Claude Code - DevOps automation toolkit",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
"type": "git",
|
|
26
26
|
"url": "git+https://github.com/metraton/gaia-ops.git"
|
|
27
27
|
},
|
|
28
|
+
"homepage": "https://github.com/metraton/gaia-ops#readme",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/metraton/gaia-ops/issues",
|
|
31
|
+
"email": "jaguilar1897@gmail.com"
|
|
32
|
+
},
|
|
28
33
|
"files": [
|
|
29
34
|
"bin/",
|
|
30
35
|
"agents/",
|
|
@@ -42,7 +47,9 @@
|
|
|
42
47
|
"scripts": {
|
|
43
48
|
"test": "pytest tests/ -v",
|
|
44
49
|
"validate": "python3 tools/commit_validator.py",
|
|
45
|
-
"lint": "eslint ."
|
|
50
|
+
"lint": "eslint .",
|
|
51
|
+
"clean": "find . -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null || true",
|
|
52
|
+
"prepublishOnly": "npm run clean"
|
|
46
53
|
},
|
|
47
54
|
"dependencies": {
|
|
48
55
|
"prompts": "^2.4.2",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|