Commit Graph
290 Commits
Author SHA1 Message Date
Menghuan1918 ba0114749f feat(dsh): adapt to DSH 0.1.5-alpha.1
Move the plugin onto the DSH 0.1.5-alpha.1 baseline (peer floor
^0.1.5-alpha.1, CI pinned to the alpha dist-tag) and fix the two host
contract changes that alpha line introduced.

Baseline:
- all @deepseek-ai/dsh-* peer/dev deps -> 0.1.5-alpha.1; optional peer
  @deepseek-ai/dsh-client-ui-sidebar-right (declared, unused until the
  native-surface phase); devDep @deepseek-ai/dsh-agent-loop (inbox fold)
- dsh.plugin.json engines >=0.1.5-alpha.1; version 0.19.0-alpha.0;
  SIDEBAR_SERVICE_VERSION follows

Live assistant stream (assistant/chunk is gone):
- 0.1.5 publishes in-flight model deltas as process-local
  agent/assistant-stream frames instead of durable assistant/chunk events
  and embeds the settled stream in assistant/message / assistant/attempt.
  src/assistant-live.ts folds the frames into a bounded per-session buffer;
  sidechat.events serves the current attempt as `live` rows (replaced every
  poll, never a delta) and the transcript renders them; the inherited
  in-progress snapshot reads message content / attempt stream / live frames.

Cold session reads (persistence.inspect is gone):
- 0.1.5 reads a stored session through an explicit read handle
  (open(id,'read') -> handle.read() -> close()). src/session-store.ts owns
  that protocol; every cold read (sidechat transcript, cold-resume preset,
  session.cwd, changes replay) goes through it.

Dead code and docs:
- drop the remote.session.openWorkspacePath interception: 0.1.5's chat opens
  files through ctx.sidebarRight.openResource instead, so the wrapper had no
  caller and would hijack the host's "open in app" gesture; the
  interceptOpenPath pref, its settings row and its locale keys go with it
- AGENTS.md §3 + external-plugin-guide.md describe the new baseline
- vitest setup bridges Node's localStorage accessor to jsdom's store (the
  pre-existing 26 failures on Node >= 22)
- desktop-layout e2e seeds through host RPC and types into the Lexical
  composer (0.1.5 replaced the textarea) instead of driving the directory
  picker

Verified: pnpm typecheck / lint / build / test (124 files, 1327 tests) /
check:consumer-types, plus pnpm test:mount against a real
@deepseek-ai/dsh@0.1.5-alpha.1 host (18/18).
2026-09-09 11:15:30 +08:00
HuanLinOTO 3e408dbe48 feat(terminal): wait_for needle 支持 regex,found 返回实际匹配文本
needle 以 JavaScript 正则优先(编译失败回退字面匹配,旧字面 needle 完全兼容);found 结果新增 match 字段回报实际匹配文本——单个 needle 可覆盖多结局场景(如 (BUILD_OK|BUILD_FAIL) 同步构建成功/失败,match 区分命中分支);工具 description / needle 参数 / output schema / render 同步更新并写明多重匹配场景;新增 3 个 pty 级测试(alternation 命中分支、非法正则回退、元字符匹配);全量测试失败集合与干净 main 基线完全一致(27 个失败均为预存在 win32 非回归)
2026-09-08 23:07:07 +08:00
Menghuan1918 81919516d8 fix(terminal): WS close reason 按 UTF-8 字节截断,避免超 123 字节抛错
ws 用 Buffer.byteLength 校验 close reason 的 123 字节上限(ws/lib/sender.js),
原 slice(0, 100) 按 UTF-16 code unit 截断,非 ASCII shell 名可达 316 字节
(实测 200 个 CJK 字符),ws.close() 会抛 RangeError 顶掉原始错误。
改为按字节截断且不切碎 code point,并补回归测试。
2026-09-08 22:20:15 +08:00
HuanLinOTO 8aa9441627 feat(terminal): shell 覆盖去引号进解析、标题跟随覆盖、close reason 机器标记 2026-09-08 21:21:30 +08:00
HuanLinOTO 26706bc3e9 feat(terminal): POSIX 也预检 shell 可执行文件,统一 shell-not-found 错误码 2026-09-08 21:21:30 +08:00
HuanLinOTO 829ad49ddf feat(terminal): 引号感知的 shell 参数解析与路径去引号纯函数 2026-09-08 21:21:30 +08:00
haruhi 900654b8fd fix(diff): git lens 折叠行接入按需展开,修复点击无反应
- src/client/changes/DiffPane.tsx / src/client/DiffTab.tsx: 按 SidebarDiffRef 构造 fold loader——commit 侧 <hash>^ 与 <hash>;staged 侧 HEAD 与 :0;unstaged 侧 :0 与工作区 fsRead(失败/二进制降级空串);per 文件内容 Promise 缓存,目标或刷新 tick 变化时重置
- fallback 换侧时记录 effectiveStaged,loader 依实际渲染侧取数,修正切片行号错位
- src/client/locales.ts 及 19 个 locales-*.ts: 新增 changesFoldLoading / changesFoldUnavailable 全量补译(共 20 文件 21 处)
- tests/diff-fold-expand.spec.tsx: 展开/折叠/缓存去重、失败降级、无 loader 保持 inert、session 路径回归

