@yuku123/z-agent-frontend-component 0.1.1

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 (41) hide show
  1. package/README.md +66 -0
  2. package/dist/z-agent-frontend-component.css +1 -0
  3. package/dist/z-agent-frontend-component.es.js +9956 -0
  4. package/dist/z-agent-frontend-component.umd.js +219 -0
  5. package/package.json +77 -0
  6. package/src/api/apiRouter.js +78 -0
  7. package/src/api/index.js +23 -0
  8. package/src/api/request.js +59 -0
  9. package/src/api/routes.js +140 -0
  10. package/src/dev.jsx +80 -0
  11. package/src/index.js +86 -0
  12. package/src/pages/agent/app/index.jsx +2 -0
  13. package/src/pages/agent/editor/AgentAppEditor.jsx +456 -0
  14. package/src/pages/agent/editor/WorkflowEditor.jsx +495 -0
  15. package/src/pages/agent/editor/nodes/index.ts +225 -0
  16. package/src/pages/agent/index.jsx +1379 -0
  17. package/src/pages/agent/share.jsx +512 -0
  18. package/src/pages/ak/AkUsageDrawer.jsx +208 -0
  19. package/src/pages/ak/index.jsx +496 -0
  20. package/src/pages/llm/index.jsx +736 -0
  21. package/src/pages/llm/model/index.jsx +220 -0
  22. package/src/pages/llm/provider/index.jsx +173 -0
  23. package/src/pages/mcp/index.jsx +359 -0
  24. package/src/pages/oss/BucketList.jsx +320 -0
  25. package/src/pages/oss/ObjectBrowser.jsx +409 -0
  26. package/src/pages/product/execute.jsx +608 -0
  27. package/src/pages/product/index.jsx +628 -0
  28. package/src/pages/product/scene.jsx +746 -0
  29. package/src/pages/script/ApiBridgeEditor.jsx +255 -0
  30. package/src/pages/script/CurlImportModal.jsx +263 -0
  31. package/src/pages/script/FieldMappingEditor.jsx +131 -0
  32. package/src/pages/script/OpenApiImportModal.jsx +212 -0
  33. package/src/pages/script/index.jsx +532 -0
  34. package/src/pages/skill/index.jsx +1595 -0
  35. package/src/pages/trace/DebugPlayground.jsx +357 -0
  36. package/src/pages/trace/components/MetricsDashboard.jsx +164 -0
  37. package/src/pages/trace/components/RagFragments.jsx +134 -0
  38. package/src/pages/trace/components/Timeline.jsx +142 -0
  39. package/src/pages/trace/components/ToolCallTree.jsx +116 -0
  40. package/src/pages/trace/index.jsx +13 -0
  41. package/src/pages/usage/index.jsx +352 -0
