dsh-plugin-toolkit 0.9.1 → 0.9.3

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,3 +1,29 @@
1
+ ## 0.9.3
2
+
3
+ - The panel needed one more thing than `dsh.client`: the host resolves the bundle
4
+ through `exports["./client"]` (`clientExportOf`), and drops the row when that
5
+ subpath is missing. 0.9.2 declared `dsh.client` but its `exports` map had no
6
+ `./client`, so the tab was still absent — this release exports `./client` and
7
+ `doctor` now checks the same thing the host does.
8
+ - `init` scaffolds `exports: { '.': './index.js', './client': './client.js' }`.
9
+ Every plugin generated before this release was missing it, so every generated
10
+ panel was invisible for the same reason.
11
+ - `doctor` reports a `dsh.client` whose `exports["./client"]` file does not exist,
12
+ and a `dsh.client` with no `./client` export at all. The `files`-list gap is now
13
+ caught at the manifest stage instead of at pack time.
14
+
15
+ ## 0.9.2
16
+
17
+ - `doctor` reports a shipped client bundle that no `dsh.client` declares. The host
18
+ serves `client.js` only for packages declaring `dsh.client`, so a plugin could
19
+ ship the bundle, mount it in `verify`, and still have no panel in the app — the
20
+ same silent failure as a tarball without it.
21
+ - The toolkit's own manifest now declares `dsh.client` (`platform: web`,
22
+ `inject: ['@deepseek-ai/dsh-client-ui-sidebar-right']`), which is what makes the
23
+ Plugin doctor tab reachable at all.
24
+ - The `not-shipped` fixture declares its client entry, so it keeps demonstrating
25
+ the `files` gap instead of tripping the new declaration check.
26
+
1
27
  ## 0.9.1
2
28
 
3
29
  - `audit` separates problems from advisories. Running 0.9.0 on a real profile
package/README.md CHANGED
@@ -313,6 +313,12 @@ dsh-plugin verify: stopped at pack
313
313
 
314
314
  ## When the panel does not appear
315
315
 
316
+ The first question is whether the host ever served your bundle. A package that
317
+ ships `client.js` but declares no `dsh.client` loads its host half and shows no
318
+ panel — `doctor` now fails that, because the host serves client bundles only for
319
+ packages that declare one:
320
+
321
+
316
322
  The install reports success and nothing shows up. In this order:
317
323
 
318
324
  1. **Did the host restart?** Client bundles are read at startup. `dsh plugin add`
package/lib/doctor.mjs CHANGED
@@ -110,6 +110,42 @@ export function checkClientEntry(dir, manifest) {
110
110
  return found ? null : `dsh.client is declared but none of ${entries.join(', ')} exists`;
111
111
  }
112
112
 
113
+ /**
114
+ * A client bundle the harness will never serve is the same failure as a tarball
115
+ * without one: the plugin loads, the row mounts, and no panel appears. The host
116
+ * serves `client.js` only for packages declaring `dsh.client`, so shipping the
117
+ * file by convention is not enough.
118
+ */
119
+ const CLIENT_FILES = ['client.js', 'lib/client.js', 'dist/client.js'];
120
+
121
+ export function checkClientDeclaration(dir, manifest) {
122
+ const client = manifest.dsh?.client;
123
+ if (client !== undefined && client !== null) {
124
+ const platform = client.platform;
125
+ if (platform !== undefined && platform !== 'web') {
126
+ return `dsh.client.platform is ${JSON.stringify(platform)}, but the harness serves client bundles on web`;
127
+ }
128
+ // The host reads the bundle path from exports["./client"] only — a
129
+ // declaration without that subpath makes the host drop the row.
130
+ const exported = manifest.exports;
131
+ const subpath = typeof exported === 'string' ? undefined : exportTarget(exported?.['./client']);
132
+ if (typeof subpath !== 'string') {
133
+ return 'dsh.client is declared but exports has no "./client" bundle, so the host drops the row and the panel cannot appear';
134
+ }
135
+ const file = subpath.replace(/^\.\//u, '');
136
+ return fs.existsSync(path.join(dir, file))
137
+ ? null
138
+ : `exports["./client"] points at ${subpath}, which does not exist`;
139
+ }
140
+ const exported = manifest.exports;
141
+ const subpath = typeof exported === 'string' ? undefined : exportTarget(exported?.['./client']);
142
+ const shipped = [subpath, ...CLIENT_FILES].find(
143
+ (file) => typeof file === 'string' && fs.existsSync(path.join(dir, file.replace(/^\.\//u, ''))),
144
+ );
145
+ if (shipped === undefined) return null;
146
+ return `${shipped.replace(/^\.\//u, '')} ships but dsh.client is not declared, so the harness never serves the bundle and the panel cannot appear`;
147
+ }
148
+
113
149
  /** Every path the manifest points at: exports, the bundle patch, the client entry. */
114
150
  export function declaredPaths(manifest) {
115
151
  const paths = new Set();
@@ -200,6 +236,7 @@ export function doctor(dir, { installed = false } = {}) {
200
236
  ['dsh field', checkDshField(manifest)],
201
237
  ['patch file', checkPatchFile(dir, manifest)],
202
238
  ['client entry', checkClientEntry(dir, manifest)],
239
+ ['client declaration', checkClientDeclaration(dir, manifest)],
203
240
  // After install the tarball is already unpacked, so `files` cannot be used to
204
241
  // decide what shipped: npm always ships package.json and the README.
205
242
  ['files list', installed === true ? null : checkFilesList(manifest)],
package/lib/init.mjs CHANGED
@@ -33,6 +33,7 @@ function manifest({ name, title, version }) {
33
33
  type: 'module',
34
34
  engines: { node: '>=18', dsh: '>=0.2.0' },
35
35
  main: 'index.js',
36
+ exports: { '.': './index.js', './client': './client.js' },
36
37
  files: ['index.js', 'client.js', 'cordis.patch.yml', 'README.md'],
37
38
  scripts: { test: 'node --test', doctor: 'dsh-plugin doctor .' },
38
39
  devDependencies: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-toolkit",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "Preflight, release and test DeepSeek Harness plugins: checks what the host needs, waits for npm to actually serve the version, and keeps the market index honest.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,6 +8,7 @@
8
8
  },
9
9
  "exports": {
10
10
  ".": "./index.js",
11
+ "./client": "./client.js",
11
12
  "./cli": "./lib/cli.mjs",
12
13
  "./testkit": "./lib/testkit/index.mjs"
13
14
  },
@@ -74,6 +75,13 @@
74
75
  "dsh": {
75
76
  "bundle": {
76
77
  "patch": "./cordis.patch.yml"
78
+ },
79
+ "client": {
80
+ "platform": "web",
81
+ "immediately": true,
82
+ "inject": [
83
+ "@deepseek-ai/dsh-client-ui-sidebar-right"
84
+ ]
77
85
  }
78
86
  },
79
87
  "main": "index.js"