Spaces:
Paused
Paused
icebear
refactor: decouple AccountPool, split codex-api and web.ts, fix CI (#113)
0c8b3c0 unverified | import { Hono } from "hono"; | |
| import { stream } from "hono/streaming"; | |
| import { getUpdateState, checkForUpdate, isUpdateInProgress } from "../../update-checker.js"; | |
| import { getProxyInfo, canSelfUpdate, checkProxySelfUpdate, applyProxySelfUpdate, isProxyUpdateInProgress, getCachedProxyUpdateResult, getDeployMode } from "../../self-update.js"; | |
| import { isEmbedded } from "../../paths.js"; | |
| export function createUpdateRoutes(): Hono { | |
| const app = new Hono(); | |
| app.get("/admin/update-status", (c) => { | |
| const proxyInfo = getProxyInfo(); | |
| const codexState = getUpdateState(); | |
| const cached = getCachedProxyUpdateResult(); | |
| return c.json({ | |
| proxy: { | |
| version: proxyInfo.version, | |
| commit: proxyInfo.commit, | |
| can_self_update: canSelfUpdate(), | |
| mode: getDeployMode(), | |
| commits_behind: cached?.commitsBehind ?? null, | |
| commits: cached?.commits ?? [], | |
| release: cached?.release ? { version: cached.release.version, body: cached.release.body, url: cached.release.url } : null, | |
| update_available: cached?.updateAvailable ?? false, | |
| update_in_progress: isProxyUpdateInProgress(), | |
| }, | |
| codex: { | |
| current_version: codexState?.current_version ?? null, | |
| current_build: codexState?.current_build ?? null, | |
| latest_version: codexState?.latest_version ?? null, | |
| latest_build: codexState?.latest_build ?? null, | |
| update_available: codexState?.update_available ?? false, | |
| update_in_progress: isUpdateInProgress(), | |
| last_check: codexState?.last_check ?? null, | |
| }, | |
| }); | |
| }); | |
| app.post("/admin/check-update", async (c) => { | |
| const results: { | |
| proxy?: { | |
| commits_behind: number; | |
| current_commit: string | null; | |
| latest_commit: string | null; | |
| commits: Array<{ hash: string; message: string }>; | |
| release: { version: string; body: string; url: string } | null; | |
| update_available: boolean; | |
| mode: string; | |
| error?: string; | |
| }; | |
| codex?: { update_available: boolean; current_version: string; latest_version: string | null; version_changed?: boolean; error?: string }; | |
| } = {}; | |
| try { | |
| const proxyResult = await checkProxySelfUpdate(); | |
| results.proxy = { | |
| commits_behind: proxyResult.commitsBehind, | |
| current_commit: proxyResult.currentCommit, | |
| latest_commit: proxyResult.latestCommit, | |
| commits: proxyResult.commits, | |
| release: proxyResult.release ? { version: proxyResult.release.version, body: proxyResult.release.body, url: proxyResult.release.url } : null, | |
| update_available: proxyResult.updateAvailable, | |
| mode: proxyResult.mode, | |
| }; | |
| } catch (err) { | |
| results.proxy = { | |
| commits_behind: 0, | |
| current_commit: null, | |
| latest_commit: null, | |
| commits: [], | |
| release: null, | |
| update_available: false, | |
| mode: getDeployMode(), | |
| error: err instanceof Error ? err.message : String(err), | |
| }; | |
| } | |
| if (!isEmbedded()) { | |
| try { | |
| const prevVersion = getUpdateState()?.current_version ?? null; | |
| const codexState = await checkForUpdate(); | |
| results.codex = { | |
| update_available: codexState.update_available, | |
| current_version: codexState.current_version, | |
| latest_version: codexState.latest_version, | |
| version_changed: prevVersion !== null && codexState.current_version !== prevVersion, | |
| }; | |
| } catch (err) { | |
| results.codex = { | |
| update_available: false, | |
| current_version: "unknown", | |
| latest_version: null, | |
| error: err instanceof Error ? err.message : String(err), | |
| }; | |
| } | |
| } | |
| return c.json({ | |
| ...results, | |
| proxy_update_in_progress: isProxyUpdateInProgress(), | |
| codex_update_in_progress: isUpdateInProgress(), | |
| }); | |
| }); | |
| app.post("/admin/apply-update", async (c) => { | |
| if (!canSelfUpdate()) { | |
| const mode = getDeployMode(); | |
| c.status(400); | |
| return c.json({ | |
| started: false, | |
| error: "Self-update not available in this deploy mode", | |
| mode, | |
| hint: mode === "docker" | |
| ? "Run: docker compose pull && docker compose up -d (or enable Watchtower for automatic updates)" | |
| : mode === "electron" | |
| ? "Updates are handled automatically by the desktop app. Check the system tray for update notifications, or restart the app to trigger a check." | |
| : "Git is not available in this environment", | |
| }); | |
| } | |
| c.header("Content-Type", "text/event-stream"); | |
| c.header("Cache-Control", "no-cache"); | |
| c.header("Connection", "keep-alive"); | |
| return stream(c, async (s) => { | |
| const send = (data: Record<string, unknown>) => s.write(`data: ${JSON.stringify(data)}\n\n`); | |
| const result = await applyProxySelfUpdate((step, status, detail) => { | |
| void send({ step, status, detail }); | |
| }); | |
| await send({ ...result, done: true }); | |
| }); | |
| }); | |
| return app; | |
| } | |