s9n-devops-agent 2.0.11-dev.9 → 2.0.13
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 +1 -1
- package/src/session-coordinator.js +101 -7
package/package.json
CHANGED
|
@@ -23,7 +23,7 @@ import crypto from 'crypto';
|
|
|
23
23
|
import readline from 'readline';
|
|
24
24
|
import { fileURLToPath } from 'url';
|
|
25
25
|
import { dirname } from 'path';
|
|
26
|
-
import { spawn, execSync, exec } from 'child_process';
|
|
26
|
+
import { spawn, execSync, exec, fork } from 'child_process';
|
|
27
27
|
import { credentialsManager } from './credentials-manager.js';
|
|
28
28
|
|
|
29
29
|
// Inject credentials immediately
|
|
@@ -273,8 +273,12 @@ class SessionCoordinator {
|
|
|
273
273
|
|
|
274
274
|
// Check if house rules exist
|
|
275
275
|
if (!houseRulesManager.houseRulesPath || !fs.existsSync(houseRulesManager.houseRulesPath)) {
|
|
276
|
-
console.log(`\n${CONFIG.colors.yellow}House rules not found -
|
|
277
|
-
|
|
276
|
+
console.log(`\n${CONFIG.colors.yellow}House rules not found - creating default house rules...${CONFIG.colors.reset}`);
|
|
277
|
+
// Auto-create default house rules without prompting
|
|
278
|
+
const result = await houseRulesManager.updateHouseRules({ createIfMissing: true, backupExisting: false });
|
|
279
|
+
if (result.created) {
|
|
280
|
+
console.log(`${CONFIG.colors.green}✓${CONFIG.colors.reset} House rules created at: ${CONFIG.colors.bright}${result.path}${CONFIG.colors.reset}`);
|
|
281
|
+
}
|
|
278
282
|
} else {
|
|
279
283
|
// House rules exist - check if they need updating
|
|
280
284
|
const status = houseRulesManager.getStatus();
|
|
@@ -601,12 +605,30 @@ class SessionCoordinator {
|
|
|
601
605
|
|
|
602
606
|
if (dockerInfo.composeFiles.length > 1) {
|
|
603
607
|
console.log(`\n${CONFIG.colors.bright}Select docker-compose file:${CONFIG.colors.reset}`);
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
608
|
+
|
|
609
|
+
// Check running containers for each compose file
|
|
610
|
+
for (let i = 0; i < dockerInfo.composeFiles.length; i++) {
|
|
611
|
+
const file = dockerInfo.composeFiles[i];
|
|
612
|
+
let runningInfo = '';
|
|
613
|
+
|
|
614
|
+
try {
|
|
615
|
+
// Try to get container count for this compose file
|
|
616
|
+
const { execSync } = await import('child_process');
|
|
617
|
+
const result = execSync(`docker compose -f "${file.path}" ps -q 2>/dev/null | wc -l`, { encoding: 'utf8' });
|
|
618
|
+
const count = parseInt(result.trim());
|
|
619
|
+
if (count > 0) {
|
|
620
|
+
runningInfo = ` ${CONFIG.colors.green}(${count} running)${CONFIG.colors.reset}`;
|
|
621
|
+
}
|
|
622
|
+
} catch (err) {
|
|
623
|
+
// Ignore errors, just don't show running info
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
console.log(` ${i + 1}) ${file.name}${runningInfo}`);
|
|
627
|
+
console.log(` ${CONFIG.colors.dim}${file.path}${CONFIG.colors.reset}`);
|
|
628
|
+
}
|
|
607
629
|
|
|
608
630
|
const fileChoice = await new Promise((resolve) => {
|
|
609
|
-
rl.question(
|
|
631
|
+
rl.question(`\nChoose file (1-${dockerInfo.composeFiles.length}) [1]: `, (answer) => {
|
|
610
632
|
const choice = parseInt(answer) || 1;
|
|
611
633
|
if (choice >= 1 && choice <= dockerInfo.composeFiles.length) {
|
|
612
634
|
resolve(dockerInfo.composeFiles[choice - 1]);
|
|
@@ -906,6 +928,77 @@ class SessionCoordinator {
|
|
|
906
928
|
return `${timestamp}-${random}`;
|
|
907
929
|
}
|
|
908
930
|
|
|
931
|
+
/**
|
|
932
|
+
* Ensure GROQ API key is configured (for AI-powered commit messages)
|
|
933
|
+
*/
|
|
934
|
+
async ensureGroqApiKey() {
|
|
935
|
+
const globalSettings = this.loadGlobalSettings();
|
|
936
|
+
|
|
937
|
+
// Check if we've already asked or if key is set
|
|
938
|
+
if (globalSettings.groqApiKeyConfigured === 'never') {
|
|
939
|
+
return; // User chose never
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
if (credentialsManager.hasGroqApiKey()) {
|
|
943
|
+
return; // Key already configured
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// First time - ask if they want AI-powered commit messages
|
|
947
|
+
console.log(`\n${CONFIG.colors.yellow}═══ AI-Powered Commit Messages ═══${CONFIG.colors.reset}`);
|
|
948
|
+
console.log(`${CONFIG.colors.dim}DevOps Agent can generate commit messages using AI (GROQ).${CONFIG.colors.reset}`);
|
|
949
|
+
console.log();
|
|
950
|
+
console.log(`${CONFIG.colors.bright}Options:${CONFIG.colors.reset}`);
|
|
951
|
+
console.log(` ${CONFIG.colors.green}Y${CONFIG.colors.reset}) Yes - Configure GROQ API key now`);
|
|
952
|
+
console.log(` ${CONFIG.colors.red}N${CONFIG.colors.reset}) Skip - Configure later with: npm run setup`);
|
|
953
|
+
console.log(` ${CONFIG.colors.magenta}Never${CONFIG.colors.reset}) Never ask again (disable AI commits)`);
|
|
954
|
+
|
|
955
|
+
const rl = readline.createInterface({
|
|
956
|
+
input: process.stdin,
|
|
957
|
+
output: process.stdout
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
const answer = await new Promise((resolve) => {
|
|
961
|
+
rl.question('\nEnable AI-powered commit messages? (Y/N/Never) [N]: ', (ans) => {
|
|
962
|
+
resolve(ans.trim().toLowerCase());
|
|
963
|
+
});
|
|
964
|
+
});
|
|
965
|
+
|
|
966
|
+
if (answer === 'never' || answer === 'nev') {
|
|
967
|
+
globalSettings.groqApiKeyConfigured = 'never';
|
|
968
|
+
this.saveGlobalSettings(globalSettings);
|
|
969
|
+
console.log(`${CONFIG.colors.dim}AI commit messages disabled. You can enable later by editing ~/.devops-agent/settings.json${CONFIG.colors.reset}`);
|
|
970
|
+
rl.close();
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
if (answer === 'y' || answer === 'yes') {
|
|
975
|
+
console.log();
|
|
976
|
+
console.log(`${CONFIG.colors.bright}GROQ API Key Setup${CONFIG.colors.reset}`);
|
|
977
|
+
console.log(`${CONFIG.colors.dim}Get your free API key at: ${CONFIG.colors.cyan}https://console.groq.com/keys${CONFIG.colors.reset}`);
|
|
978
|
+
console.log();
|
|
979
|
+
|
|
980
|
+
const apiKey = await new Promise((resolve) => {
|
|
981
|
+
rl.question('Enter your GROQ API key: ', (key) => {
|
|
982
|
+
resolve(key.trim());
|
|
983
|
+
});
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
if (apiKey) {
|
|
987
|
+
credentialsManager.setGroqApiKey(apiKey);
|
|
988
|
+
credentialsManager.injectEnv();
|
|
989
|
+
globalSettings.groqApiKeyConfigured = 'yes';
|
|
990
|
+
this.saveGlobalSettings(globalSettings);
|
|
991
|
+
console.log(`${CONFIG.colors.green}✓${CONFIG.colors.reset} GROQ API key saved successfully!`);
|
|
992
|
+
} else {
|
|
993
|
+
console.log(`${CONFIG.colors.yellow}No key entered. You can configure later with: npm run setup${CONFIG.colors.reset}`);
|
|
994
|
+
}
|
|
995
|
+
} else {
|
|
996
|
+
console.log(`${CONFIG.colors.dim}Skipping for now. Configure later with: npm run setup${CONFIG.colors.reset}`);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
rl.close();
|
|
1000
|
+
}
|
|
1001
|
+
|
|
909
1002
|
/**
|
|
910
1003
|
* Create a new session and generate Claude instructions
|
|
911
1004
|
*/
|
|
@@ -917,6 +1010,7 @@ class SessionCoordinator {
|
|
|
917
1010
|
await this.ensureGlobalSetup(); // Developer initials (once per user)
|
|
918
1011
|
await this.ensureProjectSetup(); // Version strategy (once per project)
|
|
919
1012
|
await this.ensureHouseRulesSetup(); // House rules setup (once per project)
|
|
1013
|
+
await this.ensureGroqApiKey(); // GROQ API key for AI commits (once per user)
|
|
920
1014
|
|
|
921
1015
|
const sessionId = this.generateSessionId();
|
|
922
1016
|
const task = options.task || 'development';
|