| feat: rebrand stable app icon
Signed-off-by: Innei <tukon479@gmail.com>
| 3 ไธชๆๅ |
| โจ feat(agent): add floating chat panel and workspace improvements (#13887)
* โจ feat(FloatingChatPanel): add single-instance mount guard
* โจ feat(FloatingChatPanel): add inner ChatBody layout
* โจ feat(FloatingChatPanel): add reusable floating conversation panel
* โ
test(FloatingChatPanel): add props wiring smoke tests
* Refactor agent topic and page routes
* Restore topic page routing for floating chat panel
* โจ feat(FloatingChatPanel): enhance ChatBody and TopicItem for improved routing and styling
- Updated ChatBody to maintain scroll ownership while hiding overflow.
- Refactored TopicItem to correctly highlight active topics based on routing context.
- Added tests for TopicItem to ensure correct active state behavior.
- Introduced static styles for FloatingChatPanel to manage layout overflow.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: help to merge & rebase
* chore: align merge with canary โ drop pkg.pr.new ui, adopt canary useMenu, remove NotebookButton
* โจ feat: add ViewSwitcher component and update localization for chat views
- Introduced a new ViewSwitcher component to toggle between chat, page, and task views in the conversation header.
- Updated English and Chinese localization files to include new labels for the view switcher options.
- Refactored the conversation header to integrate the ViewSwitcher, enhancing the user interface for better navigation.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: update @lobehub/ui to version 5.9.1 and refactor FloatingChatPanel to use FloatingSheet component
- Updated the @lobehub/ui dependency in package.json to version 5.9.1.
- Refactored FloatingChatPanel to utilize the new FloatingSheet component, enhancing its layout and state management.
- Introduced a new ChatLayout component for better organization of chat-related UI elements.
- Adjusted routing configuration to incorporate the new ChatLayout for agent chat pages.
Signed-off-by: Innei <tukon479@gmail.com>
* feat: add TopicCanvas and TitleSection components for topic management
- Introduced TopicCanvas component to serve as a document canvas for topics, integrating an editor and title section.
- Added TitleSection component for managing topic titles and emojis, enhancing user interaction with a dedicated UI.
- Updated FloatingChatPanel to accommodate the new TopicCanvas, ensuring a cohesive layout in the topic page.
- Enhanced tests to verify the integration of TopicCanvas within the topic page route.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat(agent-page): bind documentId to URL and introduce HeaderSlot
- Add nested /agent/:aid/:topicId/page/:docId route with PageRedirect for bare /page
- Introduce useAutoCreateTopicDocument with module-level inflight de-dup
- Lift Portal + WorkingSidebar to (chat) layout; keep ChatHeader in left column
- Sidebar document clicks on page route navigate to /page/:docId instead of opening Portal
- Add HeaderSlot (context + createPortal) as a reusable header injection point
- Mount AutoSaveHint via HeaderSlot; register Files hotkey scope in TopicCanvas so Cmd+S triggers manual save
- Sync desktopRouter.config.tsx and desktopRouter.config.desktop.tsx
- Extend RecentlyViewed plugin to round-trip optional docId segment
* Use topic titles for auto-created page documents
* Add page-agent init gating and runtime diagnostics
* Support current-topic agent documents
* Implement Active Topic Document and Disabled Tool Call Filtering
- Introduced ActiveTopicDocumentContextInjector to inject context for active topic documents into user messages.
- Added DisabledToolCallFilter to remove historical tool calls for disabled tools in the current runtime scope.
- Updated MessagesEngine to utilize the new context injectors and filters.
- Enhanced tests to verify the correct injection of active topic document context and filtering of disabled tool calls.
This update improves the handling of document editing contexts and tool management in the conversation flow.
Signed-off-by: Innei <tukon479@gmail.com>
* feat: enhance agent document management with LiteXML operations
- Updated API names for clarity, changing 'patchDocument' to 'modifyNodes'.
- Introduced LiteXML operation schema for document modifications.
- Implemented new mutation for modifying document nodes via LiteXML.
- Enhanced document retrieval methods to support format options (XML, Markdown, Both).
- Added support for editor data snapshots and normalization of diff nodes.
- Improved document history management to handle editor data with diff nodes.
- Created tests for new features and ensured existing functionality remains intact.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix: apply agent document xml edits directly
* Refine document cache invalidation and editor hydration
* ๐ fix: stabilize agent topic hydration
* fix: update @lobehub/editor dependency version and clean up test mocks
Signed-off-by: Innei <tukon479@gmail.com>
* Potential fix for pull request finding 'Useless assignment to local variable'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* ๐ fix(document): preserve pending diff nodes through save path
Skip normalizeEditorDataDiffNodes on every autosave so diff nodes awaiting
user review survive persistence. Normalization now runs only on explicit
Accept/Reject via DiffAllToolbar. Also flip headless litexml ops to delay:true
to match the new review flow.
* ๐ fix(agent): detect agent sub-route from URL params not cached topic
isInAgentSubRoute used routeTopicId (with activeTopicId fallback) as its
base path. On /agent/:aid/profile with a cached activeTopicId, the base
became /agent/:aid/:cachedTopicId which pathname cannot startsWith, so
sub-route detection returned false and sidebar topic clicks only called
switchTopic without routing back to chat โ users stayed stuck on profile.
Derive the sub-route base from params.topicId directly so stale store
state cannot mask the check. routeTopicId export keeps the fallback for
sidebar highlighting.
* ๐ fix(page): repair topic page document recovery
* ๐ fix(page-agent): block tool calls when page editor is not mounted
scope is topic-bound not route-bound, so navigating from /agent/.../Page
to /agent/... keeps scope==='page' and PageAgentIdentifier stayed in the
injected plugin list. The LLM could still call initPage / modifyNodes /
etc. against a stale editor reference, returning misleading success
(e.g. nodeCount=0).
Two layers of guard:
- PageAgentExecutor wraps `invoke` and returns a structured
PAGE_EDITOR_NOT_MOUNTED / kind: 'replan' result when the runtime
editor is not mounted, pointing the LLM at lobe-agent-documents.
- streamingExecutor drops PageAgentIdentifier from the tool set via
the new `composeEnabledTools` pipeline when scope==='page' and
the page-agent runtime is not ready.
Also extract the tool-set composition (inject merge + runtime drops)
out of the ~320-line internal_createAgentState into
`mecha/toolSetComposer`, with unit tests.
* ๐ fix(chat): unify message stream for /agent/:topicId and /page/:docId
Before this change a page-scoped conversation (FloatingChatPanel with
scope='page' in the /Page route) partitioned the client message store by
scope, so /agent/:topicId and /agent/:topicId/page/:docId each built their
own messagesMap slot and SWR cache โ but the TRPC getMessages endpoint
ignores scope and returned the same messages for both, producing duplicate
fetches and a visible message-history split between the two surfaces.
Fixes by keeping scope='page' as a capability/surfacing marker only:
- messageMapKey: collapse 'page' to the default scope early in
toMessageMapContext, so threadId/groupId still win and only the
main/page pair actually unifies.
- useFetchMessages: build the SWR key from identity fields
(agentId, groupId, threadId, topicId) instead of the full
ConversationContext, so scope no longer partitions the cache.
agentConfigResolver/streamingExecutor/composeEnabledTools still read
scope='page' from operation.context for PageAgent injection and
initialContext.pageEditor wiring โ the capability layer is unchanged.
Also fix two pre-existing test regressions surfaced by re-running the
impacted suites:
- streamingExecutor page-editor initialContext test now mocks
pageAgentRuntime.isReady() (required since the PageAgent editor-ready
guard landed).
- FloatingChatPanel default shell props test updated to match the
[180,320,520,800] snap points introduced in 62dc91e444.
* โป๏ธ refactor(FloatingChatPanel): read main slot without changing scope
Revert the global messageMapKey/SWR-key changes from b650cdc9d7 โ the
global collapse over-reached and coupled message routing to scope in
ways other surfaces don't want. Instead, specialize only the place that
actually has the dual-role problem.
`scope` should be a capability marker (PageAgent tool + pageEditor
initialContext injection), not a message-list partition. Floating panel
on /agent/:topicId/page is the only caller that sets scope='page', and
its message list should mirror /agent/:topicId โ the surfaces share a
topic.
Local collapse in FloatingChatPanel: compute chatKey with
`scope === 'page' ? 'main' : scope`, so messagesMap is read from the
main slot. The downstream ConversationContext keeps scope='page' for
the capability layer; only the slot lookup is specialized.
Kept from b650cdc9d7 (unrelated to the revert):
- streamingExecutor test mocks pageAgentRuntime.isReady() โ required
by the PageAgent editor-ready guard in 01ef7bc142.
- FloatingChatPanel snap-points test matches [180,320,520,800] from
62dc91e444.
* ๐ fix(FloatingChatPanel): simplify chat key computation for message retrieval
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix(index.desktop.test): update LocationProbe to reflect route changes and improve test accuracy
Signed-off-by: Innei <tukon479@gmail.com>
* Constrain agent header title under centered switcher
* ๐ Fix conversation header view switcher layout
* ๐ Fix agent topic path links and cmdk context
* ๐ fix(test): align document history fixtures and layout ui mock
* ๐ fix(e2e): support dialog-based topic rename
* โป๏ธ refactor(debug): use scoped debuggers for PR logging
---------
Signed-off-by: Innei <tukon479@gmail.com>
Co-authored-by: Neko Ayaka <neko@ayaka.moe>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> | 29 ๅคฉๅ |
| ๐ chore: translate non-English strings to English in apps/cli, apps/device-gateway, and apps/desktop scripts (#14626)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> | 13 ๅคฉๅ |
| ๐ fix(conversation): only swap model name for remote hetero agents in Usage (#15156)
* ๐ fix(conversation): only swap model name for remote hetero agents in Usage
Local CLI hetero agents (claude-code, codex) report their actual model
id on `turn_metadata` and persist it on the assistant message, but the
Usage extra was unconditionally replacing it with the provider brand
label ("Claude Code" / "Codex") whenever `HETEROGENEOUS_TYPE_LABELS`
had an entry. Gate the swap to remote platform agents (openclaw,
hermes) โ those don't expose a real model id โ so CC/Codex turns show
the underlying model again.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* โ
test(desktop): update GatewayConnectionCtr tests for lh hetero exec route
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> | 27 ๅ้ๅ |
| โจ feat: set OSS default model to DeepSeek V4 Pro (#14555) | 14 ๅคฉๅ |
| โจ feat(agent-browser): add browser automation skill and tool detection (#12858)
* โจ feat(tool-detectors): add browser automation support and refactor tool detector categories
- Introduced browser automation detectors to the tool detector manager.
- Updated tool categories to include 'browser-automation'.
- Refactored imports to use type imports where applicable for better clarity.
- Cleaned up unnecessary comments in tool filters.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง chore: add browser automation tool detection UI
* ๐ง chore: update react-scan version and enhance agent-browser documentation
- Updated `react-scan` dependency from version 0.4.3 to 0.5.3 in package.json.
- Improved documentation in `content.ts` for the agent-browser, clarifying command usage and workflows.
- Added development mode flag `__DEV__` in sharedRendererConfig for better environment handling.
- Integrated `scan` functionality in `initialize.ts` to enable scanning in development mode.
- Updated global type definitions to include `__DEV__` constant for clarity.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง chore(builtin-skills): add dependency and refactor skill filtering logic
- Added `@lobechat/const` as a dependency in package.json.
- Introduced a new function `shouldEnableBuiltinSkill` to determine if a skill should be enabled based on the environment.
- Refactored the `builtinSkills` export to filter skills using the new logic.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง chore(builtin-skills): refactor skill management and add filtering logic
- Removed unnecessary dependency from package.json.
- Simplified skill filtering logic by introducing `filterBuiltinSkills` and `shouldEnableBuiltinSkill` functions.
- Updated various components to utilize the new filtering logic for managing builtin skills based on the environment.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat(builtin-skills): introduce new skill APIs and refactor manifest structure
- Added new APIs for skill management: `runSkillApi`, `readReferenceApi`, and `exportFileApi` to enhance functionality.
- Created a base manifest file (`manifest.base.ts`) to centralize API definitions.
- Updated the desktop manifest (`manifest.desktop.ts`) to utilize the new base APIs.
- Refactored existing manifest to streamline API integration and improve maintainability.
- Introduced a detailed system prompt for better user guidance on skill usage.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat: desktop skill runtime, skill store inspectors, and tool UI updates
Made-with: Cursor
* โจ feat: enhance skill import functionality and testing
- Updated `importFromUrl` method in `SkillImporter` to accept additional options for identifier and source.
- Modified `importFromMarket` in `agentSkillsRouter` to utilize the new options for better tracking of skill imports.
- Added integration tests to ensure stable behavior when re-importing skills from the market, verifying that identifiers remain consistent across imports.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง chore: update .gitignore and package.json dependencies
- Added 'bin' to .gitignore to exclude binary files from version control.
- Included 'fflate' as a new dependency in package.json to support file compression in the application.
- Updated writeFile method in LocalFileCtr to handle file content as Uint8Array for improved type safety.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง chore: update package.json dependencies
- Removed 'fflate' from dependencies and added it to devDependencies for better organization.
- Ensured proper formatting by adding a newline at the end of the file.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat: add agent-browser download script and integrate binary handling
- Introduced a new script to download the `agent-browser` binary, ensuring it is available for the application.
- Updated `electron-builder.mjs` to include the binary in the build process.
- Modified `dir.ts` to define the binary directory path based on the packaging state.
- Enhanced the `App` class to set environment variables for the agent-browser integration.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat: add DevTools toggle to Linux and Windows menus
- Introduced a new menu item for toggling DevTools with the F12 accelerator key in both Linux and Windows menu implementations.
- Added a separator for better organization of the view submenu items.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat: integrate agent-browser binary download into build process
- Added functionality to download the `agent-browser` binary during the build process in `electron-builder.mjs`.
- Enhanced the download script with detailed logging for better visibility of the download status and errors.
- Updated the `App` class to log the binary directory path for improved debugging.
- Reintroduced the `AuthRequiredModal` in the layout for desktop users.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: mock binary directory path in tests
- Added a mock for the binary directory path in the App tests to facilitate testing of the agent-browser integration.
- This change enhances the test environment by providing a consistent path for the binary during test execution.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix: improve authorization notification handling
- Updated the `notifyAuthorizationRequired` method to implement trailing-edge debounce, ensuring that rapid 401 responses are coalesced and the IPC event is sent after the burst settles.
- Refactored the notification logic to enhance clarity and maintainability.
โจ feat: add desktop onboarding redirect
- Introduced a `useEffect` hook in `StoreInitialization` to redirect users to the `/desktop-onboarding` page if onboarding is not completed, ensuring a smoother user experience on fresh installs.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix(desktop): hide Agent Browser skill on Windows
Made-with: Cursor
* ๐ง chore: update memory limits for build processes
- Increased the `NODE_OPTIONS` memory limit for both `build:next` and `build:spa` scripts from 6144 to 7168, optimizing build performance and resource management.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 2 ไธชๆๅ |
| ๐ fix(desktop): add auth required modal and improve error handling (#11574)
* ๐ fix(desktop): add auth required modal and improve error handling
- Add AuthRequiredModal component to handle authentication expiration
- Improve backend proxy protocol error handling for auth errors
- Add updater manager authentication header support
- Add i18n strings for auth error messages
* ๐ง fix(desktop): update UpdaterManager to leave channel unset for GitHub prerelease matching
- Modify UpdaterManager to leave the channel unset, allowing GitHub to use version tags for prerelease matching.
- Update logging to reflect the new behavior when the channel is unset or kept as is.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง fix(desktop): clarify UpdaterManager behavior for GitHub provider
- Update comments and logging in UpdaterManager to clarify that the channel is left unset for beta/nightly, allowing GitHub to use version tags for prerelease matching.
- Ensure logging accurately reflects the new behavior when the channel is unset.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat(desktop): add desktop build channel script and update documentation
- Introduced a new script for building desktop applications for specific release channels (stable, beta, nightly).
- Updated package.json to include a new npm command for the build channel.
- Enhanced README documentation to guide users on simulating CI channel builds and retaining changes.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง fix(desktop): streamline NODE_ENV usage in logger and config
- Removed redundant process.env.NODE_ENV definition from electron.vite.config.ts.
- Simplified logger implementation by directly using process.env.NODE_ENV for environment checks.
- Improved readability and maintainability of logging behavior based on the environment.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง fix(desktop): enhance logging configuration to support debug mode
- Updated logger configuration to allow for debug level logging when DEBUG environment variable is set.
- Simplified the logic for console logging levels based on the environment, improving clarity and maintainability.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง fix(desktop): enhance version generation and logging in UpdaterManager
- Updated version generation logic in manual-build-desktop.yml to handle channel suffixes more effectively.
- Added inferredChannel logging in UpdaterManager to improve clarity on the current update channel being used.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง fix(desktop): update localization files and set default entry locale to English
- Changed default entry locale from Chinese (zh-CN) to English (en) in .i18nrc.js.
- Added full disk access messages in multiple languages (Arabic, Bulgarian, German, Spanish, French, Italian, Japanese, Korean, Dutch, Polish, Portuguese, Russian, Turkish, Vietnamese, Traditional Chinese).
- Enhanced menu localization with new settings and permissions options across various languages.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 4 ไธชๆๅ |
| โช revert: revert pnpm v11 migration (#14372)
* Revert "๐ท build: disable pnpm gvs for desktop ci (#14357)"
This reverts commit 948ba5ec68e347a116f52e3599894d3002f0cb9a.
* Revert "๐ท build(repo): migrate to pnpm v11 and consolidate workspace config (#14316)"
This reverts commit 1d9b6099bd7ce72d0b656d45936fc81cd8d0ee68. | 22 ๅคฉๅ |
| โจ feat: refactor desktop implement with brand new 2.0
| 4 ไธชๆๅ |
| ๐ง chore: update eslint v2 configuration and suppressions (#12133)
* v2 init
* chore: update eslint suppressions and package dependencies
- Removed several eslint suppressions related to array sorting and reversing from eslint-suppressions.json to clean up the configuration.
- Updated @lobehub/lint package version from 2.0.0-beta.6 to 2.0.0-beta.7 in package.json for improvements and bug fixes.
- Made minor formatting adjustments in vitest.config.mts and various SKILL.md files for better readability and consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: clean up import statements and formatting
- Removed unnecessary whitespace in replaceComponentImports.ts for improved readability.
- Standardized import statements in contextEngineering.ts and createAgentExecutors.ts by adding missing spaces for consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: update eslint suppressions and clean up code formatting
* ๐ fix: use vi.hoisted for mock variable initialization
Fix TDZ error in persona service test by using vi.hoisted() to ensure
mock variables are available when vi.mock factory runs.
---------
Signed-off-by: Innei <tukon479@gmail.com>
| 3 ไธชๆๅ |
| โจ feat: refactor desktop implement with brand new 2.0
| 4 ไธชๆๅ |
| โจ feat(desktop): screen capture overlay, Quick Chat tray, and upload pipeline improvements (#13818)
* feat: add screen capture functionality with overlay support
- Implemented ScreenCaptureManager to handle screen capture sessions.
- Added ScreenCaptureCtr for IPC methods related to screen capture.
- Created overlay.html and ScreenCaptureOverlay component for user interaction.
- Integrated window enumeration and capture logic using node-screenshots and get-windows.
- Updated menu options to include screen capture actions.
- Enhanced RendererUrlManager to support overlay routing.
- Introduced drag selection for capturing specific screen areas.
- Added necessary types and events for screen capture in electron-client-ipc.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat(desktop): refine screen capture overlay flow
* โจ feat(desktop): refine screen capture overlay flow
* โก feat(desktop): optimize screen capture overlay flow
* Delete apps/desktop/mockup/screen-capture-overlay.html
* โจ feat(desktop): open mini toolbar via double Option
* ๐ fix(desktop): separate quick composer hotkey
* ๐ fix(desktop): remove stale quick composer accelerator
* ๐ fix(desktop): stabilize double option monitor
* ๐ fix(desktop): read hardware option key state
* ๐ fix(desktop): standardize path imports and improve error handling
- Replaced `join` imports with `path` imports for consistency across files.
- Enhanced error handling in various modules to include error causes for better debugging.
- Updated test files to reflect changes in variable naming and mock implementations.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ฅ chore(hotkey): drop orphan renderer quickComposer i18n entries
The `quickComposer` hotkey is registered only on the Electron side
(DESKTOP_GLOBAL_SHORTCUT_DEFAULTS + BrowserWindowsCtr.openQuickComposer);
the renderer never referenced these i18n keys, so the entries were dead.
`desktop.quickComposer` covers the app-level trigger.
* โก๏ธ perf(screen-capture): parallelize overlay upload with route navigation
Overlay submit used to await screenshot upload before router.push,
blocking the main window for several seconds when the user was on an
unrelated page (e.g. /settings). Now we navigate immediately and run
upload in a background IIFE; MessageFromUrl waits on a new
`uploadStatus` field before calling sendMessage, so the chat page
mount and the upload proceed in parallel.
- Add `uploadStatus: 'uploading' | 'ready' | 'failed'` to
PendingOverlayDispatch; canConsumePendingOverlayDispatch blocks
while `'uploading'`.
- Store gains `markDispatchUploadComplete`; on failure it clears
screenshotFileNames so the prompt still delivers.
- Dispatcher drops stale prev search params on push to prevent
MessageFromUrl's message-param effect from double-firing.
* โก๏ธ perf(screen-capture): pre-upload captures in overlay preview + per-thumbnail status
Move uploads from post-submit to preview time, bypassing dataUrl round-trips:
- Main process assigns captureId at preview time and ships the PNG bytes
as ArrayBuffer to the main renderer via `overlayUploadRequest`.
- Main renderer uploads through a dedicated pool (uploadWithProgress,
no chatUploadFileList pollution); reports status back to the overlay
through `overlayCaptureUploadStatus`.
- Overlay thumbnails render a spinner / error badge based on status;
the send button stays grey until every capture resolves to `ready`.
- Submit now carries only captureIds; MessageFromUrl awaits the pool
promises before sendMessage, removing the second upload pass.
- Carry overlay-selected modelId/provider into the agent config so the
first message actually uses the user-chosen model (fixes the bug where
switching the model on the overlay had no effect).
* update
* โจ feat(popup): add Quick Chat tray entry backed by Inbox agent
Tray menu now exposes a "Quick Chat" action that opens (or focuses)
a single-instance popup window at `/popup/agent/inbox`. Each fresh
open starts with no active topic; the first message creates one
through the normal agent flow.
- New `PopupAgentQuickPage` resolves the inbox slug via
`builtinAgentSelectors.inboxAgentId` so `activeAgentId` points at
the real entity in `agentMap` (fixes the stuck-loading / skeleton
state from using the literal `'inbox'` slug).
- `BrowserManager.openQuickChatPopup` wraps
`createMultiInstanceWindow` with a fixed `topicPopup_quick_inbox`
uniqueId so repeat clicks focus rather than spawn.
- Wire the action into macOS / Windows / Linux tray menus and add
the `tray.quickChat` i18n key.
* Add quick chat shortcut and desktop hotkey support
* โจ feat(screen-capture): enhance window enumeration with scale factor support
- Updated `enumerateWindows` to accept an optional `displayScaleFactor` parameter for improved window geometry normalization on high-DPI displays.
- Refactored `normalizeWindowBounds` to handle scaling based on the provided scale factor, ensuring accurate window dimensions across different platforms.
- Adjusted tests in `WindowSourceService.test.ts` to validate the new scaling behavior for both Windows and macOS environments.
- Minor adjustments in `ScreenCaptureManager` to accommodate the updated window enumeration logic.
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| ๐ docs: update documents (#12982)
update document | 2 ไธชๆๅ |
| ๐ docs: update documents (#12982)
update document | 2 ไธชๆๅ |
| โจ feat(desktop): screen capture overlay, Quick Chat tray, and upload pipeline improvements (#13818)
* feat: add screen capture functionality with overlay support
- Implemented ScreenCaptureManager to handle screen capture sessions.
- Added ScreenCaptureCtr for IPC methods related to screen capture.
- Created overlay.html and ScreenCaptureOverlay component for user interaction.
- Integrated window enumeration and capture logic using node-screenshots and get-windows.
- Updated menu options to include screen capture actions.
- Enhanced RendererUrlManager to support overlay routing.
- Introduced drag selection for capturing specific screen areas.
- Added necessary types and events for screen capture in electron-client-ipc.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat(desktop): refine screen capture overlay flow
* โจ feat(desktop): refine screen capture overlay flow
* โก feat(desktop): optimize screen capture overlay flow
* Delete apps/desktop/mockup/screen-capture-overlay.html
* โจ feat(desktop): open mini toolbar via double Option
* ๐ fix(desktop): separate quick composer hotkey
* ๐ fix(desktop): remove stale quick composer accelerator
* ๐ fix(desktop): stabilize double option monitor
* ๐ fix(desktop): read hardware option key state
* ๐ fix(desktop): standardize path imports and improve error handling
- Replaced `join` imports with `path` imports for consistency across files.
- Enhanced error handling in various modules to include error causes for better debugging.
- Updated test files to reflect changes in variable naming and mock implementations.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ฅ chore(hotkey): drop orphan renderer quickComposer i18n entries
The `quickComposer` hotkey is registered only on the Electron side
(DESKTOP_GLOBAL_SHORTCUT_DEFAULTS + BrowserWindowsCtr.openQuickComposer);
the renderer never referenced these i18n keys, so the entries were dead.
`desktop.quickComposer` covers the app-level trigger.
* โก๏ธ perf(screen-capture): parallelize overlay upload with route navigation
Overlay submit used to await screenshot upload before router.push,
blocking the main window for several seconds when the user was on an
unrelated page (e.g. /settings). Now we navigate immediately and run
upload in a background IIFE; MessageFromUrl waits on a new
`uploadStatus` field before calling sendMessage, so the chat page
mount and the upload proceed in parallel.
- Add `uploadStatus: 'uploading' | 'ready' | 'failed'` to
PendingOverlayDispatch; canConsumePendingOverlayDispatch blocks
while `'uploading'`.
- Store gains `markDispatchUploadComplete`; on failure it clears
screenshotFileNames so the prompt still delivers.
- Dispatcher drops stale prev search params on push to prevent
MessageFromUrl's message-param effect from double-firing.
* โก๏ธ perf(screen-capture): pre-upload captures in overlay preview + per-thumbnail status
Move uploads from post-submit to preview time, bypassing dataUrl round-trips:
- Main process assigns captureId at preview time and ships the PNG bytes
as ArrayBuffer to the main renderer via `overlayUploadRequest`.
- Main renderer uploads through a dedicated pool (uploadWithProgress,
no chatUploadFileList pollution); reports status back to the overlay
through `overlayCaptureUploadStatus`.
- Overlay thumbnails render a spinner / error badge based on status;
the send button stays grey until every capture resolves to `ready`.
- Submit now carries only captureIds; MessageFromUrl awaits the pool
promises before sendMessage, removing the second upload pass.
- Carry overlay-selected modelId/provider into the agent config so the
first message actually uses the user-chosen model (fixes the bug where
switching the model on the overlay had no effect).
* update
* โจ feat(popup): add Quick Chat tray entry backed by Inbox agent
Tray menu now exposes a "Quick Chat" action that opens (or focuses)
a single-instance popup window at `/popup/agent/inbox`. Each fresh
open starts with no active topic; the first message creates one
through the normal agent flow.
- New `PopupAgentQuickPage` resolves the inbox slug via
`builtinAgentSelectors.inboxAgentId` so `activeAgentId` points at
the real entity in `agentMap` (fixes the stuck-loading / skeleton
state from using the literal `'inbox'` slug).
- `BrowserManager.openQuickChatPopup` wraps
`createMultiInstanceWindow` with a fixed `topicPopup_quick_inbox`
uniqueId so repeat clicks focus rather than spawn.
- Wire the action into macOS / Windows / Linux tray menus and add
the `tray.quickChat` i18n key.
* Add quick chat shortcut and desktop hotkey support
* โจ feat(screen-capture): enhance window enumeration with scale factor support
- Updated `enumerateWindows` to accept an optional `displayScaleFactor` parameter for improved window geometry normalization on high-DPI displays.
- Refactored `normalizeWindowBounds` to handle scaling based on the provided scale factor, ensuring accurate window dimensions across different platforms.
- Adjusted tests in `WindowSourceService.test.ts` to validate the new scaling behavior for both Windows and macOS environments.
- Minor adjustments in `ScreenCaptureManager` to accommodate the updated window enumeration logic.
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| โจ feat(desktop): unified update channel switching with S3 distribution (#12644)
* โจ feat(desktop): add update channel settings for desktop app
* ๐ง chore(desktop): update test scripts for multi-channel update flow
- Support stable/nightly/canary channel structure in generate-manifest.sh
- Add --all-channels flag for generating manifests across all channels
- Dual-mode run-test.sh: packaged (full updater) and --dev (UI only)
- Fix package:mac:local to skip signing for local builds
- Document Squirrel.Mac signature validation limitation
* ๐ง chore(desktop): update local app update configuration
- Change provider from GitHub to Generic for local testing.
- Update local server URL and cache directory settings.
- Revise comments for clarity on usage and configuration.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ fix(desktop): fix update channel switch race condition and downgrade flag
- P1: Use generation counter to discard stale check results when channel
is switched mid-flight. Pending recheck is scheduled after current check
completes instead of forcing concurrent checks.
- P2: Explicitly reset allowDowngrade=false on non-downgrade transitions
to prevent stale downgrade permission from persisting.
- Fix GitHub fallback repo name (lobe-chat -> lobehub).
* ๐ง chore(settings): remove dynamic import for Beta component from componentMap
- Eliminated the dynamic import for the Beta settings tab, streamlining the component map.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ง chore(settings): simplify UpdateChannel component structure
- Refactored the UpdateChannel component to streamline the Select component usage by removing unnecessary nested children.
Signed-off-by: Innei <tukon479@gmail.com>
* update
* ๐ fix(desktop): strip channel suffix from UPDATE_SERVER_URL before appending channel
The UPDATE_SERVER_URL secret may already contain a channel path (e.g., /stable).
Previously, the code unconditionally appended /{channel}, resulting in double
paths like /stable/stable/stable-mac.yml.
Now both electron-builder.mjs and UpdaterManager strip any trailing channel
suffix before re-appending the correct channel, supporting both legacy URLs
(with channel) and clean base URLs.
* update
* update
* redesign ui
- Added `getUpdaterState` method to `UpdaterManager` for retrieving current update status.
- Introduced `UpdaterState` type to encapsulate update progress, stage, and error messages.
- Updated UI components to reflect update states, including checking, downloading, and latest version notifications.
- Enhanced menu items for macOS and Windows to display appropriate update statuses.
- Localized new update messages in English and Chinese.
This improves user experience by providing real-time feedback during the update process.
Signed-off-by: Innei <tukon479@gmail.com>
* Enhance UpdaterManager tests and mock implementations
- Updated tests for UpdaterManager to reflect changes in broadcasting update states, including 'checking', 'downloading', and 'error' stages.
- Modified mock implementations in macOS and Windows test files to include `getUpdaterState` and `installNow` methods for better state management.
- Improved test coverage for update availability and download processes.
These changes ensure more accurate testing of the update flow and enhance the overall reliability of the UpdaterManager functionality.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 2 ไธชๆๅ |
| ๐ fix(desktop): split runtime externals from native deps (#14776) | 10 ๅคฉๅ |
| ๐ fix(local-system): forward all grepContent params + move executor to /client (#14888)
* ๐ fix(local-system): forward all grepContent params + move executor to /client
The local-system executor was reducing the agent's full grepContent params
({pattern, glob, output_mode, -i/-n/-A/-B/-C, multiline, head_limit, type,
scope, ...}) down to {directory, pattern} before handing them to the runtime.
`directory` isn't recognized by the IPC layer (which expects path/scope), so
cwd silently fell back to process.cwd() (= apps/desktop/ in dev), and with
glob/-i/output_mode all stripped grep matched anything containing the pattern
across the whole tree โ explaining LOBE-8666's dist/main/index.js +
tsconfig.tsbuildinfo leaks.
Also audited the rest of the executor layer:
- listFiles: forward `limit` (was silently dropped โ manifest default of 100
always won).
- getCommandOutput: forward `filter` (was silently dropped โ no regex filter
ever applied to streamed output).
- runCommand: mirror `run_in_background` โ `background` so
ComputerRuntime.RunCommandState.isBackground reflects reality (the IPC
handler reads run_in_background directly, so the command itself ran in
background โ only the state field was wrong).
Structure: moved src/executor/ โ src/client/executor/ to match the other
builtin-tool packages (task / lobe-agent / knowledge-base) and consolidate
renderer-only code under /client. Dropped the `./executor` package subpath;
consumers now import from `โฆ/client`.
Defensive: also added a resolveSearchPath helper in apps/desktop's
contentSearch module that reads params.scope as a fallback for params.path,
so any non-executor caller (direct IPC, future Gateway path) that passes
`scope` still gets routed correctly instead of falling through to
process.cwd().
Regression coverage:
- grepContent full forwarding (LOBE-8666 case + all optional flags)
- listFiles.limit forwarding
- getCommandOutput.filter forwarding
- runCommand.run_in_background โ background mirror
- resolveSearchPath fallback semantics (3 cases in base.test.ts)
Verified end-to-end via Electron CDP โ tool.invokeBuiltinTool with the
LOBE-8666 params returns 9 clean .ts matches (no dist/, no .tsbuildinfo);
listFiles {limit:3} returns 3 files (totalCount 10); runCommand
{run_in_background:true} reports state.isBackground=true.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ fix(desktop): readFile fails with `protocol.registerSchemesAsPrivileged should be called before app is ready`
Two-part fix for a regression where reading any text/JSON/source file via the
local-system `readFile` tool surfaced an Electron protocol error in the response
content. The error fired *after* `stat()` succeeded (so missing-file ENOENT was
unaffected), making it look like the file couldn't be parsed.
## Root cause
Stack trace (instrumented `read.ts` to capture it):
```
Error: protocol.registerSchemesAsPrivileged should be called before app is ready
at new App (apps/desktop/dist/main/index.js:105339:21)
at Module.<anonymous> (apps/desktop/dist/main/index.js:105615:11)
at Module._compile (...)
```
`Module._compile` on `dist/main/index.js` means the main bundle is being freshly
evaluated as a CJS module โ re-running its top-level `var app = new App(); โฆ;
app.bootstrap();` after the real Electron-launched App was already ready.
Triggering chain: agent calls `readFile` โ main runs `loadFile(path)` from
`@lobechat/file-loaders` โ `getFileLoader('txt')` โ `await import('./text')`.
The lazy text-loader chunk back-references the main bundle for the shared util
`detectUtf16NoBom`:
```js
// dist/main/text-Cbmlmtca.js
const require_index = require("./index.js"); // โ re-evaluates main
โฆ
const variant = require_index.detectUtf16NoBom(buffer);
```
Electron's main entry is not in Node's CJS module cache (it's bootstrapped
separately), so this `require("./index.js")` triggers a fresh compile of the
main bundle โ re-running `new App()` and `protocol.registerSchemesAsPrivileged`
*after* `app.whenReady()`, which is illegal per Electron's API contract.
Introduced by #14602 (`fix(local-system): guard readFile against binary blobs
and oversized output`): adding `isBinaryContent.ts` made `detectUtf16NoBom`
shared between the main bundle (via `sniffBinaryFile`) and the lazy text chunk,
so rolldown placed it in main and rewrote the text chunk's call as a
`require_index.detectUtf16NoBom`.
Identical class of bug previously fixed for the `debug` package in #11827.
## Fix
1. **`packages/file-loaders/src/loaders/index.ts`** โ TextLoader was lazy-imported
for no real benefit. It's a 10KB module whose only deps are `node:fs/promises`
and a tiny utf-16 detect util โ nothing like the multi-MB parsers (pdfjs-dist,
xlsx, mammoth) that the lazy pattern was designed for. Make it a static
import; `getFileLoader('txt')` returns it synchronously. Result: the text
chunk disappears entirely, removing this back-reference at the source.
2. **`apps/desktop/electron.vite.config.ts`** โ defensive `manualChunks` rules
so any future shared symbol doesn't recreate the same trap:
- `vendor-file-loaders-utils` for the three small text/binary detection
utils (`detectUtf16` / `isBinaryContent` / `isTextReadableFile`).
Explicitly enumerated to avoid catching `parser-utils.ts`, which pulls
in xmldom/yauzl/concat-stream (โ900KB) and belongs in the docx/pptx
chunks instead.
- `vendor-jszip` for JSZip โ same root cause for `.docx` reads: the docx
chunk had `require_index.require_lib()` (JSZip) back-referencing main.
Both ends now share the vendor chunk; no main re-eval.
Follows the project precedent set by #11827 for `debug`.
## Verification (live Electron via CDP)
Bundle inventory before/after:
| Chunk | Before | After |
| --- | --- | --- |
| `text-*.js` | 9.7KB (back-refs main) | (gone, inlined into main) |
| `vendor-file-loaders-utils-*.js` | n/a | 18KB |
| `vendor-jszip-*.js` | n/a | 899KB |
| `docx-*.js` back-refs | `require_index.require_lib` | none |
End-to-end via `tool.invokeBuiltinTool('lobe-local-system', 'readFile', โฆ)`:
| File | Before | After |
| --- | --- | --- |
| `.md` / `.json` / `.ts` | `Error accessing or processing file: protocol.registerSchemesAsPrivileged should be called before app is ready` | real file content |
`grep -o 'require_index\\.[a-zA-Z_]*' dist/main/*-*.js | sort -u` โ empty.
All 61 file-loaders tests pass; all 64 builtin-tool-local-system tests pass. | 6 ๅคฉๅ |
| ๐ fix(desktop): split runtime externals from native deps (#14776) | 10 ๅคฉๅ |
| ๐ fix(desktop): use stored locale from URL parameter instead of systeโฆ (#13620)
๐ fix(desktop): use stored locale from URL parameter instead of system language
When the desktop app restarts, the UI language was reverting to the system
language instead of respecting the user's saved language preference.
Root cause: The inline script in index.html was setting document.documentElement.lang
from navigator.language (system language) before i18n initialization could read
the stored locale from Electron store.
Fix: Check the URL's `lng` query parameter first (which is set by Electron main
process from stored settings in Browser.ts:buildUrlWithLocale()), then fall back
to navigator.language.
Fixes #13616
https://claude.ai/code/session_0128LZAbJL1a5vkGboH4U5FP
Co-authored-by: Claude <noreply@anthropic.com> | 1 ไธชๆๅ |
| ๐ fix(desktop): split runtime externals from native deps (#14776) | 10 ๅคฉๅ |
| ๐ fix(desktop): split runtime externals from native deps (#14776) | 10 ๅคฉๅ |
| โจ feat(desktop): screen capture overlay, Quick Chat tray, and upload pipeline improvements (#13818)
* feat: add screen capture functionality with overlay support
- Implemented ScreenCaptureManager to handle screen capture sessions.
- Added ScreenCaptureCtr for IPC methods related to screen capture.
- Created overlay.html and ScreenCaptureOverlay component for user interaction.
- Integrated window enumeration and capture logic using node-screenshots and get-windows.
- Updated menu options to include screen capture actions.
- Enhanced RendererUrlManager to support overlay routing.
- Introduced drag selection for capturing specific screen areas.
- Added necessary types and events for screen capture in electron-client-ipc.
Signed-off-by: Innei <tukon479@gmail.com>
* โจ feat(desktop): refine screen capture overlay flow
* โจ feat(desktop): refine screen capture overlay flow
* โก feat(desktop): optimize screen capture overlay flow
* Delete apps/desktop/mockup/screen-capture-overlay.html
* โจ feat(desktop): open mini toolbar via double Option
* ๐ fix(desktop): separate quick composer hotkey
* ๐ fix(desktop): remove stale quick composer accelerator
* ๐ fix(desktop): stabilize double option monitor
* ๐ fix(desktop): read hardware option key state
* ๐ fix(desktop): standardize path imports and improve error handling
- Replaced `join` imports with `path` imports for consistency across files.
- Enhanced error handling in various modules to include error causes for better debugging.
- Updated test files to reflect changes in variable naming and mock implementations.
Signed-off-by: Innei <tukon479@gmail.com>
* ๐ฅ chore(hotkey): drop orphan renderer quickComposer i18n entries
The `quickComposer` hotkey is registered only on the Electron side
(DESKTOP_GLOBAL_SHORTCUT_DEFAULTS + BrowserWindowsCtr.openQuickComposer);
the renderer never referenced these i18n keys, so the entries were dead.
`desktop.quickComposer` covers the app-level trigger.
* โก๏ธ perf(screen-capture): parallelize overlay upload with route navigation
Overlay submit used to await screenshot upload before router.push,
blocking the main window for several seconds when the user was on an
unrelated page (e.g. /settings). Now we navigate immediately and run
upload in a background IIFE; MessageFromUrl waits on a new
`uploadStatus` field before calling sendMessage, so the chat page
mount and the upload proceed in parallel.
- Add `uploadStatus: 'uploading' | 'ready' | 'failed'` to
PendingOverlayDispatch; canConsumePendingOverlayDispatch blocks
while `'uploading'`.
- Store gains `markDispatchUploadComplete`; on failure it clears
screenshotFileNames so the prompt still delivers.
- Dispatcher drops stale prev search params on push to prevent
MessageFromUrl's message-param effect from double-firing.
* โก๏ธ perf(screen-capture): pre-upload captures in overlay preview + per-thumbnail status
Move uploads from post-submit to preview time, bypassing dataUrl round-trips:
- Main process assigns captureId at preview time and ships the PNG bytes
as ArrayBuffer to the main renderer via `overlayUploadRequest`.
- Main renderer uploads through a dedicated pool (uploadWithProgress,
no chatUploadFileList pollution); reports status back to the overlay
through `overlayCaptureUploadStatus`.
- Overlay thumbnails render a spinner / error badge based on status;
the send button stays grey until every capture resolves to `ready`.
- Submit now carries only captureIds; MessageFromUrl awaits the pool
promises before sendMessage, removing the second upload pass.
- Carry overlay-selected modelId/provider into the agent config so the
first message actually uses the user-chosen model (fixes the bug where
switching the model on the overlay had no effect).
* update
* โจ feat(popup): add Quick Chat tray entry backed by Inbox agent
Tray menu now exposes a "Quick Chat" action that opens (or focuses)
a single-instance popup window at `/popup/agent/inbox`. Each fresh
open starts with no active topic; the first message creates one
through the normal agent flow.
- New `PopupAgentQuickPage` resolves the inbox slug via
`builtinAgentSelectors.inboxAgentId` so `activeAgentId` points at
the real entity in `agentMap` (fixes the stuck-loading / skeleton
state from using the literal `'inbox'` slug).
- `BrowserManager.openQuickChatPopup` wraps
`createMultiInstanceWindow` with a fixed `topicPopup_quick_inbox`
uniqueId so repeat clicks focus rather than spawn.
- Wire the action into macOS / Windows / Linux tray menus and add
the `tray.quickChat` i18n key.
* Add quick chat shortcut and desktop hotkey support
* โจ feat(screen-capture): enhance window enumeration with scale factor support
- Updated `enumerateWindows` to accept an optional `displayScaleFactor` parameter for improved window geometry normalization on high-DPI displays.
- Refactored `normalizeWindowBounds` to handle scaling based on the provided scale factor, ensuring accurate window dimensions across different platforms.
- Adjusted tests in `WindowSourceService.test.ts` to validate the new scaling behavior for both Windows and macOS environments.
- Minor adjustments in `ScreenCaptureManager` to accommodate the updated window enumeration logic.
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| โก๏ธ perf: warm route chunks after idle (#15109)
* โก๏ธ perf: warm route chunks after idle
* ๐ fix: normalize platform route chunk ids
* โก๏ธ perf: refine route chunk preloading
* ๐ง chore: keep desktop renderer preload unchanged
* โก๏ธ perf: skip renderer chunks in route warmup
* โก๏ธ perf: preload agent route dynamic chunks
* โก๏ธ perf: align route preload deployment urls
* โก๏ธ perf: coalesce stable vendor chunks
* โก๏ธ perf: group shared data runtime chunks
* โก๏ธ perf: group model runtime chunks
* โก๏ธ perf: trim initial route preloads
* โก๏ธ perf: limit idle route micro preloads
* โก๏ธ perf: strip tiny html modulepreloads
* โก๏ธ perf: prune redundant route chunk imports
* โก๏ธ perf: enable rolldown devtools
* โก๏ธ perf: gate vite devtools output
* โก๏ธ perf: optimize react-scan integration and update global types
Signed-off-by: Innei <tukon479@gmail.com>
* โก๏ธ perf: support cloud route chunk preload
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ๅคฉๅ |
| โป๏ธ refactor(hetero-agent): extract producer pipeline into shared package (#14425)
* ๐ style(todo-progress): use colorFillSecondary so left/right borders are visible against QueueTray
The colorBorderSecondary stroke nearly vanished against the dark elevated bg, so the TODO card looked open on the sides when stacked under QueueTray. Match QueueTray's outer border token (colorFillSecondary) for a consistent visible seam; inner dividers keep colorBorderSecondary as a softer secondary level.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* โป๏ธ refactor(hetero-agent): extract producer pipeline into shared package
LOBE-8516 phase 0. Move the JSONL framing + adapter conversion + toStreamEvent
chain out of the renderer into a new `@lobechat/heterogeneous-agents/spawn`
entry, then have desktop main run it before broadcasting. Renderer now
consumes ready-made `AgentStreamEvent`s on `heteroAgentEvent`, dropping ~50
lines of in-renderer adapter wiring.
This unifies the wire shape across desktop main, the upcoming `lh hetero exec`
CLI, and the server `heteroIngest` handler โ every consumer gets the same
stamped `AgentStreamEvent` with no per-consumer adapter step.
The desktop CC flow is unchanged behavior-wise: same adapter, same persistence
ordering, same step-boundary semantics; only the seam between main and
renderer moved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* โป๏ธ refactor(hetero-agent): pull codex tracker into shared spawn, drop desktop's gateway-client dep
Two cleanups on top of the phase 0 refactor:
1. Move `CodexFileChangeTracker` (+ its test) out of `apps/desktop/src/main/modules/heterogeneousAgent/` into `packages/heterogeneous-agents/src/spawn/`. `AgentStreamPipeline` now auto-instantiates it when `agentType === 'codex'`, so the desktop controller (and the future `lh hetero exec` CLI) stays agent-agnostic โ no more "if codex { wire tracker via transformPayload }" branching at the call site. The public `transformPayload` hook is removed since it had no other consumer.
2. Re-export `AgentStreamEvent` / `AgentStreamEventType` from `@lobechat/heterogeneous-agents/spawn` and drop `@lobechat/agent-gateway-client` from `apps/desktop/package.json`. The gateway-client package is a browser-side WebSocket client; producer-side callers (desktop main, sandbox CLI) shouldn't carry it as a direct dep โ they only need the type, which now flows through the producer-side entry.
Type predicate on Codex payloads tightened to a non-`Required<>` shape so the moved file passes the root tsconfig's `strict: true` (apps/desktop's tsconfig was lax).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐งโ๐ป chore(local-testing): harden electron-dev.sh process management
Lifecycle improvements for the local-testing helper so smoke runs against the desktop dev session are reliable:
- `find_project_pids` now also catches user-started `bun run dev` Electron sessions (matches by project electron path, not just `--remote-debugging-port`), the launcher subshell saved to PIDFILE, and any process bound to the CDP port. Vite match tightened to `electron-vite[/.].*\bdev\b` so unrelated Vite invocations aren't swept up.
- `do_stop` expands seed PIDs into their descendant trees (DFS via `pgrep -P`), SIGTERMs the whole tree, waits 5s, then SIGKILLs survivors. Belt-and-suspenders sweep for stragglers + anything still bound to the CDP port. Closes the long-standing "Helper processes survive the kill" gotcha.
- `do_start` detects existing project Electron/vite before tearing it down so the user sees what's being killed; waits for port + user-data-dir locks to release before relaunching to avoid the "user data directory in use" race.
- `wait_for_cdp` uses an explicit deadline + early bail-out if the launcher PID dies, instead of the previous fixed-step loop. `wait_for_renderer` no longer pre-sleeps 10s.
`setsid` use is intentional; it puts the launched Electron in its own session so the whole tree shares a PGID we can signal in one shot. Note: `setsid` is GNU coreutils โ on macOS without `brew install util-linux` the script will fail at the launch step. Documented as a known limitation; no fallback added.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ fix(hetero-agent): gate session-complete on stdout fully drained
Node may emit `proc.on('exit')` BEFORE child stdio fully closes (documented
in child_process: "stdio streams might still be open"). Phase 0 of LOBE-8516
moved adapter ownership to main, so renderer no longer flushes its own
adapter on session-complete โ meaning trailing events synthesized by
`pipeline.flush()` (e.g. Codex's `tool_end` for unfinished tool calls) would
race against, and lose to, the `heteroAgentSessionComplete` broadcast,
leaving renderer-side persistence to finalize on incomplete state.
Fix: in `proc.on('exit')`, await `streamFinished(stdout)` (covers `'end'`,
`'close'`, and `'error'`) BEFORE awaiting the broadcast queue. The first
await ensures the `stdout.on('end')` handler has had a chance to schedule
`pipeline.flush()` onto the queue; the second drains it. Only then do we
broadcast complete / error.
Regression test repros the documented Node race by emitting `exit` before
`stdout.end()` and asserts every `heteroAgentEvent` (including the
synthesized `tool_end` from `pipeline.flush()`) lands before
`heteroAgentSessionComplete`. Bisected: test fails without the gate, passes
with it.
Also: add `packages/heterogeneous-agents` to `apps/desktop/pnpm-workspace.yaml`
to mirror the new workspace dep added in the phase 0 refactor.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ๐ fix(hetero-agent): drop builtin-tool-claude-code dep, inline the 3 CC wire shapes the adapter needs
Phase 0 added `@lobechat/heterogeneous-agents` as a runtime dep of the desktop
main process. That transitively pulled in `@lobechat/builtin-tool-claude-code`
(declared in the shared package's deps), which the desktop pnpm workspace
doesn't list โ CI install on the desktop project fails:
ERR_PNPM_WORKSPACE_PKG_NOT_FOUND In ../../packages/heterogeneous-agents:
"@lobechat/builtin-tool-claude-code@workspace:*" is in the dependencies but
no package named "@lobechat/builtin-tool-claude-code" is present in the
workspace
The dep is also a layer-violation: `heterogeneous-agents` is the producer
side (CLI stream โ AgentStreamEvent), `builtin-tool-claude-code` is the UI
tool definition (renderers / inspectors / agent template). Producer
shouldn't depend on UI-tool packages, even if today the import is just
types/constants โ the dep cascade still drags `shared-tool-ui` etc. into
every workspace that wants the adapter.
Fix: inline the three things the adapter actually uses (`'TodoWrite'` tool
name string, `TodoWriteArgs` interface, `ClaudeCodeTodoItem` interface).
They reflect upstream Claude Code's wire schema โ if `claude` ever renames
`TodoWrite`, the adapter and the downstream renderers must both update
regardless of whether they share a constant. Renderer-side packages
(`builtin-tools/codex/TodoListRender`, etc.) keep importing the canonical
`ClaudeCodeApiName` from `@lobechat/builtin-tool-claude-code`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> | 19 ๅคฉๅ |
| โจ feat(desktop): add dedicated topic popup window with cross-window sync (#13957)
* โจ feat(desktop): add dedicated topic popup window with cross-window sync
Introduce a standalone Vite entry for the desktop "open topic in new window"
action. The popup is a lightweight SPA (no sidebar, no portal) hosting only
the Conversation, and stays in sync with the main window through a
BroadcastChannel bus.
- Add popup.html + entry.popup.tsx + popupRouter.config.tsx
- Add /popup/agent/:aid/:tid and /popup/group/:gid/:tid routes
- Reuse main Conversation/ChatInput; wrap in MarketAuth + Hotkeys providers
- Pin-on-top button in the popup titlebar (new windows IPC: set/isAlwaysOnTop)
- Group topic "open in new window" now uses groupId (previously misused agentId)
- Cross-window sync: refreshMessages/refreshTopic emit via BroadcastChannel;
subscriber revalidates local SWR caches with echo-loop suppression
- Hide WorkingPanel toggle inside /popup (no WorkingSidebar present)
- RendererUrlManager dispatches /popup/* to popup.html in prod; dev middleware
rewrites SPA deep links while skipping asset/module requests
* ๐ style(desktop): restore loading splash in popup window
* โป๏ธ refactor(desktop): replace cross-window sync with popup-ownership guard
The BroadcastChannel-based bidirectional sync between the main SPA and the
topic popup window had edge cases during streaming. Drop it in favour of a
simpler ownership model: when a topic is already open in a popup, the main
window shows a "focus popup" redirect instead of rendering a second
conversation.
- Remove src/libs/crossWindowBus.ts and src/features/CrossWindowSync
- Remove postMessagesMutation/postTopicsMutation calls from refresh actions
- Add windows.listTopicPopups + windows.focusTopicPopup IPC
- Main process broadcasts topicPopupsChanged on popup open/close; parses
(scope, id, topicId) from the popup window's /popup/... path
- Renderer useTopicPopupsRegistry subscribes to broadcasts and fetches the
initial snapshot; useTopicInPopup selects by scope
- New TopicInPopupGuard component with "Focus popup window" button
- Desktop-only index.desktop.tsx variants for (main)/agent and (main)/group
render the guard when the current topic is owned by a popup
- i18n: topic.inPopup.title / description / focus in default + en/zh
* ๐ fix(desktop): re-evaluate popup guard when topic changes
Subscribe to the popups array and derive findPopup via useMemo so scope changes (e.g. switching topic in the sidebar while a popup is open) correctly re-compute the guard and let the main window render the newly active topic.
* ๐ fix(desktop): focus detached topic popup from main window
* โจ feat(desktop): add open in popup window action to menu for active topic
Signed-off-by: Innei <tukon479@gmail.com>
* ๐จ style: sort imports to satisfy simple-import-sort rule
* โจ feat(error): add resetPath prop to ErrorCapture and ErrorBoundary for customizable navigation
Signed-off-by: Innei <tukon479@gmail.com>
* โป๏ธ refactor: restore ChatHydration in ConversationArea for web/mobile routes
Reintroduce ChatHydration component to agent and group ConversationArea
so that URL query sync (topic/thread) works on web and mobile routes,
not only on desktop entry files.
* โจ feat(electron): enforce absolute base URL in renderer config to fix asset resolution in popup windows
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com> | 1 ไธชๆๅ |
| ๐ง chore: update eslint v2 configuration and suppressions (#12133)
* v2 init
* chore: update eslint suppressions and package dependencies
- Removed several eslint suppressions related to array sorting and reversing from eslint-suppressions.json to clean up the configuration.
- Updated @lobehub/lint package version from 2.0.0-beta.6 to 2.0.0-beta.7 in package.json for improvements and bug fixes.
- Made minor formatting adjustments in vitest.config.mts and various SKILL.md files for better readability and consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: clean up import statements and formatting
- Removed unnecessary whitespace in replaceComponentImports.ts for improved readability.
- Standardized import statements in contextEngineering.ts and createAgentExecutors.ts by adding missing spaces for consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: update eslint suppressions and clean up code formatting
* ๐ fix: use vi.hoisted for mock variable initialization
Fix TDZ error in persona service test by using vi.hoisted() to ensure
mock variables are available when vi.mock factory runs.
---------
Signed-off-by: Innei <tukon479@gmail.com>
| 3 ไธชๆๅ |
| ๐ง chore: update eslint v2 configuration and suppressions (#12133)
* v2 init
* chore: update eslint suppressions and package dependencies
- Removed several eslint suppressions related to array sorting and reversing from eslint-suppressions.json to clean up the configuration.
- Updated @lobehub/lint package version from 2.0.0-beta.6 to 2.0.0-beta.7 in package.json for improvements and bug fixes.
- Made minor formatting adjustments in vitest.config.mts and various SKILL.md files for better readability and consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: clean up import statements and formatting
- Removed unnecessary whitespace in replaceComponentImports.ts for improved readability.
- Standardized import statements in contextEngineering.ts and createAgentExecutors.ts by adding missing spaces for consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: update eslint suppressions and clean up code formatting
* ๐ fix: use vi.hoisted for mock variable initialization
Fix TDZ error in persona service test by using vi.hoisted() to ensure
mock variables are available when vi.mock factory runs.
---------
Signed-off-by: Innei <tukon479@gmail.com>
| 3 ไธชๆๅ |
| โจ feat(electron): enhance native module handling and improve desktop features (#11867)
* ๐ง refactor: streamline theme handling and title bar overlay
* โจ feat(titlebar): integrate theme update handling in SimpleTitleBar component
* ๐ง chore: move `node-mac-permissions` to optionalDependencies and add TypeScript module declaration
* โจ feat(electron): implement connection drawer state management and enhance auth modal functionality
* ๐ fix(ci): fix Windows PowerShell Start-Job working directory issue
Start-Job runs in a separate process with default user directory,
causing npm install-isolated to fail. Fixed by setting correct
working directory in each job using $using:workingDir.
* ๐ fix(ci): use Start-Process instead of Start-Job for Windows parallel install
Start-Job runs in isolated PowerShell process without inheriting PATH,
causing pnpm/npm commands to fail. Start-Process inherits environment
and provides proper exit code handling.
* ๐ fix(ci): use desktop-build-setup action for Windows build
Use the same composite action as other desktop workflows instead of
custom PowerShell parallel install which has environment issues.
* โจ feat(menu): enhance context menu with additional options for image and link handling
* ๐ง fix(auth-modal): prevent modal from opening during desktop onboarding
* โจ feat(electron): enhance native module handling and improve localization resource loading
resolves LOBE-4370
- Added `copyNativeModulesToSource` function to resolve pnpm symlinks for native modules before packaging.
- Introduced `getNativeModulesFilesConfig` to explicitly include native modules in the build process.
- Updated `electron-builder` configuration to utilize the new functions for better native module management.
- Enhanced localization resource loading by splitting JSON files by namespace.
* ๐ fix(lint): use slice instead of substring
* ๐ fix(desktop): include global.d.ts in tsconfig for node-mac-permissions types
* ๐ fix(desktop): add ts-ignore for optional node-mac-permissions module
* fix: update ui | 3 ไธชๆๅ |
| โป๏ธ refactor(cli): extract shared `@lobechat/local-file-shell` package (#12865)
* โป๏ธ refactor(cli): extract shared @lobechat/local-file-shell package
Extract common file and shell operations from Desktop and CLI into a
shared package to eliminate ~1500 lines of duplicated code. CLI now
uses @lobechat/file-loaders for rich format support (PDF, DOCX, etc.).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* update
* update commands
* update version
* update deps
* refactor version issue
* โจ feat(local-file-shell): add cwd support, move/rename ops, improve logging
- Add missing `cwd` parameter to `runCommand` (align with Desktop)
- Add `moveLocalFiles` with batch support and detailed error handling
- Add `renameLocalFile` with path validation and traversal prevention
- Add error logging in shell runner's error/completion handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* support update model and provider in cli
* fix desktop build
* fix
* ๐ fix: pin fast-xml-parser to 5.4.2 in bun overrides
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> | 2 ไธชๆๅ |