Commit Graph
592 Commits
Author SHA1 Message Date
Hoemr f23e40facf fix(files): auto-refresh the tree on window focus and via a dispatchable event
The tree caches loaded directories per refresh tick, so content edited
outside DSH (another editor, a sync plugin pulling from a remote) stayed
stale until the manual refresh click.

- bump the tick when the window regains focus, so switching back to DSH
  shows the on-disk state
- also bump on a bubbling 'dsh-sidebar:refresh-files' window event, so
  external plugins (e.g. dsh-better-overleaf after a pull/push) can
  refresh the tree programmatically without reaching into internals
2026-08-30 17:55:37 +08:00
Atlas Zeng 3aab7ca3a5 Merge pull request #458 from omdsh-dev/feat/workspace-fence-toggle
feat: workspace fence toggle (workspaceFence pref + one-click off in error surfaces)
2026-08-30 15:48:44 +08:00
Atlas Zeng 3941bd5f3a Merge pull request #370 from Hoemr/add/better-overleaf-catalog
Add dsh-better-overleaf to the tab plugin catalog
2026-08-29 17:10:18 +08:00
Menghuan1918 a733425d34 fix(i18n): move pluginBetterOverleafDesc en entry into the en dictionary 2026-08-29 17:09:14 +08:00
Menghuan1918 9cc642b57e fix(i18n): add pluginBetterOverleafDesc to third-language dictionaries (locale key-set test) 2026-08-29 17:09:14 +08:00
chenwei ffe68ae9f8 List dsh-better-overleaf and dsh-quicklook in the ecosystem tables (en) 2026-08-29 17:09:13 +08:00
chenwei ac9f7f68a0 List dsh-better-overleaf and dsh-quicklook in the ecosystem tables (zh) 2026-08-29 17:09:13 +08:00
chenwei 06c908199c Add dsh-better-overleaf to the tab plugin catalog 2026-08-29 17:09:13 +08:00
chenwei cf06b58fc1 Add dsh-better-overleaf to the tab plugin catalog 2026-08-29 17:09:13 +08:00
Atlas Zeng 7d0860ebfe Merge pull request #392 from YZDame/feat/add-dsh-suhuang-scroll
feat: add Suhuang Scroll plugin to catalog
2026-08-29 17:09:10 +08:00
Menghuan1918 3e8d0214e9 fix(i18n): add missing en entry for pluginSuhuangScrollDesc 2026-08-29 17:06:11 +08:00
YZDame b0f7caa967 feat: add Suhuang Scroll plugin to catalog 2026-08-29 17:02:06 +08:00
Atlas Zeng 64afc554ec Merge pull request #404 from AnakinCao/feat/dsh-code-nav-catalog
Add dsh-code-nav to the file-viewer plugin catalog
2026-08-29 17:01:50 +08:00
Menghuan1918 28b74a27f3 fix(i18n): add pluginCodeNavDesc to third-language dictionaries (locale key-set test) 2026-08-29 16:57:23 +08:00
曹志鹏 2946511fae Add dsh-code-nav to the file-viewer plugin catalog 2026-08-29 16:57:22 +08:00
Atlas Zeng f32149d7cb Merge pull request #405 from AnakinCao/feat/dsh-md-export-catalog
Add dsh-md-export to the file-viewer plugin catalog
2026-08-29 16:57:19 +08:00
Menghuan1918 8ab02a9f9d fix(i18n): add pluginMdExportDesc to third-language dictionaries (locale key-set test) 2026-08-29 16:56:01 +08:00
曹志鹏 185d56e202 Add dsh-md-export to the file-viewer plugin catalog 2026-08-29 16:56:01 +08:00
Atlas Zeng f70cb91d23 Merge pull request #413 from meyaomiao/feat/server-deck-catalog
feat(catalog): add dsh-server-deck (server card dashboard + xterm terminal) to the tab plugin catalog
2026-08-29 16:55:40 +08:00
meyaomiao 6a9a458849 feat(catalog): add dsh-server-deck to the tab plugin catalog
- npm-published dual-mount plugin (native Servers tab via
  ctx.betterSidebar.registerTab, standalone drawer fallback)
