diff --git a/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts index dec55480af30..2df65ed268f0 100644 --- a/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/GrokAdapterV2.test.ts @@ -118,6 +118,43 @@ describe("GrokAdapterV2 capabilities", () => { flavor.promptFailure?.(new Error("Rate limit mentioned in an ordinary error")).class, "provider_error", ); + assert.deepEqual( + flavor.promptFailure?.( + new EffectAcpErrors.AcpTransportError({ + operation: "call-rpc", + method: "session/prompt", + detail: "private provider diagnostic", + cause: new Error("api_key=synthetic-private-key"), + }), + ), + { + class: "transport_error", + message: "Grok connection failed. Retry the turn.", + code: null, + retryable: null, + }, + ); + assert.deepEqual(flavor.promptFailure?.(new EffectAcpErrors.AcpInputStreamEndedError({})), { + class: "transport_error", + message: "Grok connection failed. Retry the turn.", + code: null, + retryable: null, + }); + assert.deepEqual( + flavor.promptFailure?.( + new EffectAcpErrors.AcpProcessExitedError({ + code: 1, + stderr: "private provider diagnostic", + }), + ), + { + class: "transport_error", + message: + "The provider process exited with code 1. Check the server logs for the provider's output, then retry the turn.", + code: null, + retryable: null, + }, + ); }); it("terminalizes only foreground tools under the actual Grok flavor", () => { diff --git a/packages/provider-grok/src/server/adapter.ts b/packages/provider-grok/src/server/adapter.ts index 9ed1368f1698..48973b2ecc3b 100644 --- a/packages/provider-grok/src/server/adapter.ts +++ b/packages/provider-grok/src/server/adapter.ts @@ -86,6 +86,13 @@ const GROK_DRIVER_KIND = GROK_PROVIDER; export const GROK_DEFAULT_INSTANCE_ID = defaultInstanceIdForDriver(GROK_DRIVER_KIND); const DEFAULT_GROK_SETTINGS = Schema.decodeSync(GrokSettings)({}); const isAcpRequestError = Schema.is(EffectAcpErrors.AcpRequestError); +const isAcpConnectionError = Schema.is( + Schema.Union([ + EffectAcpErrors.AcpTransportError, + EffectAcpErrors.AcpInputStreamEndedError, + EffectAcpErrors.AcpProcessExitedError, + ]), +); const GrokProviderCapabilitiesV2 = { ...AcpProviderCapabilitiesV2, @@ -314,7 +321,14 @@ export function makeGrokAcpAdapterFlavor( code: String(cause.code), class: cause.code === xAiRateLimitedErrorCode ? "usage_limit" : "provider_error", } - : { class: "provider_error" }), + : isAcpConnectionError(cause) + ? { + class: "transport_error", + ...(cause._tag === "AcpProcessExitedError" + ? {} + : { message: "Grok connection failed. Retry the turn." }), + } + : { class: "provider_error" }), }), registerExtensions: registerGrokAcpExtensions, extractSubagentUpdate: extractXAiAcpSubagentUpdate,