@deinossrl/dgp-agent 1.3.0 → 1.4.0

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.
Files changed (2) hide show
  1. package/index.mjs +217 -16
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -24,20 +24,89 @@
24
24
  */
25
25
 
26
26
  import { execSync, spawn } from 'child_process';
27
- import { hostname } from 'os';
27
+ import { hostname, homedir } from 'os';
28
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
29
+ import { join, dirname } from 'path';
28
30
 
29
- // Configuración
31
+ // ============================================
32
+ // CONFIG FILE MANAGEMENT
33
+ // ============================================
34
+
35
+ const CONFIG_DIR = join(homedir(), '.dgp-agent');
36
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
37
+
38
+ /**
39
+ * Lee la configuración del archivo
40
+ */
41
+ function loadConfigFile() {
42
+ try {
43
+ if (existsSync(CONFIG_FILE)) {
44
+ const content = readFileSync(CONFIG_FILE, 'utf-8');
45
+ return JSON.parse(content);
46
+ }
47
+ } catch (e) {
48
+ // Ignore errors, return empty config
49
+ }
50
+ return {};
51
+ }
52
+
53
+ /**
54
+ * Guarda la configuración en el archivo
55
+ */
56
+ function saveConfigFile(config) {
57
+ try {
58
+ if (!existsSync(CONFIG_DIR)) {
59
+ mkdirSync(CONFIG_DIR, { recursive: true });
60
+ }
61
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
62
+ return true;
63
+ } catch (e) {
64
+ console.error(`Error saving config: ${e.message}`);
65
+ return false;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Obtiene un valor de la configuración
71
+ */
72
+ function getConfigValue(key) {
73
+ const config = loadConfigFile();
74
+ return config[key];
75
+ }
76
+
77
+ /**
78
+ * Establece un valor en la configuración
79
+ */
80
+ function setConfigValue(key, value) {
81
+ const config = loadConfigFile();
82
+ config[key] = value;
83
+ return saveConfigFile(config);
84
+ }
85
+
86
+ /**
87
+ * Elimina un valor de la configuración
88
+ */
89
+ function deleteConfigValue(key) {
90
+ const config = loadConfigFile();
91
+ delete config[key];
92
+ return saveConfigFile(config);
93
+ }
94
+
95
+ // Cargar config del archivo
96
+ const fileConfig = loadConfigFile();
97
+
98
+ // Configuración (prioridad: env vars > archivo config > defaults)
30
99
  const CONFIG = {
31
- apiUrl: process.env.DGP_API_URL || 'https://asivayhbrqennwiwttds.supabase.co/functions/v1/dgp-agent-status',
32
- commandsUrl: process.env.DGP_COMMANDS_URL || 'https://asivayhbrqennwiwttds.supabase.co/rest/v1/dgp_agent_commands',
33
- supabaseKey: process.env.DGP_SUPABASE_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFzaXZheWhicnFlbm53aXd0dGRzIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjczMDAwOTcsImV4cCI6MjA4Mjg3NjA5N30.s3a7dR-dPkEXI7B2lUTUXU69923hhuX6meheNeo5EKA',
34
- interval: parseInt(process.env.DGP_INTERVAL || '30', 10),
35
- commandPollInterval: parseInt(process.env.DGP_COMMAND_POLL_INTERVAL || '10', 10),
36
- machineId: process.env.DGP_MACHINE_ID || `${hostname()}-${process.env.USERNAME || process.env.USER || 'dev'}`,
37
- authToken: process.env.DGP_AUTH_TOKEN || null,
100
+ apiUrl: process.env.DGP_API_URL || fileConfig.apiUrl || 'https://asivayhbrqennwiwttds.supabase.co/functions/v1/dgp-agent-status',
101
+ commandsUrl: process.env.DGP_COMMANDS_URL || fileConfig.commandsUrl || 'https://asivayhbrqennwiwttds.supabase.co/rest/v1/dgp_agent_commands',
102
+ supabaseKey: process.env.DGP_SUPABASE_KEY || fileConfig.supabaseKey || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFzaXZheWhicnFlbm53aXd0dGRzIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjczMDAwOTcsImV4cCI6MjA4Mjg3NjA5N30.s3a7dR-dPkEXI7B2lUTUXU69923hhuX6meheNeo5EKA',
103
+ interval: parseInt(process.env.DGP_INTERVAL || fileConfig.interval || '30', 10),
104
+ commandPollInterval: parseInt(process.env.DGP_COMMAND_POLL_INTERVAL || fileConfig.commandPollInterval || '10', 10),
105
+ machineId: process.env.DGP_MACHINE_ID || fileConfig.machineId || `${hostname()}-${process.env.USERNAME || process.env.USER || 'dev'}`,
106
+ authToken: process.env.DGP_AUTH_TOKEN || fileConfig.authToken || null,
38
107
  // Claude AI config
39
- anthropicApiKey: process.env.ANTHROPIC_API_KEY || null,
40
- aiModel: process.env.DGP_AI_MODEL || 'claude-sonnet-4-20250514',
108
+ anthropicApiKey: process.env.ANTHROPIC_API_KEY || fileConfig.anthropicApiKey || null,
109
+ aiModel: process.env.DGP_AI_MODEL || fileConfig.aiModel || 'claude-sonnet-4-20250514',
41
110
  };
42
111
 
43
112
  // Colores para la consola
@@ -523,7 +592,7 @@ async function reportStatus(status) {
523
592
  const payload = {
524
593
  machine_id: CONFIG.machineId,
525
594
  timestamp: new Date().toISOString(),
526
- agent_version: '1.3.0',
595
+ agent_version: '1.4.0',
527
596
  status,
528
597
  };
529
598
 
@@ -822,7 +891,7 @@ async function runAgent(deployMode = false) {
822
891
  console.log('');
823
892
  console.log(`${colors.green}╔═══════════════════════════════════════════════════════╗${colors.reset}`);
824
893
  console.log(`${colors.green}║ DGP Agent - Despliegue-GPT Local Agent ║${colors.reset}`);
825
- console.log(`${colors.green}║ @deinossrl/dgp-agent v1.3.0 ║${colors.reset}`);
894
+ console.log(`${colors.green}║ @deinossrl/dgp-agent v1.4.0 ║${colors.reset}`);
826
895
  console.log(`${colors.green}╚═══════════════════════════════════════════════════════╝${colors.reset}`);
827
896
  console.log('');
828
897
 
@@ -938,7 +1007,7 @@ async function showStatus() {
938
1007
  function showHelp() {
939
1008
  console.log(`
940
1009
  ${colors.bold}${colors.cyan}DGP Agent - Despliegue-GPT Local Agent${colors.reset}
941
- ${colors.gray}@deinossrl/dgp-agent v1.3.0${colors.reset}
1010
+ ${colors.gray}@deinossrl/dgp-agent v1.4.0${colors.reset}
942
1011
 
943
1012
  ${colors.bold}DESCRIPCIÓN${colors.reset}
944
1013
  Agente local que reporta el estado de tu repositorio Git
@@ -952,8 +1021,9 @@ ${colors.bold}USO${colors.reset}
952
1021
  ${colors.cyan}dgp-agent${colors.reset} Inicia el agente (solo reporta estado)
953
1022
  ${colors.cyan}dgp-agent deploy${colors.reset} Modo deploy (reporta + escucha comandos)
954
1023
  ${colors.cyan}dgp-agent status${colors.reset} Muestra el estado actual una vez
955
- ${colors.cyan}dgp-agent ai${colors.reset} Modo IA interactivo (requiere ANTHROPIC_API_KEY)
1024
+ ${colors.cyan}dgp-agent ai${colors.reset} Modo IA interactivo (requiere API key)
956
1025
  ${colors.cyan}dgp-agent ai "tarea"${colors.reset} Ejecuta una tarea con IA
1026
+ ${colors.cyan}dgp-agent config${colors.reset} Gestiona la configuración local
957
1027
  ${colors.cyan}dgp-agent help${colors.reset} Muestra esta ayuda
958
1028
 
959
1029
  ${colors.bold}MODOS DE OPERACIÓN${colors.reset}
@@ -988,6 +1058,7 @@ ${colors.bold}REQUISITOS PARA DEPLOY${colors.reset}
988
1058
  - Permisos sudo para reload nginx (vía sudoers sin password)
989
1059
 
990
1060
  ${colors.bold}CHANGELOG${colors.reset}
1061
+ ${colors.cyan}v1.4.0${colors.reset} - Config persistente: dgp-agent config set/get/list
991
1062
  ${colors.cyan}v1.3.0${colors.reset} - AI Mode: ejecuta tareas con lenguaje natural
992
1063
  ${colors.cyan}v1.2.7${colors.reset} - Fix: update via Edge Function (401 fix)
993
1064
  ${colors.cyan}v1.2.6${colors.reset} - Comando git_commit_push desde la UI
@@ -1002,6 +1073,133 @@ ${colors.bold}MÁS INFO${colors.reset}
1002
1073
  `);
1003
1074
  }
1004
1075
 
1076
+ /**
1077
+ * Maneja el comando config
1078
+ */
1079
+ function handleConfigCommand(args) {
1080
+ const subcommand = args[0];
1081
+ const key = args[1];
1082
+ const value = args.slice(2).join(' ');
1083
+
1084
+ // Mapeo de claves amigables a claves internas
1085
+ const keyMap = {
1086
+ 'anthropic-api-key': 'anthropicApiKey',
1087
+ 'api-key': 'anthropicApiKey',
1088
+ 'ai-model': 'aiModel',
1089
+ 'model': 'aiModel',
1090
+ 'auth-token': 'authToken',
1091
+ 'token': 'authToken',
1092
+ 'interval': 'interval',
1093
+ 'machine-id': 'machineId',
1094
+ };
1095
+
1096
+ const resolveKey = (k) => keyMap[k] || k;
1097
+
1098
+ switch (subcommand) {
1099
+ case 'set':
1100
+ if (!key || !value) {
1101
+ console.log(`${colors.red}Error: dgp-agent config set <key> <value>${colors.reset}`);
1102
+ console.log(`\nClaves disponibles:`);
1103
+ Object.keys(keyMap).forEach(k => console.log(` ${colors.cyan}${k}${colors.reset}`));
1104
+ process.exit(1);
1105
+ }
1106
+ const setKey = resolveKey(key);
1107
+ if (setConfigValue(setKey, value)) {
1108
+ logSuccess(`Config saved: ${key} = ${value.substring(0, 20)}${value.length > 20 ? '...' : ''}`);
1109
+ console.log(`${colors.gray}Archivo: ${CONFIG_FILE}${colors.reset}`);
1110
+ }
1111
+ break;
1112
+
1113
+ case 'get':
1114
+ if (!key) {
1115
+ console.log(`${colors.red}Error: dgp-agent config get <key>${colors.reset}`);
1116
+ process.exit(1);
1117
+ }
1118
+ const getKey = resolveKey(key);
1119
+ const val = getConfigValue(getKey);
1120
+ if (val) {
1121
+ console.log(val);
1122
+ } else {
1123
+ console.log(`${colors.gray}(not set)${colors.reset}`);
1124
+ }
1125
+ break;
1126
+
1127
+ case 'list':
1128
+ case 'ls':
1129
+ const config = loadConfigFile();
1130
+ console.log(`\n${colors.bold}Configuración guardada:${colors.reset}`);
1131
+ console.log(`${colors.gray}Archivo: ${CONFIG_FILE}${colors.reset}\n`);
1132
+
1133
+ if (Object.keys(config).length === 0) {
1134
+ console.log(`${colors.gray} (vacío)${colors.reset}`);
1135
+ } else {
1136
+ Object.entries(config).forEach(([k, v]) => {
1137
+ // Ocultar parcialmente las API keys
1138
+ let displayValue = v;
1139
+ if (k.toLowerCase().includes('key') || k.toLowerCase().includes('token')) {
1140
+ displayValue = typeof v === 'string' && v.length > 10
1141
+ ? v.substring(0, 10) + '...' + v.substring(v.length - 4)
1142
+ : '***';
1143
+ }
1144
+ console.log(` ${colors.cyan}${k}${colors.reset}: ${displayValue}`);
1145
+ });
1146
+ }
1147
+ console.log('');
1148
+ break;
1149
+
1150
+ case 'delete':
1151
+ case 'rm':
1152
+ case 'remove':
1153
+ if (!key) {
1154
+ console.log(`${colors.red}Error: dgp-agent config delete <key>${colors.reset}`);
1155
+ process.exit(1);
1156
+ }
1157
+ const delKey = resolveKey(key);
1158
+ if (deleteConfigValue(delKey)) {
1159
+ logSuccess(`Config deleted: ${key}`);
1160
+ }
1161
+ break;
1162
+
1163
+ case 'path':
1164
+ console.log(CONFIG_FILE);
1165
+ break;
1166
+
1167
+ default:
1168
+ console.log(`
1169
+ ${colors.bold}${colors.cyan}dgp-agent config${colors.reset} - Gestión de configuración
1170
+
1171
+ ${colors.bold}USO${colors.reset}
1172
+ ${colors.cyan}dgp-agent config set <key> <value>${colors.reset} Guardar un valor
1173
+ ${colors.cyan}dgp-agent config get <key>${colors.reset} Obtener un valor
1174
+ ${colors.cyan}dgp-agent config list${colors.reset} Listar toda la config
1175
+ ${colors.cyan}dgp-agent config delete <key>${colors.reset} Eliminar un valor
1176
+ ${colors.cyan}dgp-agent config path${colors.reset} Mostrar ruta del archivo
1177
+
1178
+ ${colors.bold}CLAVES DISPONIBLES${colors.reset}
1179
+ ${colors.yellow}anthropic-api-key${colors.reset} Tu API key de Anthropic (Claude)
1180
+ ${colors.yellow}ai-model${colors.reset} Modelo de IA (default: claude-sonnet-4-20250514)
1181
+ ${colors.yellow}auth-token${colors.reset} Token JWT para autenticación
1182
+ ${colors.yellow}interval${colors.reset} Intervalo de reporte en segundos
1183
+ ${colors.yellow}machine-id${colors.reset} ID personalizado de la máquina
1184
+
1185
+ ${colors.bold}EJEMPLOS${colors.reset}
1186
+ ${colors.gray}# Configurar API key de Claude${colors.reset}
1187
+ dgp-agent config set anthropic-api-key sk-ant-api03-...
1188
+
1189
+ ${colors.gray}# Ver configuración actual${colors.reset}
1190
+ dgp-agent config list
1191
+
1192
+ ${colors.gray}# Obtener un valor específico${colors.reset}
1193
+ dgp-agent config get ai-model
1194
+
1195
+ ${colors.bold}NOTAS${colors.reset}
1196
+ - La config se guarda en: ${colors.gray}${CONFIG_FILE}${colors.reset}
1197
+ - Las variables de entorno tienen prioridad sobre el archivo
1198
+ - Las API keys se ocultan parcialmente al listar
1199
+ `);
1200
+ }
1201
+ }
1202
+
1005
1203
  // CLI
1006
1204
  const args = process.argv.slice(2);
1007
1205
  const command = args[0];
@@ -1025,12 +1223,15 @@ switch (command) {
1025
1223
  case 'version':
1026
1224
  case '-v':
1027
1225
  case '--version':
1028
- console.log('@deinossrl/dgp-agent v1.3.0');
1226
+ console.log('@deinossrl/dgp-agent v1.4.0');
1029
1227
  break;
1030
1228
  case 'ai':
1031
1229
  case '--ai':
1032
1230
  runAIMode();
1033
1231
  break;
1232
+ case 'config':
1233
+ handleConfigCommand(args.slice(1));
1234
+ break;
1034
1235
  default:
1035
1236
  runAgent(false); // Status-only mode
1036
1237
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deinossrl/dgp-agent",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Agente local para Despliegue-GPT - Reporta el estado del repositorio Git a la plataforma TenMinute IA",
5
5
  "main": "index.mjs",
6
6
  "bin": {