Atlas Zeng
bb21657eae
Merge pull request #562 from omdsh-dev/fix/sidechat-seed-inherited-inbox
...
fix(sidechat): 种子补 fork 标记,子会话不再继承父会话未领取的 inbox 消息
2026-09-06 21:43:13 +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
Atlas Zeng
a5c52b3f1b
Merge pull request #550 from omdsh-dev/feat/file-tree-rename-delete
...
feat(files): 文件树重命名/删除 + 右键菜单减重与子菜单钳制
2026-09-04 23:04:37 +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
Atlas Zeng
e1b9b539e4
Revise version details and update QR codes
...
Updated version information and fixed QR code image links in README.
2026-09-04 17:33:42 +08:00
Menghuan1918
f59ffd0741
docs(plans): 全方位代码防腐审查报告与 backlog(2026-09-03)
2026-09-03 21:21:22 +08:00
Atlas Zeng
f7332f332b
Merge pull request #542 from omdsh-dev/feat/split-sidebar
...
feat(client): Sidebar.tsx 按关注点增量拆分
2026-09-03 21:20:15 +08:00
Menghuan1918
e105b01f2b
refactor(client): 抽取自由窗口拖出检测与浮窗层到 sidebar/free-windows.tsx
...
Sidebar.tsx 拆分第五块:useFloatDragout(document 捕获态 dragover/
drop/dragend/blur 监听、会话列矩形命中测试、hint 状态去抖)与
FreeWindowLayer(floats.map 渲染 + 拖出 hint 覆盖层,fragment 渲染
保证 DOM 顺序与原先逐字一致)原样迁出,注释逐字保留。
行为不变:effect 依赖与回调闭包相同;层组件接收的 renderTab/
getTabIcon/store/ctx/sessionId/cwd 即原先 JSX 内联闭包捕获的同一批
每 render 新建的值,FreeWindow 收到的 props 与回调语义不变。
2026-09-03 21:09:20 +08:00
Menghuan1918
b4ab3f154f
refactor(client): 抽取 pinned 虚拟 tab 注入与动作包装到 sidebar/use-pinned-tabs.ts
...
Sidebar.tsx 拆分第四块:activePinnedTabId/pinnedRevision 状态、
pinnedEntries/pinnedVirtualTabs/augmentedTree 三个 memo(含
exhaustive-deps 豁免注释随迁)与 wrappedActions(虚拟 id 路由回
HOME 会话的 reduceFor + ptyClose 语义)原样迁出,注释逐字保留。
调用点移到 actions memo 之后(hook 无 effect,仅 useState/useMemo,
位置调整不改变行为)。
行为不变:memo 依赖数组逐字相同;wrappedActions 的 actions 入参即
原先闭包捕获的同一个 memo 产物。
2026-09-03 21:08:03 +08:00
Menghuan1918
d5b1201ad8
refactor(client): 抽取宿主推送与自动激活触发器到 sidebar/use-host-feeds.ts
...
Sidebar.tsx 拆分第三块:agent-terminals / agent-opens 两条 WS 推送
(含重连退避与失败上限)、子代理自动激活(去抖重估)、后台任务自动
激活、拓扑跳回(subagentJumpRef)连同 FAILURE_LIMIT /
AUTO_OPEN_DEBOUNCE_MS 常量原样迁出,注释逐字保留。Sidebar 侧仅
消费返回的 subagentJumpRef(renderTab 的 onSubagentJump 装填)。
行为不变:五个 effect 的依赖数组与闭包值逐字相同,hook 每 render
无条件调用,effect 挂载顺序保持(feeds → center → float →
bottomAuto → drag)。
2026-09-03 21:05:41 +08:00
Menghuan1918
6bccd21a49
refactor(client): 抽取中心列定位/测量链到 sidebar/use-center-column.ts
...
Sidebar.tsx 拆分第二块:centerRectRef/centerMeasured/centerColRef/
draggingRef、measureCenter(ref + 直写 DOM,避免动画帧级 re-render)
与整条 locate/ResizeObserver/MutationObserver/1.5s 重试链原样迁出到
src/client/sidebar/use-center-column.ts,注释逐字保留。bottomRef 与
state?.bottomOpen 由调用方传入(bottomRef 在主文件先建再共享,行为与
原先 measureCenter 闭包捕获一致)。
行为不变:hook 每次 render 全量重跑,effect 依赖与值完全相同;唯一
文字差异是三处依赖数组补列了跨 hook 边界后失去 useRef 溯源的稳定
ref 对象(centerColRef/draggingRef,标识恒定,不改变触发时机),
为 react-hooks/exhaustive-deps 零告警所需。
2026-09-03 21:03:14 +08:00
Menghuan1918
dbc73f0bf3
refactor(client): 抽取 TabContent 单元格与 + 菜单构建到 sidebar/TabContent.tsx
...
Sidebar.tsx 拆分第一块:memo 化的 TabContent(含 TabContentProps 与
tabContentCompare 比较器)和 buildNewTabOptions 原样迁出到
src/client/sidebar/TabContent.tsx,注释逐字保留。
行为不变:组件体零改动,仅模块路径与 import 调整(相对路径加一层
../);Sidebar.tsx 改为 import 该模块,对外导出面不变(仍只有
Sidebar 具名导出)。
2026-09-03 21:00:20 +08:00
Atlas Zeng
68839aa5fb
Merge pull request #541 from omdsh-dev/feat/unify-polling
...
feat(client): 收敛四处轮询习语到共享 use-polling 原语
2026-09-03 20:45:46 +08:00
Menghuan1918
1ec1565b13
refactor(client): 四处轮询站点迁移到 use-polling,语义逐一保持
...
- SubagentView useSubagentLive:self-scheduling(上一请求 settle 后才排
下一次,不重叠)+ 每代 AbortSignal + signal.aborted 拦迟到写入,行为
与原 disposed 标志等价(teardown 同步置 disposed 并 abort)。
- SideChatView:立即拉取 effect 与 2s 定时拆分——输入变化(含 running
翻转)仍先拉一次转录,运行中间隔 tick 拉转录+徽章;fetchThread 自带
的逐次 abort 与卸载 abort 原样保留。
- GitLens:可见时 2s 固定静默 tick,无初始突发(mount/scope 变更的完整
刷新在别处);refresh 身份变化照旧重启间隔相位。
- ChangesTab:输入变化即拉一次(含隐藏态翻转),可见时 2.5s 固定间隔;
pull 内部 pollGen 代际守卫不动。
守护 spec 全绿:subagent-live-polling + subagent-jobs-view 13/13、
sidechat-view + sidechat-transcript 29/29、git-view-worktree +
changes-tab + changes-ops 13/13;断言零改动。
2026-09-03 20:35:59 +08:00
Menghuan1918
6ef11ae010
feat(client): 引入共享 use-polling 轮询原语
...
四处站点(SubagentView 活动预览 / SideChatView 转录 / GitLens 状态 /
ChangesTab 会话事件)各自手写取消安全与代际失效,机制各异。先落地共享
原语:间隔与调度模式(fixed-interval / self-scheduling)参数化、每代一个
AbortSignal + 卸载/依赖变更即失效(迟到响应靠 signal.aborted 拦截,不信任
abort 必然触发 reject)、任务异常静默保留旧值由下一 tick 重试。
2026-09-03 20:35:59 +08:00
Atlas Zeng
aa01140252
Merge pull request #540 from omdsh-dev/feat/drop-rc7-fallback
...
feat(client): 删除 rc.7 宿主的 __DSH_MODULES__ 回退路径
2026-09-03 20:35:46 +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
Atlas Zeng
463e96b6b4
Merge pull request #534 from omdsh-dev/feat/palette-single-source
...
refactor(theme): One Dark/Light 语法色板单源化
2026-09-03 20:18:01 +08:00
Menghuan1918
98e9a4ff0f
docs(readme): 开发与构建命令清单补 pnpm lint(双语镜像)
2026-09-03 20:00:08 +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
f418692ad0
build(lint): 引入 ESLint 工具链与 flat config 最小规则集
...
- devDependencies: eslint 10 / typescript-eslint 8 / eslint-plugin-react-hooks 7 / globals / @eslint/js(ESLint 10 起 @eslint/js 不再随 eslint 自带,需显式安装)
- eslint.config.js:@eslint/js recommended + typescript-eslint recommended(非 type-checked)+ react-hooks recommended(v7 的 React Compiler 语义规则档整体关闭——57 处存量误报,保留经典 rules-of-hooks / exhaustive-deps 双规则)
- globals 分域:src/client → browser;src 根 / scripts / 根级 config → node;tests → node+browser
- reportUnusedDisableDirectives: error 揪孤儿豁免;no-unused-vars 对齐仓库既有 _ 前缀占位约定
- package.json 增加 lint script(eslint .)
2026-09-03 20:00:07 +08:00
Menghuan1918
e8834bd349
feat(theme): drive the last-resort error bar through skin tokens
...
The host-anchor fallback diagnostic strip inlined hardcoded colors
(#f2a1a1 on #1b1b22). Route them through var() chains like the existing
SideChatView.module.css fallback pattern: text/border read
--dsw-alias-state-error-primary (the codebase's canonical error color,
23 existing usages) and the background reads
--dsw-alias-bg-layer-3,var(--dsw-alias-bg-base,...) (elevated surface,
then page base). The old hexes ride as the chain tails, so with no skin
tokens on the page the bar renders byte-identical to before, while any
--dsw-alias-* skin re-themes it (guide §12: no hardcoded colors). The
guide does not cover this strip and tests/theme.spec.ts asserts
effectiveTokenValue semantics only, so neither needs a follow-up.
2026-09-03 19:59:00 +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
Atlas Zeng
9e1a034527
Merge pull request #537 from omdsh-dev/feat/adapt-dsh-0.1.2-rc.1
...
feat: adapt to DSH 0.1.2-rc.1 and bump to v0.18.0 (stable)
v0.18.0
2026-09-03 19:38:01 +08:00
Menghuan1918
ab6f960fe4
fix(ui): animate the toggle cluster's recenter between tab strip and session header
...
The viewport-corner toggle cluster sits at top:3 riding the right panel's
tab strip while expanded, and recenters to top:14 over DSH's session
header row when collapsed — an 11px snap on every expand/collapse. Ride
the panel slide's own duration/easing (--ds-transition-duration-slow +
--ds-ease-in-out) so both moves stay in lockstep; prefers-reduced-motion
already clears .toggleCluster transitions.
2026-09-03 18:15:41 +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
Atlas Zeng
60f9acdcbe
Merge pull request #527 from omdsh-dev/fix/scripts-hardening
...
fix(scripts): e2e 脚本加固——tarball mtime 选取/DSH_CMD 统一/registry mermaid chunk/e2e-common.sh 去重
2026-09-03 16:30:12 +08:00
Atlas Zeng
dd47a2c864
Merge pull request #526 from omdsh-dev/feat/dev-commands
...
feat(dev): 引入 Makefile 规范化命令面
2026-09-03 16:30:08 +08:00
Atlas Zeng
f24f95f6d2
Merge pull request #525 from omdsh-dev/feat/dedup-core
...
feat(client): 收敛重复实现(api envelope/extOf/lineage/错误归一化)并删除死代码
2026-09-03 16:30:04 +08:00
Atlas Zeng
ceed6b244e
Merge pull request #524 from omdsh-dev/feat/test-utils
...
feat(tests): 收敛组件测试样板到共享 test-utils
2026-09-03 16:30:00 +08:00
Menghuan1918
3d23ceb467
fix(ci): pnpm 版本统一由 packageManager 字段供版,移除 action 显式 version 输入
2026-09-03 12:17:28 +08:00
Menghuan1918
c026676f41
refactor(e2e): 抽取 e2e-common.sh,收敛两挂载脚本的重复骨架
...
e2e-mount.sh 与 e2e-aggregate-mount.sh 约 40% 逐字重复:say/warn/die、
node/pnpm 前置校验、DSH_CMD 与 tarball 解析、scratch home + 清理 trap、
profile 三件套 heredoc、dsh web 启动与就绪轮询。收敛为 scripts/
e2e-common.sh 纯函数库(日志前缀 E2E_TAG 参数化),两脚本 source 之。
行为等价性(差异点全部参数化,既有注释语义原位保留):
- DSH_HOME 子路径:mount 用 $SCRATCH/home,aggregate 直接用 $SCRATCH
(调用点各自 export);
- 就绪行 grep:mount 要带 token 的完整 URL(head -1 取首个),aggregate
只取裸 origin(tail -1 取末个)——E2E_READY_RE / E2E_READY_PICK 传入,
两侧论证注释保留在各自脚本;URL 提取统一为命中串取末段(mount 模式带
`dsh web: ` 两段前缀故等价于原 awk '{print $3}',aggregate 模式不含
空白故等价于原整行);
- 额外清理项:aggregate 的 fixture TMP_DIR(mount 不设该变量即跳过);
- 就绪失败文案/尾部行数差异(提前退出 tail -30 vs 超时 tail -40 vs 双
日志 tail -5)留在调用点。
e2e-common.sh 为纯开发侧文件,不进 npm files 白名单;install.sh /
install.ps1 随 npm 包独立分发,保持自包含,不 source 它。
2026-09-03 12:08:43 +08:00
Menghuan1918
35111e163c
docs(readme): 双语补 Makefile 用法、聚合挂载回归与一键安装入口
...
- 开发与构建:补 Makefile 薄封装示例(help/check/mount/clean)与
pnpm check:consumer-types 的定位说明(浏览器-only 消费者视角)
- 参与贡献:提交前自检补 make check 与 pnpm test:mount:aggregate
- 安装:补方式三一键脚本(bash scripts/install.sh;Windows install.ps1,
-h 查看参数);README 与 README_EN 同步镜像
2026-09-03 12:07:35 +08:00
Menghuan1918
6201a2c6e6
build(ci): 补 test:mount:aggregate / clean / packageManager 并对齐 release 校验顺序
...
- package.json 新增 test:mount:aggregate(scripts/e2e-aggregate-mount.sh 的
npm 别名,CI plugin-mount lane 改经它驱动,保留 DSH_CMD/DSH_TELEMETRY_DISABLED
env)与 clean(node rmSync 删 lib,与 build 开头清理同款、跨平台);
只新增普通 script,不动任何生命周期钩子(market-manifest.spec.ts 对
packed manifest 的 lifecycle 断言不受影响,已实跑验证)
- packageManager 钉 pnpm@11.8.0(本地实装版本;pnpm 10+ 运行时按该字段
自切版本,CI action-setup 的 version: 11 输入与其兼容不冲突)
- release.yml 校验顺序统一为 typecheck → test → build → check:consumer-types
(与 ci.yml 一致),补上缺失的 consumer 类型面守卫;tag 校验等非构建
步骤位置不变
2026-09-03 12:07:29 +08:00
Menghuan1918
789696aa31
build(dev): 引入 Makefile 命令面薄封装与 .editorconfig 基线
...
- Makefile 仅转发 package.json scripts(唯一事实源),补 help 自说明、
clean 清理与 check / mount / mount-aggregate / registry 四个聚合目标;
check 用单条 recipe 串 typecheck → build → test → check:consumer-types,
避免 make 前置依赖在 -j 下乱序;lint 目标留给引入 ESLint 的后续 PR
- .editorconfig:root + utf-8/lf/末尾换行/去尾随空格,默认 2 空格,
Makefile recipe 保持 tab
2026-09-03 12:07:23 +08:00
Menghuan1918
bc1984b2f2
refactor(sidechat): 删除零引用的 sidechatSeed
...
src/sidechat-core.ts 的 sidechatSeed()(buildSidechatInheritance 的
seed 半边,doc 注明 test convenience)在 src+tests 全仓零引用,也无
barrel 转出口,删除。同文件的 SeedEvent 类型与 copyEvents 仍被
SidechatInheritance 使用,保留;其余导出不动。
2026-09-03 12:05:48 +08:00
Menghuan1918
4002f3cc5c
refactor(client): 统一 GitLens 错误归一化与 SubagentView 日志分级
...
- GitLens.tsx:六处 catch 里的 reason instanceof Error ?
reason.message : String(reason)(refreshTarget/refresh/loadMoreLog/
commit/checkout/runConfirmed)收敛为模块级 errorMessage(),
两处模板字符串插值场景(historyLoadError/checkoutError 前缀)
同样复用;归一化表达式与输出文本逐字不变。
- SubagentView.tsx:openSubagent/open session 失败的 console.warn
改为 console.error,与同严重度失败路径对齐(Sidebar.tsx tab
badge、TerminalView.tsx xterm open、service.ts urlTarget/plugin
callback 均为 console.error);前缀与消息文本不变。tests/ 无任何
钉 console.warn 的断言,已核实。
2026-09-03 12:05:48 +08:00
Menghuan1918
69cc8014a7
refactor(client): subagent lineage 遍历收敛为共享 subagent-lineage 模块
...
rootAncestor / countSubagentDescendants / treeSessionIds 三份「沿
subagent-origin 链上行 + seen 集合防环 fail-soft」实现收敛到新模块
src/client/subagent-lineage.ts:核心走链是单个私有生成器
subagentOriginChain()(seen 防环、只在节点为 subagent 且有 parent 时
前行),三个公开函数迁入并基于它重写;isSideThreadSummary 一并迁入
(countSubagentDescendants 依赖它,迁入可避免 detect↔lineage 循环
依赖),subagent-detect.ts / subagent-jobs.ts re-export 全部迁出
符号,既有 import 调用点零变化。
语义逐字保留的等价性论证:
- rootAncestor:链为空返回 start.id(原循环条件不满足即返回
current?.id);链非空返回 byId[末节点.parentId]?.id ?? sessionId
(原循环退出时 current 恰为该行,断链/行缺失回退 sessionId 不变)。
- countSubagentDescendants:生成器在 seen.add 后 yield、消费方判
parentId === sessionId 即 break——与原循环体内判断顺序一致;
descendant 的 running 判定、side-thread 过滤位置不变。
- treeSessionIds:根行缺失(byId[rootId] 无行)时任何上行都不可能
「访问到」根(原实现只匹配真实访问过的行),故提前返回空集;
根行自身(非 subagent)经 summary.id === rootId 特判入集;其余
行经链节点 parentId === rootId 判定,等价于原「上行走到 id ===
rootId 的行」——两种表述指向同一行(链上节点的 next 行)。
directSubagentCount 不迁移:它是对直接子行的单层过滤,没有上行
walk,无共享逻辑(背景侦查将其归入 walk 家族与实际代码不符)。
collectBranchIds 遍历的是 catalog 结构而非 session 链,保持不动。
2026-09-03 12:05:41 +08:00
Menghuan1918
857646ea66
refactor(client): 收敛 /sidebar envelope 解析与取扩展名双实现
...
- api.ts:call 与 fetchUpload 里逐字相同的响应 envelope 解析
(json().catch(null) + ok/value 判断 + SidebarApiError 构造)收敛为
私有 readEnvelope<T>(),两处调用;判断顺序与错误码回退逻辑不变。
- 取扩展名双实现收敛:extOf 的实现迁至零依赖的 paths.ts(lang.ts 与
service.ts 均可达的基础模块),lang.ts re-export 保持既有导入面
(tests/file-types.spec.ts 从 lang.ts 导入 extOf);service.ts 删除
模块私有的同体 extOfPath,matchFileViewer 改用 extOf。方向说明:
service.ts 不能反向 import lang.ts——lang.ts 携带全部 @codemirror/*
依赖且只经 editor 懒加载 chunk 进入浏览器,core bundle 静态引用它
会把 CodeMirror 拉进核心包(构建产物已验证:client.js /
client-registry.js 中 0 处 codemirror,client-editor.js 不变)。
2026-09-03 12:05:29 +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
Menghuan1918
61c9c550d9
fix(registry): registry 打包补上 mermaid 懒加载 chunk
...
package.json files 白名单与 tsdown 产物都含 lib/client-mermaid.js(+
.map),registry 通道的复制清单却缺它——经 dsh registry 安装后 Markdown
预览首次加载 mermaid 会拿到 /sidebar/bundle 404。与 terminal/editor
两 chunk 同款补齐。
2026-09-03 12:03:05 +08:00
Menghuan1918
2052d0554b
fix(e2e): 聚合 lane 按 mtime 取最新 tarball 并统一 DSH_CMD 缺省解析
...
e2e-aggregate-mount.sh 选 tarball 用字典序 `ls | head -1`,仓库根堆积
多个历史 tgz 时会把冒烟挂到过期产物上——完整移植 e2e-mount.sh 的
mtime 策略与多 tarball 告警。DSH_CMD 缺省从直连 npx 统一为「PATH dsh
优先、npx 回退」(CI 传 DSH_CMD=dsh 不受影响)。
顺带修一个移植中暴露的边角:候选计数行在零候选时因 pipefail+set -e
静默退出,吞掉下一行的友好报错——补 `|| true`(mount.sh 同步修复)。
2026-09-03 12:02:57 +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