dsh-opencode-go 0.1.8 → 0.1.10

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
@@ -16,7 +16,7 @@ The plugin automatically adds the session headers required by OpenCode Go, reads
16
16
 
17
17
  ## Installation and usage
18
18
 
19
- Supported DSH versions: `0.1.5-rc.1`, `0.1.5-rc.2`, `0.1.6-alpha.1`, `0.1.6-alpha.2`, and `0.1.7-alpha.1`.
19
+ Supported DSH versions: `0.1.5-rc.1`, `0.1.5-rc.2`, `0.1.6-alpha.1`, `0.1.6-alpha.2`, `0.1.7-alpha.1`, and `0.1.7-alpha.2`.
20
20
 
21
21
  ### Install from DSH (recommended)
22
22
 
@@ -33,7 +33,7 @@ If your DSH version does not have an **Add plugin** entry, use the command-line
33
33
  ### Command-line installation (alternative)
34
34
 
35
35
  ```sh
36
- dsh plugin --profile web add dsh-opencode-go@0.1.8
36
+ dsh plugin --profile web add dsh-opencode-go@0.1.10
37
37
  ```
38
38
 
39
39
  Start or restart `dsh web`, then:
@@ -47,7 +47,7 @@ Start or restart `dsh web`, then:
47
47
  Install the plugin into the Headless profile:
48
48
 
49
49
  ```sh
50
- dsh plugin --profile headless add dsh-opencode-go@0.1.8
50
+ dsh plugin --profile headless add dsh-opencode-go@0.1.10
51
51
  ```
52
52
 
53
53
  Save the following as `headless.patch.yml` to select a default model:
@@ -74,7 +74,7 @@ To build from source and install a local package:
74
74
  ```sh
75
75
  npm ci --legacy-peer-deps
76
76
  npm pack
77
- dsh plugin --profile web add ./dsh-opencode-go-0.1.8.tgz
77
+ dsh plugin --profile web add ./dsh-opencode-go-0.1.10.tgz
78
78
  ```
79
79
 
80
80
  The development dependencies include real test packages from multiple DSH generations, so installation requires `--legacy-peer-deps`. For Headless, replace `web` with `headless`.
@@ -109,6 +109,8 @@ A gateway model ID with no usable protocol or capability configuration is shown
109
109
 
110
110
  A reasoning-capable model without adjustable reasoning levels (for example, `union-alpha`) remains selectable and usable; it simply has no reasoning-strength control.
111
111
 
112
+ A model that does offer adjustable levels also declares a default effort (`high` when the model offers it, otherwise the highest level it offers) whenever its transport would answer an unset effort with an explicit disable (`deepseek`, `zai`, `qwen`, `qwen-chat-template`). DSH uses that default when no level has been chosen, so leaving the control unset still sends a reasoning level instead of turning thinking off. Transports that leave the choice to the provider declare no default and are unchanged, and an explicitly chosen level always wins.
113
+
112
114
  If the online configuration is temporarily unavailable, the plugin prefers a configuration fetched successfully earlier in the process and falls back to pi-ai's built-in metadata. If the gateway catalog is unavailable, existing requests can use the last catalog; a Settings refresh reports the failure instead of presenting stale data as current. `refreshMinutes` controls the cache lifetime for ongoing model requests, but does not prevent an explicit model-list read from fetching fresh data.
113
115
 
114
116
  ## Uninstall
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
  ## 安装与使用
18
18
 
19
19
  兼容清单:
20
- `0.1.5-rc.1`、`0.1.5-rc.2`、`0.1.6-alpha.1`、`0.1.6-alpha.2` 和 `0.1.7-alpha.1`
20
+ `0.1.5-rc.1`、`0.1.5-rc.2`、`0.1.6-alpha.1`、`0.1.6-alpha.2`、`0.1.7-alpha.1` 和 `0.1.7-alpha.2`
21
21
 
22
22
  ### 在 DSH 中安装(推荐)
23
23
 
@@ -34,7 +34,7 @@
34
34
  ### 命令行安装(备选)
35
35
 
36
36
  ```sh
37
- dsh plugin --profile web add dsh-opencode-go@0.1.8
37
+ dsh plugin --profile web add dsh-opencode-go@0.1.10
38
38
  ```
39
39
 
40
40
  安装后启动或重启 `dsh web`,然后:
