openclaw-navigator 5.6.1 → 5.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cli.mjs +43 -71
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -1136,12 +1136,12 @@ function handleRequest(req, res) {
1136
1136
  return;
1137
1137
  }
1138
1138
 
1139
- // ── Chat send: store locally + relay to OC Gateway for processing ──────
1140
- // HYBRID approach:
1141
- // 1. Store user message in bridge (for MCP tools to read via history)
1142
- // 2. Relay to OC Gateway (port 18789) so the AI agent processes it
1143
- // 3. Gateway may return response inline (JSON/SSE) store + broadcast
1144
- // 4. Or agent responds async via navigator_chat_respond MCP tool
1139
+ // ── Chat send: store locally + respond immediately ─────────────────────
1140
+ // 1. Store user message in bridge memory (for MCP tools to read)
1141
+ // 2. Respond to Navigator immediately (don't block on gateway)
1142
+ // 3. In background: try relaying to gateway for AI processing
1143
+ // - If gateway responds store assistant message + broadcast via WS
1144
+ // - If gateway hangs/fails → agent will respond via MCP tools later
1145
1145
  if (path === "/api/sessions/send" && req.method === "POST") {
1146
1146
  readBody(req)
1147
1147
  .then((bodyStr) => {
@@ -1167,25 +1167,22 @@ function handleRequest(req, res) {
1167
1167
  content: message,
1168
1168
  timestamp: Date.now(),
1169
1169
  });
1170
- broadcastToWS({
1171
- type: "chat.user",
1172
- text: message,
1173
- content: message,
1174
- sessionKey,
1175
- role: "user",
1176
- timestamp: Date.now(),
1177
- });
1178
1170
  console.log(` ${DIM}Chat send [${sessionKey}]: ${message.substring(0, 60)}...${RESET}`);
1179
1171
 
1180
- // 2. Relay to OC Gateway for AI processing
1172
+ // 2. Respond immediately don't block Navigator
1173
+ sendJSON(res, 200, { ok: true, stored: true, messageCount: session.messages.length });
1174
+
1175
+ // 3. Background: relay to gateway for AI processing
1176
+ const proxyBody = JSON.stringify({ message, sessionKey });
1181
1177
  const proxyOpts = {
1182
1178
  hostname: "127.0.0.1",
1183
1179
  port: ocGatewayPort,
1184
1180
  path: `/api/sessions/send`,
1185
1181
  method: "POST",
1182
+ timeout: 60000, // 60s — agent may take a while to respond
1186
1183
  headers: {
1187
1184
  "content-type": "application/json",
1188
- "content-length": Buffer.byteLength(bodyStr),
1185
+ "content-length": Buffer.byteLength(proxyBody),
1189
1186
  },
1190
1187
  };
1191
1188
 
@@ -1194,10 +1191,9 @@ function handleRequest(req, res) {
1194
1191
  const isSSE = contentType.includes("text/event-stream");
1195
1192
 
1196
1193
  if (isSSE) {
1197
- // ── SSE response: collect stream, broadcast chunks, return JSON ──
1194
+ // SSE response: collect stream, broadcast chunks via WebSocket
1198
1195
  let fullText = "";
1199
1196
  let buffer = "";
1200
-
1201
1197
  proxyRes.setEncoding("utf-8");
1202
1198
  proxyRes.on("data", (chunk) => {
1203
1199
  buffer += chunk;
@@ -1227,7 +1223,6 @@ function handleRequest(req, res) {
1227
1223
  }
1228
1224
  }
1229
1225
  });
1230
-
1231
1226
  proxyRes.on("end", () => {
1232
1227
  if (buffer.startsWith("data: ")) {
1233
1228
  const raw = buffer.slice(6).trim();
@@ -1241,12 +1236,7 @@ function handleRequest(req, res) {
1241
1236
  }
1242
1237
  }
1243
1238
  if (fullText) {
1244
- // Store assistant response
1245
- session.messages.push({
1246
- role: "assistant",
1247
- content: fullText,
1248
- timestamp: Date.now(),
1249
- });
1239
+ session.messages.push({ role: "assistant", content: fullText, timestamp: Date.now() });
1250
1240
  broadcastToWS({
1251
1241
  type: "chat.final",
1252
1242
  text: fullText,
@@ -1255,69 +1245,51 @@ function handleRequest(req, res) {
1255
1245
  role: "assistant",
1256
1246
  timestamp: Date.now(),
1257
1247
  });
1258
- console.log(` ${DIM}Gateway SSE→WS: ${fullText.substring(0, 80)}...${RESET}`);
1248
+ console.log(` ${GREEN}✓${RESET} Gateway SSE response: ${fullText.substring(0, 80)}...`);
1259
1249
  }
1260
- sendJSON(res, 200, {
1261
- ok: true,
1262
- stored: true,
1263
- response: fullText || null,
1264
- source: "gateway-sse",
1265
- });
1266
- });
1267
-
1268
- proxyRes.on("error", () => {
1269
- sendJSON(res, 200, { ok: true, stored: true, response: null, source: "gateway-sse-error" });
1270
1250
  });
1251
+ proxyRes.on("error", () => {});
1271
1252
  } else {
1272
- // ── JSON response from gateway ──
1253
+ // JSON response from gateway
1273
1254
  const chunks = [];
1274
1255
  proxyRes.on("data", (c) => chunks.push(c));
1275
1256
  proxyRes.on("end", () => {
1276
1257
  const body = Buffer.concat(chunks).toString("utf-8");
1277
- let jsonBody;
1278
1258
  try {
1279
- jsonBody = JSON.parse(body);
1259
+ const jsonBody = JSON.parse(body);
1260
+ const inlineResponse =
1261
+ jsonBody.response || jsonBody.message || jsonBody.answer || jsonBody.text || "";
1262
+ if (inlineResponse) {
1263
+ session.messages.push({ role: "assistant", content: inlineResponse, timestamp: Date.now() });
1264
+ broadcastToWS({
1265
+ type: "chat.final",
1266
+ text: inlineResponse,
1267
+ content: inlineResponse,
1268
+ sessionKey,
1269
+ role: "assistant",
1270
+ timestamp: Date.now(),
1271
+ });
1272
+ console.log(` ${GREEN}✓${RESET} Gateway JSON response: ${inlineResponse.substring(0, 80)}...`);
1273
+ } else {
1274
+ console.log(` ${DIM}Gateway returned JSON with no response field — waiting for MCP${RESET}`);
1275
+ }
1280
1276
  } catch {
1281
- // Non-JSON — message is stored, agent will respond via MCP
1282
- sendJSON(res, 200, { ok: true, stored: true, response: null, source: "gateway-raw" });
1283
- return;
1284
- }
1285
- // Check if gateway returned an inline AI response
1286
- const inlineResponse =
1287
- jsonBody.response || jsonBody.message || jsonBody.answer || jsonBody.text || "";
1288
- if (inlineResponse) {
1289
- session.messages.push({
1290
- role: "assistant",
1291
- content: inlineResponse,
1292
- timestamp: Date.now(),
1293
- });
1294
- broadcastToWS({
1295
- type: "chat.final",
1296
- text: inlineResponse,
1297
- content: inlineResponse,
1298
- sessionKey,
1299
- role: "assistant",
1300
- timestamp: Date.now(),
1301
- });
1302
- console.log(` ${DIM}Gateway inline→WS: ${inlineResponse.substring(0, 80)}...${RESET}`);
1277
+ console.log(` ${DIM}Gateway returned non-JSON — waiting for MCP${RESET}`);
1303
1278
  }
1304
- sendJSON(res, 200, {
1305
- ok: true,
1306
- stored: true,
1307
- response: inlineResponse || null,
1308
- source: "gateway-json",
1309
- });
1310
1279
  });
1311
1280
  }
1312
1281
  });
1313
1282
 
1283
+ proxyReq.on("timeout", () => {
1284
+ proxyReq.destroy();
1285
+ console.log(` ${DIM}Gateway relay timed out — agent will respond via MCP${RESET}`);
1286
+ });
1287
+
1314
1288
  proxyReq.on("error", (err) => {
1315
- // Gateway not reachable message is still stored, agent can use MCP tools
1316
- console.log(` ${DIM}Gateway not reachable (${err.message}) — message stored for MCP polling${RESET}`);
1317
- sendJSON(res, 200, { ok: true, stored: true, response: null, source: "local-only" });
1289
+ console.log(` ${DIM}Gateway relay failed (${err.message}) agent will respond via MCP${RESET}`);
1318
1290
  });
1319
1291
 
1320
- proxyReq.write(bodyStr);
1292
+ proxyReq.write(proxyBody);
1321
1293
  proxyReq.end();
1322
1294
  })
1323
1295
  .catch(() => sendJSON(res, 400, { ok: false, error: "Bad request body" }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-navigator",
3
- "version": "5.6.1",
3
+ "version": "5.6.2",
4
4
  "description": "One-command bridge + tunnel for the Navigator browser — works on any machine, any OS",
5
5
  "keywords": [
6
6
  "browser",