04-oct: instalar_dependencias.ps1 + omniroute-autostart.ts al repo + comparativa equipos
This commit is contained in:
116
opencode/omniroute-autostart.ts
Normal file
116
opencode/omniroute-autostart.ts
Normal file
@@ -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<boolean> {
|
||||
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<void> | null = null
|
||||
|
||||
/** Arranca OmniRoute si no está levantado y espera a que responda. */
|
||||
async function ensureServer(reason: string): Promise<void> {
|
||||
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")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user