@lobehub/chat 1.0.13 → 1.0.14

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 (106) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +16 -14
  3. package/README.zh-CN.md +16 -14
  4. package/docs/self-hosting/advanced/feature-flags.zh-CN.mdx +2 -1
  5. package/docs/self-hosting/advanced/model-list.zh-CN.mdx +1 -0
  6. package/docs/self-hosting/advanced/server-database.mdx +4 -3
  7. package/docs/self-hosting/advanced/server-database.zh-CN.mdx +1 -0
  8. package/docs/self-hosting/advanced/settings-url-share.mdx +5 -4
  9. package/docs/self-hosting/advanced/settings-url-share.zh-CN.mdx +5 -4
  10. package/docs/self-hosting/advanced/sso-providers/zitadel.mdx +3 -3
  11. package/docs/self-hosting/advanced/sso-providers/zitadel.zh-CN.mdx +2 -1
  12. package/docs/self-hosting/advanced/upstream-sync.zh-CN.mdx +10 -10
  13. package/docs/self-hosting/examples/ollama.mdx +23 -23
  14. package/docs/self-hosting/examples/ollama.zh-CN.mdx +23 -24
  15. package/docs/self-hosting/platform/docker-compose.zh-CN.mdx +2 -3
  16. package/docs/self-hosting/platform/vercel.mdx +2 -2
  17. package/docs/self-hosting/platform/vercel.zh-CN.mdx +2 -1
  18. package/docs/self-hosting/platform/zeabur.mdx +6 -7
  19. package/docs/self-hosting/platform/zeabur.zh-CN.mdx +6 -7
  20. package/docs/usage/agents/prompt.mdx +1 -1
  21. package/docs/usage/agents/prompt.zh-CN.mdx +1 -1
  22. package/docs/usage/features/auth.mdx +13 -8
  23. package/docs/usage/features/auth.zh-CN.mdx +5 -3
  24. package/docs/usage/features/database.mdx +20 -14
  25. package/docs/usage/features/database.zh-CN.mdx +1 -1
  26. package/docs/usage/features/local-llm.mdx +5 -0
  27. package/docs/usage/features/local-llm.zh-CN.mdx +5 -0
  28. package/docs/usage/features/multi-ai-providers.mdx +5 -0
  29. package/docs/usage/features/multi-ai-providers.zh-CN.mdx +5 -0
  30. package/docs/usage/features/plugin-system.zh-CN.mdx +2 -1
  31. package/docs/usage/features/pwa.mdx +3 -2
  32. package/docs/usage/features/pwa.zh-CN.mdx +3 -2
  33. package/docs/usage/providers/01ai.mdx +86 -0
  34. package/docs/usage/providers/01ai.zh-CN.mdx +85 -0
  35. package/docs/usage/providers/anthropic.mdx +79 -0
  36. package/docs/usage/providers/anthropic.zh-CN.mdx +74 -0
  37. package/docs/usage/providers/azure.mdx +89 -0
  38. package/docs/usage/providers/azure.zh-CN.mdx +82 -0
  39. package/docs/usage/providers/bedrock.mdx +140 -0
  40. package/docs/usage/providers/bedrock.zh-CN.mdx +135 -0
  41. package/docs/usage/providers/deepseek.mdx +91 -0
  42. package/docs/usage/providers/deepseek.zh-CN.mdx +86 -0
  43. package/docs/usage/providers/gemini.mdx +83 -0
  44. package/docs/usage/providers/gemini.zh-CN.mdx +80 -0
  45. package/docs/usage/providers/groq.mdx +1 -3
  46. package/docs/usage/providers/groq.zh-CN.mdx +1 -1
  47. package/docs/usage/providers/minimax.mdx +89 -0
  48. package/docs/usage/providers/minimax.zh-CN.mdx +85 -0
  49. package/docs/usage/providers/mistral.mdx +71 -0
  50. package/docs/usage/providers/mistral.zh-CN.mdx +66 -0
  51. package/docs/usage/providers/moonshot.mdx +70 -0
  52. package/docs/usage/providers/moonshot.zh-CN.mdx +66 -0
  53. package/docs/usage/providers/ollama/gemma.mdx +1 -1
  54. package/docs/usage/providers/ollama/gemma.zh-CN.mdx +1 -1
  55. package/docs/usage/providers/ollama/qwen.mdx +1 -1
  56. package/docs/usage/providers/ollama/qwen.zh-CN.mdx +1 -1
  57. package/docs/usage/providers/ollama.mdx +1 -1
  58. package/docs/usage/providers/ollama.zh-CN.mdx +1 -1
  59. package/docs/usage/providers/openai.mdx +95 -0
  60. package/docs/usage/providers/openai.zh-CN.mdx +87 -0
  61. package/docs/usage/providers/openrouter.mdx +111 -0
  62. package/docs/usage/providers/openrouter.zh-CN.mdx +109 -0
  63. package/docs/usage/providers/perplexity.mdx +64 -0
  64. package/docs/usage/providers/perplexity.zh-CN.mdx +61 -0
  65. package/docs/usage/providers/qwen.mdx +93 -0
  66. package/docs/usage/providers/qwen.zh-CN.mdx +86 -0
  67. package/docs/usage/providers/stepfun.mdx +69 -0
  68. package/docs/usage/providers/stepfun.zh-CN.mdx +64 -0
  69. package/docs/usage/providers/togetherai.mdx +74 -0
  70. package/docs/usage/providers/togetherai.zh-CN.mdx +71 -0
  71. package/docs/usage/providers/zhipu.mdx +69 -0
  72. package/docs/usage/providers/zhipu.zh-CN.mdx +64 -0
  73. package/docs/usage/providers.mdx +36 -0
  74. package/docs/usage/providers.zh-CN.mdx +34 -0
  75. package/docs/usage/start.mdx +2 -0
  76. package/docs/usage/start.zh-CN.mdx +2 -0
  77. package/locales/ar/setting.json +1 -0
  78. package/locales/bg-BG/setting.json +1 -0
  79. package/locales/de-DE/setting.json +1 -0
  80. package/locales/en-US/setting.json +1 -0
  81. package/locales/es-ES/setting.json +1 -0
  82. package/locales/fr-FR/setting.json +1 -0
  83. package/locales/it-IT/setting.json +1 -0
  84. package/locales/ja-JP/setting.json +1 -0
  85. package/locales/ko-KR/setting.json +1 -0
  86. package/locales/nl-NL/setting.json +1 -0
  87. package/locales/pl-PL/setting.json +1 -0
  88. package/locales/pt-BR/setting.json +1 -0
  89. package/locales/ru-RU/setting.json +1 -0
  90. package/locales/tr-TR/setting.json +1 -0
  91. package/locales/vi-VN/setting.json +1 -0
  92. package/locales/zh-CN/setting.json +1 -0
  93. package/locales/zh-TW/setting.json +1 -0
  94. package/package.json +6 -5
  95. package/src/app/(main)/settings/llm/ProviderList/providers.tsx +33 -4
  96. package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +41 -11
  97. package/src/app/(main)/settings/llm/index.tsx +1 -2
  98. package/src/features/ChatInput/useSend.ts +2 -1
  99. package/src/features/Conversation/Messages/Assistant/ToolCalls/index.tsx +1 -1
  100. package/src/features/Conversation/Messages/components/Arguments.tsx +5 -3
  101. package/src/features/Conversation/Messages/hooks/useYamlArguments.ts +5 -2
  102. package/src/locales/default/setting.ts +1 -0
  103. package/src/store/chat/slices/plugin/action.test.ts +5 -5
  104. package/src/store/chat/slices/plugin/action.ts +6 -2
  105. package/src/store/tool/slices/builtin/action.test.ts +8 -11
  106. package/src/store/tool/slices/builtin/action.ts +9 -9
