mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-17 12:56:41 +02:00
fix(llm): preserve native continuation metadata (#28678)
This commit is contained in:
@@ -42,10 +42,15 @@ const providerMetadata = (value: unknown): ProviderMetadata | undefined => {
|
||||
return Object.keys(result).length === 0 ? undefined : result
|
||||
}
|
||||
|
||||
// Stored AI SDK parts historically kept provider-owned continuation metadata in
|
||||
// `providerOptions`; native parts now use `providerMetadata` directly.
|
||||
const partProviderMetadata = (part: Record<string, unknown>) =>
|
||||
providerMetadata(part.providerMetadata) ?? providerMetadata(part.providerOptions)
|
||||
|
||||
const textPart = (part: Record<string, unknown>) => ({
|
||||
type: "text" as const,
|
||||
text: typeof part.text === "string" ? part.text : "",
|
||||
providerMetadata: providerMetadata(part.providerOptions),
|
||||
providerMetadata: partProviderMetadata(part),
|
||||
})
|
||||
|
||||
const mediaPart = (part: Record<string, unknown>) => {
|
||||
@@ -68,7 +73,7 @@ const toolResult = (part: Record<string, unknown>) => {
|
||||
result: "value" in output ? output.value : output,
|
||||
resultType: type,
|
||||
providerExecuted: typeof part.providerExecuted === "boolean" ? part.providerExecuted : undefined,
|
||||
providerMetadata: providerMetadata(part.providerOptions),
|
||||
providerMetadata: partProviderMetadata(part),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -80,7 +85,7 @@ const contentPart = (part: unknown) => {
|
||||
return {
|
||||
type: "reasoning" as const,
|
||||
text: typeof part.text === "string" ? part.text : "",
|
||||
providerMetadata: providerMetadata(part.providerOptions),
|
||||
providerMetadata: partProviderMetadata(part),
|
||||
}
|
||||
if (part.type === "tool-call")
|
||||
return ToolCallPart.make({
|
||||
@@ -88,7 +93,7 @@ const contentPart = (part: unknown) => {
|
||||
name: typeof part.toolName === "string" ? part.toolName : "",
|
||||
input: part.input,
|
||||
providerExecuted: typeof part.providerExecuted === "boolean" ? part.providerExecuted : undefined,
|
||||
providerMetadata: providerMetadata(part.providerOptions),
|
||||
providerMetadata: partProviderMetadata(part),
|
||||
})
|
||||
if (part.type === "tool-result") return toolResult(part)
|
||||
throw new Error(`Native LLM request adapter does not support ${String(part.type)} content parts`)
|
||||
|
||||
@@ -219,6 +219,42 @@ describe("session.llm-native.request", () => {
|
||||
])
|
||||
})
|
||||
|
||||
test("maps stored provider metadata to native content metadata", () => {
|
||||
const reasoning = Object.assign(
|
||||
{ type: "reasoning" as const, text: "thinking" },
|
||||
{
|
||||
providerMetadata: {
|
||||
openai: {
|
||||
itemId: "rs_1",
|
||||
reasoningEncryptedContent: "encrypted-state",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
const request = LLMNative.request({
|
||||
model: baseModel,
|
||||
messages: [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [reasoning],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(request.messages).toMatchObject([
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{
|
||||
type: "reasoning",
|
||||
text: "thinking",
|
||||
providerMetadata: { openai: { itemId: "rs_1", reasoningEncryptedContent: "encrypted-state" } },
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
test("selects native request routes for provider packages", () => {
|
||||
const openai = LLMNative.model({
|
||||
model: { ...baseModel, api: { ...baseModel.api, url: "", npm: "@ai-sdk/openai" } },
|
||||
|
||||
Reference in New Issue
Block a user