| # Auditoría: Puertos de OpenSkyNet vs OpenClaw |
|
|
| **Fecha:** 2025-03-14 |
| **Problema:** Los puertos de OpenSkyNet no funcionan / están ocupados por OpenClaw |
|
|
| --- |
|
|
| ## Diagnóstico del Problema |
|
|
| ### 1. No existe separación de estado |
|
|
| **Código actual (`src/config/paths.ts`):** |
| ```typescript |
| const NEW_STATE_DIRNAME = ".openclaw"; // ← Solo existe .openclaw |
| |
| export function resolveStateDir(env: NodeJS.ProcessEnv = process.env): string { |
| const override = env.OPENCLAW_STATE_DIR?.trim() || env.CLAWDBOT_STATE_DIR?.trim(); |
| // NO hay OPENSKYNET_STATE_DIR |
| if (override) { |
| return resolveUserPath(override, env, effectiveHomedir); |
| } |
| return newStateDir(effectiveHomedir); // Siempre ~/.openclaw |
| } |
| ``` |
|
|
| **Resultado:** OpenSkyNet y OpenClaw comparten: |
| - Mismo directorio de estado (`~/.openclaw`) |
| - Mismo archivo de configuración (`~/.openclaw/openclaw.json`) |
| - Mismos puertos (derivados del gateway port) |
|
|
| ### 2. Los puertos se derivan del gateway port |
|
|
| **Código actual (`src/config/port-defaults.ts`):** |
| ```typescript |
| export function deriveDefaultBrowserControlPort(gatewayPort: number): number { |
| return derivePort(gatewayPort, 2, DEFAULT_BROWSER_CONTROL_PORT); // gateway + 2 |
| } |
| |
| export function deriveDefaultCanvasHostPort(gatewayPort: number): number { |
| return derivePort(gatewayPort, 4, DEFAULT_CANVAS_HOST_PORT); // gateway + 4 |
| } |
| ``` |
|
|
| **Si gateway = 18789:** |
| - Browser Control = 18791 |
| - Canvas Host = 18793 |
|
|
| **No hay lógica para puertos diferentes basada en `cliName`.** |
|
|
| ### 3. El `cliName` solo afecta display, no configuración |
|
|
| **Código (`src/cli/cli-name.ts`):** |
| ```typescript |
| export function resolveCliDisplayName(argv: string[] = process.argv): string { |
| return resolveCliName(argv) === ALT_CLI_NAME ? "OpenSkynet" : "OpenClaw"; |
| } |
| ``` |
|
|
| Solo cambia el nombre mostrado. No afecta puertos, estado, ni configuración. |
|
|
| --- |
|
|
| ## Por qué "no funcionan los puertos de OpenSkyNet" |
|
|
| Cuando ejecutas `openskynet`: |
| 1. Lee la misma config que `openclaw` |
| 2. Usa los mismos puertos (18789, 18791, 18793) |
| 3. Si OpenClaw ya está corriendo → puertos ocupados → error |
| 4. Si intentas cambiar puertos manualmente → afecta a ambos |
|
|
| **No hay mecanismo para tener instancias separadas.** |
|
|
| --- |
|
|
| ## Soluciones Propuestas |
|
|
| ### Opción 1: Variable de entorno OPENSKYNET_STATE_DIR (Rápida) |
|
|
| **Cambio en `src/config/paths.ts`:** |
| ```typescript |
| export function resolveStateDir(env: NodeJS.ProcessEnv = process.env): string { |
| // Añadir soporte para OPENSKYNET_STATE_DIR |
| const override = |
| env.OPENSKYNET_STATE_DIR?.trim() || |
| env.OPENCLAW_STATE_DIR?.trim() || |
| env.CLAWDBOT_STATE_DIR?.trim(); |
| |
| if (override) { |
| return resolveUserPath(override, env, effectiveHomedir); |
| } |
| |
| // Si cliName es openskynet, usar directorio diferente |
| const cliName = resolveCliName(); |
| if (cliName === ALT_CLI_NAME) { |
| return path.join(effectiveHomedir(), ".openskynet"); |
| } |
| |
| return newStateDir(effectiveHomedir); |
| } |
| ``` |
|
|
| **Uso:** |
| ```bash |
| export OPENSKYNET_STATE_DIR=~/.openskynet |
| export OPENSKYNET_GATEWAY_PORT=19789 |
| openskynet gateway start |
| ``` |
|
|
| **Pros:** |
| - Simple, no rompe compatibilidad |
| - Permite instancias completamente separadas |
|
|
| **Contras:** |
| - Requiere setear variables de entorno |
| - No es automático |
|
|
| --- |
|
|
| ### Opción 2: Offset de puertos basado en cliName (Recomendada) |
|
|
| **Cambio en `src/config/port-defaults.ts`:** |
| ```typescript |
| import { resolveCliName, ALT_CLI_NAME } from "../cli/cli-name.js"; |
| |
| const PORT_OFFSET_OPENCLAW = 0; |
| const PORT_OFFSET_OPENSKYNET = 1000; // Offset de 1000 para OpenSkyNet |
| |
| function getPortOffset(): number { |
| return resolveCliName() === ALT_CLI_NAME ? PORT_OFFSET_OPENSKYNET : PORT_OFFSET_OPENCLAW; |
| } |
| |
| export function deriveDefaultGatewayPort(): number { |
| return DEFAULT_GATEWAY_PORT + getPortOffset(); // 18789 + 1000 = 19789 |
| } |
| |
| export function deriveDefaultBrowserControlPort(gatewayPort?: number): number { |
| const base = gatewayPort ?? deriveDefaultGatewayPort(); |
| return derivePort(base, 2, DEFAULT_BROWSER_CONTROL_PORT + getPortOffset()); |
| } |
| |
| export function deriveDefaultCanvasHostPort(gatewayPort?: number): number { |
| const base = gatewayPort ?? deriveDefaultGatewayPort(); |
| return derivePort(base, 4, DEFAULT_CANVAS_HOST_PORT + getPortOffset()); |
| } |
| ``` |
|
|
| **Resultado:** |
| | Servicio | OpenClaw | OpenSkyNet | |
| |----------|----------|------------| |
| | Gateway | 18789 | 19789 | |
| | Browser Control | 18791 | 19791 | |
| | Canvas Host | 18793 | 19793 | |
|
|
| **Pros:** |
| - Automático, sin variables de entorno |
| - Predictible |
| - No rompe compatibilidad |
|
|
| **Contras:** |
| - Cambio más invasivo |
| - Requiere modificar lógica de derivación |
|
|
| --- |
|
|
| ### Opción 3: Configuración por agente en openclaw.json (Flexible) |
|
|
| **Estructura de config:** |
| ```json |
| { |
| "gateway": { |
| "port": 18789, |
| "agents": { |
| "openskynet": { |
| "port": 19789, |
| "browserControlPort": 19791, |
| "canvasHostPort": 19793 |
| } |
| } |
| } |
| } |
| ``` |
|
|
| **Cambio en código:** |
| ```typescript |
| export function resolveAgentSpecificPort( |
| basePort: number, |
| agentId: string, |
| config: OpenClawConfig |
| ): number { |
| return config.gateway?.agents?.[agentId]?.port ?? basePort; |
| } |
| ``` |
|
|
| **Pros:** |
| - Máxima flexibilidad |
| - Configurable por usuario |
|
|
| **Contras:** |
| - Complejidad alta |
| - Cambios en schema de config |
|
|
| --- |
|
|
| ## Recomendación |
|
|
| **Implementar Opción 2** (offset basado en cliName) como solución principal, con **Opción 1** (variable de entorno) como override. |
|
|
| Esto permite: |
| 1. Ejecutar `openskynet` automáticamente en puertos 19789+ |
| 2. Override manual vía `OPENSKYNET_STATE_DIR` si es necesario |
| 3. Compatibilidad backward con OpenClaw existente |
|
|
| --- |
|
|
| ## Implementación Propuesta |
|
|
| ### Paso 1: Modificar `src/config/port-defaults.ts` |
|
|
| ```typescript |
| import { resolveCliName, ALT_CLI_NAME } from "../cli/cli-name.js"; |
| |
| const OPENSKYNET_PORT_OFFSET = 1000; |
| |
| function getPortOffset(): number { |
| try { |
| return resolveCliName() === ALT_CLI_NAME ? OPENSKYNET_PORT_OFFSET : 0; |
| } catch { |
| return 0; |
| } |
| } |
| |
| export const DEFAULT_GATEWAY_PORT = 18789 + getPortOffset(); |
| export const DEFAULT_BRIDGE_PORT = 18790 + getPortOffset(); |
| export const DEFAULT_BROWSER_CONTROL_PORT = 18791 + getPortOffset(); |
| export const DEFAULT_CANVAS_HOST_PORT = 18793 + getPortOffset(); |
| export const DEFAULT_BROWSER_CDP_PORT_RANGE_START = 18800 + getPortOffset(); |
| export const DEFAULT_BROWSER_CDP_PORT_RANGE_END = 18899 + getPortOffset(); |
| ``` |
|
|
| ### Paso 2: Modificar `src/config/paths.ts` |
|
|
| ```typescript |
| export function resolveStateDir( |
| env: NodeJS.ProcessEnv = process.env, |
| homedir: () => string = envHomedir(env), |
| ): string { |
| const effectiveHomedir = () => resolveRequiredHomeDir(env, homedir); |
| |
| // Prioridad: OPENSKYNET > OPENCLAW > default |
| const override = |
| env.OPENSKYNET_STATE_DIR?.trim() || |
| env.OPENCLAW_STATE_DIR?.trim() || |
| env.CLAWDBOT_STATE_DIR?.trim(); |
| |
| if (override) { |
| return resolveUserPath(override, env, effectiveHomedir); |
| } |
| |
| // Auto-detectar basado en cliName |
| try { |
| const { resolveCliName, ALT_CLI_NAME } = require("../cli/cli-name.js"); |
| if (resolveCliName() === ALT_CLI_NAME) { |
| return path.join(effectiveHomedir(), ".openskynet"); |
| } |
| } catch { |
| // Fallback a default |
| } |
| |
| return newStateDir(effectiveHomedir); |
| } |
| ``` |
|
|
| ### Paso 3: Tests |
|
|
| ```typescript |
| // src/config/port-defaults.test.ts |
| it("uses offset ports when cliName is openskynet", () => { |
| jest.mock("../cli/cli-name.js", () => ({ |
| resolveCliName: () => "openskynet", |
| ALT_CLI_NAME: "openskynet", |
| })); |
| |
| const { DEFAULT_GATEWAY_PORT } = require("./port-defaults.js"); |
| expect(DEFAULT_GATEWAY_PORT).toBe(19789); |
| }); |
| ``` |
|
|
| --- |
|
|
| ## Conclusión |
|
|
| **El problema es real:** OpenSkyNet no tiene mecanismo para puertos/estado separados. |
|
|
| **La causa:** `cliName` solo afecta display, no configuración. |
|
|
| **La solución:** Implementar offset de puertos y directorio de estado basado en `cliName`. |
|
|
| **Impacto:** Cambio moderado en `port-defaults.ts` y `paths.ts`, con alta compatibilidad backward. |
|
|
| --- |
|
|
| *Auditoría generada automáticamente por análisis de código.* |
|
|