@dan-ai-studio/dshopencodego 0.1.94 → 0.1.96

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/README.en.md CHANGED
@@ -293,7 +293,7 @@ npm run seed # refresh the bundled catalog seed before a release (see "Re
293
293
 
294
294
  **Order matters**: `npm run build` must come before `npm test` — `tests/pack-contents.spec.ts` walks every `exports` target, and whether `lib/` exists decides whether that check runs or is silently skipped (it does not fail, it just stops protecting you). `package.json` no longer carries `prepare`, so `npm ci` will not build for you; all three CI workflows run `npm run build` explicitly.
295
295
 
296
- The suite covers configuration validation, the protocol ladder, gateway and online metadata, the catalog projection, the adapter on the wire (all three protocols), Remote contracts and services, session-header invariants, usage windows and the meter, the client controller and usage pill, both halves' mounting and registration, the error mapping for stream idle timeouts and aborts, the exit-code contract of the verification scripts, and several **structural invariants** (inject declarations match the source's reads, peer coverage holds both ways, the READMEs match the manifest, and the READMEs' claims about the upstream match the upstream actually installed). That is **64 test files** — a number `tests/readme-consistency.spec.ts` checks against the `tests/` directory, so it cannot drift.
296
+ The suite covers configuration validation, the protocol ladder, gateway and online metadata, the catalog projection, the adapter on the wire (all three protocols), Remote contracts and services, session-header invariants, usage windows and the meter, the client controller and usage pill, both halves' mounting and registration, the error mapping for stream idle timeouts and aborts, the exit-code contract of the verification scripts, and several **structural invariants** (inject declarations match the source's reads, peer coverage holds both ways, the READMEs match the manifest, and the READMEs' claims about the upstream match the upstream actually installed). That is **65 test files** — a number `tests/readme-consistency.spec.ts` checks against the `tests/` directory, so it cannot drift.
297
297
 
298
298
  ## Releasing (maintainers)
299
299
 
package/README.md CHANGED
@@ -292,7 +292,7 @@ npm run seed # 发版前刷新捆绑的目录种子(见「发布」)
292
292
 
293
293
  **顺序有讲究**:`npm run build` 要排在 `npm test` 之前——`tests/pack-contents.spec.ts` 会遍历 `exports` 的每个目标,`lib/` 存在与否决定这条检查是执行还是被跳过(不报错,但会少一层保护)。`package.json` 已移除 `prepare`,因此 `npm ci` 不会再替你隐式构建;三个 CI workflow 都显式跑了 `npm run build`。
294
294
 
295
- 测试覆盖配置校验、协议阶梯、网关与在线元数据、目录投影、适配器(三种协议的线上请求)、Remote 契约与服务、会话头不变量、用量窗口与计量、客户端控制器与用量组件、两半的挂载与登记、流空闲超时与中止的错误映射、验证脚本的退出码契约、以及几条**结构性不变量**(inject 声明与源码读取一致、peer 覆盖双向、README 与 manifest 一致、README 对上游的断言与实装的上游一致)。共 **64 个测试文件**——这个数字由 `tests/readme-consistency.spec.ts` 对着 `tests/` 目录校验,不会漂移。
295
+ 测试覆盖配置校验、协议阶梯、网关与在线元数据、目录投影、适配器(三种协议的线上请求)、Remote 契约与服务、会话头不变量、用量窗口与计量、客户端控制器与用量组件、两半的挂载与登记、流空闲超时与中止的错误映射、验证脚本的退出码契约、以及几条**结构性不变量**(inject 声明与源码读取一致、peer 覆盖双向、README 与 manifest 一致、README 对上游的断言与实装的上游一致)。共 **65 个测试文件**——这个数字由 `tests/readme-consistency.spec.ts` 对着 `tests/` 目录校验,不会漂移。
296
296
 
297
297
  ## 发布(维护者)
298
298
 
package/lib/client.js CHANGED
@@ -173,6 +173,75 @@ var catalogRemote = {
173
173
  ]
174
174
  };
175
175
 
