feat: v2.5.12 — plan and quota for every AI tool, Grok Build and Kimi Code, Quit AgentHub (#65)

Usage panel (status bar):
- every account shows its plan (Claude subscriptionType, Codex
  chatgpt_plan_type, Cursor membershipType, Grok subscriptionTier)
- new quota rows: Cursor CLI (cursor.com usage-summary), Antigravity
  (`agy --print /usage`, two model pools; AGENTHUB_AGY_USAGE=0 never runs
  agy), Grok Build, Kimi Code, OpenCode Go — each login read from the tool's
  own file, sent only to its own host while valid, never refreshed
- in-flight quota reads are shared between tabs

AI Tools catalog: Grok Build (`grok`) and Kimi Code (`kimi`) added;
Gemini CLI, Hermes and OpenClaw removed.

Also: Quit AgentHub (#65, `agenthub stop`), status-area icon, Add to Chat
on an editor selection, Settings in three groups, JetBrains-style Changes
panel (ticked files/hunks, ignore, blame, file history), terminal font.

--no-verify: :3000 is taken by another dev server (lane-detect tests);
both suites run by hand — server 2636/2639 (the 3 are :3000), client
1131/1131.
This commit is contained in:
2026-10-08 12:22:14 +07:00
parent 6ef9a5d4b7
commit a9c71cd905
133 changed files with 8007 additions and 1830 deletions
+8 -2
View File
@@ -35,6 +35,7 @@ const crypto = require("crypto");
const { spawn, spawnSync } = require("child_process");
const { getDataDir, getClaudeHome, getSettingsPath } = require("../server/lib/claude-home");
const { isQuit } = require("../server/lib/quit");
const { getServerInfoPath } = require("../server/lib/server-info");
const { isOurEntry } = require("./install-hooks");
@@ -178,7 +179,8 @@ function fastPathOk(rt = runtimeDir()) {
// worker. (Observed: 271 PreToolUse events for ~135 real tool calls, and one
// Task spawning two subagent rows.)
if (hasLegacyHooks()) return false;
return serverIsLive();
// Quit (server/lib/quit.js): nothing to start until the user starts it.
return serverIsLive() || isQuit(rt);
}
/* ------------------------------------------------------- node version gate */
@@ -740,7 +742,11 @@ function bootstrap(rt = runtimeDir(), { force = false } = {}) {
// running process must be replaced"; `unitStale` is "the unit names a cache
// directory that is no longer this one", which is invisible until a reboot
// and must be repaired even while a perfectly healthy server is up.
const needsServer = movedRoot || !serverIsLive();
// A Quit holds every start off (an explicit `--force` from
// /agenthub-update overrides it); the unit is still repaired below.
const quit = !force && isQuit(rt);
if (quit) log(rt, "AgentHub was quit — not starting it (agenthub start brings it back)");
const needsServer = !quit && (movedRoot || !serverIsLive());
const unitStale = svc.unitIsStale("agenthub", PLUGIN_ROOT);
if (needsServer || unitStale) {
const unit = {