From 1e0858ffe2ec7c136ee03d0cafa52c884c211890 Mon Sep 17 00:00:00 2001 From: Peter Dove Date: Wed, 28 Jan 2026 18:18:00 +0000 Subject: [PATCH] fix: trigger agent response for webchat sessions after restart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Webchat sessions don't have channel/to in their delivery context, so the restart sentinel was falling back to enqueueSystemEvent() which queues the message but doesn't trigger an agent turn. This fix passes addChatRun and broadcast through to the sentinel, allowing it to register the run and call agentCommand() so responses stream to webchat clients. 🤖 AI-assisted (Claude) --- src/gateway/server-restart-sentinel.ts | 39 +++++++++++++++++++++++++- src/gateway/server-startup.ts | 10 ++++++- src/gateway/server.impl.ts | 2 ++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/gateway/server-restart-sentinel.ts b/src/gateway/server-restart-sentinel.ts index 28719290e..a093f6467 100644 --- a/src/gateway/server-restart-sentinel.ts +++ b/src/gateway/server-restart-sentinel.ts @@ -14,7 +14,24 @@ import { defaultRuntime } from "../runtime.js"; import { deliveryContextFromSession, mergeDeliveryContext } from "../utils/delivery-context.js"; import { loadSessionEntry } from "./session-utils.js"; -export async function scheduleRestartSentinelWake(params: { deps: CliDeps }) { +export type AddChatRunFn = ( + runId: string, + entry: { sessionKey: string; clientRunId: string }, +) => void; + +export type BroadcastFn = ( + event: string, + payload: unknown, + opts?: { dropIfSlow?: boolean }, +) => void; + +export interface RestartSentinelParams { + deps: CliDeps; + addChatRun?: AddChatRunFn; + broadcast?: BroadcastFn; +} + +export async function scheduleRestartSentinelWake(params: RestartSentinelParams) { const sentinel = await consumeRestartSentinel(); if (!sentinel) return; const payload = sentinel.payload; @@ -61,7 +78,27 @@ export async function scheduleRestartSentinelWake(params: { deps: CliDeps }) { const channel = channelRaw ? normalizeChannelId(channelRaw) : null; const to = origin?.to; if (!channel || !to) { + // No outbound channel (e.g., webchat sessions use WebSocket, not channel delivery). + // For webchat: register the run with addChatRun so responses stream to the client. enqueueSystemEvent(message, { sessionKey }); + if (params.addChatRun && params.broadcast) { + const runId = `restart-${Date.now()}`; + params.addChatRun(runId, { sessionKey, clientRunId: runId }); + try { + await agentCommand( + { + message: `System: ${summary}`, + sessionKey, + runId, + deliver: false, + }, + defaultRuntime, + params.deps, + ); + } catch { + // Agent turn failed; system event already queued as fallback context + } + } return; } diff --git a/src/gateway/server-startup.ts b/src/gateway/server-startup.ts index e6bdbb0dc..78d3a8321 100644 --- a/src/gateway/server-startup.ts +++ b/src/gateway/server-startup.ts @@ -19,6 +19,8 @@ import type { loadMoltbotPlugins } from "../plugins/loader.js"; import { type PluginServicesHandle, startPluginServices } from "../plugins/services.js"; import { startBrowserControlServerIfEnabled } from "./server-browser.js"; import { + type AddChatRunFn, + type BroadcastFn, scheduleRestartSentinelWake, shouldWakeFromRestartSentinel, } from "./server-restart-sentinel.js"; @@ -37,6 +39,8 @@ export async function startGatewaySidecars(params: { }; logChannels: { info: (msg: string) => void; error: (msg: string) => void }; logBrowser: { error: (msg: string) => void }; + addChatRun?: AddChatRunFn; + broadcast?: BroadcastFn; }) { // Start clawd browser control server (unless disabled via config). let browserControl: Awaited> = null; @@ -152,7 +156,11 @@ export async function startGatewaySidecars(params: { if (shouldWakeFromRestartSentinel()) { setTimeout(() => { - void scheduleRestartSentinelWake({ deps: params.deps }); + void scheduleRestartSentinelWake({ + deps: params.deps, + addChatRun: params.addChatRun, + broadcast: params.broadcast, + }); }, 750); } diff --git a/src/gateway/server.impl.ts b/src/gateway/server.impl.ts index f641c4076..a2f9a41ce 100644 --- a/src/gateway/server.impl.ts +++ b/src/gateway/server.impl.ts @@ -503,6 +503,8 @@ export async function startGatewayServer( logHooks, logChannels, logBrowser, + addChatRun, + broadcast, })); const { applyHotReload, requestGatewayRestart } = createGatewayReloadHandlers({