- card dashboard per host: online state, OS, uptime, CPU/mem/disk
  meters, latency; click-to-open xterm.js interactive terminal
- ~/.ssh/config import with git-hosting alias filtering
- description key pluginServerDeckDesc added to all 21 locale files
  (zh/en in locales.ts + 19 language files)
2026-08-29 16:31:52 +08:00
Atlas Zeng b2ab82cefd Merge pull request #379 from Johnblur/feat/add-bilingual-reader
feat: add dsh-bilingual-reader to tab plugin catalog
2026-08-29 16:29:32 +08:00
Atlas Zeng 2a4493db37 Merge pull request #410 from meyaomiao/feat/github-workbench-catalog
feat(catalog): 收录 dsh-github-workbench(GitHub 工作台)Tab 插件
2026-08-29 16:29:23 +08:00
Atlas Zeng 44ad014293 Merge pull request #451 from g-yixuan/feat/catalog-dsh-sidenote
feat(plugins): add dsh-sidenote to the tab-plugin catalog
2026-08-29 16:29:12 +08:00
Johnblur fd0329f82c feat: add dsh-bilingual-reader to tab plugin catalog
Registers dsh-bilingual-reader in the better-sidebar add-tab-plugin catalog:
native-PDF reading with LLM selection translation, isolated from the main
conversation. Adds the catalog entry plus pluginBilingualReaderDesc across
all 20 locale dictionaries (zh/en source + 18 mirrors).
2026-08-29 16:12:33 +08:00
meyaomiao c96ba20db0 fix(i18n): 补齐 pluginGithubWorkbenchDesc 其余 18 种语言词条
locales.spec.ts 的第三语言键位齐平守护测试要求所有 locales-*.ts 的
key 集合与 zh 完全一致;此前只补了 ja,导致 CI 单测失败。
本提交为 ar/de/fr/hi/id/it/ko/nl/pl/pt/ru/sv/th/tr/vi/zh-HK/zh-MO/zh-TW
补齐该词条,插入位置与其余键一致(GitForge 与 GitRemotes 之间)。
2026-08-29 16:12:29 +08:00
meyaomiao b0683a7c93 feat(catalog): 收录 dsh-github-workbench(GitHub 工作台)Tab 插件
- plugins-tabs.ts 新增条目(github: 形式钉住 v0.1.0,lib 已入库免本地构建)
- locales zh/en/ja 三语 description 同步
- tests/plugin-list.spec.ts 9/9 通过
2026-08-29 16:12:29 +08:00
gyixuan dd8b081665 feat(plugins): add dsh-sidenote to the tab-plugin catalog 2026-08-29 16:12:26 +08:00
North Wang a8f27c4270 fix(client): align collapsed toggle cluster with the DSH session header
- Open state keeps riding the panel's 34px tab strip (top: 3), unchanged.
- Collapsed, the cluster floats over DSH's session header, whose controls
  (title, "Session log" capsule) are vertically centered at 28px on both
  desktop and narrow viewports; top: 3 left the 28px buttons ~11px too
  high — re-center them at 14px.
- body[data-dsh-sidebar-collapsed] only exists while the right panel is
  closed, so the tab-strip alignment is untouched; with position
  compatibility active, compose the caption strip (strip + 14).
2026-08-29 15:49:39 +08:00
GeekRicardo 0504e3918b fix(terminal): 自定义字体解析失败时兜底到等宽,避免掉进比例字体毁掉网格
在设置页「侧边卡片」→ 终端卡片填入自定义「终端字体」后,若该族名在浏览器里
解析不到,终端不是退化成"没有想要的字体",而是整个网格崩掉:字符间距被撑开、
字形变成比例字形、Nerd Font 图标全部消失。

用户实测(macOS + Chrome,填 `Maple Mono NF CN`):

