@lobehub/lobehub 2.0.0-next.166 → 2.0.0-next.168

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 (75) hide show
  1. package/.husky/pre-commit +1 -1
  2. package/AGENTS.md +1 -1
  3. package/CHANGELOG.md +50 -0
  4. package/CLAUDE.md +2 -2
  5. package/GEMINI.md +1 -1
  6. package/README.md +1 -1
  7. package/README.zh-CN.md +1 -1
  8. package/apps/desktop/package.json +4 -4
  9. package/apps/desktop/tsconfig.json +4 -13
  10. package/changelog/v1.json +18 -0
  11. package/docs/development/database-schema.dbml +1 -0
  12. package/locales/ar/models.json +12 -0
  13. package/locales/ar/providers.json +3 -0
  14. package/locales/bg-BG/models.json +12 -0
  15. package/locales/bg-BG/providers.json +3 -0
  16. package/locales/de-DE/models.json +12 -0
  17. package/locales/de-DE/providers.json +3 -0
  18. package/locales/en-US/models.json +12 -0
  19. package/locales/en-US/providers.json +3 -0
  20. package/locales/es-ES/models.json +12 -0
  21. package/locales/es-ES/providers.json +3 -0
  22. package/locales/fa-IR/models.json +12 -0
  23. package/locales/fa-IR/providers.json +3 -0
  24. package/locales/fr-FR/models.json +12 -0
  25. package/locales/fr-FR/providers.json +3 -0
  26. package/locales/it-IT/models.json +12 -0
  27. package/locales/it-IT/providers.json +3 -0
  28. package/locales/ja-JP/models.json +12 -0
  29. package/locales/ja-JP/providers.json +3 -0
  30. package/locales/ko-KR/models.json +12 -0
  31. package/locales/ko-KR/providers.json +3 -0
  32. package/locales/nl-NL/models.json +12 -0
  33. package/locales/nl-NL/providers.json +3 -0
  34. package/locales/pl-PL/models.json +12 -0
  35. package/locales/pl-PL/providers.json +3 -0
  36. package/locales/pt-BR/models.json +12 -0
  37. package/locales/pt-BR/providers.json +3 -0
  38. package/locales/ru-RU/models.json +12 -0
  39. package/locales/ru-RU/providers.json +3 -0
  40. package/locales/tr-TR/models.json +12 -0
  41. package/locales/tr-TR/providers.json +3 -0
  42. package/locales/vi-VN/models.json +12 -0
  43. package/locales/vi-VN/providers.json +3 -0
  44. package/locales/zh-CN/models.json +12 -0
  45. package/locales/zh-CN/providers.json +3 -0
  46. package/locales/zh-TW/models.json +12 -0
  47. package/locales/zh-TW/providers.json +3 -0
  48. package/package.json +43 -43
  49. package/packages/database/migrations/0060_add_user_last_active_at.sql +1 -0
  50. package/packages/database/migrations/meta/0060_snapshot.json +8481 -0
  51. package/packages/database/migrations/meta/_journal.json +8 -1
  52. package/packages/database/src/core/migrations.json +9 -1
  53. package/packages/database/src/schemas/user.ts +1 -0
  54. package/packages/fetch-sse/src/__tests__/headers.test.ts +2 -2
  55. package/packages/model-bank/package.json +1 -0
  56. package/packages/model-bank/src/aiModels/index.ts +3 -0
  57. package/packages/model-bank/src/aiModels/replicate.ts +90 -0
  58. package/packages/model-bank/src/const/modelProvider.ts +1 -0
  59. package/packages/model-runtime/docs/test-coverage.md +5 -5
  60. package/packages/model-runtime/package.json +2 -1
  61. package/packages/model-runtime/src/core/ModelRuntime.ts +11 -1
  62. package/packages/model-runtime/src/providers/replicate/index.ts +424 -0
  63. package/packages/model-runtime/src/runtimeMap.ts +2 -0
  64. package/packages/model-runtime/src/utils/modelParse.ts +13 -0
  65. package/packages/ssrf-safe-fetch/index.browser.ts +22 -2
  66. package/packages/ssrf-safe-fetch/index.ts +30 -6
  67. package/packages/types/src/aiProvider.ts +2 -0
  68. package/src/config/modelProviders/index.ts +3 -0
  69. package/src/config/modelProviders/replicate.ts +23 -0
  70. package/src/libs/oidc-provider/provider.ts +2 -73
  71. package/src/server/routers/lambda/__tests__/user.test.ts +2 -0
  72. package/src/server/routers/lambda/market/index.ts +5 -2
  73. package/src/server/routers/lambda/user.ts +5 -0
  74. package/src/services/mcp.ts +1 -0
  75. package/src/store/test-coverage.md +19 -19
