@dan-ai-studio/dshopencodego 0.1.36 → 0.1.37

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
@@ -198,6 +198,7 @@ Things to keep in mind when maintaining this:
198
198
  | "The settings write was rejected" | Usually a concurrent writer (another window or process) holding the same profile. The plugin retries once automatically; if it still fails the view has reloaded — click again. |
199
199
  | The usage button shows "unavailable" | An endpoint or credential change invalidated the previous reading. Fix the configuration and press Retry. It never shows `0` in place of a missing reading. |
200
200
  | npm publish fails with `ENEEDAUTH` | OIDC did not match: check the Trusted Publisher's **workflow filename** (must be exactly `publish-npm.yml`, case-sensitive) and the organization/repository fields; run on GitHub-hosted runners with `id-token: write`. A `repository.url` that does not match the GitHub repository is rejected as well. |
201
+ | A flood of `Accessing non-existent property 'Allow' of module exports inside circular dependency` | Caused by `pi-ai`'s **named import** of `partial-json`: resolving a named export from CommonJS enumerates the module's exports, and that package's `index.js`/`options.js` require each other, so reading `Allow` before its module initialises prints once per read — **a plugin reload turns it into a flood** (a restart usually clears it). **No functional impact**: `parse` was verified against that behaviour. Since v0.1.37 this plugin filters exactly that one message by prefix (Node gives it no type, so `--disable-warning` cannot select it); every other warning passes through untouched. |
201
202
  | The whole DSH process stalls during ultra-long tool calls (multi-MB arguments) | Observed on pi-ai `0.87.1`: per-delta re-parsing of the accumulated arguments (issue #9265 / PR #9461). This plugin does not port DSH's consumer-side patch (ADR-0005); the bundled dependency is now `~1.3.0`, so a recurrence would be upstream behaviour and would be fixed by an upstream release. |
202
203
 
203
204
  ## Development
package/README.md CHANGED
@@ -198,6 +198,7 @@ API Key 通过 Harness 凭证库提供(引用名 `OPENCODE_GO_API_KEY`),
198
198
  | 设置页出现「设置写入被拒绝」 | 通常是与另一个窗口/进程并发写同一 profile;插件会自动重试一次,仍失败时界面已重载最新状态,再点一次即可。 |
199
199
  | 用量按钮显示「不可用」 | 端点或凭证变化导致旧读数作废;配置正确后点「重试」。数值不会以 0 冒充。 |
200
200
  | npm 发布报 `ENEEDAUTH` | OIDC 没匹配上:核对包设置里 Trusted Publisher 的 **workflow 文件名**(必须恰为 `publish-npm.yml`、大小写敏感)与组织/仓库字段;确认跑在 GitHub 托管 runner 上且工作流带 `id-token: write`。`package.json` 的 `repository.url` 与仓库不符也会被拒。 |
201
+ | 日志成片出现 `Accessing non-existent property 'Allow' of module exports inside circular dependency` | 成因是 `pi-ai` 对 `partial-json` 的**具名导入**:解析 CJS 的具名导出会枚举其 exports,而该包内部 `index.js`/`options.js` 互相 require,读到尚未初始化的 `Allow` 就打印一次——**插件重载会让它成片出现**(重启后往往消失)。**无功能影响**:`parse` 行为已实测验证。自 v0.1.37 起本插件**按消息前缀精确过滤这一条**(Node 未给它 type,`--disable-warning` 选不中),其余警告一律原样透传。 |
201
202
  | 超长工具调用(多 MB 参数)期间整个 DSH 进程卡顿 | 曾在 pi-ai `0.87.1` 上观测到逐 delta 重解析的固有开销(issue #9265 / PR #9461)。本插件不移植 DSH 的消费者侧补丁(ADR-0005);当前自带依赖已是 `~1.3.0`,若仍复现则属上游行为,随其发版解决。 |
202
203
 
203
204
  ## 开发
package/lib/client.js CHANGED
@@ -562,7 +562,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")
562
562
  style.textContent = ".d7lz0W_root{color:var(--dsw-alias-label-primary);flex-direction:column;gap:1.25rem;display:flex}.d7lz0W_title{margin:0;font-size:1.05rem}.d7lz0W_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.8rem}.d7lz0W_warn{color:var(--dsw-alias-state-warn-primary);margin:0;font-size:.8rem}.d7lz0W_ok{color:var(--dsw-alias-state-success-primary);font-size:.8rem}.d7lz0W_block{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:.6rem;flex-direction:column;gap:.5rem;padding:.85rem;display:flex}.d7lz0W_row{flex-wrap:wrap;align-items:center;gap:.5rem;display:flex}.d7lz0W_row>strong{margin-right:auto}.d7lz0W_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);min-width:10rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;flex:14rem;padding:.35rem .5rem;font-size:.85rem}.d7lz0W_button{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;padding:.35rem .7rem;font-size:.8rem}.d7lz0W_button:disabled{color:var(--dsw-alias-state-idle-primary);cursor:default}.d7lz0W_number{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:5rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}.d7lz0W_select{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:100%;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}.d7lz0W_list{flex-direction:column;display:flex}.d7lz0W_item{border-top:1px solid var(--dsw-alias-border-l1);align-items:flex-start;gap:.5rem;padding:.45rem .15rem;display:flex}.d7lz0W_item input[type=checkbox]{accent-color:var(--dsw-alias-brand-primary);margin-top:.15rem}.d7lz0W_itemBody{flex-direction:column;gap:.15rem;min-width:0;display:flex}.d7lz0W_itemMain{flex-wrap:wrap;align-items:baseline;gap:.6rem;display:flex}.d7lz0W_itemMeta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:.75rem;font-size:.75rem;display:flex}.d7lz0W_itemModalities{color:var(--dsw-alias-label-secondary);font-size:.75rem}.d7lz0W_name{color:var(--dsw-alias-label-primary)}.d7lz0W_mono{color:var(--dsw-alias-label-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.d7lz0W_badge{color:var(--dsw-alias-brand-primary)}";
563
563
  document.head.appendChild(style);
564
564
  }
565
- var section_default = { "button": "d7lz0W_button", "itemMeta": "d7lz0W_itemMeta", "mono": "d7lz0W_mono", "select": "d7lz0W_select", "hint": "d7lz0W_hint", "itemMain": "d7lz0W_itemMain", "ok": "d7lz0W_ok", "number": "d7lz0W_number", "title": "d7lz0W_title", "name": "d7lz0W_name", "warn": "d7lz0W_warn", "itemBody": "d7lz0W_itemBody", "item": "d7lz0W_item", "itemModalities": "d7lz0W_itemModalities", "block": "d7lz0W_block", "root": "d7lz0W_root", "badge": "d7lz0W_badge", "input": "d7lz0W_input", "row": "d7lz0W_row", "list": "d7lz0W_list" };
565
+ var section_default = { "input": "d7lz0W_input", "itemMain": "d7lz0W_itemMain", "badge": "d7lz0W_badge", "select": "d7lz0W_select", "itemBody": "d7lz0W_itemBody", "ok": "d7lz0W_ok", "list": "d7lz0W_list", "itemMeta": "d7lz0W_itemMeta", "name": "d7lz0W_name", "mono": "d7lz0W_mono", "block": "d7lz0W_block", "button": "d7lz0W_button", "hint": "d7lz0W_hint", "number": "d7lz0W_number", "item": "d7lz0W_item", "row": "d7lz0W_row", "title": "d7lz0W_title", "root": "d7lz0W_root", "warn": "d7lz0W_warn", "itemModalities": "d7lz0W_itemModalities" };
566
566
 
567
567
  // src/client/Section.tsx
568
568
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -1335,7 +1335,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
1335
1335
  style.textContent = ".mMNkkW_root{align-items:center;display:inline-flex;position:relative}.mMNkkW_trigger{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;white-space:nowrap;border-radius:999px;padding:.35rem .6rem;font-size:.8rem;line-height:1}.mMNkkW_trigger:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.mMNkkW_panel{z-index:20;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-overlay);width:18rem;color:var(--dsw-alias-label-primary);border-radius:.6rem;flex-direction:column;gap:.6rem;padding:.75rem .85rem;display:flex;position:absolute;bottom:calc(100% + .5rem);right:0;box-shadow:0 8px 24px #0000002e}.mMNkkW_window{flex-direction:column;gap:.25rem;display:flex}.mMNkkW_row{justify-content:space-between;gap:.5rem;font-size:.85rem;display:flex}.mMNkkW_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.75rem}.mMNkkW_progress{width:100%;height:.35rem;accent-color:var(--dsw-alias-brand-primary)}.mMNkkW_limited{color:var(--dsw-alias-state-warn-primary);font-size:.75rem}.mMNkkW_warning{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-label-primary);border-radius:.4rem;padding:.4rem .5rem;font-size:.75rem}.mMNkkW_retry{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;align-self:flex-start;padding:.25rem .5rem;font-size:.75rem}.mMNkkW_local{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:.2rem;padding-top:.5rem;display:flex}";
1336
1336
  document.head.appendChild(style);
1337
1337
  }
