@lobehub/chat 1.81.2 → 1.81.4

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 (154) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/changelog/v1.json +21 -0
  3. package/locales/ar/common.json +2 -0
  4. package/locales/ar/electron.json +32 -0
  5. package/locales/ar/models.json +126 -3
  6. package/locales/ar/plugin.json +1 -0
  7. package/locales/ar/tool.json +25 -0
  8. package/locales/bg-BG/common.json +2 -0
  9. package/locales/bg-BG/electron.json +32 -0
  10. package/locales/bg-BG/models.json +126 -3
  11. package/locales/bg-BG/plugin.json +1 -0
  12. package/locales/bg-BG/tool.json +25 -0
  13. package/locales/de-DE/common.json +2 -0
  14. package/locales/de-DE/electron.json +32 -0
  15. package/locales/de-DE/models.json +126 -3
  16. package/locales/de-DE/plugin.json +1 -0
  17. package/locales/de-DE/tool.json +25 -0
  18. package/locales/en-US/common.json +2 -0
  19. package/locales/en-US/electron.json +32 -0
  20. package/locales/en-US/models.json +126 -3
  21. package/locales/en-US/plugin.json +1 -0
  22. package/locales/en-US/tool.json +25 -0
  23. package/locales/es-ES/common.json +2 -0
  24. package/locales/es-ES/electron.json +32 -0
  25. package/locales/es-ES/models.json +126 -3
  26. package/locales/es-ES/plugin.json +1 -0
  27. package/locales/es-ES/tool.json +25 -0
  28. package/locales/fa-IR/common.json +2 -0
  29. package/locales/fa-IR/electron.json +32 -0
  30. package/locales/fa-IR/models.json +126 -3
  31. package/locales/fa-IR/plugin.json +1 -0
  32. package/locales/fa-IR/tool.json +25 -0
  33. package/locales/fr-FR/common.json +2 -0
  34. package/locales/fr-FR/electron.json +32 -0
  35. package/locales/fr-FR/models.json +126 -3
  36. package/locales/fr-FR/plugin.json +1 -0
  37. package/locales/fr-FR/tool.json +25 -0
  38. package/locales/it-IT/common.json +2 -0
  39. package/locales/it-IT/electron.json +32 -0
  40. package/locales/it-IT/models.json +126 -3
  41. package/locales/it-IT/plugin.json +1 -0
  42. package/locales/it-IT/tool.json +25 -0
  43. package/locales/ja-JP/common.json +2 -0
  44. package/locales/ja-JP/electron.json +32 -0
  45. package/locales/ja-JP/models.json +126 -3
  46. package/locales/ja-JP/plugin.json +1 -0
  47. package/locales/ja-JP/tool.json +25 -0
  48. package/locales/ko-KR/common.json +2 -0
  49. package/locales/ko-KR/electron.json +32 -0
  50. package/locales/ko-KR/models.json +126 -3
  51. package/locales/ko-KR/plugin.json +1 -0
  52. package/locales/ko-KR/tool.json +25 -0
  53. package/locales/nl-NL/common.json +2 -0
  54. package/locales/nl-NL/electron.json +32 -0
  55. package/locales/nl-NL/models.json +126 -3
  56. package/locales/nl-NL/plugin.json +1 -0
  57. package/locales/nl-NL/tool.json +25 -0
  58. package/locales/pl-PL/common.json +2 -0
  59. package/locales/pl-PL/electron.json +32 -0
  60. package/locales/pl-PL/models.json +126 -3
  61. package/locales/pl-PL/plugin.json +1 -0
  62. package/locales/pl-PL/tool.json +25 -0
  63. package/locales/pt-BR/common.json +2 -0
  64. package/locales/pt-BR/electron.json +32 -0
  65. package/locales/pt-BR/models.json +126 -3
  66. package/locales/pt-BR/plugin.json +1 -0
  67. package/locales/pt-BR/tool.json +25 -0
  68. package/locales/ru-RU/common.json +2 -0
  69. package/locales/ru-RU/electron.json +32 -0
  70. package/locales/ru-RU/models.json +126 -3
  71. package/locales/ru-RU/plugin.json +1 -0
  72. package/locales/ru-RU/tool.json +25 -0
  73. package/locales/tr-TR/common.json +2 -0
  74. package/locales/tr-TR/electron.json +32 -0
  75. package/locales/tr-TR/models.json +126 -3
  76. package/locales/tr-TR/plugin.json +1 -0
  77. package/locales/tr-TR/tool.json +25 -0
  78. package/locales/vi-VN/common.json +2 -0
  79. package/locales/vi-VN/electron.json +32 -0
  80. package/locales/vi-VN/models.json +126 -3
  81. package/locales/vi-VN/plugin.json +1 -0
  82. package/locales/vi-VN/tool.json +25 -0
  83. package/locales/zh-CN/common.json +2 -0
  84. package/locales/zh-CN/electron.json +32 -0
  85. package/locales/zh-CN/models.json +131 -8
  86. package/locales/zh-CN/plugin.json +1 -0
  87. package/locales/zh-CN/tool.json +25 -0
  88. package/locales/zh-TW/common.json +2 -0
  89. package/locales/zh-TW/electron.json +32 -0
  90. package/locales/zh-TW/models.json +126 -3
  91. package/locales/zh-TW/plugin.json +1 -0
  92. package/locales/zh-TW/tool.json +25 -0
  93. package/package.json +3 -2
  94. package/packages/electron-client-ipc/src/events/index.ts +5 -5
  95. package/packages/electron-client-ipc/src/events/localFile.ts +22 -0
  96. package/packages/electron-client-ipc/src/events/{file.ts → upload.ts} +1 -1
  97. package/packages/electron-client-ipc/src/types/index.ts +2 -1
  98. package/packages/electron-client-ipc/src/types/localFile.ts +52 -0
  99. package/scripts/prebuild.mts +5 -1
  100. package/src/app/(backend)/trpc/desktop/[trpc]/route.ts +26 -0
  101. package/src/config/aiModels/cloudflare.ts +41 -37
  102. package/src/config/aiModels/github.ts +90 -0
  103. package/src/config/aiModels/google.ts +25 -0
  104. package/src/features/Conversation/Messages/Assistant/Tool/Render/Arguments/ObjectEntity.tsx +81 -0
  105. package/src/features/Conversation/Messages/Assistant/Tool/Render/Arguments/ValueCell.tsx +43 -0
  106. package/src/features/Conversation/Messages/Assistant/Tool/Render/Arguments/index.tsx +120 -0
  107. package/src/features/Conversation/Messages/Assistant/Tool/Render/CustomRender.tsx +75 -2
  108. package/src/features/Conversation/Messages/Assistant/Tool/Render/KeyValueEditor.tsx +214 -0
  109. package/src/features/User/UserPanel/useMenu.tsx +8 -1
  110. package/src/libs/agent-runtime/google/index.ts +3 -0
  111. package/src/libs/trpc/client/desktop.ts +14 -0
  112. package/src/locales/default/common.ts +2 -0
  113. package/src/locales/default/electron.ts +34 -0
  114. package/src/locales/default/index.ts +2 -0
  115. package/src/locales/default/tool.ts +25 -0
  116. package/src/server/routers/desktop/index.ts +9 -0
  117. package/src/server/routers/desktop/pgTable.ts +43 -0
  118. package/src/services/electron/autoUpdate.ts +17 -0
  119. package/src/services/electron/file.ts +31 -0
  120. package/src/services/electron/localFileService.ts +39 -0
  121. package/src/services/electron/remoteServer.ts +40 -0
  122. package/src/store/chat/index.ts +1 -1
  123. package/src/store/chat/slices/builtinTool/actions/index.ts +3 -1
  124. package/src/store/chat/slices/builtinTool/actions/localFile.ts +129 -0
  125. package/src/store/chat/slices/builtinTool/initialState.ts +2 -0
  126. package/src/store/chat/slices/builtinTool/selectors.ts +2 -0
  127. package/src/store/chat/slices/plugin/action.ts +3 -3
  128. package/src/store/chat/store.ts +2 -0
  129. package/src/store/electron/actions/sync.ts +117 -0
  130. package/src/store/electron/index.ts +1 -0
  131. package/src/store/electron/initialState.ts +18 -0
  132. package/src/store/electron/selectors/index.ts +1 -0
  133. package/src/store/electron/selectors/sync.ts +9 -0
  134. package/src/store/electron/store.ts +29 -0
  135. package/src/tools/index.ts +8 -0
  136. package/src/tools/local-files/Render/ListFiles/Result.tsx +42 -0
  137. package/src/tools/local-files/Render/ListFiles/index.tsx +68 -0
  138. package/src/tools/local-files/Render/ReadLocalFile/ReadFileSkeleton.tsx +50 -0
  139. package/src/tools/local-files/Render/ReadLocalFile/ReadFileView.tsx +197 -0
  140. package/src/tools/local-files/Render/ReadLocalFile/index.tsx +31 -0
  141. package/src/tools/local-files/Render/ReadLocalFile/style.ts +37 -0
  142. package/src/tools/local-files/Render/SearchFiles/Result.tsx +42 -0
  143. package/src/tools/local-files/Render/SearchFiles/SearchQuery/SearchView.tsx +77 -0
  144. package/src/tools/local-files/Render/SearchFiles/SearchQuery/index.tsx +72 -0
  145. package/src/tools/local-files/Render/SearchFiles/index.tsx +32 -0
  146. package/src/tools/local-files/Render/index.tsx +36 -0
  147. package/src/tools/local-files/components/FileItem.tsx +117 -0
  148. package/src/tools/local-files/index.ts +149 -0
  149. package/src/tools/local-files/systemRole.ts +46 -0
  150. package/src/tools/local-files/type.ts +33 -0
  151. package/src/tools/renders.ts +3 -0
  152. package/packages/electron-client-ipc/src/events/search.ts +0 -4
  153. package/src/features/Conversation/Messages/Assistant/Tool/Render/Arguments.tsx +0 -165
  154. /package/packages/electron-client-ipc/src/types/{file.ts → upload.ts} +0 -0
