From 0739fbb80028abae6055e8b659cf9a7af44af731 Mon Sep 17 00:00:00 2001 From: taekchef Date: Sun, 16 Aug 2026 04:24:04 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20plugin=5Fcheck=20release=20hygiene=20?= =?UTF-8?q?=E2=80=94=20source=20entry,=20lib=20layout,=20prepack,=20files?= =?UTF-8?q?=20(issue=20#15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align the bundle with the tool-bundle contract: add src/index.ts, tsconfig outDir=lib + declarationDir=lib/types + types:["node"], @types/node, scripts.prepack, files lib/src/tsconfig, and update the pack gate. --- CHANGELOG.md | 10 ++++++++++ lib/types/index.d.ts | 1 + package.json | 12 +++++++++--- pnpm-lock.yaml | 39 ++++++++++++++++++++++++++++----------- scripts/prepack.mjs | 20 ++++++++++++++++++++ scripts/verify-pack.mjs | 6 ++++-- src/index.ts | 12 ++++++++++++ tsconfig.json | 9 ++++++--- tsdown.config.ts | 9 ++++++++- 9 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 lib/types/index.d.ts create mode 100644 scripts/prepack.mjs create mode 100644 src/index.ts 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,