diff --git a/README.md b/README.md index 31ca489..372207b 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ opencode-browser-tool/ - `docs/QUICKSTART.md` - `docs/VALIDACION_ENTORNO_LIMPIO.md` - `docs/PLAN_CIERRE_INSTALABLE.md` +- `docs/INSTALACION_WINDOWS.md` - `docs/REGISTRO_SITUACIONES.md` - `docs/contexto_workspace/` (snapshot de docs globales clave para continuidad) @@ -83,18 +84,28 @@ opencode-browser-tool/ La idea es que este proyecto pueda copiarse o descargarse en un PC con OpenCode y dejarse listo mediante: - `./install.sh` +- `npm run setup` (alternativa neutral por npm/node) - una guia de instalacion clara - o instrucciones que un agente de OpenCode pueda ejecutar -### Que hace `install.sh` con Chromium +### Que hace el setup -El script instala dependencias y luego ejecuta: +El setup ejecuta, en orden: -- `npx playwright install chromium` +- validacion de `Node.js 20+` +- instalacion de dependencias (`npm ci` cuando hay lockfile) +- compilacion (`npm run build`) +- instalacion de `Chromium managed by Playwright` -Esto instala el `Chromium managed by Playwright` para garantizar compatibilidad estable en la v1. +Al terminar, muestra un snippet MCP con la ruta absoluta local de `dist/server.js`. -Si el sistema ya tiene un Chromium propio, en esta fase igualmente se usa el gestionado por Playwright. +### Verificacion + +Tras instalar, ejecutar: + +- `./check.sh` o `npm run check` + +La verificacion recompila y confirma archivos clave para puesta en marcha en otro PC. ## Nota diff --git a/check.sh b/check.sh index 176ca21..433e928 100755 --- a/check.sh +++ b/check.sh @@ -20,14 +20,30 @@ node --version printf 'npm: ' npm --version -if [ -d "$SCRIPT_DIR/node_modules" ]; then - printf 'Dependencias instaladas: si\n' -else - printf 'Dependencias instaladas: no\n' +NODE_MAJOR="$(node -p 'process.versions.node.split(".")[0]')" +if [ "$NODE_MAJOR" -lt 20 ]; then + printf 'Se requiere Node.js 20 o superior.\n' >&2 + exit 1 fi +if [ ! -d "$SCRIPT_DIR/node_modules" ]; then + printf 'Dependencias instaladas: no\n' >&2 + printf 'Ejecuta ./install.sh primero.\n' >&2 + exit 1 +fi + +printf 'Dependencias instaladas: si\n' + if [ -d "$SCRIPT_DIR/artifacts" ]; then printf 'Carpeta artifacts: lista\n' else printf 'Carpeta artifacts: ausente\n' fi + +printf 'Compilando para verificar integridad...\n' +npm run --prefix "$SCRIPT_DIR" build + +printf 'Validando archivos clave...\n' +node "$SCRIPT_DIR/scripts/verify-install.mjs" + +printf 'Verificacion completada correctamente.\n' diff --git a/docs/INSTALACION_WINDOWS.md b/docs/INSTALACION_WINDOWS.md new file mode 100644 index 0000000..5025d88 --- /dev/null +++ b/docs/INSTALACION_WINDOWS.md @@ -0,0 +1,57 @@ +# Instalacion Windows (guia para agente local) + +Objetivo: que un agente OpenCode en un PC Windows pueda instalar y dejar operativa la tool desde esta carpeta. + +## Prerrequisitos + +- Node.js 20+ +- npm +- OpenCode instalado +- Git (opcional si la carpeta ya fue copiada) + +## Flujo recomendado + +1) Abrir terminal en la carpeta `opencode-browser-tool`. + +2) Ejecutar setup neutral (sin `.sh`): + +```bash +npm run setup +``` + +3) Verificar instalacion: + +```bash +npm run verify +``` + +4) Crear configuracion MCP de OpenCode con la ruta absoluta local de `dist/server.js`: + +```json +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "browser-tool": { + "type": "local", + "command": [ + "node", + "C:/ABSOLUTE/PATH/opencode-browser-tool/dist/server.js" + ] + } + } +} +``` + +5) Confirmar conexion MCP: + +```bash +opencode mcp list +``` + +6) Smoke test desde OpenCode: abrir browser -> navegar a `https://example.com` -> snapshot -> cerrar. + +## Notas operativas + +- En Windows evitar `install.sh`; usar `npm run setup`. +- Si se quiere `browserKind=system`, configurar la ruta real de Chrome en `browser_config`. +- Perfil persistente debe usar una ruta local valida de Windows (ej. `C:/Users//...`). diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md index 9c79fa1..af1097e 100644 --- a/docs/QUICKSTART.md +++ b/docs/QUICKSTART.md @@ -10,7 +10,13 @@ Desde `opencode-browser-tool/`: ./install.sh ``` -Esto instala dependencias y `Chromium managed by Playwright`. +Alternativa neutral por npm/node: + +```bash +npm run setup +``` + +Esto instala dependencias, compila y prepara `Chromium managed by Playwright`. ## 2) Compilar @@ -18,6 +24,12 @@ Esto instala dependencias y `Chromium managed by Playwright`. npm run build ``` +## 2.1) Verificar + +```bash +./check.sh +``` + ## 3) Configurar MCP en el proyecto Crear `opencode-browser-tool/.opencode/opencode.json` con: @@ -30,7 +42,7 @@ Crear `opencode-browser-tool/.opencode/opencode.json` con: "type": "local", "command": [ "node", - "/home/pancho/Documentos/Empresa/IA/opencode-browser-tool/dist/server.js" + "/ABSOLUTE/PATH/opencode-browser-tool/dist/server.js" ] } } diff --git a/docs/TODO.md b/docs/TODO.md index f1ef019..cdf4e9e 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -57,9 +57,9 @@ Recoger el trabajo completo necesario desde el estado actual hasta un producto t - [x] Documentar instalacion paso a paso en un `.md` (`docs/QUICKSTART.md`) - [ ] Verificar instalacion en un entorno limpio con OpenCode (checklist en `docs/VALIDACION_ENTORNO_LIMPIO.md`) - [x] Asegurar que todo el proyecto se despliega desde una unica carpeta -- [ ] Cerrar instalable Linux sin rutas hardcodeadas (proyecto, perfil, OpenCode) -- [ ] Alinear `install.sh` y `check.sh` con puesta en marcha en PC nuevo -- [ ] Cerrar plantilla MCP portable para rutas locales variables +- [x] Cerrar instalable Linux sin rutas hardcodeadas (proyecto, perfil, OpenCode) +- [x] Alinear `install.sh` y `check.sh` con puesta en marcha en PC nuevo +- [x] Cerrar plantilla MCP portable para rutas locales variables --- diff --git a/docs/VALIDACION_ENTORNO_LIMPIO.md b/docs/VALIDACION_ENTORNO_LIMPIO.md index c4ce280..6581ceb 100644 --- a/docs/VALIDACION_ENTORNO_LIMPIO.md +++ b/docs/VALIDACION_ENTORNO_LIMPIO.md @@ -30,11 +30,16 @@ cd "$HOME/opencode-browser-tool" ./install.sh ``` +Alternativa neutral: + +```bash +npm run setup +``` + 3) Verificacion basica: ```bash -npm run check -npm run build +./check.sh ``` 4) Configurar MCP para OpenCode con la ruta local real de `dist/server.js`: diff --git a/install.sh b/install.sh index c96c306..6fa6d91 100755 --- a/install.sh +++ b/install.sh @@ -3,14 +3,18 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if ! command -v node >/dev/null 2>&1; then + printf 'Node.js no esta disponible en el sistema.\n' >&2 + exit 1 +fi + if ! command -v npm >/dev/null 2>&1; then printf 'npm no esta disponible en el sistema.\n' >&2 exit 1 fi -mkdir -p "$SCRIPT_DIR/artifacts" -npm install --prefix "$SCRIPT_DIR" -npx --yes playwright install chromium +printf 'Iniciando setup en %s\n' "$SCRIPT_DIR" +node "$SCRIPT_DIR/scripts/setup.mjs" printf 'Instalacion base completada.\n' -printf 'Siguiente paso sugerido: revisar opencode.mcp.example.json\n' +printf 'Siguiente paso sugerido: ejecutar ./check.sh\n' diff --git a/opencode.mcp.example.json b/opencode.mcp.example.json index ec23b77..15875d7 100644 --- a/opencode.mcp.example.json +++ b/opencode.mcp.example.json @@ -1,9 +1,11 @@ { - "mcpServers": { + "$schema": "https://opencode.ai/config.json", + "mcp": { "browser-tool": { - "command": "node", - "args": [ - "/ruta/a/opencode-browser-tool/dist/server.js" + "type": "local", + "command": [ + "node", + "/ABSOLUTE/PATH/opencode-browser-tool/dist/server.js" ] } } diff --git a/package.json b/package.json index 99a15ec..e9e906b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "description": "Browser MCP tool external to OpenCode", "type": "module", "scripts": { + "setup": "node ./scripts/setup.mjs", "build": "tsc -p tsconfig.json", + "verify": "node ./scripts/verify-install.mjs", "check": "bash ./check.sh", "dev": "tsx src/server.ts", "start": "node dist/server.js" diff --git a/scripts/setup.mjs b/scripts/setup.mjs new file mode 100644 index 0000000..cec27ff --- /dev/null +++ b/scripts/setup.mjs @@ -0,0 +1,81 @@ +#!/usr/bin/env node + +import { mkdir, access } from "node:fs/promises" +import path from "node:path" +import { fileURLToPath } from "node:url" +import { spawn } from "node:child_process" + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const projectDir = path.resolve(__dirname, "..") + +function run(cmd, args, cwd = projectDir) { + return new Promise((resolve, reject) => { + const child = spawn(cmd, args, { + cwd, + stdio: "inherit", + shell: false, + }) + + child.on("error", reject) + child.on("exit", (code) => { + if (code === 0) { + resolve() + return + } + reject(new Error(`${cmd} ${args.join(" ")} exited with code ${code ?? -1}`)) + }) + }) +} + +async function exists(filePath) { + try { + await access(filePath) + return true + } catch { + return false + } +} + +function ensureNode20() { + const major = Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10) + if (!Number.isFinite(major) || major < 20) { + throw new Error(`Node.js 20+ required. Current: ${process.versions.node}`) + } +} + +async function main() { + ensureNode20() + await mkdir(path.join(projectDir, "artifacts"), { recursive: true }) + await mkdir(path.join(projectDir, "config"), { recursive: true }) + + const lockPath = path.join(projectDir, "package-lock.json") + if (await exists(lockPath)) { + await run("npm", ["ci"]) + } else { + await run("npm", ["install"]) + } + + await run("npm", ["run", "build"]) + await run("npm", ["exec", "playwright", "install", "chromium"]) + + const distPath = path.join(projectDir, "dist", "server.js") + const mcpConfig = { + $schema: "https://opencode.ai/config.json", + mcp: { + "browser-tool": { + type: "local", + command: ["node", distPath], + }, + }, + } + + process.stdout.write("\nInstall complete.\n") + process.stdout.write("Suggested MCP config snippet:\n") + process.stdout.write(`${JSON.stringify(mcpConfig, null, 2)}\n`) +} + +main().catch((error) => { + process.stderr.write(`Setup failed: ${error instanceof Error ? error.message : String(error)}\n`) + process.exit(1) +}) diff --git a/scripts/verify-install.mjs b/scripts/verify-install.mjs new file mode 100644 index 0000000..f5bb73f --- /dev/null +++ b/scripts/verify-install.mjs @@ -0,0 +1,47 @@ +#!/usr/bin/env node + +import { access } from "node:fs/promises" +import path from "node:path" +import { fileURLToPath } from "node:url" + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const projectDir = path.resolve(__dirname, "..") + +async function has(filePath) { + try { + await access(filePath) + return true + } catch { + return false + } +} + +function nodeOk() { + const major = Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10) + return Number.isFinite(major) && major >= 20 +} + +async function main() { + const report = { + node: process.versions.node, + nodeOk: nodeOk(), + packageJson: await has(path.join(projectDir, "package.json")), + nodeModules: await has(path.join(projectDir, "node_modules")), + distServer: await has(path.join(projectDir, "dist", "server.js")), + configFile: await has(path.join(projectDir, "config", "browser-tool.config.json")), + mcpTemplate: await has(path.join(projectDir, "opencode.mcp.example.json")), + } + + process.stdout.write(`${JSON.stringify(report, null, 2)}\n`) + + const ok = Object.values(report).every((value) => value !== false) + if (!ok) { + process.exit(1) + } +} + +main().catch((error) => { + process.stderr.write(`Verify failed: ${error instanceof Error ? error.message : String(error)}\n`) + process.exit(1) +})