176
+ // src/desktop/contract.ts
177
+ function parseRelease(value) {
178
+ if (value === null || typeof value !== "object") throw new Error("invalid desktop release");
179
+ const row = value;
180
+ const version = row["version"];
181
+ const url = row["url"];
182
+ if (typeof version !== "string" || version.length === 0) throw new Error("invalid desktop release");
183
+ if (typeof url !== "string" || url.length === 0) throw new Error("invalid desktop release");
184
+ const size = row["size"];
185
+ const sha512 = row["sha512"];
186
+ const stagingPercentage = row["stagingPercentage"];
187
+ const releaseDate = row["releaseDate"];
188
+ return {
189
+ version,
190
+ url,
191
+ ...typeof size === "number" && Number.isFinite(size) && size >= 0 ? { size } : {},
192
+ ...typeof sha512 === "string" && sha512.length > 0 ? { sha512 } : {},
193
+ ...typeof stagingPercentage === "number" && Number.isFinite(stagingPercentage) ? { stagingPercentage } : {},
194
+ ...typeof releaseDate === "string" && releaseDate.length > 0 ? { releaseDate } : {}
195
+ };
196
+ }
197
+ function parseDesktopReading(value) {
198
+ if (value === null || typeof value !== "object") throw new Error("invalid desktop reading");
199
+ const row = value;
200
+ if (typeof row["checked"] !== "boolean") throw new Error("invalid desktop reading");
201
+ if (typeof row["checkedAt"] !== "number" || !Number.isFinite(row["checkedAt"])) {
202
+ throw new Error("invalid desktop reading");
203
+ }
204
+ if (typeof row["platform"] !== "string") throw new Error("invalid desktop reading");
205
+ if (typeof row["channel"] !== "string") throw new Error("invalid desktop reading");
206
+ const release = row["release"];
207
+ return {
208
+ checked: row["checked"],
209
+ checkedAt: row["checkedAt"],
210
+ platform: row["platform"],
211
+ channel: row["channel"],
212
+ ...release === void 0 ? {} : { release: parseRelease(release) }
213
+ };
214
+ }
215
+ var codec2 = {
216
+ mode: "strict",
217
+ typeSymbol: "@dan-ai-studio/dshopencodego#DesktopReading",
218
+ schema: { parse: parseDesktopReading },
219
+ create: () => ({ parse: parseDesktopReading })
220
+ };
221
+ var desktopRemote = {
222
+ package: "@dan-ai-studio/dshopencodego",
223
+ descriptors: [
224
+ {
225
+ id: "@dan-ai-studio/dshopencodego#opencodeGoDesktop/readDesktop",
226
+ service: "opencodeGoDesktop",
227
+ namespace: "opencodeGoDesktop",
228
+ method: "readDesktop",
229
+ invocation: { kind: "direct" },
230
+ parameters: [],
231
+ result: codec2
232
+ },
233
+ {
234
+ id: "@dan-ai-studio/dshopencodego#opencodeGoDesktop/refreshDesktop",
235
+ service: "opencodeGoDesktop",
236
+ namespace: "opencodeGoDesktop",
237
+ method: "refreshDesktop",
238
+ invocation: { kind: "direct" },
239
+ parameters: [],
240
+ result: codec2
241
+ }
242
+ ]
243
+ };
244
+
176
245
  // src/network/contract.ts
177
246
  function parseNetworkReading(value) {
178
247
  if (value === null || typeof value !== "object") throw new Error("invalid network reading");
@@ -187,7 +256,7 @@ function parseNetworkReading(value) {
187
256
  ...typeof failed === "boolean" ? { failed } : {}
188
257
  };
189
258
  }
190
- var codec2 = {
259
+ var codec3 = {
191
260
  mode: "strict",
192
261
  typeSymbol: "@dan-ai-studio/dshopencodego#NetworkReading",
193
262
  schema: { parse: parseNetworkReading },
@@ -203,7 +272,7 @@ var networkRemote = {
203
272
  method: "readNetwork",
204
273
  invocation: { kind: "direct" },
205
274
  parameters: [],
206
- result: codec2
275
+ result: codec3
207
276
  }
208
277
  ]
209
278
  };
@@ -345,7 +414,7 @@ function parseRequestLogSnapshot(value) {
345
414
  ...typeof row["poolKey"] === "string" ? { poolKey: row["poolKey"] } : {}
346
415
  };
347
416
  }
348
- var codec3 = {
417
+ var codec4 = {
349
418
  mode: "strict",
350
419
  typeSymbol: "@dan-ai-studio/dshopencodego#RequestLogSnapshot",
351
420
  schema: { parse: parseRequestLogSnapshot },
@@ -361,7 +430,7 @@ var requestLogRemote = {
361
430
  method: "readLog",
362
431
  invocation: { kind: "direct" },
363
432
  parameters: [],
364
- result: codec3
433
+ result: codec4
365
434
  }
366
435
  ]
367
436
  };
@@ -385,7 +454,7 @@ function parseUpdateStatus(value) {
385
454
  checked: row["checked"]
386
455
  };
387
456
  }
