@lobehub/lobehub 2.0.0-next.353 → 2.0.0-next.355

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.agents/skills/add-provider-doc/SKILL.md +90 -0
  2. package/.agents/skills/add-setting-env/SKILL.md +106 -0
  3. package/.agents/skills/debug/SKILL.md +66 -0
  4. package/.agents/skills/desktop/SKILL.md +78 -0
  5. package/.agents/skills/desktop/references/feature-implementation.md +99 -0
  6. package/.agents/skills/desktop/references/local-tools.md +133 -0
  7. package/.agents/skills/desktop/references/menu-config.md +103 -0
  8. package/.agents/skills/desktop/references/window-management.md +143 -0
  9. package/.agents/skills/drizzle/SKILL.md +129 -0
  10. package/.agents/skills/drizzle/references/db-migrations.md +50 -0
  11. package/.agents/skills/hotkey/SKILL.md +90 -0
  12. package/{.cursor/rules/i18n.mdc → .agents/skills/i18n/SKILL.md} +14 -23
  13. package/.agents/skills/linear/SKILL.md +51 -0
  14. package/.agents/skills/microcopy/SKILL.md +83 -0
  15. package/.agents/skills/modal/SKILL.md +102 -0
  16. package/{.cursor/rules/project-structure.mdc → .agents/skills/project-overview/SKILL.md} +65 -37
  17. package/.agents/skills/react/SKILL.md +73 -0
  18. package/.agents/skills/react/references/layout-kit.md +100 -0
  19. package/.agents/skills/recent-data/SKILL.md +108 -0
  20. package/.agents/skills/testing/SKILL.md +89 -0
  21. package/.agents/skills/testing/references/agent-runtime-e2e.md +126 -0
  22. package/.agents/skills/testing/references/db-model-test.md +124 -0
  23. package/.agents/skills/testing/references/desktop-controller-test.md +124 -0
  24. package/.agents/skills/testing/references/electron-ipc-test.md +63 -0
  25. package/.agents/skills/testing/references/zustand-store-action-test.md +150 -0
  26. package/.agents/skills/typescript/SKILL.md +52 -0
  27. package/.agents/skills/zustand/SKILL.md +78 -0
  28. package/.agents/skills/zustand/references/action-patterns.md +125 -0
  29. package/.agents/skills/zustand/references/slice-organization.md +125 -0
  30. package/AGENTS.md +42 -55
  31. package/CHANGELOG.md +60 -0
  32. package/CLAUDE.md +57 -46
  33. package/GEMINI.md +47 -39
  34. package/changelog/v1.json +18 -0
  35. package/locales/en-US/plugin.json +3 -0
  36. package/locales/zh-CN/plugin.json +3 -0
  37. package/package.json +1 -1
  38. package/packages/builtin-tool-memory/src/client/Render/SearchUserMemory/index.tsx +3 -11
  39. package/packages/context-engine/src/engine/messages/MessagesEngine.ts +0 -13
  40. package/packages/context-engine/src/engine/messages/__tests__/MessagesEngine.test.ts +0 -25
  41. package/packages/database/src/models/__tests__/topics/topic.create.test.ts +3 -3
  42. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/List/Item/index.tsx +1 -0
  43. package/src/app/[variants]/(main)/agent/features/Conversation/ConversationArea.tsx +4 -0
  44. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/List/Item/index.tsx +1 -0
  45. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/index.tsx +1 -1
  46. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/InboxItem.tsx +19 -29
  47. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/List.tsx +1 -1
  48. package/src/app/[variants]/(main)/home/_layout/Body/Agent/ModalProvider.tsx +1 -1
  49. package/src/features/FileViewer/Renderer/PDF/index.tsx +2 -3
  50. package/src/features/ShareModal/SharePdf/PdfPreview.tsx +1 -2
  51. package/src/libs/pdfjs/index.tsx +25 -0
  52. package/src/locales/default/plugin.ts +3 -0
  53. package/src/server/modules/Mecha/ContextEngineering/__tests__/serverMessagesEngine.test.ts +0 -25
  54. package/src/services/chat/chat.test.ts +19 -19
  55. package/src/services/chat/index.ts +8 -3
  56. package/src/services/chat/mecha/agentConfigResolver.test.ts +72 -55
  57. package/src/services/chat/mecha/agentConfigResolver.ts +28 -4
  58. package/src/services/chat/mecha/contextEngineering.test.ts +21 -14
  59. package/src/services/chat/mecha/contextEngineering.ts +12 -0
  60. package/src/services/chat/types.ts +7 -1
  61. package/src/store/chat/agents/createAgentExecutors.ts +15 -4
  62. package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +1 -0
  63. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +6 -2
  64. package/src/store/test-coverage.md +5 -5
  65. package/.cursor/rules/add-provider-doc.mdc +0 -183
  66. package/.cursor/rules/add-setting-env.mdc +0 -175
  67. package/.cursor/rules/cursor-rules.mdc +0 -28
  68. package/.cursor/rules/db-migrations.mdc +0 -46
  69. package/.cursor/rules/debug-usage.mdc +0 -86
  70. package/.cursor/rules/desktop-controller-tests.mdc +0 -189
  71. package/.cursor/rules/desktop-feature-implementation.mdc +0 -155
  72. package/.cursor/rules/desktop-local-tools-implement.mdc +0 -81
  73. package/.cursor/rules/desktop-menu-configuration.mdc +0 -209
  74. package/.cursor/rules/desktop-window-management.mdc +0 -301
  75. package/.cursor/rules/drizzle-schema-style-guide.mdc +0 -218
  76. package/.cursor/rules/hotkey.mdc +0 -162
  77. package/.cursor/rules/linear.mdc +0 -53
  78. package/.cursor/rules/microcopy-cn.mdc +0 -158
  79. package/.cursor/rules/microcopy-en.mdc +0 -148
  80. package/.cursor/rules/modal-imperative.mdc +0 -162
  81. package/.cursor/rules/packages/react-layout-kit.mdc +0 -122
  82. package/.cursor/rules/project-introduce.mdc +0 -36
  83. package/.cursor/rules/react.mdc +0 -169
  84. package/.cursor/rules/recent-data-usage.mdc +0 -139
  85. package/.cursor/rules/rules-index.mdc +0 -44
  86. package/.cursor/rules/testing-guide/agent-runtime-e2e.mdc +0 -285
  87. package/.cursor/rules/testing-guide/db-model-test.mdc +0 -455
  88. package/.cursor/rules/testing-guide/electron-ipc-test.mdc +0 -80
  89. package/.cursor/rules/testing-guide/testing-guide.mdc +0 -534
  90. package/.cursor/rules/testing-guide/zustand-store-action-test.mdc +0 -574
  91. package/.cursor/rules/typescript.mdc +0 -55
  92. package/.cursor/rules/zustand-action-patterns.mdc +0 -328
  93. package/.cursor/rules/zustand-slice-organization.mdc +0 -308
  94. package/src/libs/pdfjs/pdf.worker.ts +0 -1
  95. package/src/libs/pdfjs/worker.ts +0 -12
  96. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/AGENTS.md +0 -0
  97. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/SKILL.md +0 -0
  98. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/advanced-event-handler-refs.md +0 -0
  99. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/advanced-use-latest.md +0 -0
  100. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-api-routes.md +0 -0
  101. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-defer-await.md +0 -0
  102. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-dependencies.md +0 -0
  103. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-parallel.md +0 -0
  104. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-suspense-boundaries.md +0 -0
  105. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-barrel-imports.md +0 -0
  106. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-conditional.md +0 -0
  107. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-defer-third-party.md +0 -0
  108. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-dynamic-imports.md +0 -0
  109. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-preload.md +0 -0
  110. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-event-listeners.md +0 -0
  111. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-localstorage-schema.md +0 -0
  112. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-passive-event-listeners.md +0 -0
  113. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-swr-dedup.md +0 -0
  114. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-batch-dom-css.md +0 -0
  115. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-function-results.md +0 -0
  116. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-property-access.md +0 -0
  117. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-storage.md +0 -0
  118. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-combine-iterations.md +0 -0
  119. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-early-exit.md +0 -0
  120. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-hoist-regexp.md +0 -0
  121. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-index-maps.md +0 -0
  122. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-length-check-first.md +0 -0
  123. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-min-max-loop.md +0 -0
  124. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-set-map-lookups.md +0 -0
  125. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-tosorted-immutable.md +0 -0
  126. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-activity.md +0 -0
  127. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-animate-svg-wrapper.md +0 -0
  128. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-conditional-render.md +0 -0
  129. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-content-visibility.md +0 -0
  130. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-hoist-jsx.md +0 -0
  131. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-hydration-no-flicker.md +0 -0
  132. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-svg-precision.md +0 -0
  133. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-defer-reads.md +0 -0
  134. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-dependencies.md +0 -0
  135. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-derived-state.md +0 -0
  136. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-functional-setstate.md +0 -0
  137. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-lazy-state-init.md +0 -0
  138. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-memo.md +0 -0
  139. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-transitions.md +0 -0
  140. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-after-nonblocking.md +0 -0
  141. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-cache-lru.md +0 -0
  142. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-cache-react.md +0 -0
  143. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-parallel-fetching.md +0 -0
  144. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-serialization.md +0 -0
