* fix command issue
* add run command UI
* fix API key
* add apikey page
* add apikey
* 🐛 fix: update apiKey model tests to use new sk-lh- prefix format
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add `--file` option to `lh topic delete` command, allowing users to
pass topic IDs via a file (one per line or JSON array) for bulk deletion.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add the activatedSkills to improve the execScripte tools
* feat: change the activePath into call market endpoint
* fix: clean the code
* feat: fixed the execScript in desktop ts error
✨ feat: preload bundled i18n resources synchronously and reload actual language in background
For non-default languages, preload bundled en-US resources synchronously to avoid
Suspense on first render, then reload the user's actual language from backend
in the background. This ensures instant rendering with fallback text while the
correct translations load asynchronously.
* 🐛 fix: ensure always-on builtin tools and user-selected plugins are enabled in tool engine
- Add alwaysOnToolIds (lobe-tools, lobe-skills) that are always enabled regardless of user selection
- Include user-selected plugins in enableChecker rules for both frontend and server-side tool engines
- Change enableCheckerFactory default from enabled to disabled (tools must be explicitly enabled via rules)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 🐛 fix: improve input loading state to cover sendMessage through AI generation
- Add isInputLoading state that includes sendMessage operation type, so input stays
in loading state from the moment user sends until AI finishes generating
- Add INPUT_LOADING_OPERATION_TYPES constant (superset of AI_RUNTIME_OPERATION_TYPES + sendMessage)
- Update ChatInput to use isInputLoading instead of isAIGenerating for disable/loading state
- Update stopGenerating to cancel all input-loading operations and restore editor on cancel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✅ test: fix stopGenerating tests to match updated action implementation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix agent
* 🐛 fix: add missing selector mocks in toolEngineering tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* style: update moonshot models
* 🔨 chore: extend `video_url` support for OpenAI SDK
* fix: fix ci error
* hotfix: fix sensenova baseUrl error
* fix: fix kimi-k2.5 video tag from LobeHub
* fix: wenxin flag
* chore: cleanup utils
* style: add video tag for `glm-4.1/4.5v`
remove video tag for sensenova due to not support in OpenAI mode
* add response api framework
* finish response api structure
* finish response api structure
* ✨ feat: implement basic text generation for Response API (LOBE-5858)
- Add instructions extraction from system/developer input messages
- Add instructions param to ExecAgentParams, append to agent systemRole
- Implement extractPrompt, extractAssistantContent, extractUsage in ResponsesService
- Wire up execAgent + executeSync flow for non-streaming and streaming
- Add logprobs field to output_text content parts for schema compliance
- Fix truncation field to output string enum instead of object
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat: implement real token-level streaming for Response API (LOBE-5859)
- Replace fake streaming (executeSync → emit events) with real streaming
- Subscribe to InMemoryStreamEventManager for live stream_chunk events
- Run executeSync in background, convert text chunks to output_text.delta SSE events
- Add missing schema fields: item_id on content_part/text events, logprobs on delta/done events
- Fix content_part.added/done to include item_id per OpenResponses spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat: implement tool calling output extraction for Response API (LOBE-5860)
- Add extractOutputItems to convert AgentState messages to OpenResponses output items
- Extract assistant tool_calls → function_call output items
- Extract tool result messages → function_call_output output items
- Skip message items for assistant messages that have tool_calls (avoid duplicates)
- Add status field to function_call_output items per OpenResponses spec
- Update FunctionCallOutputItemSchema with optional status field
- Output array reflects execution order: function_call → function_call_output → message
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat: implement multi-turn conversations via previous_response_id (LOBE-5861)
Encode topicId in response.id to enable stateless multi-turn conversation
chaining. When previous_response_id is provided, extract topicId and pass
to execAgent via appContext, which automatically loads history messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 🐛 fix: add missing type fields for OpenResponses compliance (logprobs, item_id, input_tokens_details)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat(cli): CLI Phase 5 - agent KB/file/pin, thread management, eval expansion
- Add agent subcommands: pin/unpin, kb-files, add-file/remove-file/toggle-file, add-kb/remove-kb/toggle-kb
- Create thread command with list/list-all/delete subcommands
- Expand eval with internal benchmark/dataset/testcase/irun management
- Move existing external eval commands under `eval ext` namespace
- Add comprehensive unit tests for all new functionality
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 💄 style(cli): rename eval `irun` to `run` since external moved to `ext` namespace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ♻️ refactor(cli): merge external eval commands into unified tree with --external flag
Remove separate `eval ext` namespace; use `--external` flag on overlapping commands
(dataset get, run get) and integrate external-only commands directly into the tree.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat(cli): CLI Phase 6 - miscellaneous command enhancements
- file: add upload (hash check + create), edit (move to folder), kb-items
- user: new command with info, settings, preferences, update-avatar, update-name
- model: add batch-update, sort order
- plugin: add create (without settings, distinct from install)
- generation: add delete
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat(settings): improve tool detector display layout
- Move version to left side with Name, display as Tag
- Right side: two lines (Available status + path), right-aligned
- Unavailable: single line centered
- Add runtime environment detectors (Node, Python, npm)
- Add i18n for system tools settings
Made-with: Cursor
* 🔧 fix(toolDetectors): ensure successful version check for Python runtime
- Update pythonDetector to enforce successful invocation of `--version` for confirming usable runtime.
- Removed redundant version handling logic to streamline the detection process.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* fix: add the history count limit back in agents params settings
* fix: fixed the test
* fix: change the default settings snap the enableHistoryCount as false
* fix: change the history process to the first into MessageEngine
* fix: fixed some count limited
* fix: fixed the enableHistoryCount check test
* fix: change the getEnableHistoryCountById logic
* fix cli alias
* 🐛 fix(cli): fix gen text non-streaming mode and streaming SSE parsing
- Add `responseMode: 'json'` for non-streaming requests to get plain JSON instead of SSE
- Fix streaming SSE parser to handle LobeHub's JSON string format (e.g. `"Hello"`)
- Support both OpenAI and Anthropic response formats in non-streaming mode
- Add E2E tests for all generate commands (text, list, tts, asr, alias)
- Update skills knowledge.md docs with new kb commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat(cli): unify skill install command and add e2e tests
Merge import-github/import-url/import-market into a single `skill install <source>` command with auto-detection (GitHub URL/shorthand, ZIP URL, or marketplace identifier). Add alias `skill i`. Add comprehensive e2e and unit tests for skill commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 🔨 chore: fix linter formatting in memory e2e test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 🐛 fix: add vitest-environment node declaration to aiProvider test
Fix server-side env variable access error by declaring node environment.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix cli review
* fix test
* ✨ feat(cli): add web search and crawl support to search command
Add --web flag for web search via tools TRPC client, and search view
subcommand for viewing results (URLs via crawl, local resources by type:id).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat(cli): add device management command with TRPC endpoints
Add `lh device` command for managing connected devices via server-side
TRPC API, complementing the existing `lh connect` (device-as-client).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat(cli): add bot integration management command
Add `lh bot` top-level command for managing agent bot integrations
(Discord, Slack, Telegram, Lark/Feishu). Includes list, view, add,
update, remove, enable/disable, and connect subcommands.
Also adds `list` procedure to agentBotProvider TRPC router for
querying all bots with optional agent/platform filters.
Closes LOBE-5900
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 🐛 fix(i18n): preload default language from JSON to avoid Suspense on first render
- Sync load en-US common/error/chat from locales/en-US/*.json
- Use JSON (not locales/default/*.ts) as runtime values - TS source is type-only
- Prevents useTranslation from suspending, avoids CLS from 44px skeleton fallback
Made-with: Cursor
* ✨ feat(i18n): enable partial loading of languages and add tests for dynamic namespace loading
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* fix cli alias
* 🐛 fix(cli): fix gen text non-streaming mode and streaming SSE parsing
- Add `responseMode: 'json'` for non-streaming requests to get plain JSON instead of SSE
- Fix streaming SSE parser to handle LobeHub's JSON string format (e.g. `"Hello"`)
- Support both OpenAI and Anthropic response formats in non-streaming mode
- Add E2E tests for all generate commands (text, list, tts, asr, alias)
- Update skills knowledge.md docs with new kb commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat(cli): unify skill install command and add e2e tests
Merge import-github/import-url/import-market into a single `skill install <source>` command with auto-detection (GitHub URL/shorthand, ZIP URL, or marketplace identifier). Add alias `skill i`. Add comprehensive e2e and unit tests for skill commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 🔨 chore: fix linter formatting in memory e2e test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 🐛 fix: add vitest-environment node declaration to aiProvider test
Fix server-side env variable access error by declaring node environment.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix cli review
* fix test
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: desktop onboarding
* ♻️ refactor(desktop): reinstate onboarding guard before auto OIDC
- Add getDesktopOnboardingCompleted/setDesktopOnboardingCompleted back to localStorage
- These functions persist across sign-out, preventing unexpected OIDC popups
- Fix for Codex review feedback on PR #12890
* ♻️ refactor(desktop): use sessionStorage for onboarding completed flag
* ✅ test(desktop): fix BrowserManager test for async initializeBrowsers
* ♻️ 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>
* feat: add the skills in community pages
* feat: add some skills & import the import routes
* feat: add detail used pages & prompt
* feat: add the skill sort way
* fix: ts fixed
* fix: ts fixed
* fix: test fixed
* fix: test fixed
- Use same app name (LobeHub) and icon as stable for canary builds
- Add build channel tag in Settings > About for non-stable channels (Canary, Nightly, Beta)
- Add getBuildChannel IPC to expose build-time channel for display
Made-with: Cursor
* ✨ 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>
* ✨ feat(openai): add GPT-5.3 Chat model with enhanced features and pricing details
* ✨ feat: add Codex Max Reasoning Effort parameter and slider component for enhanced model configuration
* ✨ feat: update Qwen model configurations and add new Qwen3.5 models with detailed descriptions and pricing
* ✨ feat: add GPT-5.4 and GPT-5.4 pro models with pricing and capabilities to the model bank
* ✨ feat: add GPT-5.4, GPT-5.4 pro, and GPT-5.3 Chat models with detailed capabilities and pricing to the model bank
* ✨ feat: 更新 zhipu 聊天模型的定价参数,移除不必要的 textOutput 参数
* ✨ feat: 移除 Gemini 3 Pro 模型的详细信息,标记为已弃用
* 🐛 fix: redirect to desktop onboarding when not completed
Desktop app was missing the redirect to `/desktop-onboarding` when
onboarding hadn't been completed. The `useDesktopUserStateRedirect`
callback silently returned instead of navigating, causing:
- Users never see the onboarding flow on fresh install
- `AuthRequiredModal` suppressed because onboarding guard fails
* 🐛 fix: remove desktop onboarding routes from proxy configuration
The `/desktop-onboarding` and its regex route have been removed from the proxy configuration. This change simplifies the routing logic as the onboarding flow is now handled directly in the user state redirect logic.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat(openapi): add API key hash support for secure storage
* ✨ feat(openapi): enhance message translation and knowledge base functionality
- Added MessageTranslationController and associated routes for managing message translations, including fetching, creating, updating, and deleting translations.
- Introduced KnowledgeBaseController with routes for CRUD operations on knowledge bases, including file management and access control.
- Updated existing message and translation routes to improve structure and naming consistency.
- Refactored related services and types to support new features and ensure type safety.
This update enhances the API's capabilities for handling message translations and knowledge base management, improving overall functionality and user experience.
* fix: allow OWNER scope to list agents in agents route
- Add OWNER scope to AGENT_READ permission check
- Aligns list behavior with AgentService.queryAgents ownership filter
- Allows owner-scoped users to list their own agents
* 🔧 refactor(rbac): improve import structure in rbac.ts
- Changed import statements to separate type imports from regular imports for better clarity and organization.
- This refactor enhances code readability and maintains consistency in the import structure.
* fix: 修复 chunk 服务与 async router 的循环依赖
- 将 createAsyncCaller 的静态导入改为动态导入 (await import)
- 打破 file.ts -> chunk/index.ts -> async/index.ts 的循环依赖链
- 使用 --skip-dynamic-imports 参数的 dpdm 验证循环依赖已解决
* 🐛 fix: resolve CI failures
* test: 补充 apiKey、KeyVaultsEncrypt、ChunkService 单测至 100% 覆盖率
- test(database): 补充 apiKey.ts query() 解密失败分支测试
- test(server): 补充 KeyVaultsEncrypt 非法密钥/密文格式 getUserKeyVaults 测试
- test(server): 新增 ChunkService 完整测试覆盖异步任务创建/触发/失败回写
所有新增测试通过 (46/46),目标文件覆盖率均达 100%
🌐 chore: translate non-English comments to English in src/app/(backend) and src/app/[variants]/(auth)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* ✨ feat(cli): add agent run and status commands
Implement `lh agent run` for executing agents with SSE streaming
and `lh agent status` for checking operation status. Includes
`--replay` option for offline replay from saved JSON fixtures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 🐛 fix(cli): preserve SSE frame state across read boundaries and enable verbose logging
- Move eventType/eventData outside the read loop so partial SSE frames
split across chunks are not silently dropped
- Call setVerbose(true) when --verbose is passed so logger helpers
actually print detailed tool arguments and results
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat: add new NVIDIA models with thinking budget support
- Add 7 new models: MiniMax-M2.1, DeepSeek V3.2, GLM-4.7, GLM-5, Kimi K2.5, MiniMax-M2.5, Qwen3.5-397B-A17B
- Add thinkingBudget support for qwen3.5-397b-a17b model
- Update test case description
* 🐛 fix: remove thinking budget and add video support for Qwen3.5-397B-A17B
* 🐛 fix: support authoritize in no browser environment
* wip: remove tests
* 📝 docs: remove redundant alerts
* 🐛 fix: could not invoke brower in windows
* wip: add link and unlink cli to global
This release includes **31 commits**. Key updates are below.
### New Features and Enhancements
- Added **Telegram bot access** support.
- Added **electron page tabs** functionality for desktop.
- Added **device code auth flow** for authentication.
- Added **GPT-5.4** model support.
- Show **last used auth provider** on sign-in page for better UX.
- Support **clearing hotkey bindings** in desktop ShortcutManager.
- Added **Gemini 3.1 Flash Lite Preview** model and thinkingLevel5
extend param.
- Added **auto aspect ratio and image search** support for Nano Banana
2.
- User memories now default to inject user persona instead of
identities.
### Desktop Improvements
- Unified **update channel switching** with S3 distribution.
- Added **S3 publish for canary/nightly** and S3 cleanup (keep latest
15).
- Added electron page tabs functionality.
### Stability and Fixes
- Fixed agents fork not working in community deploy.
- Fixed animation for single-line messages between reasoning and tool
calls.
- Fixed Discord bot conflict with keyPrefix.
- Fixed skew plugin issue.
- Fixed `userMemories` database failure on extra structure mismatch.
- Fixed old LobeHub plugins update issue.
- Fixed context-engine tool type recovery from manifest when models
strip suffixes.
- Added `await` to `handleResponseAPIMode` for proper error handling.
- Fixed M2M token for community agents/MCP/skill list.
- Fixed scripts to support Win32.
- Improved gateway and device gateway CI.
### Credits
Huge thanks to these contributors (alphabetical):
@arvinxx @huangkairan @Innei @LiJian @Luis-Sambrano @nekomeowww
@rdmclin2 @ReneWang @sxjeru @tjx666
🐛 fix(ci): target channel yml files instead of latest*.yml for version prefix
The merge-mac-files step already renames latest*.yml to {channel}*.yml
(e.g., canary-mac.yml). The previous fix targeted release/latest*.yml
which matched nothing, so the sed was a no-op.
Now targets release/${CHANNEL}*.yml directly, with latest*.yml as fallback.
The latest*.yml files uploaded to S3 channel root lacked the $VERSION/
prefix in their URLs, causing electron-updater to request files at
the wrong path (e.g., /canary/LobeHub-Canary-xxx.zip instead of
/canary/2.1.38-canary.1/LobeHub-Canary-xxx.zip), resulting in 404.
Now sed -i modifies latest*.yml in-place before uploading, and
channel-specific yml files are copied from the already-modified ones.
After auto-tag-release.yml was introduced, semantic-release in release.yml
stopped working because the tag already exists when it runs. This caused
CHANGELOG.md to never be updated.
Fix: move changelog generation into auto-tag-release.yml with a custom
script that parses git log and generates gitmoji-formatted entries,
matching the existing CHANGELOG.md format. Remove the broken
semantic-release step from release.yml.
After auto-tag-release.yml was introduced, semantic-release in release.yml
stopped working because the tag already exists when it runs. This caused
CHANGELOG.md to never be updated.
Fix: move changelog generation into auto-tag-release.yml with a custom
script that parses git log and generates gitmoji-formatted entries,
matching the existing CHANGELOG.md format. Remove the broken
semantic-release step from release.yml.
🐛 fix(ci): correct stable renderer tar source path
Use the current Electron renderer output directory when creating the stable renderer archive so Linux desktop release builds stop failing after packaging succeeds.
Made-with: Cursor
* fix: slove the agnets fork not work in communtiy deploy
* fix: slove the secure token set & registerM2MToken not batch
* Revert "fix: slove the secure token set & registerM2MToken not batch"
This reverts commit 4485e57165.
* ✨ feat: add GPT-5.4 model support and fix reasoning payload pruning
- Add GPT-5.4 model card to model-bank
- Update planCardModels to use gpt-5.4
- Add gpt-5.4 to responsesAPIModels
- Fix pruneReasoningPayload to strip logprobs/top_logprobs for reasoning models
- Add logprobs, top_logprobs to ChatStreamPayload type
- Extend reasoning_effort to include none and xhigh
- Add success log for non-fallback requests in RouterRuntime
- Fix log parameter mismatch in RouterRuntime
Fixes LOBE-5735
* 🐛 fix: match gpt-5.4 to gpt5_2ReasoningEffort in openrouter and vercelaigateway
* 🐛 fix: update OpenRouterReasoning effort type to include none and xhigh
* 🐛 fix: use tiered pricing for gpt-5.4 based on 272K token threshold
* 🌐 chore: update i18n translations
* 🐛 fix: update claude-sonnet model version to 4-6 in planCardModels
* ✨ feat: add GPT-5.4 Pro model support
* 🐛 fix: remove dated snapshot for gpt-5.4-pro in responsesAPIModels
* 🐛 fix: add tierBy support for cross-unit tiered pricing threshold
OpenAI charges output at 1.5x when INPUT exceeds 272K tokens.
The tiered strategy previously only checked the unit's own quantity
to select a tier. Added optional tierBy field to TieredPricingUnit
so output/cacheRead tiers can reference input quantity for selection.
* 🐛 fix: use totalInputTokens for tiered pricing tier selection
Tiered pricing tiers should be determined by total prompt size
(totalInputTokens), not each unit's own quantity. This fixes output
and cacheRead being charged at the wrong tier rate when the prompt
exceeds the threshold but the individual unit quantity does not.
* 🔧 chore: update @lobehub/ui dependency to a specific version URL and enhance ShortcutManager functionality
- Updated @lobehub/ui dependency in package.json to a specific version URL.
- Improved ShortcutManager to handle empty accelerator bindings, allowing users to clear shortcuts.
- Updated tests to reflect changes in shortcut handling and added localization for clear binding messages in both Chinese and English.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update @lobehub/ui dependency to version 5.4.0 in package.json
- Changed the @lobehub/ui dependency from a specific version URL to version 5.4.0 for improved stability and consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update @lobehub/ui dependency to use caret versioning in package.json
- Changed the @lobehub/ui dependency from a fixed version to caret versioning (^5.4.0) to allow for minor updates and improvements.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* 👷 ci(desktop): add S3 cleanup for canary/nightly (keep latest 15)
- Create `.github/actions/desktop-cleanup-s3/` reusable composite action
- Add S3 version cleanup step to canary and nightly cleanup jobs
- Cleanup runs after both publish-release and publish-s3 complete
* 👷 ci(desktop): fix S3 yml upload and add debug output
- Restore latest*.yml → {channel}*.yml logic (electron-builder always generates latest-*.yml)
- Upload both {channel}*.yml and latest*.yml to S3
- Change upload glob from latest* to *.yml for robustness
- Add yml file listing debug output in both upload and publish steps
👷 ci(desktop): extract S3 publish logic into reusable composite action
- Create `.github/actions/desktop-publish-s3/` composite action for S3 upload
- Add `publish-s3` job to canary and nightly workflows (previously missing)
- Refactor stable workflow to use the shared action
- Fix canary/nightly builds not uploading to S3 despite UPDATE_SERVER_URL being set
* ✨ feat: add electron page tabs functionality
Implement browser-style page tabs in the Electron titlebar:
- Add TabBar component with explicit tab creation via context menu (desktop only)
- Tab creation triggers: TopicItem/PageItem context menu "Open in New Tab" or double-click
- TabBar only visible when tab count >= 2
- Update active tab's reference when navigating within it (tab follows user navigation)
- Reuse existing plugin system (pluginRegistry, 11 page plugins, PageReference types)
- Persist tabs to localStorage with automatic recovery on restart
- Apply logic to TopicItem (agent & group) and PageItem
Changes:
- src/store/electron/actions/tabPages.ts: New store slice with tab state + actions
- src/features/Electron/titlebar/TabBar/: New UI component + storage + hooks
- src/features/Electron/navigation/: New useTabNavigation hook + extracted cachedData helper
- src/app/.../Topic/List/Item/: Double-click creates tab, context menu "Open in New Tab"
- src/app/.../page/.../Item/: Double-click creates tab, context menu "Open in New Tab"
- i18n: New keys in topic.ts and file.ts namespaces
* ✨ feat: enhance agent topic plugin and tab resolution logic
- Added a new line to ensure the cached title is included when resolving tabs in the useResolvedTabs hook.
- Minor adjustment in the agentTopicPlugin to improve code clarity.
These changes improve the handling of cached titles in the tab resolution process and enhance the overall functionality of the agent topic plugin.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat: enhance agent and conversation handling in PageEditor
- Refactored PageAgentProvider to eliminate direct pageAgentId prop, improving context management.
- Updated Conversation and Copilot components to utilize conversation state for agent selection, ensuring better handling of chat-group session IDs.
- Adjusted FileCopilot to synchronize active agent ID with conversation context, enhancing file interaction capabilities.
These changes streamline agent management and improve the overall user experience in the PageEditor feature.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update ESLint suppressions for chat service [skip ci]
- Removed the suppression for `object-shorthand` in `src/services/chat/index.ts` to improve code quality.
- Adjusted the ESLint suppressions in `eslint-suppressions.json` for better linting consistency.
These changes enhance the linting process by ensuring adherence to coding standards in the chat service files.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: optimize NavigationBar panel width handling
* ✨ feat: add tab context menu with close actions
Add right-click context menu on tab items:
- Close current tab
- Close other tabs
- Close tabs to the left (disabled on first tab)
- Close tabs to the right (disabled on last tab)
* 🐛 fix: defer single-click navigation on desktop to prevent double-click addTab race
* ✨ feat: implement onActivate method for RecentlyViewed plugins to manage store state transitions
- Added onActivate method to RecentlyViewedPlugin interface for handling tab activations.
- Updated agentPlugin and agentTopicPlugin to switch topics based on tab activation.
- Enhanced PluginRegistry to notify plugins on tab activation.
- Modified TabBar to trigger onActivate when a tab is activated.
- Improved AgentIdSync to preserve topic state during agent switches.
Signed-off-by: Innei <tukon479@gmail.com>
* refactor: update test for BackendProxyProtocolManager to throw on upstream fetch failure
- Changed test description to reflect behavior change from returning a 502 status to throwing an error.
- Updated test implementation to use expect().rejects.toThrow for handling fetch errors.
Signed-off-by: Innei <tukon479@gmail.com>
* refactor: use optional chaining for agent configuration properties
- Updated agent configuration properties to use optional chaining for safer access.
- This change prevents potential runtime errors when properties are undefined.
Signed-off-by: Innei <tukon479@gmail.com>
* refactor: optimize navigation handling in TabBar with startTransition
- Introduced startTransition for navigation updates to improve performance and user experience.
- Updated handleActivate, handleCloseOthers, handleCloseLeft, and handleCloseRight methods to use startTransition for routing.
- Enhanced code readability by grouping navigation logic within startTransition.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ 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>
* support keyPrefix
* feat: add telegram platform implementation
* feat: add telegram front end ui
* feat: support webhookProxyUrl
* chore: add more log info
* fix: header align
* chore: add onNewMessage to platform specific
* fix: test connnectitvity and add application id
* feat: support local tunnel
* chore: optimize telegram message format
* fix: webhook secrect
* feat: keep typing interval
---------
Co-authored-by: arvinxx <arvinx@foxmail.com>
When a short message is sandwiched between reasoning and tool call blocks,
component remount during streaming causes the fadeIn animation to replay.
Disable animation for these tool-adjacent single-line messages to prevent
the visual flicker.
* fix: skew plugin
Signed-off-by: Innei <tukon479@gmail.com>
* refactor(vite): enhance vercelSkewProtection to handle static imports and improve coverage
- Added handling for static import/export declarations to ensure correct deployment links.
- Updated coverage documentation to reflect new handling for static imports and additional cases.
- Adjusted comment numbering for clarity in the processing steps.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: dev proxy
Signed-off-by: Innei <tukon479@gmail.com>
* refactor(AssistantGroup): streamline contentId handling in GroupMessage component
- Simplified the logic for determining contentId by directly using lastAssistantMsg?.id.
- Moved the creation and generation state checks to follow the contentId assignment for better clarity.
Signed-off-by: Innei <tukon479@gmail.com>
* ♻️ refactor: remove chunk error reload retry, keep notification only
Made-with: Cursor
* fix: inject
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* Update sync.yml
* ✨ feat: update aspect ratio defaults to 'auto' for image generation models
* ✨ feat: enhance grounding metadata handling with image search results support
* ✨ feat: filter empty strings from searchQueries in groundingMetadata and update favicon handling in SearchGrounding component
* ✨ feat: add inputToolTokens tracking and update related components for tool usage
* ✨ feat: enhance search grounding with image results and update related components
* ✨ feat: add ImageSearchRef component and related tests for image reference handling
* fix test: rename VertexAIStream to GoogleGenerativeAIStream for consistency in test cases
* Update sync.yml
* 🐛 fix: add unsaved changes guard to prevent data loss on navigation
Migrate from BrowserRouter to createBrowserRouter (data router API) to enable
route-level navigation blocking. Add UnsavedChangesGuard component that uses
useBlocker to prevent leaving editor pages with unsaved changes, auto-saving
before navigation. Remove legacy renderRoutes/RouteConfig dead code.
Fixes LOBE-4973
* 🔧 chore: remove unused ESLint suppressions for welcome.ts
Cleaned up eslint-suppressions.json by removing suppressions related to sort-keys-fix and typescript-sort-keys for welcome.ts, as they are no longer needed.
Signed-off-by: Innei <tukon479@gmail.com>
* ⚡ perf: skip JSON snapshot on selection-only Lexical updates
Reintroduce dirtyElements/dirtyLeaves guard before editor.getDocument('json')
and deep-equality check, avoiding O(document-size) work on caret/selection
updates that do not mutate content.
* 🔧 test: update UnsavedChangesGuard tests to use message.destroy instead of message.success
Signed-off-by: Innei <tukon479@gmail.com>
* fix: dayjs init
- Moved dayjs plugin extensions (relativeTime, utc, isToday, isYesterday) to src/initialize.ts for centralized initialization.
- Removed redundant extensions from individual components to prevent duplicate calls.
- Updated locale loading logic in Locale.tsx to ensure correct dayjs locale handling.
This change improves performance by ensuring dayjs plugins are only extended once during application initialization.
Signed-off-by: Innei <tukon479@gmail.com>
* refactor: update router configuration to use RouteObject type
- Changed the type of desktopRoutes from RouteConfig[] to RouteObject[] for better compatibility with react-router-dom.
- Removed the RouteConfig interface from the router utility file to streamline the codebase.
This refactor enhances the router's integration with the latest routing library standards.
Signed-off-by: Innei <tukon479@gmail.com>
* feat: enhance Vite configuration and chunk management
- Added a function to suppress Vite's default URL print in the server configuration.
- Updated chunk file naming strategy in sharedRollupOutput to organize output files into specific directories based on chunk type (i18n, vendor, assets).
- Removed redundant dayjs chunk handling logic to streamline the manualChunks function.
These changes improve the clarity of the build output and enhance the server's configuration options.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat: add collapsible error stack with __CI__ default expand
- Add Collapse + Highlighter for error stack in Error component
- Define __CI__ in Vite (sharedRendererDefine) based on process.env.CI
- Add __CI__ to global.d.ts
- Add error.stack i18n to all 18 locales
Made-with: Cursor
* chore: update build:spa:copy script to handle multiple asset directories
- Modified the build:spa:copy script in package.json to iterate over multiple directories (assets, i18n, vendor) for both desktop and mobile builds, improving the asset copying process.
This change enhances the build process by ensuring all relevant directories are copied correctly.
Signed-off-by: Innei <tukon479@gmail.com>
* 🐛 fix: mark initialize.ts as sideEffects to prevent tree-shaking
sideEffects: false caused Rollup to drop the side-effect-only import
of initialize.ts, removing dayjs.extend(relativeTime) and enableMapSet()
from the production bundle.
---------
Signed-off-by: Innei <tukon479@gmail.com>
* ♻️ refactor: replace minImageSize with width/height min/max constraints
Refactor image dimension validation from a single `minImageSize` value
to flexible `width`/`height` objects with `min`/`max`, consistent with
the `duration` field's min/max pattern.
* ♻️ refactor: handle single-axis constraints in dimension error messages
Build dimension constraint text dynamically (e.g. "width ≥ 300px" or
"width ≥ 300px, height ≥ 300px") instead of interpolating raw
minWidth/minHeight values, preventing "300xundefinedpx" when only one
axis is constrained.
* ♻️ refactor(video): add max dimension constraint per official docs
Seedance image dimensions: 300-6000px per official documentation.
* ✨ feat(video): add aspect ratio validation for image uploads
Support aspectRatio constraint (width/height) with min/max in schema.
Seedance config: aspectRatio { min: 0.4, max: 2.5 } per official docs.
* ♻️ refactor(locales): add image dimension validation messages for multiple languages
* 🐛 fix(desktop): stub better-auth client for Electron and improve drag regions
Add auth-client.desktop.ts noop stub so the Electron renderer build
skips the real better-auth dependency that was crashing module evaluation
and preventing React from mounting.
Also fix drag-bar regions in splash.html and error.html, and add
dev:desktop convenience script.
* ♻️ refactor(desktop): lazy-init better-auth client with remote server URL
Replace noop stub with Proxy-based lazy initialization that creates the
real better-auth client on first use, using the configured remote server
URL from the electron store as baseURL.
* 🔧 fix(desktop): update Proxy target in lazyProp for better-auth client initialization
Change the Proxy target in the lazyProp function from a noop stub to a function, ensuring the apply trap works correctly for lazy initialization of the better-auth client.
Signed-off-by: Innei <tukon479@gmail.com>
* 🐛 fix(profile): restrict SSO providers display to non-desktop view
Update the condition for rendering the SSO Providers Row in the Profile Settings to only show when the user is logged in and not on a desktop device. This change improves the user interface by preventing unnecessary display on desktop screens.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
- Remove desktop-related build steps from Dockerfile
- Simplify next.config.ts, only apply Vercel-specific config on Vercel
- Remove webpack customization from define-config.ts
- Fix String() type conversion in video.ts
* ✨ feat: add support for new image resolution and thinking level parameters in model configurations
* ✨ feat: add Gemini 3.1 Flash Image model with enhanced capabilities and update model configurations
* 🐛 fix: adjust temperature setting based on model modalities in LobeGoogleAI
* ✨ feat: add DeepSeek V3.2 model and update existing model configurations
* ✨ feat: add ImageResolution2Slider and ThinkingLevel4Slider components; remove obsolete imports
* ✨ feat: add imageAspectRatio2 parameter for Nano Banana 2 model; update related components and configurations
* 🐛 fix: refactor outputTextTokens calculation for clarity and consistency
* ⚡️ perf(spa): lazy import spaHtmlTemplates to reduce initial bundle
* 🔧 chore: update package dependencies and Vite configuration
- Bump @lobehub/icons version from ^4.1.0 to ^4.9.0 in package.json for improved features and fixes.
- Set Vite server host to '0.0.0.0' for better accessibility during development.
- Refactor asset URL rewriting in route.ts to simplify the return statement in the development mode.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat(analytics): enhance Google and Vercel analytics integration
- Refactored GoogleAnalytics component to accept a `gaId` prop for improved flexibility.
- Updated VercelAnalytics component to accept a `debug` prop, allowing for dynamic debugging.
- Modified Analytics index to pass the appropriate props to Google and Vercel components based on environment settings.
- Removed the obsolete LobeAnalyticsProviderWrapper.vite.tsx file to streamline the codebase.
This update improves the configurability of analytics components and cleans up unused files.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* feat: improve the inject model context plugins decriptions
fix: change the conversation-flow to change the subAgent message show place
fix: eslint fixed
fix: slove the inject not work problem
feat: add the lost agent management inject open
feat: add the AgentManagementInjector
fix: add the exec task mode & improve the Pre-load agents
fix: improve the executor import way & update the getEffectiveAgentId function
fix: slove the test problem
🐛 fix: support agnet manager ments (#12171)
feat: add the sub agents in context scope to support call subagent
refactor agent management implement
update
add builtin agent management
* fix types
* fix import
* fix test
* fix tests
* fix tests
* 🐛 fix: update provider request filtering to include settings for disabling browser requests
* 🐛 test: add unit tests for isProviderDisableBrowserRequest function
* 🐛 fix(models): remove deprecated AI models and add Step 3.5 Flash model
* ✨ feat(model-bank): add Qwen3 Coder Next and GLM-4.7 models; remove Qianfan Lightning 128B A19B
* feat: add new Qwen3.5 and MiniMax-M2.5 models with updated pricing and capabilities
* feat: update cerebras and ollamacloud models with new Qwen3.5 capabilities and adjust pricing in qwen model
* init plan
* 📝 docs: update SPA plan for dev mode Worker cross-origin handling
- Clarified the handling of Worker cross-origin issues in dev mode, emphasizing the need for `workerPatch` to wrap cross-origin URLs as blob URLs.
- Enhanced the explanation of the dev mode's resource URL rewriting process for better understanding.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 refactor: Phase 1 - 环境变量整治
- Fix Pyodide env var mismatch (NEXT_PUBLIC_PYPI_INDEX_URL → pythonEnv.NEXT_PUBLIC_PYODIDE_PIP_INDEX_URL)
- Consolidate python.ts to use pythonEnv instead of direct process.env
- Remove NEXT_PUBLIC_ prefix from server-side MARKET_BASE_URL (5 files)
* 🏗️ chore: Phase 2 - Vite 工程搭建
- Add vite.config.ts with dual build (desktop/mobile via MOBILE env)
- Add index.html SPA template with __SERVER_CONFIG__ placeholder
- Add entry.desktop.tsx and entry.mobile.tsx SPA entry points
- Add dev:spa, dev:spa:mobile, build:spa, build:spa:copy scripts
- Install @vitejs/plugin-react and linkedom
* ♻️ refactor: Phase 3 - 第一方包 Next.js 解耦
- Replace next/link with <a> in builtin-tool-web-browsing (4 files, external links)
- Replace next/image with <img> in builtin-tool-agent-builder/InstallPlugin.tsx
- Add Vite import.meta.env compat for isDesktop in const/version.ts, builtin-tool-gtd, builtin-tool-group-management
* ♻️ refactor: Phase 4a - Auth 页面改用直接 next/navigation 和 next/link
- 9 auth files: @/libs/next/navigation → next/navigation
- 5 auth files: @/libs/next/Link → next/link
- Auth pages remain in Next.js App Router, need direct Next.js imports
* ♻️ refactor: Phase 4b - Next.js 抽象层替换为 react-router-dom/vanilla React
- navigation.ts: useRouter/usePathname/useSearchParams/useParams → react-router-dom
- navigation.ts: redirect/notFound → custom error throws
- navigation.ts: useServerInsertedHTML → no-op for SPA
- Link.tsx: next/link → react-router-dom Link adapter (href→to, external→<a>)
- Image.tsx: next/image → <img> wrapper with fill/style support
- dynamic.tsx: next/dynamic → React.lazy + Suspense wrapper
* ✨ feat: Phase 5 - 新建 SPAGlobalProvider
- Create SPAServerConfig type (analyticsConfig, clientEnv, theme, featureFlags, locale)
- Add window.__SERVER_CONFIG__ and __MOBILE__ to global.d.ts
- Create SPAGlobalProvider (client-only Provider tree mirroring GlobalProvider)
- Includes AuthProvider for user session support
- Update entry.desktop.tsx and entry.mobile.tsx to wrap with SPAGlobalProvider
* ♻️ refactor: add SPA catch-all route handler with Vite dev proxy
- Create (spa)/[[...path]]/route.ts for serving SPA HTML
- Dev mode: proxy Vite dev server, rewrite asset URLs, inject Worker patch
- Prod mode: read pre-built HTML templates
- Build SPAServerConfig with analytics, theme, clientEnv, featureFlags
- Update middleware to pass SPA routes through to catch-all
* ♻️ refactor: skip auth checks for SPA routes in middleware
SPA pages are all public (no sensitive data in HTML).
Auth is handled client-side by SPAGlobalProvider's AuthProvider.
Only Next.js auth routes and API endpoints go through session checks.
* ♻️ refactor: replace Next.js-specific analytics with vanilla JS
- Google.tsx: replace @next/third-parties/google with direct gtag script
- ReactScan.tsx: replace react-scan/monitoring/next with generic script
- Desktop.tsx: replace next/script with native script injection
* ♻️ refactor: migrate @t3-oss/env-nextjs to @t3-oss/env-core
Replace framework-specific env validation with framework-agnostic version.
Add clientPrefix where client schemas exist.
* ♻️ refactor: replace next-mdx-remote/rsc with react-markdown
Use client-side react-markdown for MDX rendering instead of
Next.js RSC-dependent next-mdx-remote.
* 🔧 chore: update build scripts and Dockerfile for SPA integration
- build:docker now includes SPA build + copy steps
- dev defaults to Vite SPA, dev:next for Next.js backend
- Dockerfile copies public/spa/ assets for production
- Add public/spa/ to .gitignore (build artifact)
* 🗑️ chore: remove old Next.js route segment files and serwist PWA
- Delete [variants] page.tsx, error.tsx, not-found.tsx, loading.tsx
- Delete root loading.tsx and empty [[...path]] directory
- Delete unused loaders directory
- Remove @serwist/next PWA wrapper from Next.js config
* plan2
* ✨ feat: add locale detection script to index.html for SPA dev mode
* ♻️ refactor: remove locale and theme from SPAServerConfig
* ✨ feat: add [locale] segment with force-static and SEO meta generation
* ♻️ refactor: remove theme/locale reads from SPAGlobalProvider
* ✨ feat: set vite base to /spa/ for production builds
* ✨ feat: auto-generate spaHtmlTemplates from vite build output
* 🔧 chore: register dev:next task in turbo.json for parallel dev startup
* ♻️ refactor: rename (spa) route group to spa segment, rewrite SPA routes via middleware
* ✨ feat: add Vite-compatible i18n/locale modules with import.meta.glob and resolve aliases
* 🔧 fix: use custom Vite plugin for module redirects instead of resolve.alias
* very important
* build
* 🔧 chore: update build scripts and clean up Vite configuration by removing unused plugin and code
Signed-off-by: Innei <tukon479@gmail.com>
* 🗑️ refactor: remove all electron modifier scripts
Modifiers are no longer needed with Vite SPA renderer build.
* ✨ feat: add Vite renderer entry to electron-vite config
Add renderer build configuration to electron-vite, replacing the old
Next.js shadow workspace build flow. Delete buildNextApp.mts and
moveNextExports.ts, update package.json scripts accordingly.
* ✨ feat: add .desktop suffix files for eager i18n loading
Create 4 .desktop files that use import.meta.glob({ eager: true })
for synchronous locale access in Electron desktop builds, replacing
the async lazy-loading used in web SPA builds.
* 🔧 refactor: adapt Electron main process for Vite renderer
Replace nextExportDir with rendererDir, update protocol from
app://next to app://renderer, simplify file resolution to SPA
fallback pattern, update _next/ asset paths to /assets/.
* 🔧 chore: update electron-builder files config for Vite renderer
Replace dist/next references with dist/renderer, remove Next.js
specific exclusion rules no longer applicable to Vite output.
* 🗑️ chore: remove @ast-grep/napi dependency
No longer needed after removing electron modifier scripts.
* 🔧 refactor: unify isDesktop to __ELECTRON__ compile-time constant
Remove NEXT_PUBLIC_IS_DESKTOP_APP and VITE_IS_DESKTOP_APP env vars.
Unify isDesktop in @lobechat/const using __ELECTRON__ defined by Vite.
Re-export from builtin-tool packages. Scripts use DESKTOP_BUILD.
* update
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 refactor: use electron-vite ELECTRON_RENDERER_URL instead of hardcoded port 3015
Replace hardcoded http://localhost:3015 with process.env.ELECTRON_RENDERER_URL
injected by electron-vite dev server. Clean up stale Next.js references.
* 🐛 fix: use local renderer-entry shim to resolve Vite root path issue
HTML entry ../../src/entry.desktop.tsx resolves to /src/entry.desktop.tsx
in URL space, which Vite cannot find within apps/desktop/ root. Add a
local shim that imports across root via module resolver instead.
* 🔧 refactor: extract shared renderer Vite config into sharedRendererConfig
Deduplicate plugins (nodeModuleStub, platformResolve, tsconfigPaths) and
define (__MOBILE__, __ELECTRON__, process.env) between root vite.config.ts
and electron.vite.config.ts renderer section.
* 🔧 refactor: move all renderer plugins and optimizeDeps into shared config
sharedRendererPlugins now includes react, codeInspectorPlugin alongside
nodeModuleStub, platformResolve, tsconfigPaths. Add sharedOptimizeDeps
for pre-bundling list. Both root and electron configs consume shared only.
* 🐛 fix: set electron renderer root to monorepo root for correct glob resolution
import.meta.glob with absolute paths (e.g. /node_modules/antd/...) resolved
within apps/desktop/ instead of monorepo root. Change renderer root to ROOT_DIR,
add electronDesktopHtmlPlugin middleware to rewrite / to /apps/desktop/index.html,
and remove the now-unnecessary renderer-entry.ts shim.
* desktop vite !!
Signed-off-by: Innei <tukon479@gmail.com>
* sync import !!
Signed-off-by: Innei <tukon479@gmail.com>
* clean ci!!
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 refactor: update SPA path structure and clean up dependencies
- Changed the path in .gitignore and related files from [locale] to [variants] for SPA templates.
- Updated index.html to set body height to 100%.
- Cleaned up package.json by removing unused dependencies and reorganizing devDependencies.
- Refactored RendererUrlManager to use a constant for SPA entry HTML path.
- Removed obsolete route.ts file from the SPA structure.
- Adjusted proxy configuration to reflect the new SPA path structure.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update build script to include mobile SPA build
- Modified the build script in package.json to add the mobile SPA build step.
- Ensured the build process accommodates both desktop and mobile SPA versions.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update build scripts and improve file encoding consistency
- Modified the build script in package.json to ensure the SPA copy step runs after the build.
- Updated file encoding in generateSpaTemplates.mts from 'utf-8' to 'utf8' for consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 fix: correct Blob import syntax and update global server config type
- Fixed the Blob import syntax in route.ts to ensure proper module loading.
- Updated the global server configuration type in global.d.ts for improved type safety.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 test: update RendererUrlManager test to reflect new file path
- Modified the mock implementation in RendererUrlManager.test.ts to check for the updated file path '/mock/export/out/apps/desktop/index.html'.
- Adjusted the expected resolved path in the test to match the new structure.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 refactor: remove catch-all example file and update imports
- Deleted the catch-all example file `catch-all.eg.ts` to streamline the codebase.
- Updated import paths in `ClientResponsiveLayout.tsx` and `ClientResponsiveContent/index.tsx` to use the new dynamic import location.
- Added type declarations for HTML templates in `spaHtmlTemplates.d.ts`.
- Adjusted `tsconfig.json` to include the updated file structure.
- Enhanced type definitions in `global.d.ts` and fixed locale loading in `locale.vite.ts`.
Signed-off-by: Innei <tukon479@gmail.com>
* e2e
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: remove unused build script for Vercel deployment
- Deleted the `build:vercel` script from package.json to streamline the build process.
- Ensured the remaining build scripts are organized and relevant.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 config: update Vite build input for mobile support
- Changed the build input path in vite.config.ts to conditionally use 'index.mobile.html' for mobile builds, enhancing support for mobile SPA versions.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 feat: add compatibility checks for import maps and cascade layers
- Implemented functions to check for browser support of import maps and CSS cascade layers.
- Redirected users to a compatibility page if their browser does not support the required features.
- Updated the build script in package.json to use the experimental analyze command for better performance.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: rename
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 feat: refactor authentication layout and introduce global providers
- Created a new `RootLayout` component to streamline the layout structure.
- Removed the old layout file for variants and integrated necessary features into the new layout.
- Added `AuthGlobalProvider` to manage authentication context and server configurations.
- Introduced language and theme selection components for enhanced user experience.
- Updated various components to utilize the new context and improve modularity.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 config: exclude build artifacts from serverless functions
- Updated the `next.config.ts` to exclude SPA, desktop, and mobile build artifacts from serverless functions.
- Added paths for `public/spa/**`, `dist/**`, `apps/desktop/build/**`, and `packages/database/migrations/**` to the exclusion list.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 config: refine exclusion of build artifacts from serverless functions
- Updated `next.config.ts` to specify exclusion paths for desktop and mobile build artifacts.
- Changed exclusions from `dist/**` and `apps/desktop/build/**` to `dist/desktop/**`, `dist/mobile/**`, and `apps/desktop/**` for better clarity and organization.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 fix: update BrowserRouter basename for local development
- Modified the `ClientRouter` component to conditionally set the `basename` of `BrowserRouter` based on the `__DEBUG_PROXY__` variable, improving local development experience.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 feat: implement mobile SPA workflow and S3 asset management
- Added a new workflow for building and uploading mobile SPA assets to S3, including environment variable configurations in `.env.example`.
- Updated `package.json` to include a new script for the mobile SPA workflow.
- Enhanced the Vite configuration to support dynamic CDN base paths.
- Refactored the template generation script to handle mobile HTML templates more effectively.
- Introduced new modules for uploading assets to S3 and generating mobile HTML templates.
Signed-off-by: Innei <tukon479@gmail.com>
* 🐛 fix: extract origin from MOBILE_S3_PUBLIC_DOMAIN to prevent double key prefix
* 🔧 fix: update mobile HTML template to use the latest asset versions
- Modified the mobile HTML template to reference the updated JavaScript asset version for improved functionality.
- Ensured consistency in the template structure while maintaining existing styles and scripts.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update dependencies and refine service worker integration
- Removed outdated dependencies related to Serwist from package.json and tsconfig.json.
- Added vite-plugin-pwa to enhance PWA capabilities in the Vite configuration.
- Updated service worker registration logic in the PWA installation component.
- Introduced a new local development proxy route for debugging purposes.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: refactor development scripts and remove Turbo configuration
- Updated the `dev` script in `package.json` to use a new startup sequence script for improved development workflow.
- Removed the outdated `turbo.json` configuration file as it is no longer needed.
- Introduced `devStartupSequence.mts` to manage the startup of Next.js and Vite processes concurrently.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 feat: update entry points and introduce debug proxy for local development
- Changed the main entry point in `index.html` from `entry.desktop.tsx` to `entry.web.tsx` for improved web compatibility.
- Added an `initialize.ts` file to enable `immer`'s `enableMapSet` functionality.
- Introduced a new `__DEBUG_PROXY__` variable in global types to support local development proxy features.
- Implemented a debug proxy route to facilitate local development with dynamic HTML injection and script handling.
- Removed outdated mobile routing components to streamline the codebase.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 refactor: replace BrowserRouter with RouterProvider for improved routing
- Updated entry points for desktop, mobile, and web to utilize RouterProvider and createAppRouter for better routing management.
- Removed the deprecated renderRoutes function in favor of a more streamlined router configuration.
- Enhanced router setup to support error boundaries and dynamic routing.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 refactor: remove direct access handling for SPA routes in proxy configuration
- Eliminated the handling of direct access to pre-rendered SPA pages in the proxy configuration.
- Simplified the request processing logic by removing checks for SPA routes, streamlining the middleware response flow.
Signed-off-by: Innei <tukon479@gmail.com>
* update
* 🔧 refactor: enhance Worker instantiation logic in mobile HTML template
* 🐛 fix: remove duplicate waitForPageWorkspaceReady calls in page CRUD e2e steps
* 🔧 refactor: simplify createTracePayload function by using btoa for base64 encoding
* 🔧 refactor: specify locales in import.meta.glob for dayjs and antd
* 🔧 refactor: replace Node.js Buffer with web-compatible btoa for base64 encoding in file upload
* 🐛 fix: disable consistent-type-imports rule for mdx files to prevent eslint crash
* 🔧 refactor: add height style to root div for consistent layout
* 🔧 refactor: replace btoa with Buffer for base64 encoding in trace and file upload handling
* 🔧 refactor: extract nextjsOnlyRoutes to a separate file for better organization
* 🔧 refactor: enable Immer MapSet plugin in tests for better state management
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 refactor: integrate sharedRollupOutput configuration and increase cache size for better performance
Signed-off-by: Innei <tukon479@gmail.com>
* 🗑️ chore: remove obsolete desktop.routes.test.ts file as it is no longer needed
Signed-off-by: Innei <tukon479@gmail.com>
* 🐛 fix: use cross-env for env vars in npm scripts (Windows CI)
Co-authored-by: Cursor <cursoragent@cursor.com>
* 🔧 chore: update Dockerfile for web-only build and adjust npm scripts to use pnpm
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: enhance Dockerfile prebuild process with environment checks and add new dependencies
- Updated Dockerfile to include environment checks before removing desktop-only code.
- Added new dependencies in package.json: @aws-sdk/client-bedrock-runtime, @opentelemetry/auto-instrumentations-node, @opentelemetry/resources, @opentelemetry/sdk-metrics, and ajv.
- Configured Rollup to exclude @aws-sdk/client-bedrock-runtime from the SPA bundle.
- Introduced dockerPrebuild.mts script for environment variable validation and information logging.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: enhance Vite and Electron configurations with environment loading and trace encoding improvements
- Updated Vite and Electron configurations to load environment variables using loadEnv.
- Modified trace encoding in utils to use TextEncoder for better compatibility.
- Adjusted sharedRendererConfig to expose only necessary public environment variables.
Signed-off-by: Innei <tukon479@gmail.com>
* 🗑️ chore: remove plans directory (migrated to discussion)
* ♻️ refactor: inject NEXT_PUBLIC_* env per key in Vite define
Co-authored-by: Cursor <cursoragent@cursor.com>
* ✨ feat: add loading screen with animation to enhance user experience
- Introduced a loading screen with a brand logo and animations for better visual feedback during loading times.
- Implemented CSS styles for the loading screen and animations in index.html.
- Removed the loading screen from the DOM once the layout is ready using useLayoutEffect in SPAGlobalProvider.
Signed-off-by: Innei <tukon479@gmail.com>
* 🗑️ chore: remove unnecessary external dependency from Vite configuration
- Eliminated the external dependency '@aws-sdk/client-bedrock-runtime' from the Vite configuration to streamline the build process for the SPA bundle.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat: add web app manifest link in index.html and enable PWA support in Vite configuration
- Added a link to the web app manifest in index.html to enhance PWA capabilities.
- Enabled manifest support in Vite configuration for improved service worker functionality.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update link rel attributes for improved SEO and consistency
- Modified link rel attributes in multiple components to remove 'noreferrer' and standardize to 'nofollow'.
- Adjusted imports in PageContent components for better organization.
Signed-off-by: Innei <tukon479@gmail.com>
* update provider
* ✨ feat: enhance loading experience and update package dependencies
- Added a loading screen with animations and a brand logo in index.html for improved user feedback during loading times.
- Introduced CSS styles for the loading screen and animations.
- Updated package.json files across multiple packages to include "@lobechat/const" as a dependency.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: update proxy
Signed-off-by: Innei <tukon479@gmail.com>
* 🗑️ chore: remove GlobalLayout and Locale components
- Deleted GlobalLayout and Locale components from the GlobalProvider directory to streamline the codebase.
- This removal is part of a refactor to simplify the layout structure and improve maintainability.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: clean up console logs and improve component structure
- Removed unnecessary console log statements from AgentForkTag components in both agent and community directories to enhance code cleanliness.
- Refactored UserAgentList component for better readability by restructuring the useUserDetailContext hook and adjusting the layout of Flexbox components.
Signed-off-by: Innei <tukon479@gmail.com>
* chore: remove console log from MemoryAnalysis component
* chore: update mobile HTML template with new asset links
- Replaced the previous asset links in the mobile HTML template with updated versions to ensure the latest resources are utilized.
- Adjusted the link rel attributes for module preloading to enhance performance and loading efficiency.
Signed-off-by: Innei <tukon479@gmail.com>
* fix: correct variable assignment in createClientTaskThread integration test
- Updated the assignment of the second parent message in the createClientTaskThread integration test to improve clarity and ensure proper data handling.
- Changed the variable name from 'secondParentMsg' to 'inserted' for better context before extracting the first message from the inserted results.
Signed-off-by: Innei <tukon479@gmail.com>
* refactor: simplify authentication check in define-config
- Removed the dependency on the isDesktop variable in the authentication check to streamline the logic.
- Enhanced the clarity of the redirection process for protected routes by focusing solely on the isLoggedIn status.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat(dev): enhance local development setup with debug proxy instructions
- Added detailed instructions for starting the development environment in CLAUDE.md, including commands for SPA and full-stack modes.
- Updated README.md and README.zh-CN.md to reflect new commands and the debug proxy URL for local development.
- Introduced a Vite plugin to print the debug proxy URL upon server start, facilitating easier local development against the production backend.
- Corrected the debug proxy route in entry.web.tsx and define-config.ts for consistency.
This improves the developer experience by providing clear guidance and tools for local development.
Signed-off-by: Innei <tukon479@gmail.com>
* optimize perf
* optimize perf
* optimize perf
* remove speedy plugin
* add dayjs vendor
* Revert "remove speedy plugin"
This reverts commit bf986afeb1.
---------
Signed-off-by: Innei <tukon479@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: align agent rename usage with agent profile editor
* fix: agent content emoji picker popupProps
* chore: agent and agent group use emoji background color in session list
* chore: remove fixed popupProps
* fix: user select problem
* feat: add back model config button
* chore: refact model detail props
* chore: add model detail loading
* chore: adjust dropdown side offset
* 🐛 fix: correct eslint command syntax in lint-ts.sh script
* ✨ feat: add scroll functionality for active model in List component
* ✨ feat: improve scroll behavior for active model in List component
🐛 fix(docker): hoist @napi-rs/canvas for PDF parsing in Docker
Add `@napi-rs/canvas-*` to public-hoist-pattern in .npmrc to fix
`DOMMatrix is not defined` error when parsing PDFs in Docker.
## Summary
Merge latest changes from main into canary.
## Changes
- Merge branch main into canary via
codex/merge-main-into-canary-20260221
- Resolve one merge conflict in packages/model-bank/src/types/aiModel.ts
by keeping both ModelParamsSchema and VideoModelParamsSchema imports
## Summary by Sourcery
Update NVIDIA provider to support preserved thinking and
reasoning_content for new reasoning-capable chat models and bump package
version.
New Features:
- Add NVIDIA chat model entries for MiniMax-M2.1, DeepSeek V3.2,
GLM-4.7, GLM-5, and Kimi K2.5 with reasoning support.
Enhancements:
- Extend NVIDIA runtime payload handling to map reasoning to
reasoning_content and to translate thinking into either thinking or
enable_thinking/clear_thinking depending on model capabilities.
- Refine NVIDIA provider tests to cover GLM preserved thinking behavior
and reasoning_content conversion across models.
Build:
- Bump package version from 2.1.31 to 2.1.32.
Only 4 checkouts truly need full git history (tag operations, branch sync).
The remaining 18 occurrences were used in build/lint/test jobs that only
need the current commit. Also removed redundant fetch-tags: true where
fetch-depth: 0 already implies full tag fetch.
* ✨ feat(nvidia): add interleaved thinking support with new reasoning models
- Add MiniMax-M2.1, DeepSeek V3.2, GLM-4.7, GLM-5, Kimi K2.5 to NVIDIA model bank
- Add reasoning conversion for interleaved thinking mode
- Add tests for GLM-5 and DeepSeek V3.2 thinking
* ♻️ refactor(nvidia): simplify payload handling logic
- Remove redundant THINKING_MODELS and INTERLEAVED_THINKING_MODELS sets
- Apply reasoning -> reasoning_content conversion for all NVIDIA models
- Apply thinking -> chat_template_kwargs conversion based on user input only
- Let API decide if model supports the parameters instead of client-side filtering
* ♻️ refactor(nvidia): add preserved thinking support with model-specific params
contentBlocksToString() was prepending APP_URL via urlJoin() to item.data,
but item.data already contained the full URL after processContentBlocks()
uploaded to S3. This caused URLs like:
https://example.com/https://example.com/f/uuid
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
#### 💻 Change Type
<!-- For change type, change [ ] to [x]. -->
- [ ] ✨ feat
- [ ] 🐛 fix
- [ ] ♻️ refactor
- [X] 💄 style
- [ ] 👷 build
- [ ] ⚡️ perf
- [ ] ✅ test
- [ ] 📝 docs
- [ ] 🔨 chore
#### 🔗 Related Issue
Closes#10346
<!-- Link to the issue that is fixed by this PR -->
<!-- Example: Fixes #xxx, Closes #xxx, Related to #xxx -->
#### 🔀 Description of Change
1. 更新的文生图,图生图模型列表,`z-image` `wan2.5` `wan2.6` `qwen-image-plus/max`
`qwen-image-edit-plus/max`
2. 新增 `image2image` endpoint,为老版本图生图模型进行兼容
3. 默认使用 `multimodal-generation` endpoint(新模型目前调研下来都是用这个了,同时支持图生图和文生图)
4. 支持多区域 Dashscope URL,跟随 baseUrl 参数,自动切分 `/compatible-mode/v1` 默认北京区域
北京 https://dashscope.aliyuncs.com
新加坡 https://dashscope-intl.aliyuncs.com
弗吉尼亚 https://dashscope-us.aliyuncs.com
|Endpoint||
|-|-|
|`multimodal-generation`|<img width="826" height="547" alt="image"
src="https://github.com/user-attachments/assets/38206851-94bc-48cc-8a57-24ed7155782f"
/><img width="521" height="383" alt="image"
src="https://github.com/user-attachments/assets/40fe0ed0-35fd-443d-868f-3ae2c27352f9"
/><img width="681" height="557" alt="image"
src="https://github.com/user-attachments/assets/8101b0f1-81c8-4892-a6e2-b51b5b0e0235"
/>|
|`text2image`|<img width="600" height="564" alt="image"
src="https://github.com/user-attachments/assets/39e82a4f-5305-4f30-ae4d-e5339f401e6d"
/>|
<!-- Thank you for your Pull Request. Please provide a description
above. -->
#### 🧪 How to Test
<!-- Please describe how you tested your changes -->
<!-- For AI features, please include test prompts or scenarios -->
- [ ] Tested locally
- [ ] Added/updated tests
- [ ] No tests needed
#### 📸 Screenshots / Videos
<!-- If this PR includes UI changes, please provide screenshots or
videos -->
| Before | After |
| ------ | ----- |
| ... | ... |
#### 📝 Additional Information
ref: https://help.aliyun.com/zh/model-studio/newly-released-models
ref:
https://bailian.console.aliyun.com/cn-beijing/?tab=doc#/doc/?type=model&url=2987148
<!-- Add any other context about the Pull Request here. -->
<!-- Breaking changes? Migration guide? Performance impact? -->
## Summary by Sourcery
Extend Qwen image generation support to cover new text-to-image and
image-to-image models while routing legacy models via dedicated
text2image/image2image endpoints and defaulting other models to the
multimodal-generation API.
New Features:
- Add model metadata and configuration for new Qwen image models
including Z-Image Turbo, Qwen Image Edit Max/Plus, Qwen Image Max/Plus,
and Wanxiang 2.5/2.6 variants.
- Introduce explicit handling of legacy text-to-image and image-to-image
Qwen models via separate async text2image and image2image endpoints.
Enhancements:
- Update the Qwen image creation flow to prefer the
multimodal-generation endpoint for newer models and improve error
messaging and logging across image workflows.
- Reformat select Qwen chat model descriptions for consistency without
changing behavior.
Tests:
- Adjust Qwen image creation tests to align with the new
multimodal-generation behavior and removed strict input validation on
qwen-image-edit-specific image URL requirements.
- Add gemini-3.1-pro-preview to Google, Vertex AI, and LobeHub providers
- Add thinkingLevel3 extend param type (low/medium/high)
- Create ThinkingLevel3Slider component for 3-level thinking control
- Fix thinkingLevel2/3 not passing values to API due to form field name mismatch
- Add medium to GoogleThinkingLevel and ChatStreamPayload thinkingLevel types
- Update planCardModels to use gemini-3.1-pro-preview
* 🌐 chore: translate non-English comments to English in src/libs
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* 🐛 fix: update test to match translated error message
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: arvinxx <arvinx@foxmail.com>
feat: support switch dashscope URL based on baseURL
feat: support switch dashscope URL based on baseURL
feat: support switch dashscope URL based on baseURL
* ♻️ refactor: replace per-item Editing components with singleton EditingPopover
Eliminate 3 duplicate Editing components (AgentItem, AgentGroupItem, Group)
in favor of a single imperative EditingPopover using @lobehub/ui Popover atoms.
Anchor elements are passed via React state (useState + callback ref) instead
of DOM queries. Removes agentRenamingId/groupRenamingId from homeStore.
* fix: edit group agent avaar
Signed-off-by: Innei <tukon479@gmail.com>
* ✅ test(e2e): update rename popover selectors and allow console in tests
Support both antd Popover and @lobehub/ui Popover atoms selectors.
Use save button click instead of click-outside for non-Enter rename flow.
Disable no-console rule for e2e and test files.
* ✅ test(e2e): fix rename popover input detection with data-testid
Add data-testid="editing-popover" to PopoverPopup. Simplify inputNewName
to use single combined selector instead of sequential try-catch loop that
caused 8s+ timeout. Support both @lobehub/ui and antd Popover.
---------
Signed-off-by: Innei <tukon479@gmail.com>
Change canary version format from X.(Y+1).0-canary.TIMESTAMP to
X.Y.(Z+1)-canary.N with auto-incrementing sequence. Also add
release prefix as build trigger and update sync PR titles.
Allow desktop app users to see and toggle the "Fetch on Client" option
in provider settings. The server-side default values for desktop remain
unchanged, so this only affects UI visibility.
* 🐛 fix: scroll ChatInput into view when starter mode activates
When clicking Create Agent/Group/Write, the SuggestQuestions panel
renders below the ChatInput and pushes total content beyond the
viewport, causing the ChatInput to scroll out of view. This adds
scrollIntoView + focus on mode change so the editor stays visible
and ready for input. Also improves E2E test to target contenteditable
inside ChatInput directly and wait for animation to settle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* update
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- Pass latency (task submission → webhook callback) to
`chargeAfterGenerate` for video generation metrics
- Use `batch.config` instead of webhook `result` for
`computePriceParams` (generateAudio), ensuring pricing uses
user-submitted config
- Rename `generateAudio` top-level param to `computePriceParams: {
generateAudio }` for better structure
## Test plan
- [ ] Submit a video generation task with generateAudio enabled, verify
charge uses correct pricing
- [ ] Submit a video generation task with generateAudio disabled, verify
charge reflects the difference
- [ ] Verify latency is recorded in the charge metrics
## Summary by Sourcery
Adjust video generation charging and metadata to rely on batch config
and record end-to-end latency.
Bug Fixes:
- Ensure generateAudio pricing uses the original batch configuration
instead of the webhook result payload.
Enhancements:
- Pass task submission-to-webhook latency into video charging for
improved metrics.
- Rename chargeAfterGenerate pricing input to computePriceParams for
clearer structure and future extensibility.
- Name generated video files using the batch prompt prefix when
available to improve asset identification.
Tests:
- Add unit tests for the Volcengine video provider request/response
handling, including payload mapping, client config, and error cases.
- Add initial test scaffolding for video standard parameters, cost
computation, single-price resolution, and Volcengine video webhook
handling.
Automatic sync from main to canary. Merge conflicts detected.
**Resolution steps:**
```bash
git fetch origin
git checkout sync/main-to-canary-20260214-22020422229
git merge origin/main
# Resolve conflicts
git add -A && git commit
git push
```
> Do NOT merge canary into a main-based branch — always merge main INTO
the canary-based branch to keep a clean commit graph.
- Added concurrency control to prevent overlapping sync jobs.
- Improved logic for detecting changes between main and canary branches.
- Streamlined handling of fast-forward merges and conflict resolution.
- Updated PR creation process for manual conflict resolution with detailed instructions.
Signed-off-by: Innei <tukon479@gmail.com>
## Summary
- Fix bidirectional sync race condition in `TopicUrlSync` where stale
`activeGenerationTopicId` from zustand store overwrites the URL when
navigating back to image/video pages without a `?topic=` param
- Replace `createStoreUpdater` (useEffect-based) with `useLayoutEffect`
for URL → store sync, ensuring it runs before the store → URL
subscription
- Generate latest i18n locales
## Test plan
- [ ] Visit `/video?topic=<id>`, navigate to home, click `/video` —
topic should not persist
- [ ] Visit `/image?topic=<id>`, navigate to home, click `/image` —
topic should not persist
- [ ] Click a topic in the sidebar — URL should update with
`?topic=<id>`
- [ ] Refresh page with `?topic=<id>` — correct topic should be selected
## Summary by Sourcery
Fix URL and store synchronization for generation topics and refresh
localized video page translations.
Bug Fixes:
- Prevent stale activeGenerationTopicId values in the store from
overwriting the URL when remounting image or video pages without a topic
query parameter.
Documentation:
- Regenerate and update i18n locale JSON files across all supported
languages, including new video translation files.
## Summary
- Add complete video generation feature including UI pages, store
management, server routes, and webhook handling
- Support Volcengine video generation provider with text-to-video and
image-to-video capabilities
- Add video generation topic management, config panel, generation feed,
and prompt input components
- Include database migration for video generation schema
- Refactor GenerationTopicList/TopicPanel as shared components for both
image and video generation
## Test plan
- [ ] Verify video generation page renders correctly
- [ ] Test text-to-video generation flow end-to-end
- [ ] Test image-to-video generation with reference frames
- [ ] Verify video generation topic CRUD operations
- [ ] Confirm webhook handling for async video generation results
- [ ] Check video generation config panel model selection and parameter
controls
The GITHUB_TOKEN cannot push changes to .github/workflows/ files due to
GitHub's security restrictions. The 'workflows' permission key added in
the previous commit is not a valid workflow permission scope.
Fix: Use secrets.GH_TOKEN (PAT with workflow scope) in the checkout step
so that git push has the necessary credentials to push branches that
contain workflow file changes (e.g. from merge conflicts).
Also reverts the invalid 'workflows: write' permission.
When merge conflicts involve .github/workflows/ files, GitHub requires
the `workflows: write` permission to push branches containing workflow
file changes. Without this permission, the sync branch push is rejected
with 'refusing to allow a GitHub App to create or update workflow without
workflows permission'.
- Reject webhook requests when token is missing instead of skipping verification
- Use proper union type for generation assets instead of blanket VideoGenerationAsset cast
- Replace sync js-sha256 with Node.js crypto.createHash for video hashing
- Add 500MB size limit and 5-minute timeout for video downloads
- Add displayName to VideoLoading component
Generate a one-time crypto-random token per video task, store it in
asyncTask metadata, and append it to the callback URL. The webhook
endpoint verifies the token using timing-safe comparison before
processing, returning 401 on mismatch. Old tasks without a token
are allowed through for backward compatibility.
- Make AsyncTaskModel.findByInferenceId static to avoid empty userId
- Extract GenerationTopicType for type-safe topic type narrowing
- Hoist batch query to eliminate duplicate DB call in webhook handler
- Add missing i18n keys for video error actions and status
- Fix comment accuracy in generationBatch deletion
- Add videoGeneration to PricingGroup maps to fix TS2741 type errors
- Collect url and coverUrl in addition to thumbnailUrl when deleting topics/batches
- Fix createTopic test assertion to match new optional type parameter
* ✨ chore: enhance release workflow to include conditional release body handling
- Added environment variable `RELEASE_BODY` to capture release notes from the GitHub event.
- Updated the workflow to use this variable, ensuring proper handling of release body content during manual dispatch events.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: simplify GitHub release workflow by removing hotfix-specific logic
- Consolidated the GitHub release creation step to handle both regular and hotfix releases under a single condition.
- Removed the separate hotfix release creation step to streamline the workflow.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ fix: replace UserPanel popover
- Introduced `PanelContentSkeleton` for better user experience during loading states in the UserPanel.
- Updated `UserPanel` to use the new skeleton and adjusted popover content handling.
- Refactored `PanelContent` to use `FC` type for better type safety.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: bump @lobehub/ui dependency to version 4.38.1
- Updated the @lobehub/ui package to the latest version for improved features and bug fixes.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 refactor: remove inset prop from Popover in UserPanel
- Cleaned up the Popover component in UserPanel by removing the unnecessary inset prop for improved clarity and maintainability.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
## 🩹 Hotfix v2.1.29
This PR starts a hotfix release from `main`.
### Release Process
1. ✅ Hotfix branch created from main
2. ✅ Pushed to remote
3. 🔄 Waiting for PR review and merge
4. ⏳ Auto tag + GitHub Release will be created after merge
---
Created by hotfix script
## Summary by Sourcery
Improve main-to-canary sync workflow robustness and tighten hotfix
auto-tagging criteria for release automation.
Enhancements:
- Make the main-to-canary sync workflow attempt direct merges to canary,
falling back to PR creation only when necessary or when conflicts occur,
and handle existing sync PRs more gracefully.
- Refine hotfix detection in the auto-tag workflow by requiring both a
hotfix branch prefix and a valid conventional commit-style PR title
prefix before tagging.
- Update the @lobehub/ui dependency to the latest patch version.
Build:
- Adjust release auto-tag workflow logic to gate hotfix tagging by both
branch naming and PR title format.
CI:
- Enhance GitHub Actions workflow for syncing main to canary with
conflict handling, direct-push optimization, and automated PR
management.
* ✨ feat(desktop): integrate electron-liquid-glass for macOS Tahoe
Add native liquid glass visual effect on macOS 26+ (Tahoe), replacing
vibrancy with Apple's NSGlassEffectView API via electron-liquid-glass.
- Centralize all platform visual effects in WindowThemeManager
- Strip platform props from BrowserWindow options to prevent config leaking
- Remove vibrancy from appBrowsers/WindowTemplate (managed by ThemeManager)
- Add isMacTahoe detection in env.ts and preload
- Fix applyVisualEffects to handle macOS platform symmetrically
* fix(tests): add isMacTahoe detection in Browser test environment
Introduce isMacTahoe flag in the test environment to support macOS Tahoe-specific features. This change enhances the test suite's ability to simulate and validate platform-specific behavior.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat(theme): update liquid glass variant and adjust background color mix for desktop themes
- Changed liquid glass variant from 2 to 15 for improved visual effects.
- Adjusted background color mix percentages for dark and light themes on desktop to enhance visual consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat(theme): adjust background color mix for dark theme on desktop
- Updated the background color mix percentage for the dark theme on desktop from 70% to 90% for improved visual effect consistency.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
Automatic sync
## Summary by Sourcery
Extend database schemas and migrations to support async task inference
tracking and typed generation topics.
New Features:
- Add an inferenceId field to async tasks with a dedicated index for
lookup by inference ID.
- Add a typed generation topic field to distinguish between image and
video topics with a default of image.
Enhancements:
- Update database schema metadata and documentation snapshots to reflect
the new async task and generation topic fields.
Tests:
- Adjust async task and generation topic tests to cover the new
inferenceId and topic type fields.
## Summary
- Optimize the main-to-canary sync workflow to directly merge and push
when there are no conflicts, avoiding unnecessary PR creation
- When merge conflicts exist, fall back to creating a PR for manual
resolution
- Add duplicate PR detection to prevent multiple PRs on the same day
## Test plan
- [ ] Push to main with no conflicts on canary → should auto-merge
without PR
- [ ] Push to main with conflicts on canary → should create PR
- [ ] Trigger workflow twice on same day with conflicts → should not
create duplicate PRs
## Summary by Sourcery
CI:
- Update the sync-main-to-canary workflow to merge main into canary
directly on no-conflict updates, only creating a PR when merge conflicts
occur and avoiding duplicate PRs for the same sync date.
* 🔧 ci: add commit prefix gate for hotfix auto-tag
* 🔧 chore: update ESLint suppressions and dependencies
- Added new ESLint suppressions for various files to address linting issues, including `no-console` and `object-shorthand`.
- Updated ESLint version to 10.0.0 in both root and desktop package.json files.
- Adjusted linting scripts for improved performance and consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: add ESLint support for YAML files in package.json
- Included ESLint fix command for YAML files (*.yml, *.yaml) in the linting scripts section.
- Ensured consistent formatting by adding a newline at the end of the file.
This update enhances linting capabilities for YAML configuration files.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: remove ESLint configuration file
- Deleted the .eslintrc.js file, which contained custom ESLint rules and overrides.
- This change simplifies the project by relying on default ESLint configurations.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
- Add handleShowOpenDialog and handlePickFile IPC methods for Electron
- Create useImageUpload hook for editor image upload with progress
- Refactor ReactImagePlugin config to support handleUpload and onPickFile
- Simplify slash command image insertion by delegating upload to plugin
- Upgrade @lobehub/editor to ^3.16.1
🔧 build: add canary desktop release workflow and channel support
Add automated canary build pipeline triggered by build/fix/style commits
on canary branch, with concurrency control to cancel stale builds.
* add
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat: enhance ChatInput with customizable action bar properties
- Added `actionSize` to `ActionBarContextValue` for flexible action sizing.
- Updated `Action` component to utilize `actionSize` for dynamic sizing.
- Introduced `actionBarStyle` and `leftContent` props in `DesktopChatInput` for custom styling and content.
- Enhanced `SendButton` to accept size from `sendButtonProps`.
- Updated `ChatInput` to support new props for improved layout customization.
- Refactored `Conversation` component to implement compact action bar style and size.
This update improves the flexibility and customization of the ChatInput feature, allowing for better user experience.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat: enhance NavHeader and Copilot Toolbar with layout improvements
- Added `allowShrink` property to Flexbox components in NavHeader for better responsiveness.
- Updated Text component in Copilot Toolbar to include tooltip support for ellipsis overflow, improving user experience.
These changes enhance the layout flexibility and visual consistency across the application.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat: update Conversation and AgentSelectorAction components for improved styling
- Adjusted padding in the compact action bar style for better alignment.
- Enhanced AgentSelectorAction styles with additional border radius for a refined look.
- Simplified title translation in AgentSelectorAction for consistency.
These changes enhance the visual appeal and maintainability of the components within the Copilot feature.
Signed-off-by: Innei <tukon479@gmail.com>
* ✨ feat: update ModelSwitchPanel to improve DropdownMenuPositioner prop usage
- Changed the `hoverTrigger` prop in `DropdownMenuPositioner` from a boolean to a destructured assignment for better clarity and consistency in the component's API.
This update enhances the readability and maintainability of the ModelSwitchPanel component.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
Skip duplicate check only applies to development branches now.
Main and canary branches will always execute E2E tests on every commit.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* 🐛 fix: improve GitHub Copilot auth retry logic
Simplify auth refresh tracking from counter to boolean flag and clear
cached bearer token on 401 to ensure fresh token exchange.
* 🔧 fix: update package.json formatting and import statements in GitHub Copilot provider
Signed-off-by: Innei <tukon479@gmail.com>
* 🐛 fix: refine GitHub Copilot auth refresh logic to check for exchange credential
Update the 401 error handling to refresh the token only if an exchange credential is available, improving the authentication flow.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore(release): bump version to v2.1.27 [skip ci]
* chore: update sync main to canary workflow
* 🐛 fix: update @lobehub/ui version and refactor dynamic import handling (#12260)
* ✨ feat: add hotfix workflow and script for automated hotfix management
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 fix: refactor PR creation command to use execFileSync for improved reliability
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update @lobehub/ui version and refactor dynamic import handling
- Bump @lobehub/ui dependency from ^4.35.0 to ^4.36.2 in package.json.
- Refactor settingsContentToStatic.mts to simplify dynamic import processing by removing business feature checks.
- Add initialize.ts to enable immer's map set functionality.
- Correct import path in layout.tsx from 'initiallize' to 'initialize'.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update @types/react version in package.json
- Bump @types/react dependency from ^19.2.9 to 19.2.14.
- Add @types/react version to overrides section for consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: enhance auto-tag-release workflow for strict semver validation
- Updated regex to match strict semantic versioning format, allowing for optional prerelease and build metadata.
- Added validation step to ensure the version is a valid semver before proceeding with the release process.
Signed-off-by: Innei <tukon479@gmail.com>
* 🗑️ chore: remove defaultSecurityBlacklist test file
- Deleted the test file for DEFAULT_SECURITY_BLACKLIST as it is no longer needed.
- This cleanup helps maintain a more streamlined test suite.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update localization files for multiple languages
- Improved translations in Arabic, Bulgarian, German, English, and Spanish for chat and tool-related strings.
- Enhanced descriptions for various parameters and added new keys for file handling and security warnings.
- Adjusted phrasing for clarity and consistency across languages.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update PR comment script to include Actions Artifacts link
- Modified the PR comment generation script to accept an additional artifactsUrl parameter.
- Updated the comment format to include both Release download and Actions Artifacts links for better accessibility.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
* 🐛 chore(hotfix): bump version to v2.1.28 [skip ci]
* chore: update secrets token
---------
Signed-off-by: Innei <tukon479@gmail.com>
Co-authored-by: rdmclin2 <rdmclin2@gmail.com>
Co-authored-by: Arvin Xu <arvinx@foxmail.com>
Co-authored-by: Innei <i@innei.in>
* ✨ feat: add hotfix workflow and script for automated hotfix management
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 fix: refactor PR creation command to use execFileSync for improved reliability
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update @lobehub/ui version and refactor dynamic import handling
- Bump @lobehub/ui dependency from ^4.35.0 to ^4.36.2 in package.json.
- Refactor settingsContentToStatic.mts to simplify dynamic import processing by removing business feature checks.
- Add initialize.ts to enable immer's map set functionality.
- Correct import path in layout.tsx from 'initiallize' to 'initialize'.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update @types/react version in package.json
- Bump @types/react dependency from ^19.2.9 to 19.2.14.
- Add @types/react version to overrides section for consistency.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: enhance auto-tag-release workflow for strict semver validation
- Updated regex to match strict semantic versioning format, allowing for optional prerelease and build metadata.
- Added validation step to ensure the version is a valid semver before proceeding with the release process.
Signed-off-by: Innei <tukon479@gmail.com>
* 🗑️ chore: remove defaultSecurityBlacklist test file
- Deleted the test file for DEFAULT_SECURITY_BLACKLIST as it is no longer needed.
- This cleanup helps maintain a more streamlined test suite.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update localization files for multiple languages
- Improved translations in Arabic, Bulgarian, German, English, and Spanish for chat and tool-related strings.
- Enhanced descriptions for various parameters and added new keys for file handling and security warnings.
- Adjusted phrasing for clarity and consistency across languages.
Signed-off-by: Innei <tukon479@gmail.com>
* 🔧 chore: update PR comment script to include Actions Artifacts link
- Modified the PR comment generation script to accept an additional artifactsUrl parameter.
- Updated the comment format to include both Release download and Actions Artifacts links for better accessibility.
Signed-off-by: Innei <tukon479@gmail.com>
---------
Signed-off-by: Innei <tukon479@gmail.com>
#### 💻 Change Type
<!-- For change type, change [ ] to [x]. -->
- [ ] ✨ feat
- [ ] 🐛 fix
- [ ] ♻️ refactor
- [ ] 💄 style
- [ ] 👷 build
- [ ] ⚡️ perf
- [ ] ✅ test
- [ ] 📝 docs
- [x] 🔨 chore
#### 🔗 Related Issue
<!-- Link to the issue that is fixed by this PR -->
<!-- Example: Fixes #xxx, Closes #xxx, Related to #xxx -->
#### 🔀 Description of Change
<!-- Thank you for your Pull Request. Please provide a description
above. -->
#### 🧪 How to Test
<!-- Please describe how you tested your changes -->
<!-- For AI features, please include test prompts or scenarios -->
- [ ] Tested locally
- [ ] Added/updated tests
- [ ] No tests needed
#### 📸 Screenshots / Videos
<!-- If this PR includes UI changes, please provide screenshots or
videos -->
| Before | After |
| ------ | ----- |
| ... | ... |
#### 📝 Additional Information
<!-- Add any other context about the Pull Request here. -->
<!-- Breaking changes? Migration guide? Performance impact? -->
## Summary by Sourcery
CI:
- Introduce a new sync-main-to-canary GitHub Actions workflow that
creates an automatic PR from main to canary on pushes to main and remove
the previous sync-main-to-dev workflow.
description: "Agent tracing CLI for inspecting agent execution snapshots. Use when user mentions 'agent-tracing', 'trace', 'snapshot', wants to debug agent execution, inspect LLM calls, view context engine data, or analyze agent steps. Triggers on agent debugging, trace inspection, or execution analysis tasks."
user-invocable: false
---
# Agent Tracing CLI Guide
`@lobechat/agent-tracing` is a zero-config local dev tool that records agent execution snapshots to disk and provides a CLI to inspect them.
## How It Works
In `NODE_ENV=development`, `AgentRuntimeService.executeStep()` automatically records each step to `.agent-tracing/` as partial snapshots. When the operation completes, the partial is finalized into a complete `ExecutionSnapshot` JSON file.
**Data flow**: executeStep loop -> build `StepPresentationData` -> write partial snapshot to disk -> on completion, finalize to `.agent-tracing/{timestamp}_{traceId}.json`
**Context engine capture**: In `RuntimeExecutors.ts`, the `call_llm` executor emits a `context_engine_result` event after `serverMessagesEngine()` processes messages. This event carries the full `contextEngineInput` (DB messages, systemRole, model, knowledge, tools, userMemory, etc.) and the processed `output` messages (the final LLM payload).
3.**Final LLM Payload** — Processed messages after context engine (system date injection, user memory, history truncation, etc.), with `[0]`, `[1]`, ... indices. Use `--msg N` to view full content.
## Integration Points
- **Recording**: `src/server/services/agentRuntime/AgentRuntimeService.ts` — in the `executeStep()` method, after building `stepPresentationData`, writes partial snapshot in dev mode
- **Context engine event**: `src/server/modules/AgentRuntime/RuntimeExecutors.ts` — in `call_llm` executor, after `serverMessagesEngine()` returns, emits `context_engine_result` event
- **Store**: `FileSnapshotStore` reads/writes to `.agent-tracing/` relative to `process.cwd()`
| `@chat-adapter/state-redis` | Redis state (production) |
| `@chat-adapter/state-ioredis` | ioredis state (alternative) |
| `@chat-adapter/state-memory` | In-memory state (development) |
## Changesets (Release Flow)
This monorepo uses [Changesets](https://github.com/changesets/changesets) for versioning and changelogs. Every PR that changes a package's behavior must include a changeset.
# → choose bump type: patch (fixes), minor (features), major (breaking)
# → write a short summary for the CHANGELOG
```
This creates a file in `.changeset/` — commit it with the PR. When merged to `main`, the Changesets GitHub Action opens a "Version Packages" PR to bump versions and update CHANGELOGs. Merging that PR publishes to npm.
## Webhook setup
Each adapter exposes a webhook handler via `bot.webhooks.{platform}`. Wire these to your HTTP framework's routes (e.g. Next.js API routes, Hono, Express).
description: LobeHub CLI (@lobehub/cli) development guide. Use when working on CLI commands, adding new subcommands, fixing CLI bugs, or understanding CLI architecture. Triggers on CLI development, command implementation, or `lh` command questions.
disable-model-invocation: true
---
# LobeHub CLI Development Guide
## Overview
LobeHub CLI (`@lobehub/cli`) is a command-line tool for managing and interacting with LobeHub services. Built with Commander.js + TypeScript.
- **Package**: `apps/cli/`
- **Entry**: `apps/cli/src/index.ts`
- **Binaries**: `lh`, `lobe`, `lobehub` (all aliases for the same CLI)
- **Build**: tsup
- **Runtime**: Node.js / Bun
## Architecture
```
apps/cli/src/
├── index.ts # Entry point, registers all commands
The base directory (`~/.lobehub/`) can be overridden with the `LOBEHUB_CLI_HOME` env var (e.g. `LOBEHUB_CLI_HOME=.lobehub-dev` for dev mode isolation).
## Key Dependencies
-`commander` - CLI framework
-`@trpc/client` + `superjson` - Type-safe API client
-`src/server/routers/lambda/video/index.ts` — video creation (uses `authedProcedure` + `serverDatabase`)
-`src/server/routers/lambda/generation.ts` — status checking
**Note**: Image/video routes do NOT use the `keyVaults` middleware — they read API keys from the database via `initModelRuntimeFromDB` or `createAsyncCaller`.
Manage knowledge bases for RAG (Retrieval-Augmented Generation). Supports directory tree structure with folders, documents, and file uploads.
**Source**: `apps/cli/src/commands/kb.ts`
### `lh kb list`
```bash
lh kb list [--json [fields]]
```
**Table columns**: ID, NAME, DESCRIPTION, UPDATED
### `lh kb view <id>`
```bash
lh kb view [fields]] < id > [--json
```
**Displays**: Name, description, full directory tree with all files and documents (recursively fetched). Shows indented tree structure with item type (File/Doc), file type, and size.
**API**: Uses `file.getKnowledgeItems` to recursively fetch items. Folders (`custom/folder` fileType) are traversed in parallel via `Promise.all` for performance.
description: Database migration guide. Use when generating migrations, writing migration SQL, or modifying database schemas. Triggers on migration generation, schema changes, or idempotent SQL questions.
This generates an empty SQL file and properly updates `_journal.json` and snapshot. Then edit the generated SQL file to add your custom SQL:
```sql
-- Custom SQL migration file, put your code below! --
CREATEEXTENSIONIFNOTEXISTSpg_search;
```
**Do NOT manually create migration files or edit `_journal.json`** — always use `drizzle-kit generate` to ensure correct journal entries and snapshots.
description: Internationalization guide using react-i18next. Use when adding translations, creating i18n keys, or working with localized text in React components (.tsx files). Triggers on translation tasks, locale management, or i18n implementation.
You are **LobeHub’s English UI Copy & Microcopy Specialist**.
LobeHub is an assistant workspace: users can create **Agents** and **Agent Teams** so people↔agents and agent↔agent can collaborate to improve productivity in work and life.
Brand vibe: youthful, friendly, modern on the surface; professional, reliable, productivity- and controllability-first underneath. Overall style reference: Notion / Figma / Apple / Discord / OpenAI / Gemini — clear, restrained, trustworthy, human but not cheesy.
Product slogan: **For Collaborative Agents**. Your copy must continuously reinforce that LobeHub is not about “generation”, but about a **collaborative agent system**: shareable context, traceable outcomes, replayable runs, evolvable setup, and **human-in-the-loop**.
---
## 1) Fixed Terminology (must follow)
Use **exactly** these English terms across the product. Do not mix synonyms for the same concept.
- 空间: **Workspace**
- 助理: **Agent**
- 群组: **Group**
- 上下文: **Context**
- 记忆: **Memory**
- 连接器: **Integration**
- 技能 /tool/plugin: **Skill**
- 助理档案: **Agent Profile**
- 话题: **Topic**
- 文稿: **Page**
- 社区: **Community**
- 资源: **Resource**
- 库: **Library**
- MCP: **MCP**
- 模型服务商: **Provider**
Terminology rule: one concept = one term site-wide. Never alternate with “bot/assistant/AI agent/team/workspace” variations.
---
## 2) Your Responsibilities
- Improve, rewrite, or create from scratch any **English UI copy**: titles, buttons, form labels/help text, placeholders, onboarding, empty states, toasts, modals, errors, permission prompts, settings, creation/run flows, collaboration and Agent Team pages, etc.
- Copy must work for both:
- general users (immediately understandable)
- power users (not childish)
- It must fit both playful and serious contexts.
- Avoid overclaiming AI capabilities; add human warmth at the right moments.
---
## 3) The Three Brand Principles (bake into structure & wording)
- **Create**: create an Agent in one sentence; clear next step from idea → usable.
- **Collaborate**: multi-agent collaboration; align info and outputs; share Context (controlled, manageable).
- **Evolve**: Agents can remember preferences **only with user consent**; become more helpful over time; emphasize explainability, settings, and replay.
2.**Layered messaging (single version for everyone)**:
- Main line: simple and actionable
- Optional second line: more precise / technical / boundary-setting (subtitle, helper text, tooltip, collapsible)
- Do not produce “Pro vs Lite” variants; one main + optional detail
3.**Use terms sparingly but correctly**: prefer plain words (“connect”, “run”, “context”) unless a technical term is necessary. When it is, add a plain-English explanation.
4.**Consistency**: keep verbs consistent across similar actions (Create / Connect / Run / Pause / Retry / View details / Clear Memory).
5.**Actionable**: every message tells the user what to do next. Avoid generic “OK/Cancel”; use specific actions.
- Retry / View details / Go to Settings / Contact support / Copy logs
Never blame the user. Don’t show only an error code; put codes in “Details” if needed.
For data/security/billing: be neutral, thorough, and respectful—warmth comes from clarity, not emotion.
---
## 7) Your Special Task: CN i18n → EN (localized, length-aware)
You translate **raw Chinese i18n strings into English** for LobeHub.
Requirements:
- Prefer **localized**, product-native English over literal translation.
- Do **not** chase perfect one-to-one consistency if a more natural UI phrase reads better.
- Keep the **character length difference small**; try to make the English string **roughly the same visual length** as the Chinese source (avoid overly long expansions).
- Preserve meaning, tone, and actionability; keep verbs consistent with LobeHub’s UI patterns.
- If space is tight (buttons, tabs, toasts), prioritize: **verb + object**, drop optional words first.
- If the Chinese includes placeholders/variables, preserve them exactly (e.g., `{name}`, `{{count}}`, `%s`) and keep word order sensible.
- Keep capitalization consistent with UI norms (buttons/title case only when appropriate).
Output format when translating:
- Provide **English only**, unless asked otherwise.
- If multiple options are useful, give **one best option** + **one shorter fallback** (only when length constraints are likely).
---
You always optimize for: **clarity, control, collaboration, replayability, and human-in-the-loop**—in a modern, restrained, trustworthy English voice.
## 8) Product Introduction
LobeHub, we define agents as the unit of work. We’re building the first human–agent co-working, co-evolving network.
It is a fundamentally new, agent-first experience.You can pop up your agents or agent teams while writing, while chatting -- from ideation, to execution, to delivery -- across your entire workflow. Here, agents are not just tools, but always-on units of work.
### Create
It is a unified workspace where you can find, build, or team up with agent co-workers.Simply describe what you need, and Lobe AI will generate the prompts and assemble the right set of tools to compose your agent.In agent marketplace, you can easily discover agents created by others,use them instantly,and flexibly swap in your own tools.
### Collaboration
You can also spin up agent groups to handle system-level projects, even like building a quant team.
Within this group, some agents track signals and mine quantitative factors in real time, some manage risk, some execute orders, collaborate together to make money.
We’re defining how humans and agents work together. Now we support agent-to-agent collaboration, and we continue to scale new forms of collaboration networks — from agents collaborating across teams, to multiple humans working through the same agent.
### Evolve
Humans and agents should co-evolve, and we design this paradigm from both technical and economic perspectives. Our memory system is structured and editable,enabling models to better align with individual users, while allowing users to provide cleaner reward signals for continual learning. Agent evolution is powered by shared human intelligence through our agent marketplace. Creators are rewarded, and agents, in turn, pay for human intelligence.
Is AI replacing humans? No.
We’re building a human–agent co-working, co-evolving society.
Agents become smarter and more personalized through human intelligence, taking on repetitive and exhausting work — so humans can focus on fewer, but more important things: taste, and creation.
description: Complete project architecture and structure guide. Use when exploring the codebase, understanding project organization, finding files, or needing comprehensive architectural context. Triggers on architecture questions, directory navigation, or project overview needs.
description: OpenResponses API compliance testing. Use when testing the Response API endpoint, running compliance tests, or debugging Response API schema issues. Triggers on 'compliance', 'response api test', 'openresponses test'.
---
# OpenResponses Compliance Test
Run the official OpenResponses compliance test suite against the local (or remote) Response API endpoint.
## Quick Start
```bash
# From the openapi package directory
cd lobehub/packages/openapi
# Run all tests (dev mode, localhost:3010)
APP_URL=http://localhost:3010 bun run test:response-compliance -- \
| `APP_URL` | `http://localhost:3010` | Server base URL (auto-appends `/api/v1`) |
| `API_KEY` | — | API key (alternative to `--api-key` flag) |
## How It Works
The script (`lobehub/packages/openapi/scripts/compliance-test.sh`) clones the official [openresponses/openresponses](https://github.com/openresponses/openresponses) repo into `scripts/openresponses-compliance/` (gitignored) and runs its CLI test runner. First run clones; subsequent runs update from upstream.
## Debugging Failures
1. Run with `-v` to see full request/response payloads
2. Common failure patterns:
- **"Failed to parse JSON"**: Auth failed, server returned HTML redirect
- **"Response has no output items"**: LLM execution not yet implemented
- **"Expected number, received null"**: Missing required field in response schema
- **"Invalid input"**: Zod validation on response schema — check field format
description: SPA route and feature structure. Use when adding or modifying SPA routes in src/routes, defining new route segments, or moving route logic into src/features. Covers how to keep routes thin and how to divide files between routes and features.
---
# SPA Routes and Features Guide
SPA structure:
- **`src/spa/`** – Entry points (`entry.web.tsx`, `entry.mobile.tsx`, `entry.desktop.tsx`) and router config (`router/`). Router lives here to avoid confusion with `src/routes/`.
- **`src/routes/`** – Page segments only (roots).
- **`src/features/`** – Business logic and UI by domain.
This project uses a **roots vs features** split: `src/routes/` only holds page segments; business logic and UI live in `src/features/` by domain.
## When to Use This Skill
- Adding a new SPA route or route segment
- Defining or refactoring layout/page files under `src/routes/`
- Moving route-specific components or logic into `src/features/`
- Deciding where to put a new component (route folder vs feature folder)
| `_layout/index.tsx` or `layout.tsx` | Layout for this segment: wrap with `<Outlet />`, optional shell (e.g. sidebar + main). Should be thin: prefer re-exporting or composing from `@/features/*`. |
| `index.tsx` or `page.tsx` | Page entry for this segment. Only import from features and render; no business logic. |
| `[param]/index.tsx` (e.g. `[id]`, `[cronId]`) | Dynamic segment page. Same rule: thin, delegate to features. |
**Rule:** Route files should only **import and compose**. No new `features/` folders or heavy components inside `src/routes/`.
---
## 2. What Belongs in `src/features/`
Put **domain-oriented** UI and logic here:
- Layout building blocks: sidebars, headers, body panels, drawers
- Hooks and store usage for that domain
- Domain-specific forms, lists, modals, etc.
Organize by **domain** (e.g. `Pages`, `Home`, `Agent`, `PageEditor`), not by route path. One route can use several features; one feature can be used by several routes.
Each feature should:
- Live under `src/features/<FeatureName>/`
- Export a clear public API via `index.ts` or `index.tsx`
- Use `@/features/<FeatureName>/...` for internal imports when needed
---
## 3. How to Add a New SPA Route
1.**Choose the route group**
-`(main)/`– desktop main app
-`(mobile)/`– mobile
-`(desktop)/`– Electron-specific
-`onboarding/`, `share/`– special flows
2.**Create only segment files under `src/routes/`**
- e.g. `src/routes/(main)/my-feature/_layout/index.tsx` and `src/routes/(main)/my-feature/index.tsx` (and optional `[id]/index.tsx`).
3.**Implement layout and page content in `src/features/`**
- Create or reuse a domain (e.g. `src/features/MyFeature/`).
- Put layout (sidebar, header, body) and page UI there; export from the feature’s `index`.
4.**Keep route files thin**
- Layout: `export { default } from '@/features/MyFeature/MyLayout'` or compose a few feature components + `<Outlet />`.
- Page: import from `@/features/MyFeature` (or a specific subpath) and render; no business logic in the route file.
5.**Register the route**
- Add the segment to `src/spa/router/desktopRouter.config.tsx` (or the right router config) with `dynamicElement` / `dynamicLayout` pointing at the new route paths (e.g. `@/routes/(main)/my-feature`).
---
## 4. How to Divide Files (route vs feature)
| Question | Put in `src/routes/` | Put in `src/features/` |
| Is it the route’s layout wrapper or page entry? | Yes –`_layout/index.tsx`, `index.tsx`, `[id]/index.tsx` | No |
| Does it contain business logic or non-trivial UI? | No | Yes – under the right domain |
| Is it a reusable layout piece (sidebar, header, body)? | No | Yes |
| Is it a hook, store usage, or domain logic? | No | Yes |
| Is it only re-exporting or composing feature components? | Yes | No |
**Examples**
- **Route (thin):**\
`src/routes/(main)/page/_layout/index.tsx` → `export { default } from '@/features/Pages/PageLayout'`
- **Feature (real implementation):**\
`src/features/Pages/PageLayout/` → Sidebar, DataSync, Body, Header, styles, etc.
- **Route (thin):**\
`src/routes/(main)/page/index.tsx` → Import `PageTitle`, `PageExplorerPlaceholder` from `@/features/Pages` and `@/features/PageExplorer`; render with `<PageTitle />` and placeholder.
- **Feature:**\
Page list, actions, drawers, and hooks live under `src/features/Pages/`.
---
## 5. Progressive Migration (existing code)
We are migrating existing routes to this structure step by step:
- **Phase 1 (done):** `/page` route – segment files in `src/routes/(main)/page/`, implementation in `src/features/Pages/`.
When touching an old route that still has logic or `features/` inside `src/routes/`:
1. Prefer adding **new** code in `src/features/<Domain>/` and importing from routes.
2. For larger refactors, move existing route-only logic into the right feature and then thin out the route files (re-export or compose from features).
3. Use `git mv` when moving files so history is preserved.
---
## 6. Reference Structure (after Phase 1)
**Route (thin):**
```
src/routes/(main)/page/
├── _layout/index.tsx → re-export or compose from @/features/Pages/PageLayout
├── index.tsx → import from @/features/Pages, @/features/PageExplorer
└── [id]/index.tsx → import from @/features/Pages, @/features/PageExplorer
```
**Feature (implementation):**
```
src/features/Pages/
├── index.ts → export PageLayout, PageTitle
├── PageTitle.tsx
└── PageLayout/
├── index.tsx → Sidebar + Outlet + DataSync
├── DataSync.tsx
├── Sidebar.tsx
├── style.ts
├── Body/ → list, actions, drawer, etc.
└── Header/ → breadcrumb, add button, etc.
```
Router config continues to point at **route** paths (e.g. `@/routes/(main)/page`, `@/routes/(main)/page/_layout`); route files then delegate to features.
description: Zustand store data structure patterns for LobeHub. Covers List vs Detail data structures, Map + Reducer patterns, type definitions, and when to use each pattern. Use when designing store state, choosing data structures, or implementing list/detail pages.
---
# LobeHub Store Data Structures
This guide covers how to structure data in Zustand stores for optimal performance and user experience.
## Core Principles
### ✅ DO
1.**Separate List and Detail** - Use different structures for list pages and detail pages
2.**Use Map for Details** - Cache multiple detail pages with `Record<string, Detail>`
3.**Use Array for Lists** - Simple arrays for list display
4.**Types from @lobechat/types** - Never use `@lobechat/database` types in stores
5.**Distinguish List and Detail types** - List types may have computed UI fields
### ❌ DON'T
1.**Don't use single detail object** - Can't cache multiple pages
2.**Don't mix List and Detail types** - They have different purposes
3.**Don't use database types** - Use types from `@lobechat/types`
4.**Don't use Map for lists** - Simple arrays are sufficient
---
## Type Definitions
Types should be organized by entity in separate files:
```
@lobechat/types/src/eval/
├── benchmark.ts # Benchmark types
├── agentEvalDataset.ts # Dataset types
├── agentEvalRun.ts # Run types
└── index.ts # Re-exports
```
### Example: Benchmark Types
```typescript
// packages/types/src/eval/benchmark.ts
importtype{EvalBenchmarkRubric}from'./rubric';
// ============================================
// Detail Type - Full entity (for detail pages)
// ============================================
/**
* Full benchmark entity with all fields including heavy data
*/
exportinterfaceAgentEvalBenchmark{
createdAt: Date;
description?: string|null;
id: string;
identifier: string;
isSystem: boolean;
metadata?: Record<string,unknown>|null;
name: string;
referenceUrl?: string|null;
rubrics: EvalBenchmarkRubric[];// Heavy field
updatedAt: Date;
}
// ============================================
// List Type - Lightweight (for list display)
// ============================================
/**
* Lightweight benchmark item - excludes heavy fields
* May include computed statistics for UI
*/
exportinterfaceAgentEvalBenchmarkListItem{
createdAt: Date;
description?: string|null;
id: string;
identifier: string;
isSystem: boolean;
name: string;
// Note: rubrics NOT included (heavy field)
// Computed statistics for UI display
datasetCount?: number;
runCount?: number;
testCaseCount?: number;
}
```
### Example: Document Types (with heavy content)
```typescript
// packages/types/src/document.ts
/**
* Full document entity - includes heavy content fields
*/
exportinterfaceDocument{
id: string;
title: string;
description?: string;
content: string;// Heavy field - full markdown content
editorData: any;// Heavy field - editor state
metadata?: Record<string,unknown>;
createdAt: Date;
updatedAt: Date;
}
/**
* Lightweight document item - excludes heavy content
*/
exportinterfaceDocumentListItem{
id: string;
title: string;
description?: string;
// Note: content and editorData NOT included
createdAt: Date;
updatedAt: Date;
// Computed statistics
wordCount?: number;
lastEditedBy?: string;
}
```
**Key Points:**
- **Detail types** include ALL fields from database (full entity)
- **List types** are **subsets** that exclude heavy/large fields
- List types may add computed statistics for UI (e.g., `testCaseCount`)
- **Each entity gets its own file** (not mixed together)
- **All types** exported from `@lobechat/types`, NOT `@lobechat/database`
**Heavy fields to exclude from List:**
- Large text content (`content`, `editorData`, `fullDescription`)
description: Testing guide using Vitest. Use when writing tests (.test.ts, .test.tsx), fixing failing tests, improving test coverage, or debugging test issues. Triggers on test creation, test debugging, mock setup, or test-related questions.
---
# LobeChat Testing Guide
# LobeHub Testing Guide
## Quick Reference
@@ -83,6 +83,34 @@ See `references/` for specific testing scenarios:
When tests fail due to implementation changes (not bugs), evaluate before blindly fixing:
### Keep & Fix (update test data/assertions)
- **Behavior tests**: Tests that verify _what_ the code does (output, side effects, user-visible behavior). Just update mock data formats or expected values.
- Example: Tool data structure changed from `{ name }` to `{ function: { name } }` → update mock data
- Example: Output format changed from `Current date: YYYY-MM-DD` to `Current date: YYYY-MM-DD (TZ)` → update expected string
### Delete (over-specified, low value)
- **Param-forwarding tests**: Tests that assert exact internal function call arguments (e.g., `expect(internalFn).toHaveBeenCalledWith(expect.objectContaining({ exact params }))`) — these break on every refactor and duplicate what behavior tests already cover.
- **Implementation-coupled tests**: Tests that verify _how_ the code works internally rather than _what_ it produces. If a higher-level test already covers the same behavior, the low-level test adds maintenance cost without coverage gain.
### Decision Checklist
1. Does the test verify **externally observable behavior** (API response, DB write, rendered output)? → **Keep**
2. Does the test only verify **internal wiring** (which function receives which params)? → Check if a behavior test already covers it. If yes → **Delete**
3. Is the same behavior already tested at a **higher integration level**? → Delete the lower-level duplicate
4. Would the test break again on the **next routine refactor**? → Consider raising to integration level or deleting
### When Writing New Tests
- Prefer **integration-level assertions** (verify final output) over **white-box assertions** (verify internal calls)
- Use `expect.objectContaining` only for stable, public-facing contracts — not for internal param shapes that change with refactors
- Mock at boundaries (DB, network, external services), not between internal modules
## Common Issues
1.**Module pollution**: Use `vi.resetModules()` when tests fail mysteriously
LobeChat Desktop uses Vitest as the test framework. Controller unit tests should be placed in the `__tests__` directory adjacent to the controller file, named with the original controller filename plus `.test.ts`.
LobeHub Desktop uses Vitest as the test framework. Controller unit tests should be placed in the `__tests__` directory adjacent to the controller file, named with the original controller filename plus `.test.ts`.
echo"export { POST } from 'lobehub/src/app/(backend)/api/workflows/feature-name/layer/route';" > lobehub-cloud/src/app/\(backend\)/api/workflows/feature-name/layer/route.ts
```
### Type Errors After Moving to Lobehub
**Cause**: Cloud-specific types or services used in lobehub code
**Solution**:
1. Extract cloud-specific logic to cloud-only wrapper
2. Use dependency injection for services
3. Define generic interfaces in lobehub
---
## Related Documentation
- [SKILL.md](../SKILL.md) - Standard workflow patterns
description: React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
license: MIT
metadata:
author: vercel
version: '1.0.0'
---
# Vercel React Best Practices
Comprehensive performance optimization guide for React and Next.js applications, maintained by Vercel. Contains 45 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.
## When to Apply
Reference these guidelines when:
- Writing new React components or Next.js pages
- Implementing data fetching (client or server-side)
`useEffectEvent` provides a cleaner API for the same pattern: it creates a stable function reference that always calls the latest version of the handler.
Import directly from source files instead of barrel files to avoid loading thousands of unused modules. **Barrel files** are entry points that re-export multiple modules (e.g., `index.js` that does `export * from './module'`).
Popular icon and component libraries can have **up to 10,000 re-exports** in their entry file. For many React packages, **it takes 200-800ms just to import them**, affecting both development speed and production cold starts.
**Why tree-shaking doesn't help:** When a library is marked as external (not bundled), the bundler can't optimize it. If you bundle it to enable tree-shaking, builds become substantially slower analyzing the entire module graph.
## Use Passive Event Listeners for Scrolling Performance
Add `{ passive: true }` to touch and wheel event listeners to enable immediate scrolling. Browsers normally wait for listeners to finish to check if `preventDefault()` is called, causing scroll delay.
Avoid interleaving style writes with layout reads. When you read a layout property (like `offsetWidth`, `getBoundingClientRect()`, or `getComputedStyle()`) between style changes, the browser is forced to trigger a synchronous reflow.
**Incorrect (interleaved reads and writes force reflows):**
Prefer CSS classes over inline styles when possible. CSS files are cached by the browser, and classes provide better separation of concerns and are easier to maintain.
When comparing arrays with expensive operations (sorting, deep equality, serialization), check lengths first. If lengths differ, the arrays cannot be equal.
In real-world applications, this optimization is especially valuable when the comparison runs in hot paths (event handlers, render loops).
Two O(n log n) sorts run even when `current.length` is 5 and `original.length` is 100. There is also overhead of joining the arrays and comparing the strings.
Single pass through the array, no copying, no sorting.
**Alternative (Math.min/Math.max for small arrays):**
```typescript
constnumbers=[5,2,8,1,9];
constmin=Math.min(...numbers);
constmax=Math.max(...numbers);
```
This works for small arrays, but can be slower or just throw an error for very large arrays due to spread operator limitations. Maximal array length is approximately 124000 in Chrome 143 and 638000 in Safari 18; exact numbers may vary - see [the fiddle](https://jsfiddle.net/qw1jabsx/4/). Use the loop approach for reliability.
## Use toSorted() Instead of sort() for Immutability
`.sort()` mutates the array in place, which can cause bugs with React state and props. Use `.toSorted()` to create a new sorted array without mutation.
This applies to all CSS transforms and transitions (`transform`, `opacity`, `translate`, `scale`, `rotate`). The wrapper div allows browsers to use GPU acceleration for smoother animations.
Use explicit ternary operators (`? :`) instead of `&&` for conditional rendering when the condition can be `0`, `NaN`, or other falsy values that render.
This is especially helpful for large and static SVG nodes, which can be expensive to recreate on every render.
**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, the compiler automatically hoists static JSX elements and optimizes component re-renders, making manual hoisting unnecessary.
When rendering content that depends on client-side storage (localStorage, cookies), avoid both SSR breakage and post-hydration flickering by injecting a synchronous script that updates the DOM before React hydrates.
var theme = localStorage.getItem('theme') || 'light';
var el = document.getElementById('theme-wrapper');
if (el) el.className = theme;
} catch (e) {}
})();
`,
}}
/>
</>
);
}
```
The inline script executes synchronously before showing the element, ensuring the DOM already has the correct value. No flickering, no hydration mismatch.
This pattern is especially useful for theme toggles, user preferences, authentication states, and any client-only data that should render immediately without flashing default values.
Reduce SVG coordinate precision to decrease file size. The optimal precision depends on the viewBox size, but in general reducing precision should be considered.
**Incorrect (excessive precision):**
```svg
<pathd="M 10.293847 20.847362 L 30.938472 40.192837"/>
When updating state based on the current state value, use the functional update form of setState instead of directly referencing the state variable. This prevents stale closures, eliminates unnecessary dependencies, and creates stable callback references.
**Incorrect (requires state as dependency):**
```tsx
functionTodoList() {
const[items,setItems]=useState(initialItems);
// Callback must depend on items, recreated on every items change
constaddItems=useCallback(
(newItems: Item[])=>{
setItems([...items,...newItems]);
},
[items],
);// ❌ items dependency causes recreations
// Risk of stale closure if dependency is forgotten
constremoveItem=useCallback((id: string)=>{
setItems(items.filter((item)=>item.id!==id));
},[]);// ❌ Missing items dependency - will use stale items!
The first callback is recreated every time `items` changes, which can cause child components to re-render unnecessarily. The second callback has a stale closure bug—it will always reference the initial `items` value.
**Correct (stable callbacks, no stale closures):**
```tsx
functionTodoList() {
const[items,setItems]=useState(initialItems);
// Stable callback, never recreated
constaddItems=useCallback((newItems: Item[])=>{
setItems((curr)=>[...curr,...newItems]);
},[]);// ✅ No dependencies needed
// Always uses latest state, no stale closure risk
1.**Stable callback references** - Callbacks don't need to be recreated when state changes
2.**No stale closures** - Always operates on the latest state value
3.**Fewer dependencies** - Simplifies dependency arrays and reduces memory leaks
4.**Prevents bugs** - Eliminates the most common source of React closure bugs
**When to use functional updates:**
- Any setState that depends on the current state value
- Inside useCallback/useMemo when state is needed
- Event handlers that reference state
- Async operations that update state
**When direct updates are fine:**
- Setting state to a static value: `setCount(0)`
- Setting state from props/arguments only: `setName(newName)`
- State doesn't depend on previous value
**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, the compiler can automatically optimize some cases, but functional updates are still recommended for correctness and to prevent stale closure bugs.
Pass a function to `useState` for expensive initial values. Without the function form, the initializer runs on every render even though the value is only used once.
**Incorrect (runs on every render):**
```tsx
functionFilteredList({items}:{items: Item[]}){
// buildSearchIndex() runs on EVERY render, even after initialization
Use lazy initialization when computing initial values from localStorage/sessionStorage, building data structures (indexes, maps), reading from the DOM, or performing heavy transformations.
For simple primitives (`useState(0)`), direct references (`useState(props.value)`), or cheap literals (`useState({})`), the function form is unnecessary.
**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, manual memoization with `memo()` and `useMemo()` is not necessary. The compiler automatically optimizes re-renders.
Use Next.js's `after()` to schedule work that should execute after a response is sent. This prevents logging, analytics, and other side effects from blocking the response.
`React.cache()` only works within one request. For data shared across sequential requests (user clicks button A then button B), use an LRU cache.
**Implementation:**
```typescript
import{LRUCache}from'lru-cache';
constcache=newLRUCache<string,any>({
max: 1000,
ttl: 5*60*1000,// 5 minutes
});
exportasyncfunctiongetUser(id: string){
constcached=cache.get(id);
if(cached)returncached;
constuser=awaitdb.user.findUnique({where:{id}});
cache.set(id,user);
returnuser;
}
// Request 1: DB query, result cached
// Request 2: cache hit, no DB query
```
Use when sequential user actions hit multiple endpoints needing the same data within seconds.
**With Vercel's [Fluid Compute](https://vercel.com/docs/fluid-compute):** LRU caching is especially effective because multiple concurrent requests can share the same function instance and cache. This means the cache persists across requests without needing external storage like Redis.
**In traditional serverless:** Each invocation runs in isolation, so consider Redis for cross-process caching.
If you must pass objects, pass the same reference:
```typescript
constparams={uid: 1};
getUser(params);// Query runs
getUser(params);// Cache hit (same reference)
```
**Next.js-Specific Note:**
In Next.js, the `fetch` API is automatically extended with request memoization. Requests with the same URL and options are automatically deduplicated within a single request, so you don't need `React.cache()` for `fetch` calls. However, `React.cache()` is still essential for other async tasks:
- Database queries (Prisma, Drizzle, etc.)
- Heavy computations
- Authentication checks
- File system operations
- Any non-fetch async work
Use `React.cache()` to deduplicate these operations across your component tree.
The React Server/Client boundary serializes all object properties into strings and embeds them in the HTML response and subsequent RSC requests. This serialized data directly impacts page weight and load time, so **size matters a lot**. Only pass fields that the client actually uses.
description: "Version release workflow. Use when the user mentions 'release', 'hotfix', 'version upgrade', 'weekly release', or '发版'/'发布'/'小班车'. Provides guides for Minor Release and Patch Release workflows."
---
# Version Release Workflow
## Overview
The primary development branch is **canary**. All day-to-day development happens on canary. When releasing, canary is merged into main. After merge, `auto-tag-release.yml` automatically handles tagging, version bumping, creating a GitHub Release, and syncing back to the canary branch.
Only two release types are used in practice (major releases are extremely rare and can be ignored):
| Type | Use Case | Frequency | Source Branch | PR Title Format | Version |
| Minor | Feature iteration release | \~Every 4 weeks | canary | `🚀 release: v{x.y.0}` | Manually set |
| Patch | Weekly release / hotfix / model / DB migration | \~Weekly or as needed | canary or main | Custom (e.g. `🚀 release: 20260222`) | Auto patch +1 |
## Minor Release Workflow
Used to publish a new minor version (e.g. v2.2.0), roughly every 4 weeks.
### Steps
1.**Create a release branch from canary**
```bash
git checkout canary
git pull origin canary
git checkout -b release/v{version}
git push -u origin release/v{version}
```
2.**Determine the version number** — Read the current version from `package.json` and compute the next minor version (e.g. 2.1.x → 2.2.0)
3.**Create a PR to main**
```bash
gh pr create \
--title "🚀 release: v{version}"\
--base main \
--head release/v{version}\
--body "## 📦 Release v{version} ..."
```
> \[!IMPORTANT]: The PR title must strictly match the `🚀 release: v{x.y.z}` format. CI uses a regex on this title to determine the exact version number.
4.**Automatic trigger after merge**: auto-tag-release detects the title format and uses the version number from the title to complete the release.
### Scripts
```bash
bun run release:branch # Interactive
bun run release:branch --minor # Directly specify minor
```
## Patch Release Workflow
Version number is automatically bumped by patch +1. There are 4 common scenarios:
| New Model Launch | canary | Community PR merged directly | New model launch, triggered by PR title prefix |
| DB Schema Migration | main | `release/db-migration-{name}` | Database migration, requires dedicated changelog |
All scenarios auto-bump patch +1. Patch PR titles do not need a version number. See `reference/patch-release-scenarios.md` for detailed steps per scenario.
4.**Dispatch sync-main-to-canary** — syncs main back to the canary branch
## Claude Action Guide
When the user requests a release:
### Minor Release
1. Read `package.json` to get the current version and compute the next minor version
2. Create a `release/v{version}` branch from canary
3. Push and create a PR — **title must be `🚀 release: v{version}`**
4. Inform the user that merging the PR will automatically trigger the release
### Precheck
Before creating the release branch, verify the source branch:
- **Weekly Release** (`release/weekly-*`): must branch from `canary`
- **All other release/hotfix branches**: must branch from `main` — run `git merge-base --is-ancestor main <branch> && echo OK` to confirm
- If the branch is based on the wrong source, delete and recreate from the correct base
### Patch Release
Choose the appropriate workflow based on the scenario (see `reference/patch-release-scenarios.md`):
- **Weekly Release**: Create a `release/weekly-{YYYYMMDD}` branch from canary, scan `git log main..canary` to write the changelog, title like `🚀 release: 20260222`
- **Bug Hotfix**: Create a `hotfix/` branch from main, use a gitmoji prefix title (e.g. `🐛 fix: ...`)
- **New Model Launch**: Community PRs trigger automatically via title prefix (`feat` / `style`), no extra steps needed
- **DB Migration**: Create a `release/db-migration-{name}` branch from main, cherry-pick migration commits, write a dedicated migration changelog
### Important Notes
- **Do NOT manually modify the version in package.json** — CI will auto-bump it
- **Do NOT manually create tags** — CI will create them automatically
- The Minor Release PR title format is a hard requirement — incorrect format will not use the specified version number
- Patch PRs do not need a version number — CI auto-bumps patch +1
- All release PRs must include a user-facing changelog
## Changelog Writing Guidelines
All release PR bodies (both Minor and Patch) must include a user-facing changelog. Scan changes via `git log main..canary --oneline` or `git diff main...canary --stat`, then write following the format below.
### Format Reference
- Weekly Release: See `reference/changelog-example/weekly-release.md`
- DB Migration: See `reference/changelog-example/db-migration.md`
### Writing Tips
- **User-facing**: Describe changes that users can perceive, not internal implementation details
- **Clear categories**: Group by features, models/providers, desktop, stability/fixes, etc.
- **Highlight key items**: Use `**bold**` for important feature names
- **Credit contributors**: Collect all committers via `git log` and list alphabetically
- **Flexible categories**: Choose categories based on actual changes — no need to force-fit all categories
A real-world changelog reference for weekly patch release PR bodies.
---
This release includes **82 commits** , Key updates are below.
### New Features and Enhancements
- Added **Agent Benchmark** support for more systematic agent performance evaluation.
- Introduced the **video generation** feature end-to-end, including entry points, sidebar "new" badge support, and skeleton loading for topic switching.
- Expanded memory capabilities: support for memory effort/tool permission configuration and improved timeout calculation for memory analysis tasks.
- Added desktop editor support for image upload via file picker.
### Models and Provider Expansion
- Added a new provider: **Straico**.
- Added/updated support for:
- Claude Sonnet 4.6
- Gemini 3.1 Pro Preview
- Qwen3.5 series
- Grok Imagine (`grok-imagine-image`)
- MiniMax 2.5
- Added related i18n copy and model parameter adaptations.
description: Zustand state management guide. Use when working with store code (src/store/**), implementing actions, managing state, or creating slices. Triggers on Zustand store development, state management questions, or action implementation.
// FIXME: Linting error in src/app/[variants]/(main)/chat/features/Migration/DBReader.ts, the fundamental solution should be upgrading typescript-eslint
# Priority 2: fallback to PR title prefix gate (legacy behavior).
if echo "$PR_TITLE" | grep -qiE '^(💄[[:space:]]*)?style(\(.+\))?:|^(✨[[:space:]]*)?feat(\(.+\))?:|^(🐛[[:space:]]*)?fix(\(.+\))?:|^(♻️[[:space:]]*)?refactor(\(.+\))?:|^((🐛|🩹)[[:space:]]*)?hotfix(\(.+\))?:|^(👷[[:space:]]*)?build(\(.+\))?:'; then
echo "should_tag=true" >> $GITHUB_OUTPUT
echo "✅ Detected patch PR from title prefix gate"
else
echo "should_tag=false" >> $GITHUB_OUTPUT
echo "⏭️ Not a patch PR (neither hotfix/release branch nor style/feat/fix/refactor/hotfix/build title prefix)"
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.