@lobehub/lobehub 2.0.0-next.310 → 2.0.0-next.312

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 (118) hide show
  1. package/.github/PULL_REQUEST_TEMPLATE.md +1 -1
  2. package/CHANGELOG.md +58 -0
  3. package/changelog/v1.json +21 -0
  4. package/docs/development/basic/chat-api.mdx +0 -1
  5. package/docs/development/basic/chat-api.zh-CN.mdx +0 -1
  6. package/e2e/README.md +1 -1
  7. package/e2e/src/features/community/detail-pages.feature +2 -2
  8. package/e2e/src/features/community/interactions.feature +5 -5
  9. package/e2e/src/features/community/smoke.feature +1 -1
  10. package/e2e/src/steps/community/detail-pages.steps.ts +6 -4
  11. package/e2e/src/steps/community/interactions.steps.ts +3 -3
  12. package/package.json +1 -1
  13. package/packages/builtin-tool-agent-builder/src/systemRole.ts +9 -0
  14. package/packages/model-runtime/src/core/BaseAI.ts +0 -2
  15. package/packages/model-runtime/src/core/ModelRuntime.test.ts +0 -37
  16. package/packages/model-runtime/src/core/ModelRuntime.ts +0 -5
  17. package/packages/model-runtime/src/core/RouterRuntime/baseRuntimeMap.ts +4 -0
  18. package/packages/model-runtime/src/core/RouterRuntime/createRuntime.test.ts +325 -200
  19. package/packages/model-runtime/src/core/RouterRuntime/createRuntime.ts +205 -64
  20. package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +0 -14
  21. package/packages/model-runtime/src/providers/aihubmix/index.test.ts +14 -20
  22. package/packages/model-runtime/src/types/index.ts +0 -1
  23. package/packages/model-runtime/src/utils/createError.test.ts +0 -20
  24. package/packages/model-runtime/src/utils/createError.ts +0 -1
  25. package/public/favicon-32x-32-error.ico +0 -0
  26. package/public/favicon-32x32-done-dev.ico +0 -0
  27. package/public/favicon-32x32-done.ico +0 -0
  28. package/public/favicon-32x32-error-dev.ico +0 -0
  29. package/public/favicon-32x32-progress-dev.ico +0 -0
  30. package/public/favicon-32x32-progress.ico +0 -0
  31. package/public/favicon-done-dev.ico +0 -0
  32. package/public/favicon-done.ico +0 -0
  33. package/public/favicon-error-dev.ico +0 -0
  34. package/public/favicon-error.ico +0 -0
  35. package/public/favicon-progress-dev.ico +0 -0
  36. package/public/favicon-progress.ico +0 -0
  37. package/src/app/(backend)/market/agent/[[...segments]]/route.ts +3 -33
  38. package/src/app/(backend)/market/oidc/[[...segments]]/route.ts +5 -6
  39. package/src/app/(backend)/market/social/[[...segments]]/route.ts +5 -52
  40. package/src/app/(backend)/market/user/[username]/route.ts +3 -9
  41. package/src/app/(backend)/market/user/me/route.ts +3 -34
  42. package/src/app/[variants]/(main)/agent/profile/features/Header/AgentPublishButton/PublishResultModal.tsx +1 -1
  43. package/src/app/[variants]/(main)/community/(detail)/_layout/Header.tsx +15 -3
  44. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Overview/TagList.tsx +1 -1
  45. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Related/index.tsx +2 -2
  46. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/SystemRole/TagList.tsx +1 -1
  47. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/SystemRole/index.tsx +1 -1
  48. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Header.tsx +2 -2
  49. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Sidebar/ActionButton/AddAgent.tsx +1 -1
  50. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Sidebar/ActionButton/index.tsx +1 -1
  51. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Sidebar/Related/index.tsx +2 -2
  52. package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/StatusPage/index.tsx +2 -2
  53. package/src/app/[variants]/(main)/community/(detail)/user/features/UserAgentCard.tsx +2 -2
  54. package/src/app/[variants]/(main)/community/(detail)/user/features/UserFavoriteAgents.tsx +1 -1
  55. package/src/app/[variants]/(main)/community/(list)/(home)/index.tsx +2 -2
  56. package/src/app/[variants]/(main)/community/(list)/(home)/loading.tsx +1 -1
  57. package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/Client.tsx +5 -1
  58. package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/features/Category/index.tsx +1 -1
  59. package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/features/List/Item.tsx +1 -1
  60. package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/features/MarketSourceSwitch.tsx +1 -1
  61. package/src/app/[variants]/(main)/community/_layout/Sidebar/Header/Nav.tsx +2 -2
  62. package/src/app/[variants]/(main)/home/features/CommunityAgents/List.tsx +1 -1
  63. package/src/app/[variants]/(main)/home/features/CommunityAgents/index.tsx +1 -1
  64. package/src/app/[variants]/(mobile)/_layout/index.tsx +1 -1
  65. package/src/app/[variants]/(mobile)/router/mobileRouter.config.tsx +6 -6
  66. package/src/app/[variants]/router/desktopRouter.config.tsx +8 -8
  67. package/src/app/[variants]/share/t/[id]/_layout/index.tsx +1 -1
  68. package/src/features/ChatMiniMap/useMinimapData.ts +1 -1
  69. package/src/features/CommandMenu/SearchResults.tsx +1 -1
  70. package/src/features/Conversation/ChatList/components/VirtualizedList.tsx +20 -2
  71. package/src/features/Conversation/store/slices/virtuaList/action.ts +9 -0
  72. package/src/features/Electron/navigation/routeMetadata.ts +1 -1
  73. package/src/layout/GlobalProvider/FaviconProvider.tsx +92 -0
  74. package/src/layout/GlobalProvider/index.tsx +15 -11
  75. package/src/libs/next/config/define-config.ts +1 -1
  76. package/src/libs/trpc/lambda/middleware/marketSDK.ts +14 -23
  77. package/src/libs/trusted-client/index.ts +1 -1
  78. package/src/server/routers/lambda/market/index.ts +5 -0
  79. package/src/server/routers/lambda/market/oidc.ts +41 -61
  80. package/src/server/routers/tools/market.ts +12 -44
  81. package/src/server/services/agentRuntime/AgentRuntimeService.test.ts +7 -0
  82. package/src/server/services/agentRuntime/AgentRuntimeService.ts +1 -1
  83. package/src/server/services/aiAgent/__tests__/execAgent.threadId.test.ts +7 -0
  84. package/src/server/services/aiAgent/__tests__/execGroupSubAgentTask.test.ts +7 -0
  85. package/src/server/services/aiAgent/index.ts +9 -96
  86. package/src/server/services/discover/index.ts +11 -16
  87. package/src/server/services/market/index.ts +485 -0
  88. package/src/server/services/toolExecution/builtin.ts +11 -17
  89. package/src/server/services/toolExecution/index.ts +6 -2
  90. package/src/server/sitemap.test.ts +5 -5
  91. package/src/server/sitemap.ts +3 -3
  92. package/src/services/codeInterpreter.ts +0 -13
  93. package/packages/model-runtime/src/types/textToImage.ts +0 -36
  94. package/src/server/services/lobehubSkill/index.ts +0 -109
  95. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/DetailProvider.tsx +0 -0
  96. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Capabilities/Block.tsx +0 -0
  97. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Capabilities/Knowledge.tsx +0 -0
  98. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Capabilities/KnowledgeItem.tsx +0 -0
  99. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Capabilities/PluginItem.tsx +0 -0
  100. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Capabilities/Plugins.tsx +0 -0
  101. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Capabilities/index.tsx +0 -0
  102. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Nav.tsx +0 -0
  103. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Overview/index.tsx +0 -0
  104. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/Versions/index.tsx +0 -0
  105. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Details/index.tsx +0 -0
  106. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Sidebar/Related/Item.tsx +0 -0
  107. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Sidebar/Summary/index.tsx +0 -0
  108. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Sidebar/TocList/index.tsx +0 -0
  109. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/features/Sidebar/index.tsx +0 -0
  110. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/index.tsx +0 -0
  111. /package/src/app/[variants]/(main)/community/(detail)/{assistant → agent}/loading.tsx +0 -0
  112. /package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/_layout/index.tsx +0 -0
  113. /package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/_layout/style.ts +0 -0
  114. /package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/features/Category/useCategory.tsx +0 -0
  115. /package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/features/List/TokenTag.tsx +0 -0
  116. /package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/features/List/index.tsx +0 -0
  117. /package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/index.tsx +0 -0
  118. /package/src/app/[variants]/(main)/community/(list)/{assistant → agent}/loading.tsx +0 -0