package/GEMINI.md CHANGED
@@ -1,64 +1,72 @@
1
1
  # GEMINI.md
2
2
 
3
- This document serves as a shared guideline for all team members when using Gemini CLI in this repository.
3
+ Guidelines for using Gemini CLI in this LobeChat repository.
4
4
 
5
5
  ## Tech Stack
6
6
 
7
- read @.cursor/rules/project-introduce.mdc
8
-
9
- ## Directory Structure
10
-
11
- read @.cursor/rules/project-structure.mdc
7
+ - Next.js 16 + React 19 + TypeScript
8
+ - SPA inside Next.js with `react-router-dom`
9
+ - `@lobehub/ui`, antd for components; antd-style for CSS-in-JS
10
+ - react-i18next for i18n; zustand for state management
11
+ - SWR for data fetching; TRPC for type-safe backend
12
+ - Drizzle ORM with PostgreSQL; Vitest for testing
13
+
14
+ ## Project Structure
15
+
16
+ ```
17
+ lobe-chat/
18
+ ├── apps/desktop/ # Electron desktop app
19
+ ├── packages/ # Shared packages (@lobechat/*)
20
+ │ ├── database/ # Database schemas, models, repositories
21
+ │ ├── agent-runtime/ # Agent runtime
22
+ │ └── ...
23
+ ├── src/
24
+ │ ├── app/ # Next.js app router
25
+ │ ├── store/ # Zustand stores
26
+ │ ├── services/ # Client services
27
+ │ ├── server/ # Server services and routers
28
+ │ └── ...
29
+ └── e2e/ # E2E tests (Cucumber + Playwright)
30
+ ```
12
31
 
