🎨 style(claude-code): tool inspectors + heterogeneous-agent follow-ups#14030
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 #14030 +/- ##
==========================================
+ Coverage 66.86% 66.93% +0.07%
==========================================
Files 2100 2103 +3
Lines 179535 179818 +283
Branches 21192 17792 -3400
==========================================
+ Hits 120038 120363 +325
+ Misses 59373 59331 -42
Partials 124 124
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: 0260d94b34
ℹ️ 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".
| /** Look up a subagent run by the tool_call_id of ANY tool inside it. */ | ||
| const findRunByInnerToolCallId = (toolCallId: string): SubagentRunState | undefined => { | ||
| for (const run of subagentRuns.values()) { | ||
| if (run.state.persistedIds.has(toolCallId)) return run; |
There was a problem hiding this comment.
Preserve subagent tool-call lookup across turn boundaries
findRunByInnerToolCallId only checks run.state.persistedIds, but that set is turn-scoped and gets replaced when subagentMessageId advances in ensureSubagentRun. If a subagent tool_result is delayed until after a turn transition, this lookup returns no run, so the thread-bucket updateMessage path is skipped and the tool bubble can remain stuck in loading state until the thread is reopened (main fetchAndReplaceMessages does not hydrate thread buckets).
Useful? React with 👍 / 👎.
… inspector CC emits three tool calls we were previously rendering as raw JSON: `ScheduleWakeup` (self-paced /loop), `TaskOutput` (read from background task), `TaskStop` (terminate background task). Add dedicated inspectors and register them alongside the existing CC tool set. `TaskStop` accepts both `task_id` and the legacy `shell_id` field name since older CC builds still emit the latter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r filter Two sibling components in each chat-topic sidebar were both calling `useFetchTopics`, but with different args: the outer `Topic` passed the preference-driven `excludeStatuses: ['completed']` filter while the inner `List` / `TopicListContent` called it bare. Since `excludeStatuses` is part of the SWR key, both calls fired independent requests whose `onData` handlers wrote back to the same `topicDataMap[containerKey]` slot — whichever response landed last won, and when the un-filtered sibling won, completed topics reappeared in the sidebar despite the "Include completed" preference being off. Introduce `useFetchChatTopics` as the single call site for chat-topic fetching. It reads `topicIncludeCompleted` from preferences and pins `excludeTriggers` to the always-excluded cron/eval set, so every sibling mounts with identical args, collapses onto one SWR key, and SWR dedupes them to a single request. Group sidebars now also exclude cron/eval triggers for parity with the agent sidebar (groups don't produce either trigger today, so this is a no-op in practice but prevents divergence if the rules change). Popup and mobile-modal call sites keep using the raw `useFetchTopics` because they deliberately need the unfiltered set — the popup has to resolve a specific (possibly completed) topic's title from the map. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…essions When the active agent is backed by a heterogeneous provider (currently only `claude-code`), swap the generic "Ask, create, or start a task" placeholder for a task-specific variant that names the provider (e.g. "Ask Claude Code to do a task"). @-mention assignment hint is suppressed in that mode since heterogeneous agents don't yet route to sibling agents.
Local preview translations for the new heterogeneous-agent chat input placeholder; en-US mirrors the default, zh-CN carries the Chinese copy. CI regenerates locale JSON on release so this commit only seeds dev preview.
…and calls
Both branches of getWorkflowSummaryText now share the same suffix structure:
list · 共 N 种工具 · 共 X 次调用 · N 次失败. summaryMoreTools changes from
remaining count ("+N more" / "等 N 种工具") to total count, and the inline
(failed) per-tool marker is dropped in favor of the global error suffix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Show "N tool kinds" only when the displayed list is truncated, and "X calls total" only when at least one tool was called more than once. Otherwise the aggregates duplicate information already visible in the per-tool list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Heterogeneous-agent placeholder (e.g. "让 Claude Code 帮你完成任务…") no longer trails the "press ⌘↵ to insert a line break" hotkey hint, which read awkwardly attached to a short single-clause prompt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Search Drop leading lucide icons, add `:` suffix so the label row reads like ToolSearch, and promote ScheduleWakeup's `reason` into the chip with `delaySeconds` trailing as secondary context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…turn boundaries `findRunByInnerToolCallId` consulted `run.state.persistedIds`, but that set is wiped every time `ensureSubagentRun` advances `subagentMessageId`. A `tool_result` delayed past the owning turn therefore failed the lookup and skipped the thread-bucket `run.stream.update`, leaving the in-thread tool bubble stuck on its loading spinner until the user re-opened the Thread (main-topic `fetchAndReplaceMessages` doesn't rehydrate thread buckets). Add a run-lifetime `lifetimeToolCallIds` set that only grows and route the lookup through it; leave `state.persistedIds` as-is so `persistToolBatch`'s turn-scoped dedupe is untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8e8cf96 to
3d6fd11
Compare
# 🚀 LobeHub v2.1.53 (20260427) **Release Date:** April 27, 2026 **Since v2.1.52:** 194 merged PRs · 17 contributors > Introduce Heterogeneous Agent — Claude Code and Codex run as first-class desktop runtimes, paired with a new Agent Signal package, sharper desktop UX, and a wave of flagship model additions. --- ## ✨ Highlights - **Introduce Heterogeneous Agent** — Claude Code and Codex run as first-class desktop agents: subagent rendering, partial-message streaming, multi-turn resume, terminal error surfacing, rich tool inspectors, and runtime polish. (#14162, #13754, #14067, #14001, #13970, #13942) - **Screen capture & Quick Chat tray** — New desktop screen capture overlay (macOS permission-gated) with Quick Chat tray and upload pipeline improvements; chat input auto-focuses on overlay mount. (#13818, #14097, #14105) - **Desktop topic & tab UX** — Dedicated topic popup window with cross-window sync, Cmd+W/Cmd+T tab shortcuts, TabBar polish, recent working directories expanded to 20, and human approval notifications. (#13957, #13983, #13972, #14036, #14092) - **Git workflow built-in** — One-click pull/push from the branch chip, ahead/behind badge, and submodule/worktree repo detection. (#14041, #13980, #13978) - **Agent Signal package** — New `@lobechat/agent-signal` runtime for dynamic memory feedback signals, with OTel metrics and self-iteration in Lab. (#14157, #14170, #14159, #14169, #14187) - **New models** — Claude Opus 4.7 with `xhigh` effort tier, GPT-5.5, DeepSeek V4 Flash/Pro with reasoning slider, Kimi K2.6, MiMo-V2.5/Pro, gpt-image-2, Qwen3.6 Flash/Plus, and Pixverse-c1. (#13903, #14147, #14114, #14004, #14089, #14039, #13923) - **New providers** — OpenCode Zen, OpenCode Go, and Azure OpenAI Router runtime. (#13943, #14064, #13823) - **Mobile settings overhaul** — Full settings menu and responsive profile layout for mobile. (#14019) --- ## 🏗️ Heterogeneous Agent - Claude Code runtime, working-directory awareness, and sidebar polish. (#13970) - CC subagent rendering with persistent streamed text; parallel-tool orphan fix. (#14001, #13968, #14024) - Per-step usage persisted to each step assistant message. (#13964) - Per-phase workflow expand defaults; full-expand toggle with three-level expansion. (#14171, #13906) - Hetero-mode actions bar; tool inspector polish. (#13963, #14034, #14030) - Codex desktop integration with rich tool rendering and devtools preview. (#14067, #14100) - Codex terminal error surfacing and CLI output tracing. (#14166) - Tighten `isCanUseVision` default and add aggregator fallback. (#14172) - Persist `ccSessionId` in topic metadata for CC multi-turn resume. (#13902) - CC account card, topic filter, and integration polish. (#13955, #13942, #13950) - Token-level deltas streamed via `--include-partial-messages`. (#13929) --- ## 🧠 Agent Signal & Self-Iteration - New `@lobechat/agent-signal` package with dynamic feedback signals. (#14157) - AgentSignalRuntime wired through agent-tracing and observability-otel metrics. (#14170, #14159) - Self-iteration feature flag added to Lab; front-side flag check. (#14169, #14186) - Signal policy for receiving memory feedback dynamically. (#14187) --- ## 💬 Conversation - Queue follow-up sends during running CC turns. (#14179) - Persist per-topic chat scroll position; pin user message + fold long messages. (#14191, #14056) - Inline resend when editing last user message. (#14080) - Disable first-block markdown streaming to prevent flicker. (#14193, #13904) - Prevent Markdown stream replay when vlist remounts streaming items. (#14086) - Stop repinning after manual scroll; unify scroll-to-user + spacer hooks. (#14099, #14132) --- ## 📱 Platforms & Integrations ### Desktop / Electron - Screen capture overlay, Quick Chat tray, and upload pipeline improvements. (#13818) - macOS permission gate for screen capture; auto-focus chat panel input. (#14097, #14105) - Dedicated topic popup window with cross-window sync. (#13957) - TabBar polish: `+` button for new topic, dark theme blend, close icon by default. (#13972, #14203, #13973) - Recent working directories expanded from 5 to 20; submodule/worktree repo detection. (#14036, #13978) - Cmd+W / Cmd+T tab shortcuts and global shortcut consolidation. (#13983, #13880) - Linux icon configuration; human approval desktop notifications. (#14042, #14092) ### Git Workflow - One-click pull/push from branch chip; ahead/behind badge with refactored GitCtr. (#14041, #13980) ### Mobile - Full settings menu and responsive profile layout. (#14019) - Agent route added to mobile router; mobile agent topic route registered. (#14103, #14158) - Session list skeleton row layout corrected. (#14040) ### Bot / Messaging - DM strategy support; bot emoji and markdown render optimization. (#14201, #14091, #14140) - Slack webhook fix; bot platform setup guide reference. (#14052, #14121) --- ## 🤖 Models & Providers ### New models - **Claude Opus 4.7** with `xhigh` effort tier; strip temperature/top_p. (#13903, #13909) - **GPT-5.5**. (#14147) - **DeepSeek V4** Flash/Pro cards with reasoning slider; cache-hit and Pro discount pricing. (#14114, #14209, #14196, #14131) - **Kimi K2.6** model with LobeHub-hosted card. (#14004, #14006) - **MiMo-V2.5 / V2.5-Pro**. (#14089) - **gpt-image-2**, **Qwen3.6 Flash/Plus**, **Pixverse-c1**. (#14039, #13923) ### New providers - **OpenCode Zen** and **OpenCode Go** with env-var support. (#13943, #14064) - **Azure OpenAI Router** runtime support. (#13823) - Model alias mapping for image and video runtimes. (#13896) - Seedance video models migrated to Dreamina. (#14144) ### Runtime reliability - Sanitize invalid tool_call arguments to unbreak strict providers. (#14033) - Tolerate null `function.name` in streaming tool_call deltas. (#14139) - Preserve Gemini 3 `thoughtSignature` in `call_tools_batch` normalization. (#14032) - Downgrade `image_url` parts when target model lacks vision. (#14029) - Preserve Cloudflare provider error context. (#14136) - Use `safety_identifier` for OpenAI Responses API. (#14148) - Unwrap underlying PG error in `formatErrorEventData`. (#14038) --- ## 🖥️ User Experience - **Onboarding** — Preset agent naming suggestions, structured hunk ops for `updateDocument`, persona analytics snapshot, footer promotion pipeline, wrap-up button. (#13931, #13989, #13930, #13853, #13934) - **Document workflow** — Agent documents promoted as primary workspace panel; history management and compare workflow; web-crawl docs associated with agent documents. (#13924, #13725, #13893) - **cmdk** — Agent identity surfaced on topic search results; topic/message search scoped to current agent. (#14204, #13960) - **Floating chat panel** and workspace improvements. (#13887) - **Topic completion status** with dropdown action and filter. (#14005) --- ## 🔧 Tooling - Redis-backed feature flag provider for runtime config. (#14098) - Vite upgraded to 8.0.0 with Rolldown strict execution order. (#12720, #14058) - `@lobechat/model-bank` automated npm release with provenance. (#14015, #14017, #14018) - Skill activation fallback when `activateTools` cannot find identifier. (#14010) - Cron tool: timezone and existing jobs injected into system prompt; clarified `lobe-gtd` and `lobe-cron` descriptions. (#14012, #14013) --- ## 🔒 Security & Reliability - **Security:** uuid bumped to v14 (advisory). (#14083) - **Security:** validate avatar URL and scope old-avatar deletion to owner. (#13982) - **Security:** clear OIDC sessions on better-auth signout; return 401 (not 500) for expired OIDC JWT. (#13916, #14014) - **Reliability:** scope pending-approval check to current assistant turn. (#14182) - **Reliability:** sanitize heterogeneous-agent attachment cache filenames. (#13937) - **Reliability:** reduce subagent task status error noise. (#14026) --- ## 👥 Contributors Huge thanks to **17 contributors** who shipped **194 merged PRs** this week. @hardy · @shaun0927 · @hezhijie0327 · @sxjeru · @arvinxx · @Innei · @tjx666 · @lijian · @neko · @rdmclin2 · @AmAzing129 · @sudongyuer · @CanisMinor · @rivertwilight Plus @lobehubbot and renovate[bot] for maintenance. --- **Full Changelog**: v2.1.52...v2.1.53
💻 Change Type
🔗 Related Issue
Follow-up polish after LOBE-7365 / #14024 landed in canary.
🔀 Description of Change
Nine commits across five independent threads; no shared code path so each can be reviewed in isolation.
CC tool inspectors (new)
f96e06201f✨ render dedicated inspectors forScheduleWakeup(self-paced /loop),TaskOutput(read from background task), andTaskStop(terminate background task). These three were falling back to the generic(param:value 等 N 个参数)row.TaskStopaccepts bothtask_idand the legacyshell_idfield name since older CC builds still emit the latter.6391860a9f🎨 align those inspectors with the existingToolSearchshape: drop the leading lucide icon, add the:label suffix, and put ScheduleWakeup's human-readablereasonin the chip withdelaySecondstrailing as secondary context.Heterogeneous-agent subagent regression fix
3d6fd113e8🐛 retain subagent tool-call lookup across turn boundaries.findRunByInnerToolCallIdconsultedrun.state.persistedIds, but that set is wiped each timeensureSubagentRunadvancessubagentMessageId. A delayedtool_resultfor a prior turn'stool_usetherefore missed the lookup and skipped the thread-bucketrun.stream.update, leaving the in-thread tool bubble stuck on its loading spinner until the user re-opened the Thread (main-topicfetchAndReplaceMessagesdoes not rehydrate thread buckets). Adds a run-lifetimelifetimeToolCallIdsset (append-only) and routes the lookup through it;state.persistedIdsstays turn-scoped forpersistToolBatch's dedupe.Chat input placeholder for CC sessions
08ddddebc2✨ swap the generic chat-input placeholder for a task-specific variant when the active agent is backed by a heterogeneous provider (e.g. "Ask Claude Code to do a task"). Suppresses the @-mention assignment hint in that mode since heterogeneous agents don't yet route to sibling agents.fb52b7d6d6🌐 en-US + zh-CN dev preview translations for the new placeholder key (CI regenerates locale JSON on release).0517b6b7f9🎨 drop the trailing ⌘↵ hotkey hint for the heterogeneous variant — it read awkwardly attached to a short single-clause prompt.Workflow summary polish
732137e145♻️ unify both branches ofgetWorkflowSummaryTextonto one suffix structure:list · 共 N 种工具 · 共 X 次调用 · N 次失败. Replaces the inline per-tool(failed)marker with the global error suffix.3151d2bb7f♻️ hide the kinds/calls suffixes when they would duplicate what the per-tool list already shows (N kinds only when truncated, X calls only when at least one tool was called more than once).Sidebar topic filter
67ea4c6858🐛 stop completed topics from leaking past the sidebar filter. The outerTopicand innerList/TopicListContenteach mounteduseFetchTopicswith different args — outer passedexcludeStatuses: ['completed'], inner called it bare. SinceexcludeStatusesis part of the SWR key, both fired independent requests whoseonDatahandlers wrote back to the sametopicDataMap[containerKey]slot, and whichever landed last won. IntroducesuseFetchChatTopicsas the single call site so every sibling mounts with identical args and SWR dedupes to one request.🧪 How to Test
Regression test added to
src/store/chat/slices/aiChat/actions/__tests__/heterogeneousAgentExecutor.test.tsunderCC subagent thread-container > routes delayed tool_result to thread bucket when it arrives after subagent turn has rolled over: subagent emits turn-1 tool_use, turn advances (subagentMessageIdchanges), turn-1's delayedtool_resultlands — asserts the thread-scopedupdateMessagedispatch still fires with the result content. Verified the test fails on the pre-fix lookup.Manual smoke:
tool_resultclears the loading spinner without reopening the Thread.📸 Screenshots / Videos
ToolSearch-style inspector layout shared inline in the review thread.
📝 Additional Information
No breaking changes, no migrations.
useFetchChatTopicsis a thin wrapper overuseFetchTopics— the popup and mobile-modal call sites intentionally keep using rawuseFetchTopicsbecause they need the unfiltered set to resolve titles for already-completed topics.