| 「终端字体」的值 | DevTools Rendered Fonts | 结果 |
| --- | --- | --- |
| `Maple Mono NF CN` | **PingFang SC** | cell 12.09px @ 13px 字号(0.93em),网格崩坏 |
| `Maple Mono NF CN, monospace` | **Menlo** | 间距恢复正常 |

`resolveTerminalFont` 对用户值(以及主题 `--ds-font-family-code` token 值)
原样返回,只有内置的 `DEFAULT_TERMINAL_FONT_FAMILY` 末尾带 `monospace`。

字体栈若不以通用族收尾,浏览器解析不到任何具名字体时会落到**标准字体**
(standard font,macOS 中文环境是 PingFang SC)——它是**比例字体**。
xterm 用它的推进宽度量 cell(0.93em,等宽字体应为 0.6em),网格随即失真。

这条路径比想象中容易踩:终端里跑的 shell 在 host 上,字体却由**浏览器所在机器**
提供,两者不同机时(远程/容器化的 DSH)用户按 host 侧装的字体填名字必然解析失败。

新增 `withMonospaceFallback()`,在 `resolveTerminalFont` 出口保证字体栈以通用族收尾。

- **不做字体嗅探**:终端字体设计文档 §2 把"字体合法性嗅探"列为非目标;本改动
  不检测具名字体是否存在,只补一个通用族尾项。
- **已有通用族则原样保留**:包括用户主动写的非等宽通用族(`sans-serif` 等)
  ——那是用户的选择,不该被覆盖。
- **主题 token 值同样兜底**:它掉进比例字体的后果与用户值完全一样。
- **CSS 全局关键字单独处理**:`inherit` / `initial` / `unset` / `revert` /
  `revert-layer` 追加逗号后是非法 CSS,会被 CSSOM 整条丢弃,反而让 xterm
  一个字体都拿不到;这类值直接回落内置栈。
- 字体栈按**顶层逗号**切分并感知引号、转义与括号,避免拆坏 `"Foo, Bar"`
  与 `var(--x, y)`;通用族匹配大小写不敏感且只认未加引号的项。

- `tests/terminal-font.spec.ts` 4 → 13 例(兜底追加、已有通用族免动、大小写与
  引号边界、顶层逗号切分、幂等性、CSS 全局关键字、空值)
- `pnpm typecheck` 零错误
- 全量 `pnpm test`:941 passed(改动前基线 932 passed,+9 为本次新增);
  另有 31 例失败在本分支基线(干净 main)上同样失败,与本改动无关

互补、不重叠。#190 解决"字体解析成功、但栈里没显式列 Nerd Font 导致补充平面
PUA 图标缺字";本 PR 解决"字体压根没解析到、栈又没有通用族尾项导致落进比例
字体"。两者都落在 `terminal-font.ts` 的同一出口,合并时按先后 rebase 即可。
2026-08-29 15:49:35 +08:00
Menghuan1918 a9353ce627 feat: workspace fence toggle (workspaceFence pref + one-click off in error surfaces)
- New persisted built-in pref workspaceFence (default true) under the
  files card's secondary settings modal; host reads it per request via
  the settings seam (fenceEnabledOf — absent/malformed stays ON).
- ensureWorkspacePath/ensureWorkspaceWritePath gain a fence param:
  disarmed skips the containment assert but keeps realpath resolution;
  wired through fs.tree/fs.read/fs.write, the media + html routes, and
  the upload path (writeWorkspaceUpload fence input).
- Editor load failures and file-tree level errors show the localized
  reason plus a one-click global off (FenceErrorNotice) that flips the
  pref, adopts it into the store, and auto-retries the failed operation
  (reloadSeq / retryDir) — the raw wire text is never shown.
- GitView's two client-side pre-checks (hidden open action + no-op
  defense) respect the pref; store threaded through TreePanel/FileTree.
- i18n: 4 new keys across all 21 dictionaries; tests: fence-off route
  coverage, prefs parsing, schema default, editor toggles list;
  docs: guide §8/§8.1 + plans/2026-08-29 design record.
