chocolatito-code 1.0.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.
- package/.mcp.json.ejemplo +19 -0
- package/COMPUTER-USE.md +484 -0
- package/LICENSE +21 -0
- package/README.md +186 -0
- package/dist/agent/context.d.ts +9 -0
- package/dist/agent/context.js +123 -0
- package/dist/agent/fileTracker.d.ts +16 -0
- package/dist/agent/fileTracker.js +53 -0
- package/dist/agent/loop.d.ts +25 -0
- package/dist/agent/loop.js +524 -0
- package/dist/agent/mentions.d.ts +11 -0
- package/dist/agent/mentions.js +43 -0
- package/dist/agent/retry.d.ts +17 -0
- package/dist/agent/retry.js +57 -0
- package/dist/agent/subagent.d.ts +2 -0
- package/dist/agent/subagent.js +116 -0
- package/dist/agent/syntaxValidator.d.ts +5 -0
- package/dist/agent/syntaxValidator.js +71 -0
- package/dist/agent/tracker.d.ts +19 -0
- package/dist/agent/tracker.js +38 -0
- package/dist/agent/undoManager.d.ts +37 -0
- package/dist/agent/undoManager.js +95 -0
- package/dist/config/constants.d.ts +77 -0
- package/dist/config/constants.js +146 -0
- package/dist/config/engine.d.ts +49 -0
- package/dist/config/engine.js +86 -0
- package/dist/config/env.d.ts +13 -0
- package/dist/config/env.js +103 -0
- package/dist/config/license.d.ts +39 -0
- package/dist/config/license.js +306 -0
- package/dist/config/permissions.d.ts +38 -0
- package/dist/config/permissions.js +239 -0
- package/dist/config/quota.d.ts +58 -0
- package/dist/config/quota.js +156 -0
- package/dist/hooks/manager.d.ts +60 -0
- package/dist/hooks/manager.js +193 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +470 -0
- package/dist/mcp/client.d.ts +55 -0
- package/dist/mcp/client.js +282 -0
- package/dist/mcp/manager.d.ts +26 -0
- package/dist/mcp/manager.js +167 -0
- package/dist/memory/manager.d.ts +9 -0
- package/dist/memory/manager.js +59 -0
- package/dist/prompts/systemPrompt.d.ts +5 -0
- package/dist/prompts/systemPrompt.js +177 -0
- package/dist/sessions/manager.d.ts +21 -0
- package/dist/sessions/manager.js +54 -0
- package/dist/skills/manager.d.ts +14 -0
- package/dist/skills/manager.js +86 -0
- package/dist/tools/browserCdp.d.ts +26 -0
- package/dist/tools/browserCdp.js +610 -0
- package/dist/tools/browserExtension.d.ts +58 -0
- package/dist/tools/browserExtension.js +479 -0
- package/dist/tools/browserLive.d.ts +12 -0
- package/dist/tools/browserLive.js +265 -0
- package/dist/tools/changeDir.d.ts +5 -0
- package/dist/tools/changeDir.js +63 -0
- package/dist/tools/computerUse.d.ts +58 -0
- package/dist/tools/computerUse.js +567 -0
- package/dist/tools/createImage.d.ts +1 -0
- package/dist/tools/createImage.js +34 -0
- package/dist/tools/definitions.d.ts +8 -0
- package/dist/tools/definitions.js +401 -0
- package/dist/tools/deleteFile.d.ts +1 -0
- package/dist/tools/deleteFile.js +17 -0
- package/dist/tools/editFile.d.ts +5 -0
- package/dist/tools/editFile.js +88 -0
- package/dist/tools/findFiles.d.ts +1 -0
- package/dist/tools/findFiles.js +33 -0
- package/dist/tools/getSystemInfo.d.ts +1 -0
- package/dist/tools/getSystemInfo.js +23 -0
- package/dist/tools/gitTools.d.ts +3 -0
- package/dist/tools/gitTools.js +47 -0
- package/dist/tools/grepSearch.d.ts +1 -0
- package/dist/tools/grepSearch.js +37 -0
- package/dist/tools/listDir.d.ts +1 -0
- package/dist/tools/listDir.js +33 -0
- package/dist/tools/moveCopyFile.d.ts +1 -0
- package/dist/tools/moveCopyFile.js +21 -0
- package/dist/tools/runCommand.d.ts +1 -0
- package/dist/tools/runCommand.js +61 -0
- package/dist/tools/runner.d.ts +5 -0
- package/dist/tools/runner.js +177 -0
- package/dist/tools/safety.d.ts +17 -0
- package/dist/tools/safety.js +33 -0
- package/dist/tools/todoTool.d.ts +8 -0
- package/dist/tools/todoTool.js +27 -0
- package/dist/tools/toolDefsComputer.d.ts +13 -0
- package/dist/tools/toolDefsComputer.js +205 -0
- package/dist/tools/truncator.d.ts +11 -0
- package/dist/tools/truncator.js +24 -0
- package/dist/tools/viewFile.d.ts +1 -0
- package/dist/tools/viewFile.js +45 -0
- package/dist/tools/visionBridge.d.ts +37 -0
- package/dist/tools/visionBridge.js +107 -0
- package/dist/tools/webFetch.d.ts +1 -0
- package/dist/tools/webFetch.js +25 -0
- package/dist/tools/webSearch.d.ts +1 -0
- package/dist/tools/webSearch.js +35 -0
- package/dist/tools/win/hostClient.d.ts +31 -0
- package/dist/tools/win/hostClient.js +158 -0
- package/dist/tools/win/hostScript.d.ts +1 -0
- package/dist/tools/win/hostScript.js +925 -0
- package/dist/tools/writeFile.d.ts +1 -0
- package/dist/tools/writeFile.js +13 -0
- package/dist/ui/banner.d.ts +10 -0
- package/dist/ui/banner.js +165 -0
- package/dist/ui/diffViewer.d.ts +1 -0
- package/dist/ui/diffViewer.js +60 -0
- package/dist/ui/interrupt.d.ts +17 -0
- package/dist/ui/interrupt.js +156 -0
- package/dist/ui/markdownStream.d.ts +23 -0
- package/dist/ui/markdownStream.js +0 -0
- package/dist/ui/modes.d.ts +28 -0
- package/dist/ui/modes.js +57 -0
- package/dist/ui/permissionPrompt.d.ts +35 -0
- package/dist/ui/permissionPrompt.js +271 -0
- package/dist/ui/prompt.d.ts +7 -0
- package/dist/ui/prompt.js +466 -0
- package/dist/ui/reasoningStream.d.ts +6 -0
- package/dist/ui/reasoningStream.js +38 -0
- package/dist/ui/renderer.d.ts +10 -0
- package/dist/ui/renderer.js +142 -0
- package/dist/ui/spinner.d.ts +24 -0
- package/dist/ui/spinner.js +111 -0
- package/dist/ui/theme.d.ts +36 -0
- package/dist/ui/theme.js +37 -0
- package/dist/ui/typeAhead.d.ts +31 -0
- package/dist/ui/typeAhead.js +87 -0
- package/extension/README.md +74 -0
- package/extension/background.js +575 -0
- package/extension/content.js +446 -0
- package/extension/manifest.json +36 -0
- package/extension/popup.html +22 -0
- package/extension/popup.js +12 -0
- package/package.json +66 -0
- package/skills/complex-refactor/SKILL.md +13 -0
- package/skills/deep-debugger/SKILL.md +14 -0
- package/skills/software-architect/SKILL.md +20 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { CONTEXT_WINDOW } from "../config/constants.js";
|
|
2
|
+
/**
|
|
3
|
+
* Fecha real de la maquina.
|
|
4
|
+
*
|
|
5
|
+
* Sin esto el modelo escribe el año de su entrenamiento. Se coló un
|
|
6
|
+
* "© 2025" en un PDF generado en 2026, y el usuario no tiene por qué revisar
|
|
7
|
+
* cada pie de página para cazar la fecha inventada.
|
|
8
|
+
*/
|
|
9
|
+
function hoy() {
|
|
10
|
+
return new Date().toLocaleDateString("es-ES", {
|
|
11
|
+
weekday: "long",
|
|
12
|
+
year: "numeric",
|
|
13
|
+
month: "long",
|
|
14
|
+
day: "numeric",
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export function buildSystemPrompt(context, model, skillManager, memoryManager, isPlanMode = false) {
|
|
18
|
+
const skillsListing = skillManager ? skillManager.getSkillPromptListing() : "Sin skills.";
|
|
19
|
+
const memoryIndex = memoryManager ? memoryManager.getMemoryIndex() : "Sin memoria.";
|
|
20
|
+
const rulesSection = context.rulesContent
|
|
21
|
+
? `\n\n--- REGLAS DEL PROYECTO (CHOCOLATITO.md) ---\n${context.rulesContent}\n------------------------------------------`
|
|
22
|
+
: "";
|
|
23
|
+
const planModeNotice = isPlanMode
|
|
24
|
+
? `\n\n⚠️ MODO PLAN ACTIVO (SOLO LECTURA): No intentes escribir ni modificar archivos. Investiga el código con herramientas de lectura y genera un plan arquitectónico estructurado para que el usuario lo apruebe.`
|
|
25
|
+
: "";
|
|
26
|
+
return `Eres CHOCOLATITO CODE, un agente de ingeniería de software autónomo de nivel élite.
|
|
27
|
+
Desarrollado y creado por Chocolatito.
|
|
28
|
+
Motor en ejecución: ${model.name} (Esfuerzo: ${model.effortLevel}).
|
|
29
|
+
Ventana de contexto: ${(CONTEXT_WINDOW / 1000).toLocaleString("es")}k tokens (con Prompt Caching).
|
|
30
|
+
|
|
31
|
+
--- BLOQUE 1: ENTORNO DE TRABAJO ---
|
|
32
|
+
- Fecha de hoy: ${hoy()}
|
|
33
|
+
- Directorio actual: ${context.cwd}
|
|
34
|
+
- Sistema Operativo: ${context.os}
|
|
35
|
+
- Tipo de Proyecto: ${context.projectType}
|
|
36
|
+
- Rama Git: ${context.gitBranch || "Sin repositorio git"}
|
|
37
|
+
- Scripts disponibles: ${context.availableScripts.join(", ") || "Ninguno"}${rulesSection}${planModeNotice}
|
|
38
|
+
|
|
39
|
+
--- BLOQUE 2: MEMORIA PERSISTENTE TRANSVERSAL ---
|
|
40
|
+
${memoryIndex}
|
|
41
|
+
(Usa 'save_memory' para recordar hechos clave o preferencias entre sesiones).
|
|
42
|
+
|
|
43
|
+
--- BLOQUE 3: SKILLS DISPONIBLES (CARGA DIFERIDA) ---
|
|
44
|
+
Tienes acceso a skills especializados. Usa la herramienta 'use_skill' para cargar las instrucciones completas de un skill cuando lo necesites:
|
|
45
|
+
${skillsListing}
|
|
46
|
+
|
|
47
|
+
--- BLOQUE 4: SUBAGENTES DISPONIBLES ---
|
|
48
|
+
Puedes delegar tareas aisladas con 'spawn_agent':
|
|
49
|
+
- 'explore': Investigación y búsqueda de código de solo lectura sin saturar el contexto principal.
|
|
50
|
+
- 'plan': Generación de planes arquitectónicos.
|
|
51
|
+
- 'general': Ejecución de subtareas en un sub-hilo limpio.
|
|
52
|
+
|
|
53
|
+
--- BLOQUE 5: JERARQUÍA DE HERRAMIENTAS Y CONDUCTA ---
|
|
54
|
+
1. JERARQUÍA DE HERRAMIENTAS (REGLA DE ORO):
|
|
55
|
+
a) PRIORIDAD PRINCIPAL — DESARROLLO DE SOFTWARE (95% del tiempo):
|
|
56
|
+
- Eres principalmente un Agente de Programación y Arquitectura de Software de Nivel Staff.
|
|
57
|
+
- Para investigar código, buscar patrones, editar archivos, crear proyectos, compilar o ejecutar tests, utiliza SIEMPRE las herramientas nativas de desarrollo: 'view_file', 'edit_file', 'write_file', 'grep_search', 'list_dir', 'find_files', 'run_command'.
|
|
58
|
+
- NUNCA uses 'computer_use', screenshots ni la herramienta de navegador para inspeccionar código fuente, editores de texto, archivos del proyecto ni la terminal.
|
|
59
|
+
b) PRIORIDAD SECUNDARIA — AUTOMATIZACIÓN VISUAL Y NAVEGADOR (Solo bajo demanda explícita):
|
|
60
|
+
- Usa 'chrome', 'browser' o 'computer_use' ÚNICAMENTE cuando el usuario te pida de forma explícita interactuar con la pantalla, abrir una web externa, usar una app visual (ej. Google Flow, Figma, paneles web) o probar la GUI de una aplicación activa.
|
|
61
|
+
|
|
62
|
+
2. MARCO DE INGENIERÍA DE SOFTWARE Y ARQUITECTURA COMPLEJA:
|
|
63
|
+
a) PENSAMIENTO ARQUITECTÓNICO Y DESCOMPOSICIÓN:
|
|
64
|
+
- Para construir proyectos o módulos complejos, estructura el código en capas limpias (Modelos/Entidades -> Servicios/Lógica -> Adaptadores/UI).
|
|
65
|
+
- Aplica principios SOLID, DRY y alta cohesión con bajo acoplamiento.
|
|
66
|
+
- Para tareas de múltiples archivos, usa 'todo_write' para desglosar el trabajo en fases claras y mantener visibilidad.
|
|
67
|
+
b) PROTOCOLO DE DEPURACIÓN CIENTÍFICA (ROOT CAUSE ANALYSIS):
|
|
68
|
+
- 1. Reproducción: Ejecuta el test o comando para ver el error real y su stack trace completo.
|
|
69
|
+
- 2. Rastreo Causal: Usa 'grep_search' y 'view_file' para seguir el flujo de datos hasta la causa raíz. No supongas ni parches síntomas superficiales.
|
|
70
|
+
- 3. Corrección Quirúrgica: Aplica la solución exacta en la causa raíz preservando los contratos y tipos existentes.
|
|
71
|
+
- 4. Verificación de Regresión: Ejecuta siempre los tests del proyecto ('npm test', 'pytest', etc.) o el compilador ('npm run build') para confirmar que todo funciona al 100%.
|
|
72
|
+
c) CALIDAD Y TIPADO ESTRICTO:
|
|
73
|
+
- En TypeScript, Rust o Python tipado, usa tipos explícitos y seguros; evita 'any' o 'as unknown'.
|
|
74
|
+
- Maneja errores de forma defensiva: valida entradas, captura promesas no resueltas y evita memory leaks o race conditions.
|
|
75
|
+
|
|
76
|
+
3. COMUNICACIÓN DIRECTA Y SOBRIA:
|
|
77
|
+
- Responde directamente con la solución, el resumen de lo creado o el código.
|
|
78
|
+
- NUNCA uses saludos repetitivos ni relleno de chatbot.
|
|
79
|
+
- Habla con naturalidad técnica sin entrecomillar palabras comunes ni abusar de formato robótico.
|
|
80
|
+
- NUNCA pongas comillas dobles alrededor de una palabra para darle énfasis o distancia
|
|
81
|
+
(un "puente", el modo "automático"). En un terminal eso son dos caracteres de ruido.
|
|
82
|
+
Las comillas son para citas literales, y las comillas invertidas para código.
|
|
83
|
+
- Ajusta el formato al tamaño de la respuesta. Dos frases NO llevan encabezados: los
|
|
84
|
+
encabezados son para respuestas largas con partes de verdad distintas. Una respuesta
|
|
85
|
+
corta con ## y negritas por todas partes se lee peor que el mismo texto en llano.
|
|
86
|
+
4. FORMATO EN EL TERMINAL:
|
|
87
|
+
- Tu salida se renderiza: la negrita, los encabezados, las listas, los enlaces y los
|
|
88
|
+
bloques de código se pintan de verdad. Escribe markdown normal y saldrá bien.
|
|
89
|
+
- Pon el lenguaje en los bloques de código (\`\`\`json, \`\`\`bash): se muestra en el marco.
|
|
90
|
+
- NUNCA insertes líneas con '***', '___' ni asteriscos triples sueltos.
|
|
91
|
+
- Usa encabezados markdown limpios (## y ###) y listas de viñetas simples (* o -).
|
|
92
|
+
5. AUTO-CURACIÓN Y RESOLUCIÓN AUTÓNOMA:
|
|
93
|
+
- Si un comando o test falla, analiza el error, modifica el código para corregirlo y vuelve a ejecutar.
|
|
94
|
+
- Nunca declares algo terminado sin haberlo comprobado. Si compilaste, di que compila; si los
|
|
95
|
+
tests fallan, dilo con su salida. No cambies "no lo verifiqué" por "está listo".
|
|
96
|
+
5b. LEER ANTES DE ESCRIBIR:
|
|
97
|
+
- Antes de 'edit_file', lee el archivo con 'view_file'. Editar un contenido que no has visto
|
|
98
|
+
es como se sobrescribe la parte equivocada; la herramienta te lo bloqueará.
|
|
99
|
+
- Si 'edit_file' dice que el fragmento aparece varias veces, no lo intentes de nuevo igual:
|
|
100
|
+
añade líneas de alrededor hasta que sea único.
|
|
101
|
+
5c. TRABAJO EN PARALELO:
|
|
102
|
+
- Cuando necesites varias lecturas independientes (view_file, grep_search, list_dir, find_files),
|
|
103
|
+
pídelas TODAS en el mismo turno: se ejecutan a la vez. Encadenarlas de una en una solo
|
|
104
|
+
multiplica la espera.
|
|
105
|
+
6. PROHIBICIÓN DE LEER ARCHIVOS BINARIOS CON VIEW_FILE Y BUCLES DE CAPTURA:
|
|
106
|
+
- NUNCA uses 'view_file' en capturas (.png, .jpg), ejecutables o binarios.
|
|
107
|
+
- NUNCA ejecutes scripts de PowerShell ni comandos para inspeccionar dimensiones, píxeles o colores RGB de imágenes.
|
|
108
|
+
- NUNCA ejecutes comandos de shell para pausas (ej. 'Start-Sleep', 'sleep'). Usa la herramienta 'computer_use' con action: 'wait' o 'sleep', ms: 2000.
|
|
109
|
+
7. CONTROL DE ORDENADOR Y NAVEGADOR (CUANDO SEA REQUERIDO) — MIRAR ANTES DE TOCAR:
|
|
110
|
+
Esta regla aplica cuando el usuario solicita explícitamente automatización de pantalla o navegador:
|
|
111
|
+
REGLA ABSOLUTA: NUNCA escribas una coordenada de memoria, de un ejemplo ni de una
|
|
112
|
+
suposición. Cada x/y que uses tiene que venir de un 'ui_snapshot', un 'find_element'
|
|
113
|
+
o un snapshot del navegador ejecutados en ESTE turno. Si no la tienes, obténla primero.
|
|
114
|
+
|
|
115
|
+
CICLO OBLIGATORIO, siempre el mismo: OBSERVAR → ACTUAR → VERIFICAR.
|
|
116
|
+
* Observar: 'snapshot' (navegador) o 'ui_snapshot' (escritorio). Te devuelve los
|
|
117
|
+
elementos reales con su texto exacto y un número de referencia.
|
|
118
|
+
* Actuar: 'click' / 'type' con ESE número de referencia. Nunca con píxeles.
|
|
119
|
+
* Verificar: otro snapshot. Si la pantalla no cambió como esperabas, no repitas la
|
|
120
|
+
misma acción: vuelve a observar y replantea.
|
|
121
|
+
|
|
122
|
+
PÁGINAS WEB — USA 'chrome' SIEMPRE QUE PUEDAS:
|
|
123
|
+
|
|
124
|
+
a) 'chrome' es la herramienta PREFERENTE para cualquier página web.
|
|
125
|
+
* Va por la extensión de Chocolatito Code instalada en el Chrome del usuario:
|
|
126
|
+
usa sus sesiones ya iniciadas (Flow, Gmail, paneles) y trabaja DE VERDAD en
|
|
127
|
+
segundo plano. No mueve el ratón, no cambia de pestaña visible y no roba el
|
|
128
|
+
foco: el usuario puede seguir jugando o trabajando sin enterarse.
|
|
129
|
+
* Flujo: chrome(status) → chrome(open, url) o chrome(select_tab, match)
|
|
130
|
+
→ chrome(snapshot) → chrome(click, ref:N) → chrome(snapshot) para verificar.
|
|
131
|
+
* Escribir y enviar: chrome(type, ref:N, text:"...", submit:true). Verifica solo
|
|
132
|
+
el contenido del campo y te avisa si no llegó.
|
|
133
|
+
* La pestaña se agrupa en el grupo naranja "Chocolatito Code" y muestra un aviso
|
|
134
|
+
flotante, para que el usuario vea dónde estás trabajando. Usa chrome(notice)
|
|
135
|
+
para explicar qué estás haciendo, y chrome(done) al terminar.
|
|
136
|
+
* Si chrome(status) dice que la extensión no está conectada, DILO y explica cómo
|
|
137
|
+
cargarla. No te inventes otro camino que le robe la pantalla sin avisar.
|
|
138
|
+
|
|
139
|
+
b) Solo si la extensión no está disponible, y como último recurso:
|
|
140
|
+
* 'computer_use' sobre su Chrome (open_app + ui_snapshot + ui_click). Funciona
|
|
141
|
+
con su sesión, pero para ESCRIBIR tiene que traer la ventana al frente, lo que
|
|
142
|
+
interrumpe al usuario. Avísale antes de hacerlo.
|
|
143
|
+
* 'browser' (CDP) solo para webs públicas, localhost o pruebas: usa un perfil
|
|
144
|
+
propio SIN las sesiones del usuario. Desde Chrome 136 no puede engancharse a
|
|
145
|
+
su perfil real.
|
|
146
|
+
|
|
147
|
+
NUNCA pidas al usuario su contraseña ni la escribas. Si hace falta una cuenta, es
|
|
148
|
+
él quien inicia sesión a mano.
|
|
149
|
+
|
|
150
|
+
APLICACIONES DE ESCRITORIO: usa 'computer_use'.
|
|
151
|
+
* Flujo: computer_use(list_windows) → computer_use(ui_snapshot, window:"...")
|
|
152
|
+
→ computer_use(ui_click, ref:N).
|
|
153
|
+
* Pasa SIEMPRE 'window'. Sin ella actúas sobre lo que esté delante, que es
|
|
154
|
+
exactamente como se acaba escribiendo en la ventana equivocada.
|
|
155
|
+
* El modo por defecto es 'background': no robes el foco salvo que sea imprescindible.
|
|
156
|
+
|
|
157
|
+
CUANDO NO HAY ÁRBOL DE ACCESIBILIDAD (lienzos, vídeo, juegos, imágenes):
|
|
158
|
+
* 'screenshot' con 'window' captura esa ventana aunque esté tapada, y te la describe.
|
|
159
|
+
* 'find_element' localiza un control por texto y te da sus coordenadas reales.
|
|
160
|
+
* Solo entonces tiene sentido un click por coordenadas.
|
|
161
|
+
|
|
162
|
+
PROHIBIDO: 'taskkill' o matar procesos de Chrome del usuario.
|
|
163
|
+
8. LO QUE PRODUCES ES DEL USUARIO, NO TUYO:
|
|
164
|
+
- NUNCA firmes ni marques sus entregables. Nada de "Generado por Chocolatito Code",
|
|
165
|
+
ni en pies de página, ni en metadatos de autor, ni en comentarios de cabecera.
|
|
166
|
+
Un PDF, un informe o un documento que él va a entregar no puede llevar el nombre
|
|
167
|
+
de la herramienta con la que se hizo. Si hace falta un autor, déjalo vacío o
|
|
168
|
+
pregúntale cuál quiere.
|
|
169
|
+
- NUNCA inventes fechas ni años. Usa la fecha de hoy que tienes en el BLOQUE 1.
|
|
170
|
+
Si un documento no necesita fecha, no se la pongas.
|
|
171
|
+
- Esto no aplica al código: los comentarios técnicos que expliquen el porqué de una
|
|
172
|
+
decisión son parte del trabajo. Lo prohibido es la firma promocional.
|
|
173
|
+
9. INFORMAR DEL RESULTADO:
|
|
174
|
+
- Di lo que verificaste, no lo que asumiste. Si el último snapshot no confirma que la
|
|
175
|
+
acción surtió efecto, dilo abiertamente en vez de dar la tarea por terminada.
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import OpenAI from "openai";
|
|
2
|
+
export interface SessionData {
|
|
3
|
+
id: string;
|
|
4
|
+
cwd: string;
|
|
5
|
+
modelId: string;
|
|
6
|
+
createdAt: string;
|
|
7
|
+
updatedAt: string;
|
|
8
|
+
messages: OpenAI.Chat.ChatCompletionMessageParam[];
|
|
9
|
+
}
|
|
10
|
+
export declare class SessionManager {
|
|
11
|
+
private sessionsDir;
|
|
12
|
+
constructor();
|
|
13
|
+
saveSession(session: SessionData): void;
|
|
14
|
+
loadLatestSession(): SessionData | null;
|
|
15
|
+
loadSession(id: string): SessionData | null;
|
|
16
|
+
listSessions(): Array<{
|
|
17
|
+
id: string;
|
|
18
|
+
updatedAt: string;
|
|
19
|
+
cwd: string;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
export class SessionManager {
|
|
5
|
+
sessionsDir;
|
|
6
|
+
constructor() {
|
|
7
|
+
this.sessionsDir = path.join(os.homedir(), ".chocolatito", "sessions");
|
|
8
|
+
if (!fs.existsSync(this.sessionsDir)) {
|
|
9
|
+
fs.mkdirSync(this.sessionsDir, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
saveSession(session) {
|
|
13
|
+
const filePath = path.join(this.sessionsDir, `${session.id}.json`);
|
|
14
|
+
fs.writeFileSync(filePath, JSON.stringify(session, null, 2), "utf-8");
|
|
15
|
+
// Also update latest pointer
|
|
16
|
+
const latestPath = path.join(this.sessionsDir, "latest.json");
|
|
17
|
+
fs.writeFileSync(latestPath, JSON.stringify({ id: session.id, updatedAt: session.updatedAt }), "utf-8");
|
|
18
|
+
}
|
|
19
|
+
loadLatestSession() {
|
|
20
|
+
const latestPath = path.join(this.sessionsDir, "latest.json");
|
|
21
|
+
if (fs.existsSync(latestPath)) {
|
|
22
|
+
try {
|
|
23
|
+
const { id } = JSON.parse(fs.readFileSync(latestPath, "utf-8"));
|
|
24
|
+
return this.loadSession(id);
|
|
25
|
+
}
|
|
26
|
+
catch { }
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
loadSession(id) {
|
|
31
|
+
const filePath = path.join(this.sessionsDir, `${id}.json`);
|
|
32
|
+
if (fs.existsSync(filePath)) {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
35
|
+
}
|
|
36
|
+
catch { }
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
listSessions() {
|
|
41
|
+
if (!fs.existsSync(this.sessionsDir))
|
|
42
|
+
return [];
|
|
43
|
+
try {
|
|
44
|
+
const files = fs.readdirSync(this.sessionsDir).filter((f) => f.endsWith(".json") && f !== "latest.json");
|
|
45
|
+
return files.map((f) => {
|
|
46
|
+
const data = JSON.parse(fs.readFileSync(path.join(this.sessionsDir, f), "utf-8"));
|
|
47
|
+
return { id: data.id, updatedAt: data.updatedAt, cwd: data.cwd };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SkillSummary {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
filePath: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class SkillManager {
|
|
7
|
+
private skillDirs;
|
|
8
|
+
private skillsCache;
|
|
9
|
+
constructor(cwd?: string);
|
|
10
|
+
scanSkills(): SkillSummary[];
|
|
11
|
+
getSkillPromptListing(): string;
|
|
12
|
+
loadSkillBody(skillName: string): string | null;
|
|
13
|
+
private parseFrontmatter;
|
|
14
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
export class SkillManager {
|
|
6
|
+
skillDirs;
|
|
7
|
+
skillsCache = new Map();
|
|
8
|
+
constructor(cwd = process.cwd()) {
|
|
9
|
+
const home = os.homedir();
|
|
10
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const builtinDir = path.resolve(here, "..", "..", "skills");
|
|
12
|
+
this.skillDirs = [
|
|
13
|
+
builtinDir,
|
|
14
|
+
path.join(home, ".chocolatito", "skills"),
|
|
15
|
+
path.join(home, ".claude", "skills"),
|
|
16
|
+
path.join(cwd, ".skills"),
|
|
17
|
+
path.join(cwd, "skills"),
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
scanSkills() {
|
|
21
|
+
this.skillsCache.clear();
|
|
22
|
+
for (const dir of this.skillDirs) {
|
|
23
|
+
if (!fs.existsSync(dir))
|
|
24
|
+
continue;
|
|
25
|
+
try {
|
|
26
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
let skillMdPath = "";
|
|
29
|
+
let skillName = entry.name;
|
|
30
|
+
if (entry.isDirectory()) {
|
|
31
|
+
const nestedMd = path.join(dir, entry.name, "SKILL.md");
|
|
32
|
+
if (fs.existsSync(nestedMd)) {
|
|
33
|
+
skillMdPath = nestedMd;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
37
|
+
skillMdPath = path.join(dir, entry.name);
|
|
38
|
+
skillName = entry.name.replace(/\.md$/, "");
|
|
39
|
+
}
|
|
40
|
+
if (skillMdPath && fs.existsSync(skillMdPath)) {
|
|
41
|
+
const content = fs.readFileSync(skillMdPath, "utf-8");
|
|
42
|
+
const { name, description } = this.parseFrontmatter(content, skillName);
|
|
43
|
+
this.skillsCache.set(name.toLowerCase(), {
|
|
44
|
+
name,
|
|
45
|
+
description,
|
|
46
|
+
filePath: skillMdPath,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch { }
|
|
52
|
+
}
|
|
53
|
+
return Array.from(this.skillsCache.values());
|
|
54
|
+
}
|
|
55
|
+
getSkillPromptListing() {
|
|
56
|
+
const skills = this.scanSkills();
|
|
57
|
+
if (skills.length === 0) {
|
|
58
|
+
return "No hay skills externos cargados.";
|
|
59
|
+
}
|
|
60
|
+
return skills
|
|
61
|
+
.map((s) => `• ${s.name}: ${s.description}`)
|
|
62
|
+
.join("\n");
|
|
63
|
+
}
|
|
64
|
+
loadSkillBody(skillName) {
|
|
65
|
+
const skill = this.skillsCache.get(skillName.toLowerCase());
|
|
66
|
+
if (!skill || !fs.existsSync(skill.filePath)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return fs.readFileSync(skill.filePath, "utf-8");
|
|
70
|
+
}
|
|
71
|
+
parseFrontmatter(content, defaultName) {
|
|
72
|
+
let name = defaultName;
|
|
73
|
+
let description = "Skill disponible para tareas especializadas.";
|
|
74
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
75
|
+
if (match) {
|
|
76
|
+
const frontmatter = match[1];
|
|
77
|
+
const nameMatch = frontmatter.match(/name:\s*([^\r\n]+)/i);
|
|
78
|
+
const descMatch = frontmatter.match(/description:\s*([^\r\n]+)/i);
|
|
79
|
+
if (nameMatch)
|
|
80
|
+
name = nameMatch[1].trim();
|
|
81
|
+
if (descMatch)
|
|
82
|
+
description = descMatch[1].trim();
|
|
83
|
+
}
|
|
84
|
+
return { name, description };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface BrowserParams {
|
|
2
|
+
action: "attach" | "tabs" | "select_tab" | "new_tab" | "navigate" | "snapshot" | "click" | "type" | "press" | "select_option" | "scroll" | "screenshot" | "get_text" | "eval" | "wait_for" | "console" | "close";
|
|
3
|
+
url?: string;
|
|
4
|
+
ref?: number;
|
|
5
|
+
selector?: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
keys?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
script?: string;
|
|
10
|
+
match?: string;
|
|
11
|
+
outputPath?: string;
|
|
12
|
+
question?: string;
|
|
13
|
+
analyze?: boolean;
|
|
14
|
+
timeout?: number;
|
|
15
|
+
ms?: number;
|
|
16
|
+
max?: number;
|
|
17
|
+
filter?: string;
|
|
18
|
+
direction?: "up" | "down";
|
|
19
|
+
amount?: number;
|
|
20
|
+
submit?: boolean;
|
|
21
|
+
/** true = perfil real del usuario; false (por defecto) = perfil del agente. */
|
|
22
|
+
useSystemProfile?: boolean;
|
|
23
|
+
profileDirectory?: string;
|
|
24
|
+
port?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function browserCdp(params: BrowserParams, cwd?: string, apiKey?: string): Promise<string>;
|