fix(ai): replay function call item ids
This commit is contained in:
@@ -335,12 +335,16 @@ const metadataItemID = (
|
||||
: undefined
|
||||
}
|
||||
|
||||
const lowerToolCall = (part: ToolCallPart): OpenResponsesInputItem => ({
|
||||
type: "function_call",
|
||||
call_id: part.id,
|
||||
name: part.name,
|
||||
arguments: ProviderShared.encodeJson(part.input),
|
||||
})
|
||||
const lowerToolCall = (part: ToolCallPart, providerMetadataKey: string): OpenResponsesInputItem => {
|
||||
const itemId = metadataItemID(part, providerMetadataKey)
|
||||
return {
|
||||
type: "function_call",
|
||||
...(itemId === undefined ? {} : { id: itemId }),
|
||||
call_id: part.id,
|
||||
name: part.name,
|
||||
arguments: ProviderShared.encodeJson(part.input),
|
||||
}
|
||||
}
|
||||
|
||||
const lowerReasoning = (part: ReasoningPart, providerMetadataKey: string): OpenResponsesReasoningInput | undefined => {
|
||||
const metadata = part.providerMetadata?.[providerMetadataKey]
|
||||
@@ -503,7 +507,7 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
|
||||
if (part.type === "tool-call") {
|
||||
flushText()
|
||||
if (part.providerExecuted === true) continue
|
||||
input.push(lowerToolCall(part))
|
||||
input.push(lowerToolCall(part, providerMetadataKey))
|
||||
continue
|
||||
}
|
||||
if (part.type === "tool-result" && part.providerExecuted === true) {
|
||||
|
||||
+3
-3
File diff suppressed because one or more lines are too long
+4
-4
File diff suppressed because one or more lines are too long
-54
File diff suppressed because one or more lines are too long
-28
File diff suppressed because one or more lines are too long
-28
File diff suppressed because one or more lines are too long
+4
-4
File diff suppressed because one or more lines are too long
+6
-6
File diff suppressed because one or more lines are too long
Vendored
+10
-4
File diff suppressed because one or more lines are too long
+38
File diff suppressed because one or more lines are too long
Vendored
+39
File diff suppressed because one or more lines are too long
Vendored
+57
File diff suppressed because one or more lines are too long
@@ -458,14 +458,19 @@ describe("OpenAI Responses route", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("preserves opaque assistant item ids without assigning ids to function items", () =>
|
||||
it.effect("replays provider function call item ids without assigning output ids", () =>
|
||||
Effect.gen(function* () {
|
||||
const canonical = LLM.request({
|
||||
model,
|
||||
messages: [
|
||||
Message.assistant([
|
||||
{ type: "text", text: "Calling.", itemId: "plain-text" },
|
||||
ToolCallPart.make({ id: "call_1", itemId: "plain-call", name: "lookup", input: {} }),
|
||||
ToolCallPart.make({
|
||||
id: "call_1",
|
||||
name: "lookup",
|
||||
input: {},
|
||||
providerMetadata: { openai: { itemId: "plain-call" } },
|
||||
}),
|
||||
]),
|
||||
Message.tool({ id: "call_1", itemId: "plain-output", name: "lookup", result: "done" }),
|
||||
],
|
||||
@@ -474,12 +479,12 @@ describe("OpenAI Responses route", () => {
|
||||
|
||||
expect(canonical.messages[0]?.content.map((part) => (part.type === "media" ? undefined : part.itemId))).toEqual([
|
||||
"plain-text",
|
||||
"plain-call",
|
||||
undefined,
|
||||
])
|
||||
expect(canonical.messages[1]?.content[0]).toMatchObject({ itemId: "plain-output" })
|
||||
expect(prepared.body.input).toEqual([
|
||||
{ role: "assistant", id: "plain-text", content: [{ type: "output_text", text: "Calling." }] },
|
||||
{ type: "function_call", call_id: "call_1", name: "lookup", arguments: "{}" },
|
||||
{ type: "function_call", id: "plain-call", call_id: "call_1", name: "lookup", arguments: "{}" },
|
||||
{ type: "function_call_output", call_id: "call_1", output: '"done"' },
|
||||
])
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user