File size: 8,018 Bytes
fc93158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# 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.*