@lobehub/chat 1.53.3 → 1.53.5
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/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/src/database/repositories/aiInfra/index.ts +16 -5
- package/src/features/Conversation/components/ChatItem/index.tsx +3 -3
- package/src/features/Conversation/components/MarkdownElements/Thinking/index.ts +1 -1
- package/src/features/Conversation/components/MarkdownElements/{Thinking/remarkPlugin.ts → remarkPlugins/createRemarkCustomTagPlugin.ts} +3 -12
- package/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.test.ts +396 -0
- package/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.ts +55 -0
- package/src/features/DevPanel/SystemInspector/AiProviderRuntimeConfig.tsx +11 -0
- package/src/features/DevPanel/SystemInspector/JsonViewer.tsx +17 -0
- package/src/features/DevPanel/SystemInspector/ServerConfig.tsx +11 -0
- package/src/features/DevPanel/SystemInspector/index.tsx +42 -0
- package/src/features/DevPanel/features/FloatPanel.tsx +7 -25
- package/src/features/DevPanel/index.tsx +7 -1
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,56 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.53.5](https://github.com/lobehub/lobe-chat/compare/v1.53.4...v1.53.5)
|
6
|
+
|
7
|
+
<sup>Released on **2025-02-13**</sup>
|
8
|
+
|
9
|
+
#### 🐛 Bug Fixes
|
10
|
+
|
11
|
+
- **misc**: Fix latex in thinking tag render.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### What's fixed
|
19
|
+
|
20
|
+
- **misc**: Fix latex in thinking tag render, closes [#6063](https://github.com/lobehub/lobe-chat/issues/6063) ([7e89b2d](https://github.com/lobehub/lobe-chat/commit/7e89b2d))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
30
|
+
### [Version 1.53.4](https://github.com/lobehub/lobe-chat/compare/v1.53.3...v1.53.4)
|
31
|
+
|
32
|
+
<sup>Released on **2025-02-12**</sup>
|
33
|
+
|
34
|
+
#### 🐛 Bug Fixes
|
35
|
+
|
36
|
+
- **misc**: Fix ai model abilities issue.
|
37
|
+
|
38
|
+
<br/>
|
39
|
+
|
40
|
+
<details>
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
42
|
+
|
43
|
+
#### What's fixed
|
44
|
+
|
45
|
+
- **misc**: Fix ai model abilities issue, closes [#6060](https://github.com/lobehub/lobe-chat/issues/6060) ([718f477](https://github.com/lobehub/lobe-chat/commit/718f477))
|
46
|
+
|
47
|
+
</details>
|
48
|
+
|
49
|
+
<div align="right">
|
50
|
+
|
51
|
+
[](#readme-top)
|
52
|
+
|
53
|
+
</div>
|
54
|
+
|
5
55
|
### [Version 1.53.3](https://github.com/lobehub/lobe-chat/compare/v1.53.2...v1.53.3)
|
6
56
|
|
7
57
|
<sup>Released on **2025-02-12**</sup>
|
package/changelog/v1.json
CHANGED
@@ -1,4 +1,22 @@
|
|
1
1
|
[
|
2
|
+
{
|
3
|
+
"children": {
|
4
|
+
"fixes": [
|
5
|
+
"Fix latex in thinking tag render."
|
6
|
+
]
|
7
|
+
},
|
8
|
+
"date": "2025-02-13",
|
9
|
+
"version": "1.53.5"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"children": {
|
13
|
+
"fixes": [
|
14
|
+
"Fix ai model abilities issue."
|
15
|
+
]
|
16
|
+
},
|
17
|
+
"date": "2025-02-12",
|
18
|
+
"version": "1.53.4"
|
19
|
+
},
|
2
20
|
{
|
3
21
|
"children": {
|
4
22
|
"fixes": [
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.53.
|
3
|
+
"version": "1.53.5",
|
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",
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { isEmpty } from 'lodash-es';
|
1
2
|
import pMap from 'p-map';
|
2
3
|
|
3
4
|
import { DEFAULT_MODEL_PROVIDER_LIST } from '@/config/modelProviders';
|
@@ -88,15 +89,25 @@ export class AiInfraRepos {
|
|
88
89
|
.map<EnabledAiModel & { enabled?: boolean | null }>((item) => {
|
89
90
|
const user = allModels.find((m) => m.id === item.id && m.providerId === provider.id);
|
90
91
|
|
92
|
+
if (!user)
|
93
|
+
return {
|
94
|
+
...item,
|
95
|
+
abilities: item.abilities || {},
|
96
|
+
providerId: provider.id,
|
97
|
+
};
|
98
|
+
|
91
99
|
return {
|
92
|
-
abilities:
|
93
|
-
config:
|
94
|
-
contextWindowTokens:
|
100
|
+
abilities: !isEmpty(user.abilities) ? user.abilities : item.abilities || {},
|
101
|
+
config: !isEmpty(user.config) ? user.config : item.config,
|
102
|
+
contextWindowTokens:
|
103
|
+
typeof user.contextWindowTokens === 'number'
|
104
|
+
? user.contextWindowTokens
|
105
|
+
: item.contextWindowTokens,
|
95
106
|
displayName: user?.displayName || item.displayName,
|
96
|
-
enabled:
|
107
|
+
enabled: user.enabled || item.enabled,
|
97
108
|
id: item.id,
|
98
109
|
providerId: provider.id,
|
99
|
-
sort:
|
110
|
+
sort: user.sort || undefined,
|
100
111
|
type: item.type,
|
101
112
|
};
|
102
113
|
})
|
@@ -174,10 +174,10 @@ const Item = memo<ChatListItemProps>(
|
|
174
174
|
() => ({
|
175
175
|
components,
|
176
176
|
customRender: markdownCustomRender,
|
177
|
-
rehypePlugins,
|
178
|
-
remarkPlugins,
|
177
|
+
rehypePlugins: item?.role === 'user' ? undefined : rehypePlugins,
|
178
|
+
remarkPlugins: item?.role === 'user' ? undefined : remarkPlugins,
|
179
179
|
}),
|
180
|
-
[components, markdownCustomRender],
|
180
|
+
[components, markdownCustomRender, item?.role],
|
181
181
|
);
|
182
182
|
|
183
183
|
const onChange = useCallback((value: string) => updateMessageContent(id, value), [id]);
|
@@ -1,6 +1,6 @@
|
|
1
|
+
import { createRemarkCustomTagPlugin } from '../remarkPlugins/createRemarkCustomTagPlugin';
|
1
2
|
import { MarkdownElement } from '../type';
|
2
3
|
import Component from './Render';
|
3
|
-
import { createRemarkCustomTagPlugin } from './remarkPlugin';
|
4
4
|
|
5
5
|
const ThinkingElement: MarkdownElement = {
|
6
6
|
Component,
|
@@ -1,6 +1,7 @@
|
|
1
|
-
import { toMarkdown } from 'mdast-util-to-markdown';
|
2
1
|
import { SKIP, visit } from 'unist-util-visit';
|
3
2
|
|
3
|
+
import { treeNodeToString } from './getNodeContent';
|
4
|
+
|
4
5
|
export const createRemarkCustomTagPlugin = (tag: string) => () => {
|
5
6
|
return (tree: any) => {
|
6
7
|
visit(tree, 'html', (node, index, parent) => {
|
@@ -31,17 +32,7 @@ export const createRemarkCustomTagPlugin = (tag: string) => () => {
|
|
31
32
|
);
|
32
33
|
|
33
34
|
// 转换为 Markdown 字符串
|
34
|
-
const content = contentNodes
|
35
|
-
.map((n: any) => {
|
36
|
-
// fix https://github.com/lobehub/lobe-chat/issues/5668
|
37
|
-
if (n.type === 'paragraph') {
|
38
|
-
return n.children.map((child: any) => child.value).join('');
|
39
|
-
}
|
40
|
-
|
41
|
-
return toMarkdown(n);
|
42
|
-
})
|
43
|
-
.join('\n\n')
|
44
|
-
.trim();
|
35
|
+
const content = treeNodeToString(contentNodes);
|
45
36
|
|
46
37
|
// 创建自定义节点
|
47
38
|
const customNode = {
|
package/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.test.ts
ADDED
@@ -0,0 +1,396 @@
|
|
1
|
+
import { toMarkdown } from 'mdast-util-to-markdown';
|
2
|
+
import { Parent } from 'unist';
|
3
|
+
import { expect } from 'vitest';
|
4
|
+
|
5
|
+
import { treeNodeToString } from '@/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent';
|
6
|
+
|
7
|
+
describe('treeNodeToString', () => {
|
8
|
+
it('with latex', () => {
|
9
|
+
const nodes = [
|
10
|
+
{
|
11
|
+
type: 'paragraph',
|
12
|
+
children: [
|
13
|
+
{
|
14
|
+
type: 'text',
|
15
|
+
value: '设正向数列 ',
|
16
|
+
position: {
|
17
|
+
start: {
|
18
|
+
line: 3,
|
19
|
+
column: 1,
|
20
|
+
offset: 9,
|
21
|
+
},
|
22
|
+
end: {
|
23
|
+
line: 3,
|
24
|
+
column: 7,
|
25
|
+
offset: 15,
|
26
|
+
},
|
27
|
+
},
|
28
|
+
},
|
29
|
+
{
|
30
|
+
type: 'inlineMath',
|
31
|
+
value: '{ a_n }',
|
32
|
+
data: {
|
33
|
+
hName: 'code',
|
34
|
+
hProperties: {
|
35
|
+
className: ['language-math', 'math-inline'],
|
36
|
+
},
|
37
|
+
hChildren: [
|
38
|
+
{
|
39
|
+
type: 'text',
|
40
|
+
value: '{ a_n }',
|
41
|
+
},
|
42
|
+
],
|
43
|
+
},
|
44
|
+
position: {
|
45
|
+
start: {
|
46
|
+
line: 3,
|
47
|
+
column: 7,
|
48
|
+
offset: 15,
|
49
|
+
},
|
50
|
+
end: {
|
51
|
+
line: 3,
|
52
|
+
column: 18,
|
53
|
+
offset: 26,
|
54
|
+
},
|
55
|
+
},
|
56
|
+
},
|
57
|
+
{
|
58
|
+
type: 'text',
|
59
|
+
value: ' 的首项为 ',
|
60
|
+
position: {
|
61
|
+
start: {
|
62
|
+
line: 3,
|
63
|
+
column: 18,
|
64
|
+
offset: 26,
|
65
|
+
},
|
66
|
+
end: {
|
67
|
+
line: 3,
|
68
|
+
column: 24,
|
69
|
+
offset: 32,
|
70
|
+
},
|
71
|
+
},
|
72
|
+
},
|
73
|
+
{
|
74
|
+
type: 'inlineMath',
|
75
|
+
value: '4',
|
76
|
+
data: {
|
77
|
+
hName: 'code',
|
78
|
+
hProperties: {
|
79
|
+
className: ['language-math', 'math-inline'],
|
80
|
+
},
|
81
|
+
hChildren: [
|
82
|
+
{
|
83
|
+
type: 'text',
|
84
|
+
value: '4',
|
85
|
+
},
|
86
|
+
],
|
87
|
+
},
|
88
|
+
position: {
|
89
|
+
start: {
|
90
|
+
line: 3,
|
91
|
+
column: 24,
|
92
|
+
offset: 32,
|
93
|
+
},
|
94
|
+
end: {
|
95
|
+
line: 3,
|
96
|
+
column: 29,
|
97
|
+
offset: 37,
|
98
|
+
},
|
99
|
+
},
|
100
|
+
},
|
101
|
+
{
|
102
|
+
type: 'text',
|
103
|
+
value: ' ,满足 ',
|
104
|
+
position: {
|
105
|
+
start: {
|
106
|
+
line: 3,
|
107
|
+
column: 29,
|
108
|
+
offset: 37,
|
109
|
+
},
|
110
|
+
end: {
|
111
|
+
line: 3,
|
112
|
+
column: 34,
|
113
|
+
offset: 42,
|
114
|
+
},
|
115
|
+
},
|
116
|
+
},
|
117
|
+
{
|
118
|
+
type: 'inlineMath',
|
119
|
+
value: 'a^2_n = a_{n+1} + 3na_n - 3',
|
120
|
+
data: {
|
121
|
+
hName: 'code',
|
122
|
+
hProperties: {
|
123
|
+
className: ['language-math', 'math-inline'],
|
124
|
+
},
|
125
|
+
hChildren: [
|
126
|
+
{
|
127
|
+
type: 'text',
|
128
|
+
value: 'a^2_n = a_{n+1} + 3na_n - 3',
|
129
|
+
},
|
130
|
+
],
|
131
|
+
},
|
132
|
+
position: {
|
133
|
+
start: {
|
134
|
+
line: 3,
|
135
|
+
column: 34,
|
136
|
+
offset: 42,
|
137
|
+
},
|
138
|
+
end: {
|
139
|
+
line: 3,
|
140
|
+
column: 65,
|
141
|
+
offset: 73,
|
142
|
+
},
|
143
|
+
},
|
144
|
+
},
|
145
|
+
{
|
146
|
+
type: 'text',
|
147
|
+
value: '.',
|
148
|
+
position: {
|
149
|
+
start: {
|
150
|
+
line: 3,
|
151
|
+
column: 65,
|
152
|
+
offset: 73,
|
153
|
+
},
|
154
|
+
end: {
|
155
|
+
line: 3,
|
156
|
+
column: 66,
|
157
|
+
offset: 74,
|
158
|
+
},
|
159
|
+
},
|
160
|
+
},
|
161
|
+
],
|
162
|
+
position: {
|
163
|
+
start: {
|
164
|
+
line: 3,
|
165
|
+
column: 1,
|
166
|
+
offset: 9,
|
167
|
+
},
|
168
|
+
end: {
|
169
|
+
line: 3,
|
170
|
+
column: 66,
|
171
|
+
offset: 74,
|
172
|
+
},
|
173
|
+
},
|
174
|
+
},
|
175
|
+
{
|
176
|
+
type: 'list',
|
177
|
+
ordered: true,
|
178
|
+
start: 1,
|
179
|
+
spread: false,
|
180
|
+
children: [
|
181
|
+
{
|
182
|
+
type: 'listItem',
|
183
|
+
spread: false,
|
184
|
+
checked: null,
|
185
|
+
children: [
|
186
|
+
{
|
187
|
+
type: 'paragraph',
|
188
|
+
children: [
|
189
|
+
{
|
190
|
+
type: 'text',
|
191
|
+
value: '求 ',
|
192
|
+
position: {
|
193
|
+
start: {
|
194
|
+
line: 5,
|
195
|
+
column: 5,
|
196
|
+
offset: 80,
|
197
|
+
},
|
198
|
+
end: {
|
199
|
+
line: 5,
|
200
|
+
column: 7,
|
201
|
+
offset: 82,
|
202
|
+
},
|
203
|
+
},
|
204
|
+
},
|
205
|
+
{
|
206
|
+
type: 'inlineMath',
|
207
|
+
value: 'a_2',
|
208
|
+
data: {
|
209
|
+
hName: 'code',
|
210
|
+
hProperties: {
|
211
|
+
className: ['language-math', 'math-inline'],
|
212
|
+
},
|
213
|
+
hChildren: [
|
214
|
+
{
|
215
|
+
type: 'text',
|
216
|
+
value: 'a_2',
|
217
|
+
},
|
218
|
+
],
|
219
|
+
},
|
220
|
+
position: {
|
221
|
+
start: {
|
222
|
+
line: 5,
|
223
|
+
column: 7,
|
224
|
+
offset: 82,
|
225
|
+
},
|
226
|
+
end: {
|
227
|
+
line: 5,
|
228
|
+
column: 14,
|
229
|
+
offset: 89,
|
230
|
+
},
|
231
|
+
},
|
232
|
+
},
|
233
|
+
{
|
234
|
+
type: 'text',
|
235
|
+
value: ' 和 ',
|
236
|
+
position: {
|
237
|
+
start: {
|
238
|
+
line: 5,
|
239
|
+
column: 14,
|
240
|
+
offset: 89,
|
241
|
+
},
|
242
|
+
end: {
|
243
|
+
line: 5,
|
244
|
+
column: 17,
|
245
|
+
offset: 92,
|
246
|
+
},
|
247
|
+
},
|
248
|
+
},
|
249
|
+
{
|
250
|
+
type: 'inlineMath',
|
251
|
+
value: 'a_3',
|
252
|
+
data: {
|
253
|
+
hName: 'code',
|
254
|
+
hProperties: {
|
255
|
+
className: ['language-math', 'math-inline'],
|
256
|
+
},
|
257
|
+
hChildren: [
|
258
|
+
{
|
259
|
+
type: 'text',
|
260
|
+
value: 'a_3',
|
261
|
+
},
|
262
|
+
],
|
263
|
+
},
|
264
|
+
position: {
|
265
|
+
start: {
|
266
|
+
line: 5,
|
267
|
+
column: 17,
|
268
|
+
offset: 92,
|
269
|
+
},
|
270
|
+
end: {
|
271
|
+
line: 5,
|
272
|
+
column: 24,
|
273
|
+
offset: 99,
|
274
|
+
},
|
275
|
+
},
|
276
|
+
},
|
277
|
+
{
|
278
|
+
type: 'text',
|
279
|
+
value: ',根据前三项的规律猜想该数列的通项公式',
|
280
|
+
position: {
|
281
|
+
start: {
|
282
|
+
line: 5,
|
283
|
+
column: 24,
|
284
|
+
offset: 99,
|
285
|
+
},
|
286
|
+
end: {
|
287
|
+
line: 5,
|
288
|
+
column: 43,
|
289
|
+
offset: 118,
|
290
|
+
},
|
291
|
+
},
|
292
|
+
},
|
293
|
+
],
|
294
|
+
position: {
|
295
|
+
start: {
|
296
|
+
line: 5,
|
297
|
+
column: 5,
|
298
|
+
offset: 80,
|
299
|
+
},
|
300
|
+
end: {
|
301
|
+
line: 5,
|
302
|
+
column: 43,
|
303
|
+
offset: 118,
|
304
|
+
},
|
305
|
+
},
|
306
|
+
},
|
307
|
+
],
|
308
|
+
position: {
|
309
|
+
start: {
|
310
|
+
line: 5,
|
311
|
+
column: 2,
|
312
|
+
offset: 77,
|
313
|
+
},
|
314
|
+
end: {
|
315
|
+
line: 5,
|
316
|
+
column: 43,
|
317
|
+
offset: 118,
|
318
|
+
},
|
319
|
+
},
|
320
|
+
},
|
321
|
+
{
|
322
|
+
type: 'listItem',
|
323
|
+
spread: false,
|
324
|
+
checked: null,
|
325
|
+
children: [
|
326
|
+
{
|
327
|
+
type: 'paragraph',
|
328
|
+
children: [
|
329
|
+
{
|
330
|
+
type: 'text',
|
331
|
+
value: '用数学归纳法证明你的猜想。',
|
332
|
+
position: {
|
333
|
+
start: {
|
334
|
+
line: 6,
|
335
|
+
column: 5,
|
336
|
+
offset: 123,
|
337
|
+
},
|
338
|
+
end: {
|
339
|
+
line: 6,
|
340
|
+
column: 18,
|
341
|
+
offset: 136,
|
342
|
+
},
|
343
|
+
},
|
344
|
+
},
|
345
|
+
],
|
346
|
+
position: {
|
347
|
+
start: {
|
348
|
+
line: 6,
|
349
|
+
column: 5,
|
350
|
+
offset: 123,
|
351
|
+
},
|
352
|
+
end: {
|
353
|
+
line: 6,
|
354
|
+
column: 18,
|
355
|
+
offset: 136,
|
356
|
+
},
|
357
|
+
},
|
358
|
+
},
|
359
|
+
],
|
360
|
+
position: {
|
361
|
+
start: {
|
362
|
+
line: 6,
|
363
|
+
column: 2,
|
364
|
+
offset: 120,
|
365
|
+
},
|
366
|
+
end: {
|
367
|
+
line: 6,
|
368
|
+
column: 18,
|
369
|
+
offset: 136,
|
370
|
+
},
|
371
|
+
},
|
372
|
+
},
|
373
|
+
],
|
374
|
+
position: {
|
375
|
+
start: {
|
376
|
+
line: 5,
|
377
|
+
column: 2,
|
378
|
+
offset: 77,
|
379
|
+
},
|
380
|
+
end: {
|
381
|
+
line: 6,
|
382
|
+
column: 18,
|
383
|
+
offset: 136,
|
384
|
+
},
|
385
|
+
},
|
386
|
+
},
|
387
|
+
];
|
388
|
+
|
389
|
+
const result = treeNodeToString(nodes as Parent[]);
|
390
|
+
|
391
|
+
expect(result).toEqual(`设正向数列 \${ a_n }$ 的首项为 $4$ ,满足 $a^2_n = a_{n+1} + 3na_n - 3$.
|
392
|
+
|
393
|
+
1. 求 $a_2$ 和 $a_3$,根据前三项的规律猜想该数列的通项公式
|
394
|
+
2. 用数学归纳法证明你的猜想。`);
|
395
|
+
});
|
396
|
+
});
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import { toMarkdown } from 'mdast-util-to-markdown';
|
2
|
+
import { Parent } from 'unist';
|
3
|
+
|
4
|
+
const processNode = (node: any): string => {
|
5
|
+
// 处理数学公式节点
|
6
|
+
if (node.type === 'inlineMath') {
|
7
|
+
return `$${node.value}$`;
|
8
|
+
}
|
9
|
+
|
10
|
+
// 处理带有子节点的容器
|
11
|
+
if (node.children) {
|
12
|
+
const content = node.children.map((element: Parent) => processNode(element)).join('');
|
13
|
+
|
14
|
+
// 处理列表的特殊换行逻辑
|
15
|
+
if (node.type === 'list') {
|
16
|
+
return `\n${content}\n`;
|
17
|
+
}
|
18
|
+
|
19
|
+
// 处理列表项的前缀
|
20
|
+
if (node.type === 'listItem') {
|
21
|
+
const prefix = node.checked !== null ? `[${node.checked ? 'x' : ' '}] ` : '';
|
22
|
+
return `${prefix}${content}`;
|
23
|
+
}
|
24
|
+
|
25
|
+
return content;
|
26
|
+
}
|
27
|
+
|
28
|
+
// 处理文本节点
|
29
|
+
if (node.value) {
|
30
|
+
// 保留原始空白字符处理逻辑
|
31
|
+
return node.value.replaceAll(/^\s+|\s+$/g, ' ');
|
32
|
+
}
|
33
|
+
|
34
|
+
// 兜底使用标准转换
|
35
|
+
return toMarkdown(node);
|
36
|
+
};
|
37
|
+
|
38
|
+
export const treeNodeToString = (nodes: Parent[]) => {
|
39
|
+
return nodes
|
40
|
+
.map((node) => {
|
41
|
+
// 处理列表的缩进问题
|
42
|
+
if (node.type === 'list') {
|
43
|
+
return node.children
|
44
|
+
.map((item, index) => {
|
45
|
+
const prefix = (node as any).ordered ? `${(node as any).start + index}. ` : '- ';
|
46
|
+
return `${prefix}${processNode(item)}`;
|
47
|
+
})
|
48
|
+
.join('\n');
|
49
|
+
}
|
50
|
+
|
51
|
+
return processNode(node);
|
52
|
+
})
|
53
|
+
.join('\n\n')
|
54
|
+
.trim();
|
55
|
+
};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { useAiInfraStore } from '@/store/aiInfra';
|
2
|
+
|
3
|
+
import JsonViewer from './JsonViewer';
|
4
|
+
|
5
|
+
const AiProviderRuntimeConfig = () => {
|
6
|
+
const aiProviderRuntimeConfig = useAiInfraStore((s) => s.aiProviderRuntimeConfig);
|
7
|
+
|
8
|
+
return <JsonViewer data={aiProviderRuntimeConfig} />;
|
9
|
+
};
|
10
|
+
|
11
|
+
export default AiProviderRuntimeConfig;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Highlighter } from '@lobehub/ui';
|
2
|
+
import { memo } from 'react';
|
3
|
+
import { Flexbox } from 'react-layout-kit';
|
4
|
+
|
5
|
+
interface JsonViewerProps {
|
6
|
+
data: object;
|
7
|
+
}
|
8
|
+
|
9
|
+
const JsonViewer = memo<JsonViewerProps>(({ data }) => {
|
10
|
+
return (
|
11
|
+
<Flexbox style={{ overflow: 'scroll' }}>
|
12
|
+
<Highlighter language={'json'}>{JSON.stringify(data, null, 2)}</Highlighter>
|
13
|
+
</Flexbox>
|
14
|
+
);
|
15
|
+
});
|
16
|
+
|
17
|
+
export default JsonViewer;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { useServerConfigStore } from '@/store/serverConfig';
|
2
|
+
|
3
|
+
import JsonViewer from './JsonViewer';
|
4
|
+
|
5
|
+
const ServerConfig = () => {
|
6
|
+
const serverConfig = useServerConfigStore((s) => s.serverConfig);
|
7
|
+
|
8
|
+
return <JsonViewer data={serverConfig} />;
|
9
|
+
};
|
10
|
+
|
11
|
+
export default ServerConfig;
|
@@ -0,0 +1,42 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { TabsNav } from '@lobehub/ui';
|
4
|
+
import { useState } from 'react';
|
5
|
+
import { Flexbox } from 'react-layout-kit';
|
6
|
+
|
7
|
+
import AiProviderRuntimeConfig from './AiProviderRuntimeConfig';
|
8
|
+
import ServerConfig from './ServerConfig';
|
9
|
+
|
10
|
+
enum TabKey {
|
11
|
+
AiProviderRuntimeConfig = 'aiProviderRuntimeConfig',
|
12
|
+
ServerConfig = 'serverConfig',
|
13
|
+
}
|
14
|
+
|
15
|
+
const SystemInspector = () => {
|
16
|
+
const [activeTab, setActiveTab] = useState<TabKey>(TabKey.ServerConfig);
|
17
|
+
|
18
|
+
return (
|
19
|
+
<Flexbox gap={4} height={'100%'}>
|
20
|
+
<TabsNav
|
21
|
+
activeKey={activeTab}
|
22
|
+
items={[
|
23
|
+
{
|
24
|
+
key: TabKey.ServerConfig,
|
25
|
+
label: 'Server Config',
|
26
|
+
},
|
27
|
+
{
|
28
|
+
key: TabKey.AiProviderRuntimeConfig,
|
29
|
+
label: 'Ai Provider Runtime Config',
|
30
|
+
},
|
31
|
+
]}
|
32
|
+
onChange={(activeTab) => setActiveTab(activeTab as TabKey)}
|
33
|
+
variant={'compact'}
|
34
|
+
/>
|
35
|
+
|
36
|
+
{activeTab === TabKey.ServerConfig && <ServerConfig />}
|
37
|
+
{activeTab === TabKey.AiProviderRuntimeConfig && <AiProviderRuntimeConfig />}
|
38
|
+
</Flexbox>
|
39
|
+
);
|
40
|
+
};
|
41
|
+
|
42
|
+
export default SystemInspector;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
3
|
import { ActionIcon, FluentEmoji, Icon, SideNav } from '@lobehub/ui';
|
4
|
-
import {
|
4
|
+
import { FloatButton } from 'antd';
|
5
5
|
import { createStyles } from 'antd-style';
|
6
6
|
import { BugIcon, BugOff, XIcon } from 'lucide-react';
|
7
7
|
import { ReactNode, memo, useEffect, useState } from 'react';
|
@@ -81,7 +81,7 @@ interface CollapsibleFloatPanelProps {
|
|
81
81
|
const CollapsibleFloatPanel = memo<CollapsibleFloatPanelProps>(({ items }) => {
|
82
82
|
const { styles, theme } = useStyles();
|
83
83
|
const [tab, setTab] = useState<string>(items[0].key);
|
84
|
-
|
84
|
+
|
85
85
|
const [isExpanded, setIsExpanded] = useState(false);
|
86
86
|
const [position, setPosition] = useState({ x: 100, y: 100 });
|
87
87
|
const [size, setSize] = useState({ height: minHeight, width: minWidth });
|
@@ -108,29 +108,11 @@ const CollapsibleFloatPanel = memo<CollapsibleFloatPanelProps>(({ items }) => {
|
|
108
108
|
|
109
109
|
return (
|
110
110
|
<>
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
icon: (
|
117
|
-
<Icon color={theme.colorTextSecondary} icon={BugOff} size={{ fontSize: 16 }} />
|
118
|
-
),
|
119
|
-
key: 'hide',
|
120
|
-
label: 'Hide Toolbar',
|
121
|
-
onClick: () => setIsHide(true),
|
122
|
-
},
|
123
|
-
],
|
124
|
-
}}
|
125
|
-
trigger={['hover']}
|
126
|
-
>
|
127
|
-
<FloatButton
|
128
|
-
className={styles.floatButton}
|
129
|
-
icon={<Icon icon={isExpanded ? BugOff : BugIcon} />}
|
130
|
-
onClick={() => setIsExpanded(!isExpanded)}
|
131
|
-
/>
|
132
|
-
</Dropdown>
|
133
|
-
)}
|
111
|
+
<FloatButton
|
112
|
+
className={styles.floatButton}
|
113
|
+
icon={<Icon icon={isExpanded ? BugOff : BugIcon} />}
|
114
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
115
|
+
/>
|
134
116
|
{isExpanded && (
|
135
117
|
<Rnd
|
136
118
|
bounds="window"
|
@@ -1,9 +1,10 @@
|
|
1
|
-
import { BookText, DatabaseIcon, FlagIcon, GlobeLockIcon } from 'lucide-react';
|
1
|
+
import { BookText, Cog, DatabaseIcon, FlagIcon, GlobeLockIcon } from 'lucide-react';
|
2
2
|
|
3
3
|
import CacheViewer from './CacheViewer';
|
4
4
|
import FeatureFlagViewer from './FeatureFlagViewer';
|
5
5
|
import MetadataViewer from './MetadataViewer';
|
6
6
|
import PostgresViewer from './PostgresViewer';
|
7
|
+
import SystemInspector from './SystemInspector';
|
7
8
|
import FloatPanel from './features/FloatPanel';
|
8
9
|
|
9
10
|
const DevPanel = () => (
|
@@ -29,6 +30,11 @@ const DevPanel = () => (
|
|
29
30
|
icon: <FlagIcon size={16} />,
|
30
31
|
key: 'Feature Flags',
|
31
32
|
},
|
33
|
+
{
|
34
|
+
children: <SystemInspector />,
|
35
|
+
icon: <Cog size={16} />,
|
36
|
+
key: 'System Status',
|
37
|
+
},
|
32
38
|
]}
|
33
39
|
/>
|
34
40
|
);
|