Chat tabs, chat mode, own modes, compaction notice, CLI binaries again

- Terminals and file managers as tabs of a chat; chat terminals keep running on
  the server (no idle timeout) and re-attach from any device
- "Just chat" in New session and a built-in chat mode with a lean prompt and only
  web tools; custom modes with kind (coding/conversation), read-only and tool picker
- Mode selector as a dropdown
- The chat shows running compactions (automatic: tokens and share of the limit)
  and labels summaries
- Docker image builds and serves the terminal client binaries again
- Fix: atomic session updates; background title/usage writes no longer undo each
  other (auto compaction triggered one turn late)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-09 11:24:58 +01:00
1 parent 242b80605c
commit c850586a81
29 files changed
+831 -187

No files matched your search

+11 -11
View File
@@ -288,20 +288,20 @@ export function Composer({
/>
<div className="composer-bar">
<div className="composer-options">
<div className="mode-tabs" role="tablist" aria-label={t("composer.mode")}>
<select
className="mode-select"
value={session.agent}
onChange={(e) => onUpdate({ agent: e.target.value })}
aria-label={t("composer.mode")}
title={agents.find((a) => a.name === session.agent)?.description ?? t("composer.mode")}
>
{!agents.some((a) => a.name === session.agent) && <option value={session.agent}>{session.agent}</option>}
{agents.map((a) => (
<button
key={a.name}
role="tab"
aria-selected={session.agent === a.name}
className={session.agent === a.name ? "active" : ""}
title={a.description}
onClick={() => onUpdate({ agent: a.name })}
>
<option key={a.name} value={a.name} title={a.description}>
{a.name}
</button>
</option>
))}
</div>
</select>
{session.agent === "craft" && (
<div className="mode-tabs" role="tablist" aria-label={t("craft.mode")} title={t("craft.modeHint")}>
<button className={session.clean_room !== false ? "active" : ""} onClick={() => onUpdate({ clean_room: true })}>