@lobehub/lobehub 2.0.0-next.376 → 2.0.0-next.378

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 (62) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/changelog/v1.json +21 -0
  3. package/docs/development/database-schema.dbml +51 -0
  4. package/docs/self-hosting/advanced/auth/providers/casdoor.mdx +1 -1
  5. package/docs/self-hosting/advanced/auth/providers/casdoor.zh-CN.mdx +1 -1
  6. package/docs/self-hosting/advanced/auth/providers/logto.mdx +1 -1
  7. package/docs/self-hosting/advanced/auth/providers/logto.zh-CN.mdx +1 -1
  8. package/package.json +1 -2
  9. package/packages/database/migrations/0075_add_user_memory_persona.sql +51 -0
  10. package/packages/database/migrations/meta/0075_snapshot.json +11957 -0
  11. package/packages/database/migrations/meta/_journal.json +8 -1
  12. package/packages/database/src/schemas/userMemories/persona.ts +81 -0
  13. package/scripts/_shared/checkDeprecatedAuth.js +46 -16
  14. package/scripts/_shared/checkDeprecatedAuth.test.ts +180 -0
  15. package/src/app/(backend)/api/webhooks/casdoor/route.ts +1 -2
  16. package/src/app/(backend)/api/webhooks/logto/route.ts +2 -3
  17. package/src/app/(backend)/trpc/async/[trpc]/route.ts +1 -2
  18. package/src/app/(backend)/trpc/mobile/[trpc]/route.ts +1 -2
  19. package/src/app/[variants]/(main)/agent/profile/features/ProfileEditor/index.tsx +1 -0
  20. package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/AgentProfilePopup.tsx +9 -0
  21. package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMember.tsx +27 -2
  22. package/src/app/[variants]/(main)/home/_layout/Body/Agent/Actions.tsx +1 -1
  23. package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +40 -32
  24. package/src/app/[variants]/(main)/memory/(home)/index.tsx +1 -1
  25. package/src/app/[variants]/(main)/memory/contexts/index.tsx +2 -0
  26. package/src/app/[variants]/(main)/memory/experiences/index.tsx +2 -0
  27. package/src/app/[variants]/(main)/memory/features/MemoryAnalysis/Action.tsx +13 -2
  28. package/src/app/[variants]/(main)/memory/features/MemoryAnalysis/AnalysisTrigger.tsx +26 -13
  29. package/src/app/[variants]/(main)/memory/features/MemoryAnalysis/index.tsx +10 -1
  30. package/src/app/[variants]/(main)/memory/identities/index.tsx +2 -0
  31. package/src/app/[variants]/(main)/memory/preferences/index.tsx +2 -0
  32. package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +7 -3
  33. package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +30 -30
  34. package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +31 -31
  35. package/src/app/[variants]/(main)/settings/skill/index.tsx +2 -2
  36. package/src/components/FileParsingStatus/EmbeddingStatus.tsx +3 -16
  37. package/src/components/FileParsingStatus/index.tsx +2 -15
  38. package/src/features/ChatInput/ActionBar/Tools/PopoverContent.tsx +1 -3
  39. package/src/features/ChatInput/ActionBar/Tools/ToolsList.tsx +4 -0
  40. package/src/features/ChatInput/ActionBar/Tools/index.tsx +1 -10
  41. package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +41 -16
  42. package/src/features/ChatInput/ActionBar/components/ActionDropdown.tsx +2 -1
  43. package/src/features/Conversation/ChatItem/components/Title.tsx +6 -2
  44. package/src/features/ModelSelect/index.tsx +10 -3
  45. package/src/features/ProfileEditor/AgentTool.tsx +52 -33
  46. package/src/features/ProfileEditor/PopoverContent.tsx +28 -61
  47. package/src/features/SharePopover/index.tsx +3 -3
  48. package/src/features/SkillStore/CommunityList/Item.tsx +2 -1
  49. package/src/features/SkillStore/CommunityList/index.tsx +16 -22
  50. package/src/features/SkillStore/CustomList/Item.tsx +2 -1
  51. package/src/features/SkillStore/CustomList/index.tsx +11 -31
  52. package/src/features/SkillStore/LobeHubList/Item.tsx +4 -3
  53. package/src/features/SkillStore/LobeHubList/index.tsx +2 -18
  54. package/src/features/SkillStore/Search/index.tsx +1 -1
  55. package/src/features/SkillStore/index.tsx +6 -3
  56. package/src/features/SkillStore/style.ts +34 -1
  57. package/src/libs/next/config/define-config.ts +0 -3
  58. package/src/server/routers/lambda/agent.ts +1 -2
  59. package/src/server/services/user/index.ts +1 -2
  60. package/src/server/services/webhookUser/index.test.ts +290 -0
  61. package/src/server/services/webhookUser/index.ts +29 -12
  62. package/src/libs/logger/index.ts +0 -5
