From 29157d4f08e694f8fc7c0cdc784146ab66f149f0 Mon Sep 17 00:00:00 2001 From: minguezsanzjuanjose Date: Sun, 4 Oct 2026 00:15:07 +0200 Subject: [PATCH] 04-oct: instalar_dependencias.ps1 + omniroute-autostart.ts al repo + comparativa equipos --- CHANGELOG_INFRA.md | 14 ++-- changelog_infra.json | 12 ++++ docs/COMPARATIVA_EQUIPOS.md | 69 ++++++++++++++++++ opencode/omniroute-autostart.ts | 116 ++++++++++++++++++++++++++++++ scripts/instalar_dependencias.ps1 | 28 ++++++++ scripts/instalar_global.ps1 | 7 ++ 6 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 docs/COMPARATIVA_EQUIPOS.md create mode 100644 opencode/omniroute-autostart.ts create mode 100644 scripts/instalar_dependencias.ps1 diff --git a/CHANGELOG_INFRA.md b/CHANGELOG_INFRA.md index a56d806..2a0d8cd 100644 --- a/CHANGELOG_INFRA.md +++ b/CHANGELOG_INFRA.md @@ -9,13 +9,10 @@ - **2026-10-03-perfil-juanjo-instaladas-dependencias-python-21-paquetes-en-** [scripts] Perfil juanjo: instaladas dependencias Python (21 paquetes) en C:\Python314 (aplicado en: sobremesa) - **2026-10-03-sobremesa-juanjo-instaladas-17-apps-de-usuario-que-estaban-e** [scripts] Sobremesa juanjo: instaladas 17 apps de usuario que estaban en juanm (aplicado en: sobremesa) - **2026-10-03-migracion-cuenta-juanjo-rutas-juanm-dinamicas-os-path-expand** [scripts] Migracion cuenta juanjo: rutas juanm -> dinamicas (os.path.expanduser / \C:\Users\juanjo / USERPROFILE) (aplicado en: sobremesa) -- **2026-10-03-monitor-de-estado-telegram-correo-jira-en-segundo-plano** [servicios] Monitor de estado (Telegram + correo + Jira) en segundo plano (aplicado en: portatil) -- **2026-10-03-acceso-remoto-al-sobremesa-openssh-server-tailscale-ssh-powe** [servicios] Acceso remoto al sobremesa: OpenSSH Server + Tailscale (ssh -> PowerShell) (aplicado en: portatil) -- **2026-10-03-voicemonkey-sustituido-por-home-assistant-alexa** [servicios] VoiceMonkey sustituido por Home Assistant (Alexa) (aplicado en: portatil) -- **2026-10-03-omniroute-3-8-48-3-8-51-fix-catalogo-live-antigravity** [omniroute] OmniRoute 3.8.48 -> 3.8.51: fix catalogo live antigravity (aplicado en: portatil) - **2026-10-03-enrutado-de-voz-de-avisos-carolina-juanjo-abuelo-voicestudio** [scripts] Enrutado de voz de avisos: Carolina/Juanjo/Abuelo (VoiceStudio) (aplicado en: portatil) - **2026-10-03-voces-de-aviso-cambiadas-a-nativas-en-castellano-carolina-f4** [scripts] Voces de aviso cambiadas a nativas en castellano (Carolina f40515ca / Abuelo e0ecda0a) (aplicado en: portatil) - **2026-10-04-protocolo-de-encendido-remoto-del-sobremesa-powershell-por-s** [servicios] Protocolo de encendido remoto del sobremesa + PowerShell por SSH (aplicado en: portatil) +- **2026-10-04-instalador-de-dependencias-python-plugin-omniroute-autostart** [scripts] Instalador de dependencias Python + plugin omniroute-autostart + comparativa equipos (aplicado en: portatil) ## Historial @@ -27,6 +24,14 @@ - **Aplicado en**: portatil - **Detalle**: docs/PROTOCOLO_ENCENDIDO_REMOTO_SSH.md + scripts/encender_sobremesa.py (check Tailscale -> enciende regleta via Alexa/HA -> espera 3min -> check -> WoL best-effort -> espera 3min -> informe con voz Carolina) + scripts/ssh_sobremesa.ps1 (abre PowerShell en juanjo@100.75.115.29). Validado: regleta encendio el PC y SSH funciona. Red doble NAT Zyxel(.1)->Asus(.50); se llega por Tailscale. +### 2026-10-04 · Instalador de dependencias Python + plugin omniroute-autostart + comparativa equipos +- **id**: `2026-10-04-instalador-de-dependencias-python-plugin-omniroute-autostart` +- **Equipo**: portatil +- **Categoria**: scripts +- **Transferible**: si +- **Aplicado en**: portatil +- **Detalle**: scripts/instalar_dependencias.ps1 (union de paquetes pip), opencode/omniroute-autostart.ts anadido al repo, instalar_global.ps1 ahora copia tambien ese plugin, docs/COMPARATIVA_EQUIPOS.md. Objetivo: igualar componentes comunes entre portatil y sobremesa. + ### 2026-10-03 · SuperWhisper Enter: AHK F13 boton auxiliar Logitech + tarea programada - **id**: `2026-10-03-superwhisper-enter-ahk-f13-boton-auxiliar-logitech-tarea-pro` - **Equipo**: portatil @@ -114,6 +119,7 @@ - **Transferible**: no - **Aplicado en**: sobremesa - **Detalle**: Colgaba 15s por ruta C:\Users\juanm hardcodeada tras migrar a juanjo; ahora usa ~/Documents/Github/contabo, ConnectTimeout 8s y sigue aunque el VPS no responda. + ### 2026-10-03 · Enrutado de voz de avisos: Carolina/Juanjo/Abuelo (VoiceStudio) - **id**: `2026-10-03-enrutado-de-voz-de-avisos-carolina-juanjo-abuelo-voicestudio` - **Equipo**: portatil diff --git a/changelog_infra.json b/changelog_infra.json index 811bd28..502d585 100644 --- a/changelog_infra.json +++ b/changelog_infra.json @@ -387,6 +387,18 @@ "portatil" ], "detalle": "docs/PROTOCOLO_ENCENDIDO_REMOTO_SSH.md + scripts/encender_sobremesa.py (check Tailscale -> enciende regleta via Alexa/HA -> espera 3min -> check -> WoL best-effort -> espera 3min -> informe con voz Carolina) + scripts/ssh_sobremesa.ps1 (abre PowerShell en juanjo@100.75.115.29). Validado: regleta encendio el PC y SSH funciona. Red doble NAT Zyxel(.1)->Asus(.50); se llega por Tailscale." + }, + { + "id": "2026-10-04-instalador-de-dependencias-python-plugin-omniroute-autostart", + "fecha": "2026-10-04", + "equipo": "portatil", + "categoria": "scripts", + "titulo": "Instalador de dependencias Python + plugin omniroute-autostart + comparativa equipos", + "transferible": true, + "aplicado_en": [ + "portatil" + ], + "detalle": "scripts/instalar_dependencias.ps1 (union de paquetes pip), opencode/omniroute-autostart.ts anadido al repo, instalar_global.ps1 ahora copia tambien ese plugin, docs/COMPARATIVA_EQUIPOS.md. Objetivo: igualar componentes comunes entre portatil y sobremesa." } ] } diff --git a/docs/COMPARATIVA_EQUIPOS.md b/docs/COMPARATIVA_EQUIPOS.md new file mode 100644 index 0000000..0df8921 --- /dev/null +++ b/docs/COMPARATIVA_EQUIPOS.md @@ -0,0 +1,69 @@ +# Comparativa portátil ↔ sobremesa (INFRAESTRUCTURA) + +Fecha: 04-oct-2026. Generado comparando ambos equipos en vivo (scheduled tasks, plugins, pip, winget, puertos). + +## Leyenda +- **SOBREMESA falta** = está en el portátil y **no** en el sobremesa. +- **PORTÁTIL falta** = está en el sobremesa y **no** en el portátil. + +## Apps (winget) +| App | Portátil | Sobremesa | +|-----|:--:|:--:| +| VoiceStudio 0.5.6 | ✅ | ❌ → **falta en sobremesa** (port 3900 off) | +| AutoHotkey v2 | ✅ | ❌ → **falta en sobremesa** | +| Tailscale | ✅ | ✅ | +| Obsidian | ✅ | ✅ | +| Ollama | ✅ | ✅ | +| superwhisper | ✅ | ✅ | +| Logi Options+/G HUB | ✅ | ✅ | +| Node | 24.19 | 24.21 | +| Python | 3.13.11 | **3.14.7** (distinta versión) | + +## Tareas programadas +| Tarea | Portátil | Sobremesa | +|-------|:--:|:--:| +| Monitor Estado | ✅ | ✅ | +| OmniRoute Watchdog | ✅ | ✅ | +| Recordatorios Msgbox | ✅ | ✅ | +| Shutdown Listener | ✅ | ✅ | +| Telegram Watcher | ✅ | ✅ | +| **SuperWhisper Enter** | ✅ | ❌ → **falta en sobremesa** | +| **Recordatorio_12PM** | ✅ | ❌ → **falta en sobremesa** | +| **Recordatorio_13PM** | ✅ | ❌ → **falta en sobremesa** | +| MorningRoutine Prolongo | ❌ | ✅ (solo sobremesa) | +| OmniRoute / OmnirouteFixCheck | ❌ | ✅ (solo sobremesa) | + +## Plugins globales OpenCode (`~/.config/opencode/plugins`) +| Plugin | Portátil | Sobremesa | +|--------|:--:|:--:| +| engram.ts | ✅ | ✅ | +| monitor-estado-bootstrap.ts | ✅ | ✅ | +| omniroute-bootstrap.ts | ✅ | ✅ | +| **omniroute-autostart.ts** | ✅ | ❌ → **falta en sobremesa** | + +## Dependencias Python (pip) +| Paquete | Portátil | Sobremesa | +|---------|:--:|:--:| +| Pillow | ✅ | ❌ → **falta en sobremesa** | +| caldav | ❌ | ✅ → **falta en portátil** | +| edge-tts | ❌ | ✅ → **falta en portátil** | +| wakeonlan | ❌ | ✅ → **falta en portátil** | + +## Servicios/carpetas +| Elemento | Portátil | Sobremesa | +|----------|:--:|:--:| +| OmniRoute 20128 | ✅ | ✅ | +| VoiceStudio 3900 | ✅ | ❌ | +| `Documents\voz_mensajes` | ✅ | ❌ (lo crea VoiceStudio) | + +--- + +## Cómo instalar lo que falta en el SOBREMESA (fácil) +1. **Dependencias Python** (incluye Pillow) — `scripts\instalar_dependencias.ps1` (ver abajo). +2. **VoiceStudio** (puerto 3900 + voz Carolina/Abuelo): pendiente #196 → `docs/INFRA_PENDIENTE_SOBREMESA.md`. +3. **AutoHotkey v2** + `superwhisper_enter.ahk` + tarea **SuperWhisper Enter**: pendiente #201. +4. **Plugin `omniroute-autostart.ts`**: copiar de `~/.config/opencode/plugins` del portátil (o desde `INFRAESTRUCTURA/opencode/` si está versionado). +5. **Tareas Recordatorio_12PM/13PM**: exportar/importar XML de tareas programadas. + +## Cómo instalar lo que falta en el PORTÁTIL +- `pip install caldav edge-tts wakeonlan` (una línea). diff --git a/opencode/omniroute-autostart.ts b/opencode/omniroute-autostart.ts new file mode 100644 index 0000000..1afa2fb --- /dev/null +++ b/opencode/omniroute-autostart.ts @@ -0,0 +1,116 @@ +/** + * OmniRoute autostart — OpenCode plugin + * + * Arranca el servidor local OmniRoute (http://127.0.0.1:20128) cada vez que + * OpenCode se inicia, si no está ya escuchando. También lo relanza si se cae + * durante la sesión. Esto garantiza que los modelos del proveedor `omniroute` + * estén siempre disponibles (modelos gratuitos de la suscripción Claude Code). + * + * Se carga automáticamente desde ~/.config/opencode/plugins/*.ts + */ + +import type { Plugin } from "@opencode-ai/plugin" +import { spawn } from "node:child_process" +import { appendFileSync, mkdirSync } from "node:fs" +import { homedir } from "node:os" +import { join } from "node:path" + +// ─── Configuración ─────────────────────────────────────────────────────────── + +const OR_URL = "http://127.0.0.1:20128" +const OR_PORT = 20128 + +const NODE_BIN = process.env.OMNIROUTE_NODE ?? "C:\\Program Files\\nodejs\\node.exe" +const OR_ENTRY = + process.env.OMNIROUTE_ENTRY ?? + join( + process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), + "npm", + "node_modules", + "omniroute", + "bin", + "omniroute.mjs", + ) + +const LOG_FILE = join(homedir(), ".omniroute", "autostart-plugin.log") + +// ─── Utilidades ────────────────────────────────────────────────────────────── + +function log(msg: string): void { + try { + mkdirSync(join(homedir(), ".omniroute"), { recursive: true }) + appendFileSync(LOG_FILE, `[${new Date().toISOString()}] ${msg}\n`) + } catch { + // el log nunca debe romper el arranque de OpenCode + } +} + +/** ¿Responde OmniRoute? El dashboard en "/" devuelve 200 sin autenticación. */ +async function isUp(): Promise { + try { + const ctrl = new AbortController() + const timer = setTimeout(() => ctrl.abort(), 3000) + const res = await fetch(`${OR_URL}/`, { signal: ctrl.signal }) + clearTimeout(timer) + return res.status > 0 && res.status < 500 + } catch { + return false + } +} + +/** Lanza OmniRoute desacoplado para que sobreviva al cierre de OpenCode. */ +function startServer(): void { + const child = spawn(NODE_BIN, [OR_ENTRY, "serve"], { + detached: true, + stdio: "ignore", + windowsHide: true, + env: process.env, + }) + child.unref() + log(`lanzado OmniRoute (pid ${child.pid})`) +} + +// Evita arranques concurrentes si coinciden el inicio y varios session.created +let starting: Promise | null = null + +/** Arranca OmniRoute si no está levantado y espera a que responda. */ +async function ensureServer(reason: string): Promise { + if (await isUp()) return + if (starting) return starting + + starting = (async () => { + log(`OmniRoute caído (${reason}) — arrancando...`) + startServer() + // El arranque puede tardar ~60s; sondeamos hasta 2 minutos + for (let i = 0; i < 40; i++) { + await new Promise((r) => setTimeout(r, 3000)) + if (await isUp()) { + log(`OmniRoute listo en puerto ${OR_PORT}`) + return + } + } + log("OmniRoute no respondió dentro del tiempo de espera") + })() + + try { + await starting + } finally { + starting = null + } +} + +// ─── Plugin ────────────────────────────────────────────────────────────────── + +export const OmniRouteAutostart: Plugin = async () => { + // Al cargar el plugin (= arranque de OpenCode) nos aseguramos de que esté vivo + void ensureServer("opencode-start") + + return { + event: async ({ event }) => { + // Re-verificación barata al crear sesión (cubre una caída a mitad de sesión) + if (event.type === "session.created") { + void ensureServer("session-created") + } + }, + } +} diff --git a/scripts/instalar_dependencias.ps1 b/scripts/instalar_dependencias.ps1 new file mode 100644 index 0000000..e21c271 --- /dev/null +++ b/scripts/instalar_dependencias.ps1 @@ -0,0 +1,28 @@ +<# +.SYNOPSIS + Instala/actualiza las dependencias Python comunes (union portatil + sobremesa). + +.DESCRIPTION + Deja cualquier equipo con el mismo juego de paquetes Python que usan los + watchers, la biblioteca, el monitor, tapo/netatmo, etc. Idempotente. + + Uso: powershell -ExecutionPolicy Bypass -File scripts\instalar_dependencias.ps1 +#> +$ErrorActionPreference = "Continue" + +$pkgs = @( + "pycryptodome", "PyP100", "caldav", "python-dotenv", "edge-tts", "feedparser", + "flask", "ftfy", "google-auth-oauthlib", "google-api-python-client", "openpyxl", + "psutil", "qrcode", "requests", "requests-oauthlib", "google-auth", + "google-auth-httplib2", "google-api-core", "telethon", "todoist-api-python", + "urllib3", "wakeonlan", "watchdog", "win10toast", "pywin32", "pillow", "setuptools<82" +) + +Write-Host "== Instalando dependencias Python (union) ==" -ForegroundColor Cyan +Write-Host ("Version: " + (python --version 2>&1)) -ForegroundColor DarkGray + +python -m pip install --upgrade --disable-pip-version-check @pkgs + +Write-Host "" +Write-Host "Listo. Verifica con: python -m pip freeze" -ForegroundColor Green +Write-Host "Si algun paquete avisa de incompatibilidad con tu version de Python, ignorarlo." -ForegroundColor DarkGray diff --git a/scripts/instalar_global.ps1 b/scripts/instalar_global.ps1 index f1609f6..6f4e426 100644 --- a/scripts/instalar_global.ps1 +++ b/scripts/instalar_global.ps1 @@ -36,6 +36,8 @@ $TaskMonitor = 'Monitor Estado' $WatchdogMonitor = Join-Path $RepoRoot 'scripts\monitor_estado_watchdog.ps1' $PluginSrcMon = Join-Path $RepoRoot 'opencode\monitor-estado-bootstrap.ts' $PluginDstMon = Join-Path $PluginDir 'monitor-estado-bootstrap.ts' +$PluginSrcAuto = Join-Path $RepoRoot 'opencode\omniroute-autostart.ts' +$PluginDstAuto = Join-Path $PluginDir 'omniroute-autostart.ts' Write-Host '== Instalando infraestructura global (OmniRoute + OpenCode) ==' -ForegroundColor Cyan @@ -47,6 +49,11 @@ Write-Host " - Plugin global instalado en $PluginDst" -ForegroundColor Green Copy-Item -LiteralPath $PluginSrcMon -Destination $PluginDstMon -Force Write-Host " - Plugin global instalado en $PluginDstMon" -ForegroundColor Green +if (Test-Path $PluginSrcAuto) { + Copy-Item -LiteralPath $PluginSrcAuto -Destination $PluginDstAuto -Force + Write-Host " - Plugin global instalado en $PluginDstAuto" -ForegroundColor Green +} + # 2) Tarea programada ------------------------------------------------------ if (-not (Test-Path $Watchdog)) { throw "No se encuentra el vigilante: $Watchdog" }