2026-08-29 15:49:19 +08:00
taurus 30879fff74 fix(state): seed restored free-window ids 2026-08-29 15:31:16 +08:00
taurus 1aba61a008 test(state): cover restored free-window id allocation 2026-08-29 15:31:16 +08:00
懿驹-伯乐 963560a361 fix(conversation): restore the composer caret after the draft insert (#425)
A programmatic setDraft commit resets the controlled textarea's caret
(observed landing at the start of the value), so every later insert probed
the reset position and the stack drifted (A|B + C + D became |DACB).
placeComposerCaretAfterInsert puts the caret right after the inserted text
once the value commit lands - the index accounts for the left-side
separating space - and is guarded by a value-sync check plus a two-frame
retry, so a newer edit or a different composer wins untouched.

spliceInsert now reports the caret index together with the spliced draft
so the placement math cannot drift from the join logic. Nothing else moves:
the pure insertAtCaret surface is unchanged.
2026-08-29 15:31:13 +08:00
懿驹-伯乐 a3379ef17d fix(conversation): insert the selection popup text at the composer caret (#425)
appendToDraft always spliced at the end of the draft. The conversation
service exposes no caret API, so probe the live composer textarea selection
from the DOM (value-sync guarded) and splice at that position with
whitespace-aware joins; an unknown or stale caret falls back to appending.
The explorer @-reference shares this path, so it inserts at the caret too.
2026-08-29 15:31:13 +08:00
懿驹-伯乐 d258f3f8bc fix(editor): dismiss the selection popup when its surface leaves the viewport (#425)
The portaled position:fixed add-to-conversation button stays pinned to its
viewport anchor while the sidebar keeps every tab mounted (tab switches only
set display:none; collapsing the panel translates it off-screen), so the
popup could outlive its editor surface. Extract the popup into
useSelectionPopup and close it on any mousedown outside the button, Escape,
document hidden, window blur, and - the tab-switch/collapse path - when an
IntersectionObserver reports the editor surface off-viewport.
2026-08-29 15:31:13 +08:00
Justin Skowyra cdd5706f5b fix(terminal): contain transient resize failures 2026-08-29 15:31:12 +08:00
Kunping Wang 5d8c33832c fix(git): 兼容旧版 Git 的 worktree 列表 2026-08-29 15:31:08 +08:00
Kunping Wang f1da0fe345 perf(sidebar): 保留兜底定位并限制全树查询频率
- 缓存节点连接期间按 1.5s safety-net 周期完整复核
- html style 变化时立即绕过 fast path 重新定位
- 覆盖流式热路径、定时复核、HMR 信号与节点替换行为
2026-08-29 15:31:05 +08:00
Kunping Wang a6c7cf63c1 perf(sidebar): 避免已定位会话列时重复查询 DOM
- 缓存会话列仍连接时跳过 #root 全树 querySelector
- 保留 detached/HMR 回退定位与 1.5s safety net
- 补充 locator 行为测试覆盖缓存复用与节点替换
2026-08-29 15:31:05 +08:00
Atlas Zeng 2088ef6891 Merge pull request #453 from omdsh-dev/fix/reveal-scroll-panel-shift
fix: scope the "Show in folder" reveal scroll to the tree body (panel shift on 0.1.2-alpha.1)
2026-08-29 11:48:58 +08:00
Menghuan1918 41d303623f style: restyle the reveal highlight as a merged business-blue block
The reveal tint now uses the DSH business-blue surface
(--dsw-alias-state-business-tertiary, the same source the host's nav
items use for their active accent, skin-aware) instead of a neutral
accent wash, and drops the 2px left bar. Consecutive revealed rows
square off their touching edges (sibling combinator + :has), so a
multi-file highlight renders as ONE rounded block — per-row radius
notches no longer fragment it; a solo row keeps the full radius.
2026-08-29 11:45:29 +08:00
Menghuan1918 052edb7685 fix: scope the "Show in folder" reveal scroll to the tree body
A reveal on a deep tree shifted the whole panel (tab bar included) out
of the viewport: the reveal used native scrollIntoView, which scrolls
every scrollable ancestor, and the fixed panel host
([data-dsh-panel-host], overflow hidden) is still a programmatically
scrollable container — the host scrolled instead of (or besides) the
tree, with no way to scroll back. Reported on DSH 0.1.2-alpha.1.

Two layers:
- FileTree: compute the centered, clamped target and scrollTo the tree
  body only; scrollIntoView is never called.
- panel host: overflow hidden -> clip. A hidden box remains
  programmatically scrollable; clip keeps the same viewport-edge
  clipping (collapsed panels sliding off-screen) while making the host
  impossible to scroll, killing the whole leak class (md-toc jumps,
  future consumer scrollIntoView calls).
2026-08-29 01:52:55 +08:00
Menghuan1918 50e05ecea0 docs(agents): slim AGENTS.md to repo-global rules, single-source the API reference
AGENTS.md (546 -> 63 lines) now carries only project-global development
rules: hard constraints, mount-smoke CI, DSH 0.1.2-alpha.1 adaptation
notes, npm release, a quick-rule list, and a docs/tests map. The
consumer plugin API reference lives solely in
docs/external-plugin-guide.md.

Reference sync:
- README/README_EN: collapse the dual 'full integration docs' links to
  the guide; AGENTS.md stays linked as the repo rules
- shell-presets.ts / mount.e2e.ts comments: skinning contract pointer
  moved from AGENTS.md §8 to guide §12
2026-08-28 21:42:39 +08:00
Menghuan1918 9bfe5ccb66 docs(guide): promote external-plugin-guide to the single canonical integration doc
Absorb the consumer-facing API reference previously duplicated in
AGENTS.md and refresh stale content to v0.17.1:

- TabDescriptor: full SettingRow shape (select/multi, v0.13.0+),
  urlTarget, richer dedupeKey/available/createTab semantics
- built-in tab table: replace stale explorer-based list with current
  editor/sidechat/pinned-terminal reality
- service: features list completed (urlTarget/settingSelect/
  floatWindows), OpenTabSeed meta null/undefined semantics, openFile
  path-derived-id caveat
- settings: full built-in prefs key list, select rows
- new sections: float windows (§11) and the token-driven skinning
  contract (§12, moved from AGENTS.md §8)
- traps: aionui right-panel mutex, i18n/better-locale, lazy chunks
- minimal example: drop removed @deepseek-ai/dsh-client-runtime peer
- references: 9-viewer typo fixed, plugins catalog / fs-search /
  markdown-html / agent-opens entries added
- fix duplicated §11 heading; sections now run §1-§15
2026-08-28 21:42:26 +08:00
Menghuan1918 3b1898f9cb docs: refresh issue-template DSH version examples to 0.1.1-rc.2 v0.17.1 2026-08-28 16:04:36 +08:00
Atlas Zeng c894163b17 Merge pull request #435 from omdsh-dev/feat/dsh-0.1.2-alpha.1-compat
feat: adapt to DSH 0.1.2-alpha.1 (Remote gateway + token auth + MarkdownText labels)
2026-08-28 16:04:27 +08:00
懿驹-伯乐 60a2f9026e docs: add dsh-better-sidebar-icons to the enhancements catalog
Adds eg-bole/dsh-better-sidebar-icons (VSCode-style file/folder icon
theme, DOM overlay, npm-published 0.1.2) to the '增强与工具' plugin
list in the README.
2026-08-28 14:59:15 +08:00
Menghuan1918 6cfe7a736f feat: adapt to DSH 0.1.2-alpha.1 (Remote gateway + token auth + MarkdownText labels)
Dual-version compatibility: the plugin now works identically on
0.1.0-rc.8 ~ 0.1.1-rc.2 and 0.1.2-alpha.1 (the latter verified against a
source build of the dsh-v0.1.2-alpha.1 tag: mount smoke 14/14 + aggregate
double-mount; 0.1.1-rc.2 re-verified 14/14).

- MarkdownText: alpha.1 renamed the flat optional `codeLabels` prop to a
  required nested `labels: { code: {copyLabel, copiedLabel}, footnotes }`;
  the old prop alone crashes fence rendering with "reading 'code'". All
  four render sites (mermaid / MarkdownHtml / TextEditor / SideChatView)
  now go through src/client/markdown-labels.tsx (dual-shape object passed
  under both prop names).
- e2e mount lanes speak both host dialects (tests/e2e/host-protocol.ts +
  host.ts, unit-locked by tests/e2e-host-protocol.spec.ts):
  - one-time-token browser auth: the launch URL grep extends past the
    `/?token=` query (truncating at `/` loses the token), goto navigates
    the token URL (browser cookie exchange), and stamped navigations
    pre-seed the context cookie via addCookies — the exchange 303 drops
    sibling query params;
  - Remote gateway: dot endpoints first, slash endpoints on 404 fallback,
    with args keyed by the controller parameter name (workspace/create ->
    {request}, session/list -> {_request}; verified on a live host).
- package.json: drop the @deepseek-ai/dsh-client-runtime peer (package
  removed upstream in alpha.1; zero references in the source — the chunk
  externals entry stays and is resolution-tolerant).
- scripts/e2e-mount.sh: fix a latent set -u crash in the npx fallback
  branch ($DSH_CMD followed by a full-width comma parsed as part of the
  variable name).
- CI pin stays at @deepseek-ai/dsh@0.1.1-rc.2 until alpha.1 publishes to
  npm (comment updated); README/AGENTS document the new contracts.
- Version lockstep bumped to 0.17.1.
2026-08-28 04:20:36 +08:00
多玩幻灵qwq 0314fd9b93 Merge pull request #419 from HuanLinOTO/feat/terminal-ctrl-click-url
feat(terminal): open URLs with Ctrl+Click (Cmd+Click on mac)
2026-08-27 21:44:32 +08:00
多玩幻灵qwq d71261ace3 fix(cwd): resolve detached session cwd via persistence index, not host process cwd (#372)
* fix(cwd): resolve detached session cwd via persistence index, not host process cwd

sessionCwdOf fell back to process.cwd() when a session was not yet
attached and the client did not send a cwd — on Windows the host
process cwd is the DSH source root (dsh.cmd's pushd %DSH_ROOT%),
so every user-project path failed the workspace containment guard
with 'path "..." is outside workspace'. The bug surfaced when
clicking chat file links at first paint (session still hydrating)
or any flow that hit a sidebar route before the client's
fetchedCwd effect resolved.

Fix: thread ctx.get('sessionPersistence') as the fallback between
the client cwd and the host process cwd. The persistence index
holds every persisted session's header (including cwd), so a cold
(detached) session resolves its real project cwd instead of the
DSH source root. The host process cwd remains the final fallback
for deployments without persistence (tests / stripped-down hosts);
production always provides persistence.

sessionCwdOf is now async; all 8 call sites await it. The two tool
resolvers (registerTools / registerOpenTool) take an async
resolveCwd callback; the one execute path that used it
(terminal_create) is now async.

Tests: two new regression cases in smoke.spec.ts cover the cold
session via persistence path and the persistence-without-cwd
fallback. Existing stubs updated to the async resolveCwd signature.

* Address Copilot review: fix JSDoc accuracy and validate persistence cwd

- tools.ts / agent-opens.ts: correct the resolveCwd JSDoc — the resolver
  does fall back to the host process cwd as a final tier (tests /
  stripped-down hosts); the previous "never falls back" wording
  contradicted the actual sessionCwdOf contract.
- index.ts: route the persistence meta.cwd through requireAbsolute,
  matching the clientCwd path. A buggy/corrupt persistence layer that
  stored a relative cwd would otherwise flow into the workspace guard,
  be resolved against the host process cwd, and potentially recreate
  the original "outside workspace" misclassification in a harder-to-
  debug way.
- smoke.spec.ts: use resolvePath() for the cold-cwd fixture so it is
  absolute on both POSIX and Windows; add a regression test for the
  relative-cwd rejection path.
2026-08-27 21:44:04 +08:00