@khorsheed/dsh-file-preview 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # 变更记录
2
2
 
3
+ ## 未发布
4
+
5
+ - 从只读宿主包移除 `3d-artifact` 作者 skill;现在由 `@khorsheed/dsh-inline-html-render` 分发并注册。
6
+ - 新增零会话 `capabilities()` Remote 握手(`protocolVersion: 1`),供客户端在宿主缺席时抑制全部 UI。
7
+
8
+ ## 未发布
9
+
10
+ - 从只读宿主包移除 `3d-artifact` 作者 skill;现在由 `@khorsheed/dsh-inline-html-render` 分发并注册。
11
+ - 新增零会话 `capabilities()` Remote 握手(`protocolVersion: 1`),供客户端在宿主缺席时抑制全部 UI。
12
+
13
+ ## 0.3.0(2026-09-11)
14
+
15
+ (以 minor 发布:openExternal 是新增能力;pair 包 ui-file-preview 的 peer 边由 pack-dist 按本包版本重写,两包版本线须一致。)
16
+
17
+ - **BREAKING**:minHost 前移至 `0.1.5-rc.1`;宿主 `0.1.2-rc.1` 的用户请停留在 `0.2.0`。dispatch 事件只匹配 0.1.5 的 `tool/ptc-dispatch`(官方 v2→v3 日志迁移会把持久化的旧名改写过来,0.1.5 宿主不会再发出 `tool/code-dispatch`),0.2.0 的双名探测退役
18
+ - 新增 Remote 方法 `openExternal(agent, path, app, signal)`:在指定宿主应用中打开文件(macOS `open -a`),供浏览器半的「在 IDE 打开」手势使用——官方 open-in-app 路由只收目录。`app` 为官方 catalog id(id → `.app` 名映射镜像官方 catalog 的 darwin 条目);非 macOS / 未知 id 返回 `opened: false`,不写入。
19
+
20
+
21
+ ## 0.2.0(2026-09-10)
22
+
23
+ 适配宿主 0.1.2 线。
24
+
25
+ - **BREAKING**:minHost 前移至 `0.1.2-rc.1`;宿主 `0.1.0-rc.6` ~ `0.1.1-rc.2` 的用户请停留在 0.1.x 线(末版 `0.1.1`)
26
+ - 会话事件读取走 `Session.snapshotEvents()`(`session.events` 已随宿主移除)
27
+ - 嵌套 dispatch 事件按名探测(feature detection,非版本判断):同时识别 Code Mode 的 `tool/code-dispatch` 与 PTC 更名后的 `tool/ptc-dispatch`
28
+
3
29
  ## 0.1.1(2026-08-23)
4
30
 
5
31
  - 修复:随包 skill 在目录里可见、调用即炸——宿主在 load 时才校验注册的 `source` 字段,之前没传;已补 `source: 'runtime'`,并加了真实 SkillRegistry 往返测试(list + load)防回归
package/README.en.md CHANGED
@@ -2,35 +2,37 @@
2
2
 
3
3
  English | [中文](README.md)
4
4
 
5
- Host service for dsh's file-preview surface: lists every file a session's tool calls touched — each write/edit change's diff included — and serves any file's current content for preview. Pair it with `@khorsheed/dsh-client-ui-file-preview` and the web GUI gains a Produced-files tab with inline previews and reveal-in-folder.
5
+ Every file the agent touched, on one page: what changed, and what it looks like now.
6
6
 
7
- <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview1.png" width="480" alt="the companion client's file-preview pane: file list and inline markdown preview">
7
+ This package is the host half of file preview. Install it together with the companion client, and the web GUI gains a Produced-files tab: every file the session read, wrote, or edited is listed there, each write/edit change comes with its diff, and clicking any file shows its current content. Files the agent happened to write through bash (heredocs, redirects, and the like) are collected too. The whole service is read-only — it looks at files, never touches them.
8
8
 
9
- <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview2.png" width="480" alt="per-artifact change history: pageable per-turn diffs">
10
-
11
- <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview3.png" width="480" alt="the Produced tab: every file the session wrote, at a glance">
9
+ <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview1.png" width="640" alt="the Produced tab's file preview: file list and inline markdown preview">
12
10
 
