feat(web): React SPA with realtime task detail over WebSocket
Vite + React 19 + TS console-style operator UI: hash-routed Login, Endpoints, Tasks, and TaskDetail (realtime accounts table over /ws, Run gated on all accounts testing ok on both sides). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MMHQTtnQtQqL8muAXHr9kd
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// Live task event stream. One socket per task-detail view.
|
||||
|
||||
export type TaskEventType =
|
||||
| 'run_started'
|
||||
| 'account_started'
|
||||
| 'account_test'
|
||||
| 'progress'
|
||||
| 'account_done'
|
||||
| 'error'
|
||||
| 'run_done'
|
||||
| string
|
||||
|
||||
export interface TaskEvent {
|
||||
type: TaskEventType
|
||||
task_id: number
|
||||
data: unknown
|
||||
}
|
||||
|
||||
export function connectTaskWS(taskId: number, onEvent: (ev: TaskEvent) => void): () => void {
|
||||
const proto = location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
const ws = new WebSocket(`${proto}://${location.host}/ws?task_id=${taskId}`)
|
||||
ws.onmessage = (m) => {
|
||||
try {
|
||||
onEvent(JSON.parse(m.data))
|
||||
} catch {
|
||||
// ignore malformed frames
|
||||
}
|
||||
}
|
||||
return () => ws.close()
|
||||
}
|
||||
Reference in New Issue
Block a user