@@ -1,18 +1,30 @@
1
1
  'use client';
2
2
 
3
3
  import { getKlavisServerByServerIdentifier, getLobehubSkillProviderById } from '@lobechat/const';
4
- import { Avatar, Flexbox, Icon } from '@lobehub/ui';
4
+ import { Flexbox, Icon } from '@lobehub/ui';
5
5
  import { createStaticStyles } from 'antd-style';
6
6
  import { Blocks } from 'lucide-react';
7
- import { type ReactNode, createElement, memo, useCallback, useMemo } from 'react';
7
+ import React, { createElement, memo, useCallback, useMemo } from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
 
10
10
  import { createSkillStoreModal } from '@/features/SkillStore';
11
11
  import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
12
12
  import { useToolStore } from '@/store/tool';
13
13
 
14
+ const ICON_SIZE = 16;
15
+ const AVATAR_SIZE = 24;
16
+
14
17
  const styles = createStaticStyles(({ css, cssVar }) => ({
15
18
  avatar: css`
19
+ display: flex;
20
+ flex-shrink: 0;
21
+ align-items: center;
22
+ justify-content: center;
23
+
24
+ width: ${AVATAR_SIZE}px;
25
+ height: ${AVATAR_SIZE}px;
26
+ border-radius: 50%;
27
+
16
28
  background: ${cssVar.colorBgContainer};
17
29
  box-shadow:
18
30
  0 0 8px -2px rgba(0, 0, 0, 5%),
@@ -43,6 +55,10 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
43
55
  icon: css`
44
56
  color: ${cssVar.colorTextSecondary};
45
57
  `,
58
+ iconGroup: css`
59
+ display: flex;
60
+ align-items: center;
61
+ `,
46
62
  text: css`
47
63
  font-size: 13px;
48
64
  color: ${cssVar.colorTextSecondary};
@@ -51,10 +67,10 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
51
67
 
52
68
  const BANNER_SKILL_IDS = [
53
69
  { id: 'gmail', type: 'klavis' },
54
- { id: 'notion', type: 'klavis' },
55
70
  { id: 'google-drive', type: 'klavis' },
56
71
  { id: 'google-calendar', type: 'klavis' },
57
72
  { id: 'slack', type: 'klavis' },
73
+ { id: 'notion', type: 'klavis' },
58
74
  { id: 'twitter', type: 'lobehub' },
59
75
  { id: 'github', type: 'klavis' },
60
76
  ] as const;
@@ -73,38 +89,24 @@ const SkillInstallBanner = memo(() => {
73
89
  useFetchLobehubSkillConnections(isLobehubSkillEnabled);
74
90
  useFetchUserKlavisServers(isKlavisEnabled);
75
91
 
76
- const avatarItems = useMemo(() => {
77
- const items: Array<{ avatar: ReactNode; key: string; title: string }> = [];
92
+ const skillIcons = useMemo(() => {
93
+ const icons: Array<{ icon: string | React.ComponentType<{ size?: number }>; key: string }> = [];
78
94
 
79
95
  for (const skill of BANNER_SKILL_IDS) {
80
96
  if (skill.type === 'lobehub') {
81
97
  const provider = getLobehubSkillProviderById(skill.id);
82
98
  if (provider) {
83
- items.push({
84
- avatar:
85
- typeof provider.icon === 'string'
86
- ? provider.icon
87
- : createElement(provider.icon, { size: 14 }),
88
- key: provider.id,
89
- title: provider.label,
90
- });
99
+ icons.push({ icon: provider.icon, key: provider.id });
91
100
  }
92
101
  } else {
93
102
  const server = getKlavisServerByServerIdentifier(skill.id);
94
103
  if (server) {
95
- items.push({
96
- avatar:
97
- typeof server.icon === 'string'
98
- ? server.icon
99
- : createElement(server.icon, { size: 14 }),
100
- key: server.identifier,
101
- title: server.label,
102
- });
104
+ icons.push({ icon: server.icon, key: server.identifier });
103
105
  }
104
106
  }
105
107
  }
106
108
 
107
- return items;
109
+ return icons;
108
110
  }, []);
109
111
 
110
112
  const handleOpenStore = useCallback(() => {
@@ -120,16 +122,22 @@ const SkillInstallBanner = memo(() => {
120
122
  <Icon className={styles.icon} icon={Blocks} size={18} />
121
123
  <span className={styles.text}>{t('skillInstallBanner.title')}</span>
122
124
  </Flexbox>
123
- {avatarItems.length > 0 && (
124
- <Avatar.Group
125
- classNames={{
126
- avatar: styles.avatar,
127
- }}
128
- items={avatarItems}
129
- shape="circle"
130
- size={24}
131
- variant={'outlined'}
132
- />
125
+ {skillIcons.length > 0 && (
126
+ <div className={styles.iconGroup}>
127
+ {skillIcons.map(({ icon, key }, index) => (
128
+ <div
129
+ className={styles.avatar}
130
+ key={key}
131
+ style={{ marginLeft: index === 0 ? 0 : -6, zIndex: index }}
132
+ >
133
+ {typeof icon === 'string' ? (
134
+ <img alt={key} height={ICON_SIZE} src={icon} width={ICON_SIZE} />
135
+ ) : (
136
+ createElement(icon, { size: ICON_SIZE })
137
+ )}
138
+ </div>
139
+ ))}
140
+ </div>
133
141
  )}
134
142
  </div>
135
143
  );
@@ -37,6 +37,7 @@ const Home: FC = () => {
37
37
  right={
38
38
  <Flexbox gap={8} horizontal>
39
39
  {/* <ActionIcon icon={PencilLineIcon} onClick={openEditor} /> */}
40
+ <MemoryAnalysis iconOnly />
40
41
  <WideScreenButton />
41
42
  </Flexbox>
42
43
  }
@@ -44,7 +45,6 @@ const Home: FC = () => {
44
45
  zIndex: 1,
45
46
  }}
46
47
  />
47
- <MemoryAnalysis />
48
48
  <Flexbox
49
49
  height={'100%'}
50
50
  id={SCROLL_PARENT_ID}
@@ -3,6 +3,7 @@ import { BrainCircuitIcon } from 'lucide-react';
3
3
  import { type FC, memo, useCallback, useEffect, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
+ import MemoryAnalysis from '@/app/[variants]/(main)/memory/features/MemoryAnalysis';
6
7
  import { SCROLL_PARENT_ID } from '@/app/[variants]/(main)/memory/features/TimeLineView/useScrollParent';
7
8
  import NavHeader from '@/features/NavHeader';
8
9
  import WideScreenContainer from '@/features/WideScreenContainer';
@@ -87,6 +88,7 @@ const ContextsArea = memo(() => {
87
88
  }
88
89
  right={
89
90
  <>
91
+ <MemoryAnalysis iconOnly />
90
92
  <ViewModeSwitcher onChange={setViewMode} value={viewMode} />
91
93
  <WideScreenButton />
92
94
  </>
@@ -3,6 +3,7 @@ import { BrainCircuitIcon } from 'lucide-react';
3
3
  import { type FC, memo, useCallback, useEffect, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
+ import MemoryAnalysis from '@/app/[variants]/(main)/memory/features/MemoryAnalysis';
6
7
  import { SCROLL_PARENT_ID } from '@/app/[variants]/(main)/memory/features/TimeLineView/useScrollParent';
7
8
  import NavHeader from '@/features/NavHeader';
8
9
  import WideScreenContainer from '@/features/WideScreenContainer';
@@ -85,6 +86,7 @@ const ExperiencesArea = memo(() => {
85
86
  }
86
87
  right={
87
88
  <>
89
+ <MemoryAnalysis iconOnly />
88
90
  <ViewModeSwitcher onChange={setViewMode} value={viewMode} />
89
91
  <WideScreenButton />
90
92
  </>
@@ -5,7 +5,11 @@ import { useTranslation } from 'react-i18next';
5
5
 
6
6
  import AnalysisTrigger from './AnalysisTrigger';
7
7
 
8
- const AnalysisAction = memo(() => {
8
+ interface Props {
9
+ iconOnly?: boolean;
10
+ }
11
+
12
+ const AnalysisAction = memo<Props>(({ iconOnly }) => {
9
13
  const { t } = useTranslation('memory');
10
14
  const [range, setRange] = useState<[Date | null, Date | null]>([null, null]);
11
15
 
@@ -23,7 +27,14 @@ const AnalysisAction = memo(() => {
23
27
  [range, t],
24
28
  );
25
29
 
26
- return <AnalysisTrigger footerNote={footerNote} onRangeChange={setRange} range={range} />;
30
+ return (
31
+ <AnalysisTrigger
32
+ footerNote={footerNote}
33
+ iconOnly={iconOnly}
34
+ onRangeChange={setRange}
35
+ range={range}
36
+ />
37
+ );
27
38
  });
28
39
 
29
40
  AnalysisAction.displayName = 'AnalysisAction';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
- import { Button, Icon } from '@lobehub/ui';
4
- import { App } from 'antd';
3
+ import { ActionIcon, Button, Icon } from '@lobehub/ui';
4
+ import { Tooltip , App } from 'antd';
5
5
  import { CalendarClockIcon } from 'lucide-react';
6
6
  import { memo, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
@@ -13,11 +13,12 @@ import DateRangeModal from './DateRangeModal';
13
13
 
14
14
  interface Props {
15
15
  footerNote: string;
16
+ iconOnly?: boolean;
16
17
  onRangeChange: (range: [Date | null, Date | null]) => void;
17
18
  range: [Date | null, Date | null];
18
19
  }
19
20
 
20
- const AnalysisTrigger = memo<Props>(({ footerNote, range, onRangeChange }) => {
21
+ const AnalysisTrigger = memo<Props>(({ footerNote, range, onRangeChange, iconOnly }) => {
21
22
  const { t } = useTranslation('memory');
22
23
  const { message } = App.useApp();
23
24
  const { isValidating, refresh } = useMemoryAnalysisAsyncTask();
@@ -45,18 +46,30 @@ const AnalysisTrigger = memo<Props>(({ footerNote, range, onRangeChange }) => {
45
46
  }
46
47
  };
47
48
 
49
+ const loading = submitting || isValidating;
50
+
48
51
  return (
49
52
  <>
50
- <Button
51
- icon={<Icon icon={CalendarClockIcon} />}
52
- loading={submitting || isValidating}
53
- onClick={() => setOpen(true)}
54
- size={'large'}
55
- style={{ maxWidth: 300 }}
56
- type={'primary'}
57
- >
58
- {t('analysis.action.button')}
59
- </Button>
53
+ {iconOnly ? (
54
+ <Tooltip title={t('analysis.action.button')}>
55
+ <ActionIcon
56
+ icon={CalendarClockIcon}
57
+ loading={loading}
58
+ onClick={() => setOpen(true)}
59
+ />
60
+ </Tooltip>
61
+ ) : (
62
+ <Button
63
+ icon={<Icon icon={CalendarClockIcon} />}
64
+ loading={loading}
65
+ onClick={() => setOpen(true)}
66
+ size={'large'}
67
+ style={{ maxWidth: 300 }}
68
+ type={'primary'}
69
+ >
70
+ {t('analysis.action.button')}
71
+ </Button>
72
+ )}
60
73
 
61
74
  <DateRangeModal
62
75
  footerNote={footerNote}
@@ -8,7 +8,11 @@ import AnalysisAction from './Action';
8
8
  import { MemoryAnalysisStatus } from './Status';
9
9
  import { useMemoryAnalysisAsyncTask } from './useTask';
10
10
 
11
- const MemoryAnalysis = memo(() => {
11
+ interface Props {
12
+ iconOnly?: boolean;
13
+ }
14
+
15
+ const MemoryAnalysis = memo<Props>(({ iconOnly }) => {
12
16
  const { data, isValidating } = useMemoryAnalysisAsyncTask();
13
17
 
14
18
  const { showAction, showStatus } = useMemo(() => {
@@ -26,6 +30,11 @@ const MemoryAnalysis = memo(() => {
26
30
 
27
31
  if (!showAction && !showStatus) return null;
28
32
 
33
+ // For iconOnly mode, only show the action button
34
+ if (iconOnly) {
35
+ return showAction ? <AnalysisAction iconOnly /> : null;
36
+ }
37
+
29
38
  return (
30
39
  <Flexbox gap={12} style={{ paddingTop: 16, width: '100%' }}>
31
40
  {showStatus && <MemoryAnalysisStatus task={data} />}
@@ -3,6 +3,7 @@ import { BrainCircuitIcon } from 'lucide-react';
3
3
  import { type FC, memo, useCallback, useEffect, useState } from 'react';
4
4
 
5
5
  import CommonFilterBar from '@/app/[variants]/(main)/memory/features/FilterBar';
6
+ import MemoryAnalysis from '@/app/[variants]/(main)/memory/features/MemoryAnalysis';
6
7
  import NavHeader from '@/features/NavHeader';
7
8
  import WideScreenContainer from '@/features/WideScreenContainer';
8
9
  import WideScreenButton from '@/features/WideScreenContainer/WideScreenButton';
@@ -75,6 +76,7 @@ const IdentitiesArea = memo(() => {
75
76
  }
76
77
  right={
77
78
  <>
79
+ <MemoryAnalysis iconOnly />
78
80
  <ViewModeSwitcher onChange={setViewMode} value={viewMode} />
79
81
  <WideScreenButton />
80
82
  </>
@@ -3,6 +3,7 @@ import { BrainCircuitIcon } from 'lucide-react';
3
3
  import { type FC, memo, useCallback, useEffect, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
+ import MemoryAnalysis from '@/app/[variants]/(main)/memory/features/MemoryAnalysis';
6
7
  import { SCROLL_PARENT_ID } from '@/app/[variants]/(main)/memory/features/TimeLineView/useScrollParent';
7
8
  import NavHeader from '@/features/NavHeader';
8
9
  import WideScreenContainer from '@/features/WideScreenContainer';
@@ -85,6 +86,7 @@ const PreferencesArea = memo(() => {
85
86
  }
86
87
  right={
87
88
  <>
89
+ <MemoryAnalysis iconOnly />
88
90
  <ViewModeSwitcher onChange={setViewMode} value={viewMode} />
89
91
  <WideScreenButton />
90
92
  </>
@@ -39,7 +39,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
39
39
  const Head = memo<{ id: string }>(({ id }) => {
40
40
  const navigate = useNavigate();
41
41
  const name = useKnowledgeBaseStore(knowledgeBaseSelectors.getKnowledgeBaseNameById(id));
42
- const setMode = useResourceManagerStore((s) => s.setMode);
42
+ const [setMode, setLibraryId] = useResourceManagerStore((s) => [s.setMode, s.setLibraryId]);
43
43
  const isDragActive = useDragActive();
44
44
  const [isDropZoneActive, setIsDropZoneActive] = useState(false);
45
45
 
@@ -53,10 +53,14 @@ const Head = memo<{ id: string }>(({ id }) => {
53
53
 
54
54
  const handleLibrarySwitch = useCallback(
55
55
  (libraryId: string) => {
56
- navigate(`/resource/library/${libraryId}`);
56
+ setLibraryId(libraryId);
57
57
  setMode('explorer');
58
+ // 使用 setTimeout 确保在下一个事件循环中执行 navigate
59
+ setTimeout(() => {
60
+ navigate(`/resource/library/${libraryId}`);
61
+ }, 0);
58
62
  },
59
- [navigate, setMode],
63
+ [navigate, setLibraryId, setMode],
60
64
  );
61
65
 
62
66
  // Native HTML5 drag-and-drop handlers for root directory drop
@@ -1,10 +1,10 @@
1
1
  'use client';
2
2
 
3
3
  import { type KlavisServerType } from '@lobechat/const';
4
- import { ActionIcon, Avatar, DropdownMenu, Flexbox, Icon } from '@lobehub/ui';
4
+ import { Avatar, DropdownMenu, Flexbox, Icon, Button as LobeButton } from '@lobehub/ui';
5
5
  import { App, Button } from 'antd';
6
6
  import { createStaticStyles, cssVar } from 'antd-style';
7
- import { Loader2, MoreVerticalIcon, SquareArrowOutUpRight, Unplug } from 'lucide-react';
7
+ import { Loader2, MoreHorizontalIcon, SquareArrowOutUpRight, Unplug } from 'lucide-react';
8
8
  import { memo, useCallback, useEffect, useRef, useState } from 'react';
9
9
  import { useTranslation } from 'react-i18next';
10
10
 
@@ -301,7 +301,7 @@ const KlavisSkillItem = memo<KlavisSkillItemProps>(({ serverType, server }) => {
301
301
  ]}
302
302
  placement="bottomRight"
303
303
  >
304
- <ActionIcon icon={MoreVerticalIcon} />
304
+ <LobeButton icon={MoreHorizontalIcon} />
305
305
  </DropdownMenu>
306
306
  );
307
307
  }
@@ -313,35 +313,35 @@ const KlavisSkillItem = memo<KlavisSkillItemProps>(({ serverType, server }) => {
313
313
 
314
314
  return (
315
315
  <Flexbox
316
- align="center"
317
- className={styles.container}
318
- gap={16}
319
- horizontal
320
- justify="space-between"
321
- >
322
- <Flexbox align="center" gap={16} horizontal style={{ flex: 1, overflow: 'hidden' }}>
323
- <div className={styles.icon}>{renderIcon()}</div>
324
- <Flexbox gap={4} style={{ overflow: 'hidden' }}>
325
- <span
326
- className={styles.title}
327
- onClick={() =>
328
- createIntegrationDetailModal({
329
- identifier: serverType.identifier,
330
- serverName: serverType.serverName,
331
- type: 'klavis',
332
- })
333
- }
334
- >
335
- {serverType.label}
336
- </span>
337
- {!isConnected && renderStatus()}
338
- </Flexbox>
339
- </Flexbox>
340
- <Flexbox align="center" gap={12} horizontal>
341
- {isConnected && renderStatus()}
342
- {renderAction()}
316
+ align="center"
317
+ className={styles.container}
318
+ gap={16}
319
+ horizontal
320
+ justify="space-between"
321
+ >
322
+ <Flexbox align="center" gap={16} horizontal style={{ flex: 1, overflow: 'hidden' }}>
323
+ <div className={styles.icon}>{renderIcon()}</div>
324
+ <Flexbox gap={4} style={{ overflow: 'hidden' }}>
325
+ <span
326
+ className={styles.title}
327
+ onClick={() =>
328
+ createIntegrationDetailModal({
329
+ identifier: serverType.identifier,
330
+ serverName: serverType.serverName,
331
+ type: 'klavis',
332
+ })
333
+ }
334
+ >
335
+ {serverType.label}
336
+ </span>
337
+ {!isConnected && renderStatus()}
343
338
  </Flexbox>
344
339
  </Flexbox>
340
+ <Flexbox align="center" gap={12} horizontal>
341
+ {isConnected && renderStatus()}
342
+ {renderAction()}
343
+ </Flexbox>
344
+ </Flexbox>
345
345
  );
346
346
  });
347
347
 
@@ -1,10 +1,10 @@
1
1
  'use client';
2
2
 
3
3
  import { type LobehubSkillProviderType } from '@lobechat/const';
4
- import { ActionIcon, Avatar, DropdownMenu, Flexbox, Icon } from '@lobehub/ui';
4
+ import { Avatar, DropdownMenu, Flexbox, Icon, Button as LobeButton } from '@lobehub/ui';
5
5
  import { App, Button } from 'antd';
6
6
  import { createStaticStyles, cssVar } from 'antd-style';
7
- import { Loader2, MoreVerticalIcon, SquareArrowOutUpRight, Unplug } from 'lucide-react';
7
+ import { Loader2, MoreHorizontalIcon, SquareArrowOutUpRight, Unplug } from 'lucide-react';
8
8
  import { memo, useCallback, useEffect, useRef, useState } from 'react';
9
9
  import { useTranslation } from 'react-i18next';
10
10
 
@@ -290,7 +290,7 @@ const LobehubSkillItem = memo<LobehubSkillItemProps>(({ provider, server }) => {
290
290
  ]}
291
291
  placement="bottomRight"
292
292
  >
293
- <ActionIcon icon={MoreVerticalIcon} />
293
+ <LobeButton icon={MoreHorizontalIcon} />
294
294
  </DropdownMenu>
295
295
  );
296
296
  };
@@ -299,36 +299,36 @@ const LobehubSkillItem = memo<LobehubSkillItemProps>(({ provider, server }) => {
299
299
 
300
300
  return (
301
301
  <Flexbox
302
- align="center"
303
- className={styles.container}
304
- gap={16}
305
- horizontal
306
- justify="space-between"
307
- >
308
- <Flexbox align="center" gap={16} horizontal style={{ flex: 1, overflow: 'hidden' }}>
309
- <div className={`${styles.icon} ${!isConnected ? styles.disconnectedIcon : ''}`}>
310
- {renderIcon()}
311
- </div>
312
- <Flexbox gap={4} style={{ overflow: 'hidden' }}>
313
- <span
314
- className={`${styles.title} ${!isConnected ? styles.disconnectedTitle : ''}`}
315
- onClick={() =>
316
- createIntegrationDetailModal({
317
- identifier: provider.id,
318
- type: 'lobehub',
319
- })
320
- }
321
- >
322
- {provider.label}
323
- </span>
324
- {!isConnected && renderStatus()}
325
- </Flexbox>
326
- </Flexbox>
327
- <Flexbox align="center" gap={12} horizontal>
328
- {isConnected && renderStatus()}
329
- {renderAction()}
302
+ align="center"
303
+ className={styles.container}
304
+ gap={16}
305
+ horizontal
306
+ justify="space-between"
307
+ >
308
+ <Flexbox align="center" gap={16} horizontal style={{ flex: 1, overflow: 'hidden' }}>
309
+ <div className={`${styles.icon} ${!isConnected ? styles.disconnectedIcon : ''}`}>
310
+ {renderIcon()}
311
+ </div>
312
+ <Flexbox gap={4} style={{ overflow: 'hidden' }}>
313
+ <span
314
+ className={`${styles.title} ${!isConnected ? styles.disconnectedTitle : ''}`}
315
+ onClick={() =>
316
+ createIntegrationDetailModal({
317
+ identifier: provider.id,
318
+ type: 'lobehub',
319
+ })
320
+ }
321
+ >
322
+ {provider.label}
323
+ </span>
324
+ {!isConnected && renderStatus()}
330
325
  </Flexbox>
331
326
  </Flexbox>
327
+ <Flexbox align="center" gap={12} horizontal>
328
+ {isConnected && renderStatus()}
329
+ {renderAction()}
330
+ </Flexbox>
331
+ </Flexbox>
332
332
  );
333
333
  });
334
334
 
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { Button, Icon } from '@lobehub/ui';
4
- import { PlusIcon } from 'lucide-react';
4
+ import { Store } from 'lucide-react';
5
5
  import { useCallback } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
@@ -21,7 +21,7 @@ const Page = () => {
21
21
  <>
22
22
  <SettingHeader
23
23
  extra={
24
- <Button icon={<Icon icon={PlusIcon} />} onClick={handleOpenStore}>
24
+ <Button icon={<Icon icon={Store} />} onClick={handleOpenStore}>
25
25
  {t('skillStore.button')}
26
26
  </Button>
27
27
  }
@@ -4,27 +4,17 @@ import { BoltIcon, RotateCwIcon } from 'lucide-react';
4
4
  import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
- import { useIsDark } from '@/hooks/useIsDark';
8
7
  import { AsyncTaskStatus, type FileParsingTask } from '@/types/asyncTask';
9
8
 
10
9
  const styles = createStaticStyles(({ css, cssVar }) => ({
11
- errorReasonDark: css`
10
+ errorReason: css`
12
11
  padding: 4px;
13
12
  border-radius: 4px;
14
13
 
15
14
  font-family: monospace;
16
15
  font-size: 12px;
17
16
 
18
- background: color-mix(in srgb, ${cssVar.colorText} 90%, black);
19
- `,
20
- errorReasonLight: css`
21
- padding: 4px;
22
- border-radius: 4px;
23
-
24
- font-family: monospace;
25
- font-size: 12px;
26
-
27
- background: color-mix(in srgb, ${cssVar.colorText} 90%, white);
17
+ background: ${cssVar.colorFillTertiary};
28
18
  `,
29
19
  }));
30
20
 
@@ -37,7 +27,6 @@ interface EmbeddingStatusProps extends FileParsingTask {
37
27
  const EmbeddingStatus = memo<EmbeddingStatusProps>(
38
28
  ({ chunkCount, embeddingStatus, embeddingError, onClick, onErrorClick, className }) => {
39
29
  const { t } = useTranslation(['components', 'common']);
40
- const isDarkMode = useIsDark();
41
30
 
42
31
  switch (embeddingStatus) {
43
32
  case AsyncTaskStatus.Processing: {
@@ -73,9 +62,7 @@ const EmbeddingStatus = memo<EmbeddingStatusProps>(
73
62
  <Flexbox gap={4}>
74
63
  {t('FileParsingStatus.chunks.embeddingStatus.errorResult')}
75
64
  {embeddingError && (
76
- <Flexbox
77
- className={isDarkMode ? styles.errorReasonDark : styles.errorReasonLight}
78
- >
65
+ <Flexbox className={styles.errorReason}>
79
66
  [{embeddingError.name}]:{' '}
80
67
  {embeddingError.body && typeof embeddingError.body !== 'string'
81
68
  ? embeddingError.body.detail
@@ -5,7 +5,6 @@ import { BoltIcon, Loader2Icon, RotateCwIcon } from 'lucide-react';
5
5
  import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
8
- import { useIsDark } from '@/hooks/useIsDark';
9
8
  import { AsyncTaskStatus, type FileParsingTask } from '@/types/asyncTask';
10
9
 
11
10
  import EmbeddingStatus from './EmbeddingStatus';
@@ -18,13 +17,7 @@ const styles = createStaticStyles(({ css }) => ({
18
17
  font-family: monospace;
19
18
  font-size: 12px;
20
19
 
21
- background: var(--error-reason-bg, ${cssVar.colorText});
22
- `,
23
- errorReasonDark: css`
24
- --error-reason-bg: color-mix(in srgb, ${cssVar.colorText} 90%, black);
25
- `,
26
- errorReasonLight: css`
27
- --error-reason-bg: color-mix(in srgb, ${cssVar.colorText} 90%, white);
20
+ background: ${cssVar.colorFillTertiary};
28
21
  `,
29
22
  }));
30
23
 
@@ -53,7 +46,6 @@ const FileParsingStatus = memo<FileParsingStatusProps>(
53
46
  hideEmbeddingButton,
54
47
  }) => {
55
48
  const { t } = useTranslation(['components', 'common']);
56
- const isDarkMode = useIsDark();
57
49
 
58
50
  switch (chunkingStatus) {
59
51
  case AsyncTaskStatus.Processing: {
@@ -77,12 +69,7 @@ const FileParsingStatus = memo<FileParsingStatusProps>(
77
69
  <Flexbox gap={4}>
78
70
  {t('FileParsingStatus.chunks.status.errorResult')}
79
71
  {chunkingError && (
80
- <Flexbox
81
- className={cx(
82
- styles.errorReason,
83
- isDarkMode ? styles.errorReasonDark : styles.errorReasonLight,
84
- )}
85
- >
72
+ <Flexbox className={styles.errorReason}>
86
73
  [{chunkingError.name}]:{' '}
87
74
  {chunkingError.body && typeof chunkingError.body !== 'string'
88
75
  ? chunkingError.body.detail