13
11
  ## Features
14
12
 
15
13
  - **Session file list** — every file the session's `read`/`write`/`edit` calls touched, with each write/edit change's diff attached.
16
- - **Content reads** — current text, capped and flagged when truncated; images as browser-loadable URLs on web hosts; binary, missing, and oversized files answer classified notices.
14
+ - **Content reads** — current text, capped and flagged when truncated; images as browser-loadable URLs on web hosts; binary, missing, and oversized files answer classified notices instead of errors.
17
15
  - **Bash-write capture** — files written through `bash` (heredocs, redirects, `tee`, `sed -i`) merged into the list, stat-verified and rebuilt after a host restart.
18
16
  - **Reveal in folder** — opens the file's folder with the file selected, on macOS, Windows, WSL, and desktop Linux.
19
17
  - **Read-only by design** — no session state, no writes; a restarted host loses nothing.
20
18
 
19
+ <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview2.png" width="640" alt="per-artifact change history: pageable per-turn diffs">
20
+
21
+ <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview3.png" width="640" alt="the Produced tab: every file the session wrote, at a glance">
22
+
21
23
  ## Install
22
24
 
23
25
  ```sh
24
26
  dsh plugin --profile web add @khorsheed/dsh-file-preview
25
27
  ```
26
28
 
27
- Host half only — install the companion client for the visible surface (Produced tab, preview drawer, per-turn change card):
29
+ Host half only — the visible surface (Produced tab, preview drawer, per-turn change card) lives in the companion client:
28
30
 
29
31
  ```sh
30
32
  dsh plugin --profile web add @khorsheed/dsh-client-ui-file-preview
31
33
  ```
32
34
 
33
- Uninstall; a leftover client half degrades to an empty state rather than an error:
35
+ Uninstall; if the client half is left behind, its zero-session handshake fails and every UI surface is absent (no error card or empty tab remains):
34
36
 
