From 9d991bb5f562d6d62bbdc8d60dba8fa5ab52d5b1 Mon Sep 17 00:00:00 2001 From: Clawdbot Date: Mon, 26 Jan 2026 00:15:21 +0100 Subject: [PATCH] fix(macos): menu bar activity badge not showing during agent work The gateway emits agent events with stream='lifecycle' and data.phase ('start'/'end'/'error'), but ControlChannel.swift was looking for stream='job' and data.state ('started'/'streaming'/etc). This mismatch caused the menu bar to always show 'Idle' even when the agent was actively working. Changes: - ControlChannel.swift: Handle 'lifecycle' stream instead of 'job', map phase values to the states WorkActivityStore expects - AgentEventsWindow.swift: Update stream color mapping for consistency Fixes #1932 --- apps/macos/Sources/Moltbot/AgentEventsWindow.swift | 2 +- apps/macos/Sources/Moltbot/ControlChannel.swift | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/macos/Sources/Moltbot/AgentEventsWindow.swift b/apps/macos/Sources/Moltbot/AgentEventsWindow.swift index 8e2f43eb1..32f4bab75 100644 --- a/apps/macos/Sources/Moltbot/AgentEventsWindow.swift +++ b/apps/macos/Sources/Moltbot/AgentEventsWindow.swift @@ -67,7 +67,7 @@ private struct EventRow: View { private var tint: Color { switch self.event.stream { - case "job": .blue + case "lifecycle": .blue case "tool": .orange case "assistant": .green default: .gray diff --git a/apps/macos/Sources/Moltbot/ControlChannel.swift b/apps/macos/Sources/Moltbot/ControlChannel.swift index 2af7c721d..093e89983 100644 --- a/apps/macos/Sources/Moltbot/ControlChannel.swift +++ b/apps/macos/Sources/Moltbot/ControlChannel.swift @@ -379,8 +379,11 @@ final class ControlChannel { let sessionKey = (event.data["sessionKey"]?.value as? String) ?? "main" switch event.stream.lowercased() { - case "job": - if let state = event.data["state"]?.value as? String { + case "lifecycle": + // Gateway emits phase: "start" | "end" | "error" + // WorkActivityStore expects state: "started" | "streaming" | (anything else = done) + if let phase = event.data["phase"]?.value as? String { + let state = phase.lowercased() == "start" ? "started" : "done" WorkActivityStore.shared.handleJob(sessionKey: sessionKey, state: state) } case "tool":