diff --git a/src/index.ts b/src/index.ts index 7b08550..80824de 100644 --- a/src/index.ts +++ b/src/index.ts @@ -44,6 +44,8 @@ export type { SDKReasoningMessage, SDKResultMessage, SDKStreamEventMessage, + SDKErrorMessage, + SDKRetryMessage, SkillSource, SleeptimeOptions, SleeptimeTrigger, diff --git a/src/session.ts b/src/session.ts index 11f3832..c3bc9b8 100644 --- a/src/session.ts +++ b/src/session.ts @@ -817,6 +817,44 @@ export class Session implements AsyncDisposable { }; } + // Error message — carries the actual error detail from the CLI. + // The subsequent type=result only has the opaque string "error"; + // this message has the human-readable description and API error. + if (wireMsg.type === "error") { + const msg = wireMsg as WireMessage & { + message: string; + stop_reason: string; + run_id?: string; + api_error?: Record; + }; + return { + type: "error" as const, + message: msg.message, + stopReason: msg.stop_reason, + runId: msg.run_id, + apiError: msg.api_error, + }; + } + + // Retry message — the CLI is retrying after a transient failure. + if (wireMsg.type === "retry") { + const msg = wireMsg as WireMessage & { + reason: string; + attempt: number; + max_attempts: number; + delay_ms: number; + run_id?: string; + }; + return { + type: "retry" as const, + reason: msg.reason, + attempt: msg.attempt, + maxAttempts: msg.max_attempts, + delayMs: msg.delay_ms, + runId: msg.run_id, + }; + } + // Skip other message types (system_message, user_message, etc.) return null; } diff --git a/src/types.ts b/src/types.ts index a6fc96e..54bf270 100644 --- a/src/types.ts +++ b/src/types.ts @@ -482,6 +482,41 @@ export interface SDKStreamEventMessage { uuid: string; } +/** + * Error message from the CLI — carries the actual error detail that + * would otherwise be lost (the subsequent `type=result` only has + * the opaque string "error" as its error field). + */ +export interface SDKErrorMessage { + type: "error"; + /** Human-readable error description from the CLI */ + message: string; + /** Why the run stopped (e.g. "error", "llm_api_error", "max_steps") */ + stopReason: string; + /** Run that produced the error, if available */ + runId?: string; + /** Nested Letta API error when the error originated server-side */ + apiError?: Record; +} + +/** + * Retry message — the CLI is retrying after a transient failure. + * Emitted before each retry attempt so consumers can log / display progress. + */ +export interface SDKRetryMessage { + type: "retry"; + /** The stop reason that triggered the retry */ + reason: string; + /** Current attempt number (1-based) */ + attempt: number; + /** Maximum attempts before giving up */ + maxAttempts: number; + /** Delay in ms before the next attempt */ + delayMs: number; + /** Run that triggered the retry, if available */ + runId?: string; +} + /** Union of all SDK message types */ export type SDKMessage = | SDKInitMessage @@ -490,7 +525,9 @@ export type SDKMessage = | SDKToolResultMessage | SDKReasoningMessage | SDKResultMessage - | SDKStreamEventMessage; + | SDKStreamEventMessage + | SDKErrorMessage + | SDKRetryMessage; // ═══════════════════════════════════════════════════════════════ // LIST MESSAGES API