kdczyz-dsh-model 1.2.0-beta → 1.2.1-beta

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.
@@ -1,10 +1,10 @@
1
- # Register dsh-kdczyz-mode — ONE package, THREE Loader entries.
1
+ # Register kdczyz-dsh-model — ONE package, THREE Loader entries.
2
2
  #
3
3
  # Why several entries, and why they use DIFFERENT module specifiers:
4
4
  #
5
- # entry A name: dsh-kdczyz-mode -> lib/index.js (WorkBuddy pool half)
6
- # entry B name: dsh-kdczyz-mode/trae -> lib/trae.js (Trae half)
7
- # entry C name: dsh-kdczyz-mode/qoder -> lib/qoder.js (Qoder half)
5
+ # entry A name: kdczyz-dsh-model -> lib/index.js (WorkBuddy pool half)
6
+ # entry B name: kdczyz-dsh-model/trae -> lib/trae.js (Trae half)
7
+ # entry C name: kdczyz-dsh-model/qoder -> lib/qoder.js (Qoder half)
8
8
  #
9
9
  # The two halves each declare `enabledModelIds` / `imageModelIds` /
10
10
  # `contextBudgets` / `authFile` with DIFFERENT semantics. Cordis keys a plugin's
@@ -35,8 +35,8 @@
35
35
  # comment in YAML and breaks parsing.
36
36
  - insert:
37
37
  - id: llm-workbuddy-xdpool
38
- name: dsh-kdczyz-mode
38
+ name: kdczyz-dsh-model
39
39
  - id: dsh-connect-trae
40
- name: dsh-kdczyz-mode/trae
40
+ name: kdczyz-dsh-model/trae
41
41
  - id: dsh-connect-qoder