1338
- var pill_default = { "progress": "mMNkkW_progress", "root": "mMNkkW_root", "hint": "mMNkkW_hint", "trigger": "mMNkkW_trigger", "panel": "mMNkkW_panel", "window": "mMNkkW_window", "local": "mMNkkW_local", "retry": "mMNkkW_retry", "warning": "mMNkkW_warning", "limited": "mMNkkW_limited", "row": "mMNkkW_row" };
1338
+ var pill_default = { "hint": "mMNkkW_hint", "warning": "mMNkkW_warning", "retry": "mMNkkW_retry", "root": "mMNkkW_root", "local": "mMNkkW_local", "window": "mMNkkW_window", "progress": "mMNkkW_progress", "panel": "mMNkkW_panel", "row": "mMNkkW_row", "limited": "mMNkkW_limited", "trigger": "mMNkkW_trigger" };
1339
1339
 
1340
1340
  // src/client/UsagePill.tsx
1341
1341
  var import_jsx_runtime2 = require("react/jsx-runtime");
package/lib/index.js CHANGED
@@ -1664,6 +1664,28 @@ var OpencodeGoAdapter = class extends LlmAdapter {
1664
1664
  }
1665
1665
  };
1666
1666
 
1667
+ // src/circular-warning.ts
1668
+ var PREFIX = "Accessing non-existent property";
1669
+ var INSTALLED = /* @__PURE__ */ Symbol.for("dshopencodego/circular-warning-filter");
1670
+ function warningText(warning) {
1671
+ if (typeof warning === "string") return warning;
1672
+ const message = warning?.message;
1673
+ return String(message ?? warning);
1674
+ }
1675
+ function dropsCircularWarning(warning) {
1676
+ return warningText(warning).startsWith(PREFIX);
1677
+ }
1678
+ function filterCircularWarnings(target = process) {
1679
+ const host = target;
1680
+ if (host[INSTALLED] === true) return;
1681
+ host[INSTALLED] = true;
1682
+ const original = target.emitWarning.bind(target);
1683
+ target.emitWarning = ((warning, ...rest) => {
1684
+ if (dropsCircularWarning(warning)) return;
1685
+ original(warning, ...rest);
1686
+ });
1687
+ }
1688
+
1667
1689
  // src/catalog/contract.ts
