fix(ai): retry Bun socket drops

closes #6431
This commit is contained in:
Mario Zechner
2026-07-09 11:03:41 +02:00
parent 72d77b53de
commit 4285712bae
4 changed files with 13 additions and 0 deletions
+1
View File
@@ -15,6 +15,7 @@
- Fixed OpenAI Completions and Responses providers to send `(no tool output)` instead of `(see attached image)` when a tool result has empty text and no image content, preventing the model from hallucinating image attachments.
- Fixed OpenAI Responses and Azure OpenAI Responses requests to avoid sending `max_output_tokens` values below the provider minimum ([#6265](https://github.com/earendil-works/pi/issues/6265)).
- Fixed retry classification for Cloudflare 524 timeout responses ([#6239](https://github.com/earendil-works/pi/issues/6239)).
- Fixed retry classification for Bun fetch socket-drop errors such as `socket connection was closed`, so transient stream disconnects retry automatically ([#6431](https://github.com/earendil-works/pi/issues/6431)).
- Fixed GitHub Copilot extended context window models (Claude Opus 4.7/4.8, Claude Opus 4.6, Claude Sonnet 4.6/5, Claude Fable 5, GPT-5.3 Codex, GPT-5.4, GPT-5.5) to use `contextWindow: 1000000`, preventing premature compaction and under-budgeting ([#6439](https://github.com/earendil-works/pi/issues/6439)).
### Added
+1
View File
@@ -54,6 +54,7 @@ const RETRYABLE_PROVIDER_ERROR_PATTERN = buildProviderErrorPattern([
"upstream.?connect",
"reset before headers",
"socket hang up",
"socket connection was closed",
"timed? out",
"timeout",
"terminated",
+10
View File
@@ -6,6 +6,8 @@ const openAIExplicitRetryMessage =
"An error occurred while processing your request. You can retry your request, or contact us through our help center at help.openai.com if the error persists. Please include the request ID req_******** in your message.";
const bedrockExplicitRetryMessage =
'{"message":"The system encountered an unexpected error during processing. Try your request again."}';
const bunFetchSocketClosedMessage =
"The socket connection was closed unexpectedly. For more information, pass `verbose: true` in the second argument to fetch()";
describe("provider retry classification", () => {
it("matches explicit provider retry guidance", () => {
@@ -21,6 +23,14 @@ describe("provider retry classification", () => {
).toBe(true);
});
it("matches Bun fetch socket drop wording", () => {
expect(
isRetryableAssistantError(
fauxAssistantMessage("", { stopReason: "error", errorMessage: bunFetchSocketClosedMessage }),
),
).toBe(true);
});
it("keeps provider limit errors non-retryable", () => {
expect(
isRetryableAssistantError(