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
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# 🦊 Chocolatito Code (v1.0.0)
|
|
2
|
+
|
|
3
|
+
> **Agente Autónomo de Programación para la Terminal**, desarrollado por **Chocolatito** con la arquitectura del **Motor Espectro**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ⚡ Niveles de Potencia y Esfuerzo (/effort)
|
|
8
|
+
|
|
9
|
+
Chocolatito Code te permite regular dinámicamente la profundidad y potencia del motor según la complejidad de la tarea:
|
|
10
|
+
|
|
11
|
+
| Nivel | Nombre | Nivel de Esfuerzo | Uso Recomendado |
|
|
12
|
+
| :--- | :--- | :---: | :--- |
|
|
13
|
+
| Nivel | Modelo real | Uso recomendado |
|
|
14
|
+
| :--- | :--- | :--- |
|
|
15
|
+
| **`1.0`** Ágil | `deepseek-v4-flash` | Tareas cotidianas, funciones y scripts directos. |
|
|
16
|
+
| **`1.5`** Avanzado | `deepseek-v4-flash` | Refactorizaciones, con más margen creativo. |
|
|
17
|
+
| **`2.0`** Razonamiento Pro | `deepseek-v4-pro` | Bugs difíciles, algoritmos y arquitectura. |
|
|
18
|
+
| **`2.5`** MAX | `deepseek-v4-pro` | Proyectos completos y exploración amplia. |
|
|
19
|
+
|
|
20
|
+
Ventana de contexto: **1.000.000 de tokens** en los cuatro niveles.
|
|
21
|
+
|
|
22
|
+
Para cambiar de nivel dentro de la sesión, escribe:
|
|
23
|
+
```bash
|
|
24
|
+
/effort 2.0
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🛠️ Herramientas Nativas Autónomas
|
|
30
|
+
|
|
31
|
+
- 👁️ `view_file`: Lectura precisa con numeración de líneas.
|
|
32
|
+
- ✏️ `edit_file`: Modificación de código con diffs visuales tipo Git (verde/rojo).
|
|
33
|
+
- 📄 `write_file`: Creación y sobreescritura de archivos y directorios.
|
|
34
|
+
- 💻 `run_command`: Ejecución de comandos en PowerShell/Bash con captura de logs.
|
|
35
|
+
- 📂 `list_dir`: Exploración de proyectos respetando `.gitignore`.
|
|
36
|
+
- 🔍 `grep_search`: Búsqueda instantánea de texto y regex.
|
|
37
|
+
- 🌐 `chrome`: Controla **tu** Chrome desde dentro, con tus sesiones iniciadas y en segundo
|
|
38
|
+
plano real (requiere la extensión: ver `extension/README.md`).
|
|
39
|
+
- 🖥️ `computer_use`: Aplicaciones de escritorio por árbol de accesibilidad, sin adivinar píxeles.
|
|
40
|
+
- 🧭 `browser`: Navegador propio por CDP, para webs públicas y `localhost`.
|
|
41
|
+
|
|
42
|
+
Las lecturas independientes lanzadas en el mismo turno se ejecutan **en paralelo**.
|
|
43
|
+
|
|
44
|
+
## 🔌 MCP (Model Context Protocol)
|
|
45
|
+
|
|
46
|
+
Conecta cualquier servidor MCP y sus herramientas quedan disponibles para el agente.
|
|
47
|
+
Configuración compatible con Claude Code en `.mcp.json` (ver `.mcp.json.ejemplo`):
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{ "mcpServers": { "github": {
|
|
51
|
+
"command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"],
|
|
52
|
+
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" } } } }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Las herramientas aparecen como `mcp__<servidor>__<herramienta>`. Usa `/mcp` para ver el estado.
|
|
56
|
+
|
|
57
|
+
## 🪝 Hooks
|
|
58
|
+
|
|
59
|
+
Reglas propias que el agente no puede saltarse, en `.chocolatito/settings.json`:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{ "hooks": { "PreToolUse": [ { "matcher": "run_command",
|
|
63
|
+
"hooks": [{ "type": "command", "command": "node .chocolatito/hooks/guardia.mjs" }] } ] } }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
El hook recibe el evento por stdin como JSON y puede **denegar**, **pedir confirmación** o
|
|
67
|
+
**reescribir los argumentos** antes de que la herramienta se ejecute. Salir con código 2
|
|
68
|
+
bloquea directamente.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## 🔐 Permisos
|
|
72
|
+
|
|
73
|
+
Una sola regla: **mirar es gratis, actuar se pregunta.**
|
|
74
|
+
|
|
75
|
+
| Acción | Se pregunta |
|
|
76
|
+
| :--- | :--- |
|
|
77
|
+
| `ui_snapshot`, `list_windows`, `snapshot`, `screenshot`, `get_text`, `tabs` | No. Es el paso previo obligatorio de todo. |
|
|
78
|
+
| Clic, escritura, navegación o JavaScript sobre tu ordenador o tu Chrome | **Siempre**, también en `acceptEdits`. |
|
|
79
|
+
| `run_command`, escritura y borrado de archivos | Sí, salvo patrón autorizado. |
|
|
80
|
+
|
|
81
|
+
### Cambiar de modo con `shift+tab`
|
|
82
|
+
|
|
83
|
+
Funciona **en cualquier momento**: en el prompt, a mitad de una generación y dentro del
|
|
84
|
+
propio diálogo de permiso (ahí además aprueba la acción pendiente).
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
normal → acepta ediciones → automático → normal
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- **normal** — pregunta antes de cada acción con consecuencias.
|
|
91
|
+
- **acepta ediciones** — escribe archivos sin preguntar; sigue preguntando por comandos y
|
|
92
|
+
por el control del ordenador.
|
|
93
|
+
- **automático** — no pregunta nada.
|
|
94
|
+
|
|
95
|
+
El **modo plan** se activa aparte, con `/plan`, para no dejarlo a un golpe de tecla. Es
|
|
96
|
+
solo lectura de verdad: ni comandos, ni clics, ni escrituras.
|
|
97
|
+
|
|
98
|
+
`--yes` aprueba todo sin preguntar: es para CI, no para el día a día.
|
|
99
|
+
|
|
100
|
+
## ⌨️ Escribir mientras trabaja
|
|
101
|
+
|
|
102
|
+
No hace falta esperar a que termine. Lo que escribas durante una generación aparece bajo
|
|
103
|
+
el spinner y, al pulsar Enter, queda en cola: el agente acaba su turno y lo toma como
|
|
104
|
+
siguiente orden, sin que tengas que volver a teclearlo.
|
|
105
|
+
|
|
106
|
+
`Esc` pausa el turno en curso. `Ctrl+C` una vez interrumpe; dos veces cierra la sesión.
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 🔑 Licencia
|
|
112
|
+
|
|
113
|
+
Al abrirlo por primera vez pide la clave que recibiste por correo al comprar:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
🔑 ACTIVACIÓN — CHOCOLATITO CODE
|
|
117
|
+
Licencia ❯ 38b1460a-5104-4067-a91d-77b872934d51
|
|
118
|
+
✔ Licencia activada para tu@correo.com
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Se guarda en `~/.chocolatitorc` y no vuelve a pedirla. Una clave sirve para **3 equipos**.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
/licencia # ver la licencia activa y en qué equipo estás
|
|
125
|
+
/licencia liberar # soltar este equipo para usar la clave en otro
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Si cambias de ordenador o formateas, libera el equipo antes. Si ya no puedes,
|
|
129
|
+
escribe al soporte y se libera desde el panel.
|
|
130
|
+
|
|
131
|
+
Se comprueba una vez al día. Si algún día no hay conexión, **sigues trabajando**:
|
|
132
|
+
hay 7 días de margen antes de pedirte que te conectes.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 📦 Instalación
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npm install -g chocolatito-code
|
|
140
|
+
chocolatito --version
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Requiere **Node.js 20 o superior**. La primera vez pide la API key y la guarda en
|
|
144
|
+
`~/.chocolatitorc`; también se puede pasar por `CHOCOLATITO_API_KEY` o por un `.env` del
|
|
145
|
+
proyecto.
|
|
146
|
+
|
|
147
|
+
Para desarrollar sobre el propio proyecto:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npm install && npm run build && npm link
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 🚀 Uso Rápido
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Iniciar sesión interactiva
|
|
159
|
+
chocolatito
|
|
160
|
+
|
|
161
|
+
# O ejecutar una orden directa
|
|
162
|
+
chocolatito "crea una API REST con Node.js y Express"
|
|
163
|
+
|
|
164
|
+
# Modo no interactivo: aprueba las acciones sin preguntar
|
|
165
|
+
chocolatito --yes "ejecuta los tests y arregla lo que falle"
|
|
166
|
+
|
|
167
|
+
# Ayuda y versión, sin gastar tokens
|
|
168
|
+
chocolatito --help
|
|
169
|
+
chocolatito --version
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 🧪 Pruebas
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npm run build && npm test
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## 📚 Documentación
|
|
179
|
+
|
|
180
|
+
- `MEJORAS.md` — auditoría del núcleo y de permisos: qué estaba roto, qué se arregló y cómo se comprobó.
|
|
181
|
+
- `COMPUTER-USE.md` — diseño del control de ordenador y navegador.
|
|
182
|
+
- `extension/README.md` — instalación de la extensión de Chrome.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
Desarrollado con pasión por **Chocolatito**. 🦊⚡
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { execa } from "execa";
|
|
4
|
+
import { RULES_FILE_NAME } from "../config/constants.js";
|
|
5
|
+
export async function getProjectContext(cwd = process.cwd()) {
|
|
6
|
+
let rulesContent = null;
|
|
7
|
+
// 1. Look for CHOCOLATITO.md or CLAUDE.md
|
|
8
|
+
const rulesPath = path.join(cwd, RULES_FILE_NAME);
|
|
9
|
+
const fallbackClaudePath = path.join(cwd, "CLAUDE.md");
|
|
10
|
+
if (fs.existsSync(rulesPath)) {
|
|
11
|
+
try {
|
|
12
|
+
rulesContent = fs.readFileSync(rulesPath, "utf-8");
|
|
13
|
+
}
|
|
14
|
+
catch { }
|
|
15
|
+
}
|
|
16
|
+
else if (fs.existsSync(fallbackClaudePath)) {
|
|
17
|
+
try {
|
|
18
|
+
rulesContent = fs.readFileSync(fallbackClaudePath, "utf-8");
|
|
19
|
+
}
|
|
20
|
+
catch { }
|
|
21
|
+
}
|
|
22
|
+
// 2. Git branch & status detection
|
|
23
|
+
let gitBranch = null;
|
|
24
|
+
try {
|
|
25
|
+
const { stdout: branchOut } = await execa("git", ["branch", "--show-current"], { cwd });
|
|
26
|
+
if (branchOut && branchOut.trim()) {
|
|
27
|
+
const branchName = branchOut.trim();
|
|
28
|
+
const { stdout: statusOut } = await execa("git", ["status", "--porcelain"], { cwd });
|
|
29
|
+
const changedFiles = statusOut ? statusOut.trim().split("\n").filter(Boolean).length : 0;
|
|
30
|
+
gitBranch = changedFiles > 0 ? `${branchName} (${changedFiles} archivos modificados)` : `${branchName} (limpio)`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch { }
|
|
34
|
+
// 3. Comprehensive project type & available scripts detection
|
|
35
|
+
let projectType = "Desconocido / Genérico";
|
|
36
|
+
const availableScripts = [];
|
|
37
|
+
const pkgJsonPath = path.join(cwd, "package.json");
|
|
38
|
+
const pyProjectPath = path.join(cwd, "pyproject.toml");
|
|
39
|
+
const reqTxtPath = path.join(cwd, "requirements.txt");
|
|
40
|
+
const cargoPath = path.join(cwd, "Cargo.toml");
|
|
41
|
+
const goModPath = path.join(cwd, "go.mod");
|
|
42
|
+
const pubspecPath = path.join(cwd, "pubspec.yaml");
|
|
43
|
+
const gradlePath = path.join(cwd, "build.gradle");
|
|
44
|
+
const pomPath = path.join(cwd, "pom.xml");
|
|
45
|
+
const cmakePath = path.join(cwd, "CMakeLists.txt");
|
|
46
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
47
|
+
try {
|
|
48
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
49
|
+
const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
|
|
50
|
+
const tech = [];
|
|
51
|
+
if (deps.react)
|
|
52
|
+
tech.push("React");
|
|
53
|
+
if (deps.next)
|
|
54
|
+
tech.push("Next.js");
|
|
55
|
+
if (deps.remotion)
|
|
56
|
+
tech.push("Remotion");
|
|
57
|
+
if (deps.vue)
|
|
58
|
+
tech.push("Vue");
|
|
59
|
+
if (deps.svelte)
|
|
60
|
+
tech.push("Svelte");
|
|
61
|
+
if (deps.express)
|
|
62
|
+
tech.push("Express");
|
|
63
|
+
if (deps.fastify)
|
|
64
|
+
tech.push("Fastify");
|
|
65
|
+
if (deps.nest || deps["@nestjs/core"])
|
|
66
|
+
tech.push("NestJS");
|
|
67
|
+
if (deps.typescript)
|
|
68
|
+
tech.push("TypeScript");
|
|
69
|
+
if (deps.tailwindcss)
|
|
70
|
+
tech.push("Tailwind CSS");
|
|
71
|
+
projectType = `Node.js / JavaScript${tech.length > 0 ? ` (${tech.join(", ")})` : ""}`;
|
|
72
|
+
if (pkg.scripts) {
|
|
73
|
+
Object.keys(pkg.scripts).forEach((k) => availableScripts.push(`npm run ${k}`));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch { }
|
|
77
|
+
}
|
|
78
|
+
else if (fs.existsSync(pyProjectPath) || fs.existsSync(reqTxtPath)) {
|
|
79
|
+
let framework = "";
|
|
80
|
+
try {
|
|
81
|
+
const content = (fs.existsSync(reqTxtPath) ? fs.readFileSync(reqTxtPath, "utf-8") : "") +
|
|
82
|
+
(fs.existsSync(pyProjectPath) ? fs.readFileSync(pyProjectPath, "utf-8") : "");
|
|
83
|
+
if (content.includes("fastapi"))
|
|
84
|
+
framework = " (FastAPI)";
|
|
85
|
+
else if (content.includes("django"))
|
|
86
|
+
framework = " (Django)";
|
|
87
|
+
else if (content.includes("flask"))
|
|
88
|
+
framework = " (Flask)";
|
|
89
|
+
else if (content.includes("torch"))
|
|
90
|
+
framework = " (PyTorch)";
|
|
91
|
+
}
|
|
92
|
+
catch { }
|
|
93
|
+
projectType = `Python${framework}`;
|
|
94
|
+
availableScripts.push("python main.py", "pytest");
|
|
95
|
+
}
|
|
96
|
+
else if (fs.existsSync(cargoPath)) {
|
|
97
|
+
projectType = "Rust (Cargo)";
|
|
98
|
+
availableScripts.push("cargo build", "cargo test", "cargo run");
|
|
99
|
+
}
|
|
100
|
+
else if (fs.existsSync(goModPath)) {
|
|
101
|
+
projectType = "Go (Golang)";
|
|
102
|
+
availableScripts.push("go build", "go test", "go run .");
|
|
103
|
+
}
|
|
104
|
+
else if (fs.existsSync(pubspecPath)) {
|
|
105
|
+
projectType = "Flutter / Dart";
|
|
106
|
+
availableScripts.push("flutter run", "flutter test");
|
|
107
|
+
}
|
|
108
|
+
else if (fs.existsSync(gradlePath) || fs.existsSync(pomPath)) {
|
|
109
|
+
projectType = "Java / Kotlin (JVM)";
|
|
110
|
+
}
|
|
111
|
+
else if (fs.existsSync(cmakePath)) {
|
|
112
|
+
projectType = "C / C++ (CMake)";
|
|
113
|
+
}
|
|
114
|
+
const osName = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
|
|
115
|
+
return {
|
|
116
|
+
cwd,
|
|
117
|
+
os: osName,
|
|
118
|
+
rulesContent,
|
|
119
|
+
gitBranch,
|
|
120
|
+
projectType,
|
|
121
|
+
availableScripts,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare class FileTracker {
|
|
2
|
+
private seen;
|
|
3
|
+
private key;
|
|
4
|
+
/** Se llama tras leer un archivo con exito. */
|
|
5
|
+
markRead(filePath: string, cwd: string): void;
|
|
6
|
+
/** Se llama tras escribir, para que la siguiente edicion no se queje. */
|
|
7
|
+
markWritten(filePath: string, cwd: string): void;
|
|
8
|
+
forget(filePath: string, cwd: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Devuelve un aviso si editar este archivo ahora seria arriesgado, o null si
|
|
11
|
+
* todo esta en orden.
|
|
12
|
+
*/
|
|
13
|
+
checkBeforeEdit(filePath: string, cwd: string): string | null;
|
|
14
|
+
}
|
|
15
|
+
export declare const fileTracker: FileTracker;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
class FileTracker {
|
|
4
|
+
seen = new Map();
|
|
5
|
+
key(filePath, cwd) {
|
|
6
|
+
const abs = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
|
|
7
|
+
return path.normalize(abs).toLowerCase();
|
|
8
|
+
}
|
|
9
|
+
/** Se llama tras leer un archivo con exito. */
|
|
10
|
+
markRead(filePath, cwd) {
|
|
11
|
+
try {
|
|
12
|
+
const abs = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
|
|
13
|
+
const st = fs.statSync(abs);
|
|
14
|
+
this.seen.set(this.key(filePath, cwd), { mtimeMs: st.mtimeMs, size: st.size });
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Si no se puede medir, no se registra: mejor pedir lectura de nuevo.
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Se llama tras escribir, para que la siguiente edicion no se queje. */
|
|
21
|
+
markWritten(filePath, cwd) {
|
|
22
|
+
this.markRead(filePath, cwd);
|
|
23
|
+
}
|
|
24
|
+
forget(filePath, cwd) {
|
|
25
|
+
this.seen.delete(this.key(filePath, cwd));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Devuelve un aviso si editar este archivo ahora seria arriesgado, o null si
|
|
29
|
+
* todo esta en orden.
|
|
30
|
+
*/
|
|
31
|
+
checkBeforeEdit(filePath, cwd) {
|
|
32
|
+
const abs = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
|
|
33
|
+
if (!fs.existsSync(abs))
|
|
34
|
+
return null;
|
|
35
|
+
const record = this.seen.get(this.key(filePath, cwd));
|
|
36
|
+
if (!record) {
|
|
37
|
+
return (`No has leido "${filePath}" en esta sesion. Usa view_file antes de editarlo: ` +
|
|
38
|
+
`editar un contenido que no has visto es como se sobrescribe la parte equivocada.`);
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const st = fs.statSync(abs);
|
|
42
|
+
if (st.mtimeMs > record.mtimeMs + 1 || st.size !== record.size) {
|
|
43
|
+
return (`"${filePath}" cambio despues de que lo leyeras (otro proceso, el usuario o un formateador). ` +
|
|
44
|
+
`Vuelve a leerlo con view_file antes de editar, o perderas esos cambios.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export const fileTracker = new FileTracker();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import OpenAI from "openai";
|
|
2
|
+
import { TokenTracker } from "./tracker.js";
|
|
3
|
+
import { EspectroModel } from "../config/constants.js";
|
|
4
|
+
import { PermissionManager } from "../config/permissions.js";
|
|
5
|
+
import { HookManager } from "../hooks/manager.js";
|
|
6
|
+
export declare class AgentLoop {
|
|
7
|
+
private client;
|
|
8
|
+
private currentEspectro;
|
|
9
|
+
messages: OpenAI.Chat.ChatCompletionMessageParam[];
|
|
10
|
+
tracker: TokenTracker;
|
|
11
|
+
currentCwd: string;
|
|
12
|
+
permissions: PermissionManager;
|
|
13
|
+
hooks: HookManager;
|
|
14
|
+
private apiKey;
|
|
15
|
+
private baseURL;
|
|
16
|
+
private maxIterations;
|
|
17
|
+
constructor(apiKey: string, baseURL: string, initialModel: EspectroModel, systemPrompt: string);
|
|
18
|
+
setEspectroModel(model: EspectroModel, updatedSystemPrompt?: string): void;
|
|
19
|
+
getEspectroModel(): EspectroModel;
|
|
20
|
+
clearHistory(systemPrompt: string): void;
|
|
21
|
+
compactHistory(systemPrompt: string): Promise<string>;
|
|
22
|
+
lastTurnTokens: number;
|
|
23
|
+
autoCompactIfNeeded(): Promise<boolean>;
|
|
24
|
+
runTask(userPrompt: string): Promise<void>;
|
|
25
|
+
}
|