Files
Neko 8ad5b8bfd7 🔨 chore: sync release/weekly-20260827 with latest canary (#18786)
* ✨ feat(heterogeneous-agent): support Grok provider bindings (#18737)

* ✨ feat(db): add workspace document comment schema (#18726)

* ✨ feat(db): add workspace document comment schema

* ♻️ refactor(db): use UUIDs for document comments

* 🐛 fix(db): sync comments during document transfers

* 🐛 fix(db): harden document comment transfers

* 🔨 chore(db): regenerate document comment migration

* 🐛 fix: align chat output cost estimate ratio (#18748)

* ♻️ refactor(desktop): migrate renderer OTA to V2 packs (#18745)

* ♻️ refactor(desktop): migrate renderer OTA to V2 packs

* ⚡️ perf(desktop): decode renderer packs asynchronously

* 💄 style(toast): align toast radius and offsets with desktop layout container (#18755)

* 👷 ci(desktop): read the overlay repository from a variable instead of hardcoding (#18759)

Claude-Session: https://claude.ai/code/session_01TQcoZnDo12NGCxWZDJpciZ

* 👷 ci(share): add PR-time verify workflow for the share micro app (#18757)

* 👷 ci(share): add PR-time verify workflow for the share micro app

Claude-Session: https://claude.ai/code/session_01TQcoZnDo12NGCxWZDJpciZ

* 👷 ci(share): build same-repo PR previews with the cloud overlay

Claude-Session: https://claude.ai/code/session_01TQcoZnDo12NGCxWZDJpciZ

* 📝 docs(skill): record dual-repo share verify and skeleton layout parity

Claude-Session: https://claude.ai/code/session_01TQcoZnDo12NGCxWZDJpciZ

* 👷 ci(share): keep overlay naming neutral in public workflow

Claude-Session: https://claude.ai/code/session_01TQcoZnDo12NGCxWZDJpciZ

* 👷 ci(share): reuse the existing overlay token secret

Claude-Session: https://claude.ai/code/session_01TQcoZnDo12NGCxWZDJpciZ

* ♻️ refactor: migrate lobe-cron to lobe-task (#18753)

* 💄 style(share): center skeleton hero to match hydrated layout (#18756)

Claude-Session: https://claude.ai/code/session_01TQcoZnDo12NGCxWZDJpciZ

* 💄 style: register dedicated skeletons for all lazy routes (#18752)

* 💄 style: add dedicated home route skeleton

* 💄 style: register route skeletons for all lazy routes

* ✅ test: align unit test mocks with base-ui component migration

* ✅ test: complete base-ui mock alignment for migrated components

Claude-Session: https://claude.ai/code/session_01UTDivfaszDuBjpPn7PV7gQ

* 📌 chore: pin @lobehub/ui to 5.33.1 until base-ui migration completes

Claude-Session: https://claude.ai/code/session_01UTDivfaszDuBjpPn7PV7gQ

* ♻️ refactor: finish ActionIcon, Avatar, Tag and Text base-ui migration

Completes #18729: migrates the 45 remaining call sites (plus type-only
imports) to @lobehub/ui/base-ui and drops the temporary 5.33.1 pin now
that the repo is clean under 5.33.3's expanded deprecation list.

Claude-Session: https://claude.ai/code/session_01UTDivfaszDuBjpPn7PV7gQ

* ♻️ refactor: migrate direct antd Tag and Avatar imports to base-ui

Claude-Session: https://claude.ai/code/session_01UTDivfaszDuBjpPn7PV7gQ

* ✅ test: stub base-ui ActionIcon in input banner queue case (#18760)

* ✅ test: stub base-ui ActionIcon in input banner queue case

The real base-ui ActionIcon requires the app-level MotionProvider, which
the unit env does not set up.

Claude-Session: https://claude.ai/code/session_01UTDivfaszDuBjpPn7PV7gQ

* ✅ test: render real base-ui components via a global MotionProvider stub

Redirect @lobehub/ui's internal MotionProvider module to a static stub in
vitest config so base-ui components render in unit tests without the
app-level ConfigProvider, and add composable canonical base-ui stubs
(~base-ui-stubs) for tests that want simplified DOM.

Claude-Session: https://claude.ai/code/session_01UTDivfaszDuBjpPn7PV7gQ

* ✅ test: unblock closed antd-style factories against migrated base-ui imports

Six antd-style mocks were closed factories missing createStaticStyles /
keyframes / createGlobalStyle that real base-ui style modules now need;
compose them over importOriginal. PluginTag and GroupItem retarget their
UI stubs to the base-ui import path the components migrated to.

Claude-Session: https://claude.ai/code/session_01UTDivfaszDuBjpPn7PV7gQ

* ✨ feat: support workspace document comments (#18750)

* ✨ feat: support workspace document comments

* ✨ feat: enhance document comments with mentions and attachments

* 🐛 fix: synchronize document comment activity

* 🐛 fix: guard document comment attachment uploads

* 🐛 fix: preserve comment synchronization metadata

* 🐛 fix: scope document comment API routes

* ✅ test: align base-ui component mocks

* ✅ test: complete base-ui mock migration

* ✅ test: clean up rebased component mock

* ♻️ refactor: align comment imports with base-ui

* ✅ test: align mocks with latest canary

* 🐛 fix(connect-agent): prevent device loading state flash (#18768)

* 🐛 fix(connector): canonicalize connector ownership (#18763)

* 🐛 fix(eval): rm eval hints in run topic titles (#18771)

* 🐛 fix(eval): isolate run topic titles

* 🐛 fix(eval): keep ordinal topic titles

* 🐛 fix(eval): retain run topic input

* 🐛 fix(eval): remove fallback case label

* 🐛 fix(agent): scope heterogeneous default names to shared workspaces (#18770)

* 👷 ci: upgrade pnpm setup action to v6 (#18777)

* 🐛 fix(queue): encode QStash deduplication IDs (#18778)

* 🐛 fix(agent): recover sub-agent bridge answer from isolation thread for hetero children (#18781)

* 🐛 fix(agent): recover the sub-agent bridge's answer from its isolation thread for hetero children

callAgent-invoked heterogeneous (CLI-driven) sub-agents backfill their
parent's placeholder tool message with "Sub-agent completed without a
textual answer." even when the CLI produced a real reply — always, in
production's queue mode (AGENT_RUNTIME_MODE=queue), not intermittently.

completeSubAgentBridge/completeGroupActionMember resolve content from
params.finalState, falling back to coordinator.loadAgentState(operationId)
(the standard runtime's Redis-backed step state) when finalState isn't
passed in-process. Both createSubAgentBridgeHook and
createGroupActionMemberBridgeHook's webhook config deliberately strip
finalState/lastAssistantContent from the QStash payload via `eventFields:
['operationId', 'reason', 'status']` (to keep the payload lean), so the
queue-mode callback always arrives with finalState undefined — and hetero
children never write into the coordinator's runtime state at all (confirmed
zero `saveAgentState` calls under services/heterogeneousAgent/), so the
fallback is structurally dead for them. heteroFinish already resolves the
real answer server-side (via topics.metadata.heteroCurrentMsgId ->
messageModel.findById) before dispatching, but that resolution never
reaches the callback.

Add resolveLastAssistantContentFromThread(threadId): queries the child's own
isolation thread directly (thread ids are globally unique, no agentId/topicId
needed to disambiguate) — the same source heteroFinish itself reads. Used as
a fallback in both completeSubAgentBridge and completeGroupActionMember
(isolated mode) when the existing finalState/coordinator resolution comes up
empty, before falling through to the "no textual answer" stub.

Two regression tests added (one per bridge method), reproducing the actual
hetero shape (loadAgentState resolves null, not a message-stripped state) —
verified to fail against the pre-fix code and pass with it. Full
AgentRuntimeService.test.ts suite (114 tests) still passes.

Fixes LOBE-13586

* 🐛 fix(agent): gate the thread content fallback on missing finalState

Address a P2 flagged by Codex review on 15a401edd1: the thread-fallback
guard checked only `!lastAssistantContent`, which also fires when a REAL,
authoritative finalState is present but its last turn is legitimately
textless (image-only, or the "preserve an empty leaf" case in
normalizeCompletionMessages). In that case the fallback would still query
the child's isolation thread — and a lagging read that surfaces an EARLIER
real reply from the same thread would silently show stale text instead of
the correct "no textual answer" stub.

Narrow the guard to `!finalState` in both completeSubAgentBridge and
completeGroupActionMember: this is exactly the heterogeneous-child case the
fallback exists for (finalState is never populated for them at all), and
`!finalState` already implies an empty lastAssistantContent, so nothing is
lost for the case the fallback is meant to cover.

Two regression tests added (one per bridge method) proving the fallback is
never invoked when a real finalState says the answer is textless — verified
to fail against the pre-fix (`!lastAssistantContent`) guard and pass with
the narrowed one. Full AgentRuntimeService.test.ts suite (116 tests) passes.

---------

Co-authored-by: AmAzing- <115673583+AmAzing129@users.noreply.github.com>
Co-authored-by: Rdmclin2 <rdmclin2@gmail.com>
Co-authored-by: YuTengjing <ytj2713151713@gmail.com>
Co-authored-by: Innei <i@innei.in>
Co-authored-by: Rylan Cai <67412196+cy948@users.noreply.github.com>
Co-authored-by: Tsuki <76603360+sudongyuer@users.noreply.github.com>
Co-authored-by: LiJian <onlyyoulove3@gmail.com>
2026-08-28 17:40:47 +08:00
..