35
37
  ```sh
36
38
  dsh plugin --profile web remove @khorsheed/dsh-file-preview
@@ -51,8 +53,10 @@ dsh plugin --profile web remove @khorsheed/dsh-file-preview
51
53
 
52
54
  ## Compatibility
53
55
 
54
- - npm release line (`@deepseek-ai/dsh@0.1.1-rc.2`): ✅ full — the rc.8→0.1.1-rc.1 API audit (2026-08-21) confirms every surface this plugin consumes is unchanged or additive (the ProjectionDefinition restructure, cacheHitPercent return-type change, and the credentials/updated event rename do not touch this package); no source change was needed; re-audited for rc.2 (2026-08-22): consumed surface unchanged, full build+test green.
55
- - source line (deepseek-harness master): ✅
56
+ - npm release line (`@deepseek-ai/dsh@0.1.5-rc.1`): ✅ full — adapted to the 0.1.5-rc.1 PTC rename (only `tool/ptc-dispatch` is matched; the official v2→v3 log migration renames persisted rows), full build+test green; minHost moves up to 0.1.5-rc.1 — older hosts stay on the previous release line.
57
+ - source line (deepseek-harness master): ✅ (verifiedHost: 0.1.5-rc.1)
58
+
59
+ **Version line mapping**: the first release after 0.2.0 supports host `0.1.5-rc.1` and later; hosts on `0.1.2-rc.1` stay on `0.2.0`, hosts on `0.1.0-rc.6` ~ `0.1.1-rc.2` stay on the 0.1.x release line (last release `0.1.1`).
56
60
 
57
61
  ## Known Limitations
58
62
 
@@ -64,12 +68,15 @@ dsh plugin --profile web remove @khorsheed/dsh-file-preview
64
68
  <details>
65
69
  <summary>Internals (click to expand)</summary>
66
70
 
67
- `ctx.filePreview` (wire namespace `filePreview`) exposes four generated Remote methods:
71
+ `ctx.filePreview` (wire namespace `filePreview`) exposes six generated Remote methods:
72
+
73
+ - `capabilities()` — a zero-session availability handshake returning `{ protocolVersion: 1 }`; the companion client installs UI surfaces only after it succeeds.
68
74
 
69
- - `list(agent)` — a pure fold over `agent.session.events`: `read`/`write`/`edit` `tool/call`s contribute display paths, as do settled nested Code Mode `tool/code-dispatch`es for those tools (failed dispatches record nothing; entries borrow the root call's turn/step). A `write`/`edit` `tool/result` carrying `diffs` meta appends each change to the entry in event order, `lastDiff` kept as the final one. The response carries the entries, the last scanned seq, and whether `maxFiles` was hit. No filesystem access in the fold; with `captureBashWrites` on, entries merge with the collector's verified bash-written paths.
75
+ - `list(agent)` — a pure fold over `agent.session.events`: `read`/`write`/`edit` `tool/call`s contribute display paths, as do settled nested PTC `tool/ptc-dispatch`es for those tools (failed dispatches record nothing; entries borrow the root call's turn/step). A `write`/`edit` `tool/result` carrying `diffs` meta appends each change to the entry in event order, `lastDiff` kept as the final one. The response carries the entries, the last scanned seq, and whether `maxFiles` was hit. No filesystem access in the fold; with `captureBashWrites` on, entries merge with the collector's verified bash-written paths. Before returning, each path is resolved against the session cwd and `stat`-ed, keeping only those that still exist as a regular file — the log fold is history, the product list reflects disk state (a temp script a turn wrote then cleaned up is no longer a product); existence is probed fresh per call (not cached with the log fold).
70
76
  - `read(agent, path, signal)` — resolves `path` against the session cwd and serves `kind: 'text'` (capped at `maxReadBytes`, flagged `truncated`), or `kind: 'image'` with a browser-loadable URL on web hosts — bytes ride a dedicated `/file-preview-image/<sessionId>/<path>` route, registered only when the optional `webServer` and `agents` services are composed; headless hosts answer `binary` — or a classified notice: `binary` (binary extension or NUL bytes; never read), `missing`, `too-large`, or `error` (message included).
71
77
  - `reveal(agent, path, signal)` — opens the file's folder with the file selected, shell-free through `@deepseek-ai/dsh-native-command`: macOS `open -R`, Windows `explorer /select,<path>`, WSL via `wslpath`, desktop Linux tries `nautilus`/`dolphin`/`nemo --select` in order. Answers `{ revealed: true }`, or `false` with `reason: 'missing'` (no such target) or `'select-failed'` (no capable file manager — the caller then opens the parent folder, so the gesture always lands somewhere visible). Writes nothing.
72
- - `turnFiles(agent)` — every turn's file mutations for the turn-tail card, the same single source of truth as `list` but NOT deduped: a file touched in two turns appears in both groups, so each card lists exactly what that turn mutated. Line deltas are summed from result diffs; the fold is cached per session and invalidated by the log watermark, which the response carries for the client's own cache.
78
+ - `openExternal(agent, path, app, signal)` — open a file in a specific host application (the "open in IDE" gesture): the official open-in-app route accepts directories only, so file-exact opens go here — macOS `open -a <App> <path>`, shell-free as well. `app` is an official open-in-app catalog id (the client probes `/open-in-app/apps`); the id → `.app` name map lives in `open-external.ts` (mirroring the official catalog's darwin entries). Non-macOS hosts and unknown ids answer `{ opened: false, reason }`, and the client hides the gesture. Writes nothing.
79
+ - `turnFiles(agent)` — every turn's file mutations for the turn-tail card, the same single source of truth as `list` but NOT deduped: a file touched in two turns appears in both groups, so each card lists exactly what that turn mutated. Line deltas are summed from result diffs; the fold is cached per session and invalidated by the log watermark, which the response carries for the client's own cache. Like `list`, it probes existence against the session cwd before returning and keeps only files that still exist (a cleaned-up temp script does not occupy a card).
73
80
 
74
81
  Bash-write collector: watches each session's bash `tool/call`/`tool/result` pairs, extracts high-precision write targets (`cat > path` heredocs, single `>` redirects, `tee` non-append, `sed -i`), expands `$VAR`/`~`/relative paths against the host environment and session cwd, and records only paths `fs.stat` confirms as files (a miss beats a false positive). Captures live in a per-session in-memory registry rebuilt by replaying the session's own history on `session/created`, so a restarted host regains them; the session log itself is never mutated (the official `Session.append` cannot mark a plugin event `ignorable` — see the S2 seam in `docs/upstream-seam-registry.md`). Bash-captured files carry no diff history; previews read current content through `read`.
75
82
 
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # last confirmed-consistent state. Both languages carry equal authority; after
3
3
  # editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/file-preview/README.en.md
5
- packages/file-preview/README.en.md: 244347bb89f3796d687220bfdb44c3daf7d68a5a
6
- packages/file-preview/README.md: 3131fafedb08f02e90323172cfd4d087e3ce77a6
5
+ packages/file-preview/README.en.md: e454c9f4feefaa3bd879b7e2d277c393f46fb790
6
+ packages/file-preview/README.md: 824c988049eea742c9e0f38078161829b14660ea
package/README.md CHANGED
@@ -2,21 +2,23 @@
2
2
 
3
3
  [English](README.en.md) | 中文
4
4
 
5
- dsh 文件预览界面的宿主服务:列出会话工具调用触碰过的每个文件——附每次 write/edit 改动的 diff——并提供任一文件的当前内容用于预览。与 `@khorsheed/dsh-client-ui-file-preview` 成对安装,web GUI 即获得「产物」tab:内联预览与"在文件夹中打开"。
5
+ agent 碰过的文件一页看全:改了什么、现在长什么样。
6
6
 
7
- <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview1.png" width="480" alt="配套客户端的文件预览:文件列表与内联 markdown 预览">
7
+ 这是文件预览的宿主半。装上它和配套的界面包,web GUI 会多一个「产物」tab:会话里 agent 读过、写过、改过的每个文件都列在里面,每次 write/edit 改动附 diff,点开任一文件就能看到当前内容。agent 用 bash 顺手写的文件(heredoc、重定向之类)也一样收进来。整个服务只读——它只看文件,从不动文件。
8
8
 
9
- <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview2.png" width="480" alt="每个产物的改动记录:逐轮 diff 可翻页回看">
9
+ <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview1.png" width="640" alt="「产物」tab 的文件预览:文件列表与内联 markdown 预览">
10
10
 
11
- <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview3.png" width="480" alt="「产物」tab:会话写过的全部文件一览">
11
+ ## 功能
12
12
 
13
- ## 特性
13
+ - **会话文件清单**——会话 `read`/`write`/`edit` 调用触碰过的每个文件,每次 write/edit 改动附 diff。
14
+ - **内容读取**——文件当前文本,超限截断并标记;web 宿主上图片返回浏览器可加载的 URL;二进制、不存在、超限的文件返回分类提示而不是报错。
15
+ - **bash 写入采集**——经 `bash` 写入的文件(heredoc、重定向、`tee`、`sed -i`)并入清单,经 stat 验证,宿主重启后自动重建。
16
+ - **在文件夹中打开**——在宿主文件管理器中打开所在文件夹并选中文件,支持 macOS、Windows、WSL、桌面 Linux。
17
+ - **只读设计**——无会话状态、无写入;宿主重启不丢任何东西。
14
18
 
15
- - **会话文件清单**——会话 `read`/`write`/`edit` 调用触碰过的每个文件,每次 write/edit 改动附 diff。
16
- - **内容读取**——文件当前文本,超限截断并标记;web 宿主上图片返回浏览器可加载的 URL;二进制、不存在、超限文件返回分类提示。
17
- - **bash 写入采集**——经 `bash` 写入的文件(heredoc、重定向、`tee`、`sed -i`)并入清单,经 stat 验证,宿主重启后重建。
18
- - **在文件夹中打开**——在宿主文件管理器中打开所在文件夹并选中文件,支持 macOS、Windows、WSL、桌面 Linux。
19
- - **只读设计**——无会话状态、无写入;宿主重启不丢任何东西。
19
+ <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview2.png" width="640" alt="每个产物的改动记录:逐轮 diff 可翻页回看">
20
+
21
+ <img src="https://raw.githubusercontent.com/Khorsheed/dsh-web-basic/main/docs/screenshots/file-preview3.png" width="640" alt="「产物」tab:会话写过的全部文件一览">
20
22
 
21
23
  ## 安装
22
24
 
@@ -24,13 +26,13 @@ dsh 文件预览界面的宿主服务:列出会话工具调用触碰过的每个
24
26
  dsh plugin --profile web add @khorsheed/dsh-file-preview
25
27
  ```