@@ -1,7 +1,6 @@
1
- import { MarketSDK } from '@lobehub/market-sdk';
2
1
  import { type NextRequest, NextResponse } from 'next/server';
3
2
 
4
- import { getTrustedClientTokenForSession } from '@/libs/trusted-client';
3
+ import { MarketService } from '@/server/services/market';
5
4
 
6
5
  type RouteContext = {
7
6
  params: Promise<{
@@ -9,19 +8,6 @@ type RouteContext = {
9
8
  }>;
10
9
  };
11
10
 
12
- const MARKET_BASE_URL = process.env.NEXT_PUBLIC_MARKET_BASE_URL || 'https://market.lobehub.com';
13
-
14
- /**
15
- * Helper to get authorization header
16
- */
17
- const getAccessToken = (req: NextRequest): string | undefined => {
18
- const authHeader = req.headers.get('authorization');
19
- if (authHeader?.startsWith('Bearer ')) {
20
- return authHeader.slice(7);
21
- }
22
- return undefined;
23
- };
24
-
25
11
  /**
26
12
  * POST /market/social/follow
27
13
  * POST /market/social/unfollow
@@ -34,22 +20,9 @@ const getAccessToken = (req: NextRequest): string | undefined => {
34
20
  export const POST = async (req: NextRequest, context: RouteContext) => {
35
21
  const { segments = [] } = await context.params;
36
22
  const action = segments[0];
37
- const accessToken = getAccessToken(req);
38
- const trustedClientToken = await getTrustedClientTokenForSession();
39
-
40
- const market = new MarketSDK({
41
- accessToken,
42
- baseURL: MARKET_BASE_URL,
43
- trustedClientToken,
44
- });
45
23
 
46
- // Only require accessToken if trusted client token is not available
47
- if (!accessToken && !trustedClientToken) {
48
- return NextResponse.json(
49
- { error: 'unauthorized', message: 'Access token required' },
50
- { status: 401 },
51
- );
52
- }
24
+ const marketService = await MarketService.createFromRequest(req);
25
+ const market = marketService.market;
53
26
 
54
27
  try {
55
28
  const body = await req.json();
@@ -135,14 +108,9 @@ export const POST = async (req: NextRequest, context: RouteContext) => {
135
108
  export const GET = async (req: NextRequest, context: RouteContext) => {
136
109
  const { segments = [] } = await context.params;
137
110
  const action = segments[0];
138
- const accessToken = getAccessToken(req);
139
- const trustedClientToken = await getTrustedClientTokenForSession();
140
111
 
141
- const market = new MarketSDK({
142
- accessToken,
143
- baseURL: MARKET_BASE_URL,
144
- trustedClientToken,
145
- });
112
+ const marketService = await MarketService.createFromRequest(req);
113
+ const market = marketService.market;
146
114
 
147
115
  const url = new URL(req.url);
148
116
  const limit = url.searchParams.get('pageSize') || url.searchParams.get('limit');
@@ -158,9 +126,6 @@ export const GET = async (req: NextRequest, context: RouteContext) => {
158
126
  // Follow queries
159
127
  case 'follow-status': {
160
128
  const targetUserId = Number(segments[1]);
161
- if (!accessToken && !trustedClientToken) {
162
- return NextResponse.json({ isFollowing: false, isMutual: false });
163
- }
164
129
  const result = await market.follows.checkFollowStatus(targetUserId);
165
130
  return NextResponse.json(result);
166
131
  }
@@ -193,9 +158,6 @@ export const GET = async (req: NextRequest, context: RouteContext) => {
193
158
  case 'favorite-status': {
194
159
  const targetType = segments[1] as 'agent' | 'plugin';
195
160
  const targetIdOrIdentifier = segments[2];
196
- if (!accessToken && !trustedClientToken) {
197
- return NextResponse.json({ isFavorited: false });
198
- }
199
161
  // SDK accepts both number (targetId) and string (identifier)
200
162
  const isNumeric = /^\d+$/.test(targetIdOrIdentifier);
201
163
  const targetValue = isNumeric ? Number(targetIdOrIdentifier) : targetIdOrIdentifier;
@@ -204,12 +166,6 @@ export const GET = async (req: NextRequest, context: RouteContext) => {
204
166
  }
205
167
 
206
168
  case 'favorites': {
207
- if (!accessToken) {
208
- return NextResponse.json(
209
- { error: 'unauthorized', message: 'Access token required' },
210
- { status: 401 },
211
- );
212
- }
213
169
  const result = await market.favorites.getMyFavorites(paginationParams);
214
170
  return NextResponse.json(result);
215
171
  }
@@ -236,9 +192,6 @@ export const GET = async (req: NextRequest, context: RouteContext) => {
236
192
  case 'like-status': {
237
193
  const targetType = segments[1] as 'agent' | 'plugin';
238
194
  const targetIdOrIdentifier = segments[2];
239
- if (!accessToken && !trustedClientToken) {
240
- return NextResponse.json({ isLiked: false });
241
- }
242
195
  const isNumeric = /^\d+$/.test(targetIdOrIdentifier);
243
196
  const targetValue = isNumeric ? Number(targetIdOrIdentifier) : targetIdOrIdentifier;
244
197
  const result = await market.likes.checkLike(targetType, targetValue as number);
@@ -1,7 +1,6 @@
1
- import { MarketSDK } from '@lobehub/market-sdk';
2
1
  import { type NextRequest, NextResponse } from 'next/server';
3
2
 
4
- import { getTrustedClientTokenForSession } from '@/libs/trusted-client';
3
+ import { MarketService } from '@/server/services/market';
5
4
 
6
5
  type RouteContext = {
7
6
  params: Promise<{
@@ -9,8 +8,6 @@ type RouteContext = {
9
8
  }>;
10
9
  };
11
10
 
12
- const MARKET_BASE_URL = process.env.NEXT_PUBLIC_MARKET_BASE_URL || 'https://market.lobehub.com';
13
-
14
11
  /**
15
12
  * GET /market/user/[username]
16
13
  *
@@ -20,12 +17,9 @@ const MARKET_BASE_URL = process.env.NEXT_PUBLIC_MARKET_BASE_URL || 'https://mark
20
17
  export const GET = async (req: NextRequest, context: RouteContext) => {
21
18
  const { username } = await context.params;
22
19
  const decodedUsername = decodeURIComponent(username);
23
- const trustedClientToken = await getTrustedClientTokenForSession();
24
20
 
25
- const market = new MarketSDK({
26
- baseURL: MARKET_BASE_URL,
27
- trustedClientToken,
28
- });
21
+ const marketService = await MarketService.createFromRequest(req);
22
+ const market = marketService.market;
29
23
 
30
24
  try {
31
25
  const response = await market.user.getUserInfo(decodedUsername);
@@ -1,19 +1,6 @@
1
- import { MarketSDK } from '@lobehub/market-sdk';
2
1
  import { type NextRequest, NextResponse } from 'next/server';
3
2
 
4
- import { getTrustedClientTokenForSession } from '@/libs/trusted-client';
5
-
6
- const MARKET_BASE_URL = process.env.NEXT_PUBLIC_MARKET_BASE_URL || 'https://market.lobehub.com';
7
-
8
- const extractAccessToken = (req: NextRequest) => {
9
- const authorization = req.headers.get('authorization');
10
- if (!authorization) return undefined;
11
-
12
- const [scheme, token] = authorization.split(' ');
13
- if (scheme?.toLowerCase() !== 'bearer' || !token) return undefined;
14
-
15
- return token;
16
- };
3
+ import { MarketService } from '@/server/services/market';
17
4
 
18
5
  /**
19
6
  * PUT /market/user/me
@@ -28,26 +15,8 @@ const extractAccessToken = (req: NextRequest) => {
28
15
  * - meta?: { description?: string; socialLinks?: { github?: string; twitter?: string; website?: string } }
29
16
  */
30
17
  export const PUT = async (req: NextRequest) => {
31
- const accessToken = extractAccessToken(req);
32
- const trustedClientToken = await getTrustedClientTokenForSession();
33
-
34
- const market = new MarketSDK({
35
- accessToken,
36
- baseURL: MARKET_BASE_URL,
37
- trustedClientToken,
38
- });
39
-
40
- // Only require accessToken if trusted client token is not available
41
- if (!accessToken && !trustedClientToken) {
42
- return NextResponse.json(
43
- {
44
- error: 'unauthorized',
45
- message: 'Authentication required to update user profile',
46
- status: 'error',
47
- },
48
- { status: 401 },
49
- );
50
- }
18
+ const marketService = await MarketService.createFromRequest(req);
19
+ const market = marketService.market;
51
20
 
52
21
  try {
53
22
  const payload = await req.json();
@@ -19,7 +19,7 @@ const PublishResultModal = memo<PublishResultModalProps>(({ identifier, onCancel
19
19
 
20
20
  const handleGoToMarket = () => {
21
21
  if (identifier) {
22
- navigate(`/community/assistant/${identifier}`);
22
+ navigate(`/community/agent/${identifier}`);
23
23
  }
24
24
  onCancel();
25
25
  };
@@ -18,11 +18,23 @@ const Header = memo(() => {
18
18
  const navigate = useNavigate();
19
19
 
20
20
  const handleGoBack = () => {
21
- // Extract the path segment (assistant, model, provider, mcp)
21
+ // Extract the path segment (agent, model, provider, mcp, group_agent, user)
22
22
  const path = location.pathname.split('/').filter(Boolean);
23
- if (path[1] && path[1] !== 'user') {
24
- navigate(urlJoin('/community', path[1]));
23
+ const detailType = path[1];
24
+
25
+ // group_agent goes back to agent list page
26
+ if (detailType === 'group_agent') {
27
+ navigate('/community/agent');
28
+ return;
29
+ }
30
+
31
+ // Types that have their own list pages
32
+ const typesWithListPage = ['agent', 'model', 'provider', 'mcp'];
33
+
34
+ if (detailType && typesWithListPage.includes(detailType)) {
35
+ navigate(urlJoin('/community', detailType));
25
36
  } else {
37
+ // For user or any other type without a list page
26
38
  navigate('/community');
27
39
  }
28
40
  };
@@ -38,7 +38,7 @@ const TagList = memo<{ tags: string[] }>(({ tags }) => {
38
38
  q: tag,
39
39
  source: marketSource,
40
40
  },
41
- url: '/community/assistant',
41
+ url: '/community/agent',
42
42
  },
43
43
  { skipNull: true },
44
44
  )}
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
6
6
  import { useQuery } from '@/hooks/useQuery';
7
7
  import { type AssistantMarketSource } from '@/types/discover';
8
8
 
9
- import McpList from '../../../../../(list)/assistant/features/List';
9
+ import McpList from '../../../../../(list)/agent/features/List';
10
10
  import Title from '../../../../../features/Title';
11
11
  import { useDetailContext } from '../../DetailProvider';
12
12
 
@@ -25,7 +25,7 @@ const Related = memo(() => {
25
25
  category,
26
26
  source: marketSource,
27
27
  },
28
- url: '/community/assistant',
28
+ url: '/community/agent',
29
29
  },
30
30
  { skipNull: true },
31
31
  )}
@@ -38,7 +38,7 @@ const TagList = memo<{ tags: string[] }>(({ tags }) => {
38
38
  q: tag,
39
39
  source: marketSource,
40
40
  },
41
- url: '/community/assistant',
41
+ url: '/community/agent',
42
42
  },
43
43
  { skipNull: true },
44
44
  )}
@@ -4,7 +4,7 @@ import { MessageCircleHeartIcon, MessageCircleQuestionIcon } from 'lucide-react'
4
4
  import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
- import TokenTag from '../../../../../(list)/assistant/features/List/TokenTag';
7
+ import TokenTag from '../../../../../(list)/agent/features/List/TokenTag';
8
8
  import Title from '../../../../../features/Title';
9
9
  import MarkdownRender from '../../../../features/MakedownRender';
10
10
  import { useDetailContext } from '../../DetailProvider';
@@ -32,7 +32,7 @@ import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
32
32
  import { socialService } from '@/services/social';
33
33
  import { formatIntergerNumber } from '@/utils/format';
34
34
 
35
- import { useCategory } from '../../../(list)/assistant/features/Category/useCategory';
35
+ import { useCategory } from '../../../(list)/agent/features/Category/useCategory';
36
36
  import PublishedTime from '../../../../../../../components/PublishedTime';
37
37
  import { useDetailContext } from './DetailProvider';
38
38
 
@@ -142,7 +142,7 @@ const Header = memo<{ mobile?: boolean }>(({ mobile: isMobile }) => {
142
142
  <Link
143
143
  to={qs.stringifyUrl({
144
144
  query: { category: cate?.key },
145
- url: '/community/assistant',
145
+ url: '/community/agent',
146
146
  })}
147
147
  >
148
148
  <Button icon={cate?.icon} size={'middle'} variant={'outlined'}>
@@ -87,7 +87,7 @@ const AddAgent = memo<{ mobile?: boolean }>(({ mobile }) => {
87
87
  event: 'add',
88
88
  identifier,
89
89
  source: location.pathname,
90
- })
90
+ });
91
91
  }
92
92
 
93
93
  if (shouldNavigate) {
@@ -21,7 +21,7 @@ const ActionButton = memo<{ mobile?: boolean }>(({ mobile }) => {
21
21
  desc: description,
22
22
  hashtags: tags,
23
23
  title: title,
24
- url: urlJoin(OFFICIAL_URL, '/community/assistant', identifier as string),
24
+ url: urlJoin(OFFICIAL_URL, '/community/agent', identifier as string),
25
25
  }}
26
26
  />
27
27
  </Flexbox>
@@ -28,7 +28,7 @@ const Related = memo(() => {
28
28
  category,
29
29
  source: marketSource,
30
30
  },
31
- url: '/community/assistant',
31
+ url: '/community/agent',
32
32
  },
33
33
  { skipNull: true },
34
34
  )}
@@ -40,7 +40,7 @@ const Related = memo(() => {
40
40
  const link = qs.stringifyUrl(
41
41
  {
42
42
  query: marketSource ? { source: marketSource } : undefined,
43
- url: urlJoin('/community/assistant', item.identifier),
43
+ url: urlJoin('/community/agent', item.identifier),
44
44
  },
45
45
  { skipNull: true },
46
46
  );
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { ExclamationCircleOutlined, FolderOpenOutlined } from '@ant-design/icons';
4
- import { FluentEmoji, Text , Button } from '@lobehub/ui';
4
+ import { Button, FluentEmoji, Text } from '@lobehub/ui';
5
5
  import { Result } from 'antd';
6
6
  import { memo } from 'react';
7
7
  import { Trans, useTranslation } from 'react-i18next';
@@ -16,7 +16,7 @@ const StatusPage = memo<StatusPageProps>(({ status }) => {
16
16
  const { t } = useTranslation('discover');
17
17
 
18
18
  const handleBackToMarket = () => {
19
- navigate('/community/assistant');
19
+ navigate('/community/agent');
20
20
  };
21
21
 
22
22
  // 审核中状态
@@ -142,7 +142,7 @@ const UserAgentCard = memo<UserAgentCardProps>(
142
142
  const link = qs.stringifyUrl(
143
143
  {
144
144
  query: { source: 'new' },
145
- url: urlJoin('/community/assistant', identifier),
145
+ url: urlJoin('/community/agent', identifier),
146
146
  },
147
147
  { skipNull: true },
148
148
  );
@@ -150,7 +150,7 @@ const UserAgentCard = memo<UserAgentCardProps>(
150
150
  const isPublished = status === 'published';
151
151
 
152
152
  const handleViewDetail = useCallback(() => {
153
- window.open(urlJoin('/community/assistant', identifier), '_blank');
153
+ window.open(urlJoin('/community/agent', identifier), '_blank');
154
154
  }, [identifier]);
155
155
 
156
156
  const handleEdit = useCallback(async () => {
@@ -96,7 +96,7 @@ const FavoriteAgentCard = memo<FavoriteAgentCardProps>(
96
96
  const link = qs.stringifyUrl(
97
97
  {
98
98
  query: { source: 'new' },
99
- url: urlJoin('/community/assistant', identifier),
99
+ url: urlJoin('/community/agent', identifier),
100
100
  },
101
101
  { skipNull: true },
102
102
  );
@@ -7,7 +7,7 @@ import { useDiscoverStore } from '@/store/discover';
7
7
  import { AssistantSorts, McpSorts } from '@/types/discover';
8
8
 
9
9
  import Title from '../../components/Title';
10
- import AssistantList from '../assistant/features/List';
10
+ import AssistantList from '../agent/features/List';
11
11
  import McpList from '../mcp/features/List';
12
12
  import Loading from './loading';
13
13
 
@@ -32,7 +32,7 @@ const HomePage = memo(() => {
32
32
 
33
33
  return (
34
34
  <>
35
- <Title more={t('home.more')} moreLink={'/community/assistant'}>
35
+ <Title more={t('home.more')} moreLink={'/community/agent'}>
36
36
  {t('home.featuredAssistants')}
37
37
  </Title>
38
38
  <AssistantList data={assistantList.items} rows={4} />
@@ -9,7 +9,7 @@ const Loading = memo(() => {
9
9
 
10
10
  return (
11
11
  <>
12
- <Title more={t('home.more')} moreLink={'/community/assistant'}>
12
+ <Title more={t('home.more')} moreLink={'/community/agent'}>
13
13
  {t('home.featuredAssistants')}
14
14
  </Title>
15
15
  <ListLoading length={8} rows={4} />
@@ -6,7 +6,11 @@ import { memo } from 'react';
6
6
  import { withSuspense } from '@/components/withSuspense';
7
7
  import { useQuery } from '@/hooks/useQuery';
8
8
  import { useDiscoverStore } from '@/store/discover';
9
- import { type AssistantMarketSource, type AssistantQueryParams, DiscoverTab } from '@/types/discover';
9
+ import {
10
+ type AssistantMarketSource,
11
+ type AssistantQueryParams,
12
+ DiscoverTab,
13
+ } from '@/types/discover';
10
14
 
11
15
  import Pagination from '../features/Pagination';
12
16
  import List from './features/List';
@@ -29,7 +29,7 @@ const Category = memo(() => {
29
29
  qs.stringifyUrl(
30
30
  {
31
31
  query: { category: key === AssistantCategory.All ? null : key, q, source },
32
- url: '/community/assistant',
32
+ url: '/community/agent',
33
33
  },
34
34
  { skipNull: true },
35
35
  );
@@ -73,7 +73,7 @@ const AssistantItem = memo<DiscoverAssistantItem>(
73
73
  const navigate = useNavigate();
74
74
  const { source } = useQuery() as { source?: AssistantMarketSource };
75
75
  const isGroupAgent = type === 'agent-group';
76
- const basePath = isGroupAgent ? '/community/group_agent' : '/community/assistant';
76
+ const basePath = isGroupAgent ? '/community/group_agent' : '/community/agent';
77
77
  const link = qs.stringifyUrl(
78
78
  {
79
79
  query: { source },
@@ -41,7 +41,7 @@ const MarketSourceSwitch = memo(() => {
41
41
  );
42
42
 
43
43
  const handleChange = (value: AssistantMarketSource) => {
44
- router.push('/community/assistant', {
44
+ router.push('/community/agent', {
45
45
  query: {
46
46
  page: null,
47
47
  source: value === 'new' ? null : value,
@@ -3,12 +3,12 @@
3
3
  import { Flexbox } from '@lobehub/ui';
4
4
  import { McpIcon, ProviderIcon } from '@lobehub/ui/icons';
5
5
  import { Bot, Brain, ShapesIcon } from 'lucide-react';
6
- import { usePathname } from '@/libs/router/navigation';
7
6
  import { memo, useMemo } from 'react';
8
7
  import { useTranslation } from 'react-i18next';
9
8
  import { Link, useNavigate } from 'react-router-dom';
10
9
 
11
10
  import NavItem, { type NavItemProps } from '@/features/NavPanel/components/NavItem';
11
+ import { usePathname } from '@/libs/router/navigation';
12
12
  import { DiscoverTab } from '@/types/discover';
13
13
 
14
14
  interface Item {
@@ -42,7 +42,7 @@ const Nav = memo(() => {
42
42
  icon: Bot,
43
43
  key: DiscoverTab.Assistants,
44
44
  title: t('tab.assistant'),
45
- url: '/community/assistant',
45
+ url: '/community/agent',
46
46
  },
47
47
  {
48
48
  icon: McpIcon,
@@ -41,7 +41,7 @@ const CommunityAgentsList = memo(() => {
41
41
  color: 'inherit',
42
42
  textDecoration: 'none',
43
43
  }}
44
- to={urlJoin('/community/assistant', item.identifier)}
44
+ to={urlJoin('/community/agent', item.identifier)}
45
45
  >
46
46
  <CommunityAgentItem {...item} />
47
47
  </Link>
@@ -24,7 +24,7 @@ const CommunityAgents = memo(() => {
24
24
  key: 'all-assistants',
25
25
  label: t('home.more'),
26
26
  onClick: () => {
27
- navigate('/community/assistant');
27
+ navigate('/community/agent');
28
28
  },
29
29
  },
30
30
  ]}
@@ -15,7 +15,7 @@ const CloudBanner = dynamic(() => import('@/features/AlertBanner/CloudBanner'));
15
15
  const MOBILE_NAV_ROUTES = new Set([
16
16
  '/',
17
17
  '/community',
18
- '/community/assistant',
18
+ '/community/agent',
19
19
  '/community/mcp',
20
20
  '/community/plugin',
21
21
  '/community/model',
@@ -65,10 +65,10 @@ export const mobileRoutes: RouteConfig[] = [
65
65
  children: [
66
66
  {
67
67
  element: dynamicElement(
68
- () => import('../../(main)/community/(list)/assistant'),
69
- 'Mobile > Discover > List > Assistant',
68
+ () => import('../../(main)/community/(list)/agent'),
69
+ 'Mobile > Discover > List > Agent',
70
70
  ),
71
- path: 'assistant',
71
+ path: 'agent',
72
72
  },
73
73
  ],
74
74
  },
@@ -113,12 +113,12 @@ export const mobileRoutes: RouteConfig[] = [
113
113
  {
114
114
  element: dynamicElement(
115
115
  () =>
116
- import('../../(main)/community/(detail)/assistant').then(
116
+ import('../../(main)/community/(detail)/agent').then(
117
117
  (m) => m.MobileDiscoverAssistantDetailPage,
118
118
  ),
119
- 'Mobile > Discover > Detail > Assistant',
119
+ 'Mobile > Discover > Detail > Agent',
120
120
  ),
121
- path: 'assistant/:slug',
121
+ path: 'agent/:slug',
122
122
  },
123
123
  {
124
124
  element: dynamicElement(
@@ -94,17 +94,17 @@ export const desktopRoutes: RouteConfig[] = [
94
94
  children: [
95
95
  {
96
96
  element: dynamicElement(
97
- () => import('../(main)/community/(list)/assistant'),
98
- 'Desktop > Discover > List > Assistant',
97
+ () => import('../(main)/community/(list)/agent'),
98
+ 'Desktop > Discover > List > Agent',
99
99
  ),
100
100
  index: true,
101
101
  },
102
102
  ],
103
103
  element: dynamicElement(
104
- () => import('../(main)/community/(list)/assistant/_layout'),
105
- 'Desktop > Discover > List > Assistant > Layout',
104
+ () => import('../(main)/community/(list)/agent/_layout'),
105
+ 'Desktop > Discover > List > Agent > Layout',
106
106
  ),
107
- path: 'assistant',
107
+ path: 'agent',
108
108
  },
109
109
  {
110
110
  children: [
@@ -163,10 +163,10 @@ export const desktopRoutes: RouteConfig[] = [
163
163
  children: [
164
164
  {
165
165
  element: dynamicElement(
166
- () => import('../(main)/community/(detail)/assistant'),
167
- 'Desktop > Discover > Detail > Assistant',
166
+ () => import('../(main)/community/(detail)/agent'),
167
+ 'Desktop > Discover > Detail > Agent',
168
168
  ),
169
- path: 'assistant/:slug',
169
+ path: 'agent/:slug',
170
170
  },
171
171
  {
172
172
  element: dynamicElement(
@@ -116,7 +116,7 @@ const ShareTopicLayout = memo<PropsWithChildren>(({ children }) => {
116
116
  // If agent has marketIdentifier, render as link to assistant page
117
117
  if (agentMarketIdentifier && !data?.groupMeta?.title) {
118
118
  return (
119
- <a href={`/community/assistant/${agentMarketIdentifier}`} rel="noreferrer" target="_blank">
119
+ <a href={`/community/agent/${agentMarketIdentifier}`} rel="noreferrer" target="_blank">
120
120
  <Typography.Text ellipsis strong>
121
121
  {agentOrGroupTitle}
122
122
  </Typography.Text>
@@ -91,7 +91,7 @@ export const useMinimapData = () => {
91
91
  }
92
92
  } else {
93
93
  // No active index, go to first/last
94
- targetPosition = direction === 'prev' ? indicators.length - 1 : 0;
94
+ targetPosition = direction === 'prev' ? 0 : indicators.length - 1;
95
95
  }
96
96
 
97
97
  const targetIndicator = indicators[targetPosition];
@@ -101,7 +101,7 @@ const SearchResults = memo<SearchResultsProps>(
101
101
  break;
102
102
  }
103
103
  case 'communityAgent': {
104
- navigate(`/community/assistant/${result.identifier}`);
104
+ navigate(`/community/agent/${result.identifier}`);
105
105
  break;
106
106
  }
107
107
  }