diff --git a/packages/coding-agent/src/core/agent-session.ts b/packages/coding-agent/src/core/agent-session.ts index 5cdc76d7..d02a5dd5 100644 --- a/packages/coding-agent/src/core/agent-session.ts +++ b/packages/coding-agent/src/core/agent-session.ts @@ -435,6 +435,11 @@ export class AgentSession { return this.agent.state.isStreaming; } + /** Current retry attempt (0 if not retrying) */ + get retryAttempt(): number { + return this._retryAttempt; + } + /** * Get the names of currently active tools. * Returns the names of tools currently set on the agent. diff --git a/packages/coding-agent/src/modes/interactive/components/assistant-message.ts b/packages/coding-agent/src/modes/interactive/components/assistant-message.ts index 01c919f3..399f834e 100644 --- a/packages/coding-agent/src/modes/interactive/components/assistant-message.ts +++ b/packages/coding-agent/src/modes/interactive/components/assistant-message.ts @@ -31,12 +31,11 @@ export class AssistantMessageComponent extends Container { // Clear content container this.contentContainer.clear(); - if ( - message.content.length > 0 && - message.content.some( - (c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()), - ) - ) { + const hasVisibleContent = message.content.some( + (c) => (c.type === "text" && c.text.trim()) || (c.type === "thinking" && c.thinking.trim()), + ); + + if (hasVisibleContent) { this.contentContainer.addChild(new Spacer(1)); } @@ -75,7 +74,12 @@ export class AssistantMessageComponent extends Container { const hasToolCalls = message.content.some((c) => c.type === "toolCall"); if (!hasToolCalls) { if (message.stopReason === "aborted") { - this.contentContainer.addChild(new Text(theme.fg("error", "\nAborted"), 1, 0)); + const abortMessage = + message.errorMessage && message.errorMessage !== "Request was aborted" + ? message.errorMessage + : "Operation aborted"; + const prefix = hasVisibleContent ? "\n" : ""; + this.contentContainer.addChild(new Text(theme.fg("error", `${prefix}${abortMessage}`), 1, 0)); } else if (message.stopReason === "error") { const errorMsg = message.errorMessage || "Unknown error"; this.contentContainer.addChild(new Spacer(1)); diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index d32d2d34..d7528ad2 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -1559,13 +1559,21 @@ export class InteractiveMode { if (event.message.role === "user") break; if (this.streamingComponent && event.message.role === "assistant") { this.streamingMessage = event.message; + let errorMessage: string | undefined; + if (this.streamingMessage.stopReason === "aborted") { + const retryAttempt = this.session.retryAttempt; + errorMessage = + retryAttempt > 0 + ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}` + : "Operation aborted"; + this.streamingMessage.errorMessage = errorMessage; + } this.streamingComponent.updateContent(this.streamingMessage); if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") { - const errorMessage = - this.streamingMessage.stopReason === "aborted" - ? "Operation aborted" - : this.streamingMessage.errorMessage || "Error"; + if (!errorMessage) { + errorMessage = this.streamingMessage.errorMessage || "Error"; + } for (const [, component] of this.pendingTools.entries()) { component.updateResult({ content: [{ type: "text", text: errorMessage }], @@ -1872,8 +1880,16 @@ export class InteractiveMode { this.chatContainer.addChild(component); if (message.stopReason === "aborted" || message.stopReason === "error") { - const errorMessage = - message.stopReason === "aborted" ? "Operation aborted" : message.errorMessage || "Error"; + let errorMessage: string; + if (message.stopReason === "aborted") { + const retryAttempt = this.session.retryAttempt; + errorMessage = + retryAttempt > 0 + ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}` + : "Operation aborted"; + } else { + errorMessage = message.errorMessage || "Error"; + } component.updateResult({ content: [{ type: "text", text: errorMessage }], isError: true }); } else { this.pendingTools.set(content.id, component);