@@ -102,6 +102,7 @@
102
102
  "latestTime": "Laatst bijgewerkt: {{time}}",
103
103
  "noLatestTime": "Geen lijst beschikbaar op dit moment"
104
104
  },
105
+ "helpDoc": "configuratiehandleiding",
105
106
  "modelList": {
106
107
  "desc": "Selecteer het model dat in de sessie moet worden weergegeven. Het geselecteerde model wordt weergegeven in de modellijst.",
107
108
  "placeholder": "Selecteer een model uit de lijst",
@@ -102,6 +102,7 @@
102
102
  "latestTime": "Ostatnia aktualizacja: {{time}}",
103
103
  "noLatestTime": "Brak dostępnej listy"
104
104
  },
105
+ "helpDoc": "Poradnik konfiguracji",
105
106
  "modelList": {
106
107
  "desc": "Wybierz modele do wyświetlenia w sesji. Wybrane modele będą widoczne na liście modeli",
107
108
  "placeholder": "Wybierz model z listy",
@@ -102,6 +102,7 @@
102
102
  "latestTime": "Última atualização: {{time}}",
103
103
  "noLatestTime": "Lista não disponível"
104
104
  },
105
+ "helpDoc": "Tutorial de configuração",
105
106
  "modelList": {
106
107
  "desc": "Escolha os modelos a serem exibidos na conversa. Os modelos selecionados serão exibidos na lista de modelos.",
107
108
  "placeholder": "Selecione um modelo da lista",
@@ -102,6 +102,7 @@
102
102
  "latestTime": "Последнее обновление: {{time}}",
103
103
  "noLatestTime": "Список пока не получен"
104
104
  },
