@lobehub/lobehub 2.0.0-next.342 → 2.0.0-next.344

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 (80) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/changelog/v1.json +21 -0
  3. package/package.json +1 -1
  4. package/packages/builtin-tool-cloud-sandbox/src/ExecutionRuntime/index.ts +161 -12
  5. package/packages/database/src/models/__tests__/userMemories.test.ts +62 -5
  6. package/packages/database/src/models/agentCronJob.ts +9 -9
  7. package/packages/database/src/models/userMemory/__tests__/identity.test.ts +5 -5
  8. package/packages/database/src/models/userMemory/experience.ts +91 -1
  9. package/packages/database/src/models/userMemory/identity.ts +93 -2
  10. package/packages/database/src/models/userMemory/model.ts +27 -8
  11. package/packages/types/src/userMemory/experience.ts +25 -0
  12. package/packages/types/src/userMemory/identity.ts +27 -0
  13. package/packages/types/src/userMemory/index.ts +1 -0
  14. package/packages/types/src/userMemory/shared.ts +30 -0
  15. package/src/app/[variants]/(main)/group/profile/features/Header/index.tsx +3 -4
  16. package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +7 -8
  17. package/src/app/[variants]/(main)/memory/(home)/features/Persona/PersonaDetail.tsx +58 -0
  18. package/src/app/[variants]/(main)/memory/(home)/features/Persona/PersonaHeader.tsx +22 -0
  19. package/src/app/[variants]/(main)/memory/(home)/features/Persona/PersonaSummary.tsx +43 -0
  20. package/src/app/[variants]/(main)/memory/(home)/features/Persona/index.tsx +53 -0
  21. package/src/app/[variants]/(main)/memory/(home)/features/RoleTagCloud/index.tsx +2 -2
  22. package/src/app/[variants]/(main)/memory/(home)/index.tsx +15 -3
  23. package/src/app/[variants]/(main)/memory/experiences/features/List/GridView/ExperienceCard.tsx +3 -3
  24. package/src/app/[variants]/(main)/memory/experiences/features/List/GridView/index.tsx +3 -3
  25. package/src/app/[variants]/(main)/memory/experiences/features/List/TimelineView/ExperienceCard.tsx +3 -3
  26. package/src/app/[variants]/(main)/memory/experiences/features/List/TimelineView/index.tsx +3 -3
  27. package/src/app/[variants]/(main)/memory/features/SourceLink.tsx +2 -11
  28. package/src/app/[variants]/(main)/memory/features/TimeLineView/TimeLineCard.tsx +2 -9
  29. package/src/app/[variants]/(main)/memory/identities/features/IdentityRightPanel.tsx +1 -1
  30. package/src/app/[variants]/(main)/memory/identities/features/List/GridView/IdentityCard.tsx +5 -4
  31. package/src/app/[variants]/(main)/memory/identities/features/List/GridView/index.tsx +3 -3
  32. package/src/app/[variants]/(main)/memory/identities/features/List/TimelineView/IdentityCard.tsx +6 -6
  33. package/src/app/[variants]/(main)/memory/identities/features/List/TimelineView/index.tsx +6 -4
  34. package/src/app/[variants]/(main)/settings/profile/index.tsx +8 -8
  35. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/index.tsx +0 -1
  36. package/src/app/[variants]/(main)/settings/skill/features/Actions.tsx +0 -1
  37. package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +9 -10
  38. package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +9 -10
  39. package/src/app/[variants]/(main)/settings/skill/features/McpSkillItem.tsx +4 -5
  40. package/src/app/[variants]/(main)/settings/skill/features/SkillList.tsx +4 -5
  41. package/src/app/[variants]/share/t/[id]/SharedMessageList.tsx +1 -4
  42. package/src/app/[variants]/share/t/[id]/_layout/index.tsx +47 -121
  43. package/src/app/[variants]/share/t/[id]/_layout/style.ts +59 -0
  44. package/src/app/[variants]/share/t/[id]/features/Portal/index.tsx +4 -5
  45. package/src/app/[variants]/share/t/[id]/index.tsx +30 -37
  46. package/src/components/404/index.tsx +15 -9
  47. package/src/components/DragUpload/index.tsx +15 -16
  48. package/src/features/EditorCanvas/DocumentIdMode.tsx +1 -2
  49. package/src/features/IntegrationDetailModal/index.tsx +11 -12
  50. package/src/features/ResourceManager/index.tsx +13 -6
  51. package/src/features/ShareModal/ShareImage/Preview.tsx +19 -28
  52. package/src/features/ShareModal/ShareImage/style.ts +4 -2
  53. package/src/features/ShareModal/index.tsx +5 -1
  54. package/src/features/ShareModal/style.ts +1 -0
  55. package/src/features/ShareModal/useContainerStyles.ts +1 -1
  56. package/src/features/SharePopover/index.tsx +16 -9
  57. package/src/features/SharePopover/style.ts +2 -2
  58. package/src/features/SkillStore/CommunityList/Item.tsx +2 -2
  59. package/src/features/SkillStore/LobeHubList/Item.tsx +2 -2
  60. package/src/features/SkillStore/LobeHubList/index.tsx +2 -3
  61. package/src/features/SkillStore/style.ts +4 -4
  62. package/src/layout/GlobalProvider/ServerVersionOutdatedAlert.tsx +28 -20
  63. package/src/server/routers/lambda/userMemories.ts +61 -5
  64. package/src/server/routers/lambda/userMemory.ts +5 -1
  65. package/src/services/chat/index.ts +2 -2
  66. package/src/services/userMemory/index.ts +25 -1
  67. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +0 -1
  68. package/src/store/userMemory/initialState.ts +22 -52
  69. package/src/store/userMemory/slices/context/action.ts +1 -1
  70. package/src/store/userMemory/slices/context/index.ts +1 -0
  71. package/src/store/userMemory/slices/context/initialState.ts +22 -0
  72. package/src/store/userMemory/slices/experience/action.ts +10 -22
  73. package/src/store/userMemory/slices/experience/index.ts +1 -0
  74. package/src/store/userMemory/slices/experience/initialState.ts +22 -0
  75. package/src/store/userMemory/slices/home/action.ts +17 -0
  76. package/src/store/userMemory/slices/identity/action.ts +36 -24
  77. package/src/store/userMemory/slices/identity/initialState.ts +7 -4
  78. package/src/store/userMemory/slices/preference/action.ts +1 -1
  79. package/src/store/userMemory/slices/preference/index.ts +1 -0
  80. package/src/store/userMemory/slices/preference/initialState.ts +22 -0