背景:git 提交/工作区 diff 折叠行承诺「点击展开」却永远不可点,与 session lens 行为不一致;接入状态机后承诺为真,session 路径与现有文案零变化。
设计 docs/plans/2026-09-07-git-fold-expand-design.md §4.5-4.6。
2026-09-07 23:51:10 +08:00
haruhi d990c10e59 feat(diff): 折叠行异步展开状态机与内容切片
- src/client/api.ts: 仿 gitCommitDiff 新增 gitShow 封装,走既有 git.show 服务路由(payload {rev, path},返回 content 或 null),服务端零改动
- src/client/diff/rows.ts: 新增 foldRowsFromContents 纯函数——old 侧按 fold 行号切片为 context 行(new 侧经区间偏移映射,落界才带行号),new 侧补纯增行;越界截断、\r 保留
- src/client/diff/DiffRows.tsx: 新增 resolveFold prop;foldData/foldLoading/foldFailed 三态,加载中不可点,失败降级静态标记;foldEpoch 使 segments 重置后 in-flight 回调失效
- src/client/diff/DiffFiles.tsx: resolveFold 下传各文件 DiffRows,fold 级 Promise 缓存去重并发点击与重挂载
- tests/diff-rows.spec.ts: foldRowsFromContents 六用例(对称/纯删/纯增/\r\n/空内容/越界)

背景:git -U3 不输出 hunk 间未改动行,gap fold 只有行号范围没有 rows,渲染复用「点击展开」文案却无交互;展开能力建为独立状态机(含 api 封装),git lens 只需注入取数 loader。
设计 docs/plans/2026-09-07-git-fold-expand-design.md §4.1-4.4。
2026-09-07 23:51:06 +08:00
Menghuan1918 04693192df fix(redact): keep the credential heuristics off ordinary files
Path layer: patterns now match with a right boundary (must not continue
into [a-z0-9]) and list only store-plural forms (credentials/secrets/
passwords, not tokens), so tokenizer.ts / dev.environment.ts /
style.keys.ts / api-tokens.md are no longer masked whole while
.env.local / credentials.json / mytoken.yaml still are.

Content layer: drop the bare key/auth/token/pass/bearer field names —
they label far more ordinary content (keyboard keys, CSS custom
properties, lexical tokens) than secrets; qualified names stay and
Bearer schemes remain covered by BEARER_RE.

Adds the over-masking regression cases; fixes the spec's source import
extension to .ts (repo convention).
2026-09-06 23:46:46 +08:00
lhh010 8456d77a92 Merge remote-tracking branch 'origin/main' into feat/changes-md-reading
# Conflicts:
#	src/client/MarkdownHtml.tsx
2026-09-06 22:59:56 +08:00
Menghuan1918 2a99968fa3 fix(editor): rewrite local images in markdown runs of the split renderer
Every .md preview renders through MarkdownDocument (htmlInfo is ungated),
but its markdown segments passed the raw source into MarkdownText, whose
chat-security stance drops non-http(s) image destinations — so local
markdown-syntax images (![alt](./icon.svg), reference-style definitions)
always fell back to alt text. Only HTML <img src> tags were rewritten
(postProcessSanitized).

Apply rewriteLocalImageUrls to each markdown run (segment + appended
reference definitions) inside MarkdownDocument's prepared memo, through
the same media trust fence the sanitized HTML leaves already use.
Idempotent for already-absolute media URLs; remote destinations
untouched. Also correct the stale "non-null only for HTML documents"
comment on TextEditor's htmlInfo.
2026-09-06 21:53:49 +08:00
lhh010 e356791661 feat(changes): HTML render preview for .html op targets
.html/.htm/.xhtml op previews (read / write / edit, non-error) gain a
Render/Raw toggle in the preview pane head: the render view loads the
SAVED file through the same /sidebar/html route the editor's html viewer
uses, so relative assets (./style.css, img/x.png) resolve inside the
route and a segmented read still renders the whole document (the route
serves the file, not the op snapshot — the file-trace-style srcDoc
approach would render a cut-off document whose scripts never run).