105
+ "helpDoc": "Руководство по настройке",
105
106
  "modelList": {
106
107
  "desc": "Выберите модель для отображения в сеансе, выбранная модель будет отображаться в списке моделей",
107
108
  "placeholder": "Выберите модель из списка",
@@ -102,6 +102,7 @@
102
102
  "latestTime": "Son güncelleme zamanı: {{time}}",
103
103
  "noLatestTime": "Liste henüz alınamadı"
104
104
  },
105
+ "helpDoc": "Yardım Belgeleri",
105
106
  "modelList": {
106
107
  "desc": "Görüntülenecek modeli seçin, seçilen model model listesinde görüntülenecektir",
107
108
  "placeholder": "Lütfen listeden bir model seçin",
@@ -102,6 +102,7 @@
102
102
  "latestTime": "Thời gian cập nhật lần cuối: {{time}}",
103
103
  "noLatestTime": "Chưa có danh sách nào được lấy"
104
104
  },
105
+ "helpDoc": "Hướng dẫn cấu hình",
105
106
  "modelList": {
106
107
  "desc": "Chọn mô hình hiển thị trong cuộc trò chuyện, mô hình đã chọn sẽ được hiển thị trong danh sách mô hình",
107
108
  "placeholder": "Vui lòng chọn mô hình từ danh sách",
@@ -102,6 +102,7 @@
102
102
  "latestTime": "上次更新时间:{{time}}",
103
103
  "noLatestTime": "暂未获取列表"
104
104
  },
105
+ "helpDoc": "配置教程",
105
106
  "modelList": {
106
107
  "desc": "选择在会话中展示的模型,选择的模型会在模型列表中展示",
107
108
  "placeholder": "请从列表中选择模型",
@@ -102,6 +102,7 @@
102
102
  "latestTime": "上次更新時間:{{time}}",
103
103
  "noLatestTime": "暫未獲取列表"
104
104
  },
