- Refactor session state to use ptySessionId as primary key across all components - Add SessionStateManager with PTY-scoped hook processing, approval tracking, notifications - Add sync-engine debug panel (AgentStatesSection, HookTimelineSection, TerminalRegistrySection, WsMonitorSection) - Add useLifecycleStates composable for continuous state chips (session, responding, tool, subagent, compacting) - Add WS monitor endpoint and composable for real-time connection health - Enhance SessionLifecycleStatus with animated state chips and badge counts - Enhance SystemMessage with expanded content and better formatting - Update hooks (approval-permission, approval-plan, notify) with pty_session injection - Update approval system to derive pending lists from PTY-scoped state - Update ChatContainer with PTY-derived agent status and lifecycle events - Update AgentBadge with PTY-scoped status colors - Improve PiP window, approval window, and loading window handling
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
import { jsonResponse, errorResponse } from '../utils/cors'
|
|
import { PORT_TERMINAL, PORT_GIT } from '../config'
|
|
|
|
/**
|
|
* Proxy GET /api/ws-monitor → terminal server + sync server health.
|
|
* Returns combined WebSocket connection stats from both servers.
|
|
*/
|
|
export async function handleWsMonitor(): Promise<Response> {
|
|
const controller = new AbortController()
|
|
const timeout = setTimeout(() => controller.abort(), 4000)
|
|
|
|
try {
|
|
const [terminalResp, syncResp] = await Promise.allSettled([
|
|
fetch(`http://localhost:${PORT_TERMINAL}/health`, { signal: controller.signal }),
|
|
fetch(`http://localhost:${PORT_GIT}/health`, { signal: controller.signal })
|
|
])
|
|
|
|
const terminalData = terminalResp.status === 'fulfilled' && terminalResp.value.ok
|
|
? await terminalResp.value.json()
|
|
: null
|
|
|
|
const syncData = syncResp.status === 'fulfilled' && syncResp.value.ok
|
|
? await syncResp.value.json()
|
|
: null
|
|
|
|
return jsonResponse({
|
|
terminal: {
|
|
status: terminalData?.status ?? 'unreachable',
|
|
sessions: terminalData?.sessions ?? [],
|
|
broadcastClients: terminalData?.broadcastClients ?? 0,
|
|
cwd: terminalData?.cwd ?? null,
|
|
},
|
|
sync: {
|
|
status: syncData?.status ?? 'unreachable',
|
|
clients: syncData?.clients ?? 0,
|
|
torch: syncData?.torch ?? null,
|
|
},
|
|
timestamp: Date.now(),
|
|
})
|
|
} catch (e: any) {
|
|
const msg = e.name === 'AbortError'
|
|
? 'Server health timeout (4s)'
|
|
: `Failed to reach servers: ${e.message}`
|
|
return errorResponse(msg, 502)
|
|
} finally {
|
|
clearTimeout(timeout)
|
|
}
|
|
}
|