26
28
 
27
- 仅宿主半——可见界面(「产物」tab、预览抽屉、回合变更卡片)在配套客户端里:
29
+ 仅宿主半——可见界面(「产物」tab、预览抽屉、回合变更卡片)在配套客户端里:
28
30
 
29
31
  ```sh
30
32
  dsh plugin --profile web add @khorsheed/dsh-client-ui-file-preview
31
33
  ```
32
34
 
33
- 卸载;残留的客户端半降级为空态而非报错:
35
+ 卸载;如果只残留客户端半,它的零会话握手会失败,全部 UI 面均缺席(不留错误卡或空 tab):
34
36
 
35
37
  ```sh
36
38
  dsh plugin --profile web remove @khorsheed/dsh-file-preview
@@ -47,41 +49,46 @@ dsh plugin --profile web remove @khorsheed/dsh-file-preview
47
49
  captureBashWrites: true
48
50
  ```
49
51
 
50
- `maxReadBytes` 限制单次 `read`(超限返回 `too-large`),`maxFiles` 限制 `list` 折叠结果——均为正整数,默认 512 KiB 与 500——`captureBashWrites`(默认 `true`)开关 bash 写入采集器。
52
+ `maxReadBytes` 限制单次 `read`(超限返回 `too-large`),`maxFiles` 限制 `list` 折叠结果——均为正整数,默认 512 KiB 与 500——`captureBashWrites`(默认 `true`)开关 bash 写入采集器。
51
53
 
