feat: v2.5.5 — AI Router renamed AI Proxy, reload onto new builds, update no longer spins

AI Proxy (was AI Router):
- server/lib/ai-proxies.js, proxy-apply.js, routes/ai-proxies.js mounted at
  /api/ai-proxies and the old /api/ai-routers; `router` still accepted on the
  start routes; profiles move to <CLAUDE_HOME>/agenthub-proxies/
- dashboard_runs.router renamed in place to proxy: an older build on the same
  DB fails on that column, so dev and prod sharing one DB update together
- a proxy's baseUrl stored as its root (a typed /v1 made /v1/v1/messages);
  Test probes Claude /v1/messages and Codex /v1/responses
- Settings → AI Proxy (/settings/ai-router redirects), ProxyPicker

Updates:
- every tab reloads onto the new UI build when its WebSocket reconnects to a
  server of another version (lib/newBuildReload.ts, once per version)
- Update now stops waiting on a plugin chain that failed or pulled nothing
  (the old server never goes down), and reloads as soon as a new version answers

Also:
- a pane whose command exits at once says so (EPANEEXITED) instead of
  "Command failed: tmux set-option … mouse on"
- the pane drag preview draws where the pane actually lands
This commit is contained in:
2026-10-06 22:48:09 +07:00
parent dd9b23106c
commit 5fe5d51b1b
82 changed files with 1792 additions and 1412 deletions
+6 -5
View File
@@ -82,7 +82,7 @@ const importRouter = require("./routes/import");
const updatesRouter = require("./routes/updates");
const ccConfigRouter = require("./routes/cc-config");
const codexConfigRouter = require("./routes/codex-config");
const aiRoutersRouter = require("./routes/ai-routers");
const aiProxiesRouter = require("./routes/ai-proxies");
const gitCredentialsRouter = require("./routes/git-credentials");
const aiToolsRouter = require("./routes/ai-tools");
const runRouter = require("./routes/run");
@@ -133,7 +133,8 @@ function createApp() {
app.use("/api/updates", updatesRouter);
app.use("/api/cc-config", ccConfigRouter);
app.use("/api/codex-config", codexConfigRouter);
app.use("/api/ai-routers", aiRoutersRouter);
// `/api/ai-routers` is the pre-rename path, kept for a client older than it.
app.use(["/api/ai-proxies", "/api/ai-routers"], aiProxiesRouter);
app.use("/api/git-credentials", gitCredentialsRouter);
app.use("/api/ai-tools", aiToolsRouter);
app.use("/api/run", runRouter);
@@ -680,12 +681,12 @@ function startBackgroundServices() {
} catch (err) {
console.warn("dashboard-runs reconciliation failed:", err.message);
}
// A router is chosen per session now: take the old per-workspace one out of
// A proxy is chosen per session now: take the old per-workspace one out of
// each workspace's settings.local.json (a no-op once done).
try {
require("./lib/router-apply").clearLaneRouters();
require("./lib/proxy-apply").clearLaneProxies();
} catch (err) {
console.warn("clearing workspace routers failed:", err.message);
console.warn("clearing workspace proxies failed:", err.message);
}
}