1668
1690
  function parseGoQuota(value) {
1669
1691
  if (value === null || typeof value !== "object") throw new Error("invalid go quota");
@@ -2098,7 +2120,7 @@ function createUpdateChecker(deps) {
2098
2120
  }
2099
2121
 
2100
2122
  // src/update/version.ts
2101
- var PLUGIN_VERSION = true ? "0.1.36" : "0.0.0-dev";
2123
+ var PLUGIN_VERSION = true ? "0.1.37" : "0.0.0-dev";
2102
2124
 
2103
2125
  // src/update/service.ts
2104
2126
  import { TypertRemoteService as TypertRemoteService2 } from "@deepseek-ai/dsh-typert-protocol";
@@ -2286,6 +2308,7 @@ function isLiveConfig(raw) {
2286
2308
  return typeof raw === "object" && raw !== null && typeof raw.enabled === "object" && typeof raw.enabled?.get === "function";
2287
2309
  }
2288
2310
  function apply(ctx, raw) {
2311
+ filterCircularWarnings();
2289
2312
  const live = isLiveConfig(raw) ? raw : void 0;
2290
2313
  const constant = live === void 0 ? PlainConfig(raw ?? {}) : void 0;
2291
2314
  const current = () => live === void 0 ? constant : readConfig(live);
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Silence Node's circular-dependency property warning.
3
+ *
4
+ * `@earendil-works/pi-ai` named-imports `partial-json`:
5
+ *
6
+ * ```js
7
+ * import { parse as partialParse } from "partial-json";
8
+ * ```
9
+ *
10
+ * Resolving a named import from CommonJS makes Node enumerate the module's
11
+ * exports, and `partial-json`'s `index.js` and `options.js` require each
12
+ * other — so the enumeration reads `Allow` while its own module is still
13
+ * initialising. Node prints, once per read:
14
+ *
15
+ * Accessing non-existent property 'Allow' of module exports inside circular dependency
16
+ *
17
+ * The read is harmless: `parse` resolves correctly, the value is present once
18
+ * the pair settles, and every request this plugin makes was verified against
19
+ * that behaviour. What makes it worth filtering is the volume — a plugin
20
+ * reload re-runs the graph, and each enumeration prints again, so an update
21
+ * leaves a flood of identical lines in the host's log. A wall of warnings
22
+ * nobody can act on is how a real one gets missed.
23
+ *
24
+ * Why a message filter rather than a supported switch: Node emits this one
25
+ * with a bare string and **no type**, so `--disable-warning` (which matches a
26
+ * code or type) cannot select it. Matching the message prefix is the narrowest
27
+ * filter available, and it drops exactly one message — everything else reaches
28
+ * the default handler untouched.
29
+ *
30
+ * @module @dan-ai-studio/dshopencodego/circular-warning
31
+ */
32
+ /**
33
+ * Whether this warning is the circular-dependency one.
34
+ *
35
+ * Exported so the rule can be tested directly, without installing anything.
36
+ * @param warning - the first argument Node passes to `process.emitWarning`.
37
+ * @returns true when the warning is Node's circular-dependency notice.
38
+ */
39
+ export declare function dropsCircularWarning(warning: unknown): boolean;
40
+ /**
41
+ * Install the filter. Safe to call on every mount; the first call wins.
42
+ *
43
+ * Called from `apply` rather than from module scope because ES module imports
44
+ * are hoisted — by the time any statement of this bundle runs, `pi-ai` has
45
+ * already been evaluated, so the first enumeration cannot be intercepted. Every
46
+ * later one can, and a reload is exactly what produces the flood.
47
+ * @param target - the process-like object to patch; defaults to the real one.
48
+ */
49
+ export declare function filterCircularWarnings(target?: Pick<typeof process, 'emitWarning'>): void;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Silence Node's circular-dependency property warning.
3
+ *
4
+ * `@earendil-works/pi-ai` named-imports `partial-json`:
5
+ *
6
+ * ```js
7
+ * import { parse as partialParse } from "partial-json";
8
+ * ```
9
+ *
10
+ * Resolving a named import from CommonJS makes Node enumerate the module's
11
+ * exports, and `partial-json`'s `index.js` and `options.js` require each
12
+ * other — so the enumeration reads `Allow` while its own module is still
13
+ * initialising. Node prints, once per read:
14
+ *
15
+ * Accessing non-existent property 'Allow' of module exports inside circular dependency
16
+ *
17
+ * The read is harmless: `parse` resolves correctly, the value is present once
18
+ * the pair settles, and every request this plugin makes was verified against
19
+ * that behaviour. What makes it worth filtering is the volume — a plugin
20
+ * reload re-runs the graph, and each enumeration prints again, so an update
21
+ * leaves a flood of identical lines in the host's log. A wall of warnings
22
+ * nobody can act on is how a real one gets missed.
23
+ *
24
+ * Why a message filter rather than a supported switch: Node emits this one
25
+ * with a bare string and **no type**, so `--disable-warning` (which matches a
26
+ * code or type) cannot select it. Matching the message prefix is the narrowest
27
+ * filter available, and it drops exactly one message — everything else reaches
28
+ * the default handler untouched.
29
+ *
30
+ * @module @dan-ai-studio/dshopencodego/circular-warning
31
+ */
32
+ /** The invariable opening of Node's message; the property name varies. */
33
+ const PREFIX = 'Accessing non-existent property';
34
+ /**
35
+ * Marks the process as filtered.
36
+ *
37
+ * A `Symbol.for` key so it survives a plugin reload: the host may evaluate
38
+ * this bundle again, and the filter must be installed once for the process
39
+ * rather than once per evaluation.
40
+ */
41
+ const INSTALLED = Symbol.for('dshopencodego/circular-warning-filter');
42
+ /** The text of a warning Node may pass as a string or as an `Error`. */
43
+ function warningText(warning) {
44
+ if (typeof warning === 'string')
45
+ return warning;
46
+ const message = warning?.message;
47
+ return String(message ?? warning);
48
+ }
49
+ /**
50
+ * Whether this warning is the circular-dependency one.
51
+ *
52
+ * Exported so the rule can be tested directly, without installing anything.
53
+ * @param warning - the first argument Node passes to `process.emitWarning`.
54
+ * @returns true when the warning is Node's circular-dependency notice.
55
+ */
56
+ export function dropsCircularWarning(warning) {
57
+ return warningText(warning).startsWith(PREFIX);
58
+ }
59
+ /**
60
+ * Install the filter. Safe to call on every mount; the first call wins.
61
+ *
62
+ * Called from `apply` rather than from module scope because ES module imports
63
+ * are hoisted — by the time any statement of this bundle runs, `pi-ai` has
64
+ * already been evaluated, so the first enumeration cannot be intercepted. Every
65
+ * later one can, and a reload is exactly what produces the flood.
66
+ * @param target - the process-like object to patch; defaults to the real one.
67
+ */
68
+ export function filterCircularWarnings(target = process) {
69
+ const host = target;
70
+ if (host[INSTALLED] === true)
71
+ return;
72
+ host[INSTALLED] = true;
73
+ const original = target.emitWarning.bind(target);
74
+ target.emitWarning = ((warning, ...rest) => {
75
+ if (dropsCircularWarning(warning))
76
+ return;
77
+ original(warning, ...rest);
78
+ });
79
+ }
@@ -34,6 +34,7 @@ import { LlmError } from '@deepseek-ai/dsh-llm';
34
34
  import { OpencodeGoAdapter } from "./adapter.js";
35
35
  import { DISPLAY_NAME, PROVIDER_ID, discoverCatalogModels } from "./catalog/index.js";
36
36
  import { assertBaseURL, PlainConfig, readConfig } from "./config.js";
37
+ import { filterCircularWarnings } from "./circular-warning.js";
37
38
  import { registerRemotes } from "./remotes.js";
38
39
  import { OpencodeGoCatalogService } from "./catalog/service.js";
39
40
  import { OpencodeGoUpdateService } from "./update/index.js";
@@ -60,6 +61,10 @@ function isLiveConfig(raw) {
60
61
  * @param raw - the loader's live config, or a plain object in tests.
61
62
  */
62
63
  export function apply(ctx, raw) {
64
+ // First statement on purpose: this is as early as a filter can be installed,
65
+ // since ES imports are hoisted and `pi-ai` is evaluated before any of this
66
+ // runs. See the module for why the warning is safe to drop.
67
+ filterCircularWarnings();
63
68
  const live = isLiveConfig(raw) ? raw : undefined;
64
69
  const constant = live === undefined ? PlainConfig((raw ?? {})) : undefined;
65
70
  const current = () => (live === undefined ? constant : readConfig(live));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dan-ai-studio/dshopencodego",
3
- "version": "0.1.36",
3
+ "version": "0.1.37",
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",