105
+ "helpDoc": "配置說明文件",
105
106
  "modelList": {
106
107
  "desc": "選擇在會話中展示的模型,選擇的模型會在模型列表中展示",
107
108
  "placeholder": "請從列表中選擇模型",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
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",
@@ -40,13 +40,13 @@
40
40
  "db:z-pull": "drizzle-kit introspect -- dotenv_config_path='.env'",
41
41
  "dev": "next dev -p 3010",
42
42
  "dev:clerk-proxy": "ngrok http http://localhost:3011",
43
- "docs:i18n": "lobe-i18n md && npm run workflow:docs && npm run lint:mdx",
44
- "docs:seo": "lobe-seo && npm run workflow:mdx && npm run lint:mdx",
43
+ "docs:i18n": "lobe-i18n md && npm run lint:mdx",
44
+ "docs:seo": "lobe-seo && npm run lint:mdx",
45
45
  "i18n": "npm run workflow:i18n && lobe-i18n",
46
46
  "lint": "npm run lint:ts && npm run lint:style && npm run type-check && npm run lint:circular",
47
47
  "lint:circular": "dpdm src/**/*.ts --warning false --tree false --exit-code circular:1 -T true --skip-dynamic-imports circular",
48
48
  "lint:md": "remark . --quiet --frail --output",
49
- "lint:mdx": "eslint \"{contributing,docs}/**/*.mdx\" --quiet --fix",
49
+ "lint:mdx": "npm run workflow:mdx-with-lint && prettier -c --write \"{src,docs}/**/*.mdx\" && npm run workflow:mdx-with-lint",
50
50
  "lint:style": "stylelint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
51
51
  "lint:ts": "eslint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
52
52
  "prepare": "husky",
@@ -64,7 +64,8 @@
64
64
  "type-check": "tsc --noEmit",
65
65
  "workflow:docs": "tsx scripts/docsWorkflow/index.ts",
66
66
  "workflow:i18n": "tsx scripts/i18nWorkflow/index.ts",
67
- "workflow:mdx": "tsx scripts/mdxWorkflow/index.ts",
67
+ "workflow:mdx": "tsx ./scripts/mdxWorkflow/index.ts",
68
+ "workflow:mdx-with-lint": "tsx ./scripts/mdxWorkflow/index.ts && eslint \"docs/**/*.mdx\" --quiet --fix",
68
69
  "workflow:readme": "tsx scripts/readmeWorkflow/index.ts"
69
70
  },
