Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | // Copied from userscripts/src/conversation-types.ts to avoid creating a shared package.
// This is a temporary solution until a shared types package is introduced.
export interface Turn {
id: string;
role: 'user' | 'model';
content: string;
thoughts?: string;
}
export interface Conversation {
id: string;
title: string;
model: string;
turns: Turn[];
}
// End copied content
/**
* Defines the structure for all WebSocket events in the system.
* This type is duplicated across frontend, backend, and userscripts.
* Any changes here must be synchronized.
*/
export type WebSocketEvent =
| { event: 'refresh-ui'; data: { sessionId?: string } }
| { event: 'update-chat'; data: { requestBody: Conversation } }
| { event: 'plan-ready'; data: { sessionId: string; sessionInputId: string } }
| { event: 'external-new-session'; data: Record<string, never> }
| {
event: 'system-prompt-update';
data: { systemPrompt: string };
}
| { event: 'session-created'; data: { sessionId: string } }
| { event: 'llm-input-generated'; data: { prompt: string } }
| {
event: 'llm-stream-chunk';
data: { sessionInputId: string; chunk: string; isFirst: boolean };
}
| {
event: 'llm-thought-chunk';
data: { sessionInputId: string; chunk: string; isFirst: boolean };
}
| {
event: 'llm-generation-started';
data: { sessionInputId: string; sessionId: string; isStreaming: boolean };
}
| { event: 'llm-generation-in-progress'; data: { sessionInputId: string } }
| {
event: 'llm-generation-ended';
data: { sessionInputId: string; sessionId: string; error?: string };
}
| {
event: 'llm-retry-attempt';
data: {
sessionInputId: string;
sessionId: string;
attempt: number;
maxAttempts: number;
};
};
export type WebSocketEventName = WebSocketEvent['event'];
/**
* A type guard to check if a parsed JSON object is a valid WebSocketEvent.
* @param obj The object to check.
* @returns True if the object is a valid WebSocketEvent, false otherwise.
*/
export function isWebSocketEvent(obj: unknown): obj is WebSocketEvent {
Iif (typeof obj !== 'object' || obj === null) {
return false;
}
const { event, data } = obj as { event: string; data: unknown };
Iif (typeof event !== 'string' || typeof data !== 'object') {
return false;
}
switch (event) {
case 'refresh-ui':
return true; // data can be {} or { sessionId: '...' }
case 'update-chat':
return data !== null && 'requestBody' in data;
case 'plan-ready':
return data !== null && 'sessionId' in data && 'sessionInputId' in data;
case 'external-new-session':
return true; // data is {}
case 'system-prompt-update':
return data !== null && 'systemPrompt' in data;
case 'session-created':
return data !== null && 'sessionId' in data;
case 'llm-input-generated':
return data !== null && 'prompt' in data;
case 'llm-stream-chunk':
return (
data !== null &&
'sessionInputId' in data &&
'chunk' in data &&
'isFirst' in data
);
case 'llm-thought-chunk':
return (
data !== null &&
'sessionInputId' in data &&
'chunk' in data &&
'isFirst' in data
);
case 'llm-generation-started':
return (
data !== null &&
'sessionInputId' in data &&
'sessionId' in data &&
'isStreaming' in data
);
case 'llm-generation-in-progress':
return data !== null && 'sessionInputId' in data;
case 'llm-generation-ended':
return data !== null && 'sessionInputId' in data && 'sessionId' in data;
case 'llm-retry-attempt':
return (
data !== null &&
'sessionInputId' in data &&
'sessionId' in data &&
'attempt' in data &&
'maxAttempts' in data
);
default:
return false;
}
}
|