@@ -48,7 +48,7 @@ dsh plugin --profile web add dsh-opencode-go@0.1.8
48
48
  安装到 Headless profile:
49
49
 
50
50
  ```sh
51
- dsh plugin --profile headless add dsh-opencode-go@0.1.8
51
+ dsh plugin --profile headless add dsh-opencode-go@0.1.10
52
52
  ```
53
53
 
54
54
  将以下内容保存为 `headless.patch.yml`,选择默认模型:
@@ -75,7 +75,7 @@ dsh --profile headless --patch ./headless.patch.yml "你好"
75
75
  ```sh
76
76
  npm ci --legacy-peer-deps
77
77
  npm pack
78
- dsh plugin --profile web add ./dsh-opencode-go-0.1.8.tgz
78
+ dsh plugin --profile web add ./dsh-opencode-go-0.1.10.tgz
79
79
  ```
80
80
 
81
81
  开发依赖包含多代 DSH 的真实测试包,安装时需要 `--legacy-peer-deps`。Headless 用户将 `web` 换成 `headless`。
@@ -110,6 +110,8 @@ dsh plugin --profile web update dsh-opencode-go --latest
110
110
 
111
111
  模型具有推理能力但没有可调节的推理档位时(如 `union-alpha`),仍可正常选择和使用,只是不显示推理强度选项。
112
112
 
113
+ 提供可调节档位的模型,如果其传输协议在未选择档位时会显式关闭思考(`deepseek`、`zai`、`qwen`、`qwen-chat-template`),还会声明一个默认档位(模型支持 `high` 时用 `high`,否则用它提供的最高档位)。用户未选择档位时 DSH 使用该默认值,因此留空也会带上推理档位,而不是关闭思考。由服务商自行决定的协议不声明默认值,行为不变;显式选择的档位始终优先。
114
+
113
115
  在线配置暂时不可达时,优先复用本次运行中成功获取的配置,以 pi-ai 内置配置作为备用。网关目录不可达时,已有请求可以使用上次目录;设置页刷新会显示失败,避免把旧目录误认为最新结果。`refreshMinutes` 只控制已有模型请求的缓存时长,不阻止主动读取列表获取新模型。
114
116
 
115
117
  ## 卸载
@@ -1,5 +1,39 @@
1
1
  # Verification
2
2
 
