Skip to content

Commit cb340fe

Browse files
committed
fix(bridge): buffer all delivery events for idle-Claude fallback
Channel notifications are fire-and-forget — if Claude is idle when a DM or room message arrives the push is silently lost. Buffering every event in the drain ensures it surfaces on the next tool call regardless of whether the channel notification landed. Actionable events still get the eager channel push for mid-turn delivery; the drain echo on the following call is an acceptable trade-off.
1 parent 1e4578e commit cb340fe

1 file changed

Lines changed: 8 additions & 7 deletions

File tree

src/bridges/claude-code/channel.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export async function run(): Promise<void> {
3838
store.setTransport(new TlsTransport(store.events, identity));
3939
const tool = new CommsTool(store, store.discovery);
4040
let agentId: string | undefined;
41-
const informationalBuffer: string[] = [];
41+
const pendingBuffer: string[] = [];
4242

4343
const mcp = new McpServer(
4444
{ name: "agent-comms", version: "0.2.0" },
@@ -49,14 +49,17 @@ export async function run(): Promise<void> {
4949
},
5050
);
5151

52-
// Actionable events with a non-info hint push immediately as channel
53-
// notifications. Everything else (informational system events, or messages
54-
// the sender flagged as info) buffers and drains on the next tool call.
52+
// All events land in the drain buffer so idle-Claude never silently misses
53+
// a message. Actionable events also get an eager channel push for mid-turn
54+
// delivery. If the push fired and Claude caught it, the drain will echo it
55+
// on the next tool call — acceptable duplication, far better than loss.
5556
store.onDelivery = async (_targetId: string, event) => {
5657
const line = formatDeliveryEvent(event);
5758
const hint = extractStreamingBehavior(event);
5859
const shouldPush = isActionableEvent(event) && hint !== "info";
5960

61+
pendingBuffer.push(line);
62+
6063
if (shouldPush) {
6164
await mcp.server.notification({
6265
method: "notifications/claude/channel",
@@ -65,8 +68,6 @@ export async function run(): Promise<void> {
6568
meta: { streamingBehavior: hint ?? "steer" },
6669
},
6770
});
68-
} else {
69-
informationalBuffer.push(line);
7071
}
7172
};
7273

@@ -114,7 +115,7 @@ export async function run(): Promise<void> {
114115
action,
115116
);
116117

117-
const pending = informationalBuffer.splice(0);
118+
const pending = pendingBuffer.splice(0);
118119
const prefix =
119120
pending.length > 0
120121
? `[comms] Pending:\n${pending.map((l) => ` 📬 ${l}`).join("\n")}\n\n`

0 commit comments

Comments
 (0)