feat: broadcast pilot agent traces via WebSocket for live status on reconnect
Agent trace logs are now stored in-memory (pilotRunStore) and broadcast through the existing /ws/crm-updates WebSocket channel. When a client reconnects, it receives a pilot.catchup with all accumulated logs so the user sees agent progress even after page reload. Three new WS event types: pilot.trace, pilot.finished, pilot.catchup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,10 +9,14 @@ export type RealtimeNewMessage = {
|
||||
at: string;
|
||||
};
|
||||
|
||||
export type RealtimePilotTrace = { text: string; at: string };
|
||||
|
||||
export function useCrmRealtime(opts: {
|
||||
isAuthenticated: () => boolean;
|
||||
onDashboardChanged: () => Promise<void>;
|
||||
onNewMessage?: (msg: RealtimeNewMessage) => void;
|
||||
onPilotTrace?: (log: RealtimePilotTrace) => void;
|
||||
onPilotFinished?: () => void;
|
||||
}) {
|
||||
const crmRealtimeState = ref<"idle" | "connecting" | "open" | "error">("idle");
|
||||
let crmRealtimeSocket: WebSocket | null = null;
|
||||
@@ -116,6 +120,17 @@ export function useCrmRealtime(opts: {
|
||||
if (payload.type === "message.new" && opts.onNewMessage) {
|
||||
opts.onNewMessage(payload as unknown as RealtimeNewMessage);
|
||||
}
|
||||
if (payload.type === "pilot.trace" && opts.onPilotTrace) {
|
||||
opts.onPilotTrace({ text: String(payload.text ?? ""), at: String(payload.at ?? "") });
|
||||
}
|
||||
if (payload.type === "pilot.catchup" && opts.onPilotTrace && Array.isArray(payload.logs)) {
|
||||
for (const log of payload.logs) {
|
||||
opts.onPilotTrace({ text: String((log as any).text ?? ""), at: String((log as any).at ?? "") });
|
||||
}
|
||||
}
|
||||
if (payload.type === "pilot.finished" && opts.onPilotFinished) {
|
||||
opts.onPilotFinished();
|
||||
}
|
||||
} catch {
|
||||
// ignore malformed realtime payloads
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user