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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s9n-devops-agent",
3
- "version": "2.0.11-dev.5",
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
- dockerInfo.composeFiles.forEach((file, index) => {
604
- console.log(` ${index + 1}) ${file.name}`);
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(`Choose file (1-${dockerInfo.composeFiles.length}) [1]: `, (answer) => {
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';