3
+ ## Default reasoning effort (plugin 0.1.10, 2026-09-23)
4
+
5
+ PR #6 declares a default effort for the pi-ai transports that explicitly disable thinking when the effort is unset: `deepseek`, `zai`, `qwen`, and `qwen-chat-template`. Models offering `high` default to it; otherwise the highest supported non-`off` effort is selected. Explicit choices, including `off`, still take precedence. Other transports and models without adjustable efforts retain their existing behavior.
6
+
7
+ Review found that the original fallback selected the first non-`off` effort from pi-ai's ascending list. End-to-end regressions failed with `low` in the outgoing request for models offering `low/medium` or `low/max`, then passed after selecting the last supported effort. The same cases cover `low` alone and the preference for `high` over `max` when both are offered.
8
+
9
+ Host/Client type checks, the build, and all **233 tests in 18 files** pass on macOS / Node.js 24.14.1 using the existing installed dependencies. Permanent compatibility coverage adds 42 local HTTP requests through the built plugin and all six supported DSH runtimes, verifying default effort resolution, explicit `low` and `off`, Qwen's thinking switch, provider-decides models, and reasoning/text stream conversion. Published UI primitives still emit missing-source-map warnings; all assertions pass. Completion requests use local fixtures and test credentials, with no paid model calls or manual Web/Desktop verification.
10
+
11
+ This release also includes PR #5's bounded compressed-response recovery described below, which was merged after the 0.1.9 release.
12
+
13
+ ## Bounded model discovery responses (2026-09-23)
14
+
15
+ Model discovery accepts ordinary JSON and Brotli, gzip, or deflate JSON whose `Content-Encoding` header is missing. Correctly labeled responses continue through Fetch's automatic decoding. The shared reader counts actual streamed bytes and cancels oversized bodies; fallback decoders run asynchronously with `maxOutputLength`. Both delivered bytes and fallback output are limited to 1 MiB for the gateway listing and 16 MiB for models.dev metadata. These are payload limits, not total process-memory or CPU-time budgets. Failed recovery preserves the original JSON error and each decoder's cause.
16
+
17
+ Host/Client type checks and the build passed, followed by all **222 tests in 18 files**, on macOS / Node.js 24.14.1 using the existing installed dependencies. Ten new resource-limit and diagnostic tests failed against the original parser before passing with the bounded reader. Real local HTTP tests cover both discovery sources, correctly labeled and unlabeled compression, corruption, cached fallback, and each source's limit exceeded by exactly one byte. The upstream UI primitives packages still emit missing-source-map warnings; all assertions pass.
18
+
19
+ The missing-header failure is reproduced with controlled HTTP fixtures. A read-only direct check of the two public endpoints returned HTTP 200 with correct `Content-Encoding: br` headers and valid JSON after Node's automatic decoding; models.dev was approximately 4.6 MiB decoded. This does not establish why the original reporter's proxy environment failed: response headers, a raw response sample, and the relevant proxy/runtime configuration are still needed. Curl's automatic decoding also relies on `Content-Encoding`, so successful curl access alone does not establish the reported root cause. Usage fetching is outside this change.
20
+
21
+ ## DSH 0.1.7-alpha.2 compatibility (plugin 0.1.9, 2026-09-23)
22
+
23
+ The package now declares DSH `0.1.7-alpha.2` and Cordis `4.0.4` support while retaining the five previously supported hosts. Before the change, the SemVer regression rejected the new host in `engines.dsh`; the DSH and Cordis peer ranges also excluded its published versions. `engines.dsh` is declarative in the current upstream installer, so it must not be confused with an enforced loader check. The peer ranges affect dependency resolution. Unverified future prereleases remain outside the declared range.
24
+
25
+ Review of the [upstream release diff](https://github.com/deepseek-ai/deepseek-harness/compare/dsh-v0.1.7-alpha.1...dsh-v0.1.7-alpha.2) and tests with the published packages found no required change to the adapter or settings implementation. The new `tests/hosts/v017-alpha2` workspace pins the DSH services, Cordis `4.0.4`, Loader `1.0.5`, Include `1.0.9`, and Schemastery `3.18.4` separately from the older host fixtures.
26
+
27
+ Validation on macOS / Node.js 24.14.1:
28
+
29
+ - Host/client type checks, build, and **191 tests in 17 files** pass. The six-host matrix covers artifact loading, Loader activation, catalog and usage RPCs on modern hosts, streaming, capacities, real image resizing, offload limits, and immutable history. Modern hosts also verify mixed tool-result text and image delivery.
30
+ - Both `0.1.7` prereleases pass the real profile settings fixture, including live updates without remounting, visibility changes, capacity reset, route toggling, and validation.
31
+ - The distributed browser factory renders against the legacy UI packages and both `0.1.7` prereleases' actual store and primitives packages. Model loading, settings registration, CSS composition, and cleanup pass. Published UI primitives still emit missing-source-map warnings.
32
+ - The tarball installs into a separate official `@deepseek-ai/dsh@0.1.7-alpha.2` npm consumer without `--force` or `--legacy-peer-deps`. Its resolved Cordis, LLM, settings, and attachment packages match the target versions. `verify:installed` passes package resolution, catalog, streaming, session headers, authorization, and unload checks.
33
+ - `verify:headless` passes through the official launcher with the installed bundle selected in an isolated profile. The first `dsh plugin add` stopped on pnpm's build-policy decisions for `@google/genai` and `protobufjs`. Both were explicitly disabled in that temporary profile's `allowBuilds`, then installation was retried. Because the interrupted operation had already written the dependency, the retry retained its disabled state; adding `dsh-opencode-go` to that profile's existing `dsh.profile.bundles` enabled it before the successful smoke test.
34
+
35
+ Development dependencies are reproducible with `npm ci --legacy-peer-deps --ignore-scripts`. Completion requests use a loopback gateway and fake credentials. This verification does not cover the full Web/Desktop UI, other operating systems, or live paid model calls.
36
+
3
37
  ## Release 0.1.8 (2026-09-22)
4
38
 
5
39
  Host/client type checks, the build, and all **181 tests in 16 files** pass on macOS / Node.js 24.14.1. Coverage includes the five supported host versions, deprecated-model visibility, model remote injection, and CSS composition in the distributed client. The upstream UI primitives packages still emit missing-source-map warnings; all assertions pass. This release also synchronizes the English README with the simplified Chinese guide and updates installation examples to 0.1.8.
package/lib/client.js CHANGED
@@ -103,7 +103,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")
103
103
  style.textContent = '.BtKYva_page{flex-direction:column;min-width:0;height:100%;min-height:0;display:flex;container-type:size}.BtKYva_pageBody{scrollbar-gutter:stable;flex:1;min-height:0;padding-right:4px;overflow-y:auto}.BtKYva_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.BtKYva_field+.BtKYva_field{border-top:.5px solid var(--dsw-alias-border-l2)}.BtKYva_head{align-items:center;gap:8px;display:flex}.BtKYva_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.BtKYva_badges{align-items:center;gap:8px;display:inline-flex}.BtKYva_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.BtKYva_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.BtKYva_reset:disabled{cursor:default}.BtKYva_reset:focus-visible,.BtKYva_disclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.BtKYva_input{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.BtKYva_input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px;border-color:var(--dsw-alias-brand-primary)}.BtKYva_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.BtKYva_inputInvalid{border-color:var(--dsw-alias-label-error);}.BtKYva_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.BtKYva_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.BtKYva_intro{color:var(--dsw-alias-label-secondary);margin:0 0 8px;font-size:13px;line-height:1.5}.BtKYva_disclosure{font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;margin:0;padding:0;display:flex}.BtKYva_disclosure:hover .BtKYva_label{color:var(--dsw-alias-brand-primary)}.BtKYva_chevron,.BtKYva_chevronOpen{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none}.BtKYva_chevron{transform:rotate(-90deg)}.BtKYva_advanced{flex-direction:column;gap:4px;padding:4px 0 0 22px;display:flex}.BtKYva_advanced .BtKYva_field+.BtKYva_field{border-top:none}.BtKYva_chips{flex-wrap:wrap;gap:6px;display:flex}.BtKYva_limitsEditor{flex-direction:column;gap:10px;padding-top:4px;display:flex}.BtKYva_limitsToolbar{grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:6px 10px;display:grid}.BtKYva_limitsFilterLabel{color:var(--dsw-alias-label-secondary);grid-column:1/-1;font-size:12px;font-weight:500;line-height:1.5}.BtKYva_limitsSummary{color:var(--dsw-alias-label-tertiary);white-space:nowrap;padding-bottom:8px;font-size:12px;line-height:1.5}.BtKYva_limitsId,.BtKYva_limitsModelId{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}.BtKYva_limitsId{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.4}.BtKYva_limitsModelId{color:var(--dsw-alias-label-tertiary);margin-top:2px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.4}.BtKYva_visuallyHidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@media (width<=560px){.BtKYva_limitsToolbar{grid-template-columns:1fr}.BtKYva_limitsSummary{padding-bottom:0}}.BtKYva_actions{border-top:.5px solid var(--dsw-alias-border-l2);flex-wrap:wrap;flex:none;align-items:center;gap:8px;padding:12px 0;display:flex}.BtKYva_failedNote{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.BtKYva_pageTop{align-items:flex-start;gap:16px;display:flex}.BtKYva_pageTop .BtKYva_intro{flex:1}.BtKYva_advancedTrigger{flex-shrink:0;margin-left:auto;}.BtKYva_advancedTrigger .BtKYva_label{color:var(--dsw-alias-label-tertiary);font-size:12px}.BtKYva_filters{flex-wrap:wrap;gap:6px;display:flex}.BtKYva_filter{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;padding:6px 9px;font-size:12px}.BtKYva_filter[aria-pressed=true]{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3)}.BtKYva_filter span{color:var(--dsw-alias-label-tertiary);margin-left:4px}.BtKYva_modelLayout{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;grid-template-columns:minmax(0,43fr) minmax(0,57fr);height:clamp(240px,100cqh - 460px,480px);display:grid;overflow:hidden}.BtKYva_modelList{border-right:.5px solid var(--dsw-alias-border-l2);min-height:0;padding:6px;overflow-y:auto}.BtKYva_modelChoice{text-align:left;width:100%;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:6px;padding:12px 9px;display:block}.BtKYva_modelChoice[aria-pressed=true],.BtKYva_modelChoice:hover{background:var(--dsw-alias-bg-layer-3)}.BtKYva_modelName{overflow-wrap:anywhere;flex-wrap:wrap;align-items:center;gap:5px;font-size:13px;display:flex}.BtKYva_modelDetails{flex-direction:column;align-items:stretch;gap:10px;min-width:0;padding:18px;display:flex;overflow-y:auto}.BtKYva_modelDetails h3{overflow-wrap:anywhere;margin:0;font-size:16px}.BtKYva_modelHeading{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.BtKYva_modelDetails .BtKYva_field{border:0;padding:8px 0}.BtKYva_modelDetails .BtKYva_input{box-sizing:border-box;width:100%;min-width:0}.BtKYva_modelDetails .BtKYva_reset{align-self:flex-start}.BtKYva_newBadge{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);border:.5px solid var(--dsw-alias-border-l4);border-radius:4px;padding:2px 4px;font-size:9px}.BtKYva_releaseDate{color:var(--dsw-alias-label-tertiary);margin-top:4px;font-size:10px;display:block}.BtKYva_modelChoice:focus-visible,.BtKYva_filter:focus-visible,.BtKYva_advancedTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}@container (width<=440px){.BtKYva_pageTop{flex-wrap:wrap}.BtKYva_modelLayout{grid-template-columns:minmax(0,1fr);height:auto}.BtKYva_modelList{border-right:0;border-bottom:.5px solid var(--dsw-alias-border-l2);max-height:240px}.BtKYva_modelDetails{max-height:460px}}.BtKYva_keySection{border-top:.5px solid var(--dsw-alias-border-l2);padding:12px 0}.BtKYva_keySection summary{cursor:pointer;list-style:none}.BtKYva_keySection summary:after{content:"\u2304";color:var(--dsw-alias-label-tertiary)}.BtKYva_keySection summary::-webkit-details-marker{display:none}.BtKYva_keySection>.BtKYva_input{box-sizing:border-box;width:100%;margin:10px 0 6px}.BtKYva_keySection summary:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}';
104
104
  document.head.appendChild(style);
105
105
  }
