feat: account pool per tool with groups and a Cursor pool; update runs in the background

- The update dialog can be closed while an update applies: it keeps running,
  the page still reloads itself when the new server is up, and a failure
  re-opens the dialog with its error.
- Account pool card: one tab per AI tool (Claude Code, Codex, Cursor CLI,
  Oh My Pi, and every other installed tool, which says it has no pool),
  accounts as cards with 5-hour and weekly quota shown as what is LEFT plus
  their reset times, and the saved profiles of Settings → AI tools →
  Profiles as cards with "Share to pool".
- Cursor account pool (server/lib/cursor-pool.js): Cursor API keys handed to
  a cursor-agent pane only through tmux -e CURSOR_API_KEY;
  `agenthub accounts add <name> --tool cursor`.
- Pool groups (server/lib/pool-groups.js, /api/accounts/groups): a group's
  members run only on its accounts of each tool, a user in no group on the
  accounts no group lists, a pin still wins. account_pins loses its tool
  CHECK (rebuilt, pins kept); three new tables.
- Oh My Pi login sharing can be switched from its pool tab too.
This commit is contained in:
2026-10-22 17:02:08 +07:00
parent 44426faf16
commit 685eb748e8
30 changed files with 2891 additions and 299 deletions
+52 -2
View File
@@ -535,12 +535,62 @@ agenthub accounts pin team-key mia --tool codex # pins work as for Claude
> **Ceiling:** a pane can read its own account's key (`$AGENTHUB_POOL_KEY`) or
> `auth.json`, like the Claude pool's token.
## Cursor account pool
Cursor CLI sessions get a pool too (`server/lib/cursor-pool.js`): Cursor API
keys (Cursor dashboard → Integrations → API keys), added on the Users page's
**Account pool → Cursor CLI** tab or from the shell:
```bash
agenthub accounts add cursor-team --tool cursor # key typed hidden, or piped on stdin
agenthub accounts list --tool cursor
agenthub accounts remove cursor-team --tool cursor
agenthub accounts pin cursor-team mia --tool cursor
```
- The key reaches the pane only as tmux `-e CURSOR_API_KEY=…` (a member's
launch file under S3), which `cursor-agent` prefers over the account's own
`cursor-agent login` for that process only. Nothing is written into a home.
- Cursor reports no usage or quota to AgentHub, so the account with the fewest
live Cursor panes is picked.
> **Ceiling:** a pane can read its own key (`$CURSOR_API_KEY`).
## Account pool groups
By default every user shares every pool account. **Groups** split the pool
by team (Users page → **Account pool → Groups**, server mode only,
`server/lib/pool-groups.js`):
- A group has a name, members and accounts of every pool tool (Claude, Codex,
Cursor). Its members' new sessions run only on its accounts of that tool; a
group with no account of a tool leaves its members on their own sign-in.
- A user belongs to at most one group (ticking them in another moves them).
An account may serve several groups.
- A user in no group runs on the **shared pool**: the accounts no group lists.
With no group at all, everything is shared, as before.
- A pin (Edit on an account) is an admin's explicit choice and wins over the
group.
- A login already live in a member's home stays until their panes end (one
`.credentials.json` / `auth.json` per home), even after a group change.
- Each change needs the admin's own password again and is audited. Removing
an account takes it out of every group; deleting a group sends its members
back to the shared pool and removes no account.
The tab bar also shows Oh My Pi (its login sharing, below) and every other
installed tool, which says it has no pool (Antigravity keeps its Google login
in the system keyring; there is no key AgentHub could hand a session).
The Claude and Codex tabs list the saved profiles of Settings → AI tools →
Profiles as cards; **Share to pool** moves one in (the profile leaves the
switcher, as with **Move to pool** in Settings).
## Oh My Pi login sharing
With one Linux user per account, a member's omp has its own `~/.omp` and no
login. An admin can let every member's omp run on the HOST account's omp
logins instead: **Settings → AI tools → Oh My Pi login sharing** (off by
default; `PUT /api/ai-tools/omp-sharing`, audited). It uses omp's own auth
logins instead: **Settings → AI tools → Oh My Pi login sharing**, or the
**Oh My Pi** tab of the Users page's Account pool (off by default; `PUT /api/ai-tools/omp-sharing`, audited). It uses omp's own auth
broker and gateway (`server/lib/omp-share.js`):
```bash