388
- var codec4 = (typeSymbol, parse) => ({
457
+ var codec5 = (typeSymbol, parse) => ({
389
458
  mode: "strict",
390
459
  typeSymbol,
391
460
  schema: { parse },
@@ -401,7 +470,7 @@ var updateRemote = {
401
470
  method: "readUpdate",
402
471
  invocation: { kind: "direct" },
403
472
  parameters: [],
404
- result: codec4("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
473
+ result: codec5("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
405
474
  },
406
475
  {
407
476
  id: "@dan-ai-studio/dshopencodego#opencodeGoUpdate/refreshUpdate",
@@ -410,7 +479,7 @@ var updateRemote = {
410
479
  method: "refreshUpdate",
411
480
  invocation: { kind: "direct" },
412
481
  parameters: [],
413
- result: codec4("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
482
+ result: codec5("@dan-ai-studio/dshopencodego#UpdateStatus", parseUpdateStatus)
414
483
  }
415
484
  ]
416
485
  };
@@ -476,7 +545,7 @@ function parseGoMeter(value) {
476
545
  })
477
546
  };
478
547
  }
479
- var codec5 = (typeSymbol, parse) => ({
548
+ var codec6 = (typeSymbol, parse) => ({
480
549
  mode: "strict",
481
550
  typeSymbol,
482
551
  schema: { parse },
@@ -492,7 +561,7 @@ var usageRemote = {
492
561
  method: "readWindows",
493
562
  invocation: { kind: "direct" },
494
563
  parameters: [],
495
- result: codec5("@dan-ai-studio/dshopencodego#GoUsageWindows", parseUsageWindows)
564
+ result: codec6("@dan-ai-studio/dshopencodego#GoUsageWindows", parseUsageWindows)
496
565
  },
497
566
  {
498
567
  id: "@dan-ai-studio/dshopencodego#opencodeGoUsage/readMeter",
@@ -501,7 +570,7 @@ var usageRemote = {
501
570
  method: "readMeter",
502
571
  invocation: { kind: "direct" },
503
572
  parameters: [],
504
- result: codec5("@dan-ai-studio/dshopencodego#GoMeter", parseGoMeter)
573
+ result: codec6("@dan-ai-studio/dshopencodego#GoMeter", parseGoMeter)
505
574
  }
506
575
  ]
507
576
  };
@@ -1412,20 +1481,15 @@ var SectionController = class _SectionController {
1412
1481
  /**
1413
1482
  * The desktop download Remote, when the running build mounted it.
1414
1483
  *
1415
- * Deliberately *not* in `client/index.ts`'s inject list. A declared
1416
- * dependency that never mounts does not degrade — Cordis simply never runs
1417
- * the injection, so the whole settings section disappears, which is exactly
1418
- * what a missing desktop namespace did to 0.1.92. Reading it here instead
1419
- * costs a caught error when it is absent and keeps every other panel on the
1420
- * page alive; the download row then says it is not ready.
1484
+ * Read through the holder rather than from `services.remote`: Cordis refuses
1485
+ * a service read that was not declared in an injection, and declaring this
1486
+ * one in the *main* injection is what removed the whole settings section in
1487
+ * 0.1.92. The holder is filled by its own `scope.inject`, so it is populated
1488
+ * exactly when the namespace exists and empty otherwise.
1421
1489
  * @returns the mounted desktop Remote, or undefined when it is absent.
1422
1490
  */
1423
1491
  desktopRemote() {
1424
- try {
1425
- return this.services.remote.opencodeGoDesktop;
1426
- } catch {
1427
- return void 0;
1428
- }
1492
+ return this.services.desktop?.current;
1429
1493
  }
1430
1494
  /**
1431
1495
  * Ask the Host which installer the desktop download host publishes.
@@ -3460,6 +3524,7 @@ function apply(ctx) {
3460
3524
  ...catalogRemote.descriptors,
3461
3525
  ...updateRemote.descriptors,
3462
3526
  ...networkRemote.descriptors,
3527
+ ...desktopRemote.descriptors,
3463
3528
  ...requestLogRemote.descriptors
3464
3529
  ]
3465
3530
  });
@@ -3476,12 +3541,20 @@ function apply(ctx) {
3476
3541
  ctx.inject(["configForms", "remote.opencodeGoCatalog", "remote.opencodeGoUpdate", "remote.opencodeGoNetwork", "remote.opencodeGoRequestLog", "remote.credentials"], (scope) => {
3477
3542
  const forms = scope.get("configForms");
3478
3543
  const pluginManager = {};
3544
+ const desktop = {};
3479
3545
  const profile = forms?.get("dshopencodego");
3480
3546
  const controller = new SectionController({
3481
3547
  remote: scope.remote,
3482
3548
  pluginManager,
3549
+ desktop,
3483
3550
  scope: profile
3484
3551
  });
3552
+ scope.inject(["remote.opencodeGoDesktop"], (desktopScope) => {
3553
+ desktop.current = desktopScope.remote.opencodeGoDesktop;
3554
+ return () => {
3555
+ desktop.current = void 0;
3556
+ };
3557
+ });
3485
3558
  scope.inject(["remote.pluginManager"], (managerScope) => {
3486
3559
  pluginManager.current = managerScope.remote.pluginManager;
3487
3560
  return () => {
package/lib/index.js CHANGED
@@ -80611,7 +80611,7 @@ function createUpdateChecker(deps) {
80611
80611
  }
80612
80612
 
80613
80613
  // src/update/version.ts
80614
- var PLUGIN_VERSION = true ? "0.1.94" : "0.0.0-dev";
80614
+ var PLUGIN_VERSION = true ? "0.1.96" : "0.0.0-dev";
80615
80615
 
80616
80616
  // src/update/service.ts
80617
80617
  import { TypertRemoteService as TypertRemoteService5 } from "@deepseek-ai/dsh-typert-protocol";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dan-ai-studio/dshopencodego",
3
- "version": "0.1.94",
3
+ "version": "0.1.96",
4
4
  "description": "OpenCode Go provider for DeepSeek Harness: live gateway catalog, per-conversation session header, usage",
5
5
  "type": "module",
6
6
  "license": "MIT",