68 lines
2.4 KiB
JavaScript
68 lines
2.4 KiB
JavaScript
const { LOG_BUFFER_MAX, VM_LOG_BUFFER_MAX } = require("./config");
|
|
const { workspace } = require("./workspace");
|
|
const { logChatMessage } = require("./session/chat-log");
|
|
|
|
// Ring buffer of VM-level log lines (server stdout/stderr) replayed to new
|
|
// WebSocket clients on connect.
|
|
const vmLogBuffer = [];
|
|
|
|
function broadcastVmLog(line) {
|
|
const ts = new Date().toISOString();
|
|
vmLogBuffer.push({ ts, line });
|
|
if (vmLogBuffer.length > VM_LOG_BUFFER_MAX)
|
|
vmLogBuffer.splice(0, vmLogBuffer.length - VM_LOG_BUFFER_MAX);
|
|
const payload = JSON.stringify({ type: "vm_log", ts, content: line });
|
|
for (const client of workspace.streamClients) {
|
|
if (client.readyState === 1) client.send(payload);
|
|
}
|
|
}
|
|
|
|
// Patch console so every log line is also broadcast to connected clients.
|
|
// This runs as a side effect on first require so all subsequent console calls
|
|
// are captured, including those from submodules loaded after this one.
|
|
const _origLog = console.log;
|
|
const _origWarn = console.warn;
|
|
const _origError = console.error;
|
|
console.log = (...args) => {
|
|
_origLog(...args);
|
|
broadcastVmLog(args.map(String).join(" "));
|
|
};
|
|
console.warn = (...args) => {
|
|
_origWarn(...args);
|
|
broadcastVmLog("[warn] " + args.map(String).join(" "));
|
|
};
|
|
console.error = (...args) => {
|
|
_origError(...args);
|
|
broadcastVmLog("[error] " + args.map(String).join(" "));
|
|
};
|
|
|
|
function broadcast(message) {
|
|
const msgObj =
|
|
typeof message === "string" ? { type: "raw", content: message } : message;
|
|
const payload =
|
|
typeof message === "string" ? message : JSON.stringify(message);
|
|
|
|
// Persist chat messages (user + assistant turns) to the session log.
|
|
if (msgObj.type === "chat_message" && msgObj.role && msgObj.content) {
|
|
logChatMessage({ role: msgObj.role, content: msgObj.content });
|
|
}
|
|
|
|
// Transient events that update the UI in real-time but carry no useful
|
|
// state for late-joining clients. Skip buffering to keep the log lean.
|
|
const TRANSIENT_TYPES = new Set(["llm_status", "proxy_usage"]);
|
|
|
|
const ts = new Date().toISOString();
|
|
if (!TRANSIENT_TYPES.has(msgObj.type)) {
|
|
workspace.logBuffer.push({ ...msgObj, _ts: ts });
|
|
if (workspace.logBuffer.length > LOG_BUFFER_MAX) {
|
|
workspace.logBuffer = workspace.logBuffer.slice(-LOG_BUFFER_MAX);
|
|
}
|
|
}
|
|
|
|
for (const client of workspace.streamClients) {
|
|
if (client.readyState === 1) client.send(payload);
|
|
}
|
|
}
|
|
|
|
module.exports = { broadcast, broadcastVmLog, vmLogBuffer };
|