Webchat: poll session for messages/thinking

This commit is contained in:
Peter Steinberger
2025-12-08 16:14:12 +00:00
parent 1ac6ab4428
commit 7a7c59e91a
2 changed files with 81 additions and 0 deletions

View File

@@ -35,6 +35,13 @@ async function fetchBootstrap() {
};
}
function latestTimestamp(messages) {
if (!Array.isArray(messages) || messages.length === 0) return 0;
const withTs = messages.filter((m) => typeof m?.timestamp === "number");
if (withTs.length === 0) return messages.length; // best-effort monotonic fallback
return withTs[withTs.length - 1].timestamp;
}
class NativeTransport {
constructor(sessionKey) {
this.sessionKey = sessionKey;
@@ -190,6 +197,43 @@ const startChat = async () => {
mount.textContent = "";
mount.appendChild(panel);
logStatus("boot: ready");
// Periodically sync messages + thinking from the session store so webchat stays
// in lock-step with other transports (e.g., WhatsApp or CLI).
let lastSyncedTs = latestTimestamp(initialMessages);
const syncIntervalMs = 3000;
async function syncFromSession() {
if (agent.state.isStreaming) return; // avoid stomping in-flight turns
try {
const infoUrl = new URL(`./info?session=${encodeURIComponent(sessionKey)}`, window.location.href);
const resp = await fetch(infoUrl, { credentials: "omit" });
if (!resp.ok) return;
const info = await resp.json();
const messages = Array.isArray(info.initialMessages) ? info.initialMessages : [];
const ts = latestTimestamp(messages);
const thinking = typeof info.thinkingLevel === "string" ? info.thinkingLevel : "off";
if (ts && ts !== lastSyncedTs) {
agent.replaceMessages(messages);
lastSyncedTs = ts;
}
if (thinking && thinking !== agent.state.thinkingLevel) {
agent.setThinkingLevel(thinking);
if (panel?.agentInterface) {
panel.agentInterface.sessionThinkingLevel = thinking;
panel.agentInterface.pendingThinkingLevel = null;
if (panel.agentInterface._messageEditor) {
panel.agentInterface._messageEditor.thinkingLevel = thinking;
}
}
}
} catch (err) {
console.warn("session sync failed", err);
}
}
setInterval(syncFromSession, syncIntervalMs);
};
startChat().catch((err) => {

View File

@@ -196294,6 +196294,12 @@ async function fetchBootstrap() {
thinkingLevel: typeof info$1.thinkingLevel === "string" ? info$1.thinkingLevel : "off"
};
}
function latestTimestamp(messages) {
if (!Array.isArray(messages) || messages.length === 0) return 0;
const withTs = messages.filter((m$3) => typeof m$3?.timestamp === "number");
if (withTs.length === 0) return messages.length;
return withTs[withTs.length - 1].timestamp;
}
var NativeTransport = class {
constructor(sessionKey) {
this.sessionKey = sessionKey;
@@ -196448,6 +196454,37 @@ const startChat = async () => {
mount.textContent = "";
mount.appendChild(panel);
logStatus("boot: ready");
let lastSyncedTs = latestTimestamp(initialMessages);
const syncIntervalMs = 3e3;
async function syncFromSession() {
if (agent.state.isStreaming) return;
try {
const infoUrl = new URL(`./info?session=${encodeURIComponent(sessionKey)}`, window.location.href);
const resp = await fetch(infoUrl, { credentials: "omit" });
if (!resp.ok) return;
const info$1 = await resp.json();
const messages = Array.isArray(info$1.initialMessages) ? info$1.initialMessages : [];
const ts = latestTimestamp(messages);
const thinking = typeof info$1.thinkingLevel === "string" ? info$1.thinkingLevel : "off";
if (ts && ts !== lastSyncedTs) {
agent.replaceMessages(messages);
lastSyncedTs = ts;
}
if (thinking && thinking !== agent.state.thinkingLevel) {
agent.setThinkingLevel(thinking);
if (panel?.agentInterface) {
panel.agentInterface.sessionThinkingLevel = thinking;
panel.agentInterface.pendingThinkingLevel = null;
if (panel.agentInterface._messageEditor) {
panel.agentInterface._messageEditor.thinkingLevel = thinking;
}
}
}
} catch (err) {
console.warn("session sync failed", err);
}
}
setInterval(syncFromSession, syncIntervalMs);
};
startChat().catch((err) => {
const msg = err?.stack || err?.message || String(err);