diff --git a/CLAUDE.md b/CLAUDE.md index 27c8882..e517917 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -78,7 +78,7 @@ Data flow: `keypress → xterm onData → WS → pty.write() → shell stdin`, a - `attach(null)` → spawn a new PTY + shell; PTY output goes into a ~2MB **ring buffer** and (if a WS is attached) forwards live. - `attach(sessionId)` → look up the session, **replay the ring buffer**, then resume the live stream. This is what makes "refresh the page and the Claude session is still there" work. - WS close → `detach` one client (PTY keeps running), not kill; the idle clock starts only when the **last** client leaves. -- **Multi-device sharing (v0.4):** a session may have **many concurrent WS clients** — a new attach **JOINS (mirror)**, it does **not** kick. Output/exit/status broadcast to all; any client can type (shared control). **PTY sizing = latest-writer-wins:** the device that most recently fit/focused drives the size, so whichever device you're actively using is full-screen (a shared PTY can only be one size; min-sizing letterboxed the bigger screen). Attach/detach/`blur` never resize — the active device keeps its size; the frontend re-sends dims on pane-show and window-focus so switching devices reclaims full-screen. This relaxes the original "one WS per session" invariant (#5). `GET /live-sessions` lists running sessions so any device **auto-shows them as tabs**; `?join=` and the 🔗 share-QR open a specific shared session; the **🗂 manage page** (`/manage.html`, `DELETE /live-sessions[/:id]`) lists/opens/kills sessions. +- **Multi-device sharing (v0.4):** a session may have **many concurrent WS clients** — a new attach **JOINS (mirror)**, it does **not** kick. Output/exit/status broadcast to all; any client can type (shared control). **PTY sizing = latest-writer-wins:** the device that most recently fit/focused drives the size, so whichever device you're actively using is full-screen (a shared PTY can only be one size; min-sizing letterboxed the bigger screen). Attach/detach/`blur` never resize — the active device keeps its size; the frontend re-sends dims on pane-show and window-focus so switching devices reclaims full-screen. This relaxes the original "one WS per session" invariant (#5). `GET /live-sessions` lists running sessions so any device **auto-shows them as tabs**; `?join=` and the 🔗 share-QR open a specific shared session; the **🗂 manage page** (`/manage.html`) is a full-page **grid of live preview thumbnails** — each card renders the session's current screen via a read-only xterm (fed by `GET /live-sessions/:id/preview` → `RingBuffer.tail()`, no attach) so you can see what each session is doing, with open/kill (`DELETE /live-sessions[/:id]`). - Orphan reclaim: detached longer than `IDLE_TTL` (default 24h) **with no new output since detach** → reclaim. (node-pty can't reliably detect a foreground child, so liveness is approximated via last-output time — see ARCHITECTURE §3.5 / M3.) On server exit, `pty.kill()` all sessions (no cross-restart persistence in v0.1; tmux backend is a v0.2 idea). Represent session state as immutable snapshots (id/start-time fixed at creation); hold mutable runtime handles (pty/ws) separately. diff --git a/docs/PROGRESS_LOG.md b/docs/PROGRESS_LOG.md index c5ee3c7..600930d 100644 --- a/docs/PROGRESS_LOG.md +++ b/docs/PROGRESS_LOG.md @@ -29,7 +29,7 @@ - ✅ **现代化 UI 主题**(design-token 调色板/靛蓝强调色/圆角芯片标签+键栏/毛玻璃弹层)· ✅ **键栏功能字幕**(每键下方标作用)+ 新增 ^R/^L/^D(共 17 键)· ✅ **⌨ 快捷键速查弹层**(`public/shortcuts.ts`)。 - ✅ **v0.4 多设备共享会话**:放宽不变式 #5 —— 一个 session 可挂多个 WS 客户端(镜像;输出/退出/状态广播,谁都能打字)。`GET /live-sessions` + 打开应用自动把主机活动会话**显示为 tab**;`🔗` 分享二维码 / `?join=` 加入指定会话。 - ✅ **镜像尺寸 = 最近活跃端优先(latest-writer-wins)**:共享 PTY 只能一个尺寸,之前取最小值导致宽屏桌面被 iPad 夹小(iPad 全屏、桌面留黑边)。改为"最近 fit/聚焦的设备决定尺寸",你正在用的设备永远全屏;attach/detach/`blur` 都不改尺寸,前端在 pane 显示 + 窗口聚焦时重发 dims(切设备即夺回全屏)。实测两端:200×50 → iPad 100×40 → 桌面 refit 200×50 → iPad blur 不变。后端纯客户端实测镜像输出 + 共享输入通过。 - - ✅ **🗂 会话管理页**(`/manage.html` 独立页):列出主机所有运行中 session(id/目录/状态/观看数/尺寸/时长),可 Open/Kill,批量 Kill all / Kill detached;`DELETE /live-sessions[/:id]`。实测 3→2→0。 + - ✅ **🗂 会话管理页**(`/manage.html` 独立页,非弹窗):**实时预览缩略图网格** —— 每张卡片用只读 xterm 渲染该 session 当前屏幕(像截图,缩放),一眼看出每个 session 在干嘛;`RingBuffer.tail()` + `GET /live-sessions/:id/preview`(不 attach、不影响观看数/回收),每 4s 刷新;可点缩略图/Open 进入、Kill / 批量 Kill。实测 3 个 session 缩略图(top / git log / ls)彩色可辨,Kill 3→2→0。 - ⬜ 仅剩:**O1 token 认证**(可选,默认关)+ **F4/F7 真机验收**(局域网/手机)。 - **225 测试全绿**;工具栏 🔍搜索 ⚙设置 ▦仪表盘 🕘历史 ⌨快捷键 🔗分享 🗂管理 📱QR。 - **下一步**: O1(可选)或真机验收。