From 27c6d5a3bb0aed4150c0577976f2dcca5ab70122 Mon Sep 17 00:00:00 2001 From: DhanushSantosh Date: Tue, 6 Jan 2026 14:10:48 +0530 Subject: [PATCH] refactor: improve error handling and CLI integration - Updated CodexProvider to read prompts from stdin to prevent shell escaping issues. - Enhanced AgentService to handle streamed error messages from providers, ensuring a consistent user experience. - Modified UI components to display error messages clearly, including visual indicators for errors in chat bubbles. - Updated CLI status handling to support both Claude and Codex APIs, improving compatibility and user feedback. These changes enhance the robustness of the application and improve the user experience during error scenarios. --- apps/server/src/providers/codex-provider.ts | 3 +- apps/server/src/services/agent-service.ts | 49 +++++++++++++++++++ apps/ui/src/components/views/agent-view.tsx | 1 - .../agent-view/components/agent-header.tsx | 3 -- .../views/agent-view/components/chat-area.tsx | 1 + .../agent-view/components/message-bubble.tsx | 40 +++++++++++---- .../kanban-card/agent-info-panel.tsx | 12 +++-- .../components/kanban-card/card-header.tsx | 36 +++++++++----- .../views/setup-view/hooks/use-cli-status.ts | 7 ++- .../setup-view/steps/claude-setup-step.tsx | 6 +-- .../setup-view/steps/cursor-setup-step.tsx | 6 +-- apps/ui/src/hooks/use-electron-agent.ts | 11 +++++ libs/platform/src/subprocess.ts | 8 +++ 13 files changed, 145 insertions(+), 38 deletions(-) diff --git a/apps/server/src/providers/codex-provider.ts b/apps/server/src/providers/codex-provider.ts index 4f1f2c35..60db38c1 100644 --- a/apps/server/src/providers/codex-provider.ts +++ b/apps/server/src/providers/codex-provider.ts @@ -765,7 +765,7 @@ export class CodexProvider extends BaseProvider { ...(outputSchemaPath ? [CODEX_OUTPUT_SCHEMA_FLAG, outputSchemaPath] : []), ...(imagePaths.length > 0 ? [CODEX_IMAGE_FLAG, imagePaths.join(',')] : []), ...configOverrides, - promptText, + '-', // Read prompt from stdin to avoid shell escaping issues ]; const stream = spawnJSONLProcess({ @@ -775,6 +775,7 @@ export class CodexProvider extends BaseProvider { env: buildEnv(), abortController: options.abortController, timeout: DEFAULT_TIMEOUT_MS, + stdinData: promptText, // Pass prompt via stdin }); for await (const rawEvent of stream) { diff --git a/apps/server/src/services/agent-service.ts b/apps/server/src/services/agent-service.ts index 7736fd6a..3c7fc184 100644 --- a/apps/server/src/services/agent-service.ts +++ b/apps/server/src/services/agent-service.ts @@ -13,6 +13,8 @@ import { isAbortError, loadContextFiles, createLogger, + classifyError, + getUserFriendlyErrorMessage, } from '@automaker/utils'; import { ProviderFactory } from '../providers/provider-factory.js'; import { createChatOptions, validateWorkingDirectory } from '../lib/sdk-options.js'; @@ -374,6 +376,53 @@ export class AgentService { content: responseText, toolUses, }); + } else if (msg.type === 'error') { + // Some providers (like Codex CLI/SaaS or Cursor CLI) surface failures as + // streamed error messages instead of throwing. Handle these here so the + // Agent Runner UX matches the Claude/Cursor behavior without changing + // their provider implementations. + const rawErrorText = + (typeof msg.error === 'string' && msg.error.trim()) || + 'Unexpected error from provider during agent execution.'; + + const errorInfo = classifyError(new Error(rawErrorText)); + + // Keep the provider-supplied text intact (Codex already includes helpful tips), + // only add a small rate-limit hint when we can detect it. + const enhancedText = errorInfo.isRateLimit + ? `${rawErrorText}\n\nTip: It looks like you hit a rate limit. Try waiting a bit or reducing concurrent Agent Runner / Auto Mode tasks.` + : rawErrorText; + + this.logger.error('Provider error during agent execution:', { + type: errorInfo.type, + message: errorInfo.message, + }); + + // Mark session as no longer running so the UI and queue stay in sync + session.isRunning = false; + session.abortController = null; + + const errorMessage: Message = { + id: this.generateId(), + role: 'assistant', + content: `Error: ${enhancedText}`, + timestamp: new Date().toISOString(), + isError: true, + }; + + session.messages.push(errorMessage); + await this.saveSession(sessionId, session.messages); + + this.emitAgentEvent(sessionId, { + type: 'error', + error: enhancedText, + message: errorMessage, + }); + + // Don't continue streaming after an error message + return { + success: false, + }; } } diff --git a/apps/ui/src/components/views/agent-view.tsx b/apps/ui/src/components/views/agent-view.tsx index b70e32d9..be56f70d 100644 --- a/apps/ui/src/components/views/agent-view.tsx +++ b/apps/ui/src/components/views/agent-view.tsx @@ -161,7 +161,6 @@ export function AgentView() { isConnected={isConnected} isProcessing={isProcessing} currentTool={currentTool} - agentError={agentError} messagesCount={messages.length} showSessionManager={showSessionManager} onToggleSessionManager={() => setShowSessionManager(!showSessionManager)} diff --git a/apps/ui/src/components/views/agent-view/components/agent-header.tsx b/apps/ui/src/components/views/agent-view/components/agent-header.tsx index ee020ac5..a6152736 100644 --- a/apps/ui/src/components/views/agent-view/components/agent-header.tsx +++ b/apps/ui/src/components/views/agent-view/components/agent-header.tsx @@ -7,7 +7,6 @@ interface AgentHeaderProps { isConnected: boolean; isProcessing: boolean; currentTool: string | null; - agentError: string | null; messagesCount: number; showSessionManager: boolean; onToggleSessionManager: () => void; @@ -20,7 +19,6 @@ export function AgentHeader({ isConnected, isProcessing, currentTool, - agentError, messagesCount, showSessionManager, onToggleSessionManager, @@ -61,7 +59,6 @@ export function AgentHeader({ {currentTool} )} - {agentError && {agentError}} {currentSessionId && messagesCount > 0 && (