The frame is ALWAYS sandboxed (HTML_IFRAME_SANDBOX, moved to the shared
html-preview.ts module — opaque origin, no allow-same-origin, no
top-navigation) plus the route's CSP sandbox header as
defense-in-depth; unlike the editor viewer this surface has no
no-sandbox escape hatch. The contract is pinned by new sandbox-spec
tests on the extracted HtmlRenderPreview component and the pane toggle
(off by default; absent for non-html and error targets).

Locales: zh/en + all 19 shipped third-language overrides (key-set-equal
gate green). Typecheck + eslint clean; sandbox/redact/diff-rows/frontmatter
suites 36/36 green. The full-suite host-side failures (fs-operations /
pty smoke / git / install-powershell) are pre-existing on the base
branch (verified via stash) and unrelated.
2026-09-06 10:37:53 +08:00
Menghuan1918 93ad87dfe7 fix(sidechat): stamp the seed with fork markers so the child inherits no pending inbox
sidechat.start passed `seed` without `meta.isSeeded: true` +
`inheritedEventCount`, so dsh-session treated the whole seed as the
child's OWN events and the child's Inbox constructor replayed the
parent's `agent/inbox/spliced` history — inheriting whatever input sat
UNCLAIMED in the parent at the click moment:

- next-turn: a queued follow-up behind a still-running turn;
- next-step (the reported long-context case, parent queue empty): a
  tool-result context / steering spliced between step boundaries.

The first side prompt then claimed [phantom, boundary, question] — the
stale parent message was sent to the model BEFORE the boundary and
logged as a user/message. The fix passes the exact marker pair the
host's own session.fork uses (api-session-controller); ownEvents() now
stops at the end-seed boundary and the inherited inbox replays empty.

Regression tests run the REAL Session.create + Inbox in both
directions (old shape inherits the phantom, marked shape stays empty);
routes tests pin the two create options. Verified: pnpm typecheck /
test (5 pre-existing unrelated UI-spec failures on main unchanged) /
build.
2026-09-06 00:59:03 +08:00
Menghuan1918 e39ea92ade feat(files): tree rename (inline) + delete (confirmed) + submenu visual tether
资源管理器补全:文件树右键菜单新增「重命名」(行内编辑:预填+全选、
Enter/失焦提交、Esc 取消、IME 组合键守卫)与「删除」(Modal 确认,文件/
目录文案区分,永久删除——宿主无回收站)。根行(工作区根)不提供两项,
服务端 fs.rename/fs.remove 双保险拒绝;目标已存在 409;link-aware——
symlink 行只改/删链接本身(lstat 判定),fence 校验对解析后目标进行。

落定收尾:pruneTree 清旧前缀缓存 + 收起 stale expanded + 单层重载父目录;
tab 调解走 service(rename→updateTab 改路径改标题、delete→closeTab 关
受影响 tab,覆盖两侧分栏/底栏/浮动窗口,经 tree-mutations.ts)。

二级菜单视觉关系(layout.css,仍限 data-dsh-sidebar-submenu 作用域):
父行在子菜单打开期间保持高亮(宿主已渲染 aria-expanded="true"),
卡片间距 10px→4px(悬停走廊同步收窄),翻转规则一并 4px。

i18n 新增 7 key × 20 语言文件(locales.spec 的 key-set-parity 门禁)。
测试:fs-operations 追加 12 例(rename/remove 全失败面);新增
file-tree-rename-delete.spec.tsx 8 例(菜单可见性/重命名流/删除流/错误条);
menu-flip.spec.tsx 契约扩展覆盖 tether 规则。设计文档
docs/plans/2026-09-04-file-tree-rename-delete-design.md。
2026-09-04 22:08:02 +08:00
Menghuan1918 76b57508f4 fix(ui): compact context menus + viewport-clamped submenu flip
减重:全部右键菜单(FileTree 行菜单 / TabBar tab 菜单 / GitLens 文件与
历史菜单 / FreeWindow 标题菜单)与「+」菜单切到宿主 Menu 原语的 compact
密度(26px 行高 / 12px 字 / 164px 卡片),图标随槽位 16→14,「打开方式」
子菜单图钉 20→16,还原工具型右键菜单的趁手感。

