Repository navigation
fix(v1/messages): default to non-stream for Claude format when ambiguous #2326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,12 +17,35 @@ export function clientWantsJsonResponse(acceptHeader: unknown): boolean { | |
| * Accept header only acts as fallback when stream is not explicitly set. | ||
| * Fixes #656: clients sending both `stream: true` and `Accept: application/json` | ||
| * should still get streaming responses — body intent takes precedence. | ||
| * | ||
| * Optional `sourceFormat` argument lets callers apply spec-correct defaults | ||
| * when both `stream` and `Accept` are ambiguous. The Anthropic Messages API | ||
| * defaults to non-stream when the body omits `stream`, regardless of Accept | ||
| * header. Without this hint, OmniRoute previously routed Anthropic /v1/messages | ||
| * requests with a curl-default wildcard Accept header through the streaming | ||
| * branch even though upstream returned JSON, producing STREAM_EARLY_EOF / | ||
| * HTTP 502 errors. | ||
| */ | ||
| export function resolveStreamFlag(bodyStream: unknown, acceptHeader: unknown): boolean { | ||
| export function resolveStreamFlag( | ||
| bodyStream: unknown, | ||
| acceptHeader: unknown, | ||
| sourceFormat?: string | ||
| ): boolean { | ||
| // Explicit body value always wins | ||
| if (bodyStream === true) return true; | ||
| if (bodyStream === false) return false; | ||
|
|
||
| // Anthropic Messages API spec: stream defaults to false when body omits it. | ||
| // Only honor an explicit text/event-stream Accept header as a streaming opt-in | ||
| // for /v1/messages — otherwise default to non-stream so upstream JSON responses | ||
| // are surfaced correctly instead of triggering stream_early_eof. | ||
| if (sourceFormat === "claude") { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WARNING: Hardcoded string literal The rest of Consider using |
||
| if (typeof acceptHeader === "string" && /text\/event-stream/i.test(acceptHeader)) { | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| // No explicit stream param — preserve OmniRoute's streaming default unless | ||
| // the client explicitly asks for JSON and does not also accept SSE. | ||
| return !clientWantsJsonResponse(acceptHeader); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SUGGESTION:
sourceFormatparameter typed asstringis too looseThe parameter accepts any string value, making it easy to accidentally pass an incorrect format identifier. Consider typing it more strictly, e.g.
sourceFormat?: keyof typeof FORMATS | stringor importing a dedicated format type fromformats.ts. This would improve type safety and IDE autocomplete for callers.