@dan-ai-studio/dshopencodego 0.1.50 → 0.1.51

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
@@ -247,7 +247,7 @@ npm test # contract tests against a real local HTTP mock gateway
247
247
 
248
248
  **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.
249
249
 
250
- 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 **48 test files** — a number `tests/readme-consistency.spec.ts` checks against the `tests/` directory, so it cannot drift.
250
+ 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 **50 test files** — a number `tests/readme-consistency.spec.ts` checks against the `tests/` directory, so it cannot drift.
251
251
 
252
252
  ## Releasing (maintainers)
253
253
 
package/README.md CHANGED
@@ -247,7 +247,7 @@ npm test # 契约测试:真实 HTTP mock 网关,断言请求头/
247
247
 
248
248
  **顺序有讲究**:`npm run build` 要排在 `npm test` 之前——`tests/pack-contents.spec.ts` 会遍历 `exports` 的每个目标,`lib/` 存在与否决定这条检查是执行还是被跳过(不报错,但会少一层保护)。`package.json` 已移除 `prepare`,因此 `npm ci` 不会再替你隐式构建;三个 CI workflow 都显式跑了 `npm run build`。
249
249
 
250
- 测试覆盖配置校验、协议阶梯、网关与在线元数据、目录投影、适配器(三种协议的线上请求)、Remote 契约与服务、会话头不变量、用量窗口与计量、客户端控制器与用量组件、两半的挂载与登记、流空闲超时与中止的错误映射、验证脚本的退出码契约、以及几条**结构性不变量**(inject 声明与源码读取一致、peer 覆盖双向、README 与 manifest 一致、README 对上游的断言与实装的上游一致)。共 **48 个测试文件**——这个数字由 `tests/readme-consistency.spec.ts` 对着 `tests/` 目录校验,不会漂移。
250
+ 测试覆盖配置校验、协议阶梯、网关与在线元数据、目录投影、适配器(三种协议的线上请求)、Remote 契约与服务、会话头不变量、用量窗口与计量、客户端控制器与用量组件、两半的挂载与登记、流空闲超时与中止的错误映射、验证脚本的退出码契约、以及几条**结构性不变量**(inject 声明与源码读取一致、peer 覆盖双向、README 与 manifest 一致、README 对上游的断言与实装的上游一致)。共 **50 个测试文件**——这个数字由 `tests/readme-consistency.spec.ts` 对着 `tests/` 目录校验,不会漂移。
251
251
 
252
252
  ## 发布(维护者)
253
253
 
package/lib/index.js CHANGED
@@ -43071,19 +43071,24 @@ function readFactsCache(cacheDir) {
43071
43071
  facts.set(id, fact);
43072
43072
  }
43073
43073
  if (facts.size === 0) return void 0;
43074
- return { facts, updatedAt: typeof parsed.updatedAt === "number" ? parsed.updatedAt : 0 };
43074
+ return {
43075
+ facts,
43076
+ updatedAt: typeof parsed.updatedAt === "number" ? parsed.updatedAt : 0,
43077
+ etag: typeof parsed.etag === "string" ? parsed.etag : void 0
43078
+ };
43075
43079
  } catch {
43076
43080
  return void 0;
43077
43081
  }
43078
43082
  }
