dsh-mosaic 1.1.3 → 1.1.5
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 +19 -0
- package/README.md +5 -4
- package/docs/catalog-entry.example.yml +4 -4
- package/lib/render-tool.js +12 -4
- package/lib/validate-tool.js +9 -6
- package/package.json +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
> 兼容性分两处表达:`package.json` 的 `engines.dsh` 给机器可读的范围,README「安装」一节给「插件版本 ↔ 实测 Harness 版本」对照表;每次在真实 Harness 上验证后更新这两处。
|
|
5
5
|
> `0.2.1` 及各 `0.2.1-<标签>` 是改规则前的历史版本,保留用于追溯。
|
|
6
6
|
|
|
7
|
+
## 1.1.5 — 2026-11-06
|
|
8
|
+
|
|
9
|
+
### 变更
|
|
10
|
+
|
|
11
|
+
- 仓库迁移到 `dsh-plugins` monorepo;运行时代码与 `1.1.4` 相同。
|
|
12
|
+
- 加入 DSH 兼容性 harness 与 tag 触发的 OIDC 发布流程;`engines.dsh` 不变。
|
|
13
|
+
|
|
14
|
+
## 1.1.4
|
|
15
|
+
|
|
16
|
+
### 修复
|
|
17
|
+
|
|
18
|
+
- `render_view` 与 `validate_view` 的 `presentResult` 把宿主传入的 `ToolResult`(`content`、`isError`、`meta`)当成了工具自己的规范输出值:前者读不到 `title`,已完成卡片永远显示 “Render view”;后者读不到 `status`,永远显示 “Validate dsh-view: invalid”。现在改读 `output.presentationMeta` 落下的 `meta`,`validate_view` 相应补上 `presentationMeta`。
|
|
19
|
+
- 测试按真实契约传 `ToolResult`,并覆盖「只给规范输出值」这条错误形状,避免回归。
|
|
20
|
+
|
|
21
|
+
### 文档
|
|
22
|
+
|
|
23
|
+
- 兼容性对照表补上 `0.2.2-rc.1` 实测:工具、自有路由、Client 插槽与设置页图标均正常;`settings.section.icon` 在 `0.2.2` 起真正渲染。
|
|
24
|
+
- 已知边界里的围栏扩展点说明从「0.2.1 全系列」扩到「0.2.1、0.2.2 全系列」。
|
|
25
|
+
|
|
7
26
|
## 1.1.3
|
|
8
27
|
|
|
9
28
|
- 设置页的导航图标改用插件自己的 mark(内联 SVG,按面板请求的边长渲染),不再和 General 共用同一个齿轮。注册走 `settings.section.icon`:Harness `0.2.1-rc.5` 还没有这个插槽,注册保持静默,升级到声明它的版本后自动生效。
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Mosaic 是一个轻量的 DeepSeek Harness 可视化回答插件。它把模型
|
|
|
17
17
|
|
|
18
18
|
实际 DSH Web 页面渲染:
|
|
19
19
|
|
|
20
|
-