106
- var Section_default = { "modelName": "BtKYva_modelName", "modelDetails": "BtKYva_modelDetails", "advanced": "BtKYva_advanced", "limitsEditor": "BtKYva_limitsEditor", "head": "BtKYva_head", "failedNote": "BtKYva_failedNote", "hint": "BtKYva_hint", "actions": "BtKYva_actions", "limitsFilterLabel": "BtKYva_limitsFilterLabel", "limitsId": "BtKYva_limitsId", "limitsToolbar": "BtKYva_limitsToolbar", "modelChoice": "BtKYva_modelChoice", "disclosure": "BtKYva_disclosure", "chevron": "BtKYva_chevron", "chevronOpen": "BtKYva_chevronOpen", "input": "BtKYva_input", "modelHeading": "BtKYva_modelHeading", "filter": "BtKYva_filter", "inputInvalid": "BtKYva_inputInvalid BtKYva_input", "page": "BtKYva_page", "label": "BtKYva_label", "reset": "BtKYva_reset", "badges": "BtKYva_badges", "advancedTrigger": "BtKYva_advancedTrigger BtKYva_disclosure", "visuallyHidden": "BtKYva_visuallyHidden", "keySection": "BtKYva_keySection", "limitsSummary": "BtKYva_limitsSummary", "invalid": "BtKYva_invalid", "field": "BtKYva_field", "pageTop": "BtKYva_pageTop", "modelLayout": "BtKYva_modelLayout", "newBadge": "BtKYva_newBadge", "filters": "BtKYva_filters", "releaseDate": "BtKYva_releaseDate", "chips": "BtKYva_chips", "limitsModelId": "BtKYva_limitsModelId", "pageBody": "BtKYva_pageBody", "modelList": "BtKYva_modelList", "intro": "BtKYva_intro" };
106
+ var Section_default = { "pageTop": "BtKYva_pageTop", "invalid": "BtKYva_invalid", "limitsModelId": "BtKYva_limitsModelId", "limitsToolbar": "BtKYva_limitsToolbar", "modelList": "BtKYva_modelList", "field": "BtKYva_field", "inputInvalid": "BtKYva_inputInvalid BtKYva_input", "label": "BtKYva_label", "modelDetails": "BtKYva_modelDetails", "page": "BtKYva_page", "failedNote": "BtKYva_failedNote", "limitsEditor": "BtKYva_limitsEditor", "modelChoice": "BtKYva_modelChoice", "hint": "BtKYva_hint", "chips": "BtKYva_chips", "modelName": "BtKYva_modelName", "chevronOpen": "BtKYva_chevronOpen", "modelHeading": "BtKYva_modelHeading", "releaseDate": "BtKYva_releaseDate", "advancedTrigger": "BtKYva_advancedTrigger BtKYva_disclosure", "keySection": "BtKYva_keySection", "badges": "BtKYva_badges", "disclosure": "BtKYva_disclosure", "visuallyHidden": "BtKYva_visuallyHidden", "head": "BtKYva_head", "filter": "BtKYva_filter", "actions": "BtKYva_actions", "limitsId": "BtKYva_limitsId", "pageBody": "BtKYva_pageBody", "intro": "BtKYva_intro", "modelLayout": "BtKYva_modelLayout", "input": "BtKYva_input", "advanced": "BtKYva_advanced", "newBadge": "BtKYva_newBadge", "limitsFilterLabel": "BtKYva_limitsFilterLabel", "limitsSummary": "BtKYva_limitsSummary", "reset": "BtKYva_reset", "chevron": "BtKYva_chevron", "filters": "BtKYva_filters" };
107
107
 