@@ -101,6 +101,29 @@ const githubChatModels: AIChatModelCard[] = [
101
101
  releasedAt: '2025-04-14',
102
102
  type: 'chat',
103
103
  },
104
+ {
105
+ abilities: {
106
+ functionCall: true,
107
+ reasoning: true,
108
+ },
109
+ contextWindowTokens: 200_000,
110
+ displayName: 'OpenAI o4-mini',
111
+ id: 'o4-mini',
112
+ maxOutput: 100_000,
113
+ type: 'chat',
114
+ },
115
+ {
116
+ abilities: {
117
+ functionCall: true,
118
+ reasoning: true,
119
+ },
120
+ contextWindowTokens: 200_000,
121
+ displayName: 'OpenAI o3',
122
+ enabled: true,
123
+ id: 'o3',
124
+ maxOutput: 100_000,
125
+ type: 'chat',
126
+ },
104
127
  {
105
128
  abilities: {
106
129
  functionCall: true,
@@ -174,6 +197,39 @@ const githubChatModels: AIChatModelCard[] = [
174
197
  releasedAt: '2024-09-12',
175
198
  type: 'chat',
176
199
  },
200
+ {
201
+ abilities: {
202
+ functionCall: true,
203
+ vision: true,
204
+ },
205
+ contextWindowTokens: 1_074_176,
206
+ displayName: 'OpenAI GPT-4.1',
207
+ id: 'gpt-4.1',
208
+ maxOutput: 33_792,
209
+ type: 'chat',
210
+ },
211
+ {
212
+ abilities: {
213
+ functionCall: true,
214
+ vision: true,
215
+ },
216
+ contextWindowTokens: 1_074_176,
217
+ displayName: 'OpenAI GPT-4.1 mini',
218
+ id: 'gpt-4.1-mini',
219
+ maxOutput: 33_792,
220
+ type: 'chat',
221
+ },
222
+ {
223
+ abilities: {
224
+ functionCall: true,
225
+ vision: true,
226
+ },
227
+ contextWindowTokens: 1_074_176,
228
+ displayName: 'OpenAI GPT-4.1 nano',
229
+ id: 'gpt-4.1-nano',
230
+ maxOutput: 33_792,
231
+ type: 'chat',
232
+ },
177
233
  {
178
234
  abilities: {
179
235
  functionCall: true,
@@ -198,6 +254,16 @@ const githubChatModels: AIChatModelCard[] = [
198
254
  maxOutput: 16_384,
199
255
  type: 'chat',
200
256
  },
257
+ {
258
+ abilities: {
259
+ reasoning: true,
260
+ },
261
+ contextWindowTokens: 128_000,
262
+ displayName: 'MAI DS R1',
263
+ id: 'MAI-DS-R1',
264
+ maxOutput: 4096,
265
+ type: 'chat',
266
+ },
201
267
  {
202
268
  abilities: {
203
269
  reasoning: true,
@@ -208,6 +274,16 @@ const githubChatModels: AIChatModelCard[] = [
208
274
  maxOutput: 4096,
209
275
  type: 'chat',
210
276
  },
277
+ {
278
+ abilities: {
279
+ functionCall: true,
280
+ },
281
+ contextWindowTokens: 128_000,
282
+ displayName: 'DeepSeek V3',
283
+ id: 'DeepSeek-V3-0324',
284
+ maxOutput: 4096,
285
+ type: 'chat',
286
+ },
211
287
  {
212
288
  abilities: {
213
289
  functionCall: true,
@@ -315,6 +391,20 @@ const githubChatModels: AIChatModelCard[] = [
315
391
  id: 'llama-3.3-70b-instruct',
316
392
  type: 'chat',
317
393
  },
394
+ {
395
+ contextWindowTokens: 10_240_000,
396
+ displayName: 'Meta Llama 4 Scout 17B',
397
+ id: 'llama-4-Scout-17B-16E-Instruct',
398
+ maxOutput: 4096,
399
+ type: 'chat',
400
+ },
401
+ {
402
+ contextWindowTokens: 10_240_000,
403
+ displayName: 'Meta Llama 4 Maverick 17B',
404
+ id: 'llama-4-Maverick-17B-128E-Instruct-FP8',
405
+ maxOutput: 4096,
406
+ type: 'chat',
407
+ },
318
408
  {
319
409
  contextWindowTokens: 131_072,
320
410
  description:
@@ -1,6 +1,31 @@
1
1
  import { AIChatModelCard } from '@/types/aiModel';
2
2
 
3
3
  const googleChatModels: AIChatModelCard[] = [
4
+ {
5
+ abilities: {
6
+ functionCall: true,
7
+ reasoning: true,
8
+ search: true,
9
+ vision: true,
10
+ },
11
+ contextWindowTokens: 1_048_576 + 65_536,
12
+ description:
13
+ 'Gemini 2.5 Flash Preview 是 Google 性价比最高的模型,提供全面的功能。',
14
+ displayName: 'Gemini 2.5 Flash Preview 04-17',
15
+ enabled: true,
16
+ id: 'gemini-2.5-flash-preview-04-17',
17
+ maxOutput: 65_536,
18
+ pricing: {
19
+ input: 0.15,
20
+ output: 3.5, // Thinking
21
+ },
22
+ releasedAt: '2025-04-17',
23
+ settings: {
24
+ searchImpl: 'params',
25
+ searchProvider: 'google',
26
+ },
27
+ type: 'chat',
28
+ },
4
29
  {
5
30
  abilities: {
6
31
  functionCall: true,
@@ -0,0 +1,81 @@
1
+ import { createStyles } from 'antd-style';
2
+ import { memo } from 'react';
3
+
4
+ import { useIsMobile } from '@/hooks/useIsMobile';
5
+ import { shinyTextStylish } from '@/styles/loading';
6
+
7
+ import ValueCell from './ValueCell';
8
+
9
+ const useStyles = createStyles(({ css, token }) => ({
10
+ arrayRow: css`
11
+ &:not(:first-child) {
12
+ border-block-start: 1px dotted ${token.colorBorderSecondary};
13
+ }
14
+ `,
15
+ colon: css`
16
+ color: ${token.colorTextTertiary};
17
+ `,
18
+ key: css`
19
+ color: ${token.colorTextTertiary};
20
+ `,
21
+ row: css`
22
+ display: flex;
23
+ align-items: baseline;
24
+
25
+ &:not(:first-child) {
26
+ border-block-start: 1px dotted ${token.colorBorderSecondary};
27
+ }
28
+ `,
29
+ shineText: shinyTextStylish(token),
30
+ value: css`
31
+ color: ${token.colorTextSecondary};
32
+ `,
33
+ }));
34
+
35
+ const formatValue = (value: any): string | string[] => {
36
+ if (Array.isArray(value)) {
37
+ return value.map((v) => (typeof v === 'object' ? JSON.stringify(v) : v));
38
+ }
39
+
40
+ if (typeof value === 'object' && value !== null) {
41
+ return Object.entries(value)
42
+ .map(([k, v]) => `${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`)
43
+ .join(', ');
44
+ }
45
+ return String(value);
46
+ };
47
+
48
+ interface ObjectEntityProps {
49
+ editable?: boolean;
50
+ hasMinWidth: boolean;
51
+ objectKey: string;
52
+ shine?: boolean;
53
+ value: any;
54
+ }
55
+
56
+ const ObjectEntity = memo<ObjectEntityProps>(({ hasMinWidth, shine, value, objectKey }) => {
57
+ const { styles, cx } = useStyles();
58
+ const isMobile = useIsMobile();
59
+ const formatedValue = formatValue(value);
60
+
61
+ return (
62
+ <div className={styles.row}>
63
+ <span
64
+ className={styles.key}
65
+ style={{ minWidth: hasMinWidth ? (isMobile ? 60 : 140) : undefined }}
66
+ >
67
+ {objectKey}
68
+ </span>
69
+ <span className={styles.colon}>:</span>
70
+ <div className={cx(shine ? styles.shineText : styles.value)} style={{ width: '100%' }}>
71
+ {typeof formatedValue === 'string' ? (
72
+ <ValueCell value={formatedValue} />
73
+ ) : (
74
+ formatedValue.map((v, i) => <ValueCell key={i + v} value={v} />)
75
+ )}
76
+ </div>
77
+ </div>
78
+ );
79
+ });
80
+
81
+ export default ObjectEntity;
@@ -0,0 +1,43 @@
1
+ import { copyToClipboard } from '@lobehub/ui';
2
+ import { App } from 'antd';
3
+ import { createStyles } from 'antd-style';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ const useStyles = createStyles(({ css, token }) => ({
8
+ copyable: css`
9
+ cursor: pointer;
10
+ width: 100%;
11
+ margin-block: 2px;
12
+ padding: 4px;
13
+
14
+ &:hover {
15
+ border-radius: 6px;
16
+ background: ${token.colorFillTertiary};
17
+ }
18
+ `,
19
+ }));
20
+
21
+ interface ValueCellProps {
22
+ value: string;
23
+ }
24
+
25
+ const ValueCell = memo<ValueCellProps>(({ value }) => {
26
+ const { message } = App.useApp();
27
+ const { t } = useTranslation('common');
28
+ const { styles } = useStyles();
29
+
30
+ return (
31
+ <div
32
+ className={styles.copyable}
33
+ onClick={async () => {
34
+ await copyToClipboard(value);
35
+ message.success(t('copySuccess'));
36
+ }}
37
+ >
38
+ {value}
39
+ </div>
40
+ );
41
+ });
42
+
43
+ export default ValueCell;
@@ -0,0 +1,120 @@
1
+ import { Highlighter } from '@lobehub/ui';
2
+ import { createStyles } from 'antd-style';
3
+ import { parse } from 'partial-json';
4
+ import { ReactNode, memo, useMemo } from 'react';
5
+ import { Flexbox } from 'react-layout-kit';
6
+
7
+ import { useYamlArguments } from '@/hooks/useYamlArguments';
8
+
9
+ import ObjectEntity from './ObjectEntity';
10
+
11
+ const useStyles = createStyles(({ css, token, cx }) => ({
12
+ button: css`
13
+ color: ${token.colorTextSecondary};
14
+
15
+ &:hover {
16
+ color: ${token.colorText};
17
+ }
18
+ `,
19
+ container: css`
20
+ position: relative;
21
+
22
+ padding-block: 4px;
23
+ padding-inline: 12px 64px;
24
+ border-radius: ${token.borderRadiusLG}px;
25
+
26
+ font-family: ${token.fontFamilyCode};
27
+ font-size: 13px;
28
+ line-height: 1.5;
29
+
30
+ background: ${token.colorFillQuaternary};
31
+
32
+ pre {
33
+ margin: 0 !important;
34
+ background: none !important;
35
+ }
36
+
37
+ &:hover {
38
+ .actions {
39
+ opacity: 1;
40
+ }
41
+ }
42
+ `,
43
+ editButton: cx(
44
+ 'actions',
45
+ css`
46
+ position: absolute;
47
+ z-index: 10;
48
+ inset-block-start: 4px;
49
+ inset-inline-end: 4px;
50
+
51
+ opacity: 0;
52
+
53
+ transition: opacity 0.2s ${token.motionEaseInOut};
54
+ `,
55
+ ),
56
+ }));
57
+
58
+ export interface ArgumentsProps {
59
+ actions?: ReactNode;
60
+ arguments?: string;
61
+ shine?: boolean;
62
+ }
63
+
64
+ const Arguments = memo<ArgumentsProps>(({ arguments: args = '', shine, actions }) => {
65
+ const { styles } = useStyles();
66
+
67
+ const displayArgs = useMemo(() => {
68
+ try {
69
+ const obj = parse(args);
70
+ if (Object.keys(obj).length === 0) return {};
71
+ return obj;
72
+ } catch {
73
+ return args;
74
+ }
75
+ }, [args]);
76
+
77
+ const yaml = useYamlArguments(args);
78
+
79
+ const showActions = !!actions;
80
+
81
+ if (typeof displayArgs === 'string') {
82
+ return (
83
+ !!yaml && (
84
+ <div className={styles.container}>
85
+ <Highlighter language={'yaml'} showLanguage={false}>
86
+ {yaml}
87
+ </Highlighter>
88
+ </div>
89
+ )
90
+ );
91
+ }
92
+
93
+ const hasMinWidth = Object.keys(displayArgs).length > 1;
94
+
95
+ if (Object.keys(displayArgs).length === 0) return null;
96
+
97
+ return (
98
+ <div className={styles.container}>
99
+ {showActions && (
100
+ <Flexbox className={styles.editButton} gap={4} horizontal>
101
+ {actions}
102
+ </Flexbox>
103
+ )}
104
+ {Object.entries(displayArgs).map(([key, value]) => {
105
+ return (
106
+ <ObjectEntity
107
+ editable={false}
108
+ hasMinWidth={hasMinWidth}
109
+ key={key}
110
+ objectKey={key}
111
+ shine={shine}
112
+ value={value}
113
+ />
114
+ );
115
+ })}
116
+ </div>
117
+ );
118
+ });
119
+
120
+ export default Arguments;
@@ -1,4 +1,9 @@
1
- import { memo, useEffect } from 'react';
1
+ import { ActionIcon } from '@lobehub/ui';
2
+ import { App } from 'antd';
3
+ import { Edit3Icon, PlayCircleIcon } from 'lucide-react';
4
+ import { parse } from 'partial-json';
5
+ import { memo, useCallback, useEffect, useState } from 'react';
6
+ import { useTranslation } from 'react-i18next';
2
7
  import { Flexbox } from 'react-layout-kit';
3
8
 
4
9
  import PluginRender from '@/features/PluginsUI/Render';
@@ -7,6 +12,16 @@ import { chatSelectors } from '@/store/chat/selectors';
7
12
  import { ChatMessage } from '@/types/message';
8
13
 
9
14
  import Arguments from './Arguments';
15
+ import KeyValueEditor from './KeyValueEditor';
16
+
17
+ const safeParseJson = (str: string): Record<string, any> => {
18
+ try {
19
+ const obj = parse(str);
20
+ return typeof obj === 'object' && obj !== null ? obj : {};
21
+ } catch {
22
+ return {};
23
+ }
24
+ };
10
25
 
11
26
  interface CustomRenderProps extends ChatMessage {
12
27
  requestArgs?: string;
@@ -25,7 +40,37 @@ const CustomRender = memo<CustomRenderProps>(
25
40
  setShowPluginRender,
26
41
  pluginError,
27
42
  }) => {
43
+ const { t } = useTranslation(['tool', 'common']);
28
44
  const [loading] = useChatStore((s) => [chatSelectors.isPluginApiInvoking(id)(s)]);
45
+ const [isEditing, setIsEditing] = useState(false);
46
+ const { message } = App.useApp();
47
+ const [updatePluginArguments, reInvokeToolMessage] = useChatStore((s) => [
48
+ s.updatePluginArguments,
49
+ s.reInvokeToolMessage,
50
+ ]);
51
+ const handleCancel = useCallback(() => {
52
+ setIsEditing(false);
53
+ }, []);
54
+
55
+ const handleFinish = useCallback(
56
+ async (editedObject: Record<string, any>) => {
57
+ if (!id) return;
58
+
59
+ try {
60
+ const newArgsString = JSON.stringify(editedObject, null, 2);
61
+
62
+ if (newArgsString !== requestArgs) {
63
+ await updatePluginArguments(id, editedObject, true);
64
+ await reInvokeToolMessage(id);
65
+ }
66
+ setIsEditing(false);
67
+ } catch (error) {
68
+ console.error('Error stringifying arguments:', error);
69
+ message.error(t('updateArgs.stringifyError'));
70
+ }
71
+ },
72
+ [requestArgs, id],
73
+ );
29
74
 
30
75
  useEffect(() => {
31
76
  if (!plugin?.type || loading) return;
@@ -49,8 +94,36 @@ const CustomRender = memo<CustomRenderProps>(
49
94
  pluginState={pluginState}
50
95
  type={plugin?.type}
51
96
  />
97
+ ) : isEditing ? (
98
+ <KeyValueEditor
99
+ initialValue={safeParseJson(requestArgs || '')}
100
+ onCancel={handleCancel}
101
+ onFinish={handleFinish}
102
+ />
52
103
  ) : (
53
- <Arguments arguments={requestArgs} />
104
+ <Arguments
105
+ actions={
106
+ <>
107
+ <ActionIcon
108
+ icon={Edit3Icon}
109
+ onClick={() => {
110
+ setIsEditing(true);
111
+ }}
112
+ size={'small'}
113
+ title={t('edit', { ns: 'common' })}
114
+ />
115
+ <ActionIcon
116
+ icon={PlayCircleIcon}
117
+ onClick={async () => {
118
+ await reInvokeToolMessage(id);
119
+ }}
120
+ size={'small'}
121
+ title={t('run', { ns: 'common' })}
122
+ />
123
+ </>
124
+ }
125
+ arguments={requestArgs}
126
+ />
54
127
  )}
55
128
  </Flexbox>
56
129
  );