@lobehub/lobehub 2.1.15 → 2.1.17

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 (25) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v2.json +14 -0
  3. package/locales/en-US/setting.json +3 -0
  4. package/locales/zh-CN/setting.json +3 -0
  5. package/package.json +1 -1
  6. package/packages/model-bank/src/aiModels/lobehub/chat/moonshot.ts +29 -0
  7. package/packages/model-bank/src/modelProviders/moonshot.ts +3 -4
  8. package/packages/model-runtime/src/core/RouterRuntime/baseRuntimeMap.ts +0 -2
  9. package/packages/model-runtime/src/core/RouterRuntime/createRuntime.test.ts +91 -0
  10. package/packages/model-runtime/src/core/RouterRuntime/createRuntime.ts +21 -9
  11. package/packages/model-runtime/src/core/RouterRuntime/index.ts +1 -1
  12. package/packages/model-runtime/src/{providers/anthropic → core/anthropicCompatibleFactory}/generateObject.ts +1 -1
  13. package/packages/model-runtime/src/core/anthropicCompatibleFactory/index.ts +626 -0
  14. package/packages/model-runtime/src/providers/anthropic/index.test.ts +110 -103
  15. package/packages/model-runtime/src/providers/anthropic/index.ts +12 -281
  16. package/packages/model-runtime/src/providers/bedrock/index.ts +2 -2
  17. package/packages/model-runtime/src/providers/moonshot/index.test.ts +294 -328
  18. package/packages/model-runtime/src/providers/moonshot/index.ts +225 -79
  19. package/src/app/[variants]/(main)/agent/profile/features/Header/AgentPublishButton/PublishButton.tsx +52 -8
  20. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx +52 -8
  21. package/src/locales/default/setting.ts +3 -0
  22. /package/packages/model-runtime/src/{providers/anthropic → core/anthropicCompatibleFactory}/generateObject.test.ts +0 -0
  23. /package/packages/model-runtime/src/{providers/anthropic → core/anthropicCompatibleFactory}/handleAnthropicError.ts +0 -0
  24. /package/packages/model-runtime/src/{providers/anthropic → core/anthropicCompatibleFactory}/resolveCacheTTL.ts +0 -0
  25. /package/packages/model-runtime/src/{providers/anthropic → core/anthropicCompatibleFactory}/resolveMaxTokens.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 2.1.17](https://github.com/lobehub/lobe-chat/compare/v2.1.16...v2.1.17)
6
+
7
+ <sup>Released on **2026-02-04**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **model-runtime**: Extract Anthropic factory and convert Moonshot to RouterRuntime.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **model-runtime**: Extract Anthropic factory and convert Moonshot to RouterRuntime, closes [#12109](https://github.com/lobehub/lobe-chat/issues/12109) ([71064fd](https://github.com/lobehub/lobe-chat/commit/71064fd))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ### [Version 2.1.16](https://github.com/lobehub/lobe-chat/compare/v2.1.15...v2.1.16)
31
+
32
+ <sup>Released on **2026-02-04**</sup>
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - **misc**: Add the preview publish to market button preview check.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's fixed
44
+
45
+ - **misc**: Add the preview publish to market button preview check, closes [#12105](https://github.com/lobehub/lobe-chat/issues/12105) ([28887c7](https://github.com/lobehub/lobe-chat/commit/28887c7))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 2.1.15](https://github.com/lobehub/lobe-chat/compare/v2.1.14...v2.1.15)
6
56
 
7
57
  <sup>Released on **2026-02-04**</sup>
package/changelog/v2.json CHANGED
@@ -1,4 +1,18 @@
1
1
  [
2
+ {
3
+ "children": {},
4
+ "date": "2026-02-04",
5
+ "version": "2.1.17"
6
+ },
7
+ {
8
+ "children": {
9
+ "fixes": [
10
+ "Add the preview publish to market button preview check."
11
+ ]
12
+ },
13
+ "date": "2026-02-04",
14
+ "version": "2.1.16"
15
+ },
2
16
  {
3
17
  "children": {
4
18
  "fixes": [
@@ -268,6 +268,9 @@
268
268
  "marketPublish.upload.button": "Publish New Version",
269
269
  "marketPublish.upload.tooltip": "Publish a new version to Agent Community",
270
270
  "marketPublish.uploadGroup.tooltip": "Publish a new version to Group Community",
271
+ "marketPublish.validation.confirmPublish": "Are you sure you want to publish to the market?",
272
+ "marketPublish.validation.emptyName": "Cannot publish: Name is required",
273
+ "marketPublish.validation.emptySystemRole": "Cannot publish: System Role is required",
271
274
  "memory.enabled.desc": "Allow LobeHub to extract preferences and info from conversations and use them later. You can view, edit, or clear memory anytime.",
272
275
  "memory.enabled.title": "Enable Memory",
273
276
  "memory.title": "Memory Settings",
@@ -268,6 +268,9 @@
268
268
  "marketPublish.upload.button": "发布新版本",
269
269
  "marketPublish.upload.tooltip": "发布新版本到助理社区",
270
270
  "marketPublish.uploadGroup.tooltip": "向群组社区发布新版本",
271
+ "marketPublish.validation.confirmPublish": "确定要发布到市场吗?",
272
+ "marketPublish.validation.emptyName": "无法发布:名称不能为空",
273
+ "marketPublish.validation.emptySystemRole": "无法发布:系统角色不能为空",
271
274
  "memory.enabled.desc": "允许 LobeHub 从对话中提取偏好和信息,并在之后使用。您可以随时查看、编辑或清除记忆内容。",
272
275
  "memory.enabled.title": "启用记忆功能",
273
276
  "memory.title": "记忆设置",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.1.15",
3
+ "version": "2.1.17",
4
4
  "description": "LobeHub - an open-source,comprehensive AI Agent 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",
@@ -1,6 +1,35 @@
1
1
  import { AIChatModelCard } from '../../../types/aiModel';
2
2
 
3
3
  export const moonshotChatModels: AIChatModelCard[] = [
4
+ {
5
+ abilities: {
6
+ functionCall: true,
7
+ reasoning: true,
8
+ search: true,
9
+ structuredOutput: true,
10
+ vision: true,
11
+ },
12
+ contextWindowTokens: 262_144,
13
+ description:
14
+ 'Kimi K2.5 is Kimi\'s most versatile model to date, featuring a native multimodal architecture that supports both vision and text inputs, "thinking" and "non-thinking" modes, and both conversational and agent tasks.',
15
+ displayName: 'Kimi K2.5',
16
+ enabled: true,
17
+ id: 'kimi-k2.5',
18
+ maxOutput: 32_768,
19
+ pricing: {
20
+ units: [
21
+ { name: 'textInput', rate: 0.6, strategy: 'fixed', unit: 'millionTokens' },
22
+ { name: 'textInput_cacheRead', rate: 0.1, strategy: 'fixed', unit: 'millionTokens' },
23
+ { name: 'textOutput', rate: 3, strategy: 'fixed', unit: 'millionTokens' },
24
+ ],
25
+ },
26
+ releasedAt: '2026-01-27',
27
+ settings: {
28
+ extendParams: ['enableReasoning'],
29
+ searchImpl: 'params',
30
+ },
31
+ type: 'chat',
32
+ },
4
33
  {
5
34
  abilities: {
6
35
  functionCall: true,
@@ -1,6 +1,5 @@
1
1
  import { type ModelProviderCard } from '@/types/llm';
2
2
 
3
- // ref: https://platform.moonshot.cn/docs/intro#model-list
4
3
  const Moonshot: ModelProviderCard = {
5
4
  chatModels: [],
6
5
  checkModel: 'kimi-latest',
@@ -8,12 +7,12 @@ const Moonshot: ModelProviderCard = {
8
7
  'Moonshot, from Moonshot AI (Beijing Moonshot Technology), offers multiple NLP models for use cases like content creation, research, recommendations, and medical analysis, with strong long-context and complex generation support.',
9
8
  id: 'moonshot',
10
9
  modelList: { showModelFetcher: true },
11
- modelsUrl: 'https://platform.moonshot.cn/docs/intro',
10
+ modelsUrl: 'https://platform.moonshot.ai/docs/pricing/chat',
12
11
  name: 'Moonshot',
13
12
  settings: {
14
13
  disableBrowserRequest: true, // CORS error
15
14
  proxyUrl: {
16
- placeholder: 'https://api.moonshot.cn/v1',
15
+ placeholder: 'https://api.moonshot.ai/v1',
17
16
  },
18
17
  responseAnimation: {
19
18
  speed: 2,
@@ -22,7 +21,7 @@ const Moonshot: ModelProviderCard = {
22
21
  sdkType: 'openai',
23
22
  showModelFetcher: true,
24
23
  },
25
- url: 'https://www.moonshot.cn',
24
+ url: 'https://www.moonshot.ai/',
26
25
  };
27
26
 
28
27
  export default Moonshot;
@@ -6,7 +6,6 @@ import { LobeDeepSeekAI } from '../../providers/deepseek';
6
6
  import { LobeFalAI } from '../../providers/fal';
7
7
  import { LobeGoogleAI } from '../../providers/google';
8
8
  import { LobeMinimaxAI } from '../../providers/minimax';
9
- import { LobeMoonshotAI } from '../../providers/moonshot';
10
9
  import { LobeOpenAI } from '../../providers/openai';
11
10
  import { LobeQwenAI } from '../../providers/qwen';
12
11
  import { LobeVertexAI } from '../../providers/vertexai';
@@ -21,7 +20,6 @@ export const baseRuntimeMap = {
21
20
  fal: LobeFalAI,
22
21
  google: LobeGoogleAI,
23
22
  minimax: LobeMinimaxAI,
24
- moonshot: LobeMoonshotAI,
25
23
  openai: LobeOpenAI,
26
24
  qwen: LobeQwenAI,
27
25
  vertexai: LobeVertexAI,
@@ -452,6 +452,97 @@ describe('createRouterRuntime', () => {
452
452
  });
453
453
 
454
454
  describe('router matching', () => {
455
+ describe('baseURLPattern matching', () => {
456
+ it('should match router by baseURLPattern (RegExp)', async () => {
457
+ const mockChatOpenAI = vi.fn().mockResolvedValue('openai-response');
458
+ const mockChatAnthropic = vi.fn().mockResolvedValue('anthropic-response');
459
+
460
+ class OpenAIRuntime implements LobeRuntimeAI {
461
+ chat = mockChatOpenAI;
462
+ }
463
+
464
+ class AnthropicRuntime implements LobeRuntimeAI {
465
+ chat = mockChatAnthropic;
466
+ }
467
+
468
+ const Runtime = createRouterRuntime({
469
+ id: 'test-runtime',
470
+ routers: [
471
+ {
472
+ apiType: 'anthropic',
473
+ baseURLPattern: /\/anthropic\/?$/,
474
+ options: { apiKey: 'anthropic-key' },
475
+ runtime: AnthropicRuntime as any,
476
+ },
477
+ {
478
+ apiType: 'openai',
479
+ options: { apiKey: 'openai-key' },
480
+ runtime: OpenAIRuntime as any,
481
+ },
482
+ ],
483
+ });
484
+
485
+ const runtime = new Runtime({
486
+ apiKey: 'test',
487
+ baseURL: 'https://api.example.com/anthropic',
488
+ });
489
+ const result = await runtime.chat({
490
+ model: 'test-model',
491
+ messages: [],
492
+ temperature: 0.7,
493
+ });
494
+
495
+ expect(result).toBe('anthropic-response');
496
+ expect(mockChatAnthropic).toHaveBeenCalled();
497
+ expect(mockChatOpenAI).not.toHaveBeenCalled();
498
+ });
499
+
500
+ it('should prioritize baseURLPattern over models matching', async () => {
501
+ const mockChatOpenAI = vi.fn().mockResolvedValue('openai-response');
502
+ const mockChatAnthropic = vi.fn().mockResolvedValue('anthropic-response');
503
+
504
+ class OpenAIRuntime implements LobeRuntimeAI {
505
+ chat = mockChatOpenAI;
506
+ }
507
+
508
+ class AnthropicRuntime implements LobeRuntimeAI {
509
+ chat = mockChatAnthropic;
510
+ }
511
+
512
+ const Runtime = createRouterRuntime({
513
+ id: 'test-runtime',
514
+ routers: [
515
+ {
516
+ apiType: 'anthropic',
517
+ baseURLPattern: /\/anthropic\/?$/,
518
+ options: { apiKey: 'anthropic-key' },
519
+ runtime: AnthropicRuntime as any,
520
+ models: ['claude-3'],
521
+ },
522
+ {
523
+ apiType: 'openai',
524
+ options: { apiKey: 'openai-key' },
525
+ runtime: OpenAIRuntime as any,
526
+ models: ['gpt-4', 'test-model'], // includes test-model
527
+ },
528
+ ],
529
+ });
530
+
531
+ // Even though 'test-model' matches OpenAI router, baseURLPattern should win
532
+ const runtime = new Runtime({
533
+ apiKey: 'test',
534
+ baseURL: 'https://api.example.com/anthropic',
535
+ });
536
+ const result = await runtime.chat({
537
+ model: 'test-model',
538
+ messages: [],
539
+ temperature: 0.7,
540
+ });
541
+
542
+ expect(result).toBe('anthropic-response');
543
+ });
544
+ });
545
+
455
546
  it('should fallback to last router when model does not match any', async () => {
456
547
  const mockChatFirst = vi.fn().mockResolvedValue('first-response');
457
548
  const mockChatLast = vi.fn().mockResolvedValue('last-response');
@@ -58,10 +58,11 @@ interface RouterOptionItem extends ProviderIniOptions {
58
58
 
59
59
  type RouterOptions = RouterOptionItem | RouterOptionItem[];
60
60
 
61
- export type RuntimeClass = typeof LobeOpenAI;
61
+ export type RuntimeClass = new (options?: any) => LobeRuntimeAI;
62
62
 
63
63
  interface RouterInstance {
64
64
  apiType: keyof typeof baseRuntimeMap;
65
+ baseURLPattern?: RegExp;
65
66
  models?: string[];
66
67
  options: RouterOptions;
67
68
  runtime?: RuntimeClass;
@@ -177,14 +178,25 @@ export const createRouterRuntime = ({
177
178
 
178
179
  private async resolveMatchedRouter(model: string): Promise<RouterInstance> {
179
180
  const resolvedRouters = await this.resolveRouters(model);
180
- return (
181
- resolvedRouters.find((router) => {
182
- if (router.models && router.models.length > 0) {
183
- return router.models.includes(model);
184
- }
185
- return false;
186
- }) ?? resolvedRouters.at(-1)!
187
- );
181
+ const baseURL = this._options.baseURL;
182
+
183
+ // Priority 1: Match by baseURLPattern (RegExp only)
184
+ if (baseURL) {
185
+ const baseURLMatch = resolvedRouters.find((router) => router.baseURLPattern?.test(baseURL));
186
+ if (baseURLMatch) return baseURLMatch;
187
+ }
188
+
189
+ // Priority 2: Match by models
190
+ const modelMatch = resolvedRouters.find((router) => {
191
+ if (router.models && router.models.length > 0) {
192
+ return router.models.includes(model);
193
+ }
194
+ return false;
195
+ });
196
+ if (modelMatch) return modelMatch;
197
+
198
+ // Fallback: Use the last router
199
+ return resolvedRouters.at(-1)!;
188
200
  }
189
201
 
190
202
  private normalizeRouterOptions(router: RouterInstance): RouterOptionItem[] {
@@ -6,5 +6,5 @@ export interface RuntimeItem {
6
6
  runtime: LobeRuntimeAI;
7
7
  }
8
8
 
9
- export type { UniformRuntime } from './createRuntime';
9
+ export type { CreateRouterRuntimeOptions, UniformRuntime } from './createRuntime';
10
10
  export { createRouterRuntime } from './createRuntime';
@@ -1,7 +1,7 @@
1
1
  import type Anthropic from '@anthropic-ai/sdk';
2
2
  import debug from 'debug';
3
3
 
4
- import { buildAnthropicMessages, buildAnthropicTools } from '../../core/contextBuilders/anthropic';
4
+ import { buildAnthropicMessages, buildAnthropicTools } from '../contextBuilders/anthropic';
5
5
  import { GenerateObjectOptions, GenerateObjectPayload } from '../../types';
6
6
 
7
7
  const log = debug('lobe-model-runtime:anthropic:generate-object');