Skip to content

fix(robot): message processing of the robot is optimized. #3491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 9, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 29 additions & 61 deletions examples/sites/src/views/components-doc/composition/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ export async function handleSSEStream(
)
}

let messageIndex = 0
function printMessage(data, str: string, endln = false) {
handler.onData({
id: '',
created: data.created_at,
choices: [
{
index: messageIndex++,
delta: {
role: 'assistant',
content: str + (endln ? '\n\n' : '')
},
finish_reason: null
}
],
object: '',
model: ''
})
}
Comment on lines +45 to +62
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve the printMessage helper function implementation.

The helper function has several areas for improvement:

  1. Type safety: The data parameter lacks type annotation
  2. Response structure: Empty string values for id, object, and model fields may cause issues with downstream consumers
  3. Potential memory growth: The incrementing messageIndex could grow indefinitely in long-running streams

Apply these improvements:

-  function printMessage(data, str: string, endln = false) {
+  function printMessage(data: any, str: string, endln = false) {
     handler.onData({
-      id: '',
+      id: data.id || crypto.randomUUID(),
       created: data.created_at,
       choices: [
         {
           index: messageIndex++,
           delta: {
             role: 'assistant',
             content: str + (endln ? '\n\n' : '')
           },
           finish_reason: null
         }
       ],
-      object: '',
-      model: ''
+      object: 'chat.completion.chunk',
+      model: data.model || 'unknown'
     })
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function printMessage(data, str: string, endln = false) {
handler.onData({
id: '',
created: data.created_at,
choices: [
{
index: messageIndex++,
delta: {
role: 'assistant',
content: str + (endln ? '\n\n' : '')
},
finish_reason: null
}
],
object: '',
model: ''
})
}
function printMessage(data: any, str: string, endln = false) {
handler.onData({
id: data.id || crypto.randomUUID(),
created: data.created_at,
choices: [
{
index: messageIndex++,
delta: {
role: 'assistant',
content: str + (endln ? '\n\n' : '')
},
finish_reason: null
}
],
object: 'chat.completion.chunk',
model: data.model || 'unknown'
})
}
🤖 Prompt for AI Agents
In examples/sites/src/views/components-doc/composition/utils.ts around lines 45
to 62, improve the printMessage function by adding a proper type annotation for
the data parameter to ensure type safety, replace empty string values for id,
object, and model with meaningful or default values to avoid issues downstream,
and implement a mechanism to reset or limit the growth of the messageIndex
variable to prevent unbounded memory growth during long-running streams.

try {
while (true) {
if (signal?.aborted) {
Expand All @@ -59,8 +78,6 @@ export async function handleSSEStream(
const lines = buffer.split('\n\n')
buffer = lines.pop() || ''

let messageIndex = 0

for (const line of lines) {
if (line.trim() === '') continue
if (line.trim() === 'data: [DONE]') {
Expand All @@ -75,68 +92,19 @@ export async function handleSSEStream(

const data = JSON.parse(dataMatch[1])
// console.log('SSE data:', data)
if (data?.event === 'workflow_started') {
handler.onData({
id: data.workflow_run_id,
created: data.created_at,
choices: [
{
index: messageIndex++,
delta: {
role: 'assistant',
content: ' '
},
finish_reason: null
}
],
object: '',
model: ''
})
message.value.slice(-1)[0].loading = true
if (!globalConversation.id) {
globalConversation.id = data.conversation_id
}
if (data?.event === 'node_started') {
printMessage(data, `${data.data.title} 节点运行...`, true)
}

if (data?.event === 'message' && data?.answer) {
handler.onData({
id: data.id,
created: data.created_at,
choices: [
{
index: messageIndex++,
delta: {
role: 'assistant',
content: data.answer
},
finish_reason: null
}
],
object: '',
model: ''
})
message.value.slice(-1)[0].loading = false
if (data?.event === 'node_finished') {
printMessage(
data,
`${data.data.title} 节点结束\n\n` +
(data.data.node_type === 'answer' ? `${data.data.outputs.answer}` : '')
)
}
if (data?.event === 'message_end') {
handler.onData({
id: data.id,
created: data.created_at,
choices: [
{
index: messageIndex++,
delta: {
role: 'assistant',
content: ''
},
finish_reason: 'stop'
}
],
object: '',
model: ''
})
message.value.slice(-1)[0].loading = false
if (data?.event === 'agent_log' && data.data.status === 'success' && data.data.label.startsWith('CALL')) {
printMessage(data, `--${data.data.label}(${JSON.stringify(data.data.data.output.tool_call_input)})`, true)
}
Comment on lines +95 to 107
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Verify the new event handling logic and add error protection.

The new event handling logic introduces several potential issues:

  1. Missing null checks: Direct property access without validation could cause runtime errors
  2. JSON.stringify safety: Could fail with circular references or non-serializable objects
  3. Hardcoded Chinese text: May cause encoding issues in some environments

Add proper error handling and validation:

-          if (data?.event === 'node_started') {
-            printMessage(data, `${data.data.title} 节点运行...`, true)
+          if (data?.event === 'node_started' && data.data?.title) {
+            printMessage(data, `${data.data.title} 节点运行...`, true)
           }
-          if (data?.event === 'node_finished') {
+          if (data?.event === 'node_finished' && data.data?.title) {
             printMessage(
               data,
               `${data.data.title} 节点结束\n\n` +
-                (data.data.node_type === 'answer' ? `${data.data.outputs.answer}` : '')
+                (data.data.node_type === 'answer' && data.data.outputs?.answer ? `${data.data.outputs.answer}` : '')
             )
           }
-          if (data?.event === 'agent_log' && data.data.status === 'success' && data.data.label.startsWith('CALL')) {
-            printMessage(data, `--${data.data.label}(${JSON.stringify(data.data.data.output.tool_call_input)})`, true)
+          if (data?.event === 'agent_log' && data.data?.status === 'success' && data.data?.label?.startsWith('CALL')) {
+            try {
+              const toolCallInput = JSON.stringify(data.data.data?.output?.tool_call_input || {})
+              printMessage(data, `--${data.data.label}(${toolCallInput})`, true)
+            } catch (error) {
+              console.warn('Failed to stringify tool call input:', error)
+              printMessage(data, `--${data.data.label}(${String(data.data.data?.output?.tool_call_input || '')})`, true)
+            }
           }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (data?.event === 'node_started') {
printMessage(data, `${data.data.title} 节点运行...`, true)
}
if (data?.event === 'message' && data?.answer) {
handler.onData({
id: data.id,
created: data.created_at,
choices: [
{
index: messageIndex++,
delta: {
role: 'assistant',
content: data.answer
},
finish_reason: null
}
],
object: '',
model: ''
})
message.value.slice(-1)[0].loading = false
if (data?.event === 'node_finished') {
printMessage(
data,
`${data.data.title} 节点结束\n\n` +
(data.data.node_type === 'answer' ? `${data.data.outputs.answer}` : '')
)
}
if (data?.event === 'message_end') {
handler.onData({
id: data.id,
created: data.created_at,
choices: [
{
index: messageIndex++,
delta: {
role: 'assistant',
content: ''
},
finish_reason: 'stop'
}
],
object: '',
model: ''
})
message.value.slice(-1)[0].loading = false
if (data?.event === 'agent_log' && data.data.status === 'success' && data.data.label.startsWith('CALL')) {
printMessage(data, `--${data.data.label}(${JSON.stringify(data.data.data.output.tool_call_input)})`, true)
}
if (data?.event === 'node_started' && data.data?.title) {
printMessage(data, `${data.data.title} 节点运行...`, true)
}
if (data?.event === 'node_finished' && data.data?.title) {
printMessage(
data,
`${data.data.title} 节点结束\n\n` +
(data.data.node_type === 'answer' && data.data.outputs?.answer
? `${data.data.outputs.answer}`
: '')
)
}
if (
data?.event === 'agent_log' &&
data.data?.status === 'success' &&
data.data?.label?.startsWith('CALL')
) {
try {
const toolCallInput = JSON.stringify(
data.data.data?.output?.tool_call_input || {}
)
printMessage(data, `--${data.data.label}(${toolCallInput})`, true)
} catch (error) {
console.warn('Failed to stringify tool call input:', error)
printMessage(
data,
`--${data.data.label}(${String(
data.data.data?.output?.tool_call_input || ''
)})`,
true
)
}
}
🤖 Prompt for AI Agents
In examples/sites/src/views/components-doc/composition/utils.ts around lines 95
to 107, the event handling code lacks null checks for nested properties, uses
JSON.stringify without error handling which may fail on circular or
non-serializable data, and contains hardcoded Chinese text that could cause
encoding issues. To fix this, add conditional checks to ensure all nested
properties exist before accessing them, wrap JSON.stringify calls in try-catch
blocks to handle serialization errors gracefully, and replace hardcoded Chinese
strings with variables or constants that can be localized or encoded properly.

// handler.onData(data)
} catch (error) {
console.error('Error parsing SSE message:', error)
}
Expand Down
Loading