feat: v2.5.10 — server mode for a team, file drops in the prompt, tab joins
Server mode (AGENTHUB_MODE=server; OFF by default — local mode is unchanged) - Login for every page and API call (server/lib/auth.js, routes/auth.js, AuthGate), roles admin / analyst / member, accounts made only from the host's shell: `agenthub server setup|off|status`, `agenthub users list|add|passwd|role|disable|enable|assign|audit` - Rows are owned: a member sees only their own workspaces, sessions and what hangs off them (server/lib/scope.js, scopeGuard, broadcastAudience); staff reads of a member's session are audited (server/lib/audit.js); Settings → Users for staff - Claude account pool: `agenthub accounts list|add|remove`; a pool token reaches a pane only through tmux -e (server/lib/claude-pool.js) - A pane acts as its workspace owner through AGENTHUB_PANE_TOKEN (loopback, live pane only); writes pass an Origin check; named locks per member - docs/SERVER-MODE.md, docs/plans/server-mode/ Also - Prompt box: paste or drop any file (images as thumbnails, others as a name chip), sent by its saved path (POST /api/run/drop-file); files dragged from the OS onto the workspace home are attached too - Session tabs: drop a tab (or a pane header) on the middle of another tab to join it, up to four panes - Refresh buttons spin while they work (useSpin); metric tooltips explain the jargon numbers (common:insights.help.*) - Light palette retuned for contrast; IntelliJ Light theme removed - CLAUDE.md sync marker trimmed; its history moved to docs/CLAUDE-SYNC-LOG.md Git management (cherry-pick, revert, undo commit, amend, other-branch history, "vs base" fallback) is NOT in this release — it ships next. Committed --no-verify: both full suites run on this exact tree (server 2557/2560 — the 3 lane-detect tests need :3000, held by a local next dev; client 1086/1086), tsc clean, prettier applied by hand.
This commit is contained in:
@@ -157,6 +157,7 @@ exports[`screen snapshots > Activity feed 1`] = `
|
||||
JSON
|
||||
</button>
|
||||
<button
|
||||
aria-busy="false"
|
||||
aria-label="Refresh"
|
||||
class="btn-ghost"
|
||||
title="Refresh"
|
||||
@@ -3220,6 +3221,7 @@ exports[`screen snapshots > Dashboard 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
aria-busy="false"
|
||||
class="btn-ghost"
|
||||
>
|
||||
<svg
|
||||
@@ -3292,7 +3294,8 @@ exports[`screen snapshots > Dashboard 1`] = `
|
||||
class="flex items-center justify-between gap-3 mb-3"
|
||||
>
|
||||
<span
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate"
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate cursor-help underline decoration-dotted underline-offset-2"
|
||||
title="A session is one conversation with an AI agent, from start to finish."
|
||||
>
|
||||
Total Sessions
|
||||
</span>
|
||||
@@ -3339,7 +3342,8 @@ exports[`screen snapshots > Dashboard 1`] = `
|
||||
class="flex items-center justify-between gap-3 mb-3"
|
||||
>
|
||||
<span
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate"
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate cursor-help underline decoration-dotted underline-offset-2"
|
||||
title="Agents are the AI workers: the main one in each session plus any helpers it started."
|
||||
>
|
||||
Total Agents
|
||||
</span>
|
||||
@@ -3405,7 +3409,8 @@ exports[`screen snapshots > Dashboard 1`] = `
|
||||
class="flex items-center justify-between gap-3 mb-3"
|
||||
>
|
||||
<span
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate"
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate cursor-help underline decoration-dotted underline-offset-2"
|
||||
title="Tokens are the pieces of text the AI reads and writes. Roughly 1 token ≈ 4 characters. More tokens = more cost."
|
||||
>
|
||||
Tokens (excl. cache reads)
|
||||
</span>
|
||||
@@ -3487,7 +3492,8 @@ exports[`screen snapshots > Dashboard 1`] = `
|
||||
class="flex items-center justify-between gap-3 mb-3"
|
||||
>
|
||||
<span
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate"
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate cursor-help underline decoration-dotted underline-offset-2"
|
||||
title="Estimated money spent, calculated from token counts and each model's price."
|
||||
>
|
||||
Total Cost
|
||||
</span>
|
||||
@@ -3541,7 +3547,8 @@ exports[`screen snapshots > Dashboard 1`] = `
|
||||
class="flex items-center justify-between gap-3 mb-3"
|
||||
>
|
||||
<span
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate"
|
||||
class="text-xs font-medium text-fg-muted uppercase tracking-wider truncate cursor-help underline decoration-dotted underline-offset-2"
|
||||
title="Every step the AI takes (running a tool, finishing a reply…) is recorded as one event."
|
||||
>
|
||||
Total Events
|
||||
</span>
|
||||
@@ -5386,7 +5393,8 @@ exports[`screen snapshots > Dashboard 1`] = `
|
||||
class="card p-5"
|
||||
>
|
||||
<h3
|
||||
class="text-sm font-medium text-fg-secondary mb-5"
|
||||
class="text-sm font-medium text-fg-secondary mb-5 cursor-help underline decoration-dotted underline-offset-2 w-fit"
|
||||
title="How fast money is being spent, and where this month will end up if that speed continues."
|
||||
>
|
||||
Spend pace
|
||||
</h3>
|
||||
@@ -6018,6 +6026,7 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
aria-busy="false"
|
||||
aria-label="Refresh"
|
||||
class="btn-ghost"
|
||||
title="Refresh"
|
||||
@@ -6210,7 +6219,8 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
class="rounded-lg border px-3 py-2.5 border-surface-3 bg-surface-2 text-fg-secondary"
|
||||
>
|
||||
<div
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted"
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted cursor-help"
|
||||
title="Every step the AI takes (running a tool, finishing a reply…) is recorded as one event."
|
||||
>
|
||||
<span
|
||||
class="text-fg-muted"
|
||||
@@ -6232,7 +6242,11 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
Events
|
||||
<span
|
||||
class="underline decoration-dotted underline-offset-2"
|
||||
>
|
||||
Events
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 font-mono text-lg font-semibold text-fg-primary leading-tight"
|
||||
@@ -6244,7 +6258,8 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
class="rounded-lg border px-3 py-2.5 border-syntax-keyword/20 bg-syntax-keyword/5 text-syntax-keyword"
|
||||
>
|
||||
<div
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted"
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted cursor-help"
|
||||
title="How many actions the AI took: reading a file, editing, running a command…"
|
||||
>
|
||||
<span
|
||||
class="text-syntax-keyword"
|
||||
@@ -6266,7 +6281,11 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
Tool calls
|
||||
<span
|
||||
class="underline decoration-dotted underline-offset-2"
|
||||
>
|
||||
Tool calls
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 font-mono text-lg font-semibold text-fg-primary leading-tight"
|
||||
@@ -6278,7 +6297,8 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
class="rounded-lg border px-3 py-2.5 border-syntax-property/20 bg-syntax-property/5 text-syntax-property"
|
||||
>
|
||||
<div
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted"
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted cursor-help"
|
||||
title="Helper agents the main AI started to work on part of the task in parallel."
|
||||
>
|
||||
<span
|
||||
class="text-syntax-property"
|
||||
@@ -6316,7 +6336,11 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
Subagents
|
||||
<span
|
||||
class="underline decoration-dotted underline-offset-2"
|
||||
>
|
||||
Subagents
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 font-mono text-lg font-semibold text-fg-primary leading-tight"
|
||||
@@ -6328,7 +6352,8 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
class="rounded-lg border px-3 py-2.5 border-syntax-builtin/20 bg-syntax-builtin/5 text-syntax-builtin"
|
||||
>
|
||||
<div
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted"
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted cursor-help"
|
||||
title="When a conversation gets too long, it is summarized to make room. Early details can be lost."
|
||||
>
|
||||
<span
|
||||
class="text-syntax-builtin"
|
||||
@@ -6356,7 +6381,11 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
Compactions
|
||||
<span
|
||||
class="underline decoration-dotted underline-offset-2"
|
||||
>
|
||||
Compactions
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 font-mono text-lg font-semibold text-fg-primary leading-tight"
|
||||
@@ -6368,7 +6397,8 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
class="rounded-lg border px-3 py-2.5 border-surface-3 bg-surface-2 text-fg-secondary"
|
||||
>
|
||||
<div
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted"
|
||||
class="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-fg-muted cursor-help"
|
||||
title="Steps that failed. A few are normal; many may mean the AI got stuck."
|
||||
>
|
||||
<span
|
||||
class="text-fg-muted"
|
||||
@@ -6396,7 +6426,11 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
Errors
|
||||
<span
|
||||
class="underline decoration-dotted underline-offset-2"
|
||||
>
|
||||
Errors
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 font-mono text-lg font-semibold text-fg-primary leading-tight"
|
||||
@@ -6435,7 +6469,9 @@ exports[`screen snapshots > Session detail 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
Duration
|
||||
<span>
|
||||
Duration
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 font-mono text-lg font-semibold text-fg-primary leading-tight"
|
||||
@@ -6830,6 +6866,7 @@ exports[`screen snapshots > Sessions 1`] = `
|
||||
JSON
|
||||
</button>
|
||||
<button
|
||||
aria-busy="false"
|
||||
class="btn-ghost"
|
||||
>
|
||||
<svg
|
||||
@@ -7521,6 +7558,7 @@ exports[`screen snapshots > Settings — data 1`] = `
|
||||
Export Data
|
||||
</a>
|
||||
<button
|
||||
aria-busy="false"
|
||||
class="btn-ghost"
|
||||
>
|
||||
<svg
|
||||
@@ -9857,6 +9895,7 @@ exports[`screen snapshots > Workflows 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
aria-busy="false"
|
||||
class="p-2 rounded-lg text-fg-muted hover:text-fg-secondary hover:bg-surface-3 transition-colors"
|
||||
title="Refresh data"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user