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
+11 -6
View File
@@ -46,7 +46,7 @@ import { Settings } from "./Settings";
import { CcConfig } from "./CcConfig";
import { CodexConfig } from "./CodexConfig";
import { AiToolConfig } from "./AiToolConfig";
import { AiRouterConfig } from "./AiRouterConfig";
import { AiProxyConfig } from "./AiProxyConfig";
import { GitCredentialsConfig } from "./GitCredentialsConfig";
import { AppearanceSettings } from "../components/settings/AppearanceSettings";
import { SnapshotSettings } from "../components/settings/SnapshotSettings";
@@ -82,7 +82,7 @@ const LEGACY_TOOL: Record<string, string> = {
dashboard: "appearance",
"claude-code": "agents/claude-code",
codex: "agents/codex",
"ai-router": "ai-router",
"ai-router": "ai-proxy",
"git-credentials": "git-credentials",
};
@@ -117,7 +117,12 @@ function toolNavIcon(id: string, label: string) {
return Icon;
}
const MOVED: Record<string, string> = { general: "appearance", pet: "appearance#pet" };
const MOVED: Record<string, string> = {
general: "appearance",
pet: "appearance#pet",
// The AI Router → AI Proxy rename.
"ai-router": "ai-proxy",
};
/** An unknown section: say so, then show Appearance. */
function UnknownSection({ name }: { name: string }) {
@@ -290,11 +295,11 @@ export function SettingsHub() {
render: () => <AiToolConfig key={x.id} toolId={x.id} />,
})),
{
id: "ai-router",
id: "ai-proxy",
group: "routing",
Icon: Router,
...s("aiRouter"),
render: () => <AiRouterConfig />,
...s("aiProxy"),
render: () => <AiProxyConfig />,
},
{
id: "pricing",