@wisdoverse/dsh-inline-media-viewer 1.0.1

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 ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ ## 1.0.1
4
+
5
+ - Publish the plugin as `@wisdoverse/dsh-inline-media-viewer` for one-command
6
+ installation through the DSH plugin manager.
7
+ - Align the bundle manifest, package metadata, and bilingual installation
8
+ documentation with the scoped package name.
9
+
10
+ ## 1.0.0
11
+
12
+ - **Initial public release.** Inline image/video/audio previews in the
13
+ conversation tail (`conversation.chat.turnTail` projection): any media
14
+ path or media URL mentioned in a chat turn renders inline under that
15
+ turn.
16
+ - **Workspace-confined local reads** — a path renders only when it
17
+ resolves inside the calling session's workspace root (`realpath` +
18
+ containment; no symlink escapes).
19
+ - **Configurable ComfyUI proxy** — media URLs on the local aliases
20
+ (`127.0.0.1`/`localhost` on port 8188) or on the configured server
21
+ address are fetched server-side from the configured origin, with
22
+ redirects refused, a 20 s timeout, and a 48 MiB cap.
23
+ - **Settings page** (媒体预览 / Media preview): auto-render toggle,
24
+ per-turn cap (1–30), max media height (160–1200 px), ComfyUI server
25
+ address — persisted through the DSH settings document (loopback
26
+ writes).
27
+ - **Pure helpers** in a dependency-free `lib.js` with a zero-dependency
28
+ unit test runner (`node test.mjs`), plus README, SECURITY, and MIT
29
+ LICENSE.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Wisdoverse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,166 @@
1
+ <h1 align="center">dsh-inline-media-viewer</h1>
2
+
3
+ <p align="center">
4
+ <strong>Inline image, video, and audio previews for DeepSeek Harness Web</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="CHANGELOG.md"><img alt="Latest tag" src="https://img.shields.io/github/v/tag/Wisdoverse/dsh-inline-media-viewer-plugin?style=flat-square&amp;label=version"></a>
9
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/github/license/Wisdoverse/dsh-inline-media-viewer-plugin?style=flat-square"></a>
10
+ <a href="package.json"><img alt="Top language" src="https://img.shields.io/github/languages/top/Wisdoverse/dsh-inline-media-viewer-plugin?style=flat-square"></a>
11
+ <a href="#configuration"><img alt="ComfyUI support" src="https://img.shields.io/badge/ComfyUI-supported-ff6f00?style=flat-square"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <strong>English</strong> · <a href="README.zh-CN.md">简体中文</a>
16
+ </p>
17
+
18
+ Turn media paths and URLs mentioned in a DSH conversation into secure inline
19
+ previews—without copying them out of the chat log.
20
+
21
+ ```text
22
+ https://…/view?filename=frame.png → <img>
23
+ exports/demo.mp4 → <video controls>
24
+ audio/sound.mp3 → <audio controls>
25
+ ```
26
+
27
+ ## Contents
28
+
29
+ - [Features](#features)
30
+ - [Supported media](#supported-media)
31
+ - [Installation](#installation)
32
+ - [Configuration](#configuration)
33
+ - [Security](#security)
34
+ - [Development](#development)
35
+ - [License](#license)
36
+
37
+ ## Features
38
+
39
+ | Feature | Description |
40
+ | --- | --- |
41
+ | Inline rendering | Displays images, videos, and audio directly below the chat turn that mentions them. |
42
+ | Workspace-safe reads | Resolves local paths with `realpath` and rejects traversal, out-of-workspace paths, and symlink escapes. |
43
+ | ComfyUI proxy | Fetches recognized ComfyUI media URLs server-side from the configured origin, including for remote users and HTTPS pages. |
44
+ | Bounded transfers | Limits each file or response to 48 MiB and remote requests to 20 seconds. |
45
+ | User controls | Provides auto-render, per-turn item limit, media height, and ComfyUI origin settings. |
46
+
47
+ ## Supported media
48
+
49
+ | Type | Extensions |
50
+ | --- | --- |
51
+ | Images | `png`, `jpg`, `jpeg`, `webp`, `gif`, `avif`, `bmp`, `svg` |
52
+ | Video | `mp4`, `webm`, `mov`, `m4v`, `mkv`, `avi`, `ogv` |
53
+ | Audio | `mp3`, `wav`, `m4a`, `aac`, `ogg`, `oga`, `flac`, `opus` |
54
+
55
+ ## Installation
56
+
57
+ ### From npm
58
+
59
+ Install and activate the bundle in your Web profile:
60
+
61
+ ```bash
62
+ dsh plugin --profile web add @wisdoverse/dsh-inline-media-viewer
63
+ ```
64
+
65
+ Restart the Web profile after installation.
66
+
67
+ ### From source
68
+
69
+ 1. Clone the plugin into a location available to your Web profile:
70
+
71
+ ```bash
72
+ git clone https://github.com/Wisdoverse/dsh-inline-media-viewer-plugin.git \
73
+ /path/to/local-plugins/dsh-inline-media-viewer
74
+ ```
75
+
76
+ 2. Add the bundle to `profiles/web/package.json`:
77
+
78
+ ```jsonc
79
+ {
80
+ "dependencies": {
81
+ "@wisdoverse/dsh-inline-media-viewer": "link:/path/to/local-plugins/dsh-inline-media-viewer"
82
+ },
83
+ "dsh": {
84
+ "profile": {
85
+ "bundles": ["…", "@wisdoverse/dsh-inline-media-viewer"]
86
+ }
87
+ }
88
+ }
89
+ ```
90
+
91
+ 3. Rebuild or restart the Web profile.
92
+
93
+ The plugin mounts its host RPC channel, client projection, and settings section
94
+ through [`cordis.patch.yml`](cordis.patch.yml).
95
+
96
+ ## Configuration
97
+
98
+ Open **Settings → 媒体预览 / Media preview**.
99
+
100
+ | Setting | Default | Allowed values |
101
+ | --- | --- | --- |
102
+ | Auto-render detected media | On | On / off |
103
+ | Maximum items per turn | `12` | `1`–`30` |
104
+ | Maximum media height | `380 px` | `160`–`1200 px` |
105
+ | ComfyUI origin | Empty | `http(s)://host[:port]` |
106
+
107
+ Settings are stored in the DSH settings document. Writes are available only on
108
+ loopback connections; remote browsers can read settings but cannot persist
109
+ changes.
110
+
111
+ ### ComfyUI origin
112
+
113
+ - Leave the field empty to use `http://127.0.0.1:8188`.
114
+ - Accepted forms are `http://host[:port]`, `https://host[:port]`, and bare
115
+ `host[:port]` (`http` is assumed).
116
+ - The default port is `8188` for HTTP and `443` for HTTPS.
117
+ - Credentials, paths, query strings, and fragments are rejected.
118
+ - The origin must be reachable from the DSH host process. For a containerized
119
+ host, use the address visible from inside the container.
120
+
121
+ Local aliases (`127.0.0.1:8188` and `localhost:8188`) and the configured origin
122
+ are recognized as ComfyUI sources. A non-empty invalid address fails explicitly
123
+ instead of silently falling back to another target.
124
+
125
+ ## Security
126
+
127
+ The plugin is designed as a local trust helper, not a general-purpose file or
128
+ network proxy:
129
+
130
+ - Local reads are confined to the active session's workspace and known media
131
+ extensions.
132
+ - Remote reads can target only the configured ComfyUI origin; redirects are
133
+ refused.
134
+ - Local files and remote responses are capped at 48 MiB.
135
+ - Settings writes are restricted to loopback connections.
136
+ - The browser receives media as `data:` URLs rather than filesystem paths.
137
+
138
+ See [SECURITY.md](SECURITY.md) for the complete trust model and known
139
+ limitations.
140
+
141
+ ## Development
142
+
143
+ ### Commands
144
+
145
+ | Command | Purpose |
146
+ | --- | --- |
147
+ | `node test.mjs` | Run the dependency-free unit tests directly. |
148
+ | `npm test` | Run the same unit test suite through npm. |
149
+ | `npm run lint` | Syntax-check the host modules and test file. |
150
+
151
+ ### Project structure
152
+
153
+ | Path | Responsibility |
154
+ | --- | --- |
155
+ | `index.js` | Host RPC channel, ComfyUI proxy, and settings registration. |
156
+ | `lib.js` | Pure, dependency-free helpers. |
157
+ | `client/client.js` | Turn projection, media renderer, and settings UI. |
158
+ | `cordis.patch.yml` | Bundle mounting and integration points. |
159
+ | `test.mjs` | Unit tests for the pure helpers. |
160
+
161
+ The running Web profile serves a bundled copy. Rebuild or restart it after
162
+ changing the source files.
163
+
164
+ ## License
165
+
166
+ Released under the [MIT License](LICENSE).
@@ -0,0 +1,155 @@
1
+ <h1 align="center">dsh-inline-media-viewer</h1>
2
+
3
+ <p align="center">
4
+ <strong>为 DeepSeek Harness Web 提供内联图像、视频和音频预览</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="CHANGELOG.md"><img alt="最新标签" src="https://img.shields.io/github/v/tag/Wisdoverse/dsh-inline-media-viewer-plugin?style=flat-square&amp;label=version"></a>
9
+ <a href="LICENSE"><img alt="许可证" src="https://img.shields.io/github/license/Wisdoverse/dsh-inline-media-viewer-plugin?style=flat-square"></a>
10
+ <a href="package.json"><img alt="主要语言" src="https://img.shields.io/github/languages/top/Wisdoverse/dsh-inline-media-viewer-plugin?style=flat-square"></a>
11
+ <a href="#配置"><img alt="支持 ComfyUI" src="https://img.shields.io/badge/ComfyUI-supported-ff6f00?style=flat-square"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="README.md">English</a> · <strong>简体中文</strong>
16
+ </p>
17
+
18
+ 将 DSH 对话中出现的媒体路径和 URL 安全地转换为内联预览,无需再从聊天日志中复制路径。
19
+
20
+ ```text
21
+ https://…/view?filename=frame.png → <img>
22
+ exports/demo.mp4 → <video controls>
23
+ audio/sound.mp3 → <audio controls>
24
+ ```
25
+
26
+ ## 目录
27
+
28
+ - [功能特性](#功能特性)
29
+ - [支持的媒体格式](#支持的媒体格式)
30
+ - [安装](#安装)
31
+ - [配置](#配置)
32
+ - [安全设计](#安全设计)
33
+ - [开发](#开发)
34
+ - [许可证](#许可证)
35
+
36
+ ## 功能特性
37
+
38
+ | 特性 | 说明 |
39
+ | --- | --- |
40
+ | 内联渲染 | 在提及媒体的聊天消息下方直接显示图像、视频和音频。 |
41
+ | 工作区安全读取 | 使用 `realpath` 解析本地路径,并拒绝目录穿越、工作区外路径和符号链接逃逸。 |
42
+ | ComfyUI 代理 | 由服务端从配置的源站获取识别到的 ComfyUI 媒体 URL,使远程用户和 HTTPS 页面也能正常查看。 |
43
+ | 资源限制 | 每个文件或响应最大 48 MiB,远程请求最长 20 秒。 |
44
+ | 用户控制 | 提供自动渲染、每条消息的媒体数量、媒体高度和 ComfyUI 源站设置。 |
45
+
46
+ ## 支持的媒体格式
47
+
48
+ | 类型 | 扩展名 |
49
+ | --- | --- |
50
+ | 图像 | `png`、`jpg`、`jpeg`、`webp`、`gif`、`avif`、`bmp`、`svg` |
51
+ | 视频 | `mp4`、`webm`、`mov`、`m4v`、`mkv`、`avi`、`ogv` |
52
+ | 音频 | `mp3`、`wav`、`m4a`、`aac`、`ogg`、`oga`、`flac`、`opus` |
53
+
54
+ ## 安装
55
+
56
+ ### 通过 npm 安装
57
+
58
+ 在 Web profile 中安装并启用 Bundle:
59
+
60
+ ```bash
61
+ dsh plugin --profile web add @wisdoverse/dsh-inline-media-viewer
62
+ ```
63
+
64
+ 安装后重启 Web profile。
65
+
66
+ ### 从源码安装
67
+
68
+ 1. 将插件克隆到 Web profile 可以访问的位置:
69
+
70
+ ```bash
71
+ git clone https://github.com/Wisdoverse/dsh-inline-media-viewer-plugin.git \
72
+ /path/to/local-plugins/dsh-inline-media-viewer
73
+ ```
74
+
75
+ 2. 将插件添加到 `profiles/web/package.json`:
76
+
77
+ ```jsonc
78
+ {
79
+ "dependencies": {
80
+ "@wisdoverse/dsh-inline-media-viewer": "link:/path/to/local-plugins/dsh-inline-media-viewer"
81
+ },
82
+ "dsh": {
83
+ "profile": {
84
+ "bundles": ["…", "@wisdoverse/dsh-inline-media-viewer"]
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ 3. 重新构建或重启 Web profile。
91
+
92
+ 插件通过 [`cordis.patch.yml`](cordis.patch.yml) 挂载宿主 RPC 通道、客户端投影和设置区域。
93
+
94
+ ## 配置
95
+
96
+ 打开 **设置 → 媒体预览 / Media preview**。
97
+
98
+ | 设置项 | 默认值 | 可选范围 |
99
+ | --- | --- | --- |
100
+ | 自动渲染检测到的媒体 | 开启 | 开启 / 关闭 |
101
+ | 每条消息的最大媒体数量 | `12` | `1`–`30` |
102
+ | 媒体最大高度 | `380 px` | `160`–`1200 px` |
103
+ | ComfyUI 源站 | 留空 | `http(s)://host[:port]` |
104
+
105
+ 设置值保存在 DSH 设置文档中。只有回环连接可以写入;远程浏览器可以读取设置,但不能持久化修改。
106
+
107
+ ### ComfyUI 源站
108
+
109
+ - 留空时使用 `http://127.0.0.1:8188`。
110
+ - 支持 `http://host[:port]`、`https://host[:port]` 和不带协议的
111
+ `host[:port]`(默认使用 `http`)。
112
+ - HTTP 的默认端口为 `8188`,HTTPS 的默认端口为 `443`。
113
+ - 不允许包含凭据、路径、查询字符串或片段。
114
+ - 该地址必须能从 DSH 宿主进程访问。如果宿主运行在容器中,请填写容器内部可见的地址。
115
+
116
+ 本地别名(`127.0.0.1:8188` 和 `localhost:8188`)以及配置的源站都会被识别为
117
+ ComfyUI 来源。非空的无效地址会明确报错,而不会静默回退到其他目标。
118
+
119
+ ## 安全设计
120
+
121
+ 本插件是本地信任辅助工具,不是通用的文件或网络代理:
122
+
123
+ - 本地读取仅限当前会话的工作区和已知媒体扩展名。
124
+ - 远程读取只能访问配置的 ComfyUI 源站,并拒绝重定向。
125
+ - 本地文件和远程响应均限制为最大 48 MiB。
126
+ - 设置写入仅允许回环连接。
127
+ - 浏览器接收的是 `data:` URL,而不是文件系统路径。
128
+
129
+ 完整的信任模型和已知限制请参阅 [SECURITY.md](SECURITY.md)。
130
+
131
+ ## 开发
132
+
133
+ ### 常用命令
134
+
135
+ | 命令 | 用途 |
136
+ | --- | --- |
137
+ | `node test.mjs` | 直接运行无依赖的单元测试。 |
138
+ | `npm test` | 通过 npm 运行同一套单元测试。 |
139
+ | `npm run lint` | 对宿主模块和测试文件执行语法检查。 |
140
+
141
+ ### 项目结构
142
+
143
+ | 路径 | 职责 |
144
+ | --- | --- |
145
+ | `index.js` | 宿主 RPC 通道、ComfyUI 代理和设置注册。 |
146
+ | `lib.js` | 无依赖的纯辅助函数。 |
147
+ | `client/client.js` | 消息投影、媒体渲染器和设置界面。 |
148
+ | `cordis.patch.yml` | Bundle 挂载和集成点。 |
149
+ | `test.mjs` | 纯辅助函数的单元测试。 |
150
+
151
+ 运行中的 Web profile 使用构建后的副本。修改源文件后,请重新构建或重启 Web profile。
152
+
153
+ ## 许可证
154
+
155
+ 本项目采用 [MIT 许可证](LICENSE)。
package/SECURITY.md ADDED
@@ -0,0 +1,67 @@
1
+ # Security
2
+
3
+ This plugin renders media in a user's chat. It is a **local trust helper**, not
4
+ a security boundary: the conversation content it renders is produced by the
5
+ same session that views it. What shipping standards demand here is that the
6
+ plugin *cannot be turned into a wider primitive* — no arbitrary local file
7
+ exfiltration, no arbitrary SSRF, no unbounded memory use.
8
+
9
+ ## Local file reads
10
+
11
+ - Only the session's workspace root is readable: `realpath(cwd)` + containment
12
+ check (`isInside`) against the resolved target. Symlink escapes, `..`
13
+ traversal, and out-of-workspace paths are rejected.
14
+ - Only known media extensions are accepted (MIME map in `lib.js`).
15
+ - Size cap: 48 MiB per file.
16
+ - The client must supply a valid session id; the workspace root is taken from
17
+ that session's header, never from client input.
18
+
19
+ ## Remote (ComfyUI) proxy
20
+
21
+ - The fetch target is always the **configured ComfyUI origin** (default
22
+ `http://127.0.0.1:8188`, `comfyUrl` in the `inline-media` settings
23
+ namespace) — never the source host. Chat content can therefore only
24
+ select a path/query on a server the user configured, not an arbitrary
25
+ host.
26
+ - A source URL is accepted only when its host:port is a local alias
27
+ (`127.0.0.1` / `localhost` on port 8188) **or** matches the configured
28
+ origin; everything else is rejected before any network I/O.
29
+ - The configured address is validated to a bare `http(s)://host[:port]`
30
+ origin: credentials, paths, queries, hashes, and odd hostnames are
31
+ rejected. A non-empty invalid value fails remote reads with an explicit
32
+ error instead of silently retargeting; an empty value uses the built-in
33
+ default.
34
+ - Settings writes are loopback-only (see below), so only the local user
35
+ can point the proxy at another host — a remote viewer cannot retarget it.
36
+ - `redirect: "error"` — redirects are refused.
37
+ - 20 s timeout, 48 MiB response cap, and the response MIME must be
38
+ image/video/audio.
39
+
40
+ ## Transport
41
+
42
+ - The media channel `/inline-media/read` is registered with the DSH
43
+ connection service (`authority: "trusted-host"`), so it runs under the same
44
+ browser-trust fence and session gating as DSH's own RPC surface.
45
+ - The client renderer never receives file system paths back — only `data:`
46
+ URLs — so a hostile session cannot use the channel as a file oracle for
47
+ paths the UI already knows.
48
+
49
+ ## Settings
50
+
51
+ - Values are normalized client-side and validated server-side against the
52
+ schema (autoRender boolean; displayCap 1–30; imageMaxPx 160–1200;
53
+ comfyUrl string ≤ 512 chars, parsed to a bare origin at use time).
54
+ - The settings service only writes back for **loopback** connections; remote
55
+ browsers are read-only, so a remote viewer cannot persist state.
56
+
57
+ ## Known limitations
58
+
59
+ - Remote (non-loopback) browsers cannot persist settings by design (DSH
60
+ settings writes are loopback-only).
61
+ - ComfyUI on a non-standard host/port: set the server address in the settings
62
+ page. The proxy fetches only from that configured origin, so it must be
63
+ reachable from the DSH host process — plain `http://` for a local install,
64
+ `https://` behind a TLS-terminating proxy. The loopback aliases
65
+ (`127.0.0.1`/`localhost` on port 8188) are always accepted as source
66
+ origins; editing `COMFY_HOSTS`/`COMFY_PORTS` is deliberate code surgery,
67
+ not a configuration surface.