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
+32 -17
View File
@@ -58,11 +58,7 @@
"changes.collapseContext": "Show fewer surrounding lines",
"changes.collapseFile": "Collapse {{path}}",
"changes.commitPlaceholder": "Commit message",
"changes.commitStaged": "Commit {{count}} staged",
"changes.suggestMessage": "Suggest a commit message with AI (Claude, staged changes)",
"changes.neverStage": "Never stage — Stage all skips this file",
"changes.allowStage": "Include in Stage all again",
"changes.keptHint": "Never staged by Stage all (this browser)",
"changes.suggestMessage": "Suggest a commit message with AI (Claude, ticked files)",
"changes.conflicted": "conflict",
"changes.discard": "Discard this file's changes",
"changes.discardConfirm": "Click again to discard — this cannot be undone",
@@ -79,6 +75,7 @@
"changes.commentLine": "Comment on line {{n}} — pasted into this workspace's pane",
"changes.commentOn": "Comment on {{at}} — pasted into the pane you used last; nothing is sent until you press Enter there",
"changes.commentSend": "Paste into pane",
"changes.addToChat": "Add to Chat",
"changes.commentCancel": "Cancel",
"changes.commentNoPane": "No terminal of this workspace is on screen — open its session (or narrow the Changes panel) first",
"changes.layout.split": "Side-by-side",
@@ -105,13 +102,7 @@
"changes.size.full": "Full screen",
"changes.fileCount_one": "{{count}} file",
"changes.fileCount_other": "{{count}} files",
"changes.stageFolder": "Stage every file in this folder",
"changes.unstageFolder": "Unstage every file in this folder",
"changes.stageAll": "Stage all ({{count}})",
"changes.unstageAll": "Unstage all ({{count}})",
"changes.dropEdits": "Discard your unsaved edits to this file?",
"changes.stagedGroup": "Staged Changes",
"changes.unstagedGroup": "Changes",
"changes.stage": "Stage this file",
"changes.title": "Changes",
"changes.truncated": "Some changes were left out to keep this panel responsive.",
@@ -236,10 +227,8 @@
"tooltipStart": "Spawn a conversation-mode run with no initial prompt; driven from CLI or via message",
"worktrees.heading_one": "{{count}} worktree",
"worktrees.heading_other": "{{count}} worktrees",
"changes.stageHunk": "Stage this hunk",
"changes.undoHunk": "Undo this hunk",
"changes.undoHunkConfirm": "Click again to undo this hunk — this cannot be undone",
"changes.stageHunkShort": "Keep",
"changes.undoHunkShort": "Undo",
"changes.undoHunkShortConfirm": "Confirm undo",
"changes.edit": "Edit",
@@ -278,14 +267,14 @@
"gitBar.mergeConflicts": "Merge stopped on {{count}} conflicted file(s) — resolve them in the list below.",
"gitBar.merging": "A {{op}} is in progress: finish or abort it first",
"changes.conflictsGroup": "Merge conflicts",
"changes.mergeBanner": "A {{op}} is in progress \u2014 {{count}} file(s) still conflicted",
"changes.mergeReady": "A {{op}} is in progress \u2014 every conflict is resolved",
"changes.mergeBanner": "A {{op}} is in progress — {{count}} file(s) still conflicted",
"changes.mergeReady": "A {{op}} is in progress — every conflict is resolved",
"changes.mergeCommit": "Complete {{op}}",
"changes.mergeAbort": "Abort {{op}}",
"changes.mergeAbortConfirm": "Click again to abort the {{op}}",
"changes.discardShortConfirm": "Discard?",
"changes.amend": "Amend",
"changes.amendHint": "Fold the staged changes into the last commit (only before it is pushed). Leave the message empty to keep the old one.",
"changes.amendHint": "Fold the ticked files into the last commit (only before it is pushed). Nothing ticked rewords it; leave the message empty to keep the old one.",
"changes.amendPlaceholder": "New message (empty = keep the old one)",
"changes.historyOf": "History of branch",
"changes.cherryPick": "Cherry-pick onto {{branch}}",
@@ -435,6 +424,7 @@
"panes.splitNew.right": "Split right with a new terminal",
"panes.splitNew.bottom": "Split down with a new terminal",
"panes.closeShort": "Move to own tab",
"panes.stop": "Stop session",
"changes.copyPath": "Copy relative path",
"changes.viewCommit": "View commit",
"changes.copySha": "Copy commit SHA",
@@ -475,5 +465,30 @@
"runtime.listening": "listening",
"runtime.notListening": "not listening",
"replay.pasted": "That session was already open in a tab — your message is pasted there; press Enter to send it.",
"replay.notPasted": "That session is open in a tab, but your message could not be pasted there: {{text}}"
"replay.notPasted": "That session is open in a tab, but your message could not be pasted there: {{text}}",
"changes.changesGroup": "Changes",
"changes.unversionedGroup": "Unversioned Files",
"changes.commitTicked": "Commit ({{count}})",
"changes.commitAndPush": "Commit and Push",
"changes.amendAndPush": "Amend and Push",
"changes.pushFailed": "Committed, but the push failed: {{error}}",
"changes.tickFile": "Include {{path}} in the commit",
"changes.tickFolder": "Tick every file in {{path}}",
"changes.commitFile": "Commit File…",
"changes.jumpToSource": "Jump to Source",
"changes.copyPatch": "Copy as Patch to Clipboard",
"changes.noPatch": "This file has no text diff to copy",
"changes.addToVcs": "Add to VCS",
"changes.addToGitignore": "Add to .gitignore",
"changes.includeBlock": "Include this change in the commit",
"changes.prevDiff": "Previous difference (Shift+F7)",
"changes.nextDiff": "Next difference (F7)",
"changes.prevFile": "Previous file",
"changes.nextFile": "Next file",
"changes.showHistory": "Show History",
"changes.historyOfFile": "History of {{path}}",
"changes.historyWholeBranch": "Whole branch",
"changes.annotate": "Annotate",
"changes.noBlame": "Nothing to annotate: this file has no committed history yet",
"changes.notCommitted": "Not committed yet"
}
+3 -1
View File
@@ -81,6 +81,7 @@
"quotaFailed": "Could not read the quota",
"quotaWrongAccount": "This sign-in belongs to another Claude account: log in as this account and save it again",
"quotaActive": "in use",
"quotaTokenExpired": "Sign-in expired: use the tool once so it signs in again",
"quotaProfileExpired": "Sign-in expired: use Check quota in Claude Code → Profiles to refresh it",
"quotaSignInExpires": "Sign-in expires in {{time}}",
"quotaSignInExpired": "Sign-in expired",
@@ -94,5 +95,6 @@
"resizeSidebar": "Resize sidebar (double-click to reset)",
"closeMenu": "Close menu",
"sidebar": "Sidebar",
"now": "now"
"now": "now",
"users": "Users"
}
+70 -47
View File
@@ -137,7 +137,8 @@
"incomplete": "Hooks incomplete",
"reinstall": "Reinstall Hooks",
"success": "Hooks installed successfully",
"failed": "Hook installation failed"
"failed": "Hook installation failed",
"plugin": "Provided by the agenthub plugin (its plugin.json), not settings.json"
},
"lanesSection": {
"title": "Workspaces",
@@ -311,16 +312,51 @@
"unavailable": "Not available here: needs systemd --user on Linux, or a GUI login on macOS.",
"foreign": "A service named agenthub that AgentHub did not write already exists — AgentHub leaves it alone."
},
"tray": {
"label": "Show AgentHub icon in the status area",
"desc": "An AgentHub icon beside the clock (top bar, menu bar or notification area) to open the dashboard, quit it, and start it again after a quit.",
"unavailable": "Not available here: needs a graphical desktop session, and is off in server mode."
},
"quit": {
"label": "Quit AgentHub",
"desc": "Stop the dashboard so nothing runs in the background. Opening Claude Code no longer starts it; run `agenthub start` to bring it back.",
"button": "Quit",
"confirmTitle": "Quit AgentHub?",
"confirmMessage": "Every workspace terminal is closed — running agents stop — and the dashboard shuts down. It stays off until you run `agenthub start`.",
"confirmMessageAutostart": "Every workspace terminal is closed — running agents stop — and the dashboard shuts down. It stays off until you run `agenthub start`, or until the next boot/login (start automatically is on).",
"done": "AgentHub is stopping. Run `agenthub start` to start it again."
},
"about": {
"title": "About",
"description": "Server runtime information.",
"title": "System",
"release": "Release",
"uiBuild": "UI build v{{version}} (rebuild client to match)",
"uptime": "Uptime",
"nodejs": "Node.js",
"platform": "Platform",
"wsClients": "WS Clients",
"loadingInfo": "Loading server info..."
"wsClients": "Live connections",
"wsClientsDesc": "Browser tabs and tools receiving live updates",
"loadingInfo": "Loading server info...",
"server": "Server",
"cpu": "CPU",
"cpuValue": "{{count}} cores · load {{load}}",
"memory": "Process memory",
"memoryValue": "{{rss}} RSS · heap {{used}} of {{limit}}",
"systemMemory": "System memory",
"systemMemoryValue": "{{used}} used of {{total}}",
"install": "Installation",
"installKind": {
"plugin": "Claude Code plugin",
"checkout": "Git checkout"
},
"latest": "Latest release",
"upToDate": "Up to date",
"updateAvailable": "Update available",
"unknown": "Unknown",
"database": "Database",
"dbFile": "Database file",
"journal": "Journal mode",
"activity": "Events recorded",
"activityValue": "{{m5}} in 5 min · {{m15}} in 15 min · {{h1}} in 1 h"
},
"tables": {
"sessions": "sessions",
@@ -764,9 +800,7 @@
"group": {
"general": "General",
"agents": "Agents",
"routing": "Routing",
"git": "Git",
"cost": "Cost"
"data": "Data"
},
"section": {
"appearance": {
@@ -800,37 +834,25 @@
"title": "Pricing",
"description": "Model prices for every vendor, used to estimate cost. Rates per million tokens (USD); % is a wildcard in a pattern; a model's introductory rate is shown in violet."
},
"gitCredentials": {
"title": "Git credentials",
"description": "Logins AgentHub gives git for a dashboard fetch, pull or push."
},
"worktrees": {
"title": "Worktrees",
"description": "Which untracked git worktrees a workspace's Add folder suggests."
},
"data": {
"title": "Data",
"description": "Cost and database overview, import, remote sources, export, cleanup and the danger zone."
},
"about": {
"title": "About",
"description": "Server version, uptime and runtime."
},
"snapshots": {
"title": "Snapshots",
"description": "Frozen, read-only copies of sessions, each behind its own link."
"title": "Database",
"description": "Total cost, database overview, import, remote sources, export, cleanup and the danger zone."
},
"reports": {
"title": "Reports",
"description": "Analytics summaries written on a schedule, as HTML or JSON."
"title": "Snapshots & reports",
"description": "Read-only session snapshots behind their own links, and analytics summaries written on a schedule."
},
"users": {
"title": "Users",
"description": "Accounts, their usage and the audit log."
"system": {
"title": "System",
"description": "Version, install, start at login, server runtime and the database file."
},
"git": {
"title": "Git",
"description": "Logins AgentHub gives git for a dashboard fetch, pull or push, and which worktrees Add folder suggests."
}
},
"backPrevious": "Back",
"unknownSection": "There is no “{{section}}” settings page — showing General instead."
"unknownSection": "There is no “{{section}}” settings page — showing Appearance instead."
},
"search": {
"placeholder": "Search settings",
@@ -856,6 +878,18 @@
"vi": "Tiếng Việt"
}
},
"terminalFont": {
"title": "Terminal font",
"description": "The font of the workspace terminals. Takes effect the next time a terminal opens. Saved in this browser only.",
"label": "Font",
"names": {
"jetbrains": "JetBrains Mono",
"maple": "Maple Mono (rounded)",
"system": "System font"
},
"systemNote": "Your browser's fixed-width font. It may lack some Vietnamese letters (ấ, ế, ố…), which then draw out of line.",
"preview": "Preview"
},
"rowMenu": {
"copyHost": "Copy host",
"copyUrl": "Copy endpoint",
@@ -947,20 +981,9 @@
"imported": "Imported {{count}} preference(s). Reloading…",
"badFile": "That file is not an AgentHub preferences file."
},
"users": {
"title": "Users",
"description": "Every account on this server, with its workspaces, sessions and recent usage.",
"name": "User",
"role": "Role",
"workspaces": "Workspaces",
"sessions": "Sessions",
"last7d": "7 days",
"last30d": "30 days",
"disabled": "disabled",
"tokens": "{{n}} tokens",
"manageHint": "Add, disable or change a user on the host: agenthub users …",
"auditTitle": "Audit log",
"auditDescription": "Each time an admin or analyst opened a session a member owns.",
"auditEmpty": "No reads recorded yet."
"pricingLink": {
"title": "Model pricing",
"description": "Prices for every vendor's models live on one page.",
"open": "Open Pricing"
}
}
+73
View File
@@ -0,0 +1,73 @@
{
"title": "Users",
"description": "Every account on this server, with its workspaces, sessions and recent usage.",
"name": "User",
"role": "Role",
"workspaces": "Workspaces",
"sessions": "Sessions",
"last7d": "7 days",
"last30d": "30 days",
"disabled": "disabled",
"you": "you",
"tokens": "{{n}} tokens",
"actions": "Actions",
"roles": {
"admin": "Admin",
"analyst": "Analyst",
"member": "Member"
},
"roleHint": {
"admin": "Everything, including this server's configuration and every user's data",
"analyst": "Reads everything; no terminal, no changes",
"member": "Only their own workspaces"
},
"add": "Add user",
"username": "Username",
"usernameHint": "Letters, digits, '.', '_' or '-'",
"password": "Password",
"passwordHint": "At least 8 characters",
"newPassword": "New password",
"changeRole": "Change role",
"disable": "Disable",
"enable": "Enable",
"resetPassword": "Reset password",
"assignWorkspace": "Give a workspace",
"workspace": "Workspace",
"noOwner": "no owner",
"ownedBy": "owned by {{name}}",
"noWorkspaces": "There are no workspaces yet.",
"yourPassword": "Your password",
"yourPasswordHint": "Type your own password to confirm this change.",
"save": "Save",
"dialog": {
"add": "Add a user",
"role": "Change {{name}}'s role",
"disable": "Disable {{name}}?",
"disableBody": "{{name}} is signed out everywhere and cannot sign in until enabled again. Their workspaces and history stay.",
"enable": "Enable {{name}}?",
"password": "Reset {{name}}'s password",
"passwordBody": "{{name}} is signed out everywhere and signs in with the new password.",
"workspace": "Give {{name}} a workspace",
"workspaceBody": "The workspace's sessions and costs move to {{name}}. A member sees only their own workspaces."
},
"done": {
"created": "{{name}} added",
"role": "{{name}} is now {{role}}",
"disabled": "{{name}} disabled",
"enabled": "{{name}} enabled",
"password": "{{name}}'s password reset",
"workspace": "Workspace given to {{name}}"
},
"errors": {
"EREAUTH": "Your password is wrong.",
"ETOOMANY": "Too many wrong passwords. Try again in 15 minutes.",
"ESELF": "You cannot change your own role or disable yourself.",
"EEXISTS": "That username is taken.",
"EBADUSER": "Username: letters, digits, '.', '_' or '-' (up to 64).",
"EBADPASSWORD": "Password: at least 8 characters."
},
"readOnly": "Analysts can view accounts but not change them.",
"auditTitle": "Audit log",
"auditDescription": "Account changes made here, and each time an admin or analyst opened a session a member owns.",
"auditEmpty": "Nothing recorded yet."
}