越界:宿主子菜单纯 CSS 定位(从父行向上、向右生长)不受视口钳制——树顶
部右键时「打开方式 ▸」子菜单伸出视口上沿,窄面板(280–400px)时伸出右
沿。新增 menu-flip.ts:菜单打开期间在 <body> 发布 data-dsh-sidebar-submenu
="down|left" 方向 token(y < vh/2 → down;x + 400 > vw → left),layout.css
据此翻转子菜单生长方向与 ::before 悬停桥;属性存续期即作用域,宿主自有
菜单不受影响。刻意不做 max-height 滚动钳制——overflow 裁剪会切断悬停桥。

测试:menu-flip.spec.tsx(token 纯函数 + hook 生命周期 + CSS 契约跨文件
一致性);tab-bar / file-tree 两个 spec 追加翻转向量断言;mount.e2e 追加
compact 行高(≤30px)布局级证据。设计偏差记录同步至
docs/plans/2026-08-22-open-with-menu-design.md。
2026-09-04 20:28:35 +08:00
lhh010 16d8df2e93 Merge remote-tracking branch 'origin/main' into feat/changes-md-reading
# Conflicts:
#	src/client/changes/DiffPane.tsx
#	src/client/locales-ar.ts
#	src/client/locales-de.ts
#	src/client/locales-fr.ts
#	src/client/locales-hi.ts
#	src/client/locales-id.ts
#	src/client/locales-it.ts
#	src/client/locales-ja.ts
#	src/client/locales-ko.ts
#	src/client/locales-nl.ts
#	src/client/locales-pl.ts
#	src/client/locales-pt.ts
#	src/client/locales-ru.ts
#	src/client/locales-sv.ts
#	src/client/locales-th.ts
#	src/client/locales-tr.ts
#	src/client/locales-vi.ts
#	src/client/locales-zh-HK.ts
#	src/client/locales-zh-MO.ts
#	src/client/locales-zh-TW.ts
2026-09-04 14:13:34 +08:00
lhh010 a2d3faf7b5 feat(changes): secret redaction layer for op previews
The changes-tab op previews replay read/write/edit payloads into the DOM
(diff rows, read rows, markdown reading mode, error text) — when the model
reads a credentials file, that plaintext must not land on screen or in
inspectable DOM. New display-only redaction layer, on by default with a
one-click pane toggle (persisted in localStorage):

- path layer: credential-shaped filenames (.env / *secret* / *credential* /
  *token* / *api-key* / private keys...) mask whole files line-wise
- content layer: ordinary files mask only secret-shaped spans — secret
  field assignments keep the field name (api_key: [REDACTED]), plus bare
  token prefixes (sk- / AKIA / ghp_ / xox / ya29.), Bearer headers, and
  PEM private-key block headers
- redacted payloads flow through the same viewOp shape into diff rows,
  read rows, markdown reading mode, and error text

Known edge (documented in README): an unquoted mermaid node label
containing a redacted secret breaks the diagram and falls back to source;
workaround is quoting the label. Session data is untouched — this is
display-only and not a boundary against same-context malicious plugins.

Locales: zh/en dictionaries + all 19 shipped third-language overrides
(key-set-equal gate green). 9 new unit tests; typecheck clean; targeted
suites 40/40 green. The fs-operations failure is pre-existing on the base
branch (environment-dependent, verified via stash) and unrelated.
2026-09-04 13:10:21 +08:00
Menghuan1918 dc33087ce1 feat(client): 删除 rc.7 宿主的 __DSH_MODULES__ 回退路径
peer 基线已是 ^0.1.2-rc.1(全部 dsh-* peer),最后提供
window.__DSH_MODULES__ 页面全局的宿主是 0.1.0-rc.7,远低于下限,
装不上本插件——回退在受支持宿主上不可达。受支持宿主上 apply() 在
任何懒加载发生前调 setChunkModuleSystem(ctx.modules),moduleSystem()
前两跳(注入变量 + 插件全局 __dshSidebarModuleSystem__)必中。

回退的唯一活消费者是 vitest fixture:installModuleSystem() 原先经
rc.7 全局投递 fake 模块系统,现改为与生产同路径的 setChunkModuleSystem
注入;无任何专测回退分支的用例,全部断言保持不变。