52
54
  ## Compatibility
53
55
 
54
- - npm 发布线(`@deepseek-ai/dsh@0.1.1-rc.2`):✅ 完整——rc.8→0.1.1-rc.1 API 审计(2026-08-21)确认本插件消费的所有面无变化或纯增量(ProjectionDefinition 重构、cacheHitPercent 返回值变更、credentials/updated 事件改名均不涉及本包),无需改动源码;rc.1→rc.2 复核(2026-08-22):消费面无变化,全量构建测试通过。
55
- - 源码线(deepseek-harness master):✅
56
+ - npm 发布线(`@deepseek-ai/dsh@0.1.5-rc.1`):✅ 完整——适配 0.1.5-rc.1 的 PTC 更名(只匹配 `tool/ptc-dispatch`;旧日志由官方 v2→v3 迁移改写到新名),全量构建测试通过;minHost 前移至 0.1.5-rc.1,旧宿主请停留在旧发布线。
57
+ - 源码线(deepseek-harness master):✅(verifiedHost: 0.1.5-rc.1)
58
+
59
+ **版本线对照**:0.2.0 之后的首个发布起支持宿主 `0.1.5-rc.1` 及以后;宿主 `0.1.2-rc.1` 请停留在 `0.2.0`,宿主 `0.1.0-rc.6` ~ `0.1.1-rc.2` 请停留在 0.1.x 发布线(末版 `0.1.1`)。
56
60
 
57
- ## 已知限制
61
+ ## Known Limitations
58
62
 
59
- - **列表是时间点折叠**——没有推送通道;客户端通过重新调用 `list` 刷新。
63
+ - **列表是时间点折叠**——没有推送通道;客户端通过重新调用 `list` 刷新。
60
64
  - **不提供二进制预览内容**——非图片二进制文件只返回 `kind: 'binary'` 及大小。
61
65
 
62
66
  ## 实现原理
63
67
 
64
68
  <details>
65
- <summary>内部结构(点击展开)</summary>
69
+ <summary>内部结构(点击展开)</summary>
70
+
71
+ `ctx.filePreview`(wire 命名空间 `filePreview`)暴露六个生成的 Remote 方法:
66
72
 
67
- `ctx.filePreview`(wire 命名空间 `filePreview`)暴露四个生成的 Remote 方法:
73
+ - `capabilities()`——零会话可用性握手,返回 `{ protocolVersion: 1 }`;配套客户端只在握手成功后安装 UI 面。
68
74
 