42
- name: dsh-kdczyz-mode/qoder
42
+ name: kdczyz-dsh-model/qoder
@@ -6034,17 +6034,18 @@ const __WBC_CONSOLE_FACTORY__ = (react, jsxRuntime, embedded) => {
6034
6034
  // 内联执行可以只注册一次、顺序可控,且 vendored 代码一行都不用改
6035
6035
  // (便于日后对照上游升级)。
6036
6036
  //
6037
- // 注意注册 id:本 bundle 用**合并后的包名** dsh-kdczyz-mode 注册,
6038
- // 因为 client-modules 是按包名建表、按包名 require 的;两个 vendored 脚本
6039
- // 各自声明的 id 由下面的替身加载器捕获,不会真的注册进模块表。
6037
+ // 注意注册 id:本 bundle 用**安装包名** kdczyz-dsh-model 注册,因为 client-modules
6038
+ // 是按包名建表、按包名 require 的(官方规范:\"the browser artifact registers a
6039
+ // lazy factory whose id equals the package name\");两个 vendored 脚本各自声明的
6040
+ // id 由下面的替身加载器捕获,不会真的注册进模块表。
6040
6041
  window.__ModuleLoader__.load({
6041
- id: 'dsh-kdczyz-mode',
6042
+ id: 'kdczyz-dsh-model',
6042
6043
  factory: (require) => {
6043
6044
  var module = { exports: {} };
6044
6045
  var exports = module.exports;
6045
6046
 
6046
6047
  /** 与 package.json 的 name 一致;cordis 用它定位模块 */
6047
- const pkgName = 'dsh-kdczyz-mode';
6048
+ const pkgName = 'kdczyz-dsh-model';
6048
6049
 
6049
6050
  // React 运行时:管理页组件要用。
6050
6051
  //
@@ -20,7 +20,6 @@
20
20
  ".": "./lib/index.js",
21
21
  "./trae": "./lib/trae.js",
22
22
  "./qoder": "./lib/qoder.js",
23
- "./client": "./lib/client.js",
24
23
  "./package.json": "./package.json"
25
24
  },
26
25
  "files": [
@@ -92,21 +91,5 @@
92
91
  "test:qoder-streaming": "node test/qoder-streaming.test.mjs",
93
92
  "test:qoder-payload": "node test/qoder-payload.test.mjs",
94
93
  "test:qoder-dedup": "node test/qoder-dedup.test.mjs"
95
- },
96
- "dsh": {
97
- "bundle": {
98
- "patch": "./cordis.patch.yml"
99
- },
100
- "client": {
101
- "inject": [
102
- "@deepseek-ai/dsh-client-ui-renderer",
103
- "@deepseek-ai/dsh-client-ui-slots",
104
- "@deepseek-ai/dsh-client-locale",
105
- "@deepseek-ai/dsh-client-ui-settings",
106
- "@deepseek-ai/dsh-client-ui-settings-plugins",
107
- "@deepseek-ai/dsh-client-ui-primitives"
108
- ],
109
- "platform": "web"
110
- }
111
94
  }
112
95
  }
@@ -35,6 +35,7 @@
35
35
  import fs from 'node:fs';
36
36
  import os from 'node:os';
37
37
  import path from 'node:path';
38
+ import { createRequire } from 'node:module';
38
39
  import { pathToFileURL } from 'node:url';
39
40
 
40
41
  let pass = 0;
@@ -175,20 +176,65 @@ if (PLUGIN === undefined) {
175
176
  ok('package.json 可读', false, error.message);
176
177
  }
177
178
 
178
- /* —— 5) client bundle 唯一性(2026-10-12 启动崩溃的根因)—— */
179
+ /* —— 5) Loader entry 名必须能从 profile 解析 —— */
179
180
  //
180
- // DSH 的 client-modules 对每个「声明了 ./client 的 manifest」各 emit 份
181
- // client bundle。wrapper 与内层 manifest 若都声明了 ./client,且归一化后
182
- // 指向**同一个物理文件**,那这份代码会被打进同一个 module scope 两次:
181
+ // 2026-10-12 真机故障:包从 `dsh-kdczyz-mode` 改名为 `kdczyz-dsh-model` 后,
182
+ // 包内 cordis.patch.yml 的三个 entry 名没跟着改,于是宿主报
183
+ //
184
+ // 1 entry did not activate llm-workbuddy-xdpool (dsh-kdczyz-mode): failed to import
185
+ //
186
+ // 而插件管理页只显示「未运行」,没有任何报错 —— 因为 Loader 按 entry 的
187
+ // `name:` 去 import,而 `dsh-kdczyz-mode` 已经不是可解析的包名(它现在只是
188
+ // kdczyz-dsh-model 内部的一个子目录)。
189
+ //
190
+ // 这条断言直接拿 patch 里声明的 name 去解析,是拦这个故障的第一道防线。
191
+ const patchFile = path.join(PLUGIN, 'dsh-kdczyz-mode', 'cordis.patch.yml');
192
+ const patchCandidates = [patchFile, path.join(PLUGIN, 'cordis.patch.yml')]
193
+ .filter((f) => fs.existsSync(f));
194
+ if (patchCandidates.length === 0) {
195
+ ok('找到 cordis.patch.yml', false, patchFile);
196
+ } else {
197
+ let patchText = fs.readFileSync(patchCandidates[0], 'utf8');
198
+ // dsh.bundle.patch 可能指向别处,优先用 manifest 声明的那个
199
+ const declaredPatch = manifest.dsh?.bundle?.patch;
200
+ if (typeof declaredPatch === 'string') {
201
+ const p = path.resolve(PLUGIN, declaredPatch);
202
+ if (fs.existsSync(p)) patchText = fs.readFileSync(p, 'utf8');
203
+ }
204
+ const names = [...patchText.matchAll(/^\s*name:\s*(\S+)\s*$/gm)].map((m) => m[1]);
205
+ ok('patch 里声明了 Loader entry 名', names.length > 0, `找到 ${names.length} 个`);
206
+ for (const name of names) {
207
+ // 裸名 entry:必须能作为包名解析(这是 client 归属者)
208
+ // 子路径 entry:所属包名必须能解析
209
+ const pkgName = name.startsWith('@')
210
+ ? name.split('/').slice(0, 2).join('/')
211
+ : name.split('/')[0];
212
+ let resolved;
213
+ try {
214
+ resolved = createRequire(path.join(PROFILE, 'package.json')).resolve(`${pkgName}/package.json`);
215
+ } catch (error) {
216
+ ok(`entry "${name}" 可解析`, false, `${pkgName} 解析失败: ${error.code ?? error.message}`);
217
+ continue;
218
+ }
219
+ ok(`entry "${name}" 可解析`, fs.existsSync(resolved), resolved);
220
+ }
221
+ }
222
+
223
+ /* —— 6) client bundle 唯一性(2026-10-12 启动崩溃的根因)—— */
224
+ //
225
+ // DSH 的 client-modules 对每个「声明了 dsh.client 的 package」emit 一份 client
226
+ // bundle。wrapper 与内层 manifest 若都声明了,且归一化后指向**同一个物理
227
+ // 文件**,这份代码会被打进同一个 module scope 两次:
183
228
  //
184
229
  // Uncaught SyntaxError: Identifier 'XDPOOL_CLIENT_SRC' has already been declared
185
230
  // -> entry 激活失败 -> web boot: 1 entry did not activate -> 应用起不来
186
231
  //
187
- // 关键在于 loader 的归属判定(client-modules 的 nearestPackage):
188
- // - 裸名 entry expectedPackageName = 包名 -> 向上找 name 相等的 manifest
189
- // - 子路径 entry expectedPackageName = undefined -> 向上找**第一个** manifest 即接受
190
- // 于是裸名 entry 归wrapper、子路径 entry 归内层 —— 两个不同 packageName
191
- // 各自声称同一个 client.js。这条断言就是拦住这个组合。
232
+ // 归属规则(client-modules 的 locatePkgJson/resolveMeta,逐字核对过):
233
+ // - 裸名 entry expectedPackageName = 包名 -> 向上找 name 相等的 manifest;包装成
234
+ // `kdczyz-dsh-model` 时归 **wrapper**
235
+ // - 子路径 entry `if (!pathLike && expectedPackageName === void 0) return void 0;`
236
+ // -> **完全不贡献 client**,不会与裸名 entry 抢
237
+ // 所以 client 必须且只能由 wrapper 声明 —— 这条断言就锁这个不变量。
192
238
  const claims = [];
193
239
  for (const dir of [PLUGIN, path.join(PLUGIN, 'dsh-kdczyz-mode')]) {
194
240
  const manifestPath = path.join(dir, 'package.json');
@@ -196,11 +242,12 @@ if (PLUGIN === undefined) {
196
242
  let pkg;
197
243
  try { pkg = JSON.parse(fs.readFileSync(manifestPath, 'utf8')); } catch { continue; }
198
244
  const target = pkg.exports?.['./client'];
199
- if (typeof target !== 'string') continue;
245
+ if (typeof target !== 'string' && pkg.dsh?.client === undefined) continue;
200
246
  claims.push({
201
247
  name: pkg.name,
202
248
  manifest: path.relative(PROFILE_NM, manifestPath),
203
- file: path.resolve(dir, target),
249
+ file: typeof target === 'string' ? path.resolve(dir, target) : '(未声明 ./client)',
250
+ declaresDshClient: pkg.dsh?.client !== undefined,
204
251
  });
205
252
  }
206
253
  const byFile = new Map();
@@ -211,6 +258,14 @@ if (PLUGIN === undefined) {
211
258
  collided.length === 0,
212
259
  collided.map(([f, names]) => `${path.relative(PROFILE_NM, f)} 被 ${names.join(' + ')} 同时声明`).join('; '),
213
260
  );
261
+ // 声明了 dsh.client 的 manifest 必须同时给出 ./client,否则 resolveMeta 抛错
262
+ for (const c of claims) {
263
+ ok(
264
+ `${c.name} 声明 dsh.client 时也提供 ./client`,
265
+ !c.declaresDshClient || c.file !== '(未声明 ./client)',
266
+ c.manifest,
267
+ );
268
+ }
214
269
  }
215
270
 
216
271
  console.log(`\nhost-assembly: ${pass} 通过, ${fail} 失败${skip > 0 ? `, ${skip} 跳过` : ''}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kdczyz-dsh-model",
3
- "version": "1.2.0-beta",
3
+ "version": "1.2.1-beta",
4
4
  "description": "Installable wrapper for the DSH plugin in dsh-kdczyz-mode/: WorkBuddy model pool + Trae connector + Qoder account pool as three independent providers, plus one settings page with six tabs (XD Pool / Trae config [provider switch, account binding, model selection, account pool] / accounts [WorkBuddy + Trae + Qoder, three columns] / Qoder pool [device-flow login, per-account credits, cooldown] / credits / usage history). This root manifest exists so the DSH plugin manager can install the package: it declares dsh.bundle.patch at its root and re-exports the inner package's entry points. It deliberately declares NO dsh.client and NO ./client export - the client half belongs to the inner dsh-kdczyz-mode package. Re-exporting ./client here would make two manifests claim the same client.js; DSH emits one client bundle per claiming package, and the duplicate makes the renderer throw 'Identifier XDPOOL_CLIENT_SRC has already been declared', which fails web boot and prevents the app from starting.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,6 +24,7 @@
24
24
  ".": "./dsh-kdczyz-mode/lib/index.js",
25
25
  "./trae": "./dsh-kdczyz-mode/lib/trae.js",
26
26
  "./qoder": "./dsh-kdczyz-mode/lib/qoder.js",
27
+ "./client": "./dsh-kdczyz-mode/lib/client.js",
27
28
  "./package.json": "./package.json"
28
29
  },
29
30
  "keywords": [
@@ -68,6 +69,17 @@
68
69
  "dsh": {
69
70
  "bundle": {
70
71
  "patch": "./dsh-kdczyz-mode/cordis.patch.yml"
72
+ },
73
+ "client": {
74
+ "inject": [
75
+ "@deepseek-ai/dsh-client-ui-renderer",
76
+ "@deepseek-ai/dsh-client-ui-slots",
77
+ "@deepseek-ai/dsh-client-locale",
78
+ "@deepseek-ai/dsh-client-ui-settings",
79
+ "@deepseek-ai/dsh-client-ui-settings-plugins",
80
+ "@deepseek-ai/dsh-client-ui-primitives"
81
+ ],
82
+ "platform": "web"
71
83
  }
72
84
  }
73
85
  }