config_manager dividido en partes para que no sea tan grande
This commit is contained in:
parent
d63abc971c
commit
c759a756be
Binary file not shown.
57
app.py
57
app.py
|
@ -1,6 +1,6 @@
|
||||||
from flask import Flask, render_template, request, jsonify, url_for
|
from flask import Flask, render_template, request, jsonify, url_for
|
||||||
from flask_sock import Sock
|
from flask_sock import Sock
|
||||||
from config_manager import ConfigurationManager
|
from lib.config_manager import ConfigurationManager
|
||||||
import os
|
import os
|
||||||
import json # Added import
|
import json # Added import
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -46,7 +46,7 @@ def broadcast_message(message):
|
||||||
dead_connections = set()
|
dead_connections = set()
|
||||||
timestamp = datetime.now().strftime("[%H:%M:%S] ")
|
timestamp = datetime.now().strftime("[%H:%M:%S] ")
|
||||||
|
|
||||||
# Si es una lista de mensajes, procesar cada uno
|
# Normalize input to a list of messages
|
||||||
if isinstance(message, list):
|
if isinstance(message, list):
|
||||||
messages = message
|
messages = message
|
||||||
else:
|
else:
|
||||||
|
@ -54,32 +54,32 @@ def broadcast_message(message):
|
||||||
messages = [line.strip() for line in message.splitlines() if line.strip()]
|
messages = [line.strip() for line in message.splitlines() if line.strip()]
|
||||||
|
|
||||||
# Procesar cada mensaje
|
# Procesar cada mensaje
|
||||||
for msg in messages:
|
for raw_msg in messages:
|
||||||
# Limpiar timestamps duplicados al inicio del mensaje
|
# Limpiar timestamps duplicados al inicio del mensaje
|
||||||
while msg.startswith("[") and "]" in msg:
|
while raw_msg.startswith("[") and "]" in raw_msg:
|
||||||
try:
|
try:
|
||||||
closing_bracket = msg.index("]") + 1
|
closing_bracket = raw_msg.index("]") + 1
|
||||||
if msg[1 : closing_bracket - 1].replace(":", "").isdigit():
|
if raw_msg[1 : closing_bracket - 1].replace(":", "").isdigit():
|
||||||
msg = msg[closing_bracket:].strip()
|
raw_msg = raw_msg[closing_bracket:].strip() # Update raw_msg itself
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
break
|
break
|
||||||
|
|
||||||
# Añadir un único timestamp
|
# Log the raw message using the config_manager's logger
|
||||||
formatted_msg = f"{timestamp}{msg}"
|
# The logger will handle its own timestamping for the file.
|
||||||
|
config_manager.append_log(raw_msg)
|
||||||
|
|
||||||
# Escribir en el archivo de log
|
# Format message with timestamp *for WebSocket broadcast*
|
||||||
with open(config_manager.log_file, "a", encoding="utf-8") as f:
|
formatted_msg_for_ws = f"{timestamp}{raw_msg}"
|
||||||
f.write(f"{formatted_msg}\n")
|
|
||||||
|
|
||||||
# Enviar a todos los clientes WebSocket
|
# Enviar a todos los clientes WebSocket
|
||||||
for ws in list(websocket_connections):
|
for ws in list(websocket_connections):
|
||||||
try:
|
try:
|
||||||
if ws.connected:
|
if ws.connected: # Check if ws is still connected before sending
|
||||||
ws.send(f"{formatted_msg}\n")
|
ws.send(f"{formatted_msg_for_ws}\n") # Use the correct variable name here
|
||||||
except Exception:
|
except Exception:
|
||||||
dead_connections.add(ws)
|
dead_connections.add(ws) # Collect dead connections
|
||||||
|
|
||||||
# Limpiar conexiones muertas
|
# Limpiar conexiones muertas
|
||||||
websocket_connections.difference_update(dead_connections)
|
websocket_connections.difference_update(dead_connections)
|
||||||
|
@ -205,30 +205,19 @@ def handle_logs():
|
||||||
|
|
||||||
@app.route("/api/group-description/<group>", methods=["GET", "POST"])
|
@app.route("/api/group-description/<group>", methods=["GET", "POST"])
|
||||||
def handle_group_description(group):
|
def handle_group_description(group):
|
||||||
description_path = os.path.join(
|
|
||||||
config_manager.script_groups_path, group, "description.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
try:
|
try:
|
||||||
with open(description_path, "r", encoding="utf-8") as f:
|
details = config_manager.get_group_details(group)
|
||||||
return jsonify(json.load(f))
|
if "error" in details:
|
||||||
except FileNotFoundError:
|
return jsonify(details), 404 # Group not found
|
||||||
return jsonify(
|
return jsonify(details)
|
||||||
{
|
except Exception as e:
|
||||||
"name": group,
|
return jsonify({"status": "error", "message": str(e)}), 500
|
||||||
"description": "Sin descripción",
|
|
||||||
"version": "1.0",
|
|
||||||
"author": "Unknown",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else: # POST
|
else: # POST
|
||||||
try:
|
try:
|
||||||
data = request.json
|
data = request.json
|
||||||
os.makedirs(os.path.dirname(description_path), exist_ok=True)
|
result = config_manager.update_group_description(group, data)
|
||||||
with open(description_path, "w", encoding="utf-8") as f:
|
return jsonify(result)
|
||||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
|
||||||
return jsonify({"status": "success"})
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"status": "error", "message": str(e)}), 500
|
return jsonify({"status": "error", "message": str(e)}), 500
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -0,0 +1,15 @@
|
||||||
|
--- Log de Ejecución: x1_to_json.py ---
|
||||||
|
Grupo: XML Parser to SCL
|
||||||
|
Directorio de Trabajo: C:\Trabajo\SIDEL\06 - E5.007363 - Modifica O&U - SAE196 (cip integrato)\Reporte\IOExport
|
||||||
|
Inicio: 2025-05-03 20:08:18
|
||||||
|
Fin: 2025-05-03 20:08:22
|
||||||
|
Duración: 0:00:03.850097
|
||||||
|
Estado: SUCCESS (Código de Salida: 0)
|
||||||
|
|
||||||
|
--- SALIDA ESTÁNDAR (STDOUT) ---
|
||||||
|
Por favor, selecciona el archivo XML de entrada...
|
||||||
|
|
||||||
|
--- ERRORES (STDERR) ---
|
||||||
|
No se seleccionó ningún archivo. Saliendo.
|
||||||
|
|
||||||
|
--- FIN DEL LOG ---
|
|
@ -1,9 +1,9 @@
|
||||||
--- Log de Ejecución: x1.py ---
|
--- Log de Ejecución: x1.py ---
|
||||||
Grupo: example_group
|
Grupo: example_group
|
||||||
Directorio de Trabajo: C:\Estudio
|
Directorio de Trabajo: C:\Estudio
|
||||||
Inicio: 2025-05-03 17:26:22
|
Inicio: 2025-05-03 20:54:12
|
||||||
Fin: 2025-05-03 17:26:27
|
Fin: 2025-05-03 20:54:17
|
||||||
Duración: 0:00:05.167151
|
Duración: 0:00:05.196719
|
||||||
Estado: SUCCESS (Código de Salida: 0)
|
Estado: SUCCESS (Código de Salida: 0)
|
||||||
|
|
||||||
--- SALIDA ESTÁNDAR (STDOUT) ---
|
--- SALIDA ESTÁNDAR (STDOUT) ---
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
--- Log de Ejecución: x2.py ---
|
--- Log de Ejecución: x2.py ---
|
||||||
Grupo: example_group
|
Grupo: example_group
|
||||||
Directorio de Trabajo: C:\Estudio
|
Directorio de Trabajo: C:\Estudio
|
||||||
Inicio: 2025-05-03 17:26:13
|
Inicio: 2025-05-03 20:48:23
|
||||||
Fin: 2025-05-03 17:26:14
|
Fin: 2025-05-03 20:48:27
|
||||||
Duración: 0:00:01.149705
|
Duración: 0:00:03.208350
|
||||||
Estado: SUCCESS (Código de Salida: 0)
|
Estado: SUCCESS (Código de Salida: 0)
|
||||||
|
|
||||||
--- SALIDA ESTÁNDAR (STDOUT) ---
|
--- SALIDA ESTÁNDAR (STDOUT) ---
|
||||||
|
@ -11,6 +11,10 @@ Estado: SUCCESS (Código de Salida: 0)
|
||||||
|
|
||||||
Iniciando análisis de datos simulado...
|
Iniciando análisis de datos simulado...
|
||||||
Analizando lote 1...
|
Analizando lote 1...
|
||||||
|
Lote 1 completado exitosamente
|
||||||
|
Analizando lote 2...
|
||||||
|
Lote 2 completado exitosamente
|
||||||
|
Analizando lote 3...
|
||||||
|
|
||||||
ERROR: Error simulado en el procesamiento
|
ERROR: Error simulado en el procesamiento
|
||||||
El proceso se detuvo debido a un error
|
El proceso se detuvo debido a un error
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
from pathlib import Path
|
|
||||||
import re
|
|
||||||
|
|
||||||
class ClaudeProjectOrganizer:
|
|
||||||
def __init__(self):
|
|
||||||
self.source_dir = Path.cwd()
|
|
||||||
self.claude_dir = self.source_dir / 'claude'
|
|
||||||
self.file_mapping = {}
|
|
||||||
|
|
||||||
def should_skip_directory(self, dir_name):
|
|
||||||
skip_dirs = {'.git', '__pycache__', 'venv', 'env', '.pytest_cache', '.vscode', 'claude'}
|
|
||||||
return dir_name in skip_dirs
|
|
||||||
|
|
||||||
def get_comment_prefix(self, file_extension):
|
|
||||||
"""Determina el prefijo de comentario según la extensión del archivo"""
|
|
||||||
comment_styles = {
|
|
||||||
'.py': '#',
|
|
||||||
'.js': '//',
|
|
||||||
'.css': '/*',
|
|
||||||
'.html': '<!--',
|
|
||||||
'.scss': '//',
|
|
||||||
'.less': '//',
|
|
||||||
'.tsx': '//',
|
|
||||||
'.ts': '//',
|
|
||||||
'.jsx': '//',
|
|
||||||
}
|
|
||||||
return comment_styles.get(file_extension.lower(), None)
|
|
||||||
|
|
||||||
def get_comment_suffix(self, file_extension):
|
|
||||||
"""Determina el sufijo de comentario si es necesario"""
|
|
||||||
comment_suffixes = {
|
|
||||||
'.css': ' */',
|
|
||||||
'.html': ' -->',
|
|
||||||
}
|
|
||||||
return comment_suffixes.get(file_extension.lower(), '')
|
|
||||||
|
|
||||||
def normalize_path(self, path_str: str) -> str:
|
|
||||||
"""Normaliza la ruta usando forward slashes"""
|
|
||||||
return str(path_str).replace('\\', '/')
|
|
||||||
|
|
||||||
def check_existing_path_comment(self, content: str, normalized_path: str, comment_prefix: str) -> bool:
|
|
||||||
"""Verifica si ya existe un comentario con la ruta en el archivo"""
|
|
||||||
# Escapar caracteres especiales en el prefijo de comentario para regex
|
|
||||||
escaped_prefix = re.escape(comment_prefix)
|
|
||||||
|
|
||||||
# Crear patrones para buscar tanto forward como backward slashes
|
|
||||||
forward_pattern = f"{escaped_prefix}\\s*{re.escape(normalized_path)}\\b"
|
|
||||||
backward_path = normalized_path.replace('/', '\\\\') # Doble backslash para el patrón
|
|
||||||
backward_pattern = f"{escaped_prefix}\\s*{re.escape(backward_path)}"
|
|
||||||
|
|
||||||
# Buscar en las primeras líneas del archivo
|
|
||||||
first_lines = content.split('\n')[:5]
|
|
||||||
for line in first_lines:
|
|
||||||
if (re.search(forward_pattern, line) or
|
|
||||||
re.search(backward_pattern, line)):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def add_path_comment(self, file_path: Path, content: str) -> str:
|
|
||||||
"""Agrega un comentario con la ruta al inicio del archivo si no existe"""
|
|
||||||
relative_path = file_path.relative_to(self.source_dir)
|
|
||||||
normalized_path = self.normalize_path(relative_path)
|
|
||||||
comment_prefix = self.get_comment_prefix(file_path.suffix)
|
|
||||||
|
|
||||||
if comment_prefix is None:
|
|
||||||
return content
|
|
||||||
|
|
||||||
comment_suffix = self.get_comment_suffix(file_path.suffix)
|
|
||||||
|
|
||||||
# Verificar si ya existe el comentario
|
|
||||||
if self.check_existing_path_comment(content, normalized_path, comment_prefix):
|
|
||||||
print(f" - Comentario de ruta ya existe en {file_path}")
|
|
||||||
return content
|
|
||||||
|
|
||||||
path_comment = f"{comment_prefix} {normalized_path}{comment_suffix}\n"
|
|
||||||
|
|
||||||
# Para archivos HTML, insertar después del doctype si existe
|
|
||||||
if file_path.suffix.lower() == '.html':
|
|
||||||
if content.lower().startswith('<!doctype'):
|
|
||||||
doctype_end = content.find('>') + 1
|
|
||||||
return content[:doctype_end] + '\n' + path_comment + content[doctype_end:]
|
|
||||||
|
|
||||||
return path_comment + content
|
|
||||||
|
|
||||||
def clean_claude_directory(self):
|
|
||||||
if self.claude_dir.exists():
|
|
||||||
shutil.rmtree(self.claude_dir)
|
|
||||||
self.claude_dir.mkdir()
|
|
||||||
print(f"Directorio claude limpiado: {self.claude_dir}")
|
|
||||||
|
|
||||||
def copy_files(self):
|
|
||||||
self.clean_claude_directory()
|
|
||||||
|
|
||||||
for root, dirs, files in os.walk(self.source_dir):
|
|
||||||
dirs[:] = [d for d in dirs if not self.should_skip_directory(d)]
|
|
||||||
current_path = Path(root)
|
|
||||||
|
|
||||||
for file in files:
|
|
||||||
file_path = current_path / file
|
|
||||||
|
|
||||||
if file.endswith(('.py', '.js', '.css', '.html', '.json', '.yml', '.yaml',
|
|
||||||
'.tsx', '.ts', '.jsx', '.scss', '.less')):
|
|
||||||
target_path = self.claude_dir / file
|
|
||||||
|
|
||||||
# Si el archivo ya existe en el directorio claude, agregar un sufijo numérico
|
|
||||||
if target_path.exists():
|
|
||||||
base = target_path.stem
|
|
||||||
ext = target_path.suffix
|
|
||||||
counter = 1
|
|
||||||
while target_path.exists():
|
|
||||||
target_path = self.claude_dir / f"{base}_{counter}{ext}"
|
|
||||||
counter += 1
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Leer el contenido del archivo
|
|
||||||
with open(file_path, 'r', encoding='utf-8') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
# Agregar el comentario con la ruta si no existe
|
|
||||||
modified_content = self.add_path_comment(file_path, content)
|
|
||||||
|
|
||||||
# Escribir el nuevo contenido
|
|
||||||
with open(target_path, 'w', encoding='utf-8', newline='\n') as f:
|
|
||||||
f.write(modified_content)
|
|
||||||
|
|
||||||
self.file_mapping[str(file_path)] = target_path.name
|
|
||||||
print(f"Copiado: {file_path} -> {target_path}")
|
|
||||||
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
print(f"Advertencia: No se pudo procesar {file_path} como texto. Copiando sin modificar...")
|
|
||||||
shutil.copy2(file_path, target_path)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error procesando {file_path}: {str(e)}")
|
|
||||||
|
|
||||||
def generate_tree_report(self):
|
|
||||||
"""Genera el reporte en formato árbol visual"""
|
|
||||||
report = ["Estructura del proyecto original:\n"]
|
|
||||||
|
|
||||||
def add_to_report(path, prefix="", is_last=True):
|
|
||||||
report.append(prefix + ("└── " if is_last else "├── ") + path.name)
|
|
||||||
|
|
||||||
if path.is_dir() and not self.should_skip_directory(path.name):
|
|
||||||
children = sorted(path.iterdir(), key=lambda x: (x.is_file(), x.name))
|
|
||||||
children = [c for c in children if not (c.is_dir() and self.should_skip_directory(c.name))]
|
|
||||||
|
|
||||||
for i, child in enumerate(children):
|
|
||||||
is_last_child = i == len(children) - 1
|
|
||||||
new_prefix = prefix + (" " if is_last else "│ ")
|
|
||||||
add_to_report(child, new_prefix, is_last_child)
|
|
||||||
|
|
||||||
add_to_report(self.source_dir)
|
|
||||||
|
|
||||||
report_path = self.claude_dir / "project_structure.txt"
|
|
||||||
with open(report_path, "w", encoding="utf-8") as f:
|
|
||||||
f.write("\n".join(report))
|
|
||||||
print(f"\nReporte generado en: {report_path}")
|
|
||||||
|
|
||||||
def main():
|
|
||||||
try:
|
|
||||||
print("Iniciando organización de archivos para Claude...")
|
|
||||||
organizer = ClaudeProjectOrganizer()
|
|
||||||
organizer.copy_files()
|
|
||||||
organizer.generate_tree_report()
|
|
||||||
print("\n¡Proceso completado exitosamente!")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\nError durante la ejecución: {str(e)}")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
1010
config_manager.py
1010
config_manager.py
File diff suppressed because it is too large
Load Diff
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"api_key": {
|
|
||||||
"type": "string",
|
|
||||||
"title": "API Key",
|
|
||||||
"description": "Tu clave de API para servicios externos"
|
|
||||||
},
|
|
||||||
"model": {
|
|
||||||
"type": "string",
|
|
||||||
"title": "Modelo LLM",
|
|
||||||
"description": "Modelo de lenguaje a utilizar",
|
|
||||||
"enum": [
|
|
||||||
"gpt-3.5-turbo",
|
|
||||||
"gpt-4",
|
|
||||||
"claude-v1"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,20 @@
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {}
|
"properties": {
|
||||||
|
"api_key": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "API Key",
|
||||||
|
"description": "Tu clave de API para servicios externos"
|
||||||
|
},
|
||||||
|
"model": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Modelo LLM",
|
||||||
|
"description": "Modelo de lenguaje a utilizar",
|
||||||
|
"enum": [
|
||||||
|
"gpt-3.5-turbo",
|
||||||
|
"gpt-4",
|
||||||
|
"claude-v1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
44
data/log.txt
44
data/log.txt
|
@ -1,22 +1,22 @@
|
||||||
[17:26:22] Iniciando ejecución de x1.py en C:\Estudio...
|
[20:54:12] Iniciando ejecución de x1.py en C:\Estudio...
|
||||||
[17:26:22] === Ejecutando Script de Prueba 1 ===
|
[20:54:12] === Ejecutando Script de Prueba 1 ===
|
||||||
[17:26:22] Configuraciones cargadas:
|
[20:54:12] Configuraciones cargadas:
|
||||||
[17:26:22] Nivel 1: {
|
[20:54:12] Nivel 1: {
|
||||||
[17:26:22] "api_key": "your-api-key-here",
|
[20:54:12] "api_key": "your-api-key-here",
|
||||||
[17:26:22] "model": "gpt-3.5-turbo"
|
[20:54:12] "model": "gpt-3.5-turbo"
|
||||||
[17:26:22] }
|
[20:54:12] }
|
||||||
[17:26:22] Nivel 2: {
|
[20:54:12] Nivel 2: {
|
||||||
[17:26:22] "input_dir": "D:/Datos/Entrada",
|
[20:54:12] "input_dir": "D:/Datos/Entrada",
|
||||||
[17:26:22] "output_dir": "D:/Datos/Salida",
|
[20:54:12] "output_dir": "D:/Datos/Salida",
|
||||||
[17:26:22] "batch_size": 50
|
[20:54:12] "batch_size": 50
|
||||||
[17:26:22] }
|
[20:54:12] }
|
||||||
[17:26:22] Nivel 3: {}
|
[20:54:12] Nivel 3: {}
|
||||||
[17:26:22] Simulando procesamiento...
|
[20:54:12] Simulando procesamiento...
|
||||||
[17:26:23] Progreso: 20%
|
[20:54:13] Progreso: 20%
|
||||||
[17:26:24] Progreso: 40%
|
[20:54:14] Progreso: 40%
|
||||||
[17:26:25] Progreso: 60%
|
[20:54:15] Progreso: 60%
|
||||||
[17:26:26] Progreso: 80%
|
[20:54:16] Progreso: 80%
|
||||||
[17:26:27] Progreso: 100%
|
[20:54:17] Progreso: 100%
|
||||||
[17:26:27] ¡Proceso completado!
|
[20:54:17] ¡Proceso completado!
|
||||||
[17:26:27] Ejecución de x1.py finalizada (success). Duración: 0:00:05.167151.
|
[20:54:17] Ejecución de x1.py finalizada (success). Duración: 0:00:05.196719.
|
||||||
[17:26:27] Log completo guardado en: D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\example_group\log_x1.txt
|
[20:54:17] Log completo guardado en: d:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\example_group\log_x1.txt
|
||||||
|
|
Loading…
Reference in New Issue