69
- - `list(agent)`——对 `agent.session.events` 的纯折叠:`read`/`write`/`edit` 的 `tool/call` 贡献展示路径,这些工具的已完结嵌套 Code Mode `tool/code-dispatch` 同样计入(失败的派发不记录;条目借用根调用的 turn/step)。携带 `diffs` 元数据的 `write`/`edit` `tool/result` 把每次改动按事件序追加进条目,`lastDiff` 保留为最后一次。响应携带条目、最后扫描的 seq,以及是否触达 `maxFiles`。折叠本身不访问文件系统;`captureBashWrites` 开启时并入采集器验证过的 bash 写入路径。
70
- - `read(agent, path, signal)`——以会话 cwd 为基准解析 `path`,返回 `kind: 'text'`(超过 `maxReadBytes` 截断并标记 `truncated`);web 宿主上图片返回 `kind: 'image'` 及浏览器可加载 URL——字节走专门的 `/file-preview-image/<sessionId>/<path>` 路由,仅当组合了可选的 `webServer` 与 `agents` 服务时注册;无 web 宿主返回 `binary`——否则返回分类提示:`binary`(二进制扩展名或 NUL 字节;绝不读取)、`missing`、`too-large`、`error`(含消息)。
71
- - `reveal(agent, path, signal)`——在宿主文件管理器中打开文件所在文件夹并选中它,全程无 shell,走 `@deepseek-ai/dsh-native-command`:macOS `open -R`、Windows `explorer /select,<path>`、WSL 经 `wslpath`、桌面 Linux 依次尝试 `nautilus`/`dolphin`/`nemo --select`。选中返回 `{ revealed: true }`,否则 `false` 及 `reason: 'missing'`(目标不存在)或 `'select-failed'`(无可用文件管理器——调用方改开父文件夹,手势总能落在可见处)。不写入任何东西。
72
- - `turnFiles(agent)`——每个回合的文件变更,回合卡片与 `list` 同源但**不**去重:同一文件在两个回合改过,两个分组都有它——每张卡片精确列出该回合改了什么。行数增减由 result diff 求和;折叠按会话缓存、由日志水位线失效,响应携带水位线供客户端自缓存。
75
+ - `list(agent)`——对 `agent.session.events` 的纯折叠:`read`/`write`/`edit` 的 `tool/call` 贡献展示路径,这些工具的已完结嵌套 PTC `tool/ptc-dispatch` 同样计入(失败的派发不记录;条目借用根调用的 turn/step)。携带 `diffs` 元数据的 `write`/`edit` `tool/result` 把每次改动按事件序追加进条目,`lastDiff` 保留为最后一次。响应携带条目、最后扫描的 seq,以及是否触达 `maxFiles`。折叠本身不访问文件系统;`captureBashWrites` 开启时并入采集器验证过的 bash 写入路径。返回前按会话 cwd 解析每条路径并 `stat`,只保留当前仍存在的常规文件——日志折叠是历史,产物列表只看磁盘现状(某回合写后又清理的临时脚本不再是产物);存在性每次调用都现查(不随日志折叠缓存)。
76
+ - `read(agent, path, signal)`——以会话 cwd 为基准解析 `path`,返回 `kind: 'text'`(超过 `maxReadBytes` 截断并标记 `truncated`);web 宿主上图片返回 `kind: 'image'` 及浏览器可加载 URL——字节走专门的 `/file-preview-image/<sessionId>/<path>` 路由,仅当组合了可选的 `webServer` 与 `agents` 服务时注册;无 web 宿主返回 `binary`——否则返回分类提示:`binary`(二进制扩展名或 NUL 字节;绝不读取)、`missing`、`too-large`、`error`(含消息)。
77
+ - `reveal(agent, path, signal)`——在宿主文件管理器中打开文件所在文件夹并选中它,全程无 shell,走 `@deepseek-ai/dsh-native-command`:macOS `open -R`、Windows `explorer /select,<path>`、WSL 经 `wslpath`、桌面 Linux 依次尝试 `nautilus`/`dolphin`/`nemo --select`。选中返回 `{ revealed: true }`,否则 `false` 及 `reason: 'missing'`(目标不存在)或 `'select-failed'`(无可用文件管理器——调用方改开父文件夹,手势总能落在可见处)。不写入任何东西。
78
+ - `openExternal(agent, path, app, signal)`——在指定宿主应用中打开文件(「在 IDE 打开」手势):官方 open-in-app 路由只收目录,文件级打开走这里——macOS `open -a <App> <path>`,同样无 shell。`app` 是官方 open-in-app catalog id(客户端经 `/open-in-app/apps` 探测);id → `.app` 名映射在 `open-external.ts`(镜像官方 catalog 的 darwin 条目)。非 macOS 或未知 id 返回 `{ opened: false, reason }`,客户端据此隐藏手势。不写入任何东西。
79
+ - `turnFiles(agent)`——每个回合的文件变更,回合卡片与 `list` 同源但**不**去重:同一文件在两个回合改过,两个分组都有它——每张卡片精确列出该回合改了什么。行数增减由 result diff 求和;折叠按会话缓存、由日志水位线失效,响应携带水位线供客户端自缓存。与 `list` 一样,返回前按会话 cwd 校验存在性,只保留当前仍存在的文件(被清理的临时脚本不占卡片)。
73
80
 
