Skip to content

Commit 919ff19

Browse files
committed
pass tool values through more places
1 parent 7cd12ae commit 919ff19

File tree

2 files changed

+39
-43
lines changed

2 files changed

+39
-43
lines changed

src/UIMessages.ts

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,9 @@ function createAssistantUIMessage<
385385
const allParts: UIMessage<METADATA, DATA_PARTS, TOOLS>["parts"] = [];
386386

387387
for (const message of group) {
388-
const coreMessage = message.message && deserializeMessage(message.message);
389-
if (!coreMessage) continue;
388+
if (!message.message) continue;
390389

391-
const content = coreMessage.content;
390+
const content = message.message.content;
392391
const nonStringContent =
393392
content && typeof content !== "string" ? content : [];
394393
const text = extractTextFromMessageDoc(message);
@@ -445,12 +444,11 @@ function createAssistantUIMessage<
445444
type: "step-start",
446445
} satisfies StepStartUIPart);
447446
const toolPart: ToolUIPart<TOOLS> = {
447+
...omit(contentPart, ["args", "type"]),
448448
type: `tool-${contentPart.toolName as keyof TOOLS & string}`,
449-
toolCallId: contentPart.toolCallId,
450-
input: contentPart.input as DeepPartial<
449+
input: contentPart.args as DeepPartial<
451450
TOOLS[keyof TOOLS & string]["input"]
452451
>,
453-
providerExecuted: contentPart.providerExecuted,
454452
...(message.streaming
455453
? { state: "input-streaming" }
456454
: {
@@ -482,25 +480,22 @@ function createAssistantUIMessage<
482480
call.output = output;
483481
}
484482
} else {
485-
console.warn(
486-
"Tool result without preceding tool call.. adding anyways",
487-
contentPart,
488-
);
489483
if (message.error) {
490484
allParts.push({
485+
input: contentPart.args,
486+
...omit(contentPart, ["args", "type", "output"]),
491487
type: `tool-${contentPart.toolName}`,
492-
toolCallId: contentPart.toolCallId,
493488
state: "output-error",
494-
input: undefined,
489+
output,
495490
errorText: message.error,
496491
callProviderMetadata: message.providerMetadata,
497492
} satisfies ToolUIPart<TOOLS>);
498493
} else {
499494
allParts.push({
495+
input: contentPart.args,
496+
...omit(contentPart, ["args", "type", "output"]),
500497
type: `tool-${contentPart.toolName}`,
501-
toolCallId: contentPart.toolCallId,
502498
state: "output-available",
503-
input: undefined,
504499
output,
505500
callProviderMetadata: message.providerMetadata,
506501
} satisfies ToolUIPart<TOOLS>);

src/mapping.ts

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import {
5454
getProviderName,
5555
type ModelOrMetadata,
5656
} from "./shared.js";
57-
import { pick } from "convex-helpers";
57+
import { omit, pick } from "convex-helpers";
5858
export type AIMessageWithoutId = Omit<AIMessage, "id">;
5959

6060
export type SerializeUrlsAndUint8Arrays<T> = T extends URL
@@ -102,9 +102,7 @@ export function fromModelMessage(message: ModelMessage): Message {
102102
return {
103103
role: message.role,
104104
content,
105-
...(message.providerOptions
106-
? { providerOptions: message.providerOptions }
107-
: {}),
105+
...pick(message, ["providerOptions"]),
108106
} as SerializedMessage;
109107
}
110108

@@ -121,9 +119,7 @@ export async function serializeOrThrow(
121119
return {
122120
role: message.role,
123121
content,
124-
...(message.providerOptions
125-
? { providerOptions: message.providerOptions }
126-
: {}),
122+
...pick(message, ["providerOptions"]),
127123
} as SerializedMessage;
128124
}
129125

@@ -613,20 +609,20 @@ export function deserializeContent(
613609
mediaType: getMimeOrMediaType(part)!,
614610
...metadata,
615611
} satisfies FilePart;
616-
case "tool-call": {
617-
const input = "input" in part ? part.input : part.args;
612+
case "tool-call":
618613
return {
619-
type: part.type,
620-
input: input ?? null,
621-
toolCallId: part.toolCallId,
622-
toolName: part.toolName,
623-
providerExecuted: part.providerExecuted,
624-
...metadata,
614+
input: ("input" in part ? part.input : part.args) ?? null,
615+
...omit(part as Infer<typeof vToolCallPart>, ["args"]),
625616
} satisfies ToolCallPart;
626-
}
627-
case "tool-result": {
628-
return normalizeToolResult(part, metadata);
629-
}
617+
case "tool-result":
618+
return {
619+
input: (part as Infer<typeof vToolResultPart>).args,
620+
output: normalizeToolOutput(
621+
(part as Infer<typeof vToolResultPart>).result,
622+
),
623+
...omit(part as Infer<typeof vToolResultPart>, ["result", "args"]),
624+
...metadata,
625+
} satisfies ToolResultPart & { input: unknown };
630626
case "reasoning":
631627
return {
632628
type: part.type,
@@ -684,16 +680,13 @@ function normalizeToolResult(
684680
providerOptions?: ProviderOptions;
685681
providerMetadata?: ProviderMetadata;
686682
},
687-
): ToolResultPart & Infer<typeof vToolResultPart> {
683+
): ToolResultPart & Infer<typeof vToolResultPart> & { input: unknown } {
688684
return {
689-
type: part.type,
690-
output:
691-
part.output ??
692-
normalizeToolOutput("result" in part ? part.result : undefined),
693-
toolCallId: part.toolCallId,
694-
toolName: part.toolName,
685+
input: (part as Infer<typeof vToolResultPart>).args,
686+
output: normalizeToolOutput("result" in part ? part.result : undefined),
687+
...omit(part as Infer<typeof vToolResultPart>, ["result", "args"]),
695688
...metadata,
696-
} satisfies ToolResultPart;
689+
} satisfies ToolResultPart & { input: unknown };
697690
}
698691

699692
/**
@@ -804,16 +797,24 @@ export function deserializeUrl(
804797
return urlOrString;
805798
}
806799

807-
export function toUIFilePart(part: ImagePart | FilePart): FileUIPart {
800+
export function toUIFilePart(
801+
part:
802+
| ImagePart
803+
| FilePart
804+
| Infer<typeof vImagePart>
805+
| Infer<typeof vFilePart>,
806+
): FileUIPart {
808807
const dataOrUrl = part.type === "image" ? part.image : part.data;
809808
const url =
810809
dataOrUrl instanceof ArrayBuffer
811810
? convertUint8ArrayToBase64(new Uint8Array(dataOrUrl))
812811
: dataOrUrl.toString();
813812

813+
const mediaType = getMimeOrMediaType(part);
814+
814815
return {
815816
type: "file",
816-
mediaType: part.mediaType!,
817+
mediaType: mediaType!,
817818
filename: part.type === "file" ? part.filename : undefined,
818819
url,
819820
providerMetadata: part.providerOptions,

0 commit comments

Comments
 (0)