108
108
  // src/client/ModelEditor.tsx
109
109
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -1331,7 +1331,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
1331
1331
  style.textContent = ".dmPm3q_root{min-width:0;display:inline-flex;position:relative}.dmPm3q_trigger{color:inherit;opacity:.75;font:inherit;cursor:pointer;white-space:nowrap;background:0 0;border:0;border-radius:6px;padding:4px 6px;font-size:12px}.dmPm3q_trigger:hover,.dmPm3q_trigger:focus-visible{opacity:1;background:color-mix(in srgb, currentColor 8%, transparent)}.dmPm3q_panel{z-index:100;border:1px solid color-mix(in srgb, currentColor 18%, transparent);width:280px;max-width:calc(100vw - 32px);color:var(--dsw-alias-label-primary,CanvasText);background:var(--dsw-specific-menu,Canvas);border-radius:12px;padding:16px;font-size:12px;position:absolute;bottom:calc(100% + 12px);right:0;box-shadow:0 8px 30px #0002}.dmPm3q_hint{opacity:.65;font-size:11px;line-height:1.6}.dmPm3q_window{margin-top:14px}.dmPm3q_row{justify-content:space-between;margin-bottom:5px;display:flex}.dmPm3q_window progress{accent-color:#39a878;width:100%;height:5px;margin-bottom:5px;display:block}.dmPm3q_window progress::-webkit-progress-bar{background:color-mix(in srgb, currentColor 15%, transparent);border-radius:4px}.dmPm3q_window progress::-webkit-progress-value{background:#39a878;border-radius:4px}.dmPm3q_window progress::-moz-progress-bar{background:#39a878;border-radius:4px}";
