Skip to content

Commit dc11cd6

Browse files
committed
feat: UI Tool Debugging
1 parent dde69e1 commit dc11cd6

3 files changed

Lines changed: 41 additions & 50 deletions

File tree

‎ui/src/conversation-panel/common/use-chat-store/shared/use-stream-manager.ts‎

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,10 @@ export function useStreamManager() {
4343
currentStream = new ConversationStream(
4444
response,
4545
onStream,
46-
() => {
47-
currentStream = null
48-
onFinish?.()
49-
},
5046
(e) => {
5147
currentStream = null
52-
onFailure?.(e)
48+
if (e) onFailure?.(e)
49+
else onFinish?.()
5350
},
5451
)
5552
currentStream.start()
@@ -92,13 +89,10 @@ export function useStreamManager() {
9289
currentStream = new ConversationStream(
9390
response,
9491
onStream,
95-
() => {
96-
currentStream = null
97-
onFinish?.()
98-
},
99-
() => {
92+
(e) => {
10093
currentStream = null
101-
onFailure?.()
94+
if (e) onFailure?.()
95+
else onFinish?.()
10296
},
10397
)
10498
currentStream.start()

‎ui/src/conversation-panel/stream.ts‎

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,40 @@
11
export class ConversationStream {
22
private response: any
3-
private onChunk: (chunk: any) => void
4-
private onFinish: () => void
5-
private onError: (e: any) => void
3+
private onNext: (chunk: any) => void
4+
private onComplete: (e?: any) => void
65
private cancelled = false
7-
private finished = false
6+
private completed = false
87
private reader: ReadableStreamDefaultReader<any> | null = null
98

109
constructor(
1110
response: any,
12-
onChunk: (chunk: any) => void,
13-
onFinish: () => void,
14-
onError: (e: any) => void,
11+
onNext: (chunk: any) => void,
12+
onComplete: (e?: any) => void,
1513
) {
1614
this.response = response
17-
this.onChunk = onChunk
18-
this.onFinish = onFinish
19-
this.onError = onError
15+
this.onComplete = onComplete
16+
this.onNext = onNext
2017
}
2118

22-
private finish() {
23-
if (this.finished || this.cancelled) return
24-
this.finished = true
25-
this.onFinish()
19+
private complete(e?:any) {
20+
if (this.completed || this.cancelled) return
21+
this.completed = true
22+
this.onComplete(e)
2623
}
2724

2825
async start() {
2926
try {
3027
this.reader = this.response.body?.getReader()
3128
if (!this.reader) {
32-
this.finish()
29+
this.complete()
3330
return
3431
}
3532

3633
const decoder = new TextDecoder()
3734
let buffer = ''
3835

3936
while (true) {
40-
if (this.cancelled || this.finished) break
37+
if (this.cancelled || this.completed) break
4138

4239
const { done, value } = await this.reader.read()
4340

@@ -50,21 +47,21 @@ export class ConversationStream {
5047
buffer = lines.pop() || ''
5148

5249
for (const line of lines) {
53-
if (this.cancelled || this.finished) break
50+
if (this.cancelled || this.completed) break
5451
const trimmed = line.trim()
5552
if (!trimmed) continue
5653

5754
// SSE 格式:data: {...}
5855
if (trimmed.startsWith('data:')) {
5956
const data = trimmed.slice(5).trim()
6057
if (data === '[DONE]') {
61-
this.finish()
58+
this.complete()
6259
return
6360
}
6461

6562
try {
6663
const chunk = JSON.parse(data)
67-
this.onChunk(chunk)
64+
this.onNext(chunk)
6865
} catch (e) {
6966
// Skip invalid JSON
7067
}
@@ -73,14 +70,14 @@ export class ConversationStream {
7370
}
7471

7572
// 处理 buffer 中剩余的数据
76-
if (!this.cancelled && !this.finished && buffer.trim()) {
73+
if (!this.cancelled && !this.completed && buffer.trim()) {
7774
const trimmed = buffer.trim()
7875
if (trimmed.startsWith('data:')) {
7976
const data = trimmed.slice(5).trim()
8077
if (data !== '[DONE]') {
8178
try {
8279
const chunk = JSON.parse(data)
83-
this.onChunk(chunk)
80+
this.onNext(chunk)
8481
} catch (e) {
8582
// Skip invalid JSON
8683
}
@@ -89,11 +86,11 @@ export class ConversationStream {
8986
}
9087

9188
if (!this.cancelled) {
92-
this.finish()
89+
this.complete()
9390
}
9491
} catch (e) {
95-
if (!this.cancelled && !this.finished) {
96-
this.onError(e)
92+
if (!this.cancelled && !this.completed) {
93+
this.complete(e)
9794
}
9895
} finally {
9996
this.reader = null

‎ui/src/views/workflow/tool/debug/ResultDrawer.vue‎

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { ToolWorkflowRecord } from '@/api/types'
66
import { MsgError } from '@/utils/message'
77
import { ConversationStream } from '@/conversation-panel/stream'
88
import { aggregators } from '@/conversation-panel'
9-
import ContentItem from '@/conversation-panel/content/index.vue'
9+
import ContentList from '@/conversation-panel/content-list/index.vue'
1010
import ExecutionDetailContent from '@/workflow-canvas/details/index.vue'
1111
import { WorkflowMode } from '@/workflow-canvas/types'
1212
@@ -25,6 +25,8 @@ interface ResumeParameters {
2525
formData?: Record<string, unknown>
2626
position?: unknown
2727
chunkId?: string
28+
chatRecordId?:string
29+
2830
}
2931
const props = defineProps<{ toolId: string }>()
3032
const running = defineModel<boolean>('running', { default: false })
@@ -71,9 +73,9 @@ async function execute(extra: Record<string, unknown> = {}) {
7173
stream = new ConversationStream(
7274
response,
7375
receiveChunk,
74-
() => {},
75-
(error: unknown) => {
76-
streamError = error
76+
(error?: unknown) => {
77+
if (error) streamError = error
78+
running.value = false
7779
},
7880
)
7981
await stream.start()
@@ -88,16 +90,14 @@ async function execute(extra: Record<string, unknown> = {}) {
8890
}
8991
} finally {
9092
stream = undefined
91-
running.value = false
93+
9294
}
9395
}
9496
9597
// 表单节点沿用同一条执行记录续跑,复用现有回复组件的 sendMessage 协议。
9698
provide('sendMessage', (options: ResumeParameters) => {
9799
if (running.value || !visible.value) return
98-
const block = blocks.value.find((entry) => entry.id === options.chunkId)
99-
if (block) Object.assign(block, { is_submit: true, form_data: options.formData })
100-
return execute({ ...options.formData, position: options.position })
100+
return execute({ 'form_data':options.formData,'chat_record_id':options.chatRecordId, 'chunk_id':options.chunkId,position: options.position })
101101
})
102102
103103
function open(parameters: Record<string, unknown>) {
@@ -136,21 +136,21 @@ defineExpose({ open, close })
136136
<h4 class="mk-title-decoration mb-4 mt-4">回复内容</h4>
137137

138138
<!-- // TODO: 回复内容 -->
139+
<el-card>
140+
<ContentList :content-list="blocks" />
141+
<div v-if="running">回答中...</div>
142+
</el-card>
139143

140144
<template v-if="record">
141145
<h4 class="mk-title-decoration my-4">输出参数</h4>
142-
<el-alert
143-
:title="record.state === 'SUCCESS' ? '运行成功' : '运行失败'"
144-
:type="record.state === 'SUCCESS' ? 'success' : 'error'"
145-
:closable="false"
146-
show-icon
147-
class="mb-4"
148-
/>
146+
<el-alert :title="record.state === 'SUCCESS' ? '运行成功' : '运行失败'"
147+
:type="record.state === 'SUCCESS' ? 'success' : 'error'" :closable="false" show-icon class="mb-4" />
149148
<pre class="mk-gray-card whitespace-pre-wrap break-all">{{ output }}</pre>
150149
</template>
151150
</el-tab-pane>
152151
<el-tab-pane label="执行详情" name="details">
153152
<!-- TODO 执行详情 -->
153+
<ExecutionDetailContent :detail="executionDetails" :workflow-mode="WorkflowMode.Tool"></ExecutionDetailContent>
154154
</el-tab-pane>
155155
</el-tabs>
156156
</MkDrawer>

0 commit comments

Comments
 (0)