diff --git a/src/cli/run/events.test.ts b/src/cli/run/events.test.ts index 84b025c..bcf9fd5 100644 --- a/src/cli/run/events.test.ts +++ b/src/cli/run/events.test.ts @@ -74,6 +74,8 @@ describe("event handling", () => { const ctx = createMockContext("my-session") const state: EventState = { mainSessionIdle: true, + mainSessionError: false, + lastError: null, lastOutput: "", lastPartText: "", currentTool: null, diff --git a/src/cli/run/events.ts b/src/cli/run/events.ts index 9a43e2d..176a842 100644 --- a/src/cli/run/events.ts +++ b/src/cli/run/events.ts @@ -4,6 +4,7 @@ import type { EventPayload, SessionIdleProps, SessionStatusProps, + SessionErrorProps, MessageUpdatedProps, MessagePartUpdatedProps, ToolExecuteProps, @@ -12,6 +13,8 @@ import type { export interface EventState { mainSessionIdle: boolean + mainSessionError: boolean + lastError: string | null lastOutput: string lastPartText: string currentTool: string | null @@ -20,6 +23,8 @@ export interface EventState { export function createEventState(): EventState { return { mainSessionIdle: false, + mainSessionError: false, + lastError: null, lastOutput: "", lastPartText: "", currentTool: null, @@ -43,6 +48,7 @@ export async function processEvents( logEventVerbose(ctx, payload) + handleSessionError(ctx, payload, state) handleSessionIdle(ctx, payload, state) handleSessionStatus(ctx, payload, state) handleMessagePartUpdated(ctx, payload, state) @@ -154,6 +160,23 @@ function handleSessionStatus( } } +function handleSessionError( + ctx: RunContext, + payload: EventPayload, + state: EventState +): void { + if (payload.type !== "session.error") return + + const props = payload.properties as SessionErrorProps | undefined + if (props?.sessionID === ctx.sessionID) { + state.mainSessionError = true + state.lastError = props?.error + ? String(props.error instanceof Error ? props.error.message : props.error) + : "Unknown error" + console.error(pc.red(`\n[session.error] ${state.lastError}`)) + } +} + function handleMessagePartUpdated( ctx: RunContext, payload: EventPayload, diff --git a/src/cli/run/runner.ts b/src/cli/run/runner.ts index 6bd5d03..f245fd2 100644 --- a/src/cli/run/runner.ts +++ b/src/cli/run/runner.ts @@ -87,6 +87,16 @@ export async function run(options: RunOptions): Promise { continue } + // Check if session errored - exit with failure if so + if (eventState.mainSessionError) { + console.error(pc.red(`\n\nSession ended with error: ${eventState.lastError}`)) + console.error(pc.yellow("Check if todos were completed before the error.")) + abortController.abort() + await eventProcessor.catch(() => {}) + cleanup() + return 1 + } + const shouldExit = await checkCompletionConditions(ctx) if (shouldExit) { console.log(pc.green("\n\nAll tasks completed.")) diff --git a/src/cli/run/types.ts b/src/cli/run/types.ts index c1218f9..2d2a50e 100644 --- a/src/cli/run/types.ts +++ b/src/cli/run/types.ts @@ -69,3 +69,8 @@ export interface ToolResultProps { name?: string output?: string } + +export interface SessionErrorProps { + sessionID?: string + error?: unknown +}