diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a20ec8..5957b3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [0.8.5] - 2026-08-16 +### 发布 +- **发布规范对齐 `plugin_check`(issue #15)**: + - 新增 bundle 源码入口 `src/index.ts`(`import type {}` 先引入 dsh client runtime 的 cordis Context 增广再重导出 `src/plugin/index`,规避 TS 5.9 从根入口进入时全局增广顺序不稳定的类型错误);tsdown node 入口改为命名入口 `{ index: 'src/index.ts', invariant: 'src/plugin/invariant.ts' }` 并固定 `entryFileNames`,保持发布布局 `lib/index.js` + `lib/invariant.js` 不变; + - `tsconfig`:`outDir` 改为 `lib`(与 `main` 的 `lib/` 前缀对齐)、新增 `declarationDir: "lib/types"`(类型输出布局不变)、显式 `types: ["node"]`(devDependencies 同步补 `@types/node`,消除隐式 Node 类型依赖); + - `files` 增补 `lib`、`src` 目录声明;新增 `scripts.prepack = pnpm run build`,发布 tarball 前强制重建 lib,clean checkout 可复现发布产物。 + - 已知非本仓库可修项:`plugin_check` 的 org-name 政策目前只放行 `@deepseek-ai/*`/`@dsh-external/*`/`dsh-*`,`@omdsh-dev/dsh-genui` 为社区组织公开发布名,保持不变;其 `missing-peer: cordis` 提示基于旧 cordis 键名,本包实际依赖 `@deepseek-ai/cordis@^4.0.1`,不添加幻影 peer。 +### 测试 +- 全量 373 项(271 passed / 102 skipped)0 失败;`plugin_check` 从 3 errors / 4 warnings 收敛为 1 error / 1 warning(仅剩上述命名政策与旧 peer 键提示)。 + ## [0.8.4] - 2026-08-16 ### 修复 - **genui 与普通代码块共存时整条消息被吞(issue #13)**:同一消息容器里 `dsh-ui` 围栏和 python/ts/bash 等普通代码块共存时,DOM 通道的结构兜底从普通代码块的 `
` 向上回溯,越过它自己的 `.md-code-block` 把共享的 `.markdown` 根容器误判为「dsh-ui 围栏」→ 整条消息 `display:none`、只剩 GenUI,普通代码块丢失。修复两层:① 兜底循环跳过已由已知表面选择器命中的 ``(这些块已处理,不再向上回溯);② 标签判定不认领「属于嵌套已知代码块」的 banner(`owner !== block` 即跳过),共享容器不能再通过嵌套围栏的标签自证。未知类名表面的结构兜底能力保持不变(回归测试覆盖:未知表面 + 已知 python 块并存时仍照常渲染)
diff --git a/lib/types/index.d.ts b/lib/types/index.d.ts
new file mode 100644
index 0000000..01e7ac1
--- /dev/null
+++ b/lib/types/index.d.ts
@@ -0,0 +1 @@
+export * from './plugin/index';
diff --git a/package.json b/package.json
index e4e5d2b..51acdb2 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@omdsh-dev/dsh-genui",
"description": "GenUI for DeepSeek Harness: interactive UI components rendered inline in assistant replies via the ```dsh-ui fence — layout, charts, plots, forms, quizzes, mermaid, 3D scenes, and an action event loop back to the model. Ships the fence-teaching host plugin, the browser renderer (client half), and the genui skill.",
- "version": "0.8.4",
+ "version": "0.8.5",
"type": "module",
"main": "lib/index.js",
"types": "lib/types/plugin/index.d.ts",
@@ -34,7 +34,11 @@
"README.zh-CN.md",
"CHANGELOG.md",
"demo-prompts.md",
- "cordis.patch.yml"
+ "cordis.patch.yml",
+ "lib",
+ "src",
+ "tsconfig.json",
+ "tsdown.config.ts"
],
"publishConfig": {
"access": "public"
@@ -73,6 +77,7 @@
"devDependencies": {
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.0.0",
+ "@types/node": "^22.19.0",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@types/three": "^0.185.4",
@@ -90,7 +95,8 @@
"scripts": {
"build": "rm -rf lib && tsc -p tsconfig.json && tsdown",
"test": "vitest run",
- "check": "rm -rf lib && tsc -p tsconfig.json && vitest run && tsdown"
+ "check": "rm -rf lib && tsc -p tsconfig.json && vitest run && tsdown",
+ "prepack": "node scripts/prepack.mjs"
},
"dsh": {
"bundle": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 523397f..f6777a1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,6 +45,9 @@ importers:
'@testing-library/react':
specifier: ^16.0.0
version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@types/node':
+ specifier: ^22.19.0
+ version: 22.20.1
'@types/react':
specifier: ^18.0.0
version: 18.3.31
@@ -80,10 +83,10 @@ importers:
version: 5.9.3
vite:
specifier: ^6.0.0
- version: 6.4.3(lightningcss@1.33.0)(tsx@4.23.12)
+ version: 6.4.3(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12)
vitest:
specifier: ^3.0.0
- version: 3.2.7(@types/debug@4.1.13)(jsdom@25.0.1)(lightningcss@1.33.0)(tsx@4.23.12)
+ version: 3.2.7(@types/debug@4.1.13)(@types/node@22.20.1)(jsdom@25.0.1)(lightningcss@1.33.0)(tsx@4.23.12)
packages:
@@ -1487,6 +1490,9 @@ packages:
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+ '@types/node@22.20.1':
+ resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==}
+
'@types/prop-types@15.7.15':
resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
@@ -2716,6 +2722,9 @@ packages:
unconfig-core@7.5.0:
resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==}
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
unist-util-is@6.0.1:
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
@@ -4156,6 +4165,10 @@ snapshots:
'@types/ms@2.1.0': {}
+ '@types/node@22.20.1':
+ dependencies:
+ undici-types: 6.21.0
+
'@types/prop-types@15.7.15': {}
'@types/react-dom@18.3.7(@types/react@18.3.31)':
@@ -4200,13 +4213,13 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.7(vite@6.4.3(lightningcss@1.33.0)(tsx@4.23.12))':
+ '@vitest/mocker@3.2.7(vite@6.4.3(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12))':
dependencies:
'@vitest/spy': 3.2.7
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 6.4.3(lightningcss@1.33.0)(tsx@4.23.12)
+ vite: 6.4.3(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12)
'@vitest/pretty-format@3.2.7':
dependencies:
@@ -5577,6 +5590,8 @@ snapshots:
'@quansync/fs': 1.0.0
quansync: 1.0.0
+ undici-types@6.21.0: {}
+
unist-util-is@6.0.1:
dependencies:
'@types/unist': 3.0.3
@@ -5623,13 +5638,13 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
- vite-node@3.2.4(lightningcss@1.33.0)(tsx@4.23.12):
+ vite-node@3.2.4(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 6.4.3(lightningcss@1.33.0)(tsx@4.23.12)
+ vite: 6.4.3(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -5644,7 +5659,7 @@ snapshots:
- tsx
- yaml
- vite@6.4.3(lightningcss@1.33.0)(tsx@4.23.12):
+ vite@6.4.3(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.5)
@@ -5653,15 +5668,16 @@ snapshots:
rollup: 4.62.4
tinyglobby: 0.2.17
optionalDependencies:
+ '@types/node': 22.20.1
fsevents: 2.3.3
lightningcss: 1.33.0
tsx: 4.23.12
- vitest@3.2.7(@types/debug@4.1.13)(jsdom@25.0.1)(lightningcss@1.33.0)(tsx@4.23.12):
+ vitest@3.2.7(@types/debug@4.1.13)(@types/node@22.20.1)(jsdom@25.0.1)(lightningcss@1.33.0)(tsx@4.23.12):
dependencies:
'@types/chai': 5.2.3
'@vitest/expect': 3.2.7
- '@vitest/mocker': 3.2.7(vite@6.4.3(lightningcss@1.33.0)(tsx@4.23.12))
+ '@vitest/mocker': 3.2.7(vite@6.4.3(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12))
'@vitest/pretty-format': 3.2.7
'@vitest/runner': 3.2.7
'@vitest/snapshot': 3.2.7
@@ -5679,11 +5695,12 @@ snapshots:
tinyglobby: 0.2.17
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 6.4.3(lightningcss@1.33.0)(tsx@4.23.12)
- vite-node: 3.2.4(lightningcss@1.33.0)(tsx@4.23.12)
+ vite: 6.4.3(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12)
+ vite-node: 3.2.4(@types/node@22.20.1)(lightningcss@1.33.0)(tsx@4.23.12)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.13
+ '@types/node': 22.20.1
jsdom: 25.0.1
transitivePeerDependencies:
- jiti
diff --git a/scripts/prepack.mjs b/scripts/prepack.mjs
new file mode 100644
index 0000000..55c58b2
--- /dev/null
+++ b/scripts/prepack.mjs
@@ -0,0 +1,20 @@
+#!/usr/bin/env node
+/**
+ * Cross-platform `prepack` wrapper: rebuild lib before packing, but keep the
+ * build's stdout OFF the process stdout. `npm pack --json` parses stdout as
+ * JSON, so any tsdown banner leaking to stdout corrupts the pack gate and
+ * tooling that drives npm pack programmatically. Build progress is forwarded
+ * to stderr instead.
+ */
+import { spawnSync } from 'node:child_process'
+
+const pm = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm'
+const result = spawnSync(pm, ['run', 'build'], {
+ env: process.env,
+ stdio: ['ignore', 'pipe', 'pipe'],
+})
+
+if (result.stdout !== null && result.stdout.length > 0) process.stderr.write(result.stdout)
+if (result.stderr !== null && result.stderr.length > 0) process.stderr.write(result.stderr)
+if (result.error !== undefined) throw result.error
+if (result.status !== 0) process.exit(result.status ?? 1)
diff --git a/scripts/verify-pack.mjs b/scripts/verify-pack.mjs
index 151c41c..32c66be 100644
--- a/scripts/verify-pack.mjs
+++ b/scripts/verify-pack.mjs
@@ -32,6 +32,9 @@ for (const entry of Object.values(pkgJson.exports)) {
const required = [
'package.json', 'LICENSE', 'SKILL.md', 'README.md', 'CHANGELOG.md', 'demo-prompts.md', 'cordis.patch.yml',
'lib/assets/mermaid.js', 'lib/assets/three.js',
+ // plugin_check 发布规范(issue #15):tarball 必须携带可复现构建所需的
+ // 源码入口与构建配置,prepack 已在打包前重建 lib。
+ 'src/index.ts', 'tsconfig.json', 'tsdown.config.ts',
...exportTargets,
]
@@ -53,8 +56,7 @@ try {
}
const forbidden = [...paths].filter(p =>
- p.startsWith('src/')
- || p.endsWith('.map')
+ p.endsWith('.map')
|| p.includes('.tsbuildinfo')
|| /^lib\/types\/.*\.js$/.test(p),
)
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 0000000..1bd0253
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,12 @@
+/**
+ * Bundle source entry (plugin_check tool-bundle contract): the node-half
+ * surface the host loader resolves through `package.json#main`.
+ *
+ * The `import type {}` line is NOT decorative: importing the dsh client
+ * runtime's cordis Context augmentation BEFORE re-exporting the plugin keeps
+ * TypeScript's global-augmentation ordering deterministic — without it,
+ * TS 5.9 mis-resolves `ctx.sessions` in the client half when the plugin
+ * module is first reached through this root entry.
+ */
+import type {} from '@deepseek-ai/dsh-client-runtime/client'
+export * from './plugin/index'
diff --git a/tsconfig.json b/tsconfig.json
index 6e52656..02dce3a 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -9,7 +9,9 @@
"DOM",
"DOM.Iterable"
],
- "types": [],
+ "types": [
+ "node"
+ ],
"declaration": true,
"skipLibCheck": true,
"esModuleInterop": true,
@@ -23,7 +25,7 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"rootDir": "src",
- "outDir": "lib/types",
+ "outDir": "lib",
"baseUrl": ".",
"paths": {
"@deepseek-ai/dsh-client-ui-primitives": [
@@ -111,7 +113,8 @@
"../../.dsh/source/current/vendor/cosmokit/lib/types/*"
]
},
- "emitDeclarationOnly": true
+ "emitDeclarationOnly": true,
+ "declarationDir": "lib/types"
},
"include": [
"src"
diff --git a/tsdown.config.ts b/tsdown.config.ts
index e8c6632..822dc71 100644
--- a/tsdown.config.ts
+++ b/tsdown.config.ts
@@ -165,13 +165,20 @@ function assetConfig(name: 'mermaid' | 'three', entry: string): UserConfig {
const libConfig: UserConfig = {
name: ID,
- entry: ['src/plugin/index.ts', 'src/plugin/invariant.ts'],
+ // Named entries keep the published layout stable (lib/index.js +
+ // lib/invariant.js) while src/index.ts becomes the canonical bundle
+ // source entry that plugin_check's tool-bundle contract expects.
+ entry: { index: 'src/index.ts', invariant: 'src/plugin/invariant.ts' },
outDir: 'lib',
format: ['esm'],
platform: 'node',
target: 'es2024',
fixedExtension: false,
dts: false,
+ // Flatten entry outputs to lib/.js so package exports keep the
+ // stable paths lib/index.js + lib/invariant.js (a directory-mirroring
+ // default would emit lib/plugin/invariant.js).
+ outputOptions: { entryFileNames: '[name].js' },
// Cleanup happens in the build script (`rm -rf lib` before tsc): tsdown
// must never wipe lib/types (tsc's declaration output) mid-pipeline.
clean: false,