@lobehub/chat 1.111.10 → 1.111.12
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.
- package/.github/workflows/claude-code-review.yml +12 -12
- package/.github/workflows/claude.yml +9 -9
- package/.vscode/extensions.json +13 -0
- package/.vscode/settings.json +89 -0
- package/CHANGELOG.md +42 -0
- package/CLAUDE.md +117 -0
- package/changelog/v1.json +14 -0
- package/docs/development/state-management/state-management-intro.mdx +2 -2
- package/docs/development/state-management/state-management-intro.zh-CN.mdx +2 -2
- package/package.json +1 -1
- package/packages/model-runtime/src/RouterRuntime/createRuntime.ts +9 -1
- package/packages/model-runtime/src/ai302/index.ts +1 -1
- package/packages/model-runtime/src/aihubmix/index.ts +28 -71
- package/packages/model-runtime/src/anthropic/index.ts +6 -26
- package/packages/model-runtime/src/giteeai/index.ts +2 -37
- package/packages/model-runtime/src/github/index.ts +33 -44
- package/packages/model-runtime/src/modelscope/index.ts +2 -38
- package/packages/model-runtime/src/moonshot/index.ts +2 -36
- package/packages/model-runtime/src/novita/__snapshots__/index.test.ts.snap +40 -22
- package/packages/model-runtime/src/novita/index.ts +1 -32
- package/packages/model-runtime/src/nvidia/index.ts +1 -1
- package/packages/model-runtime/src/openai/__snapshots__/index.test.ts.snap +63 -7
- package/packages/model-runtime/src/openai/index.ts +1 -1
- package/packages/model-runtime/src/openrouter/__snapshots__/index.test.ts.snap +6 -21
- package/packages/model-runtime/src/openrouter/index.ts +29 -37
- package/packages/model-runtime/src/qiniu/index.ts +3 -27
- package/packages/model-runtime/src/qwen/index.ts +1 -1
- package/packages/model-runtime/src/siliconcloud/index.ts +1 -1
- package/packages/model-runtime/src/utils/modelParse.test.ts +6 -6
- package/packages/model-runtime/src/utils/modelParse.ts +238 -40
- package/packages/model-runtime/src/utils/openaiCompatibleFactory/index.test.ts +18 -0
- package/packages/model-runtime/src/utils/streams/openai/openai.ts +12 -0
- package/packages/model-runtime/src/v0/index.ts +2 -2
- package/packages/model-runtime/src/volcengine/index.ts +1 -1
- package/packages/model-runtime/src/xai/index.ts +2 -24
- package/packages/model-runtime/src/zhipu/index.ts +1 -1
- package/src/config/aiModels/aihubmix.ts +1 -9
- package/src/config/aiModels/anthropic.ts +24 -4
- package/src/config/aiModels/fal.ts +20 -3
- package/src/config/aiModels/google.ts +60 -6
- package/src/config/aiModels/groq.ts +4 -21
- package/src/config/aiModels/hunyuan.ts +1 -1
- package/src/config/aiModels/mistral.ts +22 -5
- package/src/config/aiModels/moonshot.ts +20 -0
- package/src/config/aiModels/openai.ts +0 -45
- package/src/config/aiModels/qwen.ts +113 -3
- package/src/config/aiModels/sensenova.ts +6 -6
- package/src/config/aiModels/siliconcloud.ts +80 -0
- package/src/config/aiModels/stepfun.ts +38 -4
- package/src/config/aiModels/zhipu.ts +33 -8
- package/src/config/modelProviders/aihubmix.ts +1 -1
- package/src/config/modelProviders/mistral.ts +1 -0
- package/src/config/modelProviders/openai.ts +1 -1
- package/src/config/modelProviders/qwen.ts +1 -1
- package/src/config/modelProviders/v0.ts +1 -0
- package/src/config/modelProviders/volcengine.ts +1 -0
- package/src/server/routers/async/image.ts +1 -0
- package/src/services/file/_deprecated.ts +1 -1
- package/src/store/file/slices/upload/action.ts +1 -1
@@ -17,14 +17,14 @@ jobs:
|
|
17
17
|
# github.event.pull_request.user.login == 'external-contributor' ||
|
18
18
|
# github.event.pull_request.user.login == 'new-developer' ||
|
19
19
|
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
20
|
-
|
20
|
+
|
21
21
|
runs-on: ubuntu-latest
|
22
22
|
permissions:
|
23
23
|
contents: read
|
24
24
|
pull-requests: read
|
25
25
|
issues: read
|
26
26
|
id-token: write
|
27
|
-
|
27
|
+
|
28
28
|
steps:
|
29
29
|
- name: Checkout repository
|
30
30
|
uses: actions/checkout@v4
|
@@ -38,8 +38,9 @@ jobs:
|
|
38
38
|
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
39
39
|
|
40
40
|
# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
|
41
|
-
|
42
|
-
|
41
|
+
model: 'claude-opus-4-1-20250805'
|
42
|
+
allowed_bots: 'bot'
|
43
|
+
|
43
44
|
# Direct prompt for automated review (no @claude mention needed)
|
44
45
|
direct_prompt: |
|
45
46
|
Please review this pull request and provide feedback on:
|
@@ -48,12 +49,12 @@ jobs:
|
|
48
49
|
- Performance considerations
|
49
50
|
- Security concerns
|
50
51
|
- Test coverage
|
51
|
-
|
52
|
+
|
52
53
|
Be constructive and helpful in your feedback.
|
53
54
|
|
54
55
|
# Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
|
55
56
|
# use_sticky_comment: true
|
56
|
-
|
57
|
+
|
57
58
|
# Optional: Customize review based on file types
|
58
59
|
# direct_prompt: |
|
59
60
|
# Review this PR focusing on:
|
@@ -61,18 +62,17 @@ jobs:
|
|
61
62
|
# - For API endpoints: Security, input validation, and error handling
|
62
63
|
# - For React components: Performance, accessibility, and best practices
|
63
64
|
# - For tests: Coverage, edge cases, and test quality
|
64
|
-
|
65
|
+
|
65
66
|
# Optional: Different prompts for different authors
|
66
67
|
# direct_prompt: |
|
67
|
-
# ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' &&
|
68
|
+
# ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' &&
|
68
69
|
# 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' ||
|
69
70
|
# 'Please provide a thorough code review focusing on our coding standards and best practices.' }}
|
70
|
-
|
71
|
+
|
71
72
|
# Optional: Add specific tools for running tests or linting
|
72
|
-
|
73
|
-
|
73
|
+
allowed_tools: 'Bash(bun run:*),Bash(pnpm run:*),Bash(npm run:*),Bash(npx vitest:*),Bash(rg:*),Bash(find:*),Bash(sed:*),Bash(grep:*),Bash(awk:*),Bash(wc:*),Bash(xargs:*)'
|
74
|
+
|
74
75
|
# Optional: Skip review for certain conditions
|
75
76
|
# if: |
|
76
77
|
# !contains(github.event.pull_request.title, '[skip-review]') &&
|
77
78
|
# !contains(github.event.pull_request.title, '[WIP]')
|
78
|
-
|
@@ -39,26 +39,26 @@ jobs:
|
|
39
39
|
# This is an optional setting that allows Claude to read CI results on PRs
|
40
40
|
additional_permissions: |
|
41
41
|
actions: read
|
42
|
-
|
42
|
+
|
43
43
|
# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
|
44
|
-
|
45
|
-
|
44
|
+
model: 'claude-opus-4-1-20250805'
|
45
|
+
allowed_bots: 'bot'
|
46
|
+
|
46
47
|
# Optional: Customize the trigger phrase (default: @claude)
|
47
48
|
# trigger_phrase: "/claude"
|
48
|
-
|
49
|
+
|
49
50
|
# Optional: Trigger when specific user is assigned to an issue
|
50
51
|
# assignee_trigger: "claude-bot"
|
51
|
-
|
52
|
+
|
52
53
|
# Optional: Allow Claude to run specific commands
|
53
|
-
|
54
|
-
|
54
|
+
allowed_tools: 'Bash(bun run:*),Bash(pnpm run:*),Bash(npm run:*),Bash(npx vitest:*),Bash(rg:*),Bash(find:*),Bash(sed:*),Bash(grep:*),Bash(awk:*),Bash(wc:*),Bash(xargs:*)'
|
55
|
+
|
55
56
|
# Optional: Add custom instructions for Claude to customize its behavior for your project
|
56
57
|
# custom_instructions: |
|
57
58
|
# Follow our coding standards
|
58
59
|
# Ensure all new code has tests
|
59
60
|
# Use TypeScript for new files
|
60
|
-
|
61
|
+
|
61
62
|
# Optional: Custom environment variables for Claude
|
62
63
|
# claude_env: |
|
63
64
|
# NODE_ENV: test
|
64
|
-
|
@@ -0,0 +1,13 @@
|
|
1
|
+
{
|
2
|
+
"recommendations": [
|
3
|
+
"Anthropic.claude-code",
|
4
|
+
"dbaeumer.vscode-eslint",
|
5
|
+
"jrr997.antd-docs",
|
6
|
+
"seatonjiang.gitmoji-vscode",
|
7
|
+
"styled-components.vscode-styled-components",
|
8
|
+
"stylelint.vscode-stylelint",
|
9
|
+
"unifiedjs.vscode-mdx",
|
10
|
+
"unifiedjs.vscode-remark",
|
11
|
+
"vitest.explorer",
|
12
|
+
]
|
13
|
+
}
|
@@ -0,0 +1,89 @@
|
|
1
|
+
{
|
2
|
+
"npm.packageManager": "pnpm",
|
3
|
+
// don't show errors, but fix when save and git pre commit
|
4
|
+
"eslint.rules.customizations": [
|
5
|
+
{ "rule": "import/order", "severity": "off" },
|
6
|
+
{ "rule": "prettier/prettier", "severity": "off" },
|
7
|
+
{ "rule": "react/jsx-sort-props", "severity": "off" },
|
8
|
+
{ "rule": "sort-keys-fix/sort-keys-fix", "severity": "off" },
|
9
|
+
{ "rule": "typescript-sort-keys/interface", "severity": "off" }
|
10
|
+
],
|
11
|
+
"stylelint.validate": [
|
12
|
+
"css",
|
13
|
+
"postcss",
|
14
|
+
// make stylelint work with tsx antd-style css template string
|
15
|
+
"typescriptreact"
|
16
|
+
],
|
17
|
+
"search.exclude": {
|
18
|
+
"**/node_modules": true,
|
19
|
+
// useless to search this big folder
|
20
|
+
"locales": true
|
21
|
+
},
|
22
|
+
"vitest.maximumConfigs": 6,
|
23
|
+
"workbench.editor.customLabels.patterns": {
|
24
|
+
"**/app/**/[[]*[]]/[[]*[]]/page.tsx": "${dirname(2)}/${dirname(1)}/${dirname} • page component",
|
25
|
+
"**/app/**/[[]*[]]/page.tsx": "${dirname(1)}/${dirname} • page component",
|
26
|
+
"**/app/**/page.tsx": "${dirname} • page component",
|
27
|
+
|
28
|
+
"**/app/**/[[]*[]]/[[]*[]]/layout.tsx": "${dirname(2)}/${dirname(1)}/${dirname} • page layout",
|
29
|
+
"**/app/**/[[]*[]]/layout.tsx": "${dirname(1)}/${dirname} • page layout",
|
30
|
+
"**/app/**/layout.tsx": "${dirname} • page layout",
|
31
|
+
|
32
|
+
"**/app/**/[[]*[]]/[[]*[]]/default.tsx": "${dirname(2)}/${dirname(1)}/${dirname} • slot default",
|
33
|
+
"**/app/**/[[]*[]]/default.tsx": "${dirname(1)}/${dirname} • slot default",
|
34
|
+
"**/app/**/default.tsx": "${dirname} • slot default",
|
35
|
+
|
36
|
+
"**/app/**/[[]*[]]/[[]*[]]/error.tsx": "${dirname(2)}/${dirname(1)}/${dirname} • error component",
|
37
|
+
"**/app/**/[[]*[]]/error.tsx": "${dirname(1)}/${dirname} • error component",
|
38
|
+
"**/app/**/error.tsx": "${dirname} • error component",
|
39
|
+
|
40
|
+
"**/app/**/[[]*[]]/[[]*[]]/loading.tsx": "${dirname(2)}/${dirname(1)}/${dirname} • loading component",
|
41
|
+
"**/app/**/[[]*[]]/loading.tsx": "${dirname(1)}/${dirname} • loading component",
|
42
|
+
"**/app/**/loading.tsx": "${dirname} • loading component",
|
43
|
+
|
44
|
+
"**/src/**/route.ts": "${dirname(1)}/${dirname} • route",
|
45
|
+
"**/src/**/index.tsx": "${dirname} • component",
|
46
|
+
|
47
|
+
"**/src/database/repositories/*/index.ts": "${dirname} • db repository",
|
48
|
+
"**/src/database/models/*.ts": "${filename} • db model",
|
49
|
+
"**/src/database/schemas/*.ts": "${filename} • db schema",
|
50
|
+
|
51
|
+
"**/src/services/*.ts": "${filename} • service",
|
52
|
+
"**/src/services/*/client.ts": "${dirname} • client service",
|
53
|
+
"**/src/services/*/server.ts": "${dirname} • server service",
|
54
|
+
|
55
|
+
"**/src/store/*/action.ts": "${dirname} • action",
|
56
|
+
"**/src/store/*/slices/*/action.ts": "${dirname(2)}/${dirname} • action",
|
57
|
+
"**/src/store/*/slices/*/actions/*.ts": "${dirname(1)}/${dirname}/${filename} • action",
|
58
|
+
|
59
|
+
"**/src/store/*/initialState.ts": "${dirname} • state",
|
60
|
+
"**/src/store/*/slices/*/initialState.ts": "${dirname(2)}/${dirname} • state",
|
61
|
+
|
62
|
+
"**/src/store/*/selectors.ts": "${dirname} • selectors",
|
63
|
+
"**/src/store/*/slices/*/selectors.ts": "${dirname(2)}/${dirname} • selectors",
|
64
|
+
|
65
|
+
"**/src/store/*/reducer.ts": "${dirname} • reducer",
|
66
|
+
"**/src/store/*/slices/*/reducer.ts": "${dirname(2)}/${dirname} • reducer",
|
67
|
+
|
68
|
+
"**/src/config/modelProviders/*.ts": "${filename} • provider",
|
69
|
+
"**/src/config/aiModels/*.ts": "${filename} • model",
|
70
|
+
"**/src/config/paramsSchemas/*/*.json": "${dirname(1)}/${filename} • params",
|
71
|
+
"**/src/libs/model-runtime/*/index.ts": "${dirname} • runtime",
|
72
|
+
|
73
|
+
"**/src/server/services/*/index.ts": "${dirname} • server/service",
|
74
|
+
"**/src/server/routers/lambda/*.ts": "${filename} • lambda",
|
75
|
+
"**/src/server/routers/async/*.ts": "${filename} • async",
|
76
|
+
"**/src/server/routers/edge/*.ts": "${filename} • edge",
|
77
|
+
|
78
|
+
"**/src/locales/default/*.ts": "${filename} • locale",
|
79
|
+
},
|
80
|
+
"eslint.validate": [
|
81
|
+
"javascript",
|
82
|
+
"javascriptreact",
|
83
|
+
"typescript",
|
84
|
+
"typescriptreact",
|
85
|
+
"markdown",
|
86
|
+
// support mdx
|
87
|
+
"mdx"
|
88
|
+
]
|
89
|
+
}
|
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,48 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.111.12](https://github.com/lobehub/lobe-chat/compare/v1.111.11...v1.111.12)
|
6
|
+
|
7
|
+
<sup>Released on **2025-08-14**</sup>
|
8
|
+
|
9
|
+
<br/>
|
10
|
+
|
11
|
+
<details>
|
12
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
13
|
+
|
14
|
+
</details>
|
15
|
+
|
16
|
+
<div align="right">
|
17
|
+
|
18
|
+
[](#readme-top)
|
19
|
+
|
20
|
+
</div>
|
21
|
+
|
22
|
+
### [Version 1.111.11](https://github.com/lobehub/lobe-chat/compare/v1.111.10...v1.111.11)
|
23
|
+
|
24
|
+
<sup>Released on **2025-08-13**</sup>
|
25
|
+
|
26
|
+
#### 💄 Styles
|
27
|
+
|
28
|
+
- **misc**: Update Mistral AI models & Optimize many model providers fetching.
|
29
|
+
|
30
|
+
<br/>
|
31
|
+
|
32
|
+
<details>
|
33
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
34
|
+
|
35
|
+
#### Styles
|
36
|
+
|
37
|
+
- **misc**: Update Mistral AI models & Optimize many model providers fetching, closes [#8644](https://github.com/lobehub/lobe-chat/issues/8644) ([1d466e5](https://github.com/lobehub/lobe-chat/commit/1d466e5))
|
38
|
+
|
39
|
+
</details>
|
40
|
+
|
41
|
+
<div align="right">
|
42
|
+
|
43
|
+
[](#readme-top)
|
44
|
+
|
45
|
+
</div>
|
46
|
+
|
5
47
|
### [Version 1.111.10](https://github.com/lobehub/lobe-chat/compare/v1.111.9...v1.111.10)
|
6
48
|
|
7
49
|
<sup>Released on **2025-08-12**</sup>
|
package/CLAUDE.md
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# CLAUDE.md
|
2
|
+
|
3
|
+
This document serves as a shared guideline for all team members when using Claude Code in this repository.
|
4
|
+
|
5
|
+
## Suggestions
|
6
|
+
|
7
|
+
- When searching the project source code, it is recommended to exclude: `src/database/migrations/meta`, `**/*.test.*`, `**/__snapshots__`, `**/fixtures`
|
8
|
+
- Please store all temporary scripts (such as migration and refactoring scripts) in the `docs/.local/` directory; the contents of this folder will not be committed.
|
9
|
+
|
10
|
+
## Technologies Stack
|
11
|
+
|
12
|
+
read @.cursor/rules/project-introduce.mdc for more details.
|
13
|
+
|
14
|
+
### Directory Structure
|
15
|
+
|
16
|
+
```plaintext
|
17
|
+
src/
|
18
|
+
├── app/ # Next.js App Router
|
19
|
+
├── features/ # Feature-based UI components
|
20
|
+
├── store/ # Zustand state stores
|
21
|
+
├── services/ # Client services (tRPC/Model calls)
|
22
|
+
├── server/ # Server-side (tRPC routers, services)
|
23
|
+
├── database/ # Schemas, models, repositories
|
24
|
+
├── libs/ # External library integrations
|
25
|
+
```
|
26
|
+
|
27
|
+
### Data Flow
|
28
|
+
|
29
|
+
- **Client DB Version**: UI → Zustand → Service → Model → PGLite
|
30
|
+
- **Server DB Version**: UI → Zustand → Service → tRPC → Repository/Model → PostgreSQL
|
31
|
+
|
32
|
+
## Development
|
33
|
+
|
34
|
+
### Git Workflow
|
35
|
+
|
36
|
+
- use rebase for git pull.
|
37
|
+
- git commit message should prefix with gitmoji.
|
38
|
+
- git branch name format example: tj/feat/feature-name
|
39
|
+
- use .github/PULL_REQUEST_TEMPLATE.md to generate pull request description
|
40
|
+
|
41
|
+
### Package Management
|
42
|
+
|
43
|
+
this is a monorepo project and we use `pnpm` as package manager
|
44
|
+
|
45
|
+
### TypeScript Code Style Guide
|
46
|
+
|
47
|
+
see @.cursor/rules/typescript.mdc
|
48
|
+
|
49
|
+
### Modify Code Rules
|
50
|
+
|
51
|
+
- **Code Language**:
|
52
|
+
- For files with existing Chinese comments: Continue using Chinese to maintain consistency
|
53
|
+
- For new files or files without Chinese comments: MUST use American English.
|
54
|
+
- eg: new react tsx file and new test file
|
55
|
+
- Conservative for existing code, modern approaches for new features
|
56
|
+
|
57
|
+
### Testing
|
58
|
+
|
59
|
+
Testing work follows the Rule-Aware Task Execution system above.
|
60
|
+
|
61
|
+
- **Required Rule**: `testing-guide/testing-guide.mdc`
|
62
|
+
- **Command**: `npx vitest run --config vitest.config.ts '[file-path-pattern]'`, wrapped in single quotes to avoid shell expansion
|
63
|
+
|
64
|
+
**Important**:
|
65
|
+
|
66
|
+
- Never run `bun run test` etc to run tests, this will run all tests and cost about 10mins
|
67
|
+
- If try to fix the same test twice, but still failed, stop and ask for help.
|
68
|
+
|
69
|
+
### Typecheck
|
70
|
+
|
71
|
+
- use `bun run type-check` to check type errors.
|
72
|
+
|
73
|
+
### Internationalization
|
74
|
+
|
75
|
+
- **Keys**: Add to `src/locales/default/namespace.ts`
|
76
|
+
- **Dev**: Translate at least `zh-CN` files for preview
|
77
|
+
- **Structure**: Hierarchical nested objects, not flat keys
|
78
|
+
- **Script**: DON'T run `pnpm i18n` (user/CI handles it)
|
79
|
+
|
80
|
+
## Rules Index
|
81
|
+
|
82
|
+
Some useful rules of this project. Read them when needed.
|
83
|
+
|
84
|
+
**IMPORTANT**: All rule files referenced in this document are located in the `.cursor/rules/` directory. Throughout this document, rule files are referenced by their filename only for brevity.
|
85
|
+
|
86
|
+
### 📋 Complete Rule Files
|
87
|
+
|
88
|
+
**Core Development**
|
89
|
+
|
90
|
+
- `backend-architecture.mdc` - Three-layer architecture, data flow
|
91
|
+
- `react-component.mdc` - antd-style, Lobe UI usage
|
92
|
+
- `drizzle-schema-style-guide.mdc` - Schema naming, patterns
|
93
|
+
- `define-database-model.mdc` - Model templates, CRUD patterns
|
94
|
+
|
95
|
+
**State & UI**
|
96
|
+
|
97
|
+
- `zustand-slice-organization.mdc` - Store organization
|
98
|
+
- `zustand-action-patterns.mdc` - Action patterns
|
99
|
+
- `packages/react-layout-kit.mdc` - Layout components usage
|
100
|
+
|
101
|
+
**Testing & Quality**
|
102
|
+
|
103
|
+
- `testing-guide/testing-guide.mdc` - Test strategy, mock patterns
|
104
|
+
- `code-review.mdc` - Review process and standards
|
105
|
+
|
106
|
+
**Desktop (Electron)**
|
107
|
+
|
108
|
+
- `desktop-feature-implementation.mdc` - Main/renderer process patterns
|
109
|
+
- `desktop-local-tools-implement.mdc` - Tool integration workflow
|
110
|
+
- `desktop-menu-configuration.mdc` - App menu, context menu, tray menu
|
111
|
+
- `desktop-window-management.mdc` - Window creation, state management, multi-window
|
112
|
+
- `desktop-controller-tests.mdc` - Controller unit testing guide
|
113
|
+
|
114
|
+
**Development Tools**
|
115
|
+
|
116
|
+
- `i18n.mdc` - Internationalization workflow
|
117
|
+
- `debug.mdc` - Debugging strategies
|
package/changelog/v1.json
CHANGED
@@ -1,4 +1,18 @@
|
|
1
1
|
[
|
2
|
+
{
|
3
|
+
"children": {},
|
4
|
+
"date": "2025-08-14",
|
5
|
+
"version": "1.111.12"
|
6
|
+
},
|
7
|
+
{
|
8
|
+
"children": {
|
9
|
+
"improvements": [
|
10
|
+
"Update Mistral AI models & Optimize many model providers fetching."
|
11
|
+
]
|
12
|
+
},
|
13
|
+
"date": "2025-08-13",
|
14
|
+
"version": "1.111.11"
|
15
|
+
},
|
2
16
|
{
|
3
17
|
"children": {
|
4
18
|
"improvements": [
|
@@ -1,5 +1,3 @@
|
|
1
|
-
{/* eslint-disable no-irregular-whitespace */}
|
2
|
-
|
3
1
|
# Best Practices for State Management
|
4
2
|
|
5
3
|
LobeChat differs from traditional CRUD web applications in that it involves a large amount of rich interactive capabilities. Therefore, it is crucial to design a data flow architecture that is easy to develop and maintain. This document will introduce the best practices for data flow management in LobeChat.
|
@@ -111,6 +109,8 @@ Based on the provided directory structure of LobeChat SessionStore, we can updat
|
|
111
109
|
|
112
110
|
In the LobeChat application, session management is a complex functional module, so we use the Slice pattern to organize the data flow. Below is the directory structure of LobeChat SessionStore, where each directory and file has its specific purpose:
|
113
111
|
|
112
|
+
{/* eslint-disable no-irregular-whitespace */}
|
113
|
+
|
114
114
|
```bash
|
115
115
|
src/store/session
|
116
116
|
├── helpers.ts # Helper functions
|
@@ -1,5 +1,3 @@
|
|
1
|
-
{/* eslint-disable no-irregular-whitespace */}
|
2
|
-
|
3
1
|
# 状态管理最佳实践
|
4
2
|
|
5
3
|
LobeChat 不同于传统 CRUD 的网页,存在大量的富交互能力,如何设计一个易于开发与易于维护的数据流架构非常重要。本篇文档将介绍 LobeChat 中的数据流管理最佳实践。
|
@@ -111,6 +109,8 @@ LobeChat SessionStore
|
|
111
109
|
|
112
110
|
在 LobeChat 应用中,由于会话管理是一个复杂的功能模块,因此我们采用了 [slice 模式](https://github.com/pmndrs/zustand/blob/main/docs/guides/slices-pattern.md) 来组织数据流。下面是 LobeChat SessionStore 的目录结构,其中每个目录和文件都有其特定的用途:
|
113
111
|
|
112
|
+
{/* eslint-disable no-irregular-whitespace */}
|
113
|
+
|
114
114
|
```fish
|
115
115
|
src/store/session
|
116
116
|
├── index.ts # SessionStore 的聚合导出文件
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.111.
|
3
|
+
"version": "1.111.12",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -114,6 +114,7 @@ export const createRouterRuntime = ({
|
|
114
114
|
id,
|
115
115
|
routers,
|
116
116
|
apiKey: DEFAULT_API_LEY,
|
117
|
+
models,
|
117
118
|
...params
|
118
119
|
}: CreateRouterRuntimeOptions) => {
|
119
120
|
return class UniformRuntime implements LobeRuntimeAI {
|
@@ -201,7 +202,14 @@ export const createRouterRuntime = ({
|
|
201
202
|
}
|
202
203
|
|
203
204
|
async models() {
|
204
|
-
|
205
|
+
if (models && typeof models === 'function') {
|
206
|
+
// 如果是函数式配置,使用最后一个 runtime 的 client 调用函数
|
207
|
+
const lastRuntime = this._runtimes.at(-1)?.runtime;
|
208
|
+
if (lastRuntime && 'client' in lastRuntime) {
|
209
|
+
return await models({ client: (lastRuntime as any).client });
|
210
|
+
}
|
211
|
+
}
|
212
|
+
return this._runtimes.at(-1)?.runtime.models?.();
|
205
213
|
}
|
206
214
|
|
207
215
|
async embeddings(payload: EmbeddingsPayload, options?: EmbeddingsOptions) {
|
@@ -40,7 +40,7 @@ export const Lobe302AI = createOpenAICompatibleRuntime({
|
|
40
40
|
const modelsPage = (await client.models.list()) as any;
|
41
41
|
const modelList: Ai302ModelCard[] = modelsPage.data;
|
42
42
|
|
43
|
-
return processMultiProviderModelList(modelList);
|
43
|
+
return processMultiProviderModelList(modelList, 'ai302');
|
44
44
|
},
|
45
45
|
provider: ModelProvider.Ai302,
|
46
46
|
});
|
@@ -1,10 +1,12 @@
|
|
1
1
|
import urlJoin from 'url-join';
|
2
2
|
|
3
|
-
import
|
4
|
-
import
|
3
|
+
import { LOBE_DEFAULT_MODEL_LIST } from '@/config/aiModels';
|
4
|
+
import { responsesAPIModels } from '@/const/models';
|
5
5
|
|
6
6
|
import { createRouterRuntime } from '../RouterRuntime';
|
7
7
|
import { ModelProvider } from '../types';
|
8
|
+
import { ChatStreamPayload } from '../types/chat';
|
9
|
+
import { detectModelProvider, processMultiProviderModelList } from '../utils/modelParse';
|
8
10
|
|
9
11
|
export interface AiHubMixModelCard {
|
10
12
|
created: number;
|
@@ -15,6 +17,17 @@ export interface AiHubMixModelCard {
|
|
15
17
|
|
16
18
|
const baseURL = 'https://aihubmix.com';
|
17
19
|
|
20
|
+
const handlePayload = (payload: ChatStreamPayload) => {
|
21
|
+
if (
|
22
|
+
responsesAPIModels.has(payload.model) ||
|
23
|
+
payload.model.includes('gpt-') ||
|
24
|
+
/^o\d/.test(payload.model)
|
25
|
+
) {
|
26
|
+
return { ...payload, apiMode: 'responses' } as any;
|
27
|
+
}
|
28
|
+
return payload as any;
|
29
|
+
};
|
30
|
+
|
18
31
|
export const LobeAiHubMixAI = createRouterRuntime({
|
19
32
|
debug: {
|
20
33
|
chatCompletion: () => process.env.DEBUG_AIHUBMIX_CHAT_COMPLETION === '1',
|
@@ -24,68 +37,11 @@ export const LobeAiHubMixAI = createRouterRuntime({
|
|
24
37
|
},
|
25
38
|
id: ModelProvider.AiHubMix,
|
26
39
|
models: async ({ client }) => {
|
27
|
-
const functionCallKeywords = [
|
28
|
-
'gpt-4',
|
29
|
-
'gpt-3.5',
|
30
|
-
'claude',
|
31
|
-
'gemini',
|
32
|
-
'qwen',
|
33
|
-
'deepseek',
|
34
|
-
'llama',
|
35
|
-
];
|
36
|
-
|
37
|
-
const visionKeywords = [
|
38
|
-
'gpt-4o',
|
39
|
-
'gpt-4-vision',
|
40
|
-
'claude-3',
|
41
|
-
'claude-4',
|
42
|
-
'gemini-pro-vision',
|
43
|
-
'qwen-vl',
|
44
|
-
'llava',
|
45
|
-
];
|
46
|
-
|
47
|
-
const reasoningKeywords = [
|
48
|
-
'o1',
|
49
|
-
'deepseek-r1',
|
50
|
-
'qwq',
|
51
|
-
'claude-opus-4',
|
52
|
-
'claude-sonnet-4',
|
53
|
-
'claude-3-5-sonnet',
|
54
|
-
'claude-3-5-haiku',
|
55
|
-
];
|
56
|
-
|
57
40
|
try {
|
58
41
|
const modelsPage = (await client.models.list()) as any;
|
59
42
|
const modelList: AiHubMixModelCard[] = modelsPage.data || [];
|
60
43
|
|
61
|
-
return modelList
|
62
|
-
.map((model) => {
|
63
|
-
const knownModel = AiHubMixModels.find(
|
64
|
-
(m) => model.id.toLowerCase() === m.id.toLowerCase(),
|
65
|
-
);
|
66
|
-
|
67
|
-
const modelId = model.id.toLowerCase();
|
68
|
-
|
69
|
-
return {
|
70
|
-
contextWindowTokens: knownModel?.contextWindowTokens ?? undefined,
|
71
|
-
displayName: knownModel?.displayName ?? model.id,
|
72
|
-
enabled: knownModel?.enabled || false,
|
73
|
-
functionCall:
|
74
|
-
functionCallKeywords.some((keyword) => modelId.includes(keyword)) ||
|
75
|
-
knownModel?.abilities?.functionCall ||
|
76
|
-
false,
|
77
|
-
id: model.id,
|
78
|
-
reasoning:
|
79
|
-
reasoningKeywords.some((keyword) => modelId.includes(keyword)) ||
|
80
|
-
knownModel?.abilities?.reasoning ||
|
81
|
-
false,
|
82
|
-
vision:
|
83
|
-
visionKeywords.some((keyword) => modelId.includes(keyword)) ||
|
84
|
-
knownModel?.abilities?.vision ||
|
85
|
-
false,
|
86
|
-
};
|
87
|
-
})
|
88
|
-
.filter(Boolean) as ChatModelCard[];
|
44
|
+
return await processMultiProviderModelList(modelList, 'aihubmix');
|
89
45
|
} catch (error) {
|
90
46
|
console.warn(
|
91
47
|
'Failed to fetch AiHubMix models. Please ensure your AiHubMix API key is valid:',
|
@@ -97,25 +53,26 @@ export const LobeAiHubMixAI = createRouterRuntime({
|
|
97
53
|
routers: [
|
98
54
|
{
|
99
55
|
apiType: 'anthropic',
|
100
|
-
models:
|
101
|
-
|
102
|
-
|
103
|
-
(id) => id.startsWith('claude') || id.startsWith('kimi-k2'),
|
104
|
-
);
|
105
|
-
},
|
56
|
+
models: LOBE_DEFAULT_MODEL_LIST.map((m) => m.id).filter(
|
57
|
+
(id) => detectModelProvider(id) === 'anthropic',
|
58
|
+
),
|
106
59
|
options: { baseURL },
|
107
60
|
},
|
108
61
|
{
|
109
62
|
apiType: 'google',
|
110
|
-
models:
|
111
|
-
|
112
|
-
|
113
|
-
},
|
63
|
+
models: LOBE_DEFAULT_MODEL_LIST.map((m) => m.id).filter(
|
64
|
+
(id) => detectModelProvider(id) === 'google',
|
65
|
+
),
|
114
66
|
options: { baseURL: urlJoin(baseURL, '/gemini') },
|
115
67
|
},
|
116
68
|
{
|
117
69
|
apiType: 'openai',
|
118
|
-
options: {
|
70
|
+
options: {
|
71
|
+
baseURL: urlJoin(baseURL, '/v1'),
|
72
|
+
chatCompletion: {
|
73
|
+
handlePayload,
|
74
|
+
},
|
75
|
+
},
|
119
76
|
},
|
120
77
|
],
|
121
78
|
});
|
@@ -1,7 +1,5 @@
|
|
1
1
|
import Anthropic, { ClientOptions } from '@anthropic-ai/sdk';
|
2
2
|
|
3
|
-
import type { ChatModelCard } from '@/types/llm';
|
4
|
-
|
5
3
|
import { LobeRuntimeAI } from '../BaseAI';
|
6
4
|
import { AgentRuntimeErrorType } from '../error';
|
7
5
|
import {
|
@@ -17,8 +15,10 @@ import { desensitizeUrl } from '../utils/desensitizeUrl';
|
|
17
15
|
import { StreamingResponse } from '../utils/response';
|
18
16
|
import { AnthropicStream } from '../utils/streams';
|
19
17
|
import { handleAnthropicError } from './handleAnthropicError';
|
18
|
+
import { processModelList, MODEL_LIST_CONFIGS } from '../utils/modelParse';
|
20
19
|
|
21
20
|
export interface AnthropicModelCard {
|
21
|
+
created_at: string;
|
22
22
|
display_name: string;
|
23
23
|
id: string;
|
24
24
|
}
|
@@ -218,8 +218,6 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
|
|
218
218
|
}
|
219
219
|
|
220
220
|
async models() {
|
221
|
-
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');
|
222
|
-
|
223
221
|
const url = `${this.baseURL}/v1/models`;
|
224
222
|
const response = await fetch(url, {
|
225
223
|
headers: {
|
@@ -232,30 +230,12 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
|
|
232
230
|
|
233
231
|
const modelList: AnthropicModelCard[] = json['data'];
|
234
232
|
|
235
|
-
|
236
|
-
|
237
|
-
const knownModel = LOBE_DEFAULT_MODEL_LIST.find(
|
238
|
-
(m) => model.id.toLowerCase() === m.id.toLowerCase(),
|
239
|
-
);
|
240
|
-
|
241
|
-
return {
|
242
|
-
contextWindowTokens: knownModel?.contextWindowTokens ?? undefined,
|
233
|
+
const standardModelList = modelList.map((model) => ({
|
234
|
+
created: model.created_at,
|
243
235
|
displayName: model.display_name,
|
244
|
-
enabled: knownModel?.enabled || false,
|
245
|
-
functionCall:
|
246
|
-
model.id.toLowerCase().includes('claude-3') ||
|
247
|
-
knownModel?.abilities?.functionCall ||
|
248
|
-
false,
|
249
236
|
id: model.id,
|
250
|
-
|
251
|
-
|
252
|
-
(model.id.toLowerCase().includes('claude-3') &&
|
253
|
-
!model.id.toLowerCase().includes('claude-3-5-haiku')) ||
|
254
|
-
knownModel?.abilities?.vision ||
|
255
|
-
false,
|
256
|
-
};
|
257
|
-
})
|
258
|
-
.filter(Boolean) as ChatModelCard[];
|
237
|
+
}));
|
238
|
+
return processModelList(standardModelList, MODEL_LIST_CONFIGS.anthropic, 'anthropic');
|
259
239
|
}
|
260
240
|
|
261
241
|
private handleError(error: any): ChatCompletionErrorPayload {
|