70
71
  "lint-staged": {
@@ -20,6 +20,7 @@ import { Divider } from 'antd';
20
20
  import { useTheme } from 'antd-style';
21
21
  import { useMemo } from 'react';
22
22
  import { Flexbox } from 'react-layout-kit';
23
+ import urlJoin from 'url-join';
23
24
 
24
25
  import {
25
26
  AnthropicProviderCard,
@@ -44,6 +45,8 @@ import { useBedrockProvider } from './Bedrock';
44
45
  import { useOllamaProvider } from './Ollama';
45
46
  import { useOpenAIProvider } from './OpenAI';
46
47
 
48
+ const BASE_DOC_URL = 'https://lobehub.com/docs/usage/providers';
49
+
47
50
  const AnthropicBrand = () => {
48
51
  const { isDarkMode } = useTheme();
49
52
  return <Anthropic.Text color={isDarkMode ? undefined : Claude.colorPrimary} size={15} />;
@@ -81,64 +84,90 @@ export const useProviderList = (): ProviderItem[] => {
81
84
 
82
85
  return useMemo(
83
86
  () => [
84
- openAIProvider,
85
- ollamaProvider,
86
- azureProvider,
87
+ {
88
+ ...openAIProvider,
89
+ docUrl: urlJoin(BASE_DOC_URL, 'openai'),
90
+ },
91
+ {
92
+ ...ollamaProvider,
93
+ docUrl: urlJoin(BASE_DOC_URL, 'ollama'),
94
+ },
95
+ {
96
+ ...azureProvider,
97
+ docUrl: urlJoin(BASE_DOC_URL, 'azure'),
98
+ },
87
99
  {
88
100
  ...GoogleProviderCard,
101
+ docUrl: urlJoin(BASE_DOC_URL, 'gemini'),
89
102
  title: <GoogleBrand />,
90
103
  },
91
104
  {
92
105
  ...AnthropicProviderCard,
106
+ docUrl: urlJoin(BASE_DOC_URL, 'anthropic'),
93
107
  title: <AnthropicBrand />,
94
108
  },
95
- bedrockProvider,
109
+ {
110
+ ...bedrockProvider,
111
+ docUrl: urlJoin(BASE_DOC_URL, 'bedrock'),
112
+ },
96
113
  {
97
114
  ...GroqProviderCard,
115
+ docUrl: urlJoin(BASE_DOC_URL, 'groq'),
98
116
  title: <GroqBrand />,
99
117
  },
100
118
  {
101
119
  ...OpenRouterProviderCard,
120
+ docUrl: urlJoin(BASE_DOC_URL, 'openrouter'),
102
121
  title: <OpenRouter.Combine iconProps={{ color: OpenRouter.colorPrimary }} size={20} />,
103
122
  },
104
123
  {
105
124
  ...TogetherAIProviderCard,
125
+ docUrl: urlJoin(BASE_DOC_URL, 'togetherai'),
106
126
  title: <Together.Combine size={26} type={'color'} />,
107
127
  },
108
128
  {
109
129
  ...QwenProviderCard,
130
+ docUrl: urlJoin(BASE_DOC_URL, 'qwen'),
110
131
  title: <Tongyi.Combine extra={'千问'} size={26} type={'color'} />,
111
132
  },
112
133
  {
113
134
  ...DeepSeekProviderCard,
135
+ docUrl: urlJoin(BASE_DOC_URL, 'deepseek'),
114
136
  title: <DeepSeek.Combine size={28} type={'color'} />,
115
137
  },
116
138
  {
117
139
  ...MinimaxProviderCard,
140
+ docUrl: urlJoin(BASE_DOC_URL, 'minimax'),
118
141
  title: <Minimax.Combine size={32} type={'color'} />,
119
142
  },
120
143
  {
121
144
  ...MistralProviderCard,
145
+ docUrl: urlJoin(BASE_DOC_URL, 'mistral'),
122
146
  title: <Mistral.Combine size={26} type={'color'} />,
123
147
  },
124
148
  {
125
149
  ...MoonshotProviderCard,
150
+ docUrl: urlJoin(BASE_DOC_URL, 'moonshot'),
126
151
  title: <MoonshotBrand />,
127
152
  },
128
153
  {
129
154
  ...PerplexityProviderCard,
155
+ docUrl: urlJoin(BASE_DOC_URL, 'perplexity'),
130
156
  title: <Perplexity.Combine size={24} type={'color'} />,
131
157
  },
132
158
  {
133
159
  ...ZhiPuProviderCard,
160
+ docUrl: urlJoin(BASE_DOC_URL, 'zhipu'),
134
161
  title: <Zhipu.Combine size={32} type={'color'} />,
135
162
  },
136
163
  {
137
164
  ...ZeroOneProviderCard,
165
+ docUrl: urlJoin(BASE_DOC_URL, '01ai'),
138
166
  title: <ZeroOne.Text size={20} />,
139
167
  },
140
168
  {
141
169
  ...StepfunProviderCard,
170
+ docUrl: urlJoin(BASE_DOC_URL, 'stepfun'),
142
171
  title: <Stepfun.Combine size={20} type={'color'} />,
143
172
  },
144
173
  ],
@@ -1,12 +1,13 @@
1
1
  'use client';
2
2
 
3
- import { Form, type FormItemProps, type ItemGroup } from '@lobehub/ui';
3
+ import { Form, type FormItemProps, type ItemGroup, Tooltip } from '@lobehub/ui';
4
4
  import { Input, Switch } from 'antd';
5
5
  import { createStyles } from 'antd-style';
6
6
  import { debounce } from 'lodash-es';
7
+ import Link from 'next/link';
7
8
  import { ReactNode, memo } from 'react';
8
9
  import { useTranslation } from 'react-i18next';
9
- import { Flexbox } from 'react-layout-kit';
10
+ import { Center, Flexbox } from 'react-layout-kit';
10
11
 
11
12
  import { useSyncSettings } from '@/app/(main)/settings/hooks/useSyncSettings';
12
13
  import {
@@ -25,7 +26,7 @@ import { GlobalLLMProviderKey } from '@/types/user/settings';
25
26
  import Checker from '../Checker';
26
27
  import ProviderModelListSelect from '../ProviderModelList';
27
28
 
28
- const useStyles = createStyles(({ css, prefixCls, responsive }) => ({
29
+ const useStyles = createStyles(({ css, prefixCls, responsive, token }) => ({
29
30
  form: css`
30
31
  .${prefixCls}-form-item-control:has(.${prefixCls}-input,.${prefixCls}-select) {
31
32
  flex: none;
@@ -40,6 +41,19 @@ const useStyles = createStyles(({ css, prefixCls, responsive }) => ({
40
41
  font-size: 12px;
41
42
  }
42
43
  `,
44
+ help: css`
45
+ font-size: 12px;
46
+ font-weight: 500;
47
+ color: ${token.colorTextDescription};
48
+
49
+ background: ${token.colorFillTertiary};
50
+ border-radius: 50%;
51
+
52
+ &:hover {
53
+ color: ${token.colorText};
54
+ background: ${token.colorFill};
55
+ }
56
+ `,
43
57
  safariIconWidthFix: css`
44
58
  svg {
45
59
  width: unset !important;
@@ -52,6 +66,7 @@ export interface ProviderConfigProps extends Omit<ModelProviderCard, 'id'> {
52
66
  canDeactivate?: boolean;
53
67
  checkerItem?: FormItemProps;
54
68
  className?: string;
69
+ docUrl?: string;
55
70
  hideSwitch?: boolean;
56
71
  id: GlobalLLMProviderKey;
57
72
  modelList?: {
@@ -78,6 +93,7 @@ const ProviderConfig = memo<ProviderConfigProps>(
78
93
  disableBrowserRequest,
79
94
  className,
80
95
  name,
96
+ docUrl,
81
97
  }) => {
82
98
  const { t } = useTranslation('setting');
83
99
  const [form] = Form.useForm();
@@ -178,14 +194,28 @@ const ProviderConfig = memo<ProviderConfigProps>(
178
194
  children: formItems,
179
195
 
180
196
  defaultActive: canDeactivate ? enabled : undefined,
181
- extra: canDeactivate ? (
182
- <Switch
183
- onChange={(enabled) => {
184
- toggleProviderEnabled(id, enabled);
185
- }}
186
- value={enabled}
187
- />
188
- ) : undefined,
197
+
198
+ extra: (
199
+ <Flexbox align={'center'} gap={8} horizontal>
200
+ {docUrl && (
201
+ <Tooltip title={t('llm.helpDoc')}>
202
+ <Link href={docUrl} onClick={(e) => e.stopPropagation()} target={'_blank'}>
203
+ <Center className={styles.help} height={20} width={20}>
204
+ ?
205
+ </Center>
206
+ </Link>
207
+ </Tooltip>
208
+ )}
209
+ {canDeactivate ? (
210
+ <Switch
211
+ onChange={(enabled) => {
212
+ toggleProviderEnabled(id, enabled);
213
+ }}
214
+ value={enabled}
215
+ />
216
+ ) : undefined}
217
+ </Flexbox>
218
+ ),
189
219
  title: (
190
220
  <Flexbox
191
221
  align={'center'}
@@ -2,9 +2,8 @@
2
2
 
3
3
  import { Flexbox } from 'react-layout-kit';
4
4
 
5
- import Footer from '@/app/(main)/settings/llm/components/Footer';
6
-
7
5
  import { useProviderList } from './ProviderList/providers';
6
+ import Footer from './components/Footer';
8
7
  import ProviderConfig from './components/ProviderConfig';
9
8
 
10
9
  const Page = () => {
@@ -19,9 +19,10 @@ export const useSendMessage = () => {
19
19
  return useCallback((params: UseSendMessageParams = {}) => {
20
20
  const store = useChatStore.getState();
21
21
  if (chatSelectors.isAIGenerating(store)) return;
22
- if (!store.inputMessage) return;
23
22
 
24
23
  const imageList = filesSelectors.imageUrlOrBase64List(useFileStore.getState());
24
+ // if there is no message and no image, then we should not send the message
25
+ if (!store.inputMessage && imageList.length === 0) return;
25
26
 
26
27
  sendMessage({
27
28
  files: imageList,
@@ -22,7 +22,7 @@ export interface InspectorProps {
22
22
  }
23
23
 
24
24
  const CallItem = memo<InspectorProps>(
25
- ({ arguments: requestArgs = '{}', messageId, index, identifier, style }) => {
25
+ ({ arguments: requestArgs, messageId, index, identifier, style }) => {
26
26
  const { t } = useTranslation('plugin');
27
27
  const { styles } = useStyles();
28
28
  const [open, setOpen] = useState(false);
@@ -11,9 +11,11 @@ const Arguments = memo<ArgumentsProps>(({ arguments: args = '' }) => {
11
11
  const yaml = useYamlArguments(args);
12
12
 
13
13
  return (
14
- <Highlighter language={'yaml'} showLanguage={false}>
15
- {yaml}
16
- </Highlighter>
14
+ !!yaml && (
15
+ <Highlighter language={'yaml'} showLanguage={false}>
16
+ {yaml}
17
+ </Highlighter>
18
+ )
17
19
  );
18
20
  });
19
21
 
@@ -1,9 +1,12 @@
1
- import { Allow, parse } from 'partial-json';
1
+ import { parse } from 'partial-json';
2
2
  import { stringify } from 'yaml';
3
3
 
4
4
  export const useYamlArguments = (args: string) => {
5
5
  try {
6
- const obj = parse(args, Allow.OBJ);
6
+ const obj = parse(args);
7
+
8
+ if (Object.keys(obj).length === 0) return '';
9
+
7
10
  return stringify(obj);
8
11
  } catch {
9
12
  return args;
@@ -105,6 +105,7 @@ export default {
105
105
  latestTime: '上次更新时间:{{time}}',
106
106
  noLatestTime: '暂未获取列表',
107
107
  },
108
+ helpDoc: '配置教程',
108
109
  modelList: {
109
110
  desc: '选择在会话中展示的模型,选择的模型会在模型列表中展示',
110
111
  placeholder: '请从列表中选择模型',
@@ -463,7 +463,7 @@ describe('ChatPluginAction', () => {
463
463
  const toolResponse = JSON.stringify({ abc: 'data' });
464
464
 
465
465
  useToolStore.setState({
466
- invokeBuiltinTool: vi.fn().mockResolvedValue(toolResponse),
466
+ transformApiArgumentsToAiState: vi.fn().mockResolvedValue(toolResponse),
467
467
  });
468
468
 
469
469
  useChatStore.setState({
@@ -479,7 +479,7 @@ describe('ChatPluginAction', () => {
479
479
  });
480
480
 
481
481
  // Verify that the builtin tool was invoked with the correct arguments
482
- expect(useToolStore.getState().invokeBuiltinTool).toHaveBeenCalledWith(
482
+ expect(useToolStore.getState().transformApiArgumentsToAiState).toHaveBeenCalledWith(
483
483
  payload.apiName,
484
484
  JSON.parse(payload.arguments),
485
485
  );
@@ -511,7 +511,7 @@ describe('ChatPluginAction', () => {
511
511
 
512
512
  act(() => {
513
513
  useToolStore.setState({
514
- invokeBuiltinTool: vi.fn().mockResolvedValue(toolResponse),
514
+ transformApiArgumentsToAiState: vi.fn().mockResolvedValue(toolResponse),
515
515
  text2image: vi.fn(),
516
516
  });
517
517
 
@@ -528,7 +528,7 @@ describe('ChatPluginAction', () => {
528
528
  });
529
529
 
530
530
  // Verify that the builtin tool was invoked with the correct arguments
531
- expect(useToolStore.getState().invokeBuiltinTool).toHaveBeenCalledWith(
531
+ expect(useToolStore.getState().transformApiArgumentsToAiState).toHaveBeenCalledWith(
532
532
  payload.apiName,
533
533
  JSON.parse(payload.arguments),
534
534
  );
@@ -559,7 +559,7 @@ describe('ChatPluginAction', () => {
559
559
  const error = new Error('Builtin tool failed');
560
560
 
561
561
  useToolStore.setState({
562
- invokeBuiltinTool: vi.fn().mockRejectedValue(error),
562
+ transformApiArgumentsToAiState: vi.fn().mockRejectedValue(error),
563
563
  });
564
564
 
565
565
  useChatStore.setState({
@@ -81,7 +81,7 @@ export const chatPlugin: StateCreator<
81
81
  internal_togglePluginApiCalling(true, id, n('invokeBuiltinTool') as string);
82
82
  let data;
83
83
  try {
84
- data = await useToolStore.getState().invokeBuiltinTool(payload.apiName, params);
84
+ data = await useToolStore.getState().transformApiArgumentsToAiState(payload.apiName, params);
85
85
  } catch (error) {
86
86
  console.log(error);
87
87
  }
@@ -91,6 +91,7 @@ export const chatPlugin: StateCreator<
91
91
 
92
92
  await internal_updateMessageContent(id, data);
93
93
 
94
+ // run tool api call
94
95
  // postToolCalling
95
96
  // @ts-ignore
96
97
  const { [payload.apiName]: action } = get();
@@ -147,7 +148,10 @@ export const chatPlugin: StateCreator<
147
148
  const message = chatSelectors.getMessageById(id)(get());
148
149
  if (!message || message.role !== 'tool' || !message.plugin) return;
149
150
 
150
- get().internal_updateMessageError(id, null);
151
+ // if there is error content, then clear the error
152
+ if (!!message.error) {
153
+ get().internal_updateMessageError(id, null);
154
+ }
151
155
 
152
156
  const payload: ChatToolPayload = { ...message.plugin, id: message.tool_call_id! };
153
157
 
@@ -23,7 +23,7 @@ describe('createBuiltinToolSlice', () => {
23
23
 
24
24
  await act(async () => {
25
25
  // When
26
- const data = await result.current.invokeBuiltinTool(key, params);
26
+ const data = await result.current.transformApiArgumentsToAiState(key, params);
27
27
  expect(data).toBeUndefined();
28
28
  });
29
29
 
@@ -53,7 +53,7 @@ describe('createBuiltinToolSlice', () => {
53
53
  });
54
54
  // When
55
55
  await act(async () => {
56
- await result.current.invokeBuiltinTool(key, params);
56
+ await result.current.transformApiArgumentsToAiState(key, params);
57
57
  });
58
58
 
59
59
  expect(mockFn).toBeCalledWith({
@@ -70,15 +70,12 @@ describe('createBuiltinToolSlice', () => {
70
70
  // When
71
71
  const { result } = renderHook(() => useToolStore());
72
72
 
73
- const data = result.current.text2image(
74
- {
75
- prompts: ['prompt1', 'prompt2'],
76
- size: '1024x1024',
77
- quality: 'standard',
78
- style: 'vivid',
79
- },
80
- 'a',
81
- );
73
+ const data = result.current.text2image({
74
+ prompts: ['prompt1', 'prompt2'],
75
+ size: '1024x1024',
76
+ quality: 'standard',
77
+ style: 'vivid',
78
+ });
82
79
 
83
80
  // Then
84
81
  expect(data).toEqual([
@@ -16,9 +16,9 @@ interface Text2ImageParams extends Pick<OpenAIImagePayload, 'quality' | 'style'
16
16
  * 代理行为接口
17
17
  */
18
18
  export interface BuiltinToolAction {
19
- invokeBuiltinTool: (key: string, params: any) => Promise<string | undefined>;
20
- text2image: (params: Text2ImageParams, messageId: string) => DallEImageItem[];
19
+ text2image: (params: Text2ImageParams) => DallEImageItem[];
21
20
  toggleBuiltinToolLoading: (key: string, value: boolean) => void;
21
+ transformApiArgumentsToAiState: (key: string, params: any) => Promise<string | undefined>;
22
22
  }
23
23
 
24
24
  export const createBuiltinToolSlice: StateCreator<
@@ -27,7 +27,13 @@ export const createBuiltinToolSlice: StateCreator<
27
27
  [],
28
28
  BuiltinToolAction
29
29
  > = (set, get) => ({
30
- invokeBuiltinTool: async (key, params) => {
30
+ text2image: ({ prompts, size = '1024x1024' as const, quality = 'standard', style = 'vivid' }) =>
31
+ prompts.map((p) => ({ prompt: p, quality, size, style })),
32
+ toggleBuiltinToolLoading: (key, value) => {
33
+ set({ builtinToolLoading: { [key]: value } }, false, n('toggleBuiltinToolLoading'));
34
+ },
35
+
36
+ transformApiArgumentsToAiState: async (key, params) => {
31
37
  const { builtinToolLoading, toggleBuiltinToolLoading } = get();
32
38
 
33
39
  if (builtinToolLoading[key]) return;
@@ -45,10 +51,4 @@ export const createBuiltinToolSlice: StateCreator<
45
51
 
46
52
  return JSON.stringify(result);
47
53
  },
48
- text2image: ({ prompts, size = '1024x1024' as const, quality = 'standard', style = 'vivid' }) =>
49
- prompts.map((p) => ({ prompt: p, quality, size, style })),
50
-
51
- toggleBuiltinToolLoading: (key, value) => {
52
- set({ builtinToolLoading: { [key]: value } }, false, n('toggleBuiltinToolLoading'));
53
- },
54
54
  });