43079
- function writeFactsCache(cacheDir, facts) {
43083
+ function writeFactsCache(cacheDir, facts, etag) {
43080
43084
  if (cacheDir === void 0 || facts.size === 0) return;
43081
43085
  try {
43082
43086
  mkdirSync2(cacheDir, { recursive: true });
43083
43087
  const file = {
43084
43088
  version: CACHE_VERSION2,
43085
43089
  facts: Object.fromEntries(facts),
43086
- updatedAt: Date.now()
43090
+ updatedAt: Date.now(),
43091
+ ...etag === void 0 ? {} : { etag }
43087
43092
  };
43088
43093
  writeFileSync2(join3(cacheDir, CACHE_FILE2), `${JSON.stringify(file)}
43089
43094
  `, "utf8");
@@ -43159,6 +43164,7 @@ var OpencodeGoCatalog = class {
43159
43164
  if (cached !== void 0) {
43160
43165
  this.cachedMetadata = { models: cached.facts, errors: /* @__PURE__ */ new Map() };
43161
43166
  this.cachedAt = cached.updatedAt;
43167
+ this.metadataETag = cached.etag;
43162
43168
  }
43163
43169
  }
43164
43170
  /**
@@ -43382,29 +43388,40 @@ var OpencodeGoCatalog = class {
43382
43388
  * same document that a shell reads in half a second can take long enough
43383
43389
  * to outrun a budget set for kilobyte-sized documents.
43384
43390
  * @param builtin - the installed catalog, for the parse.
43391
+ * @param conditional - whether to ask whether the document changed. A
43392
+ * conditional request the registry answers with `304` costs a round
43393
+ * trip and no body, which is the difference between a new session that
43394
+ * starts immediately and one that waits for megabytes.
43385
43395
  * @returns the parsed metadata.
43386
43396
  */
43387
- async readMetadataDocument(builtin) {
43397
+ async readMetadataDocument(builtin, conditional = true) {
43388
43398
  const response = await fetch(MODEL_METADATA_URL, {
43389
43399
  redirect: "error",
43390
43400
  headers: {
43391
43401
  ...attributionHeaders3(),
43392
43402
  accept: "application/json",
43393
43403
  "cache-control": "no-cache",
43394
- ...this.metadataETag === void 0 ? {} : { "if-none-match": this.metadataETag }
43404
+ ...conditional && this.metadataETag !== void 0 ? { "if-none-match": this.metadataETag } : {}
43395
43405
  },
43396
43406
  signal: AbortSignal.timeout(MODEL_METADATA_TIMEOUT_MS)
43397
43407
  });
43398
- if (response.status === 304 && this.metadataDocument !== void 0) {
43408
+ if (response.status === 304) {
43399
43409
  await response.body?.cancel().catch(() => {
43400
43410
  });
43401
- const parsed2 = readOnlineMetadata(this.metadataDocument, {
43402
- builtin,
43403
- defaults: this.options.defaults,
43404
- overrides: this.options.overrides
43405
- });
43406
- this.lastMetadata = parsed2;
43407
- return parsed2;
43411
+ if (this.metadataDocument !== void 0) {
43412
+ const parsed2 = readOnlineMetadata(this.metadataDocument, {
43413
+ builtin,
43414
+ defaults: this.options.defaults,
43415
+ overrides: this.options.overrides
43416
+ });
43417
+ this.lastMetadata = parsed2;
43418
+ return parsed2;
43419
+ }
43420
+ if (this.cachedMetadata !== void 0) {
43421
+ this.lastMetadata = this.cachedMetadata;
43422
+ return this.cachedMetadata;
43423
+ }
43424
+ return this.readMetadataDocument(builtin, false);
43408
43425
  }
43409
43426
  if (!response.ok) {
43410
43427
  await response.body?.cancel().catch(() => {
@@ -43420,7 +43437,7 @@ var OpencodeGoCatalog = class {
43420
43437
  overrides: this.options.overrides
43421
43438
  });
43422
43439
  this.lastMetadata = parsed;
43423
- writeFactsCache(this.options.cacheDir, parsed.models);
43440
+ writeFactsCache(this.options.cacheDir, parsed.models, this.metadataETag);
43424
43441
  return parsed;
43425
43442
  }
43426
43443
  /**
@@ -45964,7 +45981,7 @@ function createUpdateChecker(deps) {
45964
45981
  }
45965
45982
 
45966
45983
  // src/update/version.ts
45967
- var PLUGIN_VERSION = true ? "0.1.50" : "0.0.0-dev";
45984
+ var PLUGIN_VERSION = true ? "0.1.51" : "0.0.0-dev";
45968
45985
 
45969
45986
  // src/update/service.ts
45970
45987
  import { TypertRemoteService as TypertRemoteService2 } from "@deepseek-ai/dsh-typert-protocol";
@@ -46167,6 +46184,11 @@ function apply(ctx, raw) {
46167
46184
  }
46168
46185
  });
46169
46186
  ctx.plugin(OpencodeGoUpdateService, { currentVersion: PLUGIN_VERSION });
46187
+ ctx.effect(() => {
46188
+ void adapter.catalogOf(current()).snapshot().catch(() => void 0);
46189
+ return () => {
46190
+ };
46191
+ }, "dshopencodego: catalog warm-up");
46170
46192
  let registration;
46171
46193
  let visibilityFacts = JSON.stringify(current().modelVisibility);
46172
46194
  const applyRoute = (credentialConfigured) => {
@@ -221,6 +221,10 @@ export declare class OpencodeGoCatalog {
221
221
  * same document that a shell reads in half a second can take long enough
222
222
  * to outrun a budget set for kilobyte-sized documents.
223
223
  * @param builtin - the installed catalog, for the parse.
224
+ * @param conditional - whether to ask whether the document changed. A
225
+ * conditional request the registry answers with `304` costs a round
226
+ * trip and no body, which is the difference between a new session that
227
+ * starts immediately and one that waits for megabytes.
224
228
  * @returns the parsed metadata.
225
229
  */
226
230
  private readMetadataDocument;
@@ -24,11 +24,13 @@ import type { ModelFacts } from './metadata.ts';
24
24
  * fall back on and says so, rather than pretending the models have no
25
25
  * capabilities.
26
26
  * @param cacheDir - the plugin's cache directory.
27
- * @returns the remembered facts and when they were written, or undefined.
27
+ * @returns the remembered facts, the document's ETag, and when they were
28
+ * written, or undefined.
28
29
  */
29
30
  export declare function readFactsCache(cacheDir: string | undefined): {
30
31
  readonly facts: ReadonlyMap<string, ModelFacts>;
31
32
  readonly updatedAt: number;
33
+ readonly etag: string | undefined;
32
34
  } | undefined;
33
35
  /**
34
36
  * Remember the facts a successful read produced.
@@ -37,5 +39,7 @@ export declare function readFactsCache(cacheDir: string | undefined): {
37
39
  * next restart, and nothing else: the run continues with what it has.
38
40
  * @param cacheDir - the plugin's cache directory.
39
41
  * @param facts - the parsed facts to remember.
42
+ * @param etag - the document's ETag, so the next process can ask whether the
43
+ * document changed instead of downloading it again.
40
44
  */
41
- export declare function writeFactsCache(cacheDir: string | undefined, facts: ReadonlyMap<string, ModelFacts>): void;
45
+ export declare function writeFactsCache(cacheDir: string | undefined, facts: ReadonlyMap<string, ModelFacts>, etag?: string): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dan-ai-studio/dshopencodego",
3
- "version": "0.1.50",
3
+ "version": "0.1.51",
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",