@@ -8,7 +8,7 @@ import {
8
8
  } from '@lobechat/const';
9
9
  import { Flexbox, Icon, Image, Modal, Tag, Text, Typography } from '@lobehub/ui';
10
10
  import { Button, Divider } from 'antd';
11
- import { createStyles, cssVar } from 'antd-style';
11
+ import { createStaticStyles, cssVar } from 'antd-style';
12
12
  import { ExternalLink, Loader2, SquareArrowOutUpRight } from 'lucide-react';
13
13
  import { memo, useMemo } from 'react';
14
14
  import { useTranslation } from 'react-i18next';
@@ -18,7 +18,7 @@ import { klavisStoreSelectors, lobehubSkillStoreSelectors } from '@/store/tool/s
18
18
  import { KlavisServerStatus } from '@/store/tool/slices/klavisStore';
19
19
  import { LobehubSkillStatus } from '@/store/tool/slices/lobehubSkillStore/types';
20
20
 
21
- const useStyles = createStyles(({ css, token }) => ({
21
+ const styles = createStaticStyles(({ css, cssVar }) => ({
22
22
  authorLink: css`
23
23
  cursor: pointer;
24
24
 
@@ -26,7 +26,7 @@ const useStyles = createStyles(({ css, token }) => ({
26
26
  gap: 4px;
27
27
  align-items: center;
28
28
 
29
- color: ${token.colorPrimary};
29
+ color: ${cssVar.colorPrimary};
30
30
 
31
31
  &:hover {
32
32
  text-decoration: underline;
@@ -39,7 +39,7 @@ const useStyles = createStyles(({ css, token }) => ({
39
39
  `,
40
40
  detailLabel: css`
41
41
  font-size: 12px;
42
- color: ${token.colorTextTertiary};
42
+ color: ${cssVar.colorTextTertiary};
43
43
  `,
44
44
  header: css`
45
45
  display: flex;
@@ -49,7 +49,7 @@ const useStyles = createStyles(({ css, token }) => ({
49
49
  padding: 16px;
50
50
  border-radius: 12px;
51
51
 
52
- background: ${token.colorFillTertiary};
52
+ background: ${cssVar.colorFillTertiary};
53
53
  `,
54
54
  icon: css`
55
55
  display: flex;
@@ -61,25 +61,25 @@ const useStyles = createStyles(({ css, token }) => ({
61
61
  height: 56px;
62
62
  border-radius: 12px;
63
63
 
64
- background: ${token.colorBgContainer};
64
+ background: ${cssVar.colorBgContainer};
65
65
  `,
66
66
  introduction: css`
67
67
  font-size: 14px;
68
68
  line-height: 1.8;
69
- color: ${token.colorText};
69
+ color: ${cssVar.colorText};
70
70
  `,
71
71
  sectionTitle: css`
72
72
  font-size: 14px;
73
73
  font-weight: 600;
74
- color: ${token.colorText};
74
+ color: ${cssVar.colorText};
75
75
  `,
76
76
  title: css`
77
77
  font-size: 18px;
78
78
  font-weight: 600;
79
- color: ${token.colorText};
79
+ color: ${cssVar.colorText};
80
80
  `,
81
81
  toolTag: css`
82
- font-family: ${token.fontFamilyCode};
82
+ font-family: ${cssVar.fontFamilyCode};
83
83
  font-size: 12px;
84
84
  `,
85
85
  toolsContainer: css`
@@ -90,7 +90,7 @@ const useStyles = createStyles(({ css, token }) => ({
90
90
  trustWarning: css`
91
91
  font-size: 12px;
92
92
  line-height: 1.6;
93
- color: ${token.colorTextTertiary};
93
+ color: ${cssVar.colorTextTertiary};
94
94
  `,
95
95
  }));
96
96
 
@@ -107,7 +107,6 @@ export interface IntegrationDetailModalProps {
107
107
 
108
108
  const IntegrationDetailModal = memo<IntegrationDetailModalProps>(
109
109
  ({ open, onClose, type, identifier, isConnecting, onConnect }) => {
110
- const { styles } = useStyles();
111
110
  const { t } = useTranslation(['plugin', 'setting']);
112
111
 
113
112
  // Get static config based on type
@@ -2,8 +2,8 @@
2
2
 
3
3
  import { BRANDING_NAME } from '@lobechat/business-const';
4
4
  import { Flexbox } from '@lobehub/ui';
5
- import { createStyles, cssVar } from 'antd-style';
6
- import { memo, useEffect } from 'react';
5
+ import { createStaticStyles, useTheme } from 'antd-style';
6
+ import { memo, useEffect, useMemo } from 'react';
7
7
  import { useSearchParams } from 'react-router-dom';
8
8
 
9
9
  import { useResourceManagerStore } from '@/app/[variants]/(main)/resource/features/store';
@@ -19,7 +19,7 @@ import UploadDock from './components/UploadDock';
19
19
 
20
20
  const ChunkDrawer = dynamic(() => import('./components/ChunkDrawer'), { ssr: false });
21
21
 
22
- const useStyles = createStyles(({ css, token }) => {
22
+ const styles = createStaticStyles(({ css, cssVar }) => {
23
23
  return {
24
24
  container: css`
25
25
  position: relative;
@@ -33,7 +33,7 @@ const useStyles = createStyles(({ css, token }) => {
33
33
  width: 100%;
34
34
  height: 100%;
35
35
 
36
- background-color: ${token.colorBgContainerSecondary};
36
+ background-color: var(--editor-overlay-bg, ${cssVar.colorBgContainer});
37
37
  `,
38
38
  pageEditorOverlay: css`
39
39
  position: absolute;
@@ -56,7 +56,7 @@ export type ResouceManagerMode = 'editor' | 'explorer' | 'page';
56
56
  * Business component, no need be reusable.
57
57
  */
58
58
  const ResourceManager = memo(() => {
59
- const { styles } = useStyles();
59
+ const theme = useTheme();
60
60
  const [, setSearchParams] = useSearchParams();
61
61
  const [mode, currentViewItemId, libraryId, setMode, setCurrentViewItemId] =
62
62
  useResourceManagerStore((s) => [
@@ -69,6 +69,13 @@ const ResourceManager = memo(() => {
69
69
 
70
70
  const currentDocument = useFileStore(documentSelectors.getDocumentById(currentViewItemId));
71
71
 
72
+ const cssVariables = useMemo<Record<string, string>>(
73
+ () => ({
74
+ '--editor-overlay-bg': theme.colorBgContainerSecondary,
75
+ }),
76
+ [theme.colorBgContainerSecondary],
77
+ );
78
+
72
79
  // Fetch specific document when switching to page mode if not already loaded
73
80
  useEffect(() => {
74
81
  if (mode === 'page' && currentViewItemId && !currentDocument) {
@@ -98,7 +105,7 @@ const ResourceManager = memo(() => {
98
105
 
99
106
  return (
100
107
  <>
101
- <Flexbox className={styles.container} height={'100%'}>
108
+ <Flexbox className={styles.container} height={'100%'} style={cssVariables}>
102
109
  {/* Explorer is always rendered to preserve its state */}
103
110
  <Explorer />
104
111
 
@@ -1,9 +1,7 @@
1
1
  import { ModelTag } from '@lobehub/icons';
2
- import { Avatar, Flexbox, Markdown } from '@lobehub/ui';
3
- import { ChatHeaderTitle } from '@lobehub/ui/chat';
2
+ import { Avatar, Flexbox, Markdown, Text } from '@lobehub/ui';
4
3
  import { cx } from 'antd-style';
5
4
  import { memo } from 'react';
6
- import { useTranslation } from 'react-i18next';
7
5
 
8
6
  import { ProductLogo } from '@/components/Branding';
9
7
  import PluginTag from '@/features/PluginTag';
@@ -19,21 +17,17 @@ import { type FieldType } from './type';
19
17
 
20
18
  const Preview = memo<FieldType & { title?: string }>(
21
19
  ({ title, withSystemRole, withBackground, withFooter, widthMode }) => {
22
- const [model, plugins, systemRole, isInbox, description, avatar, backgroundColor] =
23
- useAgentStore((s) => [
24
- agentSelectors.currentAgentModel(s),
25
- agentSelectors.displayableAgentPlugins(s),
26
- agentSelectors.currentAgentSystemRole(s),
27
- builtinAgentSelectors.isInboxAgent(s),
28
- agentSelectors.currentAgentDescription(s),
29
- agentSelectors.currentAgentAvatar(s),
30
- agentSelectors.currentAgentBackgroundColor(s),
31
- ]);
32
-
33
- const { t } = useTranslation('chat');
20
+ const [model, plugins, systemRole, isInbox, avatar, backgroundColor] = useAgentStore((s) => [
21
+ agentSelectors.currentAgentModel(s),
22
+ agentSelectors.displayableAgentPlugins(s),
23
+ agentSelectors.currentAgentSystemRole(s),
24
+ builtinAgentSelectors.isInboxAgent(s),
25
+ agentSelectors.currentAgentDescription(s),
26
+ agentSelectors.currentAgentAvatar(s),
27
+ agentSelectors.currentAgentBackgroundColor(s),
28
+ ]);
34
29
 
35
30
  const displayTitle = isInbox ? 'Lobe AI' : title;
36
- const displayDesc = isInbox ? t('inbox.desc') : description;
37
31
 
38
32
  return (
39
33
  <div
@@ -50,24 +44,21 @@ const Preview = memo<FieldType & { title?: string }>(
50
44
  gap={16}
51
45
  >
52
46
  <div className={styles.header}>
53
- <Flexbox align={'flex-start'} gap={12} horizontal>
47
+ <Flexbox align={'center'} gap={12} horizontal>
54
48
  <Avatar
55
49
  avatar={avatar}
56
50
  background={backgroundColor}
57
51
  shape={'square'}
58
- size={40}
52
+ size={28}
59
53
  title={title}
60
54
  />
61
- <ChatHeaderTitle
62
- desc={displayDesc}
63
- tag={
64
- <Flexbox gap={4} horizontal>
65
- <ModelTag model={model} />
66
- {plugins?.length > 0 && <PluginTag plugins={plugins} />}
67
- </Flexbox>
68
- }
69
- title={displayTitle}
70
- />
55
+ <Text fontSize={16} strong>
56
+ {displayTitle}
57
+ </Text>
58
+ <Flexbox gap={4} horizontal>
59
+ <ModelTag model={model} />
60
+ {plugins?.length > 0 && <PluginTag plugins={plugins} />}
61
+ </Flexbox>
71
62
  </Flexbox>
72
63
  {withSystemRole && systemRole && (
73
64
  <div className={styles.role}>
@@ -12,7 +12,7 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
12
12
  background-size: 120% 120%;
13
13
  `,
14
14
  container: css`
15
- background: ${cssVar.colorBgLayout};
15
+ background: ${cssVar.colorBgContainer};
16
16
  `,
17
17
  container_withBackground_true: css`
18
18
  overflow: hidden;
@@ -25,8 +25,10 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
25
25
  `,
26
26
  header: css`
27
27
  margin-block-end: -24px;
28
- padding: 16px;
28
+ padding-block: 16px;
29
+ padding-inline: 24px;
29
30
  border-block-end: 1px solid ${cssVar.colorBorder};
31
+
30
32
  background: ${cssVar.colorBgContainer};
31
33
  `,
32
34
  role: css`
@@ -60,7 +60,11 @@ const ShareModal = memo<ModalProps>(({ onCancel, open }) => {
60
60
  title={t('share', { ns: 'common' })}
61
61
  width={'min(90vw, 1024px)'}
62
62
  >
63
- <Flexbox gap={isMobile ? 8 : 24} style={{ overflow: 'hidden', position: 'relative' }}>
63
+ <Flexbox
64
+ gap={isMobile ? 8 : 24}
65
+ height={'100%'}
66
+ style={{ overflow: 'hidden', position: 'relative' }}
67
+ >
64
68
  <Segmented
65
69
  block
66
70
  onChange={(value) => setTab(value as Tab)}
@@ -5,6 +5,7 @@ export { styles as containerStyles } from './useContainerStyles';
5
5
 
6
6
  export const styles = createStaticStyles(({ css, cssVar }) => ({
7
7
  body: css`
8
+ height: 100%;
8
9
  ${responsive.sm} {
9
10
  padding-block-end: 68px;
10
11
  }
@@ -14,7 +14,7 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
14
14
  border: 1px solid ${cssVar.colorBorder};
15
15
  border-radius: ${cssVar.borderRadiusLG};
16
16
 
17
- background: ${cssVar.colorBgLayout};
17
+ background: ${cssVar.colorBgContainer};
18
18
 
19
19
  /* stylelint-disable selector-class-pattern */
20
20
  .react-pdf__Document *,
@@ -1,7 +1,15 @@
1
1
  'use client';
2
2
 
3
- import { Button, Flexbox, Popover, copyToClipboard, usePopoverContext } from '@lobehub/ui';
4
- import { App, Divider, Select, Skeleton, Typography } from 'antd';
3
+ import {
4
+ Button,
5
+ Flexbox,
6
+ Popover,
7
+ Skeleton,
8
+ Text,
9
+ copyToClipboard,
10
+ usePopoverContext,
11
+ } from '@lobehub/ui';
12
+ import { App, Divider, Select } from 'antd';
5
13
  import { ExternalLinkIcon, LinkIcon, LockIcon } from 'lucide-react';
6
14
  import { type ReactNode, memo, useCallback, useEffect, useRef, useState } from 'react';
7
15
  import { useTranslation } from 'react-i18next';
@@ -12,7 +20,7 @@ import { useIsMobile } from '@/hooks/useIsMobile';
12
20
  import { topicService } from '@/services/topic';
13
21
  import { useChatStore } from '@/store/chat';
14
22
 
15
- import { useStyles } from './style';
23
+ import { styles } from './style';
16
24
 
17
25
  type Visibility = 'private' | 'link';
18
26
 
@@ -23,7 +31,6 @@ interface SharePopoverContentProps {
23
31
  const SharePopoverContent = memo<SharePopoverContentProps>(({ onOpenModal }) => {
24
32
  const { t } = useTranslation('chat');
25
33
  const { message, modal } = App.useApp();
26
- const { styles } = useStyles();
27
34
  const [updating, setUpdating] = useState(false);
28
35
  const { close } = usePopoverContext();
29
36
  const containerRef = useRef<HTMLDivElement>(null);
@@ -103,7 +110,7 @@ const SharePopoverContent = memo<SharePopoverContentProps>(({ onOpenModal }) =>
103
110
  if (isLoading || !shareInfo) {
104
111
  return (
105
112
  <Flexbox className={styles.container} gap={16}>
106
- <Typography.Text strong>{t('share', { ns: 'common' })}</Typography.Text>
113
+ <Text strong>{t('share', { ns: 'common' })}</Text>
107
114
  <Skeleton active paragraph={{ rows: 2 }} />
108
115
  </Flexbox>
109
116
  );
@@ -135,10 +142,10 @@ const SharePopoverContent = memo<SharePopoverContentProps>(({ onOpenModal }) =>
135
142
 
136
143
  return (
137
144
  <Flexbox className={styles.container} gap={12} ref={containerRef}>
138
- <Typography.Text strong>{t('shareModal.popover.title')}</Typography.Text>
145
+ <Text strong>{t('shareModal.popover.title')}</Text>
139
146
 
140
147
  <Flexbox gap={4}>
141
- <Typography.Text type="secondary">{t('shareModal.popover.visibility')}</Typography.Text>
148
+ <Text type="secondary">{t('shareModal.popover.visibility')}</Text>
142
149
  <Select
143
150
  disabled={updating}
144
151
  getPopupContainer={() => containerRef.current || document.body}
@@ -164,9 +171,9 @@ const SharePopoverContent = memo<SharePopoverContentProps>(({ onOpenModal }) =>
164
171
  />
165
172
  </Flexbox>
166
173
 
167
- <Typography.Text className={styles.hint} type="secondary">
174
+ <Text className={styles.hint} type="secondary">
168
175
  {getVisibilityHint()}
169
- </Typography.Text>
176
+ </Text>
170
177
 
171
178
  <Divider style={{ margin: '4px 0' }} />
172
179
 
@@ -1,6 +1,6 @@
1
- import { createStyles } from 'antd-style';
1
+ import { createStaticStyles } from 'antd-style';
2
2
 
3
- export const useStyles = createStyles(({ css }) => ({
3
+ export const styles = createStaticStyles(({ css }) => ({
4
4
  container: css`
5
5
  padding: 16px;
6
6
  `,
@@ -17,10 +17,10 @@ import { useToolStore } from '@/store/tool';
17
17
  import { mcpStoreSelectors, pluginSelectors } from '@/store/tool/selectors';
18
18
  import { type DiscoverMcpItem } from '@/types/discover';
19
19
 
20
- import { useItemStyles } from '../style';
20
+ import { itemStyles } from '../style';
21
21
 
22
22
  const Item = memo<DiscoverMcpItem>(({ name, description, icon, identifier }) => {
23
- const { styles } = useItemStyles();
23
+ const styles = itemStyles;
24
24
  const { t } = useTranslation('plugin');
25
25
  const { modal } = App.useApp();
26
26
  const [detailOpen, setDetailOpen] = useState(false);
@@ -8,7 +8,7 @@ import { Loader2, MoreVerticalIcon, Plus, Unplug } from 'lucide-react';
8
8
  import React, { memo } from 'react';
9
9
  import { useTranslation } from 'react-i18next';
10
10
 
11
- import { useItemStyles } from '../style';
11
+ import { itemStyles } from '../style';
12
12
  import { useSkillConnect } from './useSkillConnect';
13
13
 
14
14
  interface ItemProps {
@@ -25,7 +25,7 @@ interface ItemProps {
25
25
  const Item = memo<ItemProps>(
26
26
  ({ description, icon, identifier, label, onOpenDetail, serverName, type }) => {
27
27
  const { t } = useTranslation('setting');
28
- const { styles } = useItemStyles();
28
+ const styles = itemStyles;
29
29
  const { modal } = App.useApp();
30
30
 
31
31
  const { handleConnect, handleDisconnect, isConnected, isConnecting } = useSkillConnect({
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { KLAVIS_SERVER_TYPES, LOBEHUB_SKILL_PROVIDERS } from '@lobechat/const';
4
- import { createStyles } from 'antd-style';
4
+ import { createStaticStyles } from 'antd-style';
5
5
  import isEqual from 'fast-deep-equal';
6
6
  import type { Klavis } from 'klavis';
7
7
  import { memo, useMemo, useState } from 'react';
@@ -17,7 +17,7 @@ import Empty from '../Empty';
17
17
  import Item from './Item';
18
18
  import { useSkillConnect } from './useSkillConnect';
19
19
 
20
- const useStyles = createStyles(({ css }) => ({
20
+ const styles = createStaticStyles(({ css }) => ({
21
21
  grid: css`
22
22
  display: grid;
23
23
  grid-template-columns: repeat(2, 1fr);
@@ -69,7 +69,6 @@ const DetailModalWithConnect = memo<DetailModalWithConnectProps>(({ detailState,
69
69
  DetailModalWithConnect.displayName = 'DetailModalWithConnect';
70
70
 
71
71
  export const LobeHubList = memo<LobeHubListProps>(({ keywords }) => {
72
- const { styles } = useStyles();
73
72
  const [detailState, setDetailState] = useState<DetailState | null>(null);
74
73
 
75
74
  const isLobehubSkillEnabled = useServerConfigStore(serverConfigSelectors.enableLobehubSkill);
@@ -1,6 +1,6 @@
1
- import { createStyles } from 'antd-style';
1
+ import { createStaticStyles } from 'antd-style';
2
2
 
3
- export const useItemStyles = createStyles(({ css, token }) => ({
3
+ export const itemStyles = createStaticStyles(({ css, cssVar }) => ({
4
4
  container: css`
5
5
  position: relative;
6
6
  overflow: hidden;
@@ -11,7 +11,7 @@ export const useItemStyles = createStyles(({ css, token }) => ({
11
11
  overflow: hidden;
12
12
 
13
13
  font-size: 12px;
14
- color: ${token.colorTextSecondary};
14
+ color: ${cssVar.colorTextSecondary};
15
15
  text-overflow: ellipsis;
16
16
  white-space: nowrap;
17
17
  `,
@@ -20,7 +20,7 @@ export const useItemStyles = createStyles(({ css, token }) => ({
20
20
 
21
21
  font-size: 14px;
22
22
  font-weight: 500;
23
- color: ${token.colorText};
23
+ color: ${cssVar.colorText};
24
24
  text-overflow: ellipsis;
25
25
  white-space: nowrap;
26
26
  `,
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import { Button, Flexbox, Icon } from '@lobehub/ui';
4
- import { createStyles } from 'antd-style';
4
+ import { createStaticStyles, useTheme } from 'antd-style';
5
5
  import { TriangleAlert, X } from 'lucide-react';
6
- import { useState } from 'react';
6
+ import { useMemo, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
 
9
9
  import { MANUAL_UPGRADE_URL } from '@/const/url';
@@ -12,7 +12,7 @@ import { useElectronStore } from '@/store/electron';
12
12
  import { electronSyncSelectors } from '@/store/electron/selectors';
13
13
  import { useGlobalStore } from '@/store/global';
14
14
 
15
- const useStyles = createStyles(({ css, token }) => ({
15
+ const styles = createStaticStyles(({ css, cssVar }) => ({
16
16
  closeButton: css`
17
17
  cursor: pointer;
18
18
 
@@ -26,15 +26,15 @@ const useStyles = createStyles(({ css, token }) => ({
26
26
 
27
27
  width: 28px;
28
28
  height: 28px;
29
- border-radius: ${token.borderRadius}px;
29
+ border-radius: ${cssVar.borderRadius};
30
30
 
31
- color: ${token.colorTextSecondary};
31
+ color: ${cssVar.colorTextSecondary};
32
32
 
33
33
  transition: all 0.2s;
34
34
 
35
35
  &:hover {
36
- color: ${token.colorText};
37
- background: ${token.colorFillSecondary};
36
+ color: ${cssVar.colorText};
37
+ background: ${cssVar.colorFillSecondary};
38
38
  }
39
39
  `,
40
40
  container: css`
@@ -46,7 +46,7 @@ const useStyles = createStyles(({ css, token }) => ({
46
46
  align-items: center;
47
47
  justify-content: center;
48
48
 
49
- background: ${token.colorBgMask};
49
+ background: ${cssVar.colorBgMask};
50
50
  `,
51
51
  content: css`
52
52
  position: relative;
@@ -55,47 +55,55 @@ const useStyles = createStyles(({ css, token }) => ({
55
55
 
56
56
  max-width: 480px;
57
57
  padding: 24px;
58
- border: 1px solid ${token.yellowBorder};
59
- border-radius: ${token.borderRadiusLG}px;
58
+ border: 1px solid var(--content-yellow-border, ${cssVar.colorWarningBorder});
59
+ border-radius: ${cssVar.borderRadiusLG};
60
60
 
61
- background: ${token.colorBgContainer};
62
- box-shadow: ${token.boxShadowSecondary};
61
+ background: ${cssVar.colorBgContainer};
62
+ box-shadow: ${cssVar.boxShadowSecondary};
63
63
  `,
64
64
  desc: css`
65
65
  line-height: 1.6;
66
- color: ${token.colorTextSecondary};
66
+ color: ${cssVar.colorTextSecondary};
67
67
  `,
68
68
  title: css`
69
69
  font-size: 16px;
70
70
  font-weight: bold;
71
- color: ${token.colorWarningText};
71
+ color: ${cssVar.colorWarningText};
72
72
  `,
73
73
  titleIcon: css`
74
74
  flex-shrink: 0;
75
- color: ${token.colorWarning};
75
+ color: ${cssVar.colorWarning};
76
76
  `,
77
77
  warning: css`
78
78
  padding: 12px;
79
- border-radius: ${token.borderRadius}px;
80
- color: ${token.colorWarningText};
81
- background: ${token.yellowBg};
79
+ border-radius: ${cssVar.borderRadius};
80
+ color: ${cssVar.colorWarningText};
81
+ background: var(--warning-yellow-bg, ${cssVar.colorWarningBg});
82
82
  `,
83
83
  }));
84
84
 
85
85
  const ServerVersionOutdatedAlert = () => {
86
- const { styles } = useStyles();
86
+ const theme = useTheme();
87
87
  const { t } = useTranslation('common');
88
88
  const [dismissed, setDismissed] = useState(false);
89
89
  const isServerVersionOutdated = useGlobalStore((s) => s.isServerVersionOutdated);
90
90
  const storageMode = useElectronStore(electronSyncSelectors.storageMode);
91
91
 
92
+ const cssVariables = useMemo<Record<string, string>>(
93
+ () => ({
94
+ '--content-yellow-border': theme.yellowBorder,
95
+ '--warning-yellow-bg': theme.yellowBg,
96
+ }),
97
+ [theme.yellowBorder, theme.yellowBg],
98
+ );
99
+
92
100
  // Only show alert when using self-hosted server, not cloud
93
101
  if (storageMode !== 'selfHost') return null;
94
102
  if (!isServerVersionOutdated || dismissed) return null;
95
103
 
96
104
  return (
97
105
  <div className={styles.container}>
98
- <div className={styles.content}>
106
+ <div className={styles.content} style={cssVariables}>
99
107
  <div className={styles.closeButton} onClick={() => setDismissed(true)}>
100
108
  <Icon icon={X} />
101
109
  </div>
@@ -21,6 +21,7 @@ import { z } from 'zod';
21
21
  import {
22
22
  type IdentityEntryBasePayload,
23
23
  type IdentityEntryPayload,
24
+ UserMemoryExperienceModel,
24
25
  UserMemoryIdentityModel,
25
26
  UserMemoryModel,
26
27
  } from '@/database/models/userMemory';
@@ -203,6 +204,8 @@ const memoryProcedure = authedProcedure.use(serverDatabase).use(async (opts) =>
203
204
  const { ctx } = opts;
204
205
  return opts.next({
205
206
  ctx: {
207
+ experienceModel: new UserMemoryExperienceModel(ctx.serverDB, ctx.userId),
208
+ identityModel: new UserMemoryIdentityModel(ctx.serverDB, ctx.userId),
206
209
  memoryModel: new UserMemoryModel(ctx.serverDB, ctx.userId),
207
210
  },
208
211
  });
@@ -220,13 +223,66 @@ export const userMemoriesRouter = router({
220
223
  }
221
224
  }),
222
225
 
223
- queryIdentitiesForInjection: authedProcedure
224
- .use(serverDatabase)
226
+ queryExperiences: memoryProcedure
227
+ .input(
228
+ z
229
+ .object({
230
+ order: z.enum(['asc', 'desc']).optional(),
231
+ page: z.coerce.number().int().min(1).optional(),
232
+ pageSize: z.coerce.number().int().min(1).max(100).optional(),
233
+ q: z.string().optional(),
234
+ sort: z.enum(['capturedAt', 'scoreConfidence']).optional(),
235
+ tags: z.array(z.string()).optional(),
236
+ types: z.array(z.string()).optional(),
237
+ })
238
+ .optional(),
239
+ )
240
+ .query(async ({ ctx, input }) => {
241
+ const params = input ?? {};
242
+ const fallbackPage = params.page ?? 1;
243
+ const fallbackPageSize = params.pageSize ?? 20;
244
+
245
+ try {
246
+ return await ctx.experienceModel.queryList(params);
247
+ } catch (error) {
248
+ console.error('Failed to query experiences:', error);
249
+ return { items: [], page: fallbackPage, pageSize: fallbackPageSize, total: 0 };
250
+ }
251
+ }),
252
+
253
+ queryIdentities: memoryProcedure
254
+ .input(
255
+ z
256
+ .object({
257
+ order: z.enum(['asc', 'desc']).optional(),
258
+ page: z.coerce.number().int().min(1).optional(),
259
+ pageSize: z.coerce.number().int().min(1).max(100).optional(),
260
+ q: z.string().optional(),
261
+ relationships: z.array(z.string()).optional(),
262
+ sort: z.enum(['capturedAt', 'type']).optional(),
263
+ tags: z.array(z.string()).optional(),
264
+ types: z.array(z.string()).optional(),
265
+ })
266
+ .optional(),
267
+ )
268
+ .query(async ({ ctx, input }) => {
269
+ const params = input ?? {};
270
+ const fallbackPage = params.page ?? 1;
271
+ const fallbackPageSize = params.pageSize ?? 20;
272
+
273
+ try {
274
+ return await ctx.identityModel.queryList(params);
275
+ } catch (error) {
276
+ console.error('Failed to query identities:', error);
277
+ return { items: [], page: fallbackPage, pageSize: fallbackPageSize, total: 0 };
278
+ }
279
+ }),
280
+
281
+ queryIdentitiesForInjection: memoryProcedure
225
282
  .input(z.object({ limit: z.coerce.number().int().min(1).max(100).optional() }).optional())
226
283
  .query(async ({ ctx, input }) => {
227
284
  try {
228
- const identityModel = new UserMemoryIdentityModel(ctx.serverDB, ctx.userId);
229
- return await identityModel.queryForInjection(input?.limit ?? 50);
285
+ return await ctx.identityModel.queryForInjection(input?.limit ?? 50);
230
286
  } catch (error) {
231
287
  console.error('Failed to query identities for injection:', error);
232
288
  return [];
@@ -262,7 +318,7 @@ export const userMemoriesRouter = router({
262
318
  pageSize: z.coerce.number().int().min(1).max(100).optional(),
263
319
  q: z.string().optional(),
264
320
  sort: z
265
- .enum(['scoreConfidence', 'scoreImpact', 'scorePriority', 'scoreUrgency'])
321
+ .enum(['capturedAt', 'scoreConfidence', 'scoreImpact', 'scorePriority', 'scoreUrgency'])
266
322
  .optional(),
267
323
  tags: z.array(z.string()).optional(),
268
324
  types: z.array(z.string()).optional(),