diff --git a/src/components/turn.tsx b/src/components/turn.tsx index d9742c7..5e0541b 100644 --- a/src/components/turn.tsx +++ b/src/components/turn.tsx @@ -1,6 +1,7 @@ import { ArrowDownToLine, ArrowUpToLine, + CircleAlert, Clock, CornerDownRight, MessageSquare, @@ -72,6 +73,19 @@ function StepEntries({ step }: { step: Step }) { ); } +function TurnError({ error }: { error: NonNullable }) { + return ( + }> +
+

{error.message}

+ + {error.code} + +
+
+ ); +} + export function Turn({ turn, index }: { turn: TurnData; index: number }) { return (
@@ -85,6 +99,7 @@ export function Turn({ turn, index }: { turn: TurnData; index: number }) { {turn.steps.map((step) => ( ))} + {turn.error !== undefined && }
); diff --git a/src/trace/events.ts b/src/trace/events.ts index 71a326f..8444c5d 100644 --- a/src/trace/events.ts +++ b/src/trace/events.ts @@ -1,4 +1,4 @@ -import type { Usage } from "@/trace/types"; +import type { TraceError, Usage } from "@/trace/types"; // Structural types for the eve stream events the devtools consume, declared // locally so the package does not depend on eve itself and tolerates fields @@ -19,7 +19,7 @@ export type ActionRequest = { type TraceEventBody = | { type: "turn.started"; data: { turnId: string } } | { type: "turn.completed"; data: { turnId: string } } - | { type: "turn.failed"; data: { turnId: string } } + | { type: "turn.failed"; data: { turnId: string } & TraceError } | { type: "message.received"; data: { turnId: string; message: string } } | { type: "step.started"; data: { turnId: string; stepIndex: number } } | { diff --git a/src/trace/projector.ts b/src/trace/projector.ts index 8b6d240..90c8145 100644 --- a/src/trace/projector.ts +++ b/src/trace/projector.ts @@ -161,6 +161,11 @@ export function createProjector(onChange: (turns: Turn[]) => void): Projector { const turn = turnById(event.data.turnId); if (turn !== undefined) { turn.status = "failed"; + turn.error = { + code: event.data.code, + message: event.data.message, + details: event.data.details, + }; turn.durationMs = millisBetween(turn.startedAt, event.meta?.at); } abortRunningActions(); diff --git a/src/trace/types.ts b/src/trace/types.ts index d9a6992..8de785e 100644 --- a/src/trace/types.ts +++ b/src/trace/types.ts @@ -13,6 +13,12 @@ export type Usage = { outputTokens?: number; }; +export type TraceError = { + code: string; + message: string; + details?: unknown; +}; + export type Action = { callId: string; name: string; @@ -34,6 +40,7 @@ export type Step = { export type Turn = { id: string; status: TurnStatus; + error?: TraceError; prompt?: string; startedAt?: string; // ISO timestamp, from the event's `meta.at` durationMs?: number;