mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
fix(chat-sdk): read a tool's call and a model's thinking off the row
A conversation row carries three things the SDK did not declare and so never read: what a tool was called with, what it returned, and the thinking behind an answer. For a tool that runs inside the agent's job the row is the only copy of the first two, and for a failed tool the result is what it failed with — so a conversation read back through the SDK showed a tool call with nothing to expand and a failure with no reason. The AI SDK adapter already preferred a tool's result over the row's text when reporting an error, so it needed only the data. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
680da0a916
commit
d6c07ce66d
+22
-6
@@ -1,5 +1,10 @@
|
||||
import type { ChatTransport, UIMessage, UIMessageChunk, UIMessagePart } from 'ai'
|
||||
import { WindmillApiError, WindmillChatApi, type WindmillChatApiOptions } from './api'
|
||||
import {
|
||||
WindmillApiError,
|
||||
WindmillChatApi,
|
||||
type FlowConversationMessage,
|
||||
type WindmillChatApiOptions
|
||||
} from './api'
|
||||
import { followJob } from './follow'
|
||||
import type { AgentStreamEvent } from './stream'
|
||||
import type { ChatMessage, Conversation } from './types'
|
||||
@@ -101,7 +106,8 @@ export function createWindmillChatTransport<UI_MESSAGE extends UIMessage = UIMes
|
||||
stepName: row.step_name ?? undefined,
|
||||
pending: false,
|
||||
seq: row.created_seq,
|
||||
tool: toolFromRowContent(row.message_type, row.content, row.success ?? true)
|
||||
reasoning: row.reasoning ?? undefined,
|
||||
tool: toolFromRow(row)
|
||||
}))
|
||||
) as UI_MESSAGE[]
|
||||
},
|
||||
@@ -123,10 +129,20 @@ export function createWindmillChatTransport<UI_MESSAGE extends UIMessage = UIMes
|
||||
}
|
||||
}
|
||||
|
||||
function toolFromRowContent(role: string, content: string, success: boolean): ChatMessage['tool'] {
|
||||
if (role !== 'tool') return undefined
|
||||
const name = /^Used (.+) tool$/.exec(content)?.[1] ?? /^Error executing (.+)$/.exec(content)?.[1]
|
||||
return name ? { name, status: success ? 'success' : 'error' } : undefined
|
||||
/** The call a stored tool row carries: its tool, named by the sentence the worker words
|
||||
* every tool row from, and the arguments and result the row keeps when its job cannot be
|
||||
* asked for them — for a failed tool, the result is what it failed with. */
|
||||
function toolFromRow(row: FlowConversationMessage): ChatMessage['tool'] {
|
||||
if (row.message_type !== 'tool') return undefined
|
||||
const name =
|
||||
/^Used (.+) tool$/.exec(row.content)?.[1] ?? /^Error executing (.+)$/.exec(row.content)?.[1]
|
||||
if (!name) return undefined
|
||||
return {
|
||||
name,
|
||||
status: (row.success ?? true) ? 'success' : 'error',
|
||||
arguments: row.tool_arguments ?? undefined,
|
||||
result: row.tool_result ?? undefined
|
||||
}
|
||||
}
|
||||
|
||||
/** Streams a job's answer as AI SDK chunks; resumes from `entry.offset` when the job is already running. */
|
||||
|
||||
@@ -40,6 +40,11 @@ export interface FlowConversationMessage {
|
||||
created_seq: number
|
||||
step_name?: string | null
|
||||
success?: boolean
|
||||
/** The call a tool row carries itself, for a tool whose job cannot be asked for it. */
|
||||
tool_arguments?: string | null
|
||||
tool_result?: string | null
|
||||
/** The thinking behind an answer, which is streamed and stored nowhere else. */
|
||||
reasoning?: string | null
|
||||
}
|
||||
|
||||
export type JobUpdateEvent =
|
||||
|
||||
+12
-1
@@ -725,7 +725,18 @@ function fromRow(row: FlowConversationMessage): ChatMessage {
|
||||
stepName: row.step_name ?? undefined,
|
||||
pending: false,
|
||||
seq: row.created_seq,
|
||||
tool: toolName ? { name: toolName, status: success ? 'success' : 'error' } : undefined
|
||||
reasoning: row.reasoning ?? undefined,
|
||||
// The call the row carries, which is all there is of it for a tool that ran inside the
|
||||
// agent's job or failed before it had one of its own. For a failed tool the result is
|
||||
// what it failed with, and the row's text names the tool rather than the reason.
|
||||
tool: toolName
|
||||
? {
|
||||
name: toolName,
|
||||
status: success ? 'success' : 'error',
|
||||
arguments: row.tool_arguments ?? undefined,
|
||||
result: row.tool_result ?? undefined
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user