mirror of
https://github.com/lobehub/lobehub.git
synced 2026-09-20 04:56:13 +08:00
fix/topic-reference-personal-fallback
106 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6313b37662 |
📝 docs: improve Feishu/Lark setup and refresh translations (#19349)
* 📝 docs: clarify Feishu and Lark event subscription setup * 📝 docs: add Feishu and Lark quick-create guides * 📝 docs: version Feishu and Lark setup screenshots * 📝 docs: use durable versioned setup screenshot URLs * 🌐 chore: refresh translations and screenshot references after rebase * 🌐 chore: sync translations and assets with latest canary * 🌐 fix: correct Dutch and Portuguese agent labels * 📝 docs: host channel screenshots through persistent file links |
||
|
|
4bf05e2499 |
🐛 fix(bot): surface budget scope and headroom in bot failure replies (#19336)
* 🐛 fix(bot): surface budget scope and headroom in bot failure replies Carry the budget context of an InsufficientBudgetForModel error from the runtime lifecycle event through the hook payload into the bot reply, and render a scope-aware message (member allowance vs. workspace pool) with the remaining and required credits instead of the generic "Agent Execution Failed". LOBE-13726 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RKPxmeT4DrAdKP3RUCYzgp * 🌐 style: update i18n Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RKPxmeT4DrAdKP3RUCYzgp * 🔒 fix(bot): stop quoting the billed allowance in budget replies Runs mentioned from a shared channel are billed to the bot owner, so a reply that quoted availableCredits / requiredCredits published the owner's balance to every channel member. Keep the scope-aware copy and drop the amounts line; a regression test asserts no figure is rendered. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RKPxmeT4DrAdKP3RUCYzgp * 💬 fix(bot): address the bot owner and split plan-limit copy in budget replies Runs are billed to the bot owner, not to whoever mentioned the bot, so the budget copy no longer calls the reader the payer ("your budget") and points at the bot owner / workspace admin instead. FreePlanLimit and SubscriptionPlanLimit get their own copy (the allowance itself is exhausted, so the fix is the plan, not a cheaper model), and the budgetTypeAtError scope refinement now applies to all three admission codes since the workspace gate throws SubscriptionPlanLimit when a run can't be priced upfront. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RKPxmeT4DrAdKP3RUCYzgp * 💬 fix(bot): cover both meanings of SubscriptionPlanLimit in the reply Per the error taxonomy the code fires when the paid-plan allowance is reached OR when the plan tier does not cover the requested model, so the copy no longer claims the credits are spent and offers upgrade / top-up / custom API as the remedies. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RKPxmeT4DrAdKP3RUCYzgp * 👷 build: serialize build scripts so editor postinstalls stop racing on lexical Three peer-variant copies of @lobehub/editor patch the same hoisted lexical files in postinstall; run concurrently they read each other's half-written output and fail with "Patch context mismatch". Only the allowBuilds packages run scripts, so childConcurrency: 1 costs seconds. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RKPxmeT4DrAdKP3RUCYzgp --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
3412626de9 |
🐛 fix: keep the resource tree and connector list in sync with their scope (#19156)
* 🐛 fix: keep the resource tree and connector list in sync with their scope Three scope/staleness fixes that share the same shape — a client store holding on to rows the current context no longer owns. - LOBE-13804: `useFileItemDropdown` refreshed the tree with the explorer's current folder, but the sidebar navigates into a folder on click, so "open it, then delete it" refreshed the deleted folder while the parent list kept the row until a reload. Tree store gains `dropNodes`, which drops the rows where they actually live, purges the removed subtree's caches, and revalidates only the parents that were hit. Explorer bulk delete now syncs the tree too, and deleting the folder the explorer sits in steps out to the parent instead of stranding a dead route. - T-392: connector fetches wrote their result without checking the scope they were issued in, so a personal `list` still in flight could land after the workspace switch and pin the wrong list for the session. Capture `getActiveWorkspaceId()` before the request and discard a stale response, mirroring the builtin slice. - LOBE-13805: drop the permanently disabled workspace settings reset entry and its locale keys. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHwD8Ev5t7y3xDiBTc9m8K * 🌐 chore(i18n): run the translation workflow Regenerated after the rebase. Backfills keys other iterations left untranslated and drops entries whose source keys are gone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHwD8Ev5t7y3xDiBTc9m8K * 🐛 fix: step out of a deleted folder's whole subtree, not just the folder Review follow-up on the sidebar delete fix. `handleDeleted` compared the deleted row against the explorer's selection directly, so it only fired when the explorer was parked in the folder being deleted. Deleting an *ancestor* — the sidebar renders the whole path, so that is one click away — left the explorer exactly where the guard exists to prevent: an empty list under a breadcrumb naming a folder that no longer exists. Opening a document inside the deleted folder had the same shape. Adds `hierarchySubtreeHoldsSelection`, which walks the loaded subtree and answers whether the selection sits anywhere inside it. A selection under a folder the sidebar never expanded is invisible to the walk and the explorer stays put, matching how the rest of the tree treats folders it has not fetched. `onDeleted` now fires before `dropNodes` rather than after: the purge forgets the subtree synchronously, so a caller that has to inspect what is about to disappear could not see it. The fallback parent key is captured before the callback runs, so the ordering carries no other meaning. Also covers the two behaviours that shipped untested — the explorer's bulk delete syncing the tree, and the folder-refresh path when the deleted set is only known to the server — and documents why a discarded connector response deliberately leaves the init flag alone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHwD8Ev5t7y3xDiBTc9m8K * 🐛 fix: don't yank the user back when a slow delete finally lands Codex review follow-up (P2). `handleDeleted` read the selection and library from the closure the context menu captured when it was rendered. The delete is async, so a user who opens another folder — or another library — while the request is still in flight was navigated back to the deleted folder's old parent once it resolved, after they had already moved on. The decision now moves into `resolveDeletedFolderRedirect`, a pure function over a snapshot the caller reads at call time: the component keeps the live library and selection in a ref updated each commit, and skips entirely when the row has unmounted, which is itself proof the user navigated away. Making it pure also lets the delayed-delete case be tested directly, which the component-level logic could not be. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHwD8Ev5t7y3xDiBTc9m8K --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
35471de251 |
🐛 fix(task): load the full task list and virtualize the Tasks page (#19108)
* 🐛 fix(task): load the full task list and virtualize the Tasks page The Tasks page only ever received the first server page (50 newest by creation) and had no pagination, so a workspace past 50 tasks silently dropped its older rows — e.g. a private task assigned to the viewer showed under "Private" but not under "All" (LOBE-13779). - `useFetchTaskList` gains `complete`: fetch every page (100/page, merged and de-duplicated by id) up to a 1000-row ceiling; the Tasks page opts in, embedded overviews keep the single page. - `TaskList` renders through `react-virtuoso` on the page's own scroller: group headers and rows are flattened into one virtual list, collapse state lives in the list, and a truncation notice covers the ceiling. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJXLhkz7QpDyRVFTjLt4JJ * 🌐 style: update i18n Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJXLhkz7QpDyRVFTjLt4JJ * 🐛 fix(task): stable page order, gate the full fetch to the ordinary tab Codex review round 1: - `seq` breaks `createdAt` / `updatedAt` ties in every task list ordering (list, group prefetch, ranked group windows) so consecutive offset pages never repeat or skip a row; regression test pages through five rows that share a timestamp. - The Tasks page only runs the full `complete` fetch on the ordinary tab; the scheduled and "My tasks" tabs render their own paginated collections. - Restore the hand-authored zh-CN goal-acceptance copy the i18n sweep rewrote. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJXLhkz7QpDyRVFTjLt4JJ * ♻️ refactor(task): walk the full task list with a keyset cursor Codex review round 2: fixed-offset pages can repeat or skip a row when a task is deleted (or created) between two page reads. `task.list` now takes an `after: { at, seq }` cursor — rows strictly after that position in the list's `(orderBy, seq)` order — and the Tasks page walks pages sequentially from the last row it holds, so concurrent changes shift nothing. Regression tests cover a delete between pages (model + store) and a cursor on the `updatedAt` ordering. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJXLhkz7QpDyRVFTjLt4JJ * ♻️ refactor(task): walk the full list only in the list view Codex review round 3: the kanban view fetches its own server groups, so the ordinary tab now walks every page only in list mode and keeps the single page the empty-hero decision needs otherwise. `complete` joins the SWR key and the store's query-scope guard, so the walked list and the single page never serve each other from a shared entry or the shared store field. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJXLhkz7QpDyRVFTjLt4JJ --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
a4caede6f5 |
✨ feat(task): member assign notifications, mentions & tool assignee (#19035)
* ✨ feat: workspace task assignment & comment notifications with member mentions - notify the assignee when a workspace task is assigned to them - notify participants on task comment activity and workspace member @mentions - task builtin tool: assigneeUserId support with dual (agent + member) assignee model - workspace member directory exposes email for assignee resolution * 🌐 style: update i18n * 🐛 fix(task): retain notifications after the response and gate them by task access Codex review round 1 on #19035: - deliver assignment / comment pings through after() with try/catch instead of bare void calls (serverless keeps the work alive, rejections are logged); same lifecycle in the tool server runtime - re-authorize comment-ping recipients against the task before delivery: private tasks never leak to members who cannot open them, and creator / assignee rows are re-checked for active membership (shared helper filterActiveWorkspaceMemberIds) - listWorkspaceMembers: optional query + limit (default 50, max 100) on both the server runtime and the client executor, header announces the cap; the tool description only promises IM identities where available - My tasks: hideCompleted is sent as a server status filter and ordering is pinned to the updatedAt-desc page order, so cuts happen before pagination * 🐛 fix(task): unwrap native Slack/Discord mentions in the member directory query Codex review round 2 on #19035: `<@U123>`, `<@U123|name>`, `<@4521>` and `<@!4521>` are folded to the bare platform id (and a leading @ stripped) in normalizeMemberQuery before matching, so the deterministic resolution the tool description promises works when the model passes a mention through verbatim. * 🐛 fix(task): scope member directory lookups to the workspace and push search into SQL Codex review round 3 on #19035: - MessengerAccountLinkModel.findByUserIds takes a scope: only identities active under the current workspace (or personal scope) are exposed, so a member's IM handles linked elsewhere never reach coworkers' tool output - WorkspaceMemberModel.searchAssignableMembers applies the role gate, the query (id / name / handle / email / workspace-scoped IM identity) and the limit in SQL with a separate count; the runtime decorates only the page - My tasks / scheduled: use the comparator token that renders a page newest-first (compareTaskItems inverts orderDirection for date columns) * ✅ test(task): fix test-file type errors flagged by the OSS type-check - integration test: otherUserId is string | undefined at the insert sites - member directory test: seed the owner row directly (addMember is typed to non-owner roles) * 🐛 fix(task): render every fetched row in the paginated task collections Codex review round 4 on #19035 (LOBE-13749): with showSubTasks off, TaskList folded a sub-task away whenever its parent shared the page, so a server page came back sparse while total still counted the hidden rows. My tasks and the scheduled tab now pin showSubTasks alongside the server page order; nesting still tucks a child under a parent on the same page. |
||
|
|
4471c7aafe |
✨ feat: KB sidebar search/add button and comment image thumbnails (#19010)
* ✨ feat: KB sidebar search/add button and comment image thumbnails * 🌐 style: update i18n * 🐛 fix: gate the KB parent bypass on folder type and reveal after deferred upload * ✨ feat: load sidebar search results incrementally and revalidate them with the tree * 🐛 fix: hide stale sidebar search rows, reveal folder action on focus, localize Untitled |
||
|
|
14b711e783 |
🐛 fix(page-editor): publish lock ownerId reliably and self-heal CONFLICT saves (#18848)
* 🐛 fix(page-editor): publish lock ownerId reliably and self-heal CONFLICT saves The lockOwnerId dispatch in useDocumentLock lands before the document row exists in the store, so the reducer drops it and every save goes out with an undefined ownerId — the server then rejects the write as a CONFLICT against the user's own lease. Republish the ownerId once the document is loaded, retry a CONFLICT save once after reclaiming the same-user lease, and stop surfacing save failures with the file-library network error copy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE * 🌐 chore(i18n): translate pending locale keys Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE * 🐛 fix(page-editor): guard the CONFLICT retry against a collaborator's newer version A conflicting lease can belong to another member who saved and released it before the recovery ran; reclaiming the now-free lease and resending the stale payload would overwrite their save. Compare the server copy with the session's last-known content and retry only on an exact match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE * 🐛 fix(page-editor): make the CONFLICT retry an atomic server-side version check The client-side content comparison left a TOCTOU window between the fetch and the reclaim, and ignored editorData-only collaborator changes. The recovery now compares content AND editorData against the session's last-known version and pins the retried save to that verified version via a new optional expectedUpdatedAt predicate, which updateDocument re-checks under FOR UPDATE inside the write transaction — an interleaved collaborator save now fails the retry with CONFLICT instead of being overwritten. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE * 🐛 fix(page-editor): hand back the reclaimed lease when the CONFLICT retry fails A failed CAS retry left this session holding the lease it had just reclaimed, so the lock recovery read the tab as the legitimate holder, cleared the save block, and reopened a stale editor. Release the lease before rethrowing so the lock state reflects reality. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE * 🐛 fix(page-editor): add expectedUpdatedAt to the manual UpdateDocumentInput type The tsgo lint step failed: the manually-maintained UpdateDocumentInput interface lagged the zod schema, and the retry helper's version check did not narrow `latest` for TypeScript. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE * 🐛 fix(page-editor): bind conflict recovery to the failed save's base version The recovery compared the fetched server copy against the LIVE store snapshot, so when an overlapping newer save from the same tab completed while the older request was in flight, the check matched the newer version and the retry replayed the older payload over it. Compare against the immutable store snapshot captured when the failed save started instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE * 🐛 fix(page-editor): self-heal only plain content saves A save carrying title/emoji or a history restore replays fields the recovery's content+editorData comparison cannot vouch for — a collaborator's metadata-only change would be silently overwritten by the retry. Those saves keep the plain CONFLICT flow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE * 🔧 chore(test): pin happy-dom below 20.12 to unblock CI happy-dom 20.12.0 (released 2026-08-29T16:12Z) changed Web Animations behavior in a way that makes motion-dom animation teardown reject with unhandled 'AbortError: The animation was canceled' — every Test App shard run after the release fails at exit despite all tests passing (canary flaps identically). Pin to ~20.11.15 until happy-dom/motion settle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011X64zT9QD5FHwJkekYAQgE --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3c551a9dfc |
♻️ refactor(verify): unify acceptance criterion UI and remove lobe-delivery-checker (#18376)
* ♻️ refactor(verify): unify acceptance criterion UI and remove lobe-delivery-checker - Add shared CriterionList / CriterionRow / CriterionRequiredChip and a single CriterionEditor + openCriterionEditModal under src/features/Verify/CriterionList - Migrate the /goal intervention card, CreateGoalModal, TaskVerifyConfig, PendingAcceptanceCheckList, TaskAcceptance and GoalDetailPage to the shared row/editor, deleting the two duplicated criterion edit modals - Unify the required chip to a blue info tag labelled 必选 (verify:criterion.*) and drop the divergent 必要/必需/必选 key trio across chat/plugin namespaces - Delete the unused builtin-tool-lobe-delivery-checker package with its server runtime, registry entries, i18n keys and the orphaned createPlanFromCriteria Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * 📝 docs(acceptance): note stale-cache fingerprint of a cross-wired browser session Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ♻️ refactor(verify): apply acceptance review feedback on criterion editing - Drop the pending-status icon and C{seq} anchor from goal-creation draft rows — those belong to the post-creation check list, not authoring - Remove TaskVerifyConfig's edit mode (SortableList reorder, side drawer, Done button): every row now edits itself through the shared criterion modal, matching the goal-creation interaction; regenerate moves into the header overflow and add/save-as-template become always-visible footer actions - Simplify the criterion edit modal title — no C{seq} interpolation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * 📝 docs(acceptance): record ingest-side identifier/internal-id gap in probe patterns Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ♻️ refactor(verify): apply round-2 acceptance review feedback - Keep the C{seq} anchor on goal-creation draft rows; only the pending status circle stays out of authoring - Drop the at-rest delete button from task criterion rows — removal lives inside the editor modal - Move save-as-template from the footer into the header overflow menu - Show the verifier tag and required chip on goal-detail check rows Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ♻️ refactor(verify): fold task criterion row edit and delete into a per-row overflow Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
26dc379af9 |
🐛 fix(agent-group): keep group membership lifecycle intact on transfer & delete (#18126)
* 🐛 fix(agent-group): keep group membership lifecycle intact on transfer & delete A chat group's roster mixes two kinds of member: agents the group itself built (its synthetic supervisor, plus members made in the group builder) and standalone agents merely linked in. Only `duplicateGroup` knew the difference; delete, roster removal, group transfer and agent transfer each acted on every member alike, which cost: - deleting a group stranded its own supervisor/members forever (`agents` has no FK to `chat_groups`, and `virtual: true` hides them from every list), and the cleanup ran outside the delete's transaction - transferring an agent silently tore it out of every group, and for a supervisor left the group headless — the next read minted a blank replacement and the configured systemRole/model were gone - transferring a group dragged referenced members into another scope, and evicted them from every OTHER group they belonged to Put the judgement in one place (`resolveGroupMembershipType`) and have all four paths read it. A group transfer now leaves referenced members where they are and takes a clone instead, remapping the group's own topics/threads/messages onto it — `agent_id` is ON DELETE CASCADE, so a stale pointer would have taken the moved history with it. The async backfill applies the same remap on the same rows it rewrites. Also surfaced up front rather than after the fact: two read endpoints (`agent.getGroupMembershipImpact`, `group.listReferencedMembers`) so the UI can say what a move will do, and `role` is now a closed enum instead of free text. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🐛 fix(test): use a role the closed set actually contains `moderator` predates `GROUP_MEMBER_ROLES` and is not a member of it, so these two cases stopped type-checking once `role` became an enum. `assistant` is the valid non-default role, so they still prove a non-default role round-trips rather than just re-asserting the default. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🐛 fix(agent-group): gate referenced-member details on member visibility `listReferencedMembers` scoped only on the GROUP, so a caller who could see the group could read the title and avatar of a member whose owner had since flipped it back to `private` — a member the roster itself hides from them (`memberAgentVisibility`). The pre-transfer warning would have been the one surface that handed it out. Apply `agentOwnership()` as well, the same predicate `checkAgentsBeforeRemoval` and the roster reads use. A hidden member is now under-reported rather than exposed, which is the right direction: it is invisible to this caller everywhere else too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🐛 fix(agent-group): guard left-behind members for the drain's duration A slow-path group transfer registers the target-scope roster — members that travelled plus the clones — as the job's covered agents. The referenced members it left behind are not covered, and deliberately so: that junction is what the migration badge reads, and an agent that never moved should not advertise a migration. But being uncovered also left them unguarded. Until the drain reaches a topic, that topic's rows still carry `messages.agent_id = sourceAgentId`, and the column is ON DELETE CASCADE — so the owner deleting their own agent mid-drain silently took the moved group history with it, the very rows the remap was about to rescue. Guard the delete without touching the badge: `hasPendingRemapForSourceAgents` reads `payload.agentIdRemap` of pending transfer jobs, and `AgentModel.delete` now refuses on it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🐛 fix(agent-group): refuse to clone a member the caller cannot see A group transfer leaves referenced members behind and clones them into the target scope — title, systemRole, model, params and plugins — via `buildCopiedAgent`. When a member's owner had since flipped it back to `private`, that clone handed the caller a full copy of an agent the roster hides from them (`memberAgentVisibility`), and which `listReferencedMembers` had just been fixed to withhold. Moving the group was the way around both. Pre-existing rather than new — the old path MOVED that agent into the target scope outright, which is strictly worse — and only narrowed, not closed, by the owner-only guard: `buildWorkspaceWhere` constrains private rows to their author, so a workspace owner cannot see such a member either. Refuse, rather than clone a redacted shell (a member answering with a blank systemRole is a silent behavior change) or drop the member (leaving moved history pointed at an agent in the source scope, which `messages.agent_id`'s cascade turns back into data loss). The error names nobody: which member is hidden is the part being withheld. `copyToWorkspace` duplicates members the same way and gets the same guard. `duplicate` needs none — it re-links referenced members instead of copying them, so no config crosses a scope. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🔒 fix(agent-group): check member visibility on locked rows, not a snapshot Both guards ran against a read taken before the row lock, so an owner committing `visibility = 'private'` in between was checked as public and then cloned anyway — from that same stale snapshot. A narrow window, but it defeated the guard entirely when it hit. - transfer: the check moves BELOW the existing `FOR UPDATE` on the member agents, and the clone now reads the locked row rather than `memberRows` - copy: the check moves INSIDE the transaction and takes its own `FOR UPDATE` on the referenced members first, since it had no lock at all on them Once those rows are locked, a concurrent visibility update blocks until this transaction ends, so what is checked is what gets cloned. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🔒 fix(agent-group): enforce single-group ownership, withhold hidden group ids Two guards that were resting on something weaker than they looked. `addAgentsToGroup` validated visibility but never rejected a `virtual` agent, so the "an owned member belongs to exactly one group" invariant that `resolveGroupMembershipType` leans on was enforced by the member picker's query rather than by the write. Sending a known group-built member or supervisor id would link it to a second group — and then deleting either group deletes an agent the other still uses. Reject it at the write. `getGroupMembershipImpact` set `groupVisible: false` for a group the caller cannot see, and withheld its title and avatar, but still returned its id — so the preflight disclosed the existence and identifier of another member's private group. Withhold the id with the rest. Done where the refs are built, so the transfer error's `groups` payload stops carrying them too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🐛 fix(agent-group): the invariant is one group, not zero The previous commit rejected every `virtual` agent at `addAgentsToGroup`, which breaks the group agent builder: it creates `virtual: true` and adds it through exactly this path, as that agent's first and only membership. Reject only a virtual agent already on ANOTHER group's roster — which is the actual invariant `resolveGroupMembershipType` needs, and the only case where deleting one group would destroy an agent another still lists. Adds the test that should have caught it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🔒 fix(agent-group): keep copy and transfer taking locks in the same order My own TOCTOU fix put the referenced-member `FOR UPDATE` at the top of `copyToWorkspace`'s transaction — ahead of the source-group lock. That inverted the order `transferToWorkspace` uses (group, then member agents), so a concurrent copy and transfer of the same group could each hold what the other wanted and deadlock, instead of meeting the pending-job guards that exist to serialize them. Move the agent lock below the group lock. Same protection, one order. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🔒 fix(agent-group): keep builtin agents off group rosters Builtins (Inbox, the agent builders) are provisioned per user and carry `virtual: true`, exactly like a group's own members — so the membership rules classify one as group-OWNED the moment it lands on a roster. And `removeAgentsFromGroup` deletes owned members with no reserved-slug protection, unlike the group-delete path. Adding your Inbox to a group and then leaving the group deleted the Inbox. Narrowing the previous virtual-agent rejection to "already in another group" is what let a builtin through the door, since a builtin normally sits on no roster at all. Two layers, matching how `ChatGroupModel.delete` already handles this: - `addAgentsToGroup` refuses a reserved builtin slug outright - the removal delete gains the same reserved-slug backstop, for a row that reached the roster some other way Both regression tests verified failing first: without the backstop the Inbox row is gone; without the door check the add resolves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🔒 fix(agent-group): a builtin is never a group-owned member The previous commit closed the two paths that DELETE an owned member. It left the one that rehomes them: `transferToWorkspace` rewrites `userId`/`workspaceId` for every owned member, so a builtin on a roster would have someone's Inbox moved into another scope. Rather than a third call-site backstop, put the carve-out in the shared judgement — which is what this whole change is about. A reserved builtin slug now resolves to `referenced` ahead of every other rule, including `supervisor`, in both the TS resolver and its SQL twin. Every owned path inherits it: delete, roster removal, group transfer, agent transfer. Call sites that partition a roster now pass `slug`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🔨 chore(agent-group): drop the now-unused `not` import Left over from the roster-eviction delete this branch removed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 🐛 fix(agent-group): classify referenced members with the same inputs everywhere `listReferencedMembers` fed `resolveGroupMembershipType` a row without `slug`, so a builtin on a roster read as merely `virtual` — owned — and dropped out of the warning. The transfer path does pass `slug`, treats the same row as referenced, and clones it. The warning therefore omitted the one row the move was about to act on. Carry `slug` here too. The shared judgement only helps if every caller hands it the same facts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e08bf97fbb |
✨ feat: support agent copy (#18030)
Extends the async agent-history-job pipeline to duplicate an agent's chat history: per-topic backfill, the same progressive gray-out UX as transfer, and guards so a source agent cannot be transferred or deleted out from under a pending copy. Copies carry `metadata.copied` and keep their own token/cost figures — consumption reports filter on the marker, while display and context-window math keep reading the numbers. The `payload` column this builds on ships separately in #18043. |
||
|
|
af2e77b551 |
🐛 fix: workspace common issues & account deletion blocker locales (#17992)
* 🐛 fix: workspace common issues & account deletion workspace blocker locales * 🐛 fix: resolve API docs link against active server origin on desktop * ✅ test: raise copy regression above the 65,535 bind-parameter cap * 🐛 fix: preserve copied updatedAt in cross-batch FK fixup updates * 🐛 fix: narrow workspace id type in workspaceUserSettings procedure ctx * 🐛 fix: route legacy chat-group sidebar assignments through ChatGroupModel * 🐛 fix: gate legacy chat-group sidebar moves behind resource edit access * 🐛 fix: honor chat-group edit locks in legacy sidebar move compat * ✅ test: cover legacy chat-group sidebar moves (routing, edit gate, lock) |
||
|
|
84335703c3 | 🌐 style: i18n LobeHub scoped model descriptions (#17900) | ||
|
|
c19240488a |
✨ feat: support proactive messenger push and notification channel settings (#17791)
✨ feat: support proactive IM notifications
|
||
|
|
6dfe6e485f |
✨ feat: support Claude Opus 5 (#17582)
* ✨ feat: support Claude Opus 5 * 🔨 chore: sync online model locales * 🐛 fix: respect disabled Bedrock thinking * 🐛 fix: preserve disabled Bedrock thinking * 🐛 fix: hide internal server error details |
||
|
|
925ef8365c |
🐛 fix: resource permission controls, chat-input hints & wechat push (#17468)
* 🐛 fix: resource/agent permission controls, use-only hints and wechat push improvements
* 🐛 fix: gate use-only notice on resolved access, not just !isAccessLoading
* ✅ test: align tests with model-profile exposure and post-rebase types
- update redaction tests: model identity is now part of the safe profile
surface (use-only members see/switch the model in chat)
- complete upstream partial mocks broken by new hook/selector usages
- add missing acceptance.workspace.filters.empty.all locale key (type break
from
|
||
|
|
1afa265b3e |
💄 style: update i18n (#17277)
* 💄 style: update i18n * ✅ test: drop stale provider footer assertions left by footer removal |
||
|
|
3d72010018 |
✨ feat(home): replace the daily brief with a triaged home inbox (#17194)
* ✨ feat(home): replace the daily brief with a triaged home inbox The home brief rendered every unresolved brief as one flat list of tall cards, so a stuck decision and a week-old insight competed for the same space. Split the feed by whether the user has to *do* something: - Needs you — briefs blocking an agent (decide / review / fix), plus topics that finished while the user was away. Errors sink to the bottom: a stuck decision blocks work right now, a failed run has already stopped. - Running — collapsed to one line; a healthy run needs nothing from you. - Worth knowing — insight briefs, one line each. Rows now carry the real task/topic status glyph from ExecutionStatus.ts (task `paused` reads as "pending review", not "suspended") instead of the brief-type icon, and the meta line names the task it belongs to. That needed the parent task's identifier + name, so listUnresolvedEnriched selects them from the join it already had. Running / unread topics come from one topicService.queryTopics call. Deliberately not HomeRepository.getUnreadCounts() — that one excludes cron/task-triggered topics because it powers a sidebar badge, and those are exactly the ones an agent inbox must surface. Recommendations, DocumentPreviewModal and TopicChatDrawer used to render inside DailyBrief; they are re-mounted in HomeInbox so artifact preview and "view run" keep working. * ✨ feat(home): make the inbox unread runs readable and actionable Rework the home inbox unread section so a finished run is legible and replyable without leaving the page, plus supporting cleanups. - Surface each topic's last assistant reply: `queryTopics` gains an opt-in `withLastMessage` correlated subquery (last non-empty assistant message, truncated to 2000 chars with a trailing ellipsis). - Unread section is now an expandable list in the news-list idiom: one row per run (ripple unread dot, agent avatar, title, time, chevron); opening a row reads it and drops the full reply inline. The expanded footer offers "view chat" (left, opens the topic drawer) and a filled "follow up" (right) that swaps in an inline reply editor and sends straight to the topic over the gateway — no drawer, no navigation. - Client agent runs now persist `topics.status = 'running'` at run start, like the gateway/hetero transports already did, so a client-driven run shows up in the home inbox running card and the Fleet board instead of being invisible off the active conversation. - Extract shared `UnreadDot` (ripple) and `CollapsibleContent` components, replacing the copy-pasted sidebar ripple dots and the bespoke task-run collapse; the collapse fade now scales with the clamp height. - Running card shows a deduped stack of the busy agents' avatars. - Section headings carry a count and each names itself (no nested headings, no single-section title suppression, no leading icon). - InboxBriefCard: drop the empty meta row for a brief with no parent task and move its timestamp onto the title line. - Loading state drops the fabricated "Needs you" group heading (bare skeletons + recommendations), and a topic-feed fetch failure now surfaces an inline error with retry instead of silently dropping the unread / running sections. - Rename the insight section to "Daily brief" with a count and subtitle, and make it an expandable list: agent avatar leads each row, clicking reads it in place (title + avatar dim) and expands the finding's detail inline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6add26c6bc |
✨ feat: add workspace RBAC control and resources management (#17172)
* ✨ feat: add workspace RBAC control and resources management * 🐛 fix: gate connector syncTools and recursive document deletes; type-safe workspaceRole access * 🐛 fix: preserve teammate files in narrowed KB clear-all; keep shared-agent rename collaborative * 🐛 fix: read-only connector bootstrap for non-creators, KB delete file scoping, api_key:read gate * 🐛 fix: gate connector getForEdit credential read behind creator/owner check * 🐛 fix: caller-scoped workspace clear-all for all roles; surface API key tab to members * 🐛 fix: creator-only verify run lazy creation; adapt tests to RBAC error semantics * 🐛 fix: viewer read-only connector bootstrap; keep shared topic co-edit ungated * 🐛 fix: hide workspace API key tab from viewers via useIsWorkspaceViewer slot * 🐛 fix: keep shared-topic metadata co-editable * 🐛 fix: workspace-scoped provider vault merge for co-owners; gate custom connector sync in UI * 🐛 fix: gate skill re-import overwrites and KB file membership behind creator/owner * 🐛 fix: block non-owner transfers that rehome teammates' rows across all cascade paths * 🐛 fix: include linked sessions in agent transfer foreign-row guard * 🐛 fix: gate agent connector bind/copy/mount/unbind/unmount behind creator-owner check * 🐛 fix: gate generateDraftPlan behind verify-run owner check * 🐛 fix: role-aware skill importer for write chain; revalidate resources after select-all delete * 🐛 fix: resolve viewer writability without injected role; creator-scoped notebook folder deletes * 🐛 fix: member-gate connector getForEdit credential read * 🐛 fix: block non-owner agent/group deletes that cascade teammates' conversations |
||
|
|
f7a0ecfbd3 | 🌐 chore(i18n): fill missing locale translations (#17041) | ||
|
|
3395fb713f |
✨ feat: support device share and optimize workspace (#16901)
Squash of: - feat: support device share and optimize workspace - 🐛 fix: grandfather legacy device ids in workspace device binding guard - 🐛 fix: coerce workspace agents away from member-local execution Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
0e6d1a759d |
✨ feat: support workspace private resources with transfer and copyTo (#16729)
* feat: support workspace private resources with transfer and copyTo Squashed 3 commits: - feat: support workspace private resources with transfer and copyTo - fix: test case and lint error - fix: file download * chore: update i18n files * fix: test case |
||
|
|
261c7652e5 |
🐛 fix: workspace problems (#16683)
* fix: workspace optimize * feat: init market org profile on community * chore: remove workspace profile * chore: update community 成员页 * fix: commnity memeber table * feat: support reserve onboarding * chore: update i18n files * feat: workspace ai model and divider scope * chore: replace workspace_memeber.role with rbac_user_roles * fix: workspace ai provider lost * chore: update i18n files * fix: codex preview |
||
|
|
335e4f5fbd |
feat: workspace private agents, viewer limit, onboarding (#16604)
* feat: workspace private agents, viewer limit, onboarding (squashed) * fix: test case and private document * fix: workspace private resource test case * fix: test case * chore: complement test case |
||
|
|
ed10e2a8a5 |
✨ feat: workspace member budget and audit log (#16530)
* feat: support workspace audit log and member budget control (squashed) * 🐛 fix(business): add WorkspaceAuditLog open-source stub The audit-log settings route imports `@/business/client/BusinessSettingPages/WorkspaceAuditLog` but the open-source slot was missing, breaking the standalone build. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: i18n keys --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
3b9f67f384 |
✨ feat(chat): show model display name in message footer (#16421)
- Render `displayName` (fallback to `id`) for the model label below assistant messages - Update GLM-5.2 Fast description copy |
||
|
|
3498537aae |
feat: workspace device member access (#16333)
* chore: adjust workspace limit copy * fix: device enroll memebership * feat: support device manage * fix: navigation route * chore: optimize device list * feat: add workspace auth * fix: workspace device role auth * feat: support inactive workspace lock * feat: support workspace unsubscription cancelled * chore: solo to free plan * chore: update downgrade i18n files * fix: billing issue * chore: update i18n files |
||
|
|
a50b6a83e7 |
✨ feat: workspace billing system (squashed) (#16308)
* feat: workspace billing system (squashed) * fix: lint error |
||
|
|
60bed5782f |
chore: update i18n (#15712)
chore: update i18n files |
||
|
|
35b6bc55b8 |
🐛 fix: workspace error (#15701)
feat: support workspace (page author, copyTo/transferTo, notifications, i18n & fixes) Squashed 13 commits from fix/workspace-error for clean rebase onto main's submodule base. |
||
|
|
7641cda958 | 💄 style: update i18n locales (#15630) | ||
|
|
f042dd352e | ✨ feat: support Claude Opus 4.8 (#15314) | ||
|
|
0195f42daa |
🐛 fix: onboarding im integration (#14988)
* feat: support onboarding messager * chore: remove telegram CN screenshots * feat: add feedback commands * fix: bot feedback commands * chore: optimize messenger intergration * chore: update onboarding style * feat: support wechat adapter attachments * feat: support ai attachments * chore: update i18n files * fix: bot message image attachment |
||
|
|
fd0d208152 | 💄 style(subscription): update budget recovery copy (#14875) | ||
|
|
566b261a12 |
✨ feat: support bot watch (#14796)
* feat: add whatsAPP and iMessage comming soon * chore: update i18n * feat: support watch keyword instruction * feat: add cli and messager api for bot channels * fix: test cases * feat: add system prompt for messenger tool * feat: add messenger mdx |
||
|
|
6933ddc4e5 |
🔨 chore: Online Messager (#14755)
* feat: add line integration Banner * chore: remove messenger lab switch * feat: add messenger banner * feat: add messenger promo * chore: update i18n files |
||
|
|
a109d22c8d |
🌐 i18n: add missing task-schedule and review strings to 16 locales (#14728)
🌐 i18n: add missing translations for task-schedule and review keys across 16 locales
Adds 14 missing i18n keys to all non-zh-CN locales (ar, bg-BG, de-DE,
es-ES, fa-IR, fr-FR, it-IT, ja-JP, ko-KR, nl-NL, pl-PL, pt-BR, ru-RU,
tr-TR, vi-VN, zh-TW):
chat.json (11 keys):
- taskSchedule.summary.everyNHoursHalfPast
- taskSchedule.summary.hourlyHalfPast
- taskSchedule.timezoneSearchEmpty
- taskSchedule.timezoneSearchPlaceholder
- workingPanel.review.revert (and 7 sub-keys)
plugin.json (1 key):
- builtins.lobe-task.apiName.setTaskSchedule
setting.json (2 keys):
- serviceModel.modelAssignments.title
- serviceModel.optionalFeatures.title
These were added in recent commits but the automated i18n sync had not
yet propagated them to non-Chinese locales.
|
||
|
|
b5c4abcaef | 🌐 i18n: update banner copy translations (#14623) | ||
|
|
c374892fea | 🐛 fix: add temporary email auth error locale (#14564) | ||
|
|
e56ccf6a5c |
🐛 fix: multiple account link (#14562)
* feat: avoid rebind link same account * chore: update i18n locales * feat: avoid discord account misslink * feat: support slack account mis match * fix: avoid claim conflict |
||
|
|
1c8ec2681c |
💄 style: update brief template style (#14483)
Co-authored-by: YuTengjing <ytj2713151713@gmail.com> |
||
|
|
2870cc73c2 |
✨ feat(builtin-tool-task): add Inspector + Render, batch createTasks/runTasks (#14403)
* ✨ feat(builtin-tool-task): add Inspector + Render, batch createTasks/runTasks Adds chip-style Inspector and per-API Render to the lobe-task tool, plus two batch APIs (createTasks, runTasks) so an agent can plan or launch a set of subtasks in a single call instead of calling createTask/runTask N times. runTask/runTasks call taskService.run, actually triggering TaskRunnerService and producing a topic+operationId — distinct from updateTaskStatus(running), which only flips a flag. The system prompt now spells this out so the model stops conflating the two. Already-running, missing-assignee, and per-item failures surface back to the agent with clear messages. Fixes LOBE-8438 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(server,task): implement createTasks/runTask/runTasks in server runtime The manifest exposes these APIs to the model, but only the client-side executor was implemented. Server-side tool execution (src/server/services/ toolExecution/builtin.ts) throws "Builtin tool ... is not implemented" when the runtime is missing a method, so production paths that route through the server runtime would fail at runtime. - Extracted createTaskImpl as a reusable closure so createTasks loops can reuse the parent-resolution + assignee-validation flow without copy-paste - runTask / runTasks call taskCaller.run(...) which already routes to TaskRunnerService — same execution path as the UI/CLI run buttons - runTasks continues past per-item failures and reports them in the summary (matching the client executor's behavior) - Added 7 tests (20 total in this file) covering happy path, per-item failure, missing identifier, and current-task fallback Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(task-drawer): hide topic feedback input until run terminates Feedback can only steer the next run, so showing the input while the topic is pending/running was misleading — gate it on terminal status (completed/failed/canceled/timeout). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d5097c7964 |
💄 fix(builtin-tool-agent-documents): wire Inspectors into registry, switch to chip UI (#14404)
* 💄 fix(builtin-tool-agent-documents): wire Inspectors into registry, switch to chip UI The Inspector components for lobe-agent-documents existed but were never registered in packages/builtin-tools/src/inspectors.ts, so the chat UI fell back to the default "(id:316c6ad5-10e7-46ff-8ccf-15f2359c19...)" header that shows raw param dumps. Registering them is the root fix. While in there, refactored all 9 inspectors to the chip pattern used by the other builtin tools — full UUIDs are noisy in a one-line header, so document ids are truncated to their first 8 chars (prefixed ids like agd_… are left intact since they're already short). Each inspector now surfaces the most useful per-API context: title chip when known (Read/Create), id chip + new title (Rename/Copy), op count + success ratio (Modify), char count (Replace), target scope + doc count (List), rule type (UpdateLoadRule), red dashed line-through (Remove). Shared chip styles live in one _styles.ts so the visual language stays consistent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 📝 docs(.agents/skills): add builtin-tool skill Self-contained reference for building/extending lobe-* builtin tools — SKILL.md entry point plus architecture / tool-design / ui deep-dives. Sits alongside the other agent skills. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
b49c1c15b7 |
🤖 style: update i18n (#14383)
💄 style: update i18n Co-authored-by: canisminor1990 <17870709+canisminor1990@users.noreply.github.com> |
||
|
|
346812ab88 |
🔨 chore: update i18n files & fix title skeleton (#14301)
* chore: update i18n files & fix title skeleton * chore: update taskTemplate json * chore: update i18n files |
||
|
|
70e7e441b2 |
🔨 chore: premerge Task detail page UI (#13653)
* ✨ feat: add AgentTaskList component on agent welcome page (LOBE-6597) - AgentTaskList with TaskListHeader, TaskItem, and styles - Embedded in AgentWelcome below ToolAuthAlert - Each task rendered as independent rounded card with status badge - Status: green filled circle (Done), blue circle (In progress) - Card width matches chat input (960px) - i18n keys for taskList.title and taskList.viewAll - Fix updateReview type to use TRPC-inferred type Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add Tasks page at /agent/:aid/tasks with route, breadcrumb, and view toggle (LOBE-6597) - Register tasks route in both desktopRouter.config.tsx and .desktop.tsx - Thin route page at src/routes/(main)/agent/tasks/index.tsx - Feature components in src/features/AgentTasks/: page, breadcrumb, header with list/kanban toggle, full task list - Wire up "View All Tasks" navigation from AgentTaskList welcome card - Add i18n keys (taskList.activeTasks, taskList.breadcrumb.task) and generate translations via pnpm i18n Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add Task detail page at /agent/:aid/tasks/:taskId (LOBE-6597) - Register :taskId child route in both desktopRouter configs - TaskDetailPage with auto-save hint, breadcrumb, and scrollable content - TaskDetailHeader: editable title (borderless Input), Run/Pause button, status/priority tags, delete - TaskInstruction: click-to-edit Markdown with debounced auto-save - TaskSubtasks: sub-issues list with status badges - TaskActivities: timeline with topic/brief/comment icons - TaskItem now navigates to detail page instead of just setting activeTaskId - Add taskDetail.* i18n keys with generated translations Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add TaskModelConfig, TaskScheduleConfig, and refine Task detail UI (LOBE-6597) Add model/provider selector and periodic execution config to Task detail page. Refine TaskDetailHeader, TaskInstruction with auto-save and i18n support. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: refine Task detail UI with Linear-style design (LOBE-6597) - Redesign SubTasks with collapsible header, progress circle, hover + click navigation - Redesign Activities with agent avatar, comment input box, and Linear-style layout - Add TaskParentBar showing parent task relationship with sibling navigation popover - Add delete confirmation modal using App.useApp().modal.confirm - Move ModelSelect to separate row below action bar - Fix zustand selector recreation in ActivityItem - Replace hardcoded colors with cssVar tokens Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add Properties panel, parent link hover, activity icon, and lifecycle save status (LOBE-6597) - Add TaskProperties sidebar with collapsible status/priority dropdowns - Parent bar: clickable parent link with hover, sibling navigation popover on progress - Activity title: add BotMessageSquare icon - Fix lifecycle actions not updating taskSaveStatus (saving/saved indicator) - Filter status dropdown to only user-selectable states (backlog/completed/canceled) - Add test task creation script for dev Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add recursive tree view for subtasks with Linear-style connecting lines (LOBE-6597) - Add buildTaskTree utility to convert flat getTaskTree API response into nested tree - Implement SubtaskTreeItem recursive component with CSS connecting lines (├─ and └─) - Fetch full task tree via taskService.getTaskTree for nested subtask display - Show loading spinner during tree fetch, fallback to flat list on error - Remove padding-inline from AgentTaskList container Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix: address PR review — delete redirect, debounce cleanup, schedule resync (LOBE-6597) - Redirect to task list after successful delete (P1) - Clean up instruction debounce timer on unmount/task switch to prevent stale writes (P1) - Resync TaskScheduleConfig local state when active task changes (P2) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor: use backend nested subtasks directly, remove buildTaskTree (LOBE-6597) Backend now returns nested subtasks in task.detail (LOBE-6814). Remove buildTaskTree utility, getTaskTree API call, and loading state. Use TaskDetailSubtask from @lobechat/types instead of local interface. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ⚡ perf: add optimistic update and save status for model config change (LOBE-6597) updateTaskModelConfig now immediately reflects new model/provider in UI via optimistic store dispatch, and tracks taskSaveStatus (saving/saved). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ⚡ perf: skip redundant refreshTaskDetail on successful model config update (LOBE-6597) Optimistic update is trusted on success — no need for full detail re-fetch. Aligns with updateTask pattern. Refresh kept only in error path for revert. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: use backend author info for activities, fix AgentTaskList after AgentHome refactor (LOBE-6597) - Activity: use act.author (TaskDetailActivityAuthor) from backend instead of agentMap lookup (LOBE-7013) - AgentTaskList: fix agentId from useParams instead of useAgentStore.activeAgentId (was undefined) - AgentHome: integrate AgentTaskList into new AgentHome layout (replaces old AgentWelcome) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: show participant avatars on task cards, use backend author for activities (LOBE-6597) - TaskItem: display up to 3 participant avatars next to task title (LOBE-6805) - Activity: use act.author from backend instead of agentMap lookup (LOBE-7013) - AgentHome: integrate AgentTaskList into new AgentHome layout - Revert AgentTaskList/TaskItem agentId back to useAgentStore (works correctly when mounted) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor: fix type safety, memoize participants filter, extract avatar styles (LOBE-6597) - Use TaskParticipant type instead of `any` in filter/map - Compute displayParticipants once with useMemo (was filtering twice per render) - Move avatar overlap styles to CSS classes (was inline objects per render) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🔇 chore: hide kanban view toggle until implemented (LOBE-6597) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor: export TaskStatus/TaskPriority/TaskActivityType from @lobechat/types (LOBE-6597) Replace hardcoded string/number types with shared type aliases: - TaskStatus: 'backlog' | 'canceled' | 'completed' | 'failed' | 'paused' | 'running' - TaskPriority: 0 | 1 | 2 | 3 | 4 - TaskActivityType: 'brief' | 'comment' | 'topic' Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: update * style: update * style: update * style: update * style: update * style: update * style: update * style: update * style: update * style: update * ✨ feat: add Daily Brief module to homepage (#13851) * ✨ feat: add Daily Brief module to homepage Add a Daily Brief section below the chat input on the homepage that displays unresolved briefs from the Agent Tasks system. Users can resolve, comment, and provide feedback directly from the brief cards. - Service: BriefService with listUnresolved, resolve, markRead, addComment - Store: Independent Zustand store (src/store/brief/) with SWR data fetching - Components: BriefCard, BriefCardActions (dynamic action buttons), BriefCardSummary (Markdown with expand/collapse), CommentInput (@lobehub/editor) - Three action types: resolve (closes brief), comment (resolve with text), link (safe URL navigation with protocol validation) - Fixed feedback button: adds task comment without resolving the brief - Inline success state ("Feedback sent") with 1.5s auto-restore - i18n: zh-CN + en-US translations - Tests: 21 tests across service, store selectors, and components - CLI: Register task and brief commands for local development Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add agent avatars to Daily Brief cards Display stacked agent avatars next to brief card titles using the new `agents` data from Arvin's enriched listUnresolved API (#13489). - Add AgentAvatarInfo type and agents field to BriefItem - Render overlapping circular avatars (20px, -6px overlap) - Use cssVar.colorBgContainer for border (dark mode compatible) - Extract avatar style to function to avoid inline object creation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor: clean up Daily Brief components - Extract duplicate success state JSX into reusable SuccessTag component - Remove redundant comments that describe what code does - Use DEFAULT_AVATAR from @lobechat/const instead of hardcoded emoji Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix: address PR review feedback for Daily Brief - Use cssVar.colorBgBase instead of hardcoded #fff for primary button text color (dark mode contrast fix) - Add submitting state to CommentInput to prevent duplicate submissions (disable buttons + show loading during async submit) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🌐 chore: generate i18n translations for Daily Brief Run pnpm i18n to generate translations for all 18 locales. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor: use shared BriefType from @lobechat/types Export BriefType union from packages/types and use it in BRIEF_TYPE_COLOR and BRIEF_TYPE_ICON records for compile-time key validation. Adding a new brief type now requires updating the shared type, and TypeScript will flag missing mappings. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: update * style: update * style: update --------- Co-authored-by: Tsuki <976499226@qq.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: update * style: update * style: update * style: update * fix: stopPropagation * fix: i18n * 🐛 fix: wire comment inputs to editor instance so Send actually submits CommentInput in AgentTasks and DailyBrief used antd TextArea inside @lobehub/editor's ChatInput while reading content via editor.getDocument('markdown'). The TextArea was never connected to the editor instance, so getDocument always returned empty and handleSubmit short-circuited silently — Send appeared to do nothing (no network request fired). Replace the TextArea with <Editor editor={editor} type="text" variant="chat" /> so useEditor() actually drives the editable surface. Keep plain-text behavior via markdownOption={false} + enablePasteMarkdown={false}, and bind Cmd/Ctrl+Enter submit via onPressEnter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix: use participant.title after TaskParticipant schema rename (#13877) PR #13877 renamed TaskParticipant.name → .title and added .backgroundColor. Our branch's UI code (AgentAvatars, listViewOptions, TaskList group header, Breadcrumb) was already written against the new schema, but TaskProperties still read firstParticipant?.name — update the last remaining call site so the type matches post-rebase. backgroundColor is already plumbed through everywhere it applies within #13877's scope; TaskActivities' TaskDetailActivityAuthor is a separate type untouched by the PR and kept as-is. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix: resolve type-check errors exposed after canary rebase canary upgraded react-i18next to a version with typed i18n keys and tightened @lobehub/editor's SendButton + IEditor APIs. Rebase pulled these in, surfacing latent type errors in LOBE-6597 code. - CommentInput: use editor.cleanDocument() (IEditor's actual API; clearContent never existed). - TaskActivities / TaskLatestActivity / TaskTriggerTag: type t as TFunction<'chat'> so typed i18n accepts the known-literal keys used inside module-level helpers. - TaskPriorityTag / TaskStatusTag / listViewOptions: add defaultValue: '' to dynamic-key t() calls (template literals and Record lookups) to match the broad-key i18n overload. - BriefCardActions: swap unusable <SendButton> (no children, no iconPlacement) for <Button>; add defaultValue to the dynamic brief-action key lookup; drop stale @ts-ignore. - DailyBrief/CommentInput: drop unsupported children on SendButton; keep label via title attribute. - Recents/Item: type TYPE_ICON_MAP as Partial<Record<...>> so 'task' (rendered via TaskStatusIcon elsewhere) is a safe absent key. - brief/slices/list/action: cast briefService.listUnresolved() result back to BriefItem[] (TRPC serialization widens BriefType to string). - AgentTasks/TasksHeader: delete dead file — no importers and its ./style module was removed by an earlier refactor. Also ran pnpm install to materialize the newly-extracted @lobechat/agent-gateway-client workspace package (canary #13866), clearing ~7 "cannot find module" errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor(builtin-tool-task): polish task tool paths (#13869) * ✨ feat: navigate to task detail when clicking brief card header Clicking the header row of a Daily Brief card (icon + title + time + agent avatars) now jumps straight to the associated task, using the brief's task-tree agent (with activeAgent / inbox as fallback). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: show parent task ids as clickable breadcrumb trail Walk the cached parent chain from taskDetailMap and insert each ancestor's identifier as a link between the "任务" entry and the current task name in the task detail breadcrumb. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add cross-agent /tasks page with View All Tasks on Daily Brief - Register `/tasks` route in desktop (web + Electron) and mobile router configs - `useFetchTaskList` supports `allAgents` mode via options object API to fetch tasks without agent filter; backend already supports optional assigneeAgentId - `Breadcrumb` accepts optional `agentId`, renders "All tasks" crumb when absent - `AgentTaskItem` navigation uses `task.assigneeAgentId` so clicks work from the cross-agent page (falls back to `activeAgentId` for unassigned tasks) - Extract `useScenarioEnabledTools` hook to share layout effect between `/tasks/_layout` and `/agent/:aid/tasks/_layout` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ♻️ refactor: use assigneeAgentId for task avatar instead of participants array Replace AgentAvatars (took participants[]) with AssigneeAvatar (takes agentId, resolves meta from agent store). This correctly represents that a task is assigned to a single agent via assigneeAgentId/detail.agentId. - New AssigneeAvatar component reads agent meta from agent store by ID - TaskProperties reads activeTaskAgentId from task detail store - listViewOptions uses task.assigneeAgentId directly for groupBy/sort - Extract shared isInboxAgentId helper to eliminate 4x inline duplication - Group headers resolve agent title at render time via AssigneeLabel component Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix: enable vertical scrolling on cross-agent tasks page Add overflowY and flex to WideScreenContainer wrapper so the task list can scroll when content exceeds viewport height. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add re-assign task agent with popover selector - Add AssigneeAgentSelector component with Popover agent list - Extract useAgentDisplayMeta hook for consistent agent name/avatar resolution - Fix optimistic update mapping assigneeAgentId → agentId in task store - Disable reassignment for running tasks with tooltip hint - Integrate selector into task list and task detail property panel Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: reuse BriefCard in task detail activities & fix raw-id navigation Render brief-type activities as full BriefCard (same as homepage) instead of plain tree rows. Decouple BriefCardActions from useBriefStore for actions lookup so it can be reused across pages. Fix infinite loading when navigating to task detail via raw DB id (task_xxx) by storing detail under both the identifier and the raw id key in taskDetailMap. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add TopicCard component for task detail activities Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: allow re-running completed tasks with dedicated button Completed tasks now show a "Re-run" button (with rotate icon) instead of hiding the action. The backend already supported this — only the frontend selector gate needed updating. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: add create task modal with markdown editor Add a "+" button on the tasks list page that opens a Linear-style modal for manually creating tasks. The modal features a title input, a markdown editor (EditorCanvas), and a bottom toolbar with priority and assignee selectors. Existing tag components (TaskStatusTag, TaskPriorityTag, AssigneeAgentSelector) are extended with an `onChange` controlled mode so they can be used in creation context where no task exists yet. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 🐛 fix: suppress spurious updateTask on Task Detail page load EditorDataMode was missing the contentChangeLockRef pattern that DocumentIdMode already uses, causing Lexical's registerUpdateListener to treat programmatic content hydration as a user edit and fire onContentChange → updateTask on every page visit. - Add contentChangeLockRef + lockIdRef staleness guard - Extract loadContentWithLock to deduplicate lock/load/unlock logic - Pass contentChangeLockRef to InternalEditor - Remove unreachable dead code in loadEditorContent Closes LOBE-7362 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ✨ feat: task detail comment CRUD and various UX improvements Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix: move canceled status group to the end of task list Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style: polish task detail layout, title, and run button - Title switched to auto-sizing TextArea so long names wrap (like Linear) - Reduce title font-size from 32px to 24px and tighten paddings - Make "运行任务" button small-sized to match the denser header - Add 120px bottom padding for end-of-content scroll breathing room - Default EditorCanvas paddingBottom trimmed from 64 to 32 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style: refine task assignee, priority, and comment input - Assignee block uses filled variant in dark mode for better contrast - Urgent priority (level 1) renders in orange for quick scanning - Comment input keeps SendButton slot reserved to prevent layout shift Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat: task detail — inline subtasks, automation mode, chronological activity - Inline subtask creation under a task via CreateTaskInlineEntry (parentTaskId/autoFocus/onCollapse/placeholder), refreshes parent on create - Track agent-created tasks via createdByAgentId through service, router, types, and the builtin task executor - Replace scheduler Segmented-only UI with an Enable switch + heartbeat/ schedule mode; persist via automationMode on the task - Sort detail activities oldest → newest for a natural timeline reading - Reducer patches nested subtask entries on updateTaskDetail so in-place edits reflect in the parent's subtask tree Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style: render activate-tool chips as rounded pills Switch inspector tool chips from monospace code tags to filled rounded pills with ellipsis overflow, making multi-tool rows scan better in tight headers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix: keep finished tool call out of loading state while siblings run The message-level isAssistantMessageBusy flag stays true while sibling tool calls are still running. Without guarding on this tool's own result, a finished tool would flip back to "loading". Now a tool that has a real result or error is never shown as calling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style: use small Segmented in schedule config popover Keeps the automation mode switcher visually aligned with the denser popover controls. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat: agent profile hover card on task activity author - Extract shared AgentProfileCard + unified AgentProfilePopup (click / hover) with lazy agent fetch; move out of group sidebar path. - Wire activity author avatar + name to a hover card; brighten title on hover; keep a small "agent" tag on the author row. - Show inline skeletons (description + footer stats) while loading. - Enrich subtask payload with assignee agent info for cleaner UI. * ✨ feat: open task topic chat in side drawer Click a topic row in the task detail activities to open a right-side drawer showing the topic's full chat history. Messages stream in live via the existing agent gateway pipeline (gateway events land in chatStore.dbMessagesMap keyed by the topic context), so a running topic refreshes its drawer in real time without a dedicated subscription. Reuses the Conversation feature (ConversationProvider + ChatList) with an isolated context (agentId + topicId + isolatedTopic), so the drawer never touches the global active topic and multiple panels coexist cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style: outline activate-tool chip with subtle border Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ✨ feat: show topic handoff summary on activity card Pull `handoff.summary` through the task service into TaskDetailActivity and render it under the title in TopicCard so completed topics surface what was accomplished without opening the drawer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🎸 chore: gate agent task feature behind agent_task flag Hide every client-side entry point to the Agent Task feature when the `agent_task` flag (default `isDev`, off in prod) is disabled: - Sidebar: task tab in the agent sidebar nav - Routes: `/agent/:aid/tasks/*` and `/tasks/*` layouts redirect to `/` when the flag is off (mobile router reuses the same layout) - Home Recents: filter out `type='task'` items in both the list and the "all recents" drawer - Daily Brief: skip fetch + hide the entire panel (all briefs link to tasks) Backend TRPC / lifecycle stays on — the feature is already live for CLI usage. Flag name mirrors `agent_onboarding` for consistency. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix: prioritize includeTriggers in topic queries * 🐛 fix: normalize task detail activity payloads * ✨ feat: add Kanban board view for task list with drag-and-drop LOBE-7493 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * 💄 style: shorten schedule tag labels & fix time width in task cards Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * update i18n * 💄 style: hide task tool from user selectors * 💄 style: hide task skill from user selectors --------- Co-authored-by: canisminor1990 <i@canisminor.cc> Co-authored-by: YuTengjing <ytj2713151713@gmail.com> Co-authored-by: Arvin Xu <arvinx@foxmail.com> |
||
|
|
c5db823a69 | 💄 style: add Kimi K2.6 to LobeHub-hosted card (#14006) | ||
|
|
632a6383f0 | ✨ feat(app): working panel, and many agent document feat (#13766) | ||
|
|
5d135b3ae1 |
🔨 fix: layout sidebar en More (#13723)
* fix: layout sidebar en More * chore: update i18n files |
||
|
|
147ff3976f | ✨ feat: add Seedance 2.0 & 2.0 Fast video generation models (#13663) | ||
|
|
965fc929e1 |
feat: add unified messaging tool for cross-platform communication (#13296)
* ✨ feat: add cross-platform message tool for AI bot channel operations Implement a unified message tool (`lobe-message`) that provides AI with messaging capabilities across Discord, Telegram, Slack, Google Chat, and IRC through a single interface with platform-specific extensions. Core APIs: sendMessage, readMessages, editMessage, deleteMessage, searchMessages, reactToMessage, getReactions, pin/unpin management, channel/member info, thread operations, and polls. Architecture follows the established builtin-tool pattern: - Package: @lobechat/builtin-tool-message (manifest, types, executor, ExecutionRuntime, client components) - Registry: registered in builtin-tools (renders, inspectors, interventions, streamings) - Server runtime: stub service ready for platform adapter integration https://claude.ai/code/session_011sHc6R7V4cSYKere9RY1QM * feat: implement platform specific message service * chore: add wechat platform * chore: update wechat api service * chore: update protocol implementation * chore: optimize platform api test * fix: lark domain error * feat: support bot message cli * chore: refactor adapter to service * chore: optimize bot status fetch * fix: bot status * fix: channel nav ignore * feat: message tool support bot manage * feat: add lobe-message runtime * feat: support direct message * feat: add history limit * chore: update const limit * feat: optimize server id message history limit * chore: optimize system role & inject platform environment info * chore: update readMessages vibe * fix: form body width 50% * chore: optimize tool prompt * chore: update i18n files * chore: optimize read message system role and update bot message lh * updage readMessage api rate limit * chore: comatible for readMessages * fix: feishu readMessage implementation error * fix: test case * chore: update i18n files * fix: lint error * chore: add timeout for conversaction case * fix: message test case * fix: vite gzip error --------- Co-authored-by: Claude <noreply@anthropic.com> |