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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s9n-devops-agent",
3
- "version": "2.0.11-dev.9",
3
+ "version": "2.0.13",
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",
@@ -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 - setting up now...${CONFIG.colors.reset}`);
277
- await houseRulesManager.initialSetup();
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
- dockerInfo.composeFiles.forEach((file, index) => {
605
- console.log(` ${index + 1}) ${file.name}`);
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(`Choose file (1-${dockerInfo.composeFiles.length}) [1]: `, (answer) => {
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';