Spaces:
Running
Running
| // Registro de herramientas de Elffuss Code: proyecto abierto + shell + web. | |
| import * as code from './code.js'; | |
| import * as shell from '../shell.js'; | |
| import * as web from './web.js'; | |
| export { code }; | |
| // El terminal (UI) se engancha aquí para reflejar lo que ejecuta la elfa. | |
| let onTerminalEcho = () => {}; | |
| export function setTerminalEcho(fn) { onTerminalEcho = fn; } | |
| export const TOOLS = { | |
| 'code.tree': { desc: 'Ver el árbol de archivos del proyecto', params: { path: 'subcarpeta (opcional)', depth: 'niveles (3)' }, run: a => code.tree(a) }, | |
| 'code.read': { desc: 'Leer un archivo del proyecto. Sin más parámetros, lo lee ENTERO. Para ficheros grandes, pagina de 100 en 100 líneas con offset (offset:101 = siguiente página tras la primera). Para ir directo a donde dio un resultado de code.search (que ya incluye número de línea), usa around:N — trae ~100 líneas centradas en la línea N, con cada línea numerada (N→contenido) para poder citarla o editarla con precisión', params: { path: 'ruta relativa', offset: 'línea 1-based donde empezar (opcional)', limit: 'líneas a devolver, 100 por defecto (opcional)', around: 'centra la página en esta línea, p.ej. la que dio code.search (opcional)' }, run: a => code.read(a) }, | |
| 'code.write': { desc: 'Escribir/crear un archivo (contenido COMPLETO; se refleja al instante en el editor). Para cambios PEQUEÑOS en un fichero YA existente, usa mejor code.edit', params: { path: 'ruta', content: 'contenido íntegro' }, run: a => code.write(a) }, | |
| 'code.edit': { desc: 'Editar PARTE de un fichero existente sin reescribirlo entero: sustituye "search" (copia literal de unas pocas líneas, con contexto suficiente para ser única en el fichero) por "replace". Preferible a code.write para cambios pequeños/medianos — más rápido y sin riesgo de perder el resto del fichero. Si falla (no encuentra el punto con confianza), relee el fichero y reintenta con un search más ajustado', params: { path: 'ruta', search: 'texto exacto a sustituir', replace: 'texto nuevo' }, run: a => code.edit(a) }, | |
| 'code.search': { desc: 'Buscar texto en el proyecto (grep)', params: { query: 'texto', ext: 'filtro extensión (opcional)' }, run: a => code.search(a) }, | |
| 'terminal.run': { desc: 'Ejecutar un comando de shell sobre los ficheros del proyecto (ls, cat, grep, find, mkdir, echo>fichero, git status…). node/npm/python REALES si el usuario tiene un Bridge local conectado (⚙ Ajustes → 🔌 Bridge local); si no está conectado, el propio resultado lo indica', params: { command: 'la línea de comando' }, run: async a => { const out = await shell.runForAgent(a.command || ''); onTerminalEcho(a.command || '', out); return out; } }, | |
| 'web.search': { desc: 'Buscar en internet (docs, errores, APIs) — devuelve títulos, URLs y fragmentos', params: { query: 'qué buscar' }, run: a => web.search(a) }, | |
| 'web.fetch': { desc: 'Leer el contenido de texto de una URL (documentación, referencia)', params: { url: 'https://…' }, run: a => web.fetchUrl(a) }, | |
| }; | |
| export function toolHelp() { | |
| return Object.entries(TOOLS).map(([n, t]) => | |
| `- ${n}(${Object.keys(t.params).join(', ')}): ${t.desc}`).join('\n'); | |
| } | |
| export async function runTool(name, args) { | |
| const tool = TOOLS[name]; | |
| if (!tool) throw new Error(`Herramienta desconocida: ${name}`); | |
| return tool.run(args || {}); | |
| } | |
| // CONTEXTO AHORA del IDE: proyecto, archivo abierto y árbol resumido. | |
| export async function snapshot() { | |
| const { projectName, currentFile } = code.current(); | |
| const parts = [ | |
| 'Fecha y hora: ' + new Date().toLocaleString(), | |
| 'Proyecto abierto: ' + (projectName || 'ninguno'), | |
| 'Archivo abierto en el editor: ' + (currentFile || 'ninguno'), | |
| ]; | |
| try { parts.push('Árbol del proyecto (resumen):\n' + await code.tree({ depth: 2 })); } | |
| catch { /* aún sin proyecto */ } | |
| // GROUNDING: incluye el contenido REAL de los archivos clave (README, config) | |
| // para que el modelo NO alucine sobre el proyecto — el heal no domina las | |
| // herramientas code.* así que le damos el material masticado. | |
| for (const key of ['README.md', 'readme.md', 'package.json', 'pyproject.toml', 'Cargo.toml', 'go.mod']) { | |
| try { const body = await code.read({ path: key }); parts.push(`Contenido REAL de ${key}:\n${body.slice(0, 1400)}`); break; } catch { /* siguiente */ } | |
| } | |
| if (currentFile) { | |
| try { | |
| const body = await code.read({ path: currentFile }); | |
| parts.push(`Contenido REAL del archivo abierto ${currentFile}:\n` + body.slice(0, 2000)); | |
| } catch { /* borrado */ } | |
| } | |
| return parts.join('\n'); | |
| } | |