- chunk-loader.ts: 删 moduleSystem() 第三跳,同步头注 /
  ChunkModuleSystem 接口注中的回退描述
- index.tsx: 删「falls back to the rc.7 global」注释
- README v0.14.0 changelog 与 docs/plans 设计文档中的提及属历史
  存档(描述 PR #232 当时的迁移),保留不改

验证:lint / typecheck / build / vitest 119 文件 1243 用例全绿;
真机挂载 lane(钉版 @deepseek-ai/dsh@0.1.2-rc.1 CLI)mount.e2e
全内置 tab sweep(含终端 / editor 懒加载 chunk)通过;lib/*.js
产物中无 __DSH_MODULES__ 残留。
2026-09-03 20:29:59 +08:00
Menghuan1918 8820efd6bf fix(tests): 补回 add-plugin-modal.spec 缺失的 builtinTabPlugins import
#535(i18n catalog names)给 tests/add-plugin-modal.spec.tsx 新增
sentinelEntry 行时漏了 import;#535 自身 CI run 被 cancel,#536 带病
合入,main HEAD 7b5c7dd 的 typecheck/test 双红(本地 stash 复现一致:
TS2304 / ReferenceError: builtinTabPlugins is not defined,CI run
33754439466 failure)。补上与 plugin-list.spec.ts 同源的 import。

与本 PR 主题无关,仅为本流验证门(typecheck/test 全绿)所需的最小
main 修复,独立成 commit 便于 review 剔除。
2026-09-03 20:29:50 +08:00
Atlas Zeng 7b5c7ddcc4 Merge pull request #536 from omdsh-dev/feat/eslint
feat(lint): 引入 ESLint flat config 并接入 CI 与 Makefile
2026-09-03 20:18:10 +08:00
Atlas Zeng f8bb3013ff Merge pull request #535 from omdsh-dev/feat/i18n-catalog-names
feat(i18n): 目录项与 shell 预设文案词典化,兜底错误条改皮肤令牌链
2026-09-03 20:18:05 +08:00
Menghuan1918 5a1e75e46b fix(lint): 清零存量 lint 告警并接入 CI / Makefile 门禁
存量清理(首跑 141 errors / 21 warnings → 0 / 0):
- 删除孤儿 disable:SideChatView / Sidebar / selection-popup 三处 exhaustive-deps 豁免与 chunk-artifact 的 no-new-func 豁免(多行理由注释把 disable-next-line 顶离了实报行;selection-popup 改为提取 popupOpen 标志真修复)
- 死代码:未用导入(Sidebar×7、TextEditor、SideCardSection、config、fs-operations 及 6 个 spec)、sidechat-core 死累加器 total、chunk-loader.spec 死助手 registry、sidechat-seed-validation 死助手 toolResultMessage
- 真实小修:agent-opens 三处 throw 补 cause;lazy-chunk any → ComponentType<P>(P extends object);service.ts claimed 初值改定值赋值;chunk-loader task / spec 内 etag / pendingLoad / snapshot 改 const;terminal-links 去掉字符类内多余转义;SubagentView catalogs 空兜底 useMemo 稳定标识;editor-host.spec 组件提出大写 FakeViewer(rules-of-hooks);pty-helpers.spec 内联 require 提升为静态导入;panel-host-css 注释里的零宽空格改为可见写法
- 依赖数组豁免(均带理由):granular scope 字段(EditorHost / PdfView / ChangesTab / GitLens×2)、job.status 粒度(SubagentView×2)、清理期读 ref、mount-only 注册等;ctx(挂载期恒定)直接入 deps(Sidebar×3)、TextEditor previewScroll 补 scope(幂等)
- 刻意控制字符正则(conversation-draft / markdown-images)与宿主槽位 any 签名(context-types)以带理由豁免保留

接入:
- Makefile:lint 目标(typecheck 旁),check 聚合补 lint 保持「对齐 CI」语义
- ci.yml ci / ci-windows 两 job 与 release.yml 在 Typecheck 后加 Lint 步骤(release 注释同步顺序)
2026-09-03 20:00:08 +08:00
Menghuan1918 040b182b1c refactor(theme): One Dark/Light 语法色板单源化
新增 src/client/one-dark-palette.ts,作为 one-dark / one-light 两套语法
色系的唯一来源:TerminalView 的 ANSI 16 与 cm-themes 的 CodeMirror 高亮
规则改为从色板常量组装各自的映射(ANSI 槽位 / lezer tag 到色相的映射
仍留在各消费方——两边的角色映射本就不同)。

行为不变的纯重构:每个 hex/rgba 迁移前后逐字节一致(旧新片段在桩
tags 下求值深度比对相等;产物 hex 清单无删除、非色板 hex 计数零变化)。
TerminalView 的 token 兜底色与 cm-themes 的 selection/activeLine rgba
与语法色系无关,保留原处未合并。

chunk 边界:色板为纯常量,被 terminal / editor 两个懒 chunk 各自内联
(每 chunk 约 200B 字面量),不引入跨 chunk import;核心 bundle
(client.js / client-registry.js)对该模块零引用(grep 产物验证)。
tests/one-dark-palette.spec.ts 钉住色板字面量防意外漂移。
2026-09-03 19:59:00 +08:00
Menghuan1918 fa301da29e feat(i18n): localize plugin catalog names and shell preset desc
Catalog entry names (15 tab + 4 viewer) and the dsh-desktop shell preset
desc were raw hardcoded zh strings rendered straight into the add-plugin
modals and the title-bar scheme dropdown. Mirror the existing desc
pattern exactly: PluginEntry.name / ShellPreset.desc widen to the
i18n-friendly string-or-() =>-string union, the catalogs carry lazy
t('pluginXxxName') / t('presetDshDesktopDesc') lookups, and the
add-plugin modal (render, search filter, aria-labels) plus the scheme
SelectMenu resolve them like every other copy. The plain-string arm of
the union stays as the raw-name fallback, and t() itself never yields
empty text (missing keys render the key), so a dict gap can never blank
a name.

20 new dictionary keys added to zh/en (locales.ts), ja (locales-ja.ts),
and all 18 third-language dictionaries — tests/locales.spec.ts enforces
key-set equality against zh for every shipped dict (precedent: 9cc642b),
so the 'leave other locales-* untouched' shortcut would fail the hard
parity gate; real translations are provided instead.

Spec follow-ups (behavior change: names/descs now render through t()):
- plugin-list.spec.ts: name non-empty assertion resolves the union.
- add-plugin-modal.spec.tsx: sentinel/office name assertions resolve
  from the catalog (en locale in tests) instead of pinning zh literals.
- shell-presets.spec.ts: desc non-empty assertion resolves the union.
2026-09-03 19:59:00 +08:00
Menghuan1918 fbfd59bd1b feat: adapt to DSH 0.1.2-rc.1 and bump to v0.18.0 (stable)
Graduate from the alpha track to the stable channel:

- Baseline: CI mount pin, dsh.plugin.json engines floor, and every
  @deepseek-ai/* peer floor / devDependencies pin move to 0.1.2-rc.1
  (published on the `next` dist-tag). alpha.5 -> rc.1 is a pure version
  bump in the harness (all package.json "version" lines, zero source
  delta), so no code adaptation; every host contract was re-verified
  unchanged and the real-host mount smoke passes.
- dsh-client-locale resumed publishing; its trailing-pin exception is
  gone — peers and devDeps align at 0.1.2-rc.1 (pnpm peers check clean).
- Version: fold the unpublished v0.18.1-alpha.0 / v0.19.0-alpha.0 bumps
  into the v0.18.0 stable release; SIDEBAR_SERVICE_VERSION follows
  package.json (asserted by tests/service.spec.ts).
- Docs: README/README_EN badges + channel notes + a full "since v0.17.1"
  changelog entry (the two folded alpha numbers are annotated), AGENTS.md
  §2/§3 baseline wording, external-plugin-guide version line, and the
  e2e-host-protocol header's re-verified list gains 0.1.2-rc.1.
2026-09-03 17:32:04 +08:00
Menghuan1918 0831505854 test(lib-guards): lib 产物缺失时 chunk-artifact / manifest-consistency 跳过而非 ENOENT
fresh clone 未 build 直接 pnpm test 时,两 spec 的 readFileSync 会
ENOENT 崩溃(此前靠 package.json prepare 钩子隐式兜底)。改为文件级
describe.skipIf 守卫:缺产物时整套显示为 skipped 并 console 提示先
pnpm build(exit 0);产物存在时行为与之前完全一致(本仓 prepare 钩
子产出 lib 后两 spec 照常执行,已验证 9 passed 非 skipped)。
2026-09-03 12:04:41 +08:00
Menghuan1918 936df662b0 test(specs): 收敛 28 个组件 spec 的渲染样板到共享 test-utils
- 7 个 spec 的本地 mount()(createRoot + act 容器循环)替换为
  renderRoot():sidechat-view、subagent-jobs-view、subagent-live-polling、
  lazy-chunk、side-card-section-rows(本地 mount 删除,调用点改名);
  editor-refresh、markdown-manual-refresh(EditorHost 包装 mount 改为
  委托 renderRoot,调用点不动)
- 24 个 spec 的内联 IS_REACT_ACT_ENVIRONMENT 赋值替换为 setupReactAct()
  (subagent-jobs-view / subagent-live-polling / lazy-chunk 原本未设
  flag,保持原样不引入)

全部为语义相同的样板替换:迁移后全量 118 files / 1241 passed +
9 skipped,与迁移前一致。
2026-09-03 12:04:35 +08:00
Menghuan1918 a627a4c84d test(utils): 新建共享 React 测试工具 setupReactAct / renderRoot
收敛组件 spec 两类样板的最小共享面:IS_REACT_ACT_ENVIRONMENT 幂等设置
(vitest 按文件隔离 global,逐 spec 调用与原内联语句语义一致)与
createRoot + act 的分离容器渲染循环。刻意不做查询 DSL / 自动清理 /
新依赖。
2026-09-03 12:04:24 +08:00
Atlas Zeng ad392ceea4 Merge pull request #522 from wang-kaopu/fix/517-client-ssh-open
fix(editor): open SSH remote editor links on the client
2026-09-03 10:54:34 +08:00
Menghuan1918 24db20a796 test: make five suites Windows-runner clean
First ci-windows run exposed four platform assumptions in the fixtures:

- smoke: the scratch repo inherited the runner's system-wide
  core.autocrlf=true (Git for Windows default), so every index restore
  smudged LF to CRLF and broke the byte-exact assertions — pin
  core.autocrlf=false in the fixture (eol policy is not what these
  destructive-op tests are about).
- git / git-worktree: Windows TEMP is the 8.3 short form
  (C:\Users\RUNNER~1\...) while git reports long paths, and
  realpathSync does not expand 8.3 aliases — switch the canonicalizer
  to realpathSync.native (libuv resolves via GetFinalPathNameByHandle,
  which does); same trick as the existing macOS /var workaround.
- bundle-route: the ETag memo revalidates on stat (mtime+size) and
  Windows updates file timestamps lazily, so the equal-size rewrite
  still looked unchanged — change the length too.
- market-manifest: GNU tar (Git Bash) reads the drive-letter colon of
  absolute Windows paths as a remote-host spec — run it from the pack
  dir with the bare tarball name instead.
2026-09-03 10:42:56 +08:00
Atlas Zeng c78c6dcf25 Merge pull request #503 from jackie-cqz/fix/windows-custom-shell-resolution
fix(terminal): resolve Windows custom shell executables
2026-09-03 10:42:45 +08:00
Atlas Zeng c9a960884f Merge pull request #461 from Guochaoo/fix/markdown-preview-toc-and-code-header
fix(markdown): preview TOC dismiss-on-outside-click, popover z-index, code-block banner stickiness
2026-09-03 10:42:20 +08:00
Kunping Wang ed2ccc829e fix(editor): 在客户端打开 SSH 远程编辑器链接 2026-09-03 10:32:34 +08:00
Ch3n4y 94ffac0224 fix(editor): keep file basename in @-reference links
The explorer @ button appended plain text (@folder/file.ts), which DSH's
composer only decorates as a folder ref (@folder/) — the file name stayed
outside the link. Insert FILE references through DSH's own structured
insert-reference event instead, minting one chip for the whole reference
(displayed as @basename, serialized as the full @path). Directories keep the
plain @dir/ mention so folder completion still works.
2026-09-03 10:00:13 +08:00
jackie-cqz 74993839e7 fix(terminal): resolve Windows custom shell executables (#487) 2026-09-03 09:58:42 +08:00
Guochao a2a26901e6 fix(markdown): preview TOC dismiss-on-outside-click, popover z-index, code-block banner stickiness
Three preview (render) bugs where DSH's chat-optimized markdown primitives
leak into the file-preview scroll world:

- CodeBlock banner: DSH's bannerWrap is position:sticky (top:0, z-index:6) so a
  block keeps its copy action reachable inside a per-message scroll container.
  In the preview every fence shares one .editorMd scroll container, so the
  banner pins to the viewport top until the whole block scrolls past and reads
  as a floating header. Neutralize stickiness for non-mermaid fences in the
  preview (mermaid chrome replaces the banner and is excluded via
  data-mermaid-processed).

- TOC popover z-index: .tocBar was z-index:3, below the code banner's 6, so the
  outline panel painted beneath a sticky fence header. Raise the bar to 7.

- TOC dismissal: only the toggle re-click closed the popover. Add a document
  pointerdown listener that closes on an outside press (blank preview space),
  exempting the button and panel so the toggle still flips.

Adds md-toc unit coverage for outside-click dismiss and toggle-preserving
behavior; records the deviations in the TOC design doc.
2026-09-03 09:56:31 +08:00
chendefine 96650fa189 fix(shell): keep an overflow:hidden fallback beneath clip + guard the cascade
shift fix) — but as a BARE declaration. Engines without clip support
(Safari < 16, older Chromium) drop an unsupported declaration at parse
time, which leaves the host `overflow: visible`: no clipping at all,
and the historical "collapsed panels extend the document's scrollable
area, whole page draggable" regression returns on those engines.

Declare `overflow: hidden` BEFORE `overflow: clip`: clip-aware engines
apply the later clip (identical behavior to #453), while old engines
fall back to hidden and keep clipping (with its pre-clip
scrollability — the same state they had before #453, strictly better
than visible). The cascade order is the contract.

Also extends the rule comment (the fix guards the whole
scroll-into-view class — focus moving into off-viewport regions,
nested iframes/workbenches claiming focus while loading — not just the
reveal case) and adds tests/panel-host-css.spec.ts guarding the
cascade (hidden first, clip last), the fixed viewport layer, and that
the degraded rule never reintroduces overflow. Contract documented in
the integration guide §12 (root anchor bullet).
2026-09-02 23:51:13 +08:00
Atlas Zeng 5337ef77dd Merge pull request #398 from SparkElf/fix/desktop-sidebar-layout-mode
fix: preserve desktop shell layout with side card
2026-09-02 23:44:15 +08:00
Atlas Zeng a446192008 Merge pull request #373 from Jstn-1g/fix/162-narrow-auto-activation
fix: avoid forcing mobile drawer on auto-activation
2026-09-02 23:44:06 +08:00
Atlas Zeng f61c161494 Merge pull request #455 from wang-kaopu/fix/issue-399-wsl-paths
fix: resolve Linux absolute paths in WSL workspaces
2026-09-02 23:43:58 +08:00
Atlas Zeng 0607517134 Merge pull request #394 from Beverly621/fix/markdown-frontmatter-preview
fix(editor): hide YAML frontmatter in Markdown preview(在 Markdown 预览中隐藏 YAML Front Matter)
2026-09-02 23:43:49 +08:00
laoyh e12927e8a9 fix: preserve desktop shell layout with side card 2026-09-02 23:37:40 +08:00
Justin Skowyra 2d2e8534a5 fix: keep restored mobile drawer closed 2026-09-02 23:26:04 +08:00
Justin Skowyra 41da8cb101 docs: align responsive auto-activation contract 2026-09-02 23:26:04 +08:00
Justin Skowyra d6c587e577 fix: avoid forcing mobile drawer on auto-activation 2026-09-02 23:26:04 +08:00
Kunping Wang 180b16de1b fix: 修复 WSL 会话 Linux 路径解析 (#399) 2026-09-02 23:20:17 +08:00
Beverly621 e31130adb8 fix(editor): hide YAML frontmatter in Markdown preview 2026-09-02 23:15:19 +08:00
Cyancat 26d37c1a8f fix(client): intercept the alpha chat file-open funnel (remote.session.openWorkspacePath)
0.1.2-alpha 宿主删除了 ctx.workspaces.openPath,聊天文件点击全部改走
remote 命名空间,旧拦截成为死代码(点击穿透到 xdg-open)。改为在
ctx.inject(['remote.session']) 内以 defineProperty 遮蔽该方法(accessor
属性,赋值无效),接管时返回 RemoteResult 成功包络。语义不变,

设计:docs/plans/2026-08-31-openpath-intercept-alpha-design.md
2026-09-02 23:13:57 +08:00
Atlas Zeng 02b2310335 Merge pull request #456 from wang-kaopu/fix/issue-403-sidebar-locate-performance
perf(sidebar): reduce repeated center-column DOM queries
2026-09-02 23:11:10 +08:00
Atlas Zeng 3b5e255882 Merge pull request #385 from TaurusWood/fix/free-window-restored-id-collision
fix(state): seed restored free-window ids
2026-09-02 23:10:46 +08:00