74
- bash 写入采集器:监听每个会话的 bash `tool/call`/`tool/result` 配对,提取高精度写入目标(`cat > path` heredoc、单 `>` 重定向、`tee` 非追加、`sed -i`),按宿主环境与会话 cwd 展开 `$VAR`/`~`/相对路径,只记录 `fs.stat` 确认为文件的路径(宁缺毋滥)。采集结果存于按会话的内存登记表,`session/created` 时重放会话自身历史重建——宿主重启后不丢;会话日志本身绝不被改动(官方 `Session.append` 无法给插件事件标 `ignorable`——见 `docs/upstream-seam-registry.md` 的 S2 条目)。bash 采集的文件没有 diff 历史;预览与普通条目一样通过 `read` 读当前内容。
81
+ bash 写入采集器:监听每个会话的 bash `tool/call`/`tool/result` 配对,提取高精度写入目标(`cat > path` heredoc、单 `>` 重定向、`tee` 非追加、`sed -i`),按宿主环境与会话 cwd 展开 `$VAR`/`~`/相对路径,只记录 `fs.stat` 确认为文件的路径(宁缺毋滥)。采集结果存于按会话的内存登记表,`session/created` 时重放会话自身历史重建——宿主重启后不丢;会话日志本身绝不被改动(官方 `Session.append` 无法给插件事件标 `ignorable`——见 `docs/upstream-seam-registry.md` 的 S2 条目)。bash 采集的文件没有 diff 历史;预览与普通条目一样通过 `read` 读当前内容。
75
82
 
76
- 信任与状态:受信任的只读能力——能读取 `ctx.fs` 允许会话访问的一切,组合它即授予对会话文件系统视图的预览权限;它不是安全边界。不产生会话事件;仅有的按会话状态是回合折叠缓存与 bash 采集器的已验证写入登记表。
83
+ 信任与状态:受信任的只读能力——能读取 `ctx.fs` 允许会话访问的一切,组合它即授予对会话文件系统视图的预览权限;它不是安全边界。不产生会话事件;仅有的按会话状态是回合折叠缓存与 bash 采集器的已验证写入登记表。
77
84
 
78
- 分享:纯宿主侧增量——一个 Remote 服务,由浏览器半经官方的 `ctx.remote.$mount` 通道挂载。浏览器半(`@khorsheed/dsh-client-ui-file-preview`)同样纯增量;两个包独立分发,零改动组合进原版 dsh 核心。
85
+ 分享:纯宿主侧增量——一个 Remote 服务,由浏览器半经官方的 `ctx.remote.$mount` 通道挂载。浏览器半(`@khorsheed/dsh-client-ui-file-preview`)同样纯增量;两个包独立分发,零改动组合进原版 dsh 核心。
79
86
 
80
87
  </details>
81
88
 
82
89
  ## 开发
83
90
 
84
- 隶属 [dsh-plugins](https://github.com/Khorsheed/dsh-plugins) monorepo(`packages/file-preview`)。问题与贡献请移步该仓库。
91
+ 隶属 [dsh-plugins](https://github.com/Khorsheed/dsh-plugins) monorepo(`packages/file-preview`)。问题与贡献请移步该仓库。
85
92
 
86
93
  ## 变更记录
87
94