openclaw-navigator 5.7.5 → 5.7.6
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.
- package/cli.mjs +22 -65
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -1216,7 +1216,8 @@ function handleRequest(req, res) {
|
|
|
1216
1216
|
chatHistory.unshift({ role: "user", content: message });
|
|
1217
1217
|
}
|
|
1218
1218
|
const proxyBody = JSON.stringify({
|
|
1219
|
-
|
|
1219
|
+
message: message, // BFF expects "message" (singular) — the current user text
|
|
1220
|
+
messages: chatHistory, // Also send full history for OpenAI-compatible endpoints
|
|
1220
1221
|
stream: true,
|
|
1221
1222
|
});
|
|
1222
1223
|
// Build cookie header: prefer captured BFF cookies, fall back to browser's cookies
|
|
@@ -1612,77 +1613,33 @@ function handleRequest(req, res) {
|
|
|
1612
1613
|
return;
|
|
1613
1614
|
}
|
|
1614
1615
|
|
|
1615
|
-
// ── SSE
|
|
1616
|
-
//
|
|
1617
|
-
//
|
|
1618
|
-
// the "data: " prefix). So we collect the full SSE stream, extract the
|
|
1619
|
-
// text, and return a single JSON response. Also store + broadcast via WS.
|
|
1616
|
+
// ── SSE passthrough for streaming endpoints (/api/chat) ────────────
|
|
1617
|
+
// Pass SSE through as-is — the web UI frontend handles SSE natively.
|
|
1618
|
+
// Disable response buffering so each SSE event reaches the client immediately.
|
|
1620
1619
|
if (isSSE && isStreamingEndpoint) {
|
|
1621
|
-
console.log(` ${DIM}SSE
|
|
1620
|
+
console.log(` ${DIM}SSE passthrough: ${path}${RESET}`);
|
|
1622
1621
|
|
|
1623
|
-
|
|
1624
|
-
|
|
1622
|
+
// Ensure SSE headers are clean for the browser
|
|
1623
|
+
headers["cache-control"] = "no-cache";
|
|
1624
|
+
headers["connection"] = "keep-alive";
|
|
1625
|
+
// Keep content-type as text/event-stream
|
|
1626
|
+
delete headers["content-length"]; // SSE is chunked
|
|
1625
1627
|
|
|
1626
|
-
proxyRes.
|
|
1628
|
+
res.writeHead(proxyRes.statusCode ?? 200, headers);
|
|
1629
|
+
|
|
1630
|
+
// Disable buffering at every layer
|
|
1631
|
+
if (res.socket) res.socket.setNoDelay(true);
|
|
1632
|
+
|
|
1633
|
+
// Pipe SSE events directly — no transformation
|
|
1627
1634
|
proxyRes.on("data", (chunk) => {
|
|
1628
|
-
|
|
1635
|
+
res.write(chunk);
|
|
1636
|
+
// Flush after each chunk to prevent TCP buffering
|
|
1637
|
+
if (typeof res.flush === "function") res.flush();
|
|
1629
1638
|
});
|
|
1630
1639
|
|
|
1631
1640
|
proxyRes.on("end", () => {
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
if (line.startsWith("data: ")) {
|
|
1635
|
-
const raw = line.slice(6).trim();
|
|
1636
|
-
if (raw === "[DONE]" || !raw) continue;
|
|
1637
|
-
try {
|
|
1638
|
-
const evt = JSON.parse(raw);
|
|
1639
|
-
const delta =
|
|
1640
|
-
evt.choices?.[0]?.delta?.content ||
|
|
1641
|
-
evt.delta?.text ||
|
|
1642
|
-
evt.text ||
|
|
1643
|
-
evt.content ||
|
|
1644
|
-
"";
|
|
1645
|
-
if (delta) fullText += delta;
|
|
1646
|
-
} catch {
|
|
1647
|
-
if (raw) fullText += raw;
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
|
-
// Return as a single OpenAI-compatible JSON response
|
|
1653
|
-
const result = {
|
|
1654
|
-
id: "chatcmpl_bridge_" + Date.now(),
|
|
1655
|
-
object: "chat.completion",
|
|
1656
|
-
created: Math.floor(Date.now() / 1000),
|
|
1657
|
-
choices: [{
|
|
1658
|
-
index: 0,
|
|
1659
|
-
message: { role: "assistant", content: fullText },
|
|
1660
|
-
finish_reason: "stop",
|
|
1661
|
-
}],
|
|
1662
|
-
};
|
|
1663
|
-
|
|
1664
|
-
headers["content-type"] = "application/json";
|
|
1665
|
-
delete headers["content-length"];
|
|
1666
|
-
delete headers["transfer-encoding"];
|
|
1667
|
-
res.writeHead(200, headers);
|
|
1668
|
-
res.end(JSON.stringify(result));
|
|
1669
|
-
|
|
1670
|
-
// Broadcast via WebSocket for live updates (but DON'T store in
|
|
1671
|
-
// bridge chat session — web UI manages its own conversation state
|
|
1672
|
-
// separately from sidepane chat. Mixing them causes 400 errors from
|
|
1673
|
-
// the BFF due to malformed message history.)
|
|
1674
|
-
if (fullText) {
|
|
1675
|
-
broadcastToWS({
|
|
1676
|
-
type: "chat.webui",
|
|
1677
|
-
text: fullText,
|
|
1678
|
-
content: fullText,
|
|
1679
|
-
role: "assistant",
|
|
1680
|
-
timestamp: Date.now(),
|
|
1681
|
-
});
|
|
1682
|
-
console.log(` ${GREEN}✓${RESET} Chat response (${fullText.length} chars): ${fullText.substring(0, 80)}...`);
|
|
1683
|
-
} else {
|
|
1684
|
-
console.log(` ${DIM}SSE stream ended with no content${RESET}`);
|
|
1685
|
-
}
|
|
1641
|
+
res.end();
|
|
1642
|
+
console.log(` ${GREEN}✓${RESET} SSE stream completed for ${path}`);
|
|
1686
1643
|
});
|
|
1687
1644
|
|
|
1688
1645
|
proxyRes.on("error", (err) => {
|