@@ -1,11 +1,9 @@
1
- import type { EmailAddress } from '@clerk/backend';
2
1
  import { LobeChatDatabase } from '@lobechat/database';
3
2
  import debug from 'debug';
4
3
  import Provider, { Configuration, KoaContextWithOIDC, errors } from 'oidc-provider';
5
4
  import urlJoin from 'url-join';
6
5
 
7
6
  import { serverDBEnv } from '@/config/db';
8
- import { enableClerk } from '@/const/auth';
9
7
  import { UserModel } from '@/database/models/user';
10
8
  import { appEnv } from '@/envs/app';
11
9
  import { getJWKS } from '@/libs/oidc-provider/jwt';
@@ -15,59 +13,9 @@ import { DrizzleAdapter } from './adapter';
15
13
  import { defaultClaims, defaultClients, defaultScopes } from './config';
16
14
  import { createInteractionPolicy } from './interaction-policy';
17
15
 
18
- const logProvider = debug('lobe-oidc:provider'); // <--- 添加 provider 日志实例
16
+ const logProvider = debug('lobe-oidc:provider');
19
17
 
20
- const MARKET_CLIENT_ID = 'lobehub-market';
21
-
22
- const resolveClerkAccount = async (accountId: string) => {
23
- if (!enableClerk) return undefined;
24
-
25
- try {
26
- const { clerkClient } = await import('@clerk/nextjs/server');
27
- const client = await clerkClient();
28
- const user = await client.users.getUser(accountId);
29
-
30
- if (!user) {
31
- logProvider('Clerk user not found for accountId: %s', accountId);
32
- return undefined;
33
- }
34
-
35
- const pickName = () =>
36
- user.fullName ||
37
- [user.firstName, user.lastName].filter(Boolean).join(' ').trim() ||
38
- user.username ||
39
- user.id;
40
-
41
- const primaryEmail = user.primaryEmailAddressId
42
- ? user.emailAddresses.find((item: EmailAddress) => item.id === user.primaryEmailAddressId)
43
- : user.emailAddresses.at(0);
44
-
45
- return {
46
- accountId: user.id,
47
- async claims(_use: string, scope: string) {
48
- const scopeSet = new Set((scope || '').split(/\s+/).filter(Boolean));
49
- const claims: { [key: string]: any; sub: string } = { sub: user.id };
50
-
51
- if (scopeSet.has('profile')) {
52
- claims.name = pickName();
53
- if (user.imageUrl) claims.picture = user.imageUrl;
54
- }
55
-
56
- if (scopeSet.has('email') && primaryEmail) {
57
- claims.email = primaryEmail.emailAddress;
58
- claims.email_verified = primaryEmail.verification?.status === 'verified' || false;
59
- }
60
-
61
- return claims;
62
- },
63
- };
64
- } catch (error) {
65
- logProvider('Error resolving Clerk account for %s: %O', accountId, error);
66
- return undefined;
67
- }
68
- };
69
-
70
- export const API_AUDIENCE = 'urn:lobehub:chat'; // <-- 把这里换成你自己的 API 标识符
18
+ export const API_AUDIENCE = 'urn:lobehub:chat';
71
19
 