1332
1332
  document.head.appendChild(style);
1333
1333
  }
1334
- var UsagePill_default = { "window": "dmPm3q_window", "row": "dmPm3q_row", "panel": "dmPm3q_panel", "hint": "dmPm3q_hint", "root": "dmPm3q_root", "trigger": "dmPm3q_trigger" };
1334
+ var UsagePill_default = { "row": "dmPm3q_row", "trigger": "dmPm3q_trigger", "panel": "dmPm3q_panel", "root": "dmPm3q_root", "hint": "dmPm3q_hint", "window": "dmPm3q_window" };
1335
1335
 
1336
1336
  // src/client/UsagePill.tsx
1337
1337
  var import_jsx_runtime3 = require("react/jsx-runtime");
package/lib/index.js CHANGED
@@ -858,11 +858,65 @@ function readModelMetadata(body, baseURL, builtin) {
858
858
  return { models, errors, details };
859
859
  }
860
860
 
861
+ // src/json-response.ts
862
+ import { promisify } from "node:util";
863
+ import { brotliDecompress, gunzip, inflate } from "node:zlib";
864
+ var decoders = [
865
+ { name: "Brotli", decode: promisify(brotliDecompress) },
866
+ { name: "gzip", decode: promisify(gunzip) },
867
+ { name: "deflate", decode: promisify(inflate) }
868
+ ];
869
+ async function readBoundedBody(response, maxBytes) {
870
+ if (response.body === null) return Buffer.alloc(0);
871
+ const reader = response.body.getReader();
872
+ const chunks = [];
873
+ let size = 0;
874
+ try {
875
+ while (true) {
876
+ const { done, value } = await reader.read();
877
+ if (done) return Buffer.concat(chunks, size);
878
+ if (value.byteLength > maxBytes - size) {
879
+ const error = new RangeError(`Response body exceeds ${maxBytes} byte limit`);
880
+ await reader.cancel(error).catch(() => {
881
+ });
882
+ throw error;
883
+ }
884
+ size += value.byteLength;
885
+ chunks.push(value);
886
+ }
887
+ } finally {
888
+ reader.releaseLock();
889
+ }
890
+ }
891
+ async function readJsonResponse(response, maxBytes) {
892
+ const bytes = await readBoundedBody(response, maxBytes);
893
+ const parse = (data) => JSON.parse(new TextDecoder().decode(data));
894
+ const errors = [];
895
+ try {
896
+ return parse(bytes);
897
+ } catch (error) {
898
+ errors.push(error);
899
+ }
900
+ for (const { name: name2, decode } of decoders) {
901
+ try {
902
+ return parse(await decode(bytes, { maxOutputLength: maxBytes }));
903
+ } catch (error) {
904
+ if (error instanceof Error && "code" in error && error.code === "ERR_BUFFER_TOO_LARGE") {
905
+ throw new RangeError(`${name2} decoded response exceeds ${maxBytes} byte limit`, { cause: error });
906
+ }
907
+ errors.push(new Error(`${name2} response decoding or JSON parsing failed`, { cause: error }));
908
+ }
909
+ }
910
+ throw new AggregateError(errors, "Response is not valid JSON, including after Brotli, gzip, or deflate decoding");
911
+ }
912
+
861
913
  // src/catalog.ts