@@ -0,0 +1,608 @@
1
+ import {useCallback, useEffect, useRef, useState} from 'react'
2
+ import {
3
+ Avatar,
4
+ Button,
5
+ Card,
6
+ Col,
7
+ Empty,
8
+ Form,
9
+ Input,
10
+ List,
11
+ message,
12
+ Modal,
13
+ Row,
14
+ Select,
15
+ Space,
16
+ Spin,
17
+ Tag,
18
+ Tooltip,
19
+ Typography
20
+ } from 'antd'
21
+ import {
22
+ CheckCircleOutlined,
23
+ ClearOutlined,
24
+ CloseCircleOutlined,
25
+ CopyOutlined,
26
+ HistoryOutlined,
27
+ LoadingOutlined,
28
+ ReloadOutlined,
29
+ RobotOutlined,
30
+ SendOutlined,
31
+ ThunderboltOutlined,
32
+ UserOutlined
33
+ } from '@ant-design/icons'
34
+ import {productApi, sceneApi} from '@/api'
35
+
36
+ const {TextArea} = Input
37
+ const {Text, Title} = Typography
38
+ const {Option} = Select
39
+
40
+ // ===== 用户端场景执行器 =====
41
+ const SceneExecutorPage = () => {
42
+ // 从 URL 参数获取 productCode / sceneCode
43
+ const params = new URLSearchParams(window.location.search)
44
+ const initProductCode = params.get('productCode') || ''
45
+ const initSceneCode = params.get('sceneCode') || ''
46
+
47
+ const [productCode, setProductCode] = useState(initProductCode)
48
+ const [sceneCode, setSceneCode] = useState(initSceneCode)
49
+ const [products, setProducts] = useState([])
50
+ const [scenes, setScenes] = useState([])
51
+ const [messages, setMessages] = useState([])
52
+ const [inputValue, setInputValue] = useState('')
53
+ const [loading, setLoading] = useState(false)
54
+ const [streaming, setStreaming] = useState(false)
55
+ const [currentReply, setCurrentReply] = useState('')
56
+ const [historyOpen, setHistoryOpen] = useState(false)
57
+ const [chatHistory, setChatHistory] = useState([])
58
+ const [configModalVisible, setConfigModalVisible] = useState(false)
59
+ const [form] = Form.useForm()
60
+ const [execConfig, setExecConfig] = useState({temperature: 0.7, maxTokens: 2048, topP: 1})
61
+ const [sceneConfig, setSceneConfig] = useState(null)
62
+
63
+ const messagesEndRef = useRef(null)
64
+ const eventSourceRef = useRef(null)
65
+ const inputRef = useRef(null)
66
+
67
+ // 加载产品列表
68
+ useEffect(() => {
69
+ productApi.page({id: 1, pageSize: 100, status: 'PUBLISHED'}).then(res => {
70
+ setProducts(res.data?.records || [])
71
+ })
72
+ }, [])
73
+
74
+ // 加载场景列表(当产品变化时)
75
+ useEffect(() => {
76
+ if (!productCode) {
77
+ setScenes([]);
78
+ return
79
+ }
80
+ sceneApi.page({id: 1, pageSize: 100, status: 'PUBLISHED', productCode}).then(res => {
81
+ setScenes(res.data?.records || [])
82
+ })
83
+ }, [productCode])
84
+
85
+ // 加载场景配置
86
+ useEffect(() => {
87
+ if (!sceneCode) {
88
+ setSceneConfig(null);
89
+ return
90
+ }
91
+ sceneApi.configGet(sceneCode).then(res => {
92
+ setSceneConfig(res.data)
93
+ }).catch(() => setSceneConfig(null))
94
+ }, [sceneCode])
95
+
96
+ // 加载历史记录
97
+ useEffect(() => {
98
+ if (!sceneCode) return
99
+ sceneApi.chatHistory(sceneCode).then(res => {
100
+ setChatHistory(Array.isArray(res.data) ? res.data : [])
101
+ }).catch(() => setChatHistory([]))
102
+ }, [sceneCode])
103
+
104
+ // 自动滚动
105
+ useEffect(() => {
106
+ messagesEndRef.current?.scrollIntoView({behavior: 'smooth'})
107
+ }, [messages, currentReply])
108
+
109
+ // 自动聚焦输入框
110
+ useEffect(() => {
111
+ inputRef.current?.focus()
112
+ }, [sceneCode])
113
+
114
+ const scrollToBottom = () => {
115
+ messagesEndRef.current?.scrollIntoView({behavior: 'smooth'})
116
+ }
117
+
118
+ const handleSend = useCallback(async () => {
119
+ if (!inputValue.trim() || !sceneCode || loading || streaming) return
120
+ const userMessage = inputValue.trim()
121
+ setInputValue('')
122
+
123
+ // 添加用户消息
124
+ const userMsg = {
125
+ id: Date.now(),
126
+ role: 'user',
127
+ content: userMessage,
128
+ timestamp: new Date().toLocaleTimeString(),
129
+ }
130
+ setMessages(prev => [...prev, userMsg])
131
+ setLoading(true)
132
+ setCurrentReply('')
133
+
134
+ try {
135
+ setStreaming(true)
136
+
137
+ // 使用 EventSource 流式调用
138
+ const userId = localStorage.getItem('userId') || 'anonymous'
139
+ const userName = localStorage.getItem('userName') || '匿名用户'
140
+
141
+ const sse = new EventSource(`/api/scene/execute/stream?sceneCode=${sceneCode}&message=${encodeURIComponent(userMessage)}&userId=${userId}&userName=${encodeURIComponent(userName)}`)
142
+ eventSourceRef.current = sse
143
+
144
+ sse.onmessage = (event) => {
145
+ try {
146
+ const data = JSON.parse(event.data)
147
+ if (data.type === 'chunk') {
148
+ setCurrentReply(prev => prev + data.content)
149
+ } else if (data.type === 'done') {
150
+ // 完成,添加AI消息
151
+ const aiMsg = {
152
+ id: Date.now() + 1,
153
+ role: 'assistant',
154
+ content: currentReply + data.content,
155
+ timestamp: new Date().toLocaleTimeString(),
156
+ }
157
+ setMessages(prev => [...prev, aiMsg])
158
+ setCurrentReply('')
159
+ setStreaming(false)
160
+ sse.close()
161
+ } else if (data.type === 'error') {
162
+ message.error(data.content || '执行出错')
163
+ setCurrentReply('')
164
+ setStreaming(false)
165
+ sse.close()
166
+ }
167
+ } catch (e) {
168
+ // 原始文本
169
+ setCurrentReply(prev => prev + event.data)
170
+ }
171
+ }
172
+
173
+ sse.onerror = async () => {
174
+ // 如果是简单非流式响应,尝试普通调用
175
+ sse.close()
176
+ setStreaming(false)
177
+ setLoading(false)
178
+
179
+ // 降级:普通请求
180
+ try {
181
+ const res = await sceneApi.execute({
182
+ sceneCode,
183
+ message: userMessage,
184
+ userId: userId,
185
+ userName: userName,
186
+ config: execConfig,
187
+ })
188
+ const aiMsg = {
189
+ id: Date.now() + 1,
190
+ role: 'assistant',
191
+ content: res.data?.content || res.data?.reply || JSON.stringify(res.data) || '无响应',
192
+ timestamp: new Date().toLocaleTimeString(),
193
+ }
194
+ setMessages(prev => [...prev, aiMsg])
195
+ } catch (e) {
196
+ const aiMsg = {
197
+ id: Date.now() + 1,
198
+ role: 'assistant',
199
+ content: '抱歉,执行过程中出现错误,请稍后重试。',
200
+ timestamp: new Date().toLocaleTimeString(),
201
+ }
202
+ setMessages(prev => [...prev, aiMsg])
203
+ }
204
+ }
205
+ } catch (e) {
206
+ message.error('执行失败')
207
+ setLoading(false)
208
+ setStreaming(false)
209
+ }
210
+ }, [inputValue, sceneCode, loading, streaming, execConfig, currentReply])
211
+
212
+ const handleKeyPress = (e) => {
213
+ if (e.key === 'Enter' && !e.shiftKey) {
214
+ e.preventDefault()
215
+ handleSend()
216
+ }
217
+ }
218
+
219
+ const handleClear = () => {
220
+ setMessages([])
221
+ message.success('对话已清空')
222
+ }
223
+
224
+ const handleStop = () => {
225
+ eventSourceRef.current?.close()
226
+ if (currentReply) {
227
+ const aiMsg = {
228
+ id: Date.now() + 1,
229
+ role: 'assistant',
230
+ content: currentReply,
231
+ timestamp: new Date().toLocaleTimeString(),
232
+ }
233
+ setMessages(prev => [...prev, aiMsg])
234
+ }
235
+ setCurrentReply('')
236
+ setStreaming(false)
237
+ setLoading(false)
238
+ message.info('已停止生成')
239
+ }
240
+
241
+ const handleCopyMessage = (content) => {
242
+ navigator.clipboard.writeText(content).then(() => message.success('已复制')).catch(() => {
243
+ })
244
+ }
245
+
246
+ const handleLoadHistory = (item) => {
247
+ if (item.messages) {
248
+ setMessages(Array.isArray(item.messages) ? item.messages : [])
249
+ }
250
+ setHistoryOpen(false)
251
+ message.success('已加载历史记录')
252
+ }
253
+
254
+ const renderMessageContent = (content) => {
255
+ // 简单渲染:支持代码块和换行
256
+ return content.split('\n').map((line, i) => {
257
+ if (line.startsWith('```') && line.endsWith('```')) {
258
+ return <pre key={i} style={{
259
+ background: '#f5f5f5',
260
+ padding: 8,
261
+ borderRadius: 6,
262
+ fontSize: 12,
263
+ overflow: 'auto'
264
+ }}>{line.slice(3, -3)}</pre>
265
+ }
266
+ return <div key={i} style={{lineHeight: 1.7}}>{line}</div>
267
+ })
268
+ }
269
+
270
+ return (
271
+ <div style={{display: 'flex', flexDirection: 'column', height: 'calc(100vh - 140px)', padding: 0}}>
272
+ {/* 顶部:场景选择栏 */}
273
+ <div style={{
274
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
275
+ padding: '14px 20px',
276
+ display: 'flex',
277
+ alignItems: 'center',
278
+ gap: 16,
279
+ flexWrap: 'wrap',
280
+ }}>
281
+ <Select
282
+ value={productCode || undefined}
283
+ onChange={v => {
284
+ setProductCode(v);
285
+ setSceneCode('')
286
+ }}
287
+ placeholder="选择产品"
288
+ allowClear
289
+ style={{width: 180, borderRadius: 8}}
290
+ size="large"
291
+ >
292
+ {products.map(p => <Option key={p.productCode} value={p.productCode}>{p.productName}</Option>)}
293
+ </Select>
294
+
295
+ <Select
296
+ value={sceneCode || undefined}
297
+ onChange={v => setSceneCode(v)}
298
+ placeholder="选择场景"
299
+ allowClear
300
+ style={{width: 200, borderRadius: 8}}
301
+ size="large"
302
+ disabled={!productCode}
303
+ >
304
+ {scenes.map(s => <Option key={s.sceneCode} value={s.sceneCode}>{s.sceneName}</Option>)}
305
+ </Select>
306
+
307
+ {sceneCode && (
308
+ <Tag icon={<CheckCircleOutlined/>} color="green" style={{borderRadius: 20}}>
309
+ {scenes.find(s => s.sceneCode === sceneCode)?.sceneName || sceneCode} 已就绪
310
+ </Tag>
311
+ )}
312
+
313
+ <div style={{flex: 1}}/>
314
+
315
+ <Space>
316
+ <Tooltip title="执行配置">
317
+ <Button icon={<ThunderboltOutlined/>} onClick={() => setConfigModalVisible(true)}
318
+ style={{borderRadius: 8}}>
319
+ 参数
320
+ </Button>
321
+ </Tooltip>
322
+ <Tooltip title="历史记录">
323
+ <Button icon={<HistoryOutlined/>} onClick={() => setHistoryOpen(true)}
324
+ style={{borderRadius: 8}}>
325
+ 历史
326
+ </Button>
327
+ </Tooltip>
328
+ <Tooltip title="清空对话">
329
+ <Button icon={<ClearOutlined/>} onClick={handleClear} style={{borderRadius: 8}}>
330
+ 清空
331
+ </Button>
332
+ </Tooltip>
333
+ </Space>
334
+ </div>
335
+
336
+ {/* 中部:消息区域 */}
337
+ <div style={{
338
+ flex: 1,
339
+ overflowY: 'auto',
340
+ padding: '16px 20px',
341
+ background: '#f5f5f5',
342
+ display: 'flex',
343
+ flexDirection: 'column',
344
+ }}>
345
+ {!sceneCode ? (
346
+ <div style={{flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center'}}>
347
+ <Empty
348
+ image={<div style={{fontSize: 48, opacity: 0.3}}><RobotOutlined/></div>}
349
+ description={
350
+ <div>
351
+ <div style={{fontWeight: 500, fontSize: 15, marginBottom: 6}}>请先选择产品与场景
352
+ </div>
353
+ <div style={{color: '#999', fontSize: 13}}>在顶部选择要执行的场景,即可开始体验</div>
354
+ </div>
355
+ }
356
+ style={{padding: 40}}
357
+ />
358
+ </div>
359
+ ) : (
360
+ <>
361
+ {/* 欢迎消息 */}
362
+ {messages.length === 0 && (
363
+ <div style={{textAlign: 'center', padding: '30px 0 20px'}}>
364
+ <Avatar
365
+ size={56}
366
+ icon={<RobotOutlined/>}
367
+ style={{
368
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
369
+ margin: '0 auto'
370
+ }}
371
+ />
372
+ <Title level={5} style={{marginTop: 12, marginBottom: 4}}>
373
+ {scenes.find(s => s.sceneCode === sceneCode)?.sceneName || '场景助手'}
374
+ </Title>
375
+ <Text type="secondary">
376
+ {sceneConfig?.description || scenes.find(s => s.sceneCode === sceneCode)?.description || '开始对话吧!'}
377
+ </Text>
378
+ </div>
379
+ )}
380
+
381
+ {/* 消息列表 */}
382
+ <div style={{display: 'flex', flexDirection: 'column', gap: 16}}>
383
+ {messages.map((msg) => (
384
+ <div key={msg.id} style={{display: 'flex', gap: 12, alignItems: 'flex-start'}}>
385
+ <Avatar
386
+ size={36}
387
+ icon={msg.role === 'user' ? <UserOutlined/> : <RobotOutlined/>}
388
+ style={{
389
+ background: msg.role === 'user' ? '#1890ff' : 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
390
+ flexShrink: 0,
391
+ }}
392
+ />
393
+ <div style={{flex: 1}}>
394
+ <div style={{display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4}}>
395
+ <Text strong
396
+ style={{fontSize: 13}}>{msg.role === 'user' ? '我' : '助手'}</Text>
397
+ <Text type="secondary" style={{fontSize: 11}}>{msg.timestamp}</Text>
398
+ {msg.role === 'assistant' && (
399
+ <Tooltip title="复制回复">
400
+ <Button size="small" type="text" icon={<CopyOutlined/>}
401
+ onClick={() => handleCopyMessage(msg.content)}
402
+ style={{padding: 0}}/>
403
+ </Tooltip>
404
+ )}
405
+ </div>
406
+ <Card
407
+ size="small"
408
+ style={{
409
+ background: msg.role === 'user' ? '#1890ff' : '#fff',
410
+ color: msg.role === 'user' ? '#fff' : '#333',
411
+ borderRadius: 12,
412
+ boxShadow: '0 1px 4px rgba(0,0,0,0.08)',
413
+ }}
414
+ styles={{body: {padding: '10px 14px'}}}
415
+ >
416
+ {renderMessageContent(msg.content)}
417
+ </Card>
418
+ </div>
419
+ </div>
420
+ ))}
421
+
422
+ {/* 流式输出中 */}
423
+ {streaming && currentReply && (
424
+ <div style={{display: 'flex', gap: 12, alignItems: 'flex-start'}}>
425
+ <Avatar
426
+ size={36}
427
+ icon={<RobotOutlined/>}
428
+ style={{
429
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
430
+ flexShrink: 0
431
+ }}
432
+ />
433
+ <div style={{flex: 1}}>
434
+ <Card
435
+ size="small"
436
+ style={{
437
+ background: '#fff',
438
+ borderRadius: 12,
439
+ boxShadow: '0 1px 4px rgba(0,0,0,0.08)'
440
+ }}
441
+ styles={{body: {padding: '10px 14px'}}}
442
+ >
443
+ {renderMessageContent(currentReply)}
444
+ <span style={{
445
+ display: 'inline-block',
446
+ width: 8,
447
+ height: 16,
448
+ background: '#667eea',
449
+ marginLeft: 2,
450
+ animation: 'blink 1s infinite',
451
+ borderRadius: 2
452
+ }}/>
453
+ </Card>
454
+ </div>
455
+ </div>
456
+ )}
457
+
458
+ {/* 加载中 */}
459
+ {loading && !streaming && (
460
+ <div style={{display: 'flex', gap: 12, alignItems: 'flex-start'}}>
461
+ <Avatar
462
+ size={36}
463
+ icon={<RobotOutlined/>}
464
+ style={{
465
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
466
+ flexShrink: 0
467
+ }}
468
+ />
469
+ <Card
470
+ size="small"
471
+ style={{
472
+ background: '#fff',
473
+ borderRadius: 12,
474
+ boxShadow: '0 1px 4px rgba(0,0,0,0.08)'
475
+ }}
476
+ styles={{body: {padding: '10px 14px'}}}
477
+ >
478
+ <Spin indicator={<LoadingOutlined style={{fontSize: 16, color: '#667eea'}}
479
+ spin/>}/>
480
+ <Text type="secondary" style={{marginLeft: 8}}>正在思考...</Text>
481
+ </Card>
482
+ </div>
483
+ )}
484
+ </div>
485
+ <div ref={messagesEndRef}/>
486
+ </>
487
+ )}
488
+ </div>
489
+
490
+ {/* 底部:输入区 */}
491
+ <div style={{
492
+ background: '#fff',
493
+ padding: '12px 20px',
494
+ borderTop: '1px solid #f0f0f0',
495
+ display: 'flex',
496
+ gap: 12,
497
+ alignItems: 'flex-end',
498
+ }}>
499
+ <TextArea
500
+ ref={inputRef}
501
+ value={inputValue}
502
+ onChange={e => setInputValue(e.target.value)}
503
+ onKeyDown={handleKeyPress}
504
+ placeholder={sceneCode ? '输入消息,Enter 发送,Shift+Enter 换行...' : '请先选择场景...'}
505
+ disabled={!sceneCode || streaming}
506
+ autoSize={{minRows: 1, maxRows: 4}}
507
+ style={{flex: 1, borderRadius: 20, resize: 'none'}}
508
+ />
509
+ <div style={{display: 'flex', flexDirection: 'column', gap: 4}}>
510
+ {streaming ? (
511
+ <Tooltip title="停止生成">
512
+ <Button danger icon={<CloseCircleOutlined/>} onClick={handleStop}
513
+ style={{borderRadius: 20}}/>
514
+ </Tooltip>
515
+ ) : (
516
+ <Tooltip title="发送">
517
+ <Button
518
+ type="primary"
519
+ icon={<SendOutlined/>}
520
+ onClick={handleSend}
521
+ disabled={!sceneCode || !inputValue.trim() || loading}
522
+ style={{
523
+ borderRadius: 20,
524
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
525
+ border: 'none'
526
+ }}
527
+ />
528
+ </Tooltip>
529
+ )}
530
+ </div>
531
+ </div>
532
+
533
+ {/* 历史记录 Modal */}
534
+ <Modal
535
+ title={<span><HistoryOutlined style={{marginRight: 8}}/>对话历史</span>}
536
+ open={historyOpen}
537
+ onCancel={() => setHistoryOpen(false)}
538
+ footer={null}
539
+ width={600}
540
+ >
541
+ {chatHistory.length === 0 ? (
542
+ <Empty description="暂无历史记录"/>
543
+ ) : (
544
+ <List
545
+ dataSource={chatHistory}
546
+ renderItem={(item, idx) => (
547
+ <List.Item
548
+ actions={[
549
+ <Button key="load" size="small" icon={<ReloadOutlined/>}
550
+ onClick={() => handleLoadHistory(item)}>加载</Button>
551
+ ]}
552
+ >
553
+ <List.Item.Meta
554
+ avatar={<Avatar icon={<ChatIcon/>} style={{background: '#667eea'}}/>}
555
+ title={`会话 ${idx + 1} — ${item.startTime || ''}`}
556
+ description={<Text type="secondary"
557
+ style={{fontSize: 12}}>{item.messages?.length || 0} 条消息</Text>}
558
+ />
559
+ </List.Item>
560
+ )}
561
+ />
562
+ )}
563
+ </Modal>
564
+
565
+ {/* 执行配置 Modal */}
566
+ <Modal
567
+ title={<span><ThunderboltOutlined style={{marginRight: 8}}/>执行参数配置</span>}
568
+ open={configModalVisible}
569
+ onCancel={() => setConfigModalVisible(false)}
570
+ onOk={() => {
571
+ setConfigModalVisible(false);
572
+ message.success('参数已保存')
573
+ }}
574
+ okText="保存"
575
+ >
576
+ <Form form={form} layout="vertical" initialValues={execConfig}>
577
+ <Row gutter={16}>
578
+ <Col span={12}>
579
+ <Form.Item name="temperature" label="Temperature (随机性)">
580
+ <InputNumber min={0} max={2} step={0.1} style={{width: '100%'}}/>
581
+ </Form.Item>
582
+ </Col>
583
+ <Col span={12}>
584
+ <Form.Item name="maxTokens" label="Max Tokens (最大字数)">
585
+ <InputNumber min={100} max={8192} step={100} style={{width: '100%'}}/>
586
+ </Form.Item>
587
+ </Col>
588
+ </Row>
589
+ <Form.Item name="topP" label="Top P">
590
+ <InputNumber min={0} max={1} step={0.05} style={{width: '100%'}}/>
591
+ </Form.Item>
592
+ </Form>
593
+ </Modal>
594
+
595
+ <style>{`
596
+ @keyframes blink {
597
+ 0%, 100% { opacity: 1; }
598
+ 50% { opacity: 0; }
599
+ }
600
+ `}</style>
601
+ </div>
602
+ )
603
+ }
604
+
605
+ // 小图标组件
606
+ const ChatIcon = () => <RobotOutlined/>
607
+
608
+ export default SceneExecutorPage