dsh-artifact-linker 0.3.8 → 0.4.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,76 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 — 2026-10-30
4
+
5
+ ### 改:彻底去掉扩展名白名单,所有文件类型都能识别、都能走侧边栏预览
6
+
7
+ 病根:旧版有两张手写白名单——`PREVIEWABLE`(决定右键菜单里「在侧边栏预览」显不显示)和 `EXT`(决定正文里哪段文字算文件名)。两者都是**对宿主渲染能力的静态猜测**,问题一样:
8
+
9
+ 1. 宿主每加一个渲染器就得回来补一次清单,漏一次就表现为「正文里明明有文件名,右键毫无反应」;
10
+ 2. 用户装了 `dsh-video-preview` / `@huanlin/...-audio` 这类插件后宿主能力早变了,白名单却停在旧结论上 —— 于是 **mp4 / mp3 / wav 右键完全没有预览入口**,本次就是这条报上来的。
11
+
12
+ ### 三处改动
13
+
14
+ | 位置 | 旧 | 新 |
15
+ |---|---|---|
16
+ | `PREVIEWABLE` | 正则白名单,`canPreview` 为 false 就不 push 菜单项 | **整条删除**,「在侧边栏预览」对所有类型无条件显示 |
17
+ | `EXT` | 手写约 130 项扩展名数组,拼进 `RE` | **整条删除**,改为通用扩展名匹配 + `EXEC_EXT` 可执行体黑名单 |
18
+ | 预览点击反馈 | 成功/失败无区分 | 成功 `toast("已在侧边栏打开(.xxx)")`,失败 `toast("侧边栏打不开 .xxx,可改用「用默认程序打开」")` |
19
+
20
+ 新的识别规则:**任意 1–12 位扩展名都算候选**,字母开头或数字开头都收(`7z` / `3mf` / `3gp` 这类数字开头的真实格式以前被漏掉)。唯一还刻意排除的是可执行体 / 系统二进制(`EXEC_EXT`:`exe msi msp mst dll sys com scr cpl ocx drv vxd efi so dylib ko elf`)——正文里出现 `xxx.exe` 九成是命令输出或报错原文,而「用默认程序打开」对它们等于**直接运行**,误点代价太大。
21
+
22
+ ### 误报怎么兜:不靠白名单,靠存在性闸门
23
+
24
+ 候选片段必须先在宿主 `/resolve` 真的解析到磁盘文件,才会变成可点目标。所以散文里的 `e.g.` / `v1.2` / `Node.js` 即使被正则当成候选也没关系:解析不到就静默,用户完全看不出它曾被识别过。这比维护一张永远追不上现实的清单可靠得多。
25
+
26
+ ### 验证
27
+
28
+ 新增 `_verify/test-ext-regex.mjs`,36 项断言全过:
29
+ - 旧白名单已支持的(`mp4`/`mp3`/`wav`/`pdf`/`xlsx`/`md`/`py`/`cas.h5`/`dat.h5`/带空格文件名)不退化;
30
+ - 旧白名单漏掉的(`mov`/`mkv`/`webm`/`flac`/`m4a`/`7z`/`heic`/`avif`/`mcap`/`parquet`/`3mf`/`usdz`/任意未知扩展名)现在都能命中;
31
+ - 可执行体(`exe`/`msi`/`dll`/`sys`/`so`/`dylib`/`ko`/`elf`/`com`/`scr`/`ocx`/`cpl`)全部不命中。
32
+
33
+ ### 顺手修
34
+
35
+ `lib/client.js` 的 `VERSION` 常量一直停在 `0.3.8`,落后 `package.json` 两个版本,现统一为 `0.4.0`。
36
+
37
+ ### 已知代价(用户已明确接受)
38
+
39
+ 极少数类型点「在侧边栏预览」会得到一句「打不开」。这是刻意的取舍:宁可点了没反应,也不要靠限制类型来回避未来的 bug —— 这样侧边栏以后补了什么能力,本插件零改动自动跟上。
40
+
41
+ ## 0.3.9 — 2026-10-29
42
+
43
+ ### 修:插件市场看不到下载量 / 版本号 / 搜不到
44
+
45
+ 根因不在市场,在**本包 npm 元数据缺 `repository` 字段**。
46
+
47
+ 市场目录(awesome-dsh-plugin / dsh-plugin-catalog)用 `scripts/probe-npm.mjs` 判定「这个 GitHub 仓库有没有对应的 npm 包」,判据是一行硬守卫:
48
+
49
+ ```js
50
+ const linked = repoField.toLowerCase().includes(repo.toLowerCase())
51
+ if (!linked) return { npm: null, version: null, checkedAt: today }
52
+ ```
53
+
54
+ 而本包此前的 packument 里 `repository` 是空串,`''.includes('loyalchiiina/dsh-artifact-linker')` 恒为 false → 每次探测都被判成「没发布到 npm」→ 目录里 `npm: null, version: null, downloads: null` → 市场前端 `downloadStatsText()` 见 null 直接 `return null`,整块统计不渲染。
55
+
56
+ 连带后果:
57
+ - 卡片上没有 `· ↓ N`、没有 `· v0.3.9`;
58
+ - 官方发现索引 `index.json`(只收有 npm 包+版本+发布时间的条目)里**完全搜不到**这个插件。
59
+
60
+ 目录方的这条规则是**故意的防冒领**(contributing.md:「The published package's `repository` field must point back at the repository listed here, or the two are not linked.」)。
61
+
62
+ ### 改:补齐 npm 元数据
63
+
64
+ `package.json` 新增三个字段:
65
+
66
+ ```json
67
+ "repository": { "type": "git", "url": "git+https://github.com/loyalchiiina/dsh-artifact-linker.git" },
68
+ "homepage": "https://github.com/loyalchiiina/dsh-artifact-linker#readme",
69
+ "bugs": { "url": "https://github.com/loyalchiiina/dsh-artifact-linker/issues" }
70
+ ```
71
+
72
+ 发布后,目录侧 `probe-npm.mjs` 的 `RECHECK_DAYS = 1` 规则(`entry.npm === null && ageDays(entry) > 1`)会**自动重探**,无需提 PR。重探通过后 npm / version / downloads 三个字段自动回填,下载量与版本号即出现在市场卡片上,插件也会进入官方发现索引。
73
+
3
74
  ## 0.3.8 — 2026-10-29
4
75
 
5
76
  ### 修:「在文件夹中显示」有时不给定位
package/README.en.md CHANGED
@@ -55,7 +55,7 @@ Click behaviour is decided by the modifier key — no first-time setup:
55
55
 
56
56
  | Item | What it does |
57
57
  | --- | --- |
58
- | **Preview in sidebar** | Opens the file in DSH's built-in right sidebar — the same route as clicking a file link in chat. That viewer handles PDF, Word, Excel, PowerPoint, Markdown, plain text, CSV, images, audio and video; an extension it cannot render is redirected to the default app instead of showing a blank pane |
58
+ | **Preview in sidebar** | Opens the file in DSH's built-in right sidebar — the same route as clicking a file link in chat. **Since 0.4.0 this menu item is shown for every file type**, with no extension filtering: whatever viewer claims the address renders it (PDF / Word / Excel / PowerPoint / Markdown / plain text / CSV / images, plus audio and video once plugins such as video-preview / audio-preview are installed); anything unclaimed falls back to plain text or the default app. The trade-off is that a rare type may answer with a plain "the sidebar cannot open this" — accepted on purpose, so future viewer capabilities are picked up with zero changes here |
59
59
  | **Open with default app** | Hands the file to the OS association (Explorer / Excel / VLC / …) |
60
60
  | **Reveal in Explorer** | Opens the containing folder and selects the file |
61
61
  | **Save as…** | Copies the file to a location you pick |
package/README.md CHANGED
@@ -51,7 +51,7 @@ DSH 里预览器已经能开图片、代码、pdf、office。但**插件、脚
51
51
 
52
52
  | 菜单项 | 作用 |
53
53
  |---|---|
54
- | **在侧边栏预览** | 在 DSH 内置右侧边栏里打开,和聊天里点文件链接是同一条通道。该查看器支持 PDF、Word、Excel、PowerPoint、Markdown、纯文本、CSV、图片、音视频;它渲染不了的扩展名会**自动改走默认程序**,不会给你一个空白面板 |
54
+ | **在侧边栏预览** | 在 DSH 内置右侧边栏里打开,和聊天里点文件链接是同一条通道。**0.4.0 起对所有文件类型一律显示这一项**,不再按扩展名筛:能认领的查看器就渲染(PDF / Word / Excel / PowerPoint / Markdown / 纯文本 / CSV / 图片,装了 video-preview / audio-preview 等插件后还有音视频),认领不了的宿主会退回纯文本或默认程序。副作用是极少数类型点下去可能只得到一句「侧边栏打不开」——这是刻意接受的代价,为的是以后侧边栏补了新能力,本插件零改动自动跟上 |
55
55
  | **用默认程序打开** | 交给系统关联(资源管理器 / Excel / 播放器……) |
56
56
  | **在文件夹中显示** | 打开所在目录并选中该文件 |
57
57
  | **另存为…** | 复制到你指定的位置 |
@@ -146,10 +146,10 @@ GET http://127.0.0.1:<port>/dsh-artifact-linker/info
146
146
 
147
147
  | 症状 | 原因与处置 |
148
148
  |---|---|
149
- | 正文文件名不可点 | ① `clientChips` 被置 false;② 扩展名不在白名单(本插件只认已知产物扩展名,避免把 `C:\Windows` 之类误标成产物);③ 客户端 bundle 没重载——**Ctrl+R 不重载客户端 bundle,必须完全重启 DSH** |
149
+ | 正文文件名不可点 | ① `clientChips` 被置 false;② 扩展名是可执行体(`exe`/`msi`/`dll`/`sys`/`so` 等,这是**唯一**仍刻意不认的一类,见 `lib/client.js` 的 `EXEC_EXT`);③ 客户端 bundle 没重载——**Ctrl+R 不重载客户端 bundle,必须完全重启 DSH** |
150
150
  | 点开提示「解析不到绝对路径」 | 裸文件名不在 workspace 内,且 `allowOutside: false`。先确认文件真实路径,再决定是否放宽 |
151
151
  | 点开提示「文件已不存在」 | 路径是真的,文件被删/移了。清单里该行会打上删除线 |
152
- | 点产物名没反应 | ① 文件不在候选 base 下(访问宿主 `/info` 看 `bases`);② 扩展名不在白名单(`lib/client.js` 的 `EXT`);③ 直接看 `/resolve?p=<名字>` 返回的 `reason` |
152
+ | 点产物名没反应 | ① 文件不在候选 base 下(访问宿主 `/info` 看 `bases`);② 直接看 `/resolve?p=<名字>` 返回的 `reason`。**0.4.0 起不再有扩展名白名单**,任何字母或数字开头的扩展名都会被识别为候选(`7z`/`3mf` 这类数字开头的也算),误报由「必须先真实解析到磁盘文件」这道存在性闸门兜掉 |
153
153
  | 右键没出本插件菜单 | 该处文字没解析成文件(同上);**对非产物右键本来就不接管**,出的是宿主原生菜单。0.3.3 起会先确认文件存在——不存在的片段既不画虚线也不接管右键 |
154
154
  | 日志里出现 N 份相同输出 | 热重载堆叠了多个实例。**Ctrl+R 无效,必须完全重启 DSH**;同时确认 `window.__dshArtifactLinkerV1.dispose()` 守卫在 |
155
155
 
package/lib/client.js CHANGED
@@ -29,7 +29,7 @@ window.__ModuleLoader__.load({
29
29
  var exports = module.exports;
30
30
 
31
31
  var GUARD = "__dshArtifactLinkerV1";
32
- var VERSION = "0.3.8";
32
+ var VERSION = "0.4.0";
33
33
  // 路由前缀必须与宿主的 ROUTE_PREFIX 一致;永远根相对,绝不拼宿主 origin
34
34
  var ROUTE = "/dsh-artifact-linker";
35
35
 
@@ -61,11 +61,21 @@ window.__ModuleLoader__.load({
61
61
  return sessionFileAddress(sessionId, normalized);
62
62
  }
63
63
 
64
- // 侧边栏 documentpreview 真正能渲染的类型(读官方 README 得出,不是猜的):
65
- // md/代码/纯文本 → 分页文本;pdf → PDF.js;图片 → 完整字节;
66
- // xlsx/xls/csv/tsv → 浏览器内只读表格;doc/docx/ppt/pptx → 本地转 PDF
67
- // 音视频与压缩包没有注册渲染器,走「不支持预览」空状态,所以干脆不显示这一项。
68
- var PREVIEWABLE = /^(pdf|docx?|pptx?|xls[xm]?|csv|tsv|md|markdown|txt|log|json|ya?ml|ini|toml|xml|html?|png|jpe?g|gif|webp|bmp|tiff?|svg|py|js|mjs|cjs|ts|tsx|ipynb|ps1|sh|cas|dat|h5|hsf|cxa|trn|rfile|plt|flprj|jou|set|out)$/i;
64
+ // 🔴 「在侧边栏预览」不再有类型白名单(2026-10-30 用户明确要求)。
65
+ //
66
+ // 旧版这里有一张 PREVIEWABLE 白名单,只放「宿主 documentpreview 当时能渲染」的
67
+ // 扩展名,音视频/压缩包被排除,右键它们根本没有预览入口。那个设计错在:
68
+ // 1) 白名单是**对宿主渲染能力的静态猜测**。宿主每加一个渲染器就得回来改一次;
69
+ // 用户装了 video-preview / audio-preview 这类插件后宿主能力早变了,
70
+ // 白名单却停在旧结论上 → 视频、mp3、wav 右键毫无入口(本次的直接病根)。
71
+ // 2) 「能不能渲染」本就不该由客户端猜。判定方是宿主
72
+ // sidebarRight.openResource:能认领就渲染,认领不了它自己退回默认程序。
73
+ //
74
+ // 现在的契约:**菜单项对所有类型一律显示,点了才见真章**。
75
+ // openInSidebar 返回 true → toast「已在侧边栏打开」
76
+ // openInSidebar 返回 false → toast「侧边栏打不开这个文件(.xxx)」
77
+ // 这样以后侧边栏补了什么能力,本插件零改动自动跟上,不会被旧白名单漏掉。
78
+ // 代价:极少数类型点了会得到一句「打不开」——用户已明确接受。
69
79
 
70
80
  function extOf(p) {
71
81
  var base = String(p).split(/[\\/]/).pop() || "";
@@ -74,24 +84,29 @@ window.__ModuleLoader__.load({
74
84
  }
75
85
 
76
86
 
77
- // 产物扩展名白名单。刻意**不含 exe/msi/dll** 之类可执行体:
78
- // 正文里出现这些名字多半是命令输出/报错文本,不是「要打开看的产物」。
79
- var EXT = [
80
- "pdf", "docx?", "xlsx?", "pptx?", "csv", "tsv",
81
- "png", "jpe?g", "gif", "webp", "bmp", "tiff?", "svg",
82
- "zip", "7z", "rar", "gz", "tar",
83
- "log", "txt", "md", "json", "ya?ml", "ini", "toml", "xml", "html?",
84
- "py", "js", "mjs", "cjs", "ts", "tsx", "ipynb", "ps1", "sh",
85
- "cas", "dat", "h5", "hsf", "cxa", "trn", "rfile", "plt", "flprj", "jou", "set", "out",
86
- "scdocx?", "pmdb", "unv", "msh", "stp", "step", "igs", "iges", "dwg", "dxf", "inp",
87
- // 音频/视频:合成音频(YuE、TTS、音色克隆)与录屏导出很常见,
88
- // 之前不在白名单里,用户右键 audio.flac 就完全没反应。
89
- "flac", "wav", "mp3", "m4a", "aac", "ogg", "opus", "wma", "amr",
90
- "mp4", "mkv", "mov", "avi", "webm", "wmv", "flv", "m4v"
91
- ].join("|");
87
+ // ── 正文里「长得像文件名」的判定 ────────────────────────────────────────
88
+ //
89
+ // 🔴 2026-10-30 起**不再维护扩展名白名单**(用户明确要求:所有文件类型都要能识别、
90
+ // 都能走侧边栏预览)。旧版是一张手写清单,问题是它永远追不上现实:
91
+ // 新格式(heic / avif / mcap / parquet / 3mf / usdz…)每出现一个就得回来补一次,
92
+ // 漏掉的表现就是「正文里明明有文件名,右键毫无反应」——本次音视频/压缩包
93
+ // 的抱怨就是这么来的。
94
+ //
95
+ // 现在的规则:**任意 1–8 位、以字母开头的扩展名都算**,只用一个黑名单挡掉
96
+ // 可执行体与系统二进制。为什么只挡这些:
97
+ // * 正文里出现 xxx.exe / xxx.dll 九成是命令输出、报错原文、依赖清单,
98
+ // 不是「要打开看的产物」;
99
+ // * 「用默认程序打开」对它们等于**直接运行**,误点代价太大。
100
+ // 真要放开,把下面对应的词删掉即可。
101
+ //
102
+ // 误报怎么兜?——不靠白名单,靠**存在性闸门**:候选片段必须先在宿主
103
+ // /resolve 真的解析到磁盘文件,才会变成可点目标(见下方 verify())。
104
+ // 所以把 e.g. / v1.2 这种散文里的点号误当成扩展名也没关系:解析不到就静默,
105
+ // 用户完全看不出它曾被识别过。这比维护一张永远不全的清单可靠得多。
106
+ var EXEC_EXT = /^(exe|msi|msp|mst|dll|sys|com|scr|cpl|ocx|drv|vxd|efi|so|dylib|ko|elf)$/i;
92
107
 
93
108
  // 一段文本里「像产物路径」的片段:
94
- // 可选的前缀(盘符 或 UNC)+ 中间任意非分隔字符 + 点 + 白名单扩展名
109
+ // 可选的前缀(盘符 或 UNC)+ 中间任意非分隔字符 + 点 + 扩展名
95
110
  // + 可选的多级尾巴(Fluent 的 xxx.cas.h5 / xxx.dat.h5 必须整体吃掉,
96
111
  // 否则会被截成 xxx.cas 去撞一个不存在的文件 → 点了没反应)
97
112
  // 末尾 (?![A-Za-z0-9_]) 防止 package.lock / a.python 这种半截匹配。
@@ -105,7 +120,13 @@ window.__ModuleLoader__.load({
105
120
  var RE = new RegExp(
106
121
  "(?:[A-Za-z]:[\\\\/]|\\\\\\\\[^\\\\/\\s]+[\\\\/][^\\\\/\\s]+)?" +
107
122
  "[^\\t\\r\\n`\"'<>|*?()()【】\\[\\]{},;、]{1,200}?\\." +
108
- "(?:" + EXT + ")(?:\\.[A-Za-z0-9]{1,6})*(?![A-Za-z0-9_])",
123
+ // 扩展名两种写法都收:
124
+ // 字母开头 1–12 位(pdf / mp4 / catproduct / properties…)
125
+ // 数字开头 2–12 位(7z / 3mf / 3gp / 8bf…)—— 必须 ≥2 位,否则
126
+ // 散文里的 v1.2 会贡献一个「扩展名 2」,虽然最后也会被存在性闸门静默掉,
127
+ // 但没必要让它进候选池。
128
+ "([A-Za-z][A-Za-z0-9_]{0,11}|[0-9][A-Za-z0-9_]{1,11})" +
129
+ "(?:\\.[A-Za-z0-9]{1,12})*(?![A-Za-z0-9_])",
109
130
  "gi"
110
131
  );
111
132
  // URL 里天然带 .png/.pdf,全部要排除,否则网页链接会被当成文件产物。
@@ -199,6 +220,9 @@ window.__ModuleLoader__.load({
199
220
  var e = m.index + m[0].length;
200
221
  if (rel < s || rel > e) continue; // 鼠标必须落在这个片段上
201
222
  if (inRanges(urls, s, e)) continue; // URL 里的 .png 不算
223
+ // 可执行体黑名单:这是唯一还刻意不认的类型(理由见上方 EXEC_EXT 注释)。
224
+ // 多级后缀取第一段判断,xxx.exe.bak 也算可执行体,宁可漏认不误点。
225
+ if (m[1] && EXEC_EXT.test(m[1])) continue;
202
226
  var raw = cleanRaw(m[0]);
203
227
  if (!raw || raw.length < 4) continue;
204
228
  return { raw: raw, rect: rectFor(range.startContainer, from + s, from + e) };
@@ -379,11 +403,13 @@ window.__ModuleLoader__.load({
379
403
  // 文案要说人话:「资源管理器」这个词很多用户不认识,改成「文件夹窗口」。
380
404
  // 顺序按「最常做的动作」排,并用 "sep" 占位分成三组:
381
405
  // 看(侧边栏预览 / 打开 / 定位)→ 搬运(另存为 / 复制文件 / 复制路径)→ 喂给 AI(添加到对话框)
382
- // 侧边栏预览只对宿主真能渲染的类型出现:音视频、压缩包在侧边栏里只有
383
- // 「不支持预览」空状态,摆一个点了白点的入口不如不摆。
384
- var canPreview = PREVIEWABLE.test(extOf(abs));
406
+ //
407
+ // 🔴 「在侧边栏预览」对所有文件类型**无条件出现**(2026-10-30 用户明确要求)。
408
+ // 旧版按 PREVIEWABLE 白名单决定显不显示,音视频/压缩包因此完全没有入口。
409
+ // 现在一律显示,点下去由宿主 sidebarRight.openResource 决定能不能认领:
410
+ // 认领得了就渲染,认领不了 openInSidebar 返回 false,我们照实提示「打不开」。
385
411
  var items = [];
386
- if (canPreview) items.push(["preview", "在侧边栏预览", "在右侧边栏里直接看,不用切出去"]);
412
+ items.push(["preview", "在侧边栏预览", "在右侧边栏里直接看,不用切出去;这个类型如果侧边栏渲染不了会如实提示"]);
387
413
  items.push(["open", "用默认程序打开", "按文件类型用对应软件打开:PDF 用阅读器、表格用 Excel 那类"]);
388
414
  items.push(["reveal", "在文件夹中显示", "打开 Windows 文件夹窗口,并选中这个文件"]);
389
415
  items.push(["sep", "", ""]);
@@ -420,8 +446,10 @@ window.__ModuleLoader__.load({
420
446
 
421
447
  // ① 侧边栏预览 —— 纯客户端,走宿主导航入口
422
448
  if (action === "preview") {
423
- if (openInSidebar(abs)) toast("已在侧边栏打开");
424
- else toast("侧边栏打不开这个文件");
449
+ // 对所有类型都尝试,成败照实说。带扩展名,用户才知道是哪个类型没成。
450
+ var pext = extOf(abs);
451
+ if (openInSidebar(abs)) toast("已在侧边栏打开" + (pext ? "(." + pext + ")" : ""));
452
+ else toast("侧边栏打不开" + (pext ? " ." + pext : "这个文件") + ",可改用「用默认程序打开」");
425
453
  return;
426
454
  }
427
455
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-artifact-linker",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "description": "DSH 产物路径联动器:常驻注入「产物路径铁律」让模型输出完整绝对路径,同时把聊天正文里的文件名/路径渲染成一键可点的产物芯片——左键预览、右键菜单可打开/定位/另存为/复制文件/复制路径/添加到对话框。宿主端提供回环只读路由与 /saveas /copyfile 两个文件搬运动作(Shell COM 揭示、WinForms 保存对话框、CF_HDROP 剪贴板),客户端零侵入、不改 React 节点、不接管 markdown 图片语法。解决「产物要打开得先复制路径再粘到文件管理器」的反复割裂。/ Turn declared artifact paths into one-click chips: resident system-prompt rules force absolute paths, the client half renders file names as clickable chips, and the right-click menu offers open / reveal in Explorer / save-as / copy-file / copy-path / insert-into-composer. Host routes are loopback-only; zero telemetry.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -30,6 +30,14 @@
30
30
  "icon.svg"
31
31
  ],
32
32
  "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/loyalchiiina/dsh-artifact-linker.git"
36
+ },
37
+ "homepage": "https://github.com/loyalchiiina/dsh-artifact-linker#readme",
38
+ "bugs": {
39
+ "url": "https://github.com/loyalchiiina/dsh-artifact-linker/issues"
40
+ },
33
41
  "keywords": [
34
42
  "dsh-plugin",
35
43
  "deepseek-harness",
@@ -56,4 +64,4 @@
56
64
  "@deepseek-ai/cordis": "^4.0.2",
57
65
  "@deepseek-ai/dsh": "\u003e=0.2.1-rc.3"
58
66
  }
59
- }
67
+ }