862
914
  var PROVIDER_ID = "opencode-go";
863
915
  var DISPLAY_NAME = "OpenCode Go";
864
916
  var DEFAULT_BASE_URL = "https://opencode.ai/zen/go/v1";
865
917
  var MODELS_FETCH_TIMEOUT_MS = 1e4;
918
+ var MODEL_LISTING_MAX_BYTES = 1024 * 1024;
919
+ var MODEL_METADATA_MAX_BYTES = 16 * 1024 * 1024;
866
920
  function builtinModels(baseURL) {
867
921
  return new Map(getBuiltinModels("opencode-go").map((model) => [model.id, {
868
922
  ...model,
@@ -894,7 +948,7 @@ async function fetchLiveModelIds(baseURL) {
894
948
  throw new LlmError5(`could not reach ${url}`, "DISCOVERY_FAILED", { cause: error });
895
949
  }
896
950
  if (!response.ok) throw new LlmError5(`${url} answered ${response.status}`, "DISCOVERY_FAILED");
897
- return readLiveModelIds(await response.json());
951
+ return readLiveModelIds(await readJsonResponse(response, MODEL_LISTING_MAX_BYTES));
898
952
  }
899
953
  function harnessApiKeyAuth() {
900
954
  return { apiKey: {
@@ -952,7 +1006,7 @@ var OpencodeGoCatalog = class {
952
1006
  });
953
1007
  if (response.status === 304 && this.metadata !== void 0) return this.metadata;
954
1008
  if (!response.ok) throw new Error(`models.dev answered ${response.status}`);
955
- const metadata = readModelMetadata(await response.json(), this.baseURL, builtin);
1009
+ const metadata = readModelMetadata(await readJsonResponse(response, MODEL_METADATA_MAX_BYTES), this.baseURL, builtin);
956
1010
  this.metadata = metadata;
957
1011
  this.metadataETag = response.headers.get("etag") ?? void 0;
958
1012
  return metadata;
@@ -1088,6 +1142,7 @@ function assertBaseURL(raw) {
1088
1142
  }
1089
1143
 
1090
1144
  // src/adapter.ts
1145
+ var DISABLES_THINKING_WHEN_UNSET = /* @__PURE__ */ new Set(["deepseek", "zai", "qwen", "qwen-chat-template"]);
1091
1146
  function withModelLimit(model, limits) {
1092
1147
  const limit = limits[model.id];
1093
1148
  if (limit == null) return model;
@@ -1165,11 +1220,14 @@ var OpencodeGoAdapter = class extends LlmAdapter {
1165
1220
  const reasoning = {};
1166
1221
  const levels = model.reasoning ? getSupportedThinkingLevels(model) : [];
1167
1222
  if (levels.length > 0) {
1223
+ const format = model.compat?.thinkingFormat;
1224
+ const fallback = format !== void 0 && DISABLES_THINKING_WHEN_UNSET.has(format) ? levels.includes("high") ? "high" : levels.findLast((level) => level !== "off") : void 0;
1168
1225
  reasoning.reasoning = {
1169
1226
  efforts: levels.map((level) => ({
1170
1227
  id: ReasoningEffortId(level),
1171
1228
  name: `${level.charAt(0).toUpperCase()}${level.slice(1)}`
1172
- }))
1229
+ })),
1230
+ ...fallback === void 0 ? {} : { defaultEffort: ReasoningEffortId(fallback) }
1173
1231
  };
1174
1232
  }
1175
1233
  return {
@@ -0,0 +1,2 @@
1
+ /** The limit applies both to bytes delivered by fetch and to any fallback decoder's output. */
2
+ export declare function readJsonResponse(response: Response, maxBytes: number): Promise<unknown>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-opencode-go",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "OpenCode Go model provider and settings UI for DeepSeek Harness",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "engines": {
16
16
  "node": "^22.19.0 || >=24.0.0",
17
- "dsh": ">=0.1.5-rc.1 <0.1.6-0 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1"
17
+ "dsh": ">=0.1.5-rc.1 <0.1.6-0 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2"
18
18
  },
19
19
  "main": "./lib/index.js",
20
20
  "types": "./lib/types/index.d.ts",
@@ -60,26 +60,26 @@
60
60
  "verify:headless": "node scripts/headless-smoke.mjs"
61
61
  },
62
62
  "peerDependencies": {
63
- "@deepseek-ai/cordis": "4.0.2 || 4.0.3",
64
- "@deepseek-ai/dsh-api-gateway": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
65
- "@deepseek-ai/dsh-api-remotes": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
66
- "@deepseek-ai/dsh-api-settings-controller": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
67
- "@deepseek-ai/dsh-attachment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
68
- "@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
69
- "@deepseek-ai/dsh-client-store": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
70
- "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
71
- "@deepseek-ai/dsh-client-ui-model-selection": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
72
- "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
73
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
74
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
75
- "@deepseek-ai/dsh-credentials": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
76
- "@deepseek-ai/dsh-fs": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
77
- "@deepseek-ai/dsh-launch-environment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
78
- "@deepseek-ai/dsh-llm": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
79
- "@deepseek-ai/dsh-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
80
- "@deepseek-ai/dsh-timeout": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
81
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
82
- "@deepseek-ai/dsh-typert-registry": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1"
63
+ "@deepseek-ai/cordis": "4.0.2 || 4.0.3 || 4.0.4",
64
+ "@deepseek-ai/dsh-api-gateway": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
65
+ "@deepseek-ai/dsh-api-remotes": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
66
+ "@deepseek-ai/dsh-api-settings-controller": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
67
+ "@deepseek-ai/dsh-attachment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
68
+ "@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
69
+ "@deepseek-ai/dsh-client-store": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
70
+ "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
71
+ "@deepseek-ai/dsh-client-ui-model-selection": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
72
+ "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
73
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
74
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
75
+ "@deepseek-ai/dsh-credentials": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
76
+ "@deepseek-ai/dsh-fs": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
77
+ "@deepseek-ai/dsh-launch-environment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
78
+ "@deepseek-ai/dsh-llm": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
79
+ "@deepseek-ai/dsh-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
80
+ "@deepseek-ai/dsh-timeout": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
81
+ "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
82
+ "@deepseek-ai/dsh-typert-registry": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2"
83
83
  },
84
84
  "dependencies": {
85
85
  "@deepseek-ai/dsh-brand": "0.1.6-alpha.1",
@@ -122,6 +122,7 @@
122
122
  "@types/node": "^22.20.0",
123
123
  "@types/react": "~18.3.1",
124
124
  "@types/react-dom": "~18.3.0",
125
+ "@types/semver": "7.8.0",
125
126
  "anser": "^2.3.5",
126
127
  "clsx": "^2.0.0",
127
128
  "diff": "^9.0.0",
@@ -153,6 +154,7 @@
153
154
  "micromark-util-types": "^2.0.2",
154
155
  "react": "^18.2.0",
155
156
  "react-dom": "^18.2.0",
157
+ "semver": "7.8.5",
156
158
  "shiki": "^4.3.1",
157
159
  "typescript": "6.0.3",
158
160
  "vitest": "^4.1.8",