72
20
  /**
73
21
  * 获取 Cookie 密钥,使用 KEY_VAULTS_SECRET
@@ -190,25 +138,6 @@ export const createOIDCProvider = async (db: LobeChatDatabase): Promise<Provider
190
138
 
191
139
  logProvider('OIDC request client id: %s', clientId);
192
140
 
193
- if (clientId === MARKET_CLIENT_ID) {
194
- logProvider('Using Clerk account resolution for marketplace client');
195
-
196
- if (!accountIdToFind) {
197
- logProvider('No account id available for Clerk resolution, returning undefined');
198
- return undefined;
199
- }
200
-
201
- const clerkAccount = await resolveClerkAccount(accountIdToFind);
202
-
203
- if (clerkAccount) {
204
- logProvider('Clerk account resolved successfully for %s', accountIdToFind);
205
- return clerkAccount;
206
- }
207
-
208
- logProvider('Clerk account resolution failed for %s', accountIdToFind);
209
- return undefined;
210
- }
211
-
212
141
  logProvider(
213
142
  'Attempting to find account with ID: %s (source: %s)',
214
143
  accountIdToFind,
@@ -98,6 +98,7 @@ describe('userRouter', () => {
98
98
  () =>
99
99
  ({
100
100
  getUserState: vi.fn().mockResolvedValue(mockState),
101
+ updateUser: vi.fn().mockResolvedValue({ rowCount: 1 }),
101
102
  }) as any,
102
103
  );
103
104
 
@@ -163,6 +164,7 @@ describe('userRouter', () => {
163
164
  preference: { telemetry: null },
164
165
  settings: {},
165
166
  }),
167
+ updateUser: vi.fn().mockResolvedValue({ rowCount: 1 }),
166
168
  }) as any,
167
169
  );
168
170
 
@@ -4,6 +4,7 @@ import { serialize } from 'cookie';
4
4
  import debug from 'debug';
5
5
  import { z } from 'zod';
6
6
 
7
+ import { ToolCallContent } from '@/libs/mcp';
7
8
  import { authedProcedure, publicProcedure, router } from '@/libs/trpc/lambda';
8
9
  import { serverDatabase } from '@/libs/trpc/lambda/middleware';
9
10
  import { DiscoverService } from '@/server/services/discover';
@@ -80,13 +81,15 @@ export const marketRouter = router({
80
81
  toolName: input.toolName,
81
82
  userAccessToken,
82
83
  });
84
+ const cloudResultContent = (cloudResult?.content ?? []) as ToolCallContent[];
83
85
 
84
86
  // Format the cloud result to MCPToolCallResult format
85
87
  // Process content blocks (upload images, etc.)
86
88
  const newContent =
87
89
  cloudResult?.isError || !ctx.fileService
88
- ? cloudResult?.content
89
- : await processContentBlocks(cloudResult?.content, ctx.fileService);
90
+ ? cloudResultContent
91
+ : // FIXME: the type assertion here is a temporary solution, need to remove it after refactoring
92
+ await processContentBlocks(cloudResultContent, ctx.fileService);
90
93
 
91
94
  // Convert content blocks to string
92
95
  const content = contentBlocksToString(newContent);
@@ -55,6 +55,11 @@ export const userRouter = router({
55
55
  }),
56
56
 
57
57
  getUserState: userProcedure.query(async ({ ctx }): Promise<UserInitializationState> => {
58
+ // don't block following process
59
+ ctx.userModel.updateUser({ lastActiveAt: new Date() }).catch((err) => {
60
+ console.error('update lastActiveAt failed, error:', err);
61
+ });
62
+
58
63
  let state: Awaited<ReturnType<UserModel['getUserState']>> | undefined;
59
64
 
60
65
  // get or create first-time user
@@ -102,6 +102,7 @@ class MCPService {
102
102
  // Call cloud gateway via lambda market endpoint
103
103
  // Server will automatically get user access token from database
104
104
  // and format the result to MCPToolCallResult
105
+ // @ts-ignore tsgo 误报错误
105
106
  result = await lambdaClient.market.callCloudMcpEndpoint.mutate({
106
107
  apiParams,
107
108
  identifier,
@@ -56,7 +56,7 @@ Key principles:
56
56
  **Subagent workflow**:
57
57
 
58
58
  1. **One subagent per action file** - Each subagent focuses on testing ONE action file completely
59
- 2. **Independent verification** - Each subagent runs its own type-check, lint, and test verification
59
+ 2. **Independent verification** - Each subagent runs its own typecheck, lint, and test verification
60
60
  3. **No commits from subagents** - Only the parent agent creates the final commit after all subagents complete
61
61
  4. **Parallel execution** - Launch all subagents in a single message using multiple Task tool calls
62
62
  5. **Consolidate results** - Parent agent reviews all results, runs final verification, updates docs, and commits
@@ -129,12 +129,12 @@ For files with multiple action files to test, use the Task tool to create subage
129
129
  2. **Launch one subagent per action file** using the Task tool
130
130
  3. **Each subagent independently**:
131
131
  - Writes tests for ONE action file only
132
- - Runs type-check and lint
132
+ - Runs typecheck and lint
133
133
  - Verifies tests pass
134
134
  - Reports results back
135
135
  - **DOES NOT commit** (parent agent handles commits)
136
136
  4. **After all subagents complete**, review all results
137
- 5. **Run final verification** (type-check, lint, tests)
137
+ 5. **Run final verification** (typecheck, lint, tests)
138
138
  6. **Update test-coverage.md** with combined results
139
139
  7. **Create single commit** with all new tests
140
140
 
@@ -146,7 +146,7 @@ Write comprehensive tests for src/store/discover/slices/plugin/action.ts followi
146
146
  Requirements:
147
147
  1. Write tests covering all actions in the file
148
148
  2. Follow SWR hooks testing pattern (if applicable)
149
- 3. Run type-check and lint to verify
149
+ 3. Run typecheck and lint to verify
150
150
  4. Run tests to ensure they pass
151
151
  5. Report back with:
152
152
  - Number of tests written
@@ -163,7 +163,7 @@ DO NOT:
163
163
 
164
164
  - ✅ Parallel execution - multiple action files tested simultaneously
165
165
  - ✅ Focused scope - each subagent handles one file completely
166
- - ✅ Independent verification - each file gets type-check/lint/test verification
166
+ - ✅ Independent verification - each file gets typecheck/lint/test verification
167
167
  - ✅ Clean commits - single commit after all work is done
168
168
  - ✅ Better organization - clear separation of concerns
169
169
 
@@ -196,7 +196,7 @@ bunx vitest run --silent='passed-only' 'src/store/[domain]/slices/[slice]/action
196
196
 
197
197
  ```bash
198
198
  # Check TypeScript types (from project root)
199
- bun run type-check
199
+ bun run typecheck
200
200
 
201
201
  # Fix any linting issues
202
202
  bunx eslint src/store/[domain]/ --fix
@@ -270,7 +270,7 @@ Based on your development summary, update the following sections:
270
270
  bunx vitest run 'src/store'
271
271
 
272
272
  # Verify type check still passes
273
- bun run type-check
273
+ bun run typecheck
274
274
  ```
275
275
 
276
276
  ### Complete Workflow Example (Single File)
@@ -281,7 +281,7 @@ bun run type-check
281
281
  bunx vitest run --silent='passed-only' 'src/store/tool/slices/mcpStore/action.test.ts'
282
282
 
283
283
  # 2. Type/Lint Phase (REQUIRED)
284
- bun run type-check # Must pass!
284
+ bun run typecheck # Must pass!
285
285
  bunx eslint src/store/tool/ --fix
286
286
 
287
287
  # 3. Coverage Phase
@@ -295,7 +295,7 @@ bunx vitest run --coverage 'src/store'
295
295
 
296
296
  # 6. Final Verification
297
297
  bunx vitest run 'src/store'
298
- bun run type-check
298
+ bun run typecheck
299
299
 
300
300
  # 7. Commit
301
301
  git add .
@@ -320,7 +320,7 @@ Task({
320
320
  Requirements:
321
321
  1. Write tests covering all actions (usePluginCategories, usePluginDetail, usePluginList, usePluginIdentifiers)
322
322
  2. Follow SWR hooks testing pattern
323
- 3. Run type-check and lint to verify
323
+ 3. Run typecheck and lint to verify
324
324
  4. Run tests to ensure they pass
325
325
  5. Report back with number of tests written and coverage areas
326
326
 
@@ -335,7 +335,7 @@ Task({
335
335
  Requirements:
336
336
  1. Write tests covering all actions (useFetchMcpDetail, useFetchMcpList, useMcpCategories)
337
337
  2. Follow SWR hooks testing pattern
338
- 3. Run type-check and lint to verify
338
+ 3. Run typecheck and lint to verify
339
339
  4. Run tests to ensure they pass
340
340
  5. Report back with number of tests written and coverage areas
341
341
 
@@ -350,7 +350,7 @@ DO NOT commit changes or update test-coverage.md.`,
350
350
  Each subagent will:
351
351
 
352
352
  - Write tests
353
- - Run type-check and lint
353
+ - Run typecheck and lint
354
354
  - Verify tests pass
355
355
  - Report results
356
356
 
@@ -365,8 +365,8 @@ After all subagents complete:
365
365
  **Step 4: Final Verification**
366
366
 
367
367
  ```bash
368
- # Run type-check on entire project
369
- bun run type-check
368
+ # Run typecheck on entire project
369
+ bun run typecheck
370
370
 
371
371
  # Run lint on all new test files
372
372
  bunx eslint src/store/discover/ --fix
@@ -396,7 +396,7 @@ git commit -m "✅ test(store): add comprehensive tests for discover store
396
396
 
397
397
  - Add tests for plugin, mcp, assistant, model, provider slices
398
398
  - Coverage: X% → Y% (+Z tests, 5 new test files)
399
- - All tests pass type-check and lint
399
+ - All tests pass typecheck and lint
400
400
 
401
401
  🤖 Generated with [Claude Code](https://claude.com/claude-code)
402
402
 
@@ -444,7 +444,7 @@ bunx vitest watch 'src/store/[domain]/slices/[slice]/action.test.ts'
444
444
 
445
445
  ```bash
446
446
  # Type check entire project (from project root)
447
- bun run type-check
447
+ bun run typecheck
448
448
 
449
449
  # Watch mode
450
450
  bunx tsc --noEmit --watch
@@ -494,7 +494,7 @@ bunx eslint src/store/[domain]/
494
494
  - Semantic search and RAG integration testing
495
495
  - File upload with progress callbacks
496
496
  - **Development Method**: Used parallel subagents (9 subagents running simultaneously)
497
- - **Type Safety**: All tests pass type-check
497
+ - **Type Safety**: All tests pass typecheck
498
498
  - **Lint**: All tests pass lint ✅
499
499
  - **Action Files Coverage**: 31/40 → 40/40 tested (100%, +9 files)
500
500
  - **🎉 MILESTONE**: All 40 action files now have comprehensive test coverage!
@@ -523,7 +523,7 @@ bunx eslint src/store/[domain]/
523
523
  - AbortController management testing
524
524
  - Mock return types matching actual services
525
525
  - **Development Method**: Used parallel subagents (2 subagents, one per file)
526
- - **Type Safety**: All tests pass type-check
526
+ - **Type Safety**: All tests pass typecheck
527
527
  - **Lint**: All tests pass lint ✅
528
528
  - **Action Files Coverage**: 31/40 tested (77.5%, +2 files)
529
529
  - **Milestone**: 🏆 All high priority files (>200 LOC) now have comprehensive tests!
@@ -544,7 +544,7 @@ bunx eslint src/store/[domain]/
544
544
  - Successfully adapted zustand testing patterns for SWR hooks
545
545
  - Mock strategy: Synchronously return data from mock useSWR
546
546
  - Type safety: Used `as any` for test mock data where needed
547
- - **Type Safety**: All tests pass type-check
547
+ - **Type Safety**: All tests pass typecheck
548
548
  - **Action Files Coverage**: 29/40 tested (72.5%, +2 files)
549
549
 
550
550
  **Session (2024-10-14)**: 📋 Store Testing Documentation Created