fix: restore complete source code and fix launchers
- Copy complete source code packages from original CodeNomad project - Add root package.json with npm workspace configuration - Include electron-app, server, ui, tauri-app, and opencode-config packages - Fix Launch-Windows.bat and Launch-Dev-Windows.bat to work with correct npm scripts - Fix Launch-Unix.sh to work with correct npm scripts - Launchers now correctly call npm run dev:electron which launches Electron app
This commit is contained in:
66
packages/ui/src/lib/server-events.ts
Normal file
66
packages/ui/src/lib/server-events.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import type { WorkspaceEventPayload, WorkspaceEventType } from "../../../server/src/api-types"
|
||||
import { serverApi } from "./api-client"
|
||||
import { getLogger } from "./logger"
|
||||
|
||||
const RETRY_BASE_DELAY = 1000
|
||||
const RETRY_MAX_DELAY = 10000
|
||||
const log = getLogger("sse")
|
||||
|
||||
function logSse(message: string, context?: Record<string, unknown>) {
|
||||
if (context) {
|
||||
log.info(message, context)
|
||||
return
|
||||
}
|
||||
log.info(message)
|
||||
}
|
||||
|
||||
class ServerEvents {
|
||||
private handlers = new Map<WorkspaceEventType | "*", Set<(event: WorkspaceEventPayload) => void>>()
|
||||
private source: EventSource | null = null
|
||||
private retryDelay = RETRY_BASE_DELAY
|
||||
|
||||
constructor() {
|
||||
this.connect()
|
||||
}
|
||||
|
||||
private connect() {
|
||||
if (this.source) {
|
||||
this.source.close()
|
||||
}
|
||||
logSse("Connecting to backend events stream")
|
||||
this.source = serverApi.connectEvents((event) => this.dispatch(event), () => this.scheduleReconnect())
|
||||
this.source.onopen = () => {
|
||||
logSse("Events stream connected")
|
||||
this.retryDelay = RETRY_BASE_DELAY
|
||||
}
|
||||
}
|
||||
|
||||
private scheduleReconnect() {
|
||||
if (this.source) {
|
||||
this.source.close()
|
||||
this.source = null
|
||||
}
|
||||
logSse("Events stream disconnected, scheduling reconnect", { delayMs: this.retryDelay })
|
||||
setTimeout(() => {
|
||||
this.retryDelay = Math.min(this.retryDelay * 2, RETRY_MAX_DELAY)
|
||||
this.connect()
|
||||
}, this.retryDelay)
|
||||
}
|
||||
|
||||
private dispatch(event: WorkspaceEventPayload) {
|
||||
logSse(`event ${event.type}`)
|
||||
this.handlers.get("*")?.forEach((handler) => handler(event))
|
||||
this.handlers.get(event.type)?.forEach((handler) => handler(event))
|
||||
}
|
||||
|
||||
on(type: WorkspaceEventType | "*", handler: (event: WorkspaceEventPayload) => void): () => void {
|
||||
if (!this.handlers.has(type)) {
|
||||
this.handlers.set(type, new Set())
|
||||
}
|
||||
const bucket = this.handlers.get(type)!
|
||||
bucket.add(handler)
|
||||
return () => bucket.delete(handler)
|
||||
}
|
||||
}
|
||||
|
||||
export const serverEvents = new ServerEvents()
|
||||
Reference in New Issue
Block a user