|
|
21
21
|
|
|
22
22
|
## 两个通道
|
|
23
23
|
|
|
@@ -108,14 +108,14 @@ grep -c '"event":"tool.failed"' "$DSH_HOME"/logs/dsh-mosaic/*.jsonl
|
|
|
108
108
|
|
|
109
109
|
## 已知边界
|
|
110
110
|
|
|
111
|
-
- 本插件的 npm 版本独立递增(当前 `1.1.
|
|
112
|
-
- 围栏渲染靠扫描页面里的代码块实现:0.2.1 全系列(实测 rc.3 与 rc.
|
|
111
|
+
- 本插件的 npm 版本独立递增(当前 `1.1.4`),不再与 Harness 版本号对齐;兼容范围由 `package.json` 的 `engines.dsh` 声明,最近一次实测的 Harness 版本见「安装」一节。
|
|
112
|
+
- 围栏渲染靠扫描页面里的代码块实现:0.2.1、0.2.2 全系列(实测 rc.3、rc.5 与 0.2.2-rc.1,master 同样)都没有给插件开放「渲染 fenced code block」的扩展点。工具通道 `render_view` + `tool.call.toolview` 是原生做法,围栏是它的补充。
|
|
113
113
|
- 从 0.2.1 起代码块由 Shiki 渲染,`<code>` 上**没有** `language-*` 类;识别靠「代码块位于 assistant 行内 + 正文能解析成合法视图 spec」这条路径,用户消息、工具结果、推理块里的代码块都被排除。
|
|
114
114
|
- `diagram` 与 `chart` 自带缩放/平移:卡片右上角有 `−`/`+`/`⟲`/`⤢`,放大后按住图面拖动即可平移,`Ctrl/⌘ + 滚轮`缩放,双击复位;示意图按原始尺寸渲染,不会被压缩到卡片宽度。触屏上图表区域只拦横向拖动(`touch-action: pan-y`),手指上下划仍然滚动聊天页面。
|
|
115
115
|
- `widget` 里调用 `window.mosaic.action()` 只有**真实用户手势**之后才会把动作发回模型:Widget 自己也在判断 `navigator.userActivation`,但决定权在宿主——消息的 nonce 就写在 Widget 自己的文档里,模型代码能读出来直接伪造,所以父页面独立再校验一次自己文档的激活状态。确实需要自行提交的 Widget 要在节点上写 `actions: "programmatic"`;无论哪种,整个会话共享「每分钟 10 次、单次 payload 16 KB(按 UTF-8 字节算)」的额度,新开一个 Widget 不会重置。浏览器若不提供 `navigator.userActivation`,非 `programmatic` 的 Widget 会被按「没有手势」处理,按钮不会回模型。
|
|
116
116
|
- `widget` 是 iframe,拿不到宿主的 `ctx.locale`,因此内部文案由调用方自己写;主题靠宿主令牌值传入。围栏是独立的 React root,切换外观不会触发它重渲染,所以 widget 会观察 `body[data-ds-dark-theme]` 这一个外观属性并在变化时重发令牌——这是插件唯一读取的宿主属性。
|
|
117
117
|
- Mermaid 资产走包内私有路由 `/dsh-mosaic/assets`;没有 Web 服务时 diagram 回落到内置 SVG 布局。
|
|
118
|
-
- 设置页的导航图标走 `settings.section.icon` 插槽。Harness `0.2.1-rc.5` 的导航图标是写死的映射,没有这个插槽,Mosaic
|
|
118
|
+
- 设置页的导航图标走 `settings.section.icon` 插槽。Harness `0.2.1-rc.5` 的导航图标是写死的映射,没有这个插槽,Mosaic 会落到默认齿轮;`0.2.2` 起声明了该插槽,实测 `0.2.2-rc.1` 已显示 Mosaic 自己的 mark,插件不用再改。
|
|
119
119
|
- 自有路由(`/prompt`、`/log`)先验 **Host 必须是本机权威**(loopback、监听地址,或 `config.trustedHosts` 里声明的),再验 `Sec-Fetch-Site` 与 `Origin`。只比 Origin 和 Host 挡不住 DNS rebinding:被 rebinding 的页面这两者都等于攻击者域名,看起来完全同源。宿主把 Web 服务绑到非 loopback 地址时,请把对应主机名写进 `config.trustedHosts`,否则这些路由会拒绝请求。
|
|
120
120
|
- bundle patch 只插入 Mosaic 自己这一行,不改动任何其他插件。若你还装了别的围栏类插件,两者可以对同一段围栏各显一套,按需在 profile 里关掉其中一个即可。
|
|
121
121
|
- 持久化只用「Host 数据目录里的一个 JSON 文件」,没有走 DSH 的 storageDomain。实测(rc.5):`storageDomain` 可用,但记录校验只在**重新打开**时执行(`put` 不校验);`single` 布局遇到版本变化会直接拒绝打开,`compatibleVersions` 也不适用。对一份 Prompt 来说这些能力换不来收益,反而多一个依赖和三条失败分支。
|
|
@@ -159,6 +159,7 @@ dsh plugin --profile desktop add link:/absolute/path/to/dsh-mosaic
|
|
|
159
159
|
|
|
160
160
|
| 插件版本 | 实测通过的 DeepSeek Harness | 说明 |
|
|
161
161
|
| --- | --- | --- |
|
|
162
|
+
| `1.1.4` | `0.2.2-rc.1` | 修复已完成工具卡片的标题读错参数形状;实测工具、自有路由、Client 插槽与设置页图标均正常 |
|
|
162
163
|
| `1.1.3` | `0.2.1-rc.5` | 设置页改用插件自己的图标;需要 Harness 声明 `settings.section.icon`,rc.5 尚未提供 |
|
|
163
164
|
| `1.1.2` | `0.2.1-rc.5` | 修复示意图标签里的括号/方括号/花括号导致解析失败;补上边与消息的可读预算 |
|
|
164
165
|
| `1.1.1` | `0.2.1-rc.5` | 运行时代码与 `1.1.0` 相同;仅修正发布工作流的无效输入 |
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Submit this file to https://github.com/awesome-dsh-plugin/awesome-dsh-plugin
|
|
2
|
-
# as data/plugins/imwhatiam__dsh-mosaic.yml after the GitHub repo exists.
|
|
3
|
-
url: https://github.com/imwhatiam/dsh-mosaic
|
|
4
|
-
name: imwhatiam/dsh-mosaic
|
|
2
|
+
# as data/plugins/imwhatiam__dsh-plugins--packages-dsh-mosaic.yml after the GitHub repo exists.
|
|
3
|
+
url: https://github.com/imwhatiam/dsh-plugins/tree/main/packages/dsh-mosaic
|
|
4
|
+
name: imwhatiam/dsh-plugins#mosaic
|
|
5
5
|
category: ui
|
|
6
6
|
description:
|
|
7
7
|
en: 'Renders structured visual answers in DeepSeek Harness: metrics, charts, tables, diagrams, media and interactive widgets, with one compact visual style, an editable model prompt, and local-first interactions.'
|
|
8
8
|
zh: '为 DeepSeek Harness 渲染结构化可视化回答:指标、图表、表格、流程图、媒体和交互组件;提供一套紧凑视觉风格、可编辑的模型 Prompt,交互默认在浏览器本地完成。'
|
|
9
|
-
icon: https://raw.githubusercontent.com/imwhatiam/dsh-
|
|
9
|
+
icon: https://raw.githubusercontent.com/imwhatiam/dsh-plugins/main/packages/dsh-mosaic/assets/icon-180.png
|
package/lib/render-tool.js
CHANGED
|
@@ -130,8 +130,16 @@ function protocolOf(value) {
|
|
|
130
130
|
].join('\n')
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
/**
|
|
134
|
+
* The completed card keeps the spec title. The host hands `presentResult` a
|
|
135
|
+
* `ToolResult` (`content`, `isError`, `meta`) rather than the canonical value, so
|
|
136
|
+
* the title is read from the presentation payload the output declaration saved.
|
|
137
|
+
*/
|
|
138
|
+
function titleOf(result) {
|
|
139
|
+
const meta = result !== null && typeof result === 'object' ? result.meta : undefined
|
|
140
|
+
return meta !== null && typeof meta === 'object' && typeof meta.title === 'string'
|
|
141
|
+
? `Render view: ${meta.title}`
|
|
142
|
+
: 'Render view'
|
|
135
143
|
}
|
|
136
144
|
|
|
137
145
|
export function createRenderViewTool() {
|
|
@@ -161,8 +169,8 @@ export function createRenderViewTool() {
|
|
|
161
169
|
const title = spec && typeof spec === 'object' && typeof spec.title === 'string' ? spec.title : undefined
|
|
162
170
|
return { card: 'generic', title: title ? `Render view: ${title}` : 'Render view', kind: 'other' }
|
|
163
171
|
},
|
|
164
|
-
presentResult(_args,
|
|
165
|
-
return { card: 'generic', title: titleOf(
|
|
172
|
+
presentResult(_args, result) {
|
|
173
|
+
return { card: 'generic', title: titleOf(result) }
|
|
166
174
|
},
|
|
167
175
|
}
|
|
168
176
|
}
|
package/lib/validate-tool.js
CHANGED
|
@@ -110,10 +110,6 @@ function protocolOf(value) {
|
|
|
110
110
|
return lines.join('\n')
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
function isValid(value) {
|
|
114
|
-
return value.status === 'valid'
|
|
115
|
-
}
|
|
116
|
-
|
|
117
113
|
export function createValidateViewTool() {
|
|
118
114
|
return {
|
|
119
115
|
name: 'validate_view',
|
|
@@ -127,6 +123,11 @@ export function createValidateViewTool() {
|
|
|
127
123
|
render(_args, value) {
|
|
128
124
|
return [{ type: 'text', text: protocolOf(value) }]
|
|
129
125
|
},
|
|
126
|
+
// The completed card names validity. `presentResult` receives a `ToolResult`,
|
|
127
|
+
// so the verdict is persisted as presentation meta and read back from there.
|
|
128
|
+
presentationMeta(_args, value) {
|
|
129
|
+
return { status: value.status }
|
|
130
|
+
},
|
|
130
131
|
},
|
|
131
132
|
async execute(args) {
|
|
132
133
|
const raw = rawOf(args)
|
|
@@ -166,8 +167,10 @@ export function createValidateViewTool() {
|
|
|
166
167
|
presentCall() {
|
|
167
168
|
return { card: 'generic', title: 'Validate dsh-view', kind: 'other' }
|
|
168
169
|
},
|
|
169
|
-
presentResult(_args,
|
|
170
|
-
|
|
170
|
+
presentResult(_args, result) {
|
|
171
|
+
const status = result?.meta?.status
|
|
172
|
+
const verdict = status === 'valid' ? 'valid' : status === 'invalid' ? 'invalid' : undefined
|
|
173
|
+
return { card: 'generic', title: verdict === undefined ? 'Validate dsh-view' : `Validate dsh-view: ${verdict}` }
|
|
171
174
|
},
|
|
172
175
|
}
|
|
173
176
|
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mosaic",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Lightweight visual answers for DeepSeek Harness: one compact visual style, an editable model prompt, dsh-view components, Mermaid diagrams, a sandboxed HTML/JS escape hatch, local-first interactions, and link-only media cards.",
|
|
6
6
|
"author": "imwhatiam",
|
|
7
|
-
"homepage": "https://github.com/imwhatiam/dsh-mosaic#readme",
|
|
7
|
+
"homepage": "https://github.com/imwhatiam/dsh-plugins/tree/main/packages/dsh-mosaic#readme",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/imwhatiam/dsh-
|
|
10
|
+
"url": "git+https://github.com/imwhatiam/dsh-plugins.git",
|
|
11
|
+
"directory": "packages/dsh-mosaic"
|
|
11
12
|
},
|
|
12
13
|
"bugs": {
|
|
13
|
-
"url": "https://github.com/imwhatiam/dsh-
|
|
14
|
+
"url": "https://github.com/imwhatiam/dsh-plugins/issues"
|
|
14
15
|
},
|
|
15
16
|
"keywords": [
|
|
16
17
|
"deepseek-harness",
|
|
@@ -56,7 +57,8 @@
|
|
|
56
57
|
}
|
|
57
58
|
},
|
|
58
59
|
"scripts": {
|
|
59
|
-
"test": "node --test test/*.test.mjs"
|
|
60
|
+
"test": "node --test test/*.test.mjs",
|
|
61
|
+
"pack:check": "node ../../scripts/pack-check.mjs"
|
|
60
62
|
},
|
|
61
63
|
"engines": {
|
|
62
64
|
"node": ">=24",
|