You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(bridge): add asyncRewake hooks for idle-Claude delivery
Replace the in-memory pendingBuffer in the Claude Code bridge with a
file-backed queue at ~/.agents/bus/pending/claude-code--<slug>.jsonl.
Both the in-process tool-call drain and the new out-of-process hook
drain script use atomic rename as the synchronisation primitive, so
concurrent drains never duplicate or lose events.
Add hooks/drain.sh and hooks/hooks.json. The hooks declare PostToolUse,
Stop, and UserPromptSubmit entries that invoke drain.sh via asyncRewake.
When pending events exist, drain.sh exits 2 with the content on stderr;
Claude Code wraps it in a <system-reminder> and wakes idle Claude via
the enqueuePendingNotification / useQueueProcessor path.
This removes the dependency on notifications/claude/channel (gated by
tengu_harbor_ledger) for delivery to idle Claude sessions.
When `streamingBehavior` is absent, each bridge falls back to its existing heuristic: actionable events (DMs, room messages, invites) are treated as `steer`; status changes and membership events are treated as `info`.
219
219
220
-
**Limitations on non-native harnesses**: Claude Code's channel protocol is a single-lane push — there is no runtime mechanism to force a mid-call interrupt. The `[STEER]` and `[FOLLOWUP]` markers are visible in the session and structured `meta.streamingBehavior`carries the intent, but acting on them is down to the receiving agent. The pi bridge honours the hint natively.
220
+
**Claude Code delivery mechanism**: Events are written to `~/.agents/bus/pending/claude-code--<cwd-slug>.jsonl`. Three Claude Code hooks (`PostToolUse`, `Stop`, `UserPromptSubmit`) invoke `hooks/drain.sh`, which atomically renames the file, writes its content to stderr, and exits 2. Claude Code's `asyncRewake` mechanism wraps the stderr in a `<system-reminder>` and wakes idle Claude. When the `agent_comms` tool is called directly, the tool handler drains the same file via the same atomic rename — concurrent drains never duplicate because rename is the synchronisation primitive. The `[STEER]` and `[FOLLOWUP]` markers and `meta.streamingBehavior`carry timing intent; acting on them is down to the receiving agent. The pi bridge honours the hint natively via `deliverAs`.
0 commit comments