β¨ feat(hetero-agent): support Monitor-style signal callbacks in AssistantGroup#14859
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Reportβ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## canary #14859 +/- ##
===========================================
- Coverage 82.78% 65.94% -16.84%
===========================================
Files 771 2961 +2190
Lines 62041 261831 +199790
Branches 9512 26563 +17051
===========================================
+ Hits 51359 172667 +121308
- Misses 10524 89004 +78480
- Partials 158 160 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
π New features to boost your workflow:
|
There was a problem hiding this comment.
π‘ Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33df2392c7
βΉοΈ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with π.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const nextMsg = this.messageMap.get(nextChild.id); | ||
| if (nextMsg?.role !== 'assistant') continue; | ||
| if (nextMsg.agentId !== agentId) continue; | ||
| if (getMessageSignal(nextMsg)) continue; // skip signal callbacks |
There was a problem hiding this comment.
Skip signal callbacks when locating the group tail
When a Monitor callback is followed by a real main-chain assistant under the same tool, this new skip makes collectAssistantGroupMessages follow the right assistant, but findNextAfterTools() still delegates to findLastNodeInAssistantGroup(), which blindly takes toolNode.children[0] without the same signal check. In the common order [signal callback, next tool-using assistant], the context-tree tail becomes the callback node, so transformToLinear stops or continues from the wrong place and can omit follow-up messages after the actual last assistant group; mirror this signal skip in the tail finder as well.
Useful? React with πΒ / π.
β¦ reader-side SignalCallbacksNode LOBE-8998 Phase 1 β data-layer work. Adapter detects repeated tool_results on the same tool_use.id (Monitor stdout pushes etc.) and tags the next stream_start(newStep) with an externalSignal peer field. Executor stamps metadata.signal on the new assistant message. conversation-flow MessageCollector / ContextTreeBuilder collect signal-tagged toolless assistants into a SignalCallbacksNode appended inside AssistantGroup children. UI rendering deferred to a follow-up commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
β¦ steps LOBE-8993: when a CC step produced only text (e.g. Monitor stdout drove Claude to reply without invoking a tool), the next step's parentId fell back to the previous assistant. MessageCollector only walks the assistant β tool β assistant zigzag, so each Monitor stdout line split into its own bubble. Carry the most recent tool result_msg_id across step boundaries via a `lastToolMsgIdEver` tracker so toolless middle steps still chain back to the originating tool result. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
β¦or Monitor-style callbacks Adds the UI layer of LOBE-8998. FlatListBuilder snapshots signal-callback groups onto the virtual AssistantGroup message via UISignalCallbacksBlock (new typed field on UIChatMessage) and marks each callback message processed so it does NOT render as a separate top-level bubble. AssistantGroup reads the field and renders a collapsible <SignalCallbacks> component under the main Group content, one block per source tool. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
β¦le instead of repeat tool_result
The previous detection model (count repeat tool_result per tool_use.id) was
based on a wrong assumption β Monitor's stdout pushes are NOT delivered as
additional tool_result events for the same tool_use.id. Verified against a
real `claude -p` trace: Monitor emits ONE tool_result (the initial "Monitor
started" ack), then each subsequent stdout line triggers a `system init` +
new `message_start` cycle within the same CLI process. The actual lifecycle
signal is `system task_started` (long-running tool registers) followed by
`system task_notification` (terminal).
New detection: a `message_start` that opens a new turn WITHOUT a preceding
`user` event, while at least one task is active, is a signal callback.
`task_started` records `{task_id β tool_use_id}`; `task_notification` drops it.
Verified against the recorded CC trace: 5/5 reactive turns get tagged with
correct sequence and source tool, the natural confirmation turn and the
post-task summary turn are correctly excluded.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
β¦ated Monitor inspector (LOBE-8998) The post-task summary turn (fired after `system task_notification` ends a long-running tool) was spawning its own AssistantGroup because the collector only followed the first non-signal toolless sibling under a tool_result β it never saw the summary that came after the SignalCallbacks. Adapter now stamps `signal.type = 'task-completion'` on the summary turn so the collector keeps it inside the same group, rendered AFTER the SignalCallbacks accordion (initial reply β callbacks β summary, in creation order). Also adds a dedicated `MonitorInspector` (lucide `Monitor` icon, chip shows description / command, trailing timeout label) so the Monitor tool call line stops falling back to the generic `claude-code > Monitor` display, and tightens the Flexbox spacing around SignalCallbacks + taskCompletions inside the AssistantGroup so the three sections read as one connected reply rather than disconnected blocks. Adapter: arm `pendingTaskCompletion` on `task_notification` (last-task- wins), consume it on the next natural `message_start`, clear on `result` so it never leaks across LLM runs. Tests: adapter (74) + executor (56) + conversation-flow (126) all green. Verified end-to-end in Electron with a 5-tick Monitor run β single AssistantGroup with the natural narrative inside. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
β¦up tail `findLastNodeInAssistantGroup` blindly took `toolNode.children[0]` when walking past a tool, so for the common `[signal callback, next tool-using assistant]` order the tail landed on the callback (a leaf) and `findNextAfterTools` returned null β truncating the AssistantGroup and omitting follow-up messages after the real last assistant. Mirror the signal-skip already used in `collectAssistantGroupMessages` (LOBE-8998).
ff4f2cf to
b5cdb4a
Compare
# π LobeHub Release (20260518) **Release Date:** May 18, 2026 **Since v2.1.58:** 208 merged PRs Β· 209 commits Β· 16 contributors > v2.2.0 introduces the **Chief Agent Operator** β an agent that runs itself end-to-end. It self-iterates against its own output, assembles sub-agent teams on demand through the heterogeneous runtime, and drives a unified task system that knows when to pause for a human. Self-review, AssistantGroup, and tasks/scheduling all converge into one operator surface. --- ## β¨ Highlights ### π© Chief Agent Operator - **Self-iteration exits Lab** β Agent Signal's self-review pipeline ships proposal actions straight into briefs and auto-executes the approved follow-ups, with prompts hardened against eval. The operator now critiques and re-runs its own work without a human in the loop. (#14769, #14583, #14647, #14882) - **Auto-formed agent teams** β Heterogeneous AssistantGroup gains Monitor-style signal callbacks, read-only SubAgent threads with breadcrumb headers, and a thread switcher. The operator dispatches sub-agents and you can step into any branch to see what the team is doing. (#14859, #14658, #14845, #14715) - **Task system as the operator's runway** β Claude Code surfaces task tools, AskUserQuestion freeform notes, and a dedicated `waitingForHuman` topic status; `lobe-task` exposes `setTaskSchedule`; the scheduler is hardened (maxExecutions cap, sub-10min heartbeat block, race-free SchedulerForm). Long-running operator runs no longer go silent and stop themselves when human input is needed. (#14870, #14639, #14713, #14865, #14853) ### π Cloud & runtime - **Cloud Claude Code V3** β Repo picker, GitHub token flow, and sandbox-aware context bring cloud-hosted Claude Code to feature parity with local; cloud sandbox completion now triggers the task lifecycle end-to-end. (#14568, #14822, #14681) - **Heterogeneous agent multi-replica safety** β Subagent threads, ingest refresh, and parallel-tool counts now survive replica swaps without losing parent_id or rolling back tool state. (#14897, #14631, #14806, #14838) - **Built-in tool lifecycle hooks** β `onBeforeCall` / `onAfterCall` land on the built-in tool runtime; sub-agent dispatch moves to `lobe-agent`; self-iteration aligns with the shared inspector pattern. (#14719, #14715, #14827) - **Knowledge base RAG unified** β Client and server share one `KnowledgeBaseSearchService`; KB files preserved on `NoSuchKey` instead of silently lost. (#14673, #14501) ### π¬ Workspace experience - **Home daily brief + recommendations** β The home screen opens with a linkable welcome, paired input hint, and a recommendations module sourced from the operator's hetero action library. (#14589, #14645, #14770) - **Chat mode + redesigned action bar** β The chat input gains a Chat/Agent mode toggle and a re-pitched action bar with icon-and-color action tag chips. (#14774, #14903, #14846) - **Documents tree, optimistic** β Document tree creates, deletes, and inline renames now apply optimistically; the agent-documents index hides web crawls and switches to a table layout. (#14714, #14292) - **Branded MCP inspectors** β Linear MCP tool calls render with the same branded inspector as the built-in Linear skill; CC MCP and built-in skills now share inspector code. (#14864, #14884) - **Bot identity gating** β Device tools are gated by sender identity, the activator bypass is closed, and Slack mpim plus Discord DM regressions are fixed. (#14634, #14664, #14733) --- ## ποΈ Core Agent & Signal Pipeline ### Self-iteration & Agent Signal - Self-iteration graduates out of Lab, with service, tool, name, and concept structure unified across `agent-signal`, `prompts`, `database`, and `builtin-tool-self-iteration`. (#14699, #14769) - Self-review now proposes actions to briefs and auto-executes the approved set, with eval-verified prompt hardening. (#14583, #14657, #14647) - Self-iteration built-in tool aligns with the shared runtime + inspector patterns. (#14827) - Agent Signal prompts adapt their response language and avoid blocking agent execution. (#14890, #14775, #14882) - Receipt descriptions now carry an Agent Signal marker, and self-review hinted skill documents route correctly. (#14764, #14895) ### Heterogeneous agent runtime - Subagent threads render read-only with a breadcrumb header and thread switcher; SUBAGENT badge dropped, indentation tightened. (#14658, #14845, #14783) - Multi-replica safety: ingest refresh restores tools/model from DB to fix parent_id breaks; new-step assistants sync across replicas; subagent-tagged events no longer leak into the main gateway handler. (#14897, #14631, #14838) - Fetch-triggering events are deferred to keep parallel tool counts from rolling back. (#14806) - AskUserQuestion is wired for Claude Code, with auto-decline disabled and a freeform note input on the cloud side; `waitingForHuman` is a first-class topic status. (#14639, #14629, #14870) - AssistantGroup gains Monitor-style signal callbacks; project skills surface in the working sidebar and markdown preview. (#14859, #14896) - Cloud Claude Code V3 β repo picker, GitHub token, sandbox context; credentials alert and disabled input when not configured. (#14568, #14822) - Cloud sandbox completion now triggers the task lifecycle end-to-end. (#14681) ### Agent runtime & context engine - Built-in tool runtime gets `onBeforeCall` / `onAfterCall` lifecycle hooks. (#14719) - `CompletionLifecycle`, `HumanInterventionHandler`, and `stepPresentation` are extracted from the runtime monolith. (#14441) - Per-tool timeout is honored end-to-end for client tool dispatch. (#14817) - Compression budget accounts for `tool_calls`, reasoning content, and tool defs; `call_llm` forwards tools into the budget. (#14813, #14837) - Pre-flight context check now fails fast for OpenAI-compatible providers. (#14824) - Malformed `tool_call` names are recovered instead of finishing the step silently. (#14577) - Sub-agent dispatch moves from `lobe-gtd` to `lobe-agent`. (#14715) - Hidden built-in tools now appear in the system prompt @-mention list. (#14823) ### Agent tracing & operations - New `agent_operations` table and runtime persistence for every hetero-agent operation. (#14416, #14736) - `signOperationJwt` issues 4-hour signed operation tokens. (#14586) - S3 trace snapshots are zstd-compressed; DB `trace_s3_key` aligns with the `.json.zst` suffix; legacy `.json` fallback preserved on fetch. (#14807, #14860, #14826) --- ## π± Platform & Integrations ### Bot / Channels - Device tools are gated by sender identity. (#14634) - Activator bypass closed and device-access checks converged. (#14664) - Slack mpim supported; Discord DM regression fixed; Slack connect + slash commands repaired. (#14733, #14591) - Bot channels, bot watch, bot callback service, and system bot reliability fixes. (#14847, #14796, #14570, #14784, #14649) - Online Messager scaffolding. (#14755) ### Onboarding - Home daily brief with linkable welcome and paired input hint. (#14589) - Recommendations module sourced from the hetero agent action library. (#14645) - Chat onboarding passes request triggers via metadata and preserves the resume request. (#14770, #14798) - Discovery turn progress gated by phase, with a reminder on stalled discovery. (#14842, #14833) - FullNameStep back button rejoins the shared prefix; ModeSwitch hidden in production. (#14898, #14760) - Agent marketplace folds into the web onboarding tool. (#14578, #14672) - Onboarding interests stored as keys instead of free text; early-exit skips marketplace and drops CJK prompts. (#14624, #14598) ### Model providers - Gemini 3.1 Flash-Lite cards; Gemini schema sanitizer drops non-compliant `enum` / `required`; zero `cachedContentTokenCount` handled in usage conversion. (#14604, #14740, #14567) - DeepSeek-V4 model cards and pricing restored to official rates. (#14110, #14911) - ernie-5.1 and spark-x2-flash support; Grok 4.3 `reasoning_effort` support. (#14643, #14731, #14642) - SiliconCloud catalog synced with API; duplicates removed; reasoning params adjusted. (#14464) - Minimax derives `max_tokens` from context window to avoid `ExceededContextWindow`. (#14814) - aihubmix uses the full models endpoint for a complete list; stale empty-apiKey test dropped. (#14511, #14669) - Stream parse errors are enriched with provider + model context. (#14636) - Visual content parts are consumed in the server runtime; video image references move to a JSON object. (#14637, #14900) - Google function call magic `thoughtSignature` now attaches to every part, not just the last turn. (#14904) - Service model assignments settings added; model extend-param options removed. (#14712, #14607) ### Built-in tools & knowledge base - `lobe-task` exposes `setTaskSchedule`; task scheduler hardened (maxExecutions cap, sub-10min heartbeat blocked, SchedulerForm race fix, rapid automation-mode toggle stabilized). (#14713, #14865, #14853, #14801) - KnowledgeBaseSearchService shares RAG runtime across client and server. (#14673) - KB files preserved on `NoSuchKey` and orphan documents/tasks cleaned. (#14501) - Document tree gets optimistic create/delete + inline rename. (#14714) - agent-documents index hides web crawls and switches to a table layout. (#14292) - `lobe-clarify` and SKILL.md frontmatter parsing/edit validation are unified. (#14566) - AnalyzeVisualMedia inspector + Portal HTML preview refactor; HTML preview restored for AssistantGroup messages. (#14777, #14811) - Branded inspector shared between CC MCP and built-in Linear skill. (#14884, #14864) --- ## π₯οΈ CLI & User Experience ### Chat & Conversation - Chat mode toggle and redesigned chat input action bar. (#14774) - Action tag chips switch to icon + colored label; ActionDropdown closes on sibling-open and focus-out; submenu uses native header/footer slots. (#14903, #14802, #14901) - Action bar padding equalized around the send button; skeleton shows in action bar while config loads. (#14846, #14656) - `useCmdEnterToSend` is respected in thread & task inputs; send button enables after pasting into thread/comment input. (#14850, #14816) - TopicChatDrawer state preserved during close animation. (#14803) - Only the last assistant block animates during markdown streaming. (#14906) - Right working panel no longer auto-collapses on chat mount; home agent config fetched so knowledge toggles reflect in UI. (#14883, #14834) ### Tasks - Task scheduler, hotkey, comment, and TodoList polish. (#14707) - Add Subtask button & card baseline aligned; activity card stop run; task agent manager polish. (#14848, #14559, #14569) - Task template skeleton CLS reduced; task page placeholder copy refreshed. (#14788, #14704) - Task agent model snapshotted into `task.config` at create time. (#14670) - User-feedback card, task card polish, and Run-now context menu in markdown. (#14727) - Inline skill auth in recommended task templates. (#14676) ### Navigation & Layout - Tab bar gains a Chrome-style divider between inactive tabs. (#14892) - SideBarDrawer & header layout polish; nav ActionIcon sizing unified; TodoList encapsulation improved. (#14762, #14692) - Desktop header icons, sidebar density, and task menus polished. (#14724) - Standardized header action icon sizes. (#14717) - Chat topic title length increased; copy session ID added to topic dropdown menu. (#14659, #14595) - Heterogeneous agent topic rows regain indentation. (#14783) ### Other polish - Usage token details shortened; tool execution time formatted as `Xmin Ys`. (#14849, #14641) - Tool arguments display gets word-wrap toggle; long tool-call params wrap instead of truncate. (#14706, #14640) - Editor stops showing per-line placeholder once content is present. (#14852) - Visible divider between queued messages; intervention confirmation bar polished. (#14593, #14587) - Credit top-up copy refreshed; auth captcha retry copy refreshed; brief recommendations layout polished. (#14821, #14561, #14871) --- ## π§ Tooling & Developer Experience - Dev-only feature flag override panel. (#14565) - `__DEV__` define replaces `process.env.NODE_ENV` in the SPA. (#14696) - Agent-settings drops Meta/Documents tabs and restores `inputTemplate`. (#14874) - `local-system` forwards all `grepContent` params and moves the executor to `/client`. (#14888) - `lobe-task` and `setTaskSchedule` exposed. (#14713) - Memory user-memory benchmark agent config and source-id extraction schemas. (#14779, #14778) - CLI man page drops stale cron entry; `clearMessages` hotkey removed. (#14709, #14906) - Skill docs simplified; cloud heteroContext gains sandbox TTL + public-repo fork push guide. (#14785, #14761) --- ## π Security & Reliability - **Security:** Sensitive comments and examples sanitized from the production JS bundle. (#14557) - **Security:** Inactive OIDC access rejected. (#14674) - **Security:** CASC `new Function()` template replaced with safe string builders. (#14751) - **Security:** Sign-in captcha flow removed in favor of safer flow. (#14573) - **Security:** Desktop local file previews restricted to safe roots. (#14789) - **Security:** Image binary capped at 3.75 MB so base64 payload stays under the Anthropic 5 MB limit. (#14711) - **Reliability:** Neon/Node pools get error listeners to prevent Lambda crashes. (#14606) - **Reliability:** `paradedb.match(...)` replaces hardcoded normalizer in memory search. (#14590) - **Reliability:** `PlaceholderVariablesProcessor` errors carry diagnostic context. (#14741) - **Reliability:** File storage upload checks are serialized; multiple account link bug fixed. (#14829, #14562) - **Reliability:** `ScrollShadow` replaced with `ScrollArea` to fix a React infinite render loop (error code 185). (#14689) - **Reliability:** Embedding token cap enforced β long memory queries are limited and truncated before search. (#14757) - **Reliability:** Embed binary blob guard + oversized output cap in `local-system.readFile`. (#14602) - **Reliability:** Windows npm CLI shims resolved before spawning agents. (#14772, #14720) - **Reliability:** Vite pinned to 8.0.12 to avoid the rolldown 1.0.1 preload regression; desktop runtime externals split from native deps. (#14804, #14776) - **Reliability:** Old lobehub cron job removed; WeChat URL rules dropped from web crawler. (#14630, #14633) --- ## π₯ Contributors Huge thanks to **16 contributors** who shipped **208 merged PRs** this cycle. @hezhijie0327 Β· @sxjeru Β· @hardy-one Β· @Bianzinan Β· @brone1323 Β· @YuSaZh Β· @Wxh16144 Β· @arvinxx Β· @Innei Β· @tjx666 Β· @neko Β· @lijian Β· @rdmclin2 Β· @sudongyuer Β· @AmAzing129 Β· @rivertwilight Plus @lobehubbot for maintenance translations. --- **Full Changelog**: v2.1.58...v2.2.0
π» Change Type
π Related Issue
Fixes LOBE-8998
Related to LOBE-8993, LOBE-7365
π Description of Change
Phase 1 of LOBE-8998 β introduce a first-class concept for external signals that drive reactive LLM turns (canonical case: CC's Monitor tool pushing stdout line by line, each push re-firing the model with no user turn in between). Without this, every Monitor reply renders as a separate top-level assistant bubble β see LOBE-8993 for the original UI breakage.
This PR also includes the fix from LOBE-8993 (PR #14839) as its foundation; if that PR merges first, git rebase will dedup automatically.
Architecture, top to bottom:
Adapter (
packages/heterogeneous-agents/src/adapters/claudeCode.ts) βClaudeCodeAdapternow tracks tool-name + tool_result count per main-agenttool_use.id. A 2nd+ result on the same id is treated as a callback push; the nextstream_start(newStep)carries anExternalSignalContextpeer field (tool-stdout,sourceToolCallId,sourceToolName,sequence). The pending signal survives across consecutive toolless steps so Monitor stdout sprays keep tagging; a freshtool_useclears it (LLM back on main chain). Subagent inner tool_results are excluded.Event types (
packages/heterogeneous-agents/src/types.ts) β newExternalSignalContextinterface + optionalexternalSignalfield onStreamStartData. Future-extensible discriminator:'tool-stdout' | 'tool-callback'(webhook / scheduled / agent-signal-source variants land here later).Executor (
src/store/chat/slices/aiChat/actions/heterogeneousAgentExecutor.ts) β readsevent.data.externalSignalonstream_start(newStep)and stamps it onto the created assistant message'smetadata.signal. Also carries the LOBE-8993lastToolMsgIdEverfix so toolless steps chain back to the originating tool, producing the fan-out structure the signal-callback collectors expect.Persistence (
@lobechat/typesMessageMetadata) βsignal?: MessageSignaladded to interface + Zod schema. Phase 2 (LOBE-8999) promotes to a dedicated `messages.signal` column.conversation-flow (
packages/conversation-flow) β new `SignalCallbacksNode` variant of `ContextNode`. `MessageCollector` gains `collectSignalCallbacks` (idNode walk) and `collectFlatSignalCallbacks` (flat-messages walk); `collectAssistantChain` and `collectAssistantGroupMessages` skip signal-tagged toolless siblings when picking the main-chain follower. A defensive guard ignores the signal tag on tool-using assistants (the adapter clears `pendingExternalSignal` at `tool_use` time, but the `stream_start` tag fires one event earlier).FlatListBuilder β snapshots signal-callback groups onto the virtual `assistantGroup` message via a new `UISignalCallbacksBlock` field on `UIChatMessage`; marks callback messages as processed so they do NOT render as separate top-level bubbles.
UI β new `` component (`src/features/Conversation/Messages/SignalCallbacks/`) β collapsible `Accordion` block, header shows `{{tool}} Β· {{count}} callback updates`, body is an inline timeline of each callback's content rendered via `Markdown`. `AssistantGroupMessage` renders one `` per source tool inside the group, between `` and the file/footer block.
i18n β `signalCallbacks.{title,collapse,expand,empty}` in `src/locales/default/chat.ts`.
Out of scope (deferred to LOBE-8999): promoting `metadata.signal` to a dedicated `messages.signal` column, unifying source taxonomy with the `agent-signal` package, agent-signal policy/receipt wiring.
π§ͺ How to Test
Targeted tests:
```bash
bunx vitest run --silent='passed-only' src/store/chat/slices/aiChat/actions/tests/heterogeneousAgentExecutor.test.ts
cd packages/heterogeneous-agents && bunx vitest run --silent='passed-only'
cd packages/conversation-flow && bunx vitest run --silent='passed-only'
```
`bun run type-check` clean for changed files (remaining errors are pre-existing canary issues β HtmlPreview / chatMarkdown).
Manual regression idea: replay topic `tpc_rwjDLWdz2Cvb`'s original stream-json against the desktop app β expect Monitor stdout pushes to collapse into one expandable `Monitor Β· N callback updates` block inside the AssistantGroup instead of N separate bubbles.
πΈ Screenshots / Videos
To capture after merge β see test plan above for the topic to replay.
π Additional Information
π€ Generated with Claude Code