* feat(gateway): support hot reload and empty startup - extract gateway runtime into pkg/gateway - add gateway.hot_reload config with default and example values - allow starting the gateway without a default model via --allow-empty - stop treating missing enabled channels as a startup error - update related tests * feat: replace gateway SSE updates with polling-based state sync - remove gateway SSE broadcasting and event endpoint - add polling-based gateway status refresh with stopping state handling - detect when gateway restart is required after default model changes - resolve gateway health and websocket proxy targets from configured host - update gateway UI labels and add backend/frontend test coverage
74 lines
1.8 KiB
TypeScript
74 lines
1.8 KiB
TypeScript
import { useAtomValue } from "jotai"
|
|
import { useCallback, useEffect, useState } from "react"
|
|
|
|
import { restartGateway, startGateway, stopGateway } from "@/api/gateway"
|
|
import {
|
|
beginGatewayStoppingTransition,
|
|
cancelGatewayStoppingTransition,
|
|
gatewayAtom,
|
|
refreshGatewayState,
|
|
subscribeGatewayPolling,
|
|
updateGatewayStore,
|
|
} from "@/store"
|
|
|
|
export function useGateway() {
|
|
const gateway = useAtomValue(gatewayAtom)
|
|
const { status: state, canStart, restartRequired } = gateway
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
useEffect(() => {
|
|
return subscribeGatewayPolling()
|
|
}, [])
|
|
|
|
const start = useCallback(async () => {
|
|
if (!canStart) return
|
|
|
|
setLoading(true)
|
|
try {
|
|
await startGateway()
|
|
updateGatewayStore({
|
|
status: "starting",
|
|
restartRequired: false,
|
|
})
|
|
} catch (err) {
|
|
console.error("Failed to start gateway:", err)
|
|
} finally {
|
|
await refreshGatewayState({ force: true })
|
|
setLoading(false)
|
|
}
|
|
}, [canStart])
|
|
|
|
const stop = useCallback(async () => {
|
|
setLoading(true)
|
|
beginGatewayStoppingTransition()
|
|
try {
|
|
await stopGateway()
|
|
} catch (err) {
|
|
console.error("Failed to stop gateway:", err)
|
|
cancelGatewayStoppingTransition()
|
|
} finally {
|
|
await refreshGatewayState({ force: true })
|
|
setLoading(false)
|
|
}
|
|
}, [])
|
|
|
|
const restart = useCallback(async () => {
|
|
if (state !== "running") return
|
|
|
|
setLoading(true)
|
|
try {
|
|
await restartGateway()
|
|
updateGatewayStore({
|
|
status: "restarting",
|
|
restartRequired: false,
|
|
})
|
|
} catch (err) {
|
|
console.error("Failed to restart gateway:", err)
|
|
} finally {
|
|
await refreshGatewayState({ force: true })
|
|
setLoading(false)
|
|
}
|
|
}, [state])
|
|
|
|
return { state, loading, canStart, restartRequired, start, stop, restart }
|
|
}
|