Skip to content

fix(ai): parse only the last final_answer message for structured output - #23834

Closed
princejain756 wants to merge 2 commits into
vercel:mainfrom
princejain756:fix-final-answer-phase-output
Closed

princejain756 wants to merge 2 commits into
vercel:mainfrom
princejain756:fix-final-answer-phase-output

Conversation

@princejain756

Copy link
Copy Markdown

Background

#23832 reports that Output.object fails on OpenAI Responses replies that contain more than one assistant message (e.g. a commentary message and a final_answer message). Each message maps to a separate text content part, and generateText / streamText join all text parts before structured output parsing, so the parser receives two concatenated JSON documents ({...}{...}) and throws AI_NoObjectGeneratedError / AI_JSONParseError even though the final answer is valid JSON.

Summary

The message phase is already available in providerMetadata.<provider>.phase on the text parts (added for openai and azure under #12475/#12858). A new getOutputParseText helper in step-result.ts uses it: when text parts carry phase metadata, only the text of the last final_answer message is handed to parseCompleteOutput in both generateText and streamText. result.text, step.content, response messages, and usage keep the full reply unchanged, and replies without phase metadata behave exactly as before. The same path also handles the "two final_answer messages" variant, where only the last one is parsed.

Contributor Credit

Issue report and reproduction by @roeibh (#23832).

End-to-End Verification

Reproduced the reported scenario through the public generateText and streamText entry points with a reply of two phase-tagged messages containing individually valid JSON. Before the change, both threw the reported AI_JSONParseError (JSON parsing failed: Text: { "value": "commentary" }{ "value": "answer" }); after it, result.output resolves to the object parsed from the last final_answer message while finalStep.text still contains the full reply.

Checklist

  • All commits are signed (PRs with unsigned commits cannot be merged)
  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

Future Work

streamText partial output (partialObjectStream) still sees the raw concatenated stream text; mid-stream partials may not parse for multi-message replies.

Related Issues

#23832

The phase filter also ran for the default text() spec, so result.output
dropped earlier messages while result.text kept them. Only structured
specs parse the last final_answer message now.

@aayush-kapoor aayush-kapoor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

theres some edge cases that this misses - will be handled in #23895

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants