From fb17a322832edbfa7c7477279f4c949c0176ab34 Mon Sep 17 00:00:00 2001 From: Emanuel Stadler <9994339+emanuelst@users.noreply.github.com> Date: Tue, 6 Jan 2026 21:17:55 +0100 Subject: [PATCH] feat: enhance error handling for socket connection errors - Added `isError` property to `EmbeddedPiRunResult` and reply items to indicate error states. - Updated error handling in `runReplyAgent` to provide more informative messages for specific socket connection errors. --- src/agents/pi-embedded-runner.ts | 11 +++++++++-- src/auto-reply/reply/agent-runner.ts | 21 +++++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/agents/pi-embedded-runner.ts b/src/agents/pi-embedded-runner.ts index 813a4ba0d..78e895c24 100644 --- a/src/agents/pi-embedded-runner.ts +++ b/src/agents/pi-embedded-runner.ts @@ -99,6 +99,7 @@ export type EmbeddedPiRunResult = { mediaUrl?: string; mediaUrls?: string[]; replyToId?: string; + isError?: boolean; }>; meta: EmbeddedPiRunMeta; }; @@ -1009,12 +1010,17 @@ export async function runEmbeddedPiAgent(params: { usage, }; - const replyItems: Array<{ text: string; media?: string[] }> = []; + const replyItems: Array<{ + text: string; + media?: string[]; + isError?: boolean; + }> = []; const errorText = lastAssistant ? formatAssistantErrorText(lastAssistant) : undefined; - if (errorText) replyItems.push({ text: errorText }); + + if (errorText) replyItems.push({ text: errorText, isError: true }); const inlineToolResults = params.verboseLevel === "on" && @@ -1047,6 +1053,7 @@ export async function runEmbeddedPiAgent(params: { text: item.text?.trim() ? item.text.trim() : undefined, mediaUrls: item.media?.length ? item.media : undefined, mediaUrl: item.media?.[0], + isError: item.isError, })) .filter( (p) => diff --git a/src/auto-reply/reply/agent-runner.ts b/src/auto-reply/reply/agent-runner.ts index d4e7ba652..d25aac8e6 100644 --- a/src/auto-reply/reply/agent-runner.ts +++ b/src/auto-reply/reply/agent-runner.ts @@ -401,8 +401,25 @@ export async function runReplyAgent(params: { const sanitizedPayloads = isHeartbeat ? payloadArray : payloadArray.flatMap((payload) => { - const text = payload.text; - if (!text || !text.includes("HEARTBEAT_OK")) return [payload]; + let text = payload.text; + + if (payload.isError) { + // Handle Bun fetch socket connection error that may indicate a context length issue + // Error source: https://github.com/oven-sh/bun/blob/main/src/bun.js/webcore/fetch/FetchTasklet.zig + const isBunFetchSocketError = + text === + "The socket connection was closed unexpectedly. For more information, pass `verbose: true` in the second argument to fetch()"; + + if (isBunFetchSocketError) { + text = `⚠️ LLM connection failed. This could be due to server issues, network problems, or context length exceeded (e.g., with local LLMs like LM Studio). Original error: + \`\`\` + ${text || "Unknown error"} + \`\`\``; + } + } + + if (!text || !text.includes("HEARTBEAT_OK")) + return [{ ...payload, text }]; const stripped = stripHeartbeatToken(text, { mode: "message" }); if (stripped.didStrip && !didLogHeartbeatStrip) { didLogHeartbeatStrip = true;