fix(schema): encode output format values read back from storage - #40172
fix(schema): encode output format values read back from storage#40172JaviOverflow wants to merge 1 commit into
Conversation
OutputFormatText and OutputFormatJsonSchema were Schema.Class, which only
encodes an actual class instance. Messages come back out of storage as plain
JSON, so every path that re-emits a stored message with a format field failed:
- GET /session/:id/message returned 400 BadRequest
("Expected OutputFormatJsonSchema, got {...} at [0]["info"]["format"]")
for any session where a prompt used an output format.
- session/fork copied no messages, because it re-publishes each copied message
through updateMessage -> events.publish(MessageUpdated), hitting the same
encode. The forked session was created but left empty.
Making both plain structs keeps the wire format, the OpenAPI component names
and the decode behaviour (including the retryCount default) identical, while
allowing the stored value to encode. Regenerating drops the orphan
OutputFormat1 component, which the class-based union duplicated and nothing
referenced.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
The following comment was made by an LLM, it may be inaccurate: Potential Duplicate FoundPR #37541: fix(session): encode persisted output formats Why it's related:
Note: PR #37541 was created earlier than the current PR #40172. This could indicate:
You may want to review PR #37541 to understand what was previously attempted and ensure the current approach doesn't duplicate prior work. |
|
This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window. Feel free to open a new pull request that follows our guidelines. |
Fixes #40169.
OutputFormatText/OutputFormatJsonSchemawereSchema.Class, which only encodes an actual class instance. Messages come back out of storage as plain JSON, so every path that re-emits a stored message carryingformatfailed:GET /session/:id/messagereturns 400Expected OutputFormatJsonSchema, got {...} at [0]["info"]["format"]for any session where a prompt used an output format. The route encodes stored rows againstSchema.Array(SessionV1.WithParts).session/forkcopies no messages: it re-publishes each copied message throughupdateMessage->events.publish(MessageUpdated), which hits the same encode. The forked session is created but stays empty, and because the request never completes, a client that retries on timeout/5xx keeps creating empty sessions.Making both plain structs (keeping their
identifierannotations) lets the stored value encode, while leaving the wire format, the OpenAPI component names and the decode behaviour - including theretryCountdefault - unchanged. Nothing constructs these classes (nonew, noinstanceof); they are only re-exported as values frompackages/core/src/v1/session.ts.Tests
Three cases added to
packages/opencode/test/session/structured-output.test.ts: encoding a storedtextformat, a storedjson_schemaformat, and a stored user message carrying one. Ondevthey fail with the production error; with the fix they pass.Verification
bun test test/sessioninpackages/opencode: 372 pass, 0 failbun turbo typecheck: 30/30 successfuldev)bun dev generate+packages/sdk/js/script/build.ts: the only regeneration diff is the removal of the orphanOutputFormat1component and its generated type, which the class-based union duplicated and which nothing referenced. That is the one API-visible consequence, in case you would rather keep the symbol around.The two
public event manifestfailures inpackages/schemareproduce identically on a cleandevcheckout and are unrelated to this change.