13
32
  ## Development
14
33
 
15
34
  ### Git Workflow
16
35
 
17
- - use rebase for git pull
18
- - git commit message should prefix with gitmoji
19
- - git branch name format template: <type>/<feature-name>
20
- - use .github/PULL_REQUEST_TEMPLATE.md to generate pull request description
21
- - PR titles starting with `✨ feat/` or `🐛 fix` will trigger the release workflow upon merge. Only use these prefixes for significant user-facing feature changes or bug fixes
36
+ - Use rebase for `git pull`
37
+ - Commit messages: prefix with gitmoji
38
+ - Branch format: `<type>/<feature-name>`
39
+ - PR titles with `✨ feat/` or `🐛 fix` trigger releases
22
40
 
23
41
  ### Package Management
24
42
 
25
- This repository adopts a monorepo structure.
26
-
27
- - Use `pnpm` as the primary package manager for dependency management
28
- - Use `bun` to run npm scripts
29
- - Use `bunx` to run executable npm packages
30
-
31
- ### TypeScript Code Style Guide
32
-
33
- see @.cursor/rules/typescript.mdc
43
+ - `pnpm` for dependency management
44
+ - `bun` to run npm scripts
45
+ - `bunx` for executable npm packages
34
46
 
35
47
  ### Testing
36
48
 
37
- - **Required Rule**: read `.cursor/rules/testing-guide/testing-guide.mdc` before writing tests
38
- - **Command**:
39
- - web: `bunx vitest run --silent='passed-only' '[file-path-pattern]'`
40
- - packages(eg: database): `cd packages/database && bunx vitest run --silent='passed-only' '[file-path-pattern]'`
41
-
42
- **Important**:
43
-
44
- - wrap the file path in single quotes to avoid shell expansion
45
- - Never run `bun run test` etc to run tests, this will run all tests and cost about 10mins
46
- - If trying to fix the same test twice, but still failed, stop and ask for help.
49
+ ```bash
50
+ # Run specific test (NEVER run `bun run test` - takes ~10 minutes)
51
+ bunx vitest run --silent='passed-only' '[file-path]'
47
52
 
48
- ### Typecheck
53
+ # Database package
54
+ cd packages/database && bunx vitest run --silent='passed-only' '[file]'
55
+ ```
49
56
 
50
- - use `bun run type-check` to check type errors.
57
+ - Tests must pass type check: `bun run type-check`
58
+ - After 2 failed fix attempts, stop and ask for help
51
59
 
52
60
  ### i18n
53
61
 
54
- - **Keys**: Add to `src/locales/default/namespace.ts`
55
- - **Dev**: Translate `locales/zh-CN/namespace.json` and `locales/en-US/namespace.json` locales file only for dev preview
56
- - DON'T run `pnpm i18n`, let CI auto handle it
62
+ - Add keys to `src/locales/default/namespace.ts`
63
+ - For dev preview: translate `locales/zh-CN/` and `locales/en-US/`
64
+ - Don't run `pnpm i18n` - CI handles it
57
65
 
58
- ## 🚨 Quality Checks
66
+ ## Quality Checks
59
67
 
60
- **MANDATORY**: After completing code changes, always run `mcp__vscode-mcp__get_diagnostics` on the modified files to identify any errors introduced by your changes and fix them.
68
+ **MANDATORY**: After completing code changes, run diagnostics on modified files to identify and fix any errors.
61
69
 
62
- ## Rules Index
70
+ ## Skills (Auto-loaded)
63
71
 
64
- Some useful project rules are listed in @.cursor/rules/rules-index.mdc
72
+ Skills are available in `.agents/skills/` directory. See CLAUDE.md for the full list.
package/changelog/v1.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Fix favorite refresh bug and group topic refresh issue."
6
+ ]
7
+ },
8
+ "date": "2026-01-23",
9
+ "version": "2.0.0-next.355"
10
+ },
11
+ {
12
+ "children": {
13
+ "improvements": [
14
+ "Migrate AI Rules to Claude Code Skills."
15
+ ]
16
+ },
17
+ "date": "2026-01-23",
18
+ "version": "2.0.0-next.354"
19
+ },
2
20
  {
3
21
  "children": {},
4
22
  "date": "2026-01-23",
@@ -177,6 +177,9 @@
177
177
  "builtins.lobe-user-memory.apiName.searchUserMemory": "Search memory",
178
178
  "builtins.lobe-user-memory.apiName.updateIdentityMemory": "Update identity memory",
179
179
  "builtins.lobe-user-memory.inspector.noResults": "No results",
180
+ "builtins.lobe-user-memory.render.contexts": "Contexts",
181
+ "builtins.lobe-user-memory.render.experiences": "Experiences",
182
+ "builtins.lobe-user-memory.render.preferences": "Preferences",
180
183
  "builtins.lobe-user-memory.title": "Memory",
181
184
  "builtins.lobe-web-browsing.apiName.crawlMultiPages": "Read multiple pages",
182
185
  "builtins.lobe-web-browsing.apiName.crawlSinglePage": "Read page content",
@@ -177,6 +177,9 @@
177
177
  "builtins.lobe-user-memory.apiName.searchUserMemory": "搜索记忆",
178
178
  "builtins.lobe-user-memory.apiName.updateIdentityMemory": "更新身份记忆",
179
179
  "builtins.lobe-user-memory.inspector.noResults": "无结果",
180
+ "builtins.lobe-user-memory.render.contexts": "情境",
181
+ "builtins.lobe-user-memory.render.experiences": "经验",
182
+ "builtins.lobe-user-memory.render.preferences": "偏好",
180
183
  "builtins.lobe-user-memory.title": "记忆",
181
184
  "builtins.lobe-web-browsing.apiName.crawlMultiPages": "读取多个页面内容",
182
185
  "builtins.lobe-web-browsing.apiName.crawlSinglePage": "读取页面内容",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.353",
3
+ "version": "2.0.0-next.355",
4
4
  "description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -6,8 +6,6 @@ import { createStaticStyles } from 'antd-style';
6
6
  import { memo } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
 
9
- import { highlightTextStyles } from '@/styles';
10
-
11
9
  import type { SearchMemoryParams, SearchUserMemoryState } from '../../../types';
12
10
 
13
11
  const styles = createStaticStyles(({ css, cssVar }) => ({
@@ -120,9 +118,7 @@ const SearchUserMemoryRender = memo<BuiltinRenderProps<SearchMemoryParams, Searc
120
118
  paddingInline={12}
121
119
  title={
122
120
  <Text className={styles.sectionHeader}>
123
- <span className={highlightTextStyles.info}>
124
- {t('builtins.lobe-user-memory.render.contexts' as any)}
125
- </span>
121
+ <span>{t('builtins.lobe-user-memory.render.contexts')}</span>
126
122
  <Text as={'span'} type={'secondary'}>
127
123
  {' '}
128
124
  ({contexts.length})
@@ -152,9 +148,7 @@ const SearchUserMemoryRender = memo<BuiltinRenderProps<SearchMemoryParams, Searc
152
148
  paddingInline={12}
153
149
  title={
154
150
  <Text className={styles.sectionHeader}>
155
- <span className={highlightTextStyles.gold}>
156
- {t('builtins.lobe-user-memory.render.experiences' as any)}
157
- </span>
151
+ <span>{t('builtins.lobe-user-memory.render.experiences')}</span>
158
152
  <Text as={'span'} type={'secondary'}>
159
153
  {' '}
160
154
  ({experiences.length})
@@ -184,9 +178,7 @@ const SearchUserMemoryRender = memo<BuiltinRenderProps<SearchMemoryParams, Searc
184
178
  paddingInline={12}
185
179
  title={
186
180
  <Text className={styles.sectionHeader}>
187
- <span className={highlightTextStyles.warning}>
188
- {t('builtins.lobe-user-memory.render.preferences' as any)}
189
- </span>
181
+ <span>{t('builtins.lobe-user-memory.render.preferences')}</span>
190
182
  <Text as={'span'} type={'secondary'}>
191
183
  {' '}
192
184
  ({preferences.length})
@@ -9,7 +9,6 @@ import {
9
9
  GroupMessageFlattenProcessor,
10
10
  GroupOrchestrationFilterProcessor,
11
11
  GroupRoleTransformProcessor,
12
- HistoryTruncateProcessor,
13
12
  InputTemplateProcessor,
14
13
  MessageCleanupProcessor,
15
14
  MessageContentProcessor,
@@ -113,8 +112,6 @@ export class MessagesEngine {
113
112
  provider,
114
113
  systemRole,
115
114
  inputTemplate,
116
- enableHistoryCount,
117
- historyCount,
118
115
  historySummary,
119
116
  formatHistorySummary,
120
117
  knowledge,
@@ -145,16 +142,6 @@ export class MessagesEngine {
145
142
  const isGTDTodoEnabled = gtd?.enabled && gtd?.todos;
146
143
 
147
144
  return [
148
- // =============================================
149
- // Phase 1: History Management
150
- // =============================================
151
-
152
- // 1. History truncation (MUST be first, before any message injection)
153
- new HistoryTruncateProcessor({
154
- enableHistoryCount,
155
- historyCount,
156
- }),
157
-
158
145
  // =============================================
159
146
  // Phase 2: System Role Injection
160
147
  // =============================================
@@ -113,31 +113,6 @@ describe('MessagesEngine', () => {
113
113
  expect(result.messages[0].content).toBe(systemRole);
114
114
  });
115
115
 
116
- it('should truncate history when enabled', async () => {
117
- const messages: UIChatMessage[] = [];
118
- for (let i = 0; i < 20; i++) {
119
- messages.push({
120
- content: `Message ${i}`,
121
- createdAt: Date.now(),
122
- id: `msg-${i}`,
123
- role: i % 2 === 0 ? 'user' : 'assistant',
124
- updatedAt: Date.now(),
125
- } as UIChatMessage);
126
- }
127
-
128
- const params = createBasicParams({
129
- enableHistoryCount: true,
130
- historyCount: 5,
131
- messages,
132
- });
133
- const engine = new MessagesEngine(params);
134
-
135
- const result = await engine.process();
136
-
137
- // Should have truncated to 5 messages
138
- expect(result.messages.length).toBeLessThanOrEqual(5);
139
- });
140
-
141
116
  it('should inject history summary when provided', async () => {
142
117
  const historySummary = 'We discussed AI and machine learning';
143
118
  const params = createBasicParams({ historySummary });
@@ -1,4 +1,4 @@
1
- import { eq, inArray } from 'drizzle-orm';
1
+ import { asc, eq, inArray } from 'drizzle-orm';
2
2
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
3
3
 
4
4
  import { getTestDB } from '../../../core/getTestDB';
@@ -188,12 +188,12 @@ describe('TopicModel - Create', () => {
188
188
  userId,
189
189
  });
190
190
 
191
- const items = await serverDB.select().from(topics);
191
+ const items = await serverDB.select().from(topics).orderBy(asc(topics.title));
192
192
  expect(items).toHaveLength(2);
193
193
  expect(items[0]).toMatchObject({ title: 'Topic 1', favorite: true, sessionId, userId });
194
194
  expect(items[1]).toMatchObject({ title: 'Topic 2', favorite: false, sessionId, userId });
195
195
 
196
- const updatedMessages = await serverDB.select().from(messages);
196
+ const updatedMessages = await serverDB.select().from(messages).orderBy(asc(messages.id));
197
197
  expect(updatedMessages).toHaveLength(3);
198
198
  expect(updatedMessages[0].topicId).toBe(createdTopics[0].id);
199
199
  expect(updatedMessages[1].topicId).toBe(createdTopics[0].id);
@@ -110,6 +110,7 @@ const TopicItem = memo<TopicItemProps>(({ id, title, fav, active, threadId }) =>
110
110
  fill={fav ? cssVar.colorWarning : 'transparent'}
111
111
  icon={Star}
112
112
  onClick={(e) => {
113
+ e.preventDefault();
113
114
  e.stopPropagation();
114
115
  favoriteTopic(id, !fav);
115
116
  }}
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { Flexbox } from '@lobehub/ui';
4
+ import debug from 'debug';
4
5
  import { Suspense, memo, useMemo } from 'react';
5
6
 
6
7
  import ChatMiniMap from '@/features/ChatMiniMap';
@@ -18,6 +19,8 @@ import ThreadHydration from './ThreadHydration';
18
19
  import { useActionsBarConfig } from './useActionsBarConfig';
19
20
  import { useAgentContext } from './useAgentContext';
20
21
 
22
+ const log = debug('lobe-render:agent:ConversationArea');
23
+
21
24
  /**
22
25
  * ConversationArea
23
26
  *
@@ -35,6 +38,7 @@ const Conversation = memo(() => {
35
38
  );
36
39
  const replaceMessages = useChatStore((s) => s.replaceMessages);
37
40
  const messages = useChatStore((s) => s.dbMessagesMap[chatKey]);
41
+ log('contextKey %s: %o', chatKey, messages);
38
42
 
39
43
  // Get operation state from ChatStore for reactive updates
40
44
  const operationState = useOperationState(context);
@@ -111,6 +111,7 @@ const TopicItem = memo<TopicItemProps>(({ id, title, fav, active, threadId }) =>
111
111
  fill={fav ? cssVar.colorWarning : 'transparent'}
112
112
  icon={Star}
113
113
  onClick={(e) => {
114
+ e.preventDefault();
114
115
  e.stopPropagation();
115
116
  favoriteTopic(id, !fav);
116
117
  }}
@@ -106,7 +106,7 @@ const AgentItem = memo<AgentItemProps>(({ item, style, className }) => {
106
106
 
107
107
  return (
108
108
  <>
109
- <Link aria-label={id} to={agentUrl}>
109
+ <Link aria-label={displayTitle} to={agentUrl}>
110
110
  <NavItem
111
111
  actions={<Actions dropdownMenu={dropdownMenu} />}
112
112
  className={className}
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { DEFAULT_INBOX_AVATAR, SESSION_CHAT_URL } from '@lobechat/const';
4
4
  import { Avatar } from '@lobehub/ui';
5
- import { type CSSProperties, memo, useCallback } from 'react';
6
- import { useNavigate } from 'react-router-dom';
5
+ import { type CSSProperties, memo } from 'react';
6
+ import { Link } from 'react-router-dom';
7
7
 
8
8
  import NavItem from '@/features/NavPanel/components/NavItem';
9
9
  import { useAgentStore } from '@/store/agent';
@@ -17,38 +17,28 @@ interface InboxItemProps {
17
17
  }
18
18
 
19
19
  const InboxItem = memo<InboxItemProps>(({ className, style }) => {
20
- const navigate = useNavigate();
21
-
22
20
  const inboxAgentId = useAgentStore(builtinAgentSelectors.inboxAgentId);
23
- const activeAgentId = useAgentStore((s) => s.activeAgentId);
24
- const isActive = !!inboxAgentId && activeAgentId === inboxAgentId;
25
21
 
26
- const isLoading = useChatStore(
27
- useCallback(
28
- (s) => (isActive ? operationSelectors.isAgentRuntimeRunning(s) : false),
29
- [isActive],
30
- ),
31
- );
22
+ const isLoading = useChatStore(operationSelectors.isAgentRuntimeRunning);
32
23
  const inboxAgentTitle = 'Lobe AI';
33
24
 
34
- const handleClick = useCallback(() => {
35
- if (inboxAgentId) {
36
- navigate(SESSION_CHAT_URL(inboxAgentId, false));
37
- }
38
- }, [inboxAgentId, navigate]);
39
-
40
25
  return (
41
- <NavItem
42
- active={isActive}
43
- className={className}
44
- icon={
45
- <Avatar avatar={DEFAULT_INBOX_AVATAR} emojiScaleWithBackground shape={'square'} size={24} />
46
- }
47
- loading={isLoading}
48
- onClick={handleClick}
49
- style={style}
50
- title={inboxAgentTitle}
51
- />
26
+ <Link aria-label={inboxAgentTitle} to={SESSION_CHAT_URL(inboxAgentId, false)}>
27
+ <NavItem
28
+ className={className}
29
+ icon={
30
+ <Avatar
31
+ avatar={DEFAULT_INBOX_AVATAR}
32
+ emojiScaleWithBackground
33
+ shape={'square'}
34
+ size={24}
35
+ />
36
+ }
37
+ loading={isLoading}
38
+ style={style}
39
+ title={inboxAgentTitle}
40
+ />
41
+ </Link>
52
42
  );
53
43
  });
54
44
 
@@ -4,6 +4,7 @@ import { MoreHorizontal } from 'lucide-react';
4
4
  import { type CSSProperties, memo, useMemo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
+ import EmptyNavItem from '@/features/NavPanel/components/EmptyNavItem';
7
8
  import NavItem from '@/features/NavPanel/components/NavItem';
8
9
  import { useGlobalStore } from '@/store/global';
9
10
  import { systemStatusSelectors } from '@/store/global/selectors';
@@ -11,7 +12,6 @@ import { useHomeStore } from '@/store/home';
11
12
  import { homeAgentListSelectors } from '@/store/home/selectors';
12
13
  import { SessionDefaultGroup } from '@/types/session';
13
14
 
14
- import EmptyNavItem from '../../../../../../../../features/NavPanel/components/EmptyNavItem';
15
15
  import { useCreateMenuItems } from '../../../hooks';
16
16
  import GroupItem from './AgentGroupItem';
17
17
  import AgentItem from './AgentItem';
@@ -5,8 +5,8 @@ import { type ReactNode, createContext, memo, useContext, useMemo, useState } fr
5
5
  import { ChatGroupWizard } from '@/components/ChatGroupWizard';
6
6
  import { MemberSelectionModal } from '@/components/MemberSelectionModal';
7
7
 
8
- import CreateGroupModal from '../../CreateGroupModal';
9
8
  import ConfigGroupModal from './Modals/ConfigGroupModal';
9
+ import CreateGroupModal from './Modals/CreateGroupModal';
10
10
 
11
11
  interface AgentModalContextValue {
12
12
  closeAllModals: () => void;
@@ -2,12 +2,11 @@
2
2
 
3
3
  import { Flexbox } from '@lobehub/ui';
4
4
  import { Fragment, memo, useCallback, useState } from 'react';
5
- import { Document, Page, pdfjs } from 'react-pdf';
6
5
  import 'react-pdf/dist/Page/AnnotationLayer.css';
7
6
  import 'react-pdf/dist/Page/TextLayer.css';
8
7
 
9
8
  import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
10
- import '@/libs/pdfjs/worker';
9
+ import { Document, Page, pdfjs } from '@/libs/pdfjs';
11
10
  import { lambdaQuery } from '@/libs/trpc/client';
12
11
 
13
12
  import HighlightLayer from './HighlightLayer';
@@ -71,7 +70,7 @@ const PDFViewer = memo<PDFViewerProps>(({ url, fileId }) => {
71
70
  onLoadSuccess={onDocumentLoadSuccess}
72
71
  options={options}
73
72
  >
74
- {Array.from({ length: numPages }, (el, index) => {
73
+ {Array.from({ length: numPages }, (_, index) => {
75
74
  const width = containerWidth ? Math.min(containerWidth, maxWidth) : maxWidth;
76
75
 
77
76
  return (
@@ -7,10 +7,9 @@ import { createStaticStyles, cx } from 'antd-style';
7
7
  import { ChevronLeft, ChevronRight, Expand, FileText } from 'lucide-react';
8
8
  import { memo, useState } from 'react';
9
9
  import { useTranslation } from 'react-i18next';
10
- import { Document, Page } from 'react-pdf';
11
10
 
12
11
  import { useIsMobile } from '@/hooks/useIsMobile';
13
- import '@/libs/pdfjs/worker';
12
+ import { Document, Page } from '@/libs/pdfjs';
14
13
 
15
14
  import { containerStyles } from '../style';
16
15
 
@@ -0,0 +1,25 @@
1
+ 'use client';
2
+
3
+ import type { ComponentProps } from 'react';
4
+ import { Document as PdfDocument, Page as PdfPage, pdfjs } from 'react-pdf';
5
+
6
+ const workerSrc = `https://registry.npmmirror.com/pdfjs-dist/${pdfjs.version}/files/build/pdf.worker.min.mjs`;
7
+
8
+ function ensureWorker() {
9
+ if (!pdfjs.GlobalWorkerOptions.workerSrc) {
10
+ pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;
11
+ }
12
+ }
13
+
14
+ export type DocumentProps = ComponentProps<typeof PdfDocument>;
15
+ export type PageProps = ComponentProps<typeof PdfPage>;
16
+
17
+ export const Document = (props: DocumentProps) => {
18
+ ensureWorker();
19
+ return <PdfDocument {...props} />;
20
+ };
21
+
22
+
23
+
24
+
25
+ export {Page, pdfjs} from 'react-pdf';
@@ -178,6 +178,9 @@ export default {
178
178
  'builtins.lobe-user-memory.apiName.searchUserMemory': 'Search memory',
179
179
  'builtins.lobe-user-memory.apiName.updateIdentityMemory': 'Update identity memory',
180
180
  'builtins.lobe-user-memory.inspector.noResults': 'No results',
181
+ 'builtins.lobe-user-memory.render.contexts': 'Contexts',
182
+ 'builtins.lobe-user-memory.render.experiences': 'Experiences',
183
+ 'builtins.lobe-user-memory.render.preferences': 'Preferences',
181
184
  'builtins.lobe-user-memory.title': 'Memory',
182
185
  'builtins.lobe-web-browsing.apiName.crawlMultiPages': 'Read multiple pages',
183
186
  'builtins.lobe-web-browsing.apiName.crawlSinglePage': 'Read page content',
@@ -68,31 +68,6 @@ describe('serverMessagesEngine', () => {
68
68
  });
69
69
  });
70
70
 
71
- describe('history truncation', () => {
72
- it('should truncate history when enabled', async () => {
73
- const messages: UIChatMessage[] = [];
74
- for (let i = 0; i < 20; i++) {
75
- messages.push({
76
- content: `Message ${i}`,
77
- createdAt: Date.now(),
78
- id: `msg-${i}`,
79
- role: i % 2 === 0 ? 'user' : 'assistant',
80
- updatedAt: Date.now(),
81
- } as UIChatMessage);
82
- }
83
-
84
- const result = await serverMessagesEngine({
85
- enableHistoryCount: true,
86
- historyCount: 5,
87
- messages,
88
- model: 'gpt-4',
89
- provider: 'openai',
90
- });
91
-
92
- expect(result.length).toBeLessThanOrEqual(5);
93
- });
94
- });
95
-
96
71
  describe('knowledge injection', () => {
97
72
  it('should inject file contents', async () => {
98
73
  const messages = createBasicMessages();