s9n-devops-agent 2.0.11-dev.5 → 2.0.12
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/package.json +2 -2
- package/src/session-coordinator.js +96 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "s9n-devops-agent",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.12",
|
|
4
4
|
"description": "CS_DevOpsAgent - Intelligent Git Automation System with multi-agent support and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/cs-devops-agent-worker.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"house-rules:status": "node src/house-rules-manager.js status",
|
|
30
30
|
"house-rules:update": "node src/house-rules-manager.js update",
|
|
31
31
|
"house-rules:repair": "./scripts/repair-house-rules.sh",
|
|
32
|
-
"test": "jest test_cases/",
|
|
32
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest test_cases/",
|
|
33
33
|
"test:watch": "jest --watch",
|
|
34
34
|
"test:coverage": "jest --coverage",
|
|
35
35
|
"test:worktree": "jest test_cases/worktree/",
|
|
@@ -19,10 +19,11 @@
|
|
|
19
19
|
|
|
20
20
|
import fs from 'fs';
|
|
21
21
|
import path from 'path';
|
|
22
|
+
import crypto from 'crypto';
|
|
22
23
|
import readline from 'readline';
|
|
23
24
|
import { fileURLToPath } from 'url';
|
|
24
25
|
import { dirname } from 'path';
|
|
25
|
-
import { spawn, execSync, exec } from 'child_process';
|
|
26
|
+
import { spawn, execSync, exec, fork } from 'child_process';
|
|
26
27
|
import { credentialsManager } from './credentials-manager.js';
|
|
27
28
|
|
|
28
29
|
// Inject credentials immediately
|
|
@@ -600,12 +601,30 @@ class SessionCoordinator {
|
|
|
600
601
|
|
|
601
602
|
if (dockerInfo.composeFiles.length > 1) {
|
|
602
603
|
console.log(`\n${CONFIG.colors.bright}Select docker-compose file:${CONFIG.colors.reset}`);
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
604
|
+
|
|
605
|
+
// Check running containers for each compose file
|
|
606
|
+
for (let i = 0; i < dockerInfo.composeFiles.length; i++) {
|
|
607
|
+
const file = dockerInfo.composeFiles[i];
|
|
608
|
+
let runningInfo = '';
|
|
609
|
+
|
|
610
|
+
try {
|
|
611
|
+
// Try to get container count for this compose file
|
|
612
|
+
const { execSync } = await import('child_process');
|
|
613
|
+
const result = execSync(`docker compose -f "${file.path}" ps -q 2>/dev/null | wc -l`, { encoding: 'utf8' });
|
|
614
|
+
const count = parseInt(result.trim());
|
|
615
|
+
if (count > 0) {
|
|
616
|
+
runningInfo = ` ${CONFIG.colors.green}(${count} running)${CONFIG.colors.reset}`;
|
|
617
|
+
}
|
|
618
|
+
} catch (err) {
|
|
619
|
+
// Ignore errors, just don't show running info
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
console.log(` ${i + 1}) ${file.name}${runningInfo}`);
|
|
623
|
+
console.log(` ${CONFIG.colors.dim}${file.path}${CONFIG.colors.reset}`);
|
|
624
|
+
}
|
|
606
625
|
|
|
607
626
|
const fileChoice = await new Promise((resolve) => {
|
|
608
|
-
rl.question(
|
|
627
|
+
rl.question(`\nChoose file (1-${dockerInfo.composeFiles.length}) [1]: `, (answer) => {
|
|
609
628
|
const choice = parseInt(answer) || 1;
|
|
610
629
|
if (choice >= 1 && choice <= dockerInfo.composeFiles.length) {
|
|
611
630
|
resolve(dockerInfo.composeFiles[choice - 1]);
|
|
@@ -905,6 +924,77 @@ class SessionCoordinator {
|
|
|
905
924
|
return `${timestamp}-${random}`;
|
|
906
925
|
}
|
|
907
926
|
|
|
927
|
+
/**
|
|
928
|
+
* Ensure GROQ API key is configured (for AI-powered commit messages)
|
|
929
|
+
*/
|
|
930
|
+
async ensureGroqApiKey() {
|
|
931
|
+
const globalSettings = this.loadGlobalSettings();
|
|
932
|
+
|
|
933
|
+
// Check if we've already asked or if key is set
|
|
934
|
+
if (globalSettings.groqApiKeyConfigured === 'never') {
|
|
935
|
+
return; // User chose never
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
if (credentialsManager.hasGroqApiKey()) {
|
|
939
|
+
return; // Key already configured
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// First time - ask if they want AI-powered commit messages
|
|
943
|
+
console.log(`\n${CONFIG.colors.yellow}═══ AI-Powered Commit Messages ═══${CONFIG.colors.reset}`);
|
|
944
|
+
console.log(`${CONFIG.colors.dim}DevOps Agent can generate commit messages using AI (GROQ).${CONFIG.colors.reset}`);
|
|
945
|
+
console.log();
|
|
946
|
+
console.log(`${CONFIG.colors.bright}Options:${CONFIG.colors.reset}`);
|
|
947
|
+
console.log(` ${CONFIG.colors.green}Y${CONFIG.colors.reset}) Yes - Configure GROQ API key now`);
|
|
948
|
+
console.log(` ${CONFIG.colors.red}N${CONFIG.colors.reset}) Skip - Configure later with: npm run setup`);
|
|
949
|
+
console.log(` ${CONFIG.colors.magenta}Never${CONFIG.colors.reset}) Never ask again (disable AI commits)`);
|
|
950
|
+
|
|
951
|
+
const rl = readline.createInterface({
|
|
952
|
+
input: process.stdin,
|
|
953
|
+
output: process.stdout
|
|
954
|
+
});
|
|
955
|
+
|
|
956
|
+
const answer = await new Promise((resolve) => {
|
|
957
|
+
rl.question('\nEnable AI-powered commit messages? (Y/N/Never) [N]: ', (ans) => {
|
|
958
|
+
resolve(ans.trim().toLowerCase());
|
|
959
|
+
});
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
if (answer === 'never' || answer === 'nev') {
|
|
963
|
+
globalSettings.groqApiKeyConfigured = 'never';
|
|
964
|
+
this.saveGlobalSettings(globalSettings);
|
|
965
|
+
console.log(`${CONFIG.colors.dim}AI commit messages disabled. You can enable later by editing ~/.devops-agent/settings.json${CONFIG.colors.reset}`);
|
|
966
|
+
rl.close();
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
if (answer === 'y' || answer === 'yes') {
|
|
971
|
+
console.log();
|
|
972
|
+
console.log(`${CONFIG.colors.bright}GROQ API Key Setup${CONFIG.colors.reset}`);
|
|
973
|
+
console.log(`${CONFIG.colors.dim}Get your free API key at: ${CONFIG.colors.cyan}https://console.groq.com/keys${CONFIG.colors.reset}`);
|
|
974
|
+
console.log();
|
|
975
|
+
|
|
976
|
+
const apiKey = await new Promise((resolve) => {
|
|
977
|
+
rl.question('Enter your GROQ API key: ', (key) => {
|
|
978
|
+
resolve(key.trim());
|
|
979
|
+
});
|
|
980
|
+
});
|
|
981
|
+
|
|
982
|
+
if (apiKey) {
|
|
983
|
+
credentialsManager.setGroqApiKey(apiKey);
|
|
984
|
+
credentialsManager.injectEnv();
|
|
985
|
+
globalSettings.groqApiKeyConfigured = 'yes';
|
|
986
|
+
this.saveGlobalSettings(globalSettings);
|
|
987
|
+
console.log(`${CONFIG.colors.green}✓${CONFIG.colors.reset} GROQ API key saved successfully!`);
|
|
988
|
+
} else {
|
|
989
|
+
console.log(`${CONFIG.colors.yellow}No key entered. You can configure later with: npm run setup${CONFIG.colors.reset}`);
|
|
990
|
+
}
|
|
991
|
+
} else {
|
|
992
|
+
console.log(`${CONFIG.colors.dim}Skipping for now. Configure later with: npm run setup${CONFIG.colors.reset}`);
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
rl.close();
|
|
996
|
+
}
|
|
997
|
+
|
|
908
998
|
/**
|
|
909
999
|
* Create a new session and generate Claude instructions
|
|
910
1000
|
*/
|
|
@@ -916,6 +1006,7 @@ class SessionCoordinator {
|
|
|
916
1006
|
await this.ensureGlobalSetup(); // Developer initials (once per user)
|
|
917
1007
|
await this.ensureProjectSetup(); // Version strategy (once per project)
|
|
918
1008
|
await this.ensureHouseRulesSetup(); // House rules setup (once per project)
|
|
1009
|
+
await this.ensureGroqApiKey(); // GROQ API key for AI commits (once per user)
|
|
919
1010
|
|
|
920
1011
|
const sessionId = this.generateSessionId();
|
|
921
1012
|
const task = options.task || 'development';
|