From acf639471d1c89945369caf4d040216eeb5645ff Mon Sep 17 00:00:00 2001 From: HuanLinOTO Date: Wed, 26 Aug 2026 18:44:46 +0800 Subject: [PATCH] feat: pinned terminal i18n + docs + v0.17.0 bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit M5 of pinned terminals (v0.17.0): - README/README_EN: feature list adds pinned terminals - AGENTS.md §3.4: terminal row documents pin capability - Design doc: implementation deviations (M3 disconnect signal convergence, M4 railRevision state for reduceFor non-notify) - package.json + dsh.plugin.json: 0.16.1 → 0.17.0 - i18n: 12 new keys synced across all 19 language dictionaries (done in M2) - All client-side tests green (149/149); typecheck + build pass --- AGENTS.md | 2 +- README.md | 1 + README_EN.md | 1 + docs/plans/2026-08-26-pinned-terminal-design.md | 10 ++++++++++ dsh.plugin.json | 2 +- package.json | 2 +- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4364695..8c086c9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -356,7 +356,7 @@ ctx.effect(() => { | `git` | 20 | 是 | 否 | Git 面板 | | `subagent` | 30 | 是 | 否 | 子代理拓扑 | | `sidechat` | 35 | 否(createTab 铸造 `sidechat:`/按 `meta.threadId` 去重) | 否 | 侧边对话(Codex 风格,**每个对话一个独立 Tab**):打开 Tab 即自动创建空线程(composer 拥有首条消息,host 侧包裹边界提示 + 创建时停泊的进行中快照,首条消息赢得真实标签并同步 Tab 标题);线程 = 插件自建子会话(自定义种子继承父会话完整上下文,进行中回合以 `interrupted` 冻结诚实闭合;种子尾部带合法 `subagent/descriptor`——否则 cold 线程在宿主 subagents.list 里是 corrupt 诊断行——SubagentView/subagent-detect 按 `Side: ` 前缀过滤保持拓扑零噪音),`origin:'subagent'` 隐藏于主列表;生命周期走自有 `/sidebar/api/sidechat.*` 路由(`ctx.agents.create/resume` + `agent.followup/cancel` + `sidechat.info` 读 Agent 身份/状态);头部菜单可切换/重开既有线程(`parkSidechatReopen` + `sidechat:` 确定性 id),关闭 Tab 释放 live agent(历史保留);重开 Tab 经 `collectOwnEvents` 大页回源到种子边界(cold 读会展开 chunk 压缩行,小窗口会丢早期 tool/call 行);「保存为新会话」= `session.fork` 提升顶层会话(必须方法调用形态,`this` 敏感)。UI 对齐主对话区(用户气泡 `--dsw-specific-bubble`、assistant 通栏 markdown、胶囊 composer + 圆形发送/停止钮、运行扫光状态行)。见 [设计文档](docs/plans/2026-08-20-sidechat-tab-design.md) | -| `terminal` | 40 | 否 | 否 | 终端(nextTerminal 自增) | +| `terminal` | 40 | 否 | 否 | 终端(nextTerminal 自增)。v0.17.0+ 支持右键「固定到工作区 / 固定到全局」:固定后切换会话不消失,在面板顶部 PinnedRail 跨会话呈现(global 任意会话可见;workspace 仅同 cwd 会话可见);Agent 终端(`agent:`)被 reconcile 移除时豁免保留为「已断开」(xterm 重连失败 banner 承担断开信号);pin 元数据 `tab.pin = { scope, homeCwd? }` 随宿主会话 state 持久化,渲染期跨会话解析(`collectPinnedTabs`),不写跨会话投影 | | `browser` | 50 | 否(createTab 铸造 browser:``,nextBrowser 自增) | 否 | 内嵌网页浏览器(沙箱 iframe;可设置关闭沙箱) | | `diff` | -1 | 否(按 id 去重) | 是 | 差异查看(由 GitView 触发) | diff --git a/README.md b/README.md index 3e28a2e..fa0b30e 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ - **💬 侧边对话(beta)**:Codex 风格的侧边线程——继承主会话完整上下文(含进行中的回合与工具调用)独立运行,不进入主会话;线程内可持续追问,一键「保存为新会话」提升为顶层会话 - **🪟 双工作台**:右侧栏 + 底部面板;拖 Tab 拆分 / 合并分栏(可跨面板),移动端自动合并全宽抽屉 - **🪟 自由窗口**:把标签栏的任一 tab 拖到主会话区域——成为可移动 / 缩放 / 置顶的悬浮窗口(默认 390×780),拖回侧边栏 pane 即停靠,随会话持久化;`features` 含 `'floatWindows'`,插件 tab 无差别支持 +- **📌 固定终端**:右键终端 Tab 可「固定到工作区 / 固定到全局」——固定后切换会话不消失,在面板顶部 PinnedRail 跨会话呈现(点击切回宿主会话并激活,PTY 保活无需重连);Agent 终端被 reconcile 移除时豁免保留为「已断开」 - **🔁 会话隔离**:布局 / Tab / 面板按会话持久化,陈旧状态自动净化 - **⚙️ 声明式设置**:设置页「侧边卡片」逐项独立开关,二级设置经齿轮弹窗 - **⚡ 按需加载**:启动只拉 ~325KB 核心,终端 / 编辑器 / Mermaid 图表等重依赖用到才按需拉取([设计文档](docs/plans/2026-08-12-lazy-chunks-design.md)) diff --git a/README_EN.md b/README_EN.md index c7e6dca..4ae9127 100644 --- a/README_EN.md +++ b/README_EN.md @@ -49,6 +49,7 @@ - **💬 Side Chat (beta)**: Codex-style side threads — the child inherits the parent's FULL context (completed turns + the pending question + the in-progress turn's assistant output and tool activity, honestly frozen as "interrupted") and runs independently without entering the main conversation; threads support continuous follow-ups (auto-resumed after a DSH restart) and one-click "Save as new session" promotion to a top-level session - **🪟 Dual Workbench**: right sidebar + bottom panel; drag tabs to split / merge panes (cross-panel), mobile auto-merges into a full-width drawer - **🪟 Free Windows**: drag any tab onto the main conversation area to turn it into a movable / resizable / raiseable floating window (default 390×780); drag it back onto a pane to dock; persisted per session. `features` includes `'floatWindows'` and plugin tabs are supported identically +- **📌 Pinned Terminals**: right-click a terminal tab to "Pin to Workspace / Pin Globally" — pinned terminals survive session switches and surface in a PinnedRail at the top of the panel across sessions (click jumps back to the home session and activates; PTY stays alive, no reconnect needed); agent terminals exempted from reconcile removal - **🔁 Session Isolation**: layout / tabs / panels persisted per session, stale state auto-purged - **⚙️ Declarative Settings**: per-item toggles in the "Side Cards" settings section, secondary settings via the gear dialog - **⚡ On-demand Loading**: only ~325KB core at startup; heavy deps (terminal / editor / mermaid diagrams) load on demand ([design](docs/plans/2026-08-12-lazy-chunks-design.md)) diff --git a/docs/plans/2026-08-26-pinned-terminal-design.md b/docs/plans/2026-08-26-pinned-terminal-design.md index 3932bc1..03ecf2b 100644 --- a/docs/plans/2026-08-26-pinned-terminal-design.md +++ b/docs/plans/2026-08-26-pinned-terminal-design.md @@ -114,6 +114,16 @@ getSessionStates(): ReadonlyMap | 底部面板/窄屏迁移 | pinned tab 若在 bottomSplits,`migrateBottomTabs` 照常迁移(pin 语义不受影响) | | 自由窗口中的 pinned tab | 允许;rail 点击切回 home 会话后 `raiseFloat`(floatWithTab 命中走置顶,openTabInActivePane 已有此分支) | +## 12. 实施偏差记录 + +### M3:断开信号收敛 + +设计 §6 原表「Agent 终端被 reconcile 移除」行提到「标题渲染时追加 `(已断开)`」。实施时收敛为:**M3 只做豁免,断开的用户可见信号由 xterm 现有重连失败 banner 承担**。原因:rail/tab 标题渲染处无法知道宿主列表(`reconcileAgentTerminals` 的 uuid 匹配是 state 级的,渲染层不持有该信息),改 meta 会写持久化(违反「reconcile uuid 匹配不受影响」)。xterm 的 WS 连接 1011/超时已有 fatal UI,足以承担断开信号。设计 §6 表相应行实施时修正为「banner 承担断开信号」。 + +### M4:railRevision 状态 + +设计 §3 提到「store 任意会话更新已全局 notify,rail 随 uSES 自动重渲染」。实施时发现 `reduceFor` **不 notify**(targeted opens 的契约:UI 不跟随)。rail 的 unpin/close 走 `reduceFor`(目标是其他会话),store 不 notify → rail 不重渲染。解决方案:Sidebar 维护 `railRevision` 状态,rail action 后 bump,强制 `collectPinnedTabs` useMemo 重算。这是自包含的组件级方案,不改变 `reduceFor` 的 notify 契约。 + ## 7. 测试计划(Unit + 组件,vitest) | 文件 | 覆盖 | diff --git a/dsh.plugin.json b/dsh.plugin.json index 52a6a76..1e7db14 100644 --- a/dsh.plugin.json +++ b/dsh.plugin.json @@ -1,6 +1,6 @@ { "id": "dsh-external/dsh-better-sidebar", - "version": "0.16.1", + "version": "0.17.0", "main": "./lib/index.js", "description": "VSCode 风格右侧侧边栏:文件资源管理器 / 编辑器 / 终端 / Git / 浏览器,按会话隔离。暴露服务供其他插件注册侧边栏页面和文件预览器", "engines": { diff --git a/package.json b/package.json index 7ccd9e9..f782e69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dsh-better-sidebar", - "version": "0.16.1", + "version": "0.17.0", "description": "DSH web plugin: a VSCode-like right sidebar (explorer / editor / terminal / git / browser), isolated per conversation session. Exposes a service for other plugins to register sidebar tabs and file viewers.", "type": "module", "repository": {