openskynet / docs /status /AUDITORIA_PUERTOS_OPENSKYNET.md
Darochin's picture
Mirror OpenSkyNet workspace snapshot from Git HEAD
fc93158 verified

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):

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):

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):

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:

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:

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:

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:

{
  "gateway": {
    "port": 18789,
    "agents": {
      "openskynet": {
        "port": 19789,
        "browserControlPort": 19791,
        "canvasHostPort": 19793
      }
    }
  }
}

Cambio en código:

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

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

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

// 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.