dsh-opencode-go 0.1.4 → 0.1.6
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.md +29 -0
- package/docs/verification.md +66 -1
- package/lib/client.js +2 -2
- package/lib/index.js +88 -54
- package/lib/types/conversion/context.d.ts +3 -2
- package/lib/types/conversion/image-offload.d.ts +12 -0
- package/package.json +33 -21
package/README.md
CHANGED
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
|
|
10
10
|
## 安装与使用
|
|
11
11
|
|
|
12
|
+
插件 `0.1.6` 兼容 DSH `0.1.5-rc.1`、`0.1.5-rc.2`、`0.1.6-alpha.1` 和 `0.1.6-alpha.2`,并通过这四个版本的真实图片和普通代码请求验证。使用 DSH `0.1.5` 的用户无需升级宿主。
|
|
13
|
+
|
|
14
|
+
插件 `0.1.6` 修复了 `0.1.5` 在旧版 DSH 上图片请求缺少 `maxPixels` 的问题([Issue #2](https://github.com/Duskriver/dsh-opencode-go/issues/2)),同时保留新版宿主要求的图片目标宽高。
|
|
15
|
+
|
|
16
|
+
npm 包通过 `engines.dsh` 明确声明宿主版本要求,并保留 DSH 组件的 peerDependencies。dshmarket 中本插件的安装来源也是该 npm 包,市场会将其安装到选定的 DSH profile。
|
|
17
|
+
|
|
12
18
|
### Web
|
|
13
19
|
|
|
14
20
|
```sh
|
|
@@ -78,6 +84,29 @@ Web 用户可直接在 **设置 → OpenCode Go** 中修改配置。启用开关
|
|
|
78
84
|
|
|
79
85
|
## 常见问题
|
|
80
86
|
|
|
87
|
+
### DSH 0.1.5 安装插件后无法启动
|
|
88
|
+
|
|
89
|
+
插件 `0.1.0`–`0.1.4` 使用了 DSH `0.1.6` 新增的图片接口,在旧版 DSH 上可能出现 `IMAGE_OFFLOAD_REQUIRED_CODE` 导出不存在的启动错误。升级插件到 `0.1.5` 或更新版本后重启即可:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
dsh plugin --profile web add dsh-opencode-go@0.1.6
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Headless 用户将 `web` 换成 `headless`。修复保留了两版宿主的图片处理方式:DSH `0.1.5` 在请求超过图片预算时将最旧图片转成占位文本,DSH `0.1.6` 继续由宿主记录并处理图片卸载。
|
|
96
|
+
|
|
97
|
+
### 新版本是否必须等待一天才能安装
|
|
98
|
+
|
|
99
|
+
npm 本身没有统一的 24 小时安装等待期。DSH 插件命令底层使用 pnpm;pnpm 11 起默认设置 `minimumReleaseAge: 1440`,按包名或 `latest` 安装、升级时可能继续选中发布满一天的旧版本。默认的非严格策略允许上面显式指定 `@0.1.6` 的安装;如果 profile 显式配置了严格的发布时间限制,则仍会被阻止。
|
|
100
|
+
|
|
101
|
+
需要立即安装该修复时,可在对应 profile 的 `pnpm-workspace.yaml`(默认位于 `~/.dsh/profiles/web/`)中,将此版本合并到已有的例外列表,再运行上面的安装命令:
|
|
102
|
+
|
|
103
|
+
```yaml
|
|
104
|
+
minimumReleaseAgeExclude:
|
|
105
|
+
- dsh-opencode-go@0.1.6
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
保留文件中的其他设置和已有例外。此项仅豁免本插件的 `0.1.6`,不改变其他依赖的等待策略。参见 [pnpm 发布时间限制文档](https://pnpm.io/settings/dependency-resolution#minimumreleaseage)。市场目录、兼容性缓存或 npm 镜像也可能晚于官方 registry 更新;页面仍显示旧版本不代表新版尚未发布。
|
|
109
|
+
|
|
81
110
|
|
|
82
111
|
### 提示 `opencode-go` 路由已被占用
|
|
83
112
|
|
package/docs/verification.md
CHANGED
|
@@ -59,4 +59,69 @@ A read-only check against the live OpenCode Go listing and models.dev resolved 3
|
|
|
59
59
|
|
|
60
60
|
## Remaining limits
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
Desktop, non-macOS platforms, and DSH releases outside the versions documented here are not verified. Live OpenCode Go verification is limited to the four image requests and four text-only code-generation requests documented below. The automated gateway tests preserve the adapter's request and replay semantics but cannot establish account validity or live provider availability.
|
|
63
|
+
|
|
64
|
+
## DSH 0.1.5 compatibility (plugin 0.1.5)
|
|
65
|
+
|
|
66
|
+
Issue #1 reproduced as an ESM import failure before plugin activation: DSH 0.1.5 lacks `IMAGE_OFFLOAD_REQUIRED_CODE`, `requiredImageOffload`, and `projectOffloadedImages`. The regression test failed against both actual published `dsh-llm` 0.1.5 release candidates before the fix.
|
|
67
|
+
|
|
68
|
+
`npm test` builds the distributed artifact and runs `tests/host-compatibility.spec.ts` in fresh Node processes against the published LLM packages `0.1.5-rc.1`, `0.1.5-rc.2`, and `0.1.6-alpha.1`. The two older versions are pinned npm aliases in development dependencies. A resolution hook selects the LLM package for both the plugin and Cordis Loader; it does not mock that package's exports. This focused matrix does not replace full CLI/profile checks.
|
|
69
|
+
|
|
70
|
+
The original fixture verifies native ESM loading, Loader activation, model listing, streamed text, image transport with a mock attachment store, repeated-image byte accounting, nested oldest-image offloading, immutable history, and a second check against encoded image sizes. It did not validate the real attachment service's request policy (see Issue #2 below). All external model metadata is replaced by an offline fixture, and completions go to a loopback gateway with a fake credential.
|
|
71
|
+
|
|
72
|
+
The compatibility bridge uses the host's own functions. On 0.1.5 it preserves the stock adapter's two-pass transient projection (estimated bytes before reading images, exact encoded bytes afterward). On 0.1.6 it preserves durable offload marks and the `IMAGE_OFFLOAD_REQUIRED` retry signal; it never silently substitutes legacy offloading on a modern host. The existing conversion suite additionally checks surface-marked images, path descriptions, and unsupported image roles.
|
|
73
|
+
|
|
74
|
+
Validation: 146 tests passed, Host and Client type checks passed, and the package built successfully on Node.js 24.14.1.
|
|
75
|
+
|
|
76
|
+
Full installed checks also passed against separate npm CLI installations whose entire DSH dependency closures were pinned to `0.1.5-rc.1` and `0.1.5-rc.2` respectively (not just the CLI version). The `0.1.5` plugin tarball was installed through `dsh plugin` into each installation's Web and Headless profiles under isolated `DSH_HOME` directories. Both versions passed `verify:installed` for package resolution, catalog, streaming, request headers, and unload; both passed `verify:headless` through the official launcher and loopback gateway. Browser checks confirmed the Web shell and OpenCode Go settings section load, including the API-key field, advanced settings, and enable switch, with no page errors.
|
|
77
|
+
|
|
78
|
+
## Image policy compatibility (plugin 0.1.6, Issue #2)
|
|
79
|
+
|
|
80
|
+
The real published `dsh-attachment-local` 0.1.5-rc.2 reproduced `Image request maxPixels must be a positive integer.` with an 800×600 PNG before the fix. The adapter passed `{ width, height, maxBytes }`, but DSH 0.1.5 requires `{ maxPixels, maxBytes }`. DSH 0.1.6 requires explicit dimensions, so replacing dimensions with only the old policy would break the newer hosts. The adapter now supplies both the computed dimensions and the original pixel/byte budgets; each host consumes its own contract.
|
|
81
|
+
|
|
82
|
+
The automated matrix now covers four matching sets of published `dsh-llm`, `dsh-attachment`, and `dsh-attachment-local` packages:
|
|
83
|
+
|
|
84
|
+
| Host packages | Real image requests | Existing loading, text, and offload checks |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| 0.1.5-rc.1 | Pass | Pass |
|
|
87
|
+
| 0.1.5-rc.2 | Pass | Pass |
|
|
88
|
+
| 0.1.6-alpha.1 | Pass | Pass |
|
|
89
|
+
| 0.1.6-alpha.2 | Pass | Pass |
|
|
90
|
+
|
|
91
|
+
`tests/fixtures/host-compatibility.mjs` saves actual PNGs in a temporary local attachment store, streams them through the built adapter to a loopback gateway, and decodes the transmitted bytes. It checks an unchanged 800×600 image, a 3000×2000 image downscaled under the default pixel budget, and a custom pixel/byte budget. Storage admission keeps the original dimensions so resizing is exercised in the request path. Temporary storage is removed after each run. The mock attachment checks remain for exact byte-bound and offload scenarios.
|
|
92
|
+
|
|
93
|
+
Run `npm test -- tests/host-compatibility.spec.ts` for the focused matrix. The aliases intentionally install multiple host generations; use `npm ci --force` to retain the pinned development dependency tree despite their conflicting peer ranges. Resolution hooks select the matching LLM and attachment API at runtime. Other services use the development dependency tree, so this is not a full four-version CLI/Desktop or browser matrix, and no live paid completion is sent.
|
|
94
|
+
|
|
95
|
+
Additional isolated-install checks passed on macOS/Node.js 24.14.1 for all four versions. The built tarball was npm-installed into four temporary consumers with all DSH packages in each dependency closure pinned to the target version (38, 38, 39, and 40 DSH packages respectively; no version mismatches). A copy of the fixture loaded the installed plugin and packages directly, without resolution hooks, and passed ESM loading, Cordis Loader activation, model listing, streamed text, real image resizing, custom budgets, and image-offload/history assertions. These checks exercise the installed dependency combinations, not the official CLI launcher, Desktop, or browser UI.
|
|
96
|
+
|
|
97
|
+
Validation: 147 tests passed, Host/Client type checks and builds passed, and the focused four-version matrix passed again after adding custom-budget checks. Windows Desktop remains unverified.
|
|
98
|
+
|
|
99
|
+
## Live image verification (2026-09-21)
|
|
100
|
+
|
|
101
|
+
With the user's authorization, the fixed tarball was tested against the real OpenCode Go endpoint `https://opencode.ai/zen/go/v1` using model `deepseek-v4.1-flash`. Each of the four isolated consumers above used its actual Cordis Loader, LLM service, local attachment service, and installed plugin, with no mocked metadata or gateway response. SHA-256 comparisons confirmed all four installed Host artifacts matched the current built fix.
|
|
102
|
+
|
|
103
|
+
Each consumer sent exactly one completion request containing an 800×600 solid red PNG and a 3000×2000 solid blue PNG. Admission preserved the original dimensions, so the larger image exercised the adapter's request-size preparation. The prompt asked for the two dominant colors in order without naming them. Every outgoing completion contained both image parts, received HTTP 200, returned `red, blue`, and ended with `finish.kind: stop`.
|
|
104
|
+
|
|
105
|
+
| DSH dependency version | Result | Elapsed time including setup/discovery | Reported input/output tokens |
|
|
106
|
+
| --- | --- | --- | --- |
|
|
107
|
+
| 0.1.5-rc.1 | Pass | 2.586 s | 1501 / 26 |
|
|
108
|
+
| 0.1.5-rc.2 | Pass | 2.503 s | 1501 / 70 |
|
|
109
|
+
| 0.1.6-alpha.1 | Pass | 2.993 s | 1501 / 128 |
|
|
110
|
+
| 0.1.6-alpha.2 | Pass | 2.686 s | 1501 / 53 |
|
|
111
|
+
|
|
112
|
+
Total: four live completion requests and 6,281 reported tokens (including reasoning output). The credential was supplied through hidden stdin, passed to child processes through their environment, and never saved in repository files or test logs. Temporary image storage was removed. These checks verify the real model/attachment request path on macOS; they do not exercise Windows Desktop's UI or establish compatibility for every other model.
|
|
113
|
+
|
|
114
|
+
## Live text-only code verification (2026-09-21)
|
|
115
|
+
|
|
116
|
+
The same four isolated consumers and `deepseek-v4.1-flash` model were then tested with one ordinary text-only code-generation request each. No attachment service was mounted for these requests. The task was to implement a JavaScript `mergeIntervals(intervals)` function that handles unsorted closed intervals, merges overlaps/shared endpoints, and returns new arrays without mutating its input. Each outgoing completion contained zero image parts and used the actual installed Loader, LLM service, and plugin against the live gateway.
|
|
117
|
+
|
|
118
|
+
All four requests returned HTTP 200 and `finish.kind: stop`. After inspecting each generated function, it was executed in a time-bounded VM context without process, filesystem, module-loading, or credential bindings. Eight cases covered empty input, overlaps, chains sharing endpoints, negative bounds, nested intervals, duplicate points, unsorted disjoint intervals, and distinct adjacent integer points. Inputs were frozen; every case checked the expected result, unchanged inputs, and independent output arrays.
|
|
119
|
+
|
|
120
|
+
| DSH dependency version | Code checks | Elapsed time including setup/discovery | Reported input/output tokens |
|
|
121
|
+
| --- | --- | --- | --- |
|
|
122
|
+
| 0.1.5-rc.1 | 8/8 passed | 4.278 s | 133 / 599 |
|
|
123
|
+
| 0.1.5-rc.2 | 8/8 passed | 4.487 s | 133 / 670 |
|
|
124
|
+
| 0.1.6-alpha.1 | 8/8 passed | 3.882 s | 133 / 589 |
|
|
125
|
+
| 0.1.6-alpha.2 | 8/8 passed | 4.759 s | 133 / 702 |
|
|
126
|
+
|
|
127
|
+
Total: four additional live completion requests and 3,092 reported tokens, including reasoning output. No code corrections or retries were needed. This verifies ordinary text-only code generation and executable output; it does not exercise an agent's multi-turn tool-call workflow. Credential handling was identical to the live image checks above.
|
package/lib/client.js
CHANGED
|
@@ -40,7 +40,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")
|
|
|
40
40
|
style.textContent = ".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_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{border-color:var(--dsw-alias-brand-primary);outline:none}.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{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_actions{align-items:center;gap:8px;padding-top:12px;display:flex}.BtKYva_failedNote{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}";
|
|
41
41
|
document.head.appendChild(style);
|
|
42
42
|
}
|
|
43
|
-
var Section_default = { "
|
|
43
|
+
var Section_default = { "failedNote": "BtKYva_failedNote", "intro": "BtKYva_intro", "badges": "BtKYva_badges", "head": "BtKYva_head", "input": "BtKYva_input", "field": "BtKYva_field", "label": "BtKYva_label", "invalid": "BtKYva_invalid", "chevronOpen": "BtKYva_chevronOpen", "chips": "BtKYva_chips", "actions": "BtKYva_actions", "chevron": "BtKYva_chevron", "disclosure": "BtKYva_disclosure", "reset": "BtKYva_reset", "hint": "BtKYva_hint", "inputInvalid": "BtKYva_inputInvalid", "advanced": "BtKYva_advanced" };
|
|
44
44
|
|
|
45
45
|
// src/client/Section.tsx
|
|
46
46
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -885,7 +885,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
|
|
|
885
885
|
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}";
|
|
886
886
|
document.head.appendChild(style);
|
|
887
887
|
}
|
|
888
|
-
var UsagePill_default = { "
|
|
888
|
+
var UsagePill_default = { "root": "dmPm3q_root", "trigger": "dmPm3q_trigger", "window": "dmPm3q_window", "row": "dmPm3q_row", "panel": "dmPm3q_panel", "hint": "dmPm3q_hint" };
|
|
889
889
|
|
|
890
890
|
// src/client/UsagePill.tsx
|
|
891
891
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
package/lib/index.js
CHANGED
|
@@ -47,14 +47,14 @@ var __callDispose = (stack, error, hasError) => {
|
|
|
47
47
|
// src/index.ts
|
|
48
48
|
import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
|
|
49
49
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
50
|
-
import { LlmError as
|
|
50
|
+
import { LlmError as LlmError7, assertUsableApiKey, resolveImageAttachmentAccess } from "@deepseek-ai/dsh-llm";
|
|
51
51
|
|
|
52
52
|
// src/adapter.ts
|
|
53
53
|
import { randomUUID } from "node:crypto";
|
|
54
54
|
import { getSupportedThinkingLevels } from "@earendil-works/pi-ai";
|
|
55
55
|
import {
|
|
56
56
|
LlmAdapter,
|
|
57
|
-
LlmError as
|
|
57
|
+
LlmError as LlmError6,
|
|
58
58
|
ReasoningEffortId,
|
|
59
59
|
attributionHeaders as attributionHeaders2,
|
|
60
60
|
contentHasImage as contentHasImage2
|
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
|
|
63
63
|
// src/conversion/context.ts
|
|
64
64
|
import { brandString } from "@deepseek-ai/dsh-brand";
|
|
65
|
-
import { contentHasImage,
|
|
65
|
+
import { contentHasImage, LlmError as LlmError3, offloadedImageText, requestImageHandleText } from "@deepseek-ai/dsh-llm";
|
|
66
66
|
|
|
67
67
|
// src/conversion/replay.ts
|
|
68
68
|
import { LlmError } from "@deepseek-ai/dsh-llm";
|
|
@@ -267,6 +267,40 @@ var DEFAULT_MAX_REQUEST_IMAGE_BYTES = 20 * 1024 * 1024;
|
|
|
267
267
|
var DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET = 2048 * 2048;
|
|
268
268
|
var DEFAULT_REQUEST_IMAGE_MAX_BYTES = 1024 * 1024;
|
|
269
269
|
|
|
270
|
+
// src/conversion/image-offload.ts
|
|
271
|
+
import * as llm from "@deepseek-ai/dsh-llm";
|
|
272
|
+
var api = llm;
|
|
273
|
+
function projectRequestImages(messages, policy) {
|
|
274
|
+
if (api.requiredImageOffload !== void 0 && api.projectOffloadedImages !== void 0) {
|
|
275
|
+
if (!policy.exact) return messages;
|
|
276
|
+
if (policy.maxBytes !== void 0) {
|
|
277
|
+
const offloadImages = api.requiredImageOffload(
|
|
278
|
+
messages,
|
|
279
|
+
{ representation: "base64", maxBytes: policy.maxBytes },
|
|
280
|
+
(block) => policy.byteLength(block.attachment)
|
|
281
|
+
);
|
|
282
|
+
if (offloadImages > 0) {
|
|
283
|
+
throw new llm.LlmError(
|
|
284
|
+
`pi-ai request images exceed the ${policy.maxBytes}-byte base64 bound; ${offloadImages} more oldest occurrence(s) must be offloaded.`,
|
|
285
|
+
api.IMAGE_OFFLOAD_REQUIRED_CODE ?? "IMAGE_OFFLOAD_REQUIRED",
|
|
286
|
+
{ offloadImages }
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return api.projectOffloadedImages(messages, policy.placeholder);
|
|
291
|
+
}
|
|
292
|
+
if (api.offloadRequestImagesWithPolicy === void 0) {
|
|
293
|
+
throw new llm.LlmError("The DSH host has no supported image offload API", "UNSUPPORTED_CONTENT");
|
|
294
|
+
}
|
|
295
|
+
return api.offloadRequestImagesWithPolicy(messages, {
|
|
296
|
+
representation: "base64",
|
|
297
|
+
byteQuantum: 1,
|
|
298
|
+
maxBytes: policy.maxBytes,
|
|
299
|
+
byteLength: policy.byteLength,
|
|
300
|
+
placeholder: policy.placeholder
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
270
304
|
// src/conversion/context.ts
|
|
271
305
|
function flattenText(message) {
|
|
272
306
|
return message.content.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
@@ -277,7 +311,7 @@ function toolResultText(blocks) {
|
|
|
277
311
|
function assertSupportedImageRoles(messages) {
|
|
278
312
|
for (const message of messages) {
|
|
279
313
|
if (message.role !== "user" && contentHasImage(message.content)) {
|
|
280
|
-
throw new
|
|
314
|
+
throw new LlmError3(
|
|
281
315
|
`pi-ai cannot represent an image in an in-history ${message.role} message`,
|
|
282
316
|
"UNSUPPORTED_CONTENT"
|
|
283
317
|
);
|
|
@@ -381,7 +415,7 @@ function textOnlyContext(options, onReplayDegrade) {
|
|
|
381
415
|
const messages = [];
|
|
382
416
|
for (const message of split.messages) {
|
|
383
417
|
if (contentHasImage(message.content)) {
|
|
384
|
-
throw new
|
|
418
|
+
throw new LlmError3("pi-ai image conversion requires the durable attachment service", "UNSUPPORTED_CONTENT");
|
|
385
419
|
}
|
|
386
420
|
if (message.role === "system") {
|
|
387
421
|
messages.push({ role: "user", content: flattenText(message), timestamp: 0 });
|
|
@@ -411,7 +445,11 @@ function textOnlyContext(options, onReplayDegrade) {
|
|
|
411
445
|
return piContext(split.systemPrompt, options, messages);
|
|
412
446
|
}
|
|
413
447
|
function requestImageTarget(ref, budget) {
|
|
414
|
-
return {
|
|
448
|
+
return {
|
|
449
|
+
...requestImageDimensions(ref.width, ref.height, budget.maxPixels),
|
|
450
|
+
maxPixels: budget.maxPixels,
|
|
451
|
+
maxBytes: budget.maxBytes
|
|
452
|
+
};
|
|
415
453
|
}
|
|
416
454
|
function toPiContext(options, images, onReplayDegrade) {
|
|
417
455
|
return images === void 0 ? textOnlyContext(options, onReplayDegrade) : toPiContextWithImages(options, images, onReplayDegrade);
|
|
@@ -424,25 +462,21 @@ async function toPiContextWithImages(options, images, onReplayDegrade) {
|
|
|
424
462
|
};
|
|
425
463
|
assertSupportedImageRoles(options.messages);
|
|
426
464
|
const split = splitSystemPrompt(options);
|
|
427
|
-
const
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
const exactMessages = projectOffloadedImages(
|
|
443
|
-
split.messages,
|
|
444
|
-
(ref) => offloadedImageText(ref, resolveImageAccess(ref))
|
|
445
|
-
);
|
|
465
|
+
const projection = {
|
|
466
|
+
maxBytes: maxRequestImageBytes,
|
|
467
|
+
placeholder: (ref) => offloadedImageText(ref, resolveImageAccess(ref))
|
|
468
|
+
};
|
|
469
|
+
const requestMessages = projectRequestImages(split.messages, {
|
|
470
|
+
...projection,
|
|
471
|
+
exact: false,
|
|
472
|
+
byteLength: (ref) => Math.min(ref.bytes, requestImagePolicy.maxBytes)
|
|
473
|
+
});
|
|
474
|
+
const requestImages = await prepareRequestImages(requestMessages, attachments, requestImagePolicy, options.signal);
|
|
475
|
+
const exactMessages = projectRequestImages(requestMessages, {
|
|
476
|
+
...projection,
|
|
477
|
+
exact: true,
|
|
478
|
+
byteLength: (ref) => requestImages.get(ref.attachmentId).bytes
|
|
479
|
+
});
|
|
446
480
|
const toolNames = /* @__PURE__ */ new Map();
|
|
447
481
|
const messages = [];
|
|
448
482
|
for (const message of exactMessages) {
|
|
@@ -477,7 +511,7 @@ async function toPiContextWithImages(options, images, onReplayDegrade) {
|
|
|
477
511
|
|
|
478
512
|
// src/conversion/stream.ts
|
|
479
513
|
import { brandString as brandString2 } from "@deepseek-ai/dsh-brand";
|
|
480
|
-
import { CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, isContextWindowExceededError, isQuotaExceededError, LlmError as
|
|
514
|
+
import { CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, isContextWindowExceededError, isQuotaExceededError, LlmError as LlmError4, QUOTA_EXCEEDED_CODE } from "@deepseek-ai/dsh-llm";
|
|
481
515
|
import { isContextOverflow } from "@earendil-works/pi-ai";
|
|
482
516
|
function mapUsage(usage) {
|
|
483
517
|
return {
|
|
@@ -628,7 +662,7 @@ async function* toStreamChunks(events, contextWindow, callerSignal, requestedMod
|
|
|
628
662
|
return;
|
|
629
663
|
}
|
|
630
664
|
}
|
|
631
|
-
throw new
|
|
665
|
+
throw new LlmError4("pi-ai event stream ended without done/error", "STREAM_CLOSED");
|
|
632
666
|
}
|
|
633
667
|
|
|
634
668
|
// src/adapter.ts
|
|
@@ -640,7 +674,7 @@ import { getBuiltinModels } from "@earendil-works/pi-ai/providers/all";
|
|
|
640
674
|
import { anthropicMessagesApi } from "@earendil-works/pi-ai/api/anthropic-messages.lazy";
|
|
641
675
|
import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy";
|
|
642
676
|
import { openAIResponsesApi } from "@earendil-works/pi-ai/api/openai-responses.lazy";
|
|
643
|
-
import { attributionHeaders, LlmError as
|
|
677
|
+
import { attributionHeaders, LlmError as LlmError5 } from "@deepseek-ai/dsh-llm";
|
|
644
678
|
|
|
645
679
|
// src/model-metadata.ts
|
|
646
680
|
var MODEL_METADATA_URL = "https://models.dev/api.json";
|
|
@@ -680,9 +714,9 @@ function thinkingLevels(metadata, known) {
|
|
|
680
714
|
if (known?.reasoning && known.thinkingLevelMap?.off !== null) map.off ??= known.thinkingLevelMap?.off ?? "off";
|
|
681
715
|
return map;
|
|
682
716
|
}
|
|
683
|
-
function modelBaseURL(
|
|
717
|
+
function modelBaseURL(api2, baseURL) {
|
|
684
718
|
const base = baseURL.replace(/\/+$/, "");
|
|
685
|
-
return
|
|
719
|
+
return api2 === "anthropic-messages" ? base.replace(/\/v1$/, "") : base;
|
|
686
720
|
}
|
|
687
721
|
function readModelMetadata(body, baseURL, builtin) {
|
|
688
722
|
const provider = record(record(body)["opencode-go"]);
|
|
@@ -696,22 +730,22 @@ function readModelMetadata(body, baseURL, builtin) {
|
|
|
696
730
|
try {
|
|
697
731
|
const metadata = record(value);
|
|
698
732
|
const npm = record(metadata.provider).npm ?? provider.npm;
|
|
699
|
-
const
|
|
700
|
-
if (
|
|
733
|
+
const api2 = npm === "@ai-sdk/anthropic" ? "anthropic-messages" : npm === "@ai-sdk/openai" ? "openai-responses" : npm === "@ai-sdk/openai-compatible" ? "openai-completions" : void 0;
|
|
734
|
+
if (api2 === void 0) throw new Error(`unsupported model protocol ${String(npm)}`);
|
|
701
735
|
const limit = record(metadata.limit);
|
|
702
736
|
const input = record(metadata.modalities).input;
|
|
703
737
|
if (!Array.isArray(input) || !input.includes("text")) throw new Error("missing text input modality");
|
|
704
738
|
if (typeof metadata.reasoning !== "boolean") throw new Error("missing reasoning capability");
|
|
705
739
|
const exact = builtin.get(id);
|
|
706
|
-
const family = typeof metadata.family === "string" ? Object.keys(entries).find((key) => record(entries[key]).family === metadata.family && builtin.get(key)?.api ===
|
|
707
|
-
const known = exact?.api ===
|
|
708
|
-
const compat =
|
|
740
|
+
const family = typeof metadata.family === "string" ? Object.keys(entries).find((key) => record(entries[key]).family === metadata.family && builtin.get(key)?.api === api2) : void 0;
|
|
741
|
+
const known = exact?.api === api2 ? exact : family === void 0 ? void 0 : builtin.get(family);
|
|
742
|
+
const compat = api2 === "openai-completions" ? {
|
|
709
743
|
supportsStore: false,
|
|
710
744
|
supportsDeveloperRole: false,
|
|
711
745
|
maxTokensField: "max_tokens",
|
|
712
746
|
...record(metadata.interleaved).field === "reasoning_content" ? { requiresReasoningContentOnAssistantMessages: true } : {},
|
|
713
747
|
...known?.compat
|
|
714
|
-
} :
|
|
748
|
+
} : api2 === "openai-responses" ? { sessionAffinityFormat: "openai-nosession", ...known?.compat } : { ...known?.compat };
|
|
715
749
|
const cost = rates(metadata.cost);
|
|
716
750
|
const tiers = record(metadata.cost).tiers;
|
|
717
751
|
if (Array.isArray(tiers)) {
|
|
@@ -724,8 +758,8 @@ function readModelMetadata(body, baseURL, builtin) {
|
|
|
724
758
|
id,
|
|
725
759
|
name: typeof metadata.name === "string" && metadata.name.length > 0 ? metadata.name : id,
|
|
726
760
|
provider: "opencode-go",
|
|
727
|
-
api,
|
|
728
|
-
baseUrl: modelBaseURL(
|
|
761
|
+
api: api2,
|
|
762
|
+
baseUrl: modelBaseURL(api2, baseURL),
|
|
729
763
|
reasoning: metadata.reasoning,
|
|
730
764
|
thinkingLevelMap: thinkingLevels(metadata, known),
|
|
731
765
|
input: input.includes("image") ? ["text", "image"] : ["text"],
|
|
@@ -774,9 +808,9 @@ async function fetchLiveModelIds(baseURL) {
|
|
|
774
808
|
signal: AbortSignal.timeout(MODELS_FETCH_TIMEOUT_MS)
|
|
775
809
|
});
|
|
776
810
|
} catch (error) {
|
|
777
|
-
throw new
|
|
811
|
+
throw new LlmError5(`could not reach ${url}`, "DISCOVERY_FAILED", { cause: error });
|
|
778
812
|
}
|
|
779
|
-
if (!response.ok) throw new
|
|
813
|
+
if (!response.ok) throw new LlmError5(`${url} answered ${response.status}`, "DISCOVERY_FAILED");
|
|
780
814
|
return readLiveModelIds(await response.json());
|
|
781
815
|
}
|
|
782
816
|
function harnessApiKeyAuth() {
|
|
@@ -889,7 +923,7 @@ var OpencodeGoCatalog = class {
|
|
|
889
923
|
let snapshot = await this.snapshot();
|
|
890
924
|
if (!snapshot.models.has(id) && snapshot === cached) snapshot = await this.snapshot(true);
|
|
891
925
|
if (snapshot.unavailable.has(id)) {
|
|
892
|
-
throw new
|
|
926
|
+
throw new LlmError5(
|
|
893
927
|
`opencode-go model "${id}" is advertised but cannot be configured: ${snapshot.unavailable.get(id)}; refresh the model list to retry`,
|
|
894
928
|
"MODEL_METADATA_UNAVAILABLE"
|
|
895
929
|
);
|
|
@@ -900,7 +934,7 @@ var OpencodeGoCatalog = class {
|
|
|
900
934
|
async function discoverCatalogModels(catalog) {
|
|
901
935
|
const snapshot = await catalog.snapshot(true);
|
|
902
936
|
if (!snapshot.live) {
|
|
903
|
-
throw new
|
|
937
|
+
throw new LlmError5("llm-opencode-go: the live model listing is unreachable; try again later", "DISCOVERY_FAILED");
|
|
904
938
|
}
|
|
905
939
|
return [
|
|
906
940
|
...[...snapshot.models.values()].map((model) => ({
|
|
@@ -1006,7 +1040,7 @@ var OpencodeGoAdapter = class extends LlmAdapter {
|
|
|
1006
1040
|
const snapshot = await this.catalogOf(this.options.config()).forModel(model);
|
|
1007
1041
|
const resolved = snapshot.models.get(model);
|
|
1008
1042
|
if (resolved === void 0) {
|
|
1009
|
-
throw new
|
|
1043
|
+
throw new LlmError6(`opencode-go has no model "${model}"`, "UNKNOWN_MODEL");
|
|
1010
1044
|
}
|
|
1011
1045
|
return this.modelInfo(resolved);
|
|
1012
1046
|
}
|
|
@@ -1036,7 +1070,7 @@ var OpencodeGoAdapter = class extends LlmAdapter {
|
|
|
1036
1070
|
if (effort === void 0) return void 0;
|
|
1037
1071
|
const supported = getSupportedThinkingLevels(model);
|
|
1038
1072
|
if (supported.some((level) => level === effort)) return effort;
|
|
1039
|
-
throw new
|
|
1073
|
+
throw new LlmError6(
|
|
1040
1074
|
`opencode-go model "${model.id}" does not support reasoning effort "${effort}"`,
|
|
1041
1075
|
"UNSUPPORTED_REASONING_EFFORT"
|
|
1042
1076
|
);
|
|
@@ -1045,17 +1079,17 @@ var OpencodeGoAdapter = class extends LlmAdapter {
|
|
|
1045
1079
|
var _stack = [];
|
|
1046
1080
|
try {
|
|
1047
1081
|
if (options.stop !== void 0) {
|
|
1048
|
-
throw new
|
|
1082
|
+
throw new LlmError6("llm-opencode-go does not support GenerateOptions.stop", "UNSUPPORTED_OPTION");
|
|
1049
1083
|
}
|
|
1050
1084
|
const config = this.options.config();
|
|
1051
1085
|
const snapshot = await this.catalogOf(config).forModel(options.model);
|
|
1052
1086
|
const model = snapshot.models.get(options.model);
|
|
1053
1087
|
if (model === void 0) {
|
|
1054
|
-
throw new
|
|
1088
|
+
throw new LlmError6(`opencode-go has no model "${options.model}"`, "UNKNOWN_MODEL");
|
|
1055
1089
|
}
|
|
1056
1090
|
const apiKey = await this.options.resolveApiKey();
|
|
1057
1091
|
if (apiKey === void 0 || apiKey.length === 0) {
|
|
1058
|
-
throw new
|
|
1092
|
+
throw new LlmError6("llm-opencode-go: no credential resolved for the route", "MISSING_CREDENTIAL");
|
|
1059
1093
|
}
|
|
1060
1094
|
const reasoning = this.resolveReasoningLevel(model, options.reasoningEffort);
|
|
1061
1095
|
const consumer = new AbortController();
|
|
@@ -1064,14 +1098,14 @@ var OpencodeGoAdapter = class extends LlmAdapter {
|
|
|
1064
1098
|
try {
|
|
1065
1099
|
const containsImage = options.messages.some((message) => contentHasImage2(message.content));
|
|
1066
1100
|
if (containsImage && !model.input.includes("image")) {
|
|
1067
|
-
throw new
|
|
1101
|
+
throw new LlmError6(`opencode-go model "${model.id}" does not support image input`, "UNSUPPORTED_CONTENT");
|
|
1068
1102
|
}
|
|
1069
1103
|
let imageRequest;
|
|
1070
1104
|
if (containsImage) {
|
|
1071
1105
|
const access = this.options.imageAccess;
|
|
1072
1106
|
const store = access?.resolveAttachments();
|
|
1073
1107
|
if (access === void 0 || store === void 0) {
|
|
1074
|
-
throw new
|
|
1108
|
+
throw new LlmError6("llm-opencode-go image input requires the durable attachment service", "UNSUPPORTED_CONTENT");
|
|
1075
1109
|
}
|
|
1076
1110
|
imageRequest = {
|
|
1077
1111
|
attachments: store,
|
|
@@ -1108,7 +1142,7 @@ var OpencodeGoAdapter = class extends LlmAdapter {
|
|
|
1108
1142
|
while (true) {
|
|
1109
1143
|
const result = await watchdog.next(iterator);
|
|
1110
1144
|
if (timeoutOf(watchdog.signal, "LLM_STREAM_IDLE_TIMEOUT") !== void 0) {
|
|
1111
|
-
throw new
|
|
1145
|
+
throw new LlmError6("opencode-go stream idle timeout", "TIMEOUT");
|
|
1112
1146
|
}
|
|
1113
1147
|
if (result.done) {
|
|
1114
1148
|
exhausted = true;
|
|
@@ -1127,10 +1161,10 @@ var OpencodeGoAdapter = class extends LlmAdapter {
|
|
|
1127
1161
|
}
|
|
1128
1162
|
} catch (error) {
|
|
1129
1163
|
if (timeoutOf(watchdog.signal, "LLM_STREAM_IDLE_TIMEOUT") !== void 0) {
|
|
1130
|
-
throw new
|
|
1164
|
+
throw new LlmError6("opencode-go stream idle timeout", "TIMEOUT", { cause: error });
|
|
1131
1165
|
}
|
|
1132
1166
|
if (options.signal?.aborted) {
|
|
1133
|
-
throw new
|
|
1167
|
+
throw new LlmError6("opencode-go request aborted by caller", "ABORTED", { cause: error });
|
|
1134
1168
|
}
|
|
1135
1169
|
throw error;
|
|
1136
1170
|
}
|
|
@@ -1222,7 +1256,7 @@ function apply(ctx, raw) {
|
|
|
1222
1256
|
const credentials = ctx.get("credentials");
|
|
1223
1257
|
const hit = credentials !== void 0 ? (await credentials.resolve(credentialRef(ref)))?.value : launchEnvironmentOf(ctx).get(ref)?.value;
|
|
1224
1258
|
if (hit !== void 0 && hit.length > 0) return assertUsableApiKey(hit, name, ref);
|
|
1225
|
-
throw new
|
|
1259
|
+
throw new LlmError7(
|
|
1226
1260
|
`llm-opencode-go: no credential; the profile resolves ${ref}, which is not set \u2014 store ${ref} through the credentials service or export it`,
|
|
1227
1261
|
"MISSING_CREDENTIAL"
|
|
1228
1262
|
);
|
|
@@ -1284,7 +1318,7 @@ function apply(ctx, raw) {
|
|
|
1284
1318
|
syncRoute();
|
|
1285
1319
|
const undiscover = ctx.llm.registerModelDiscovery(name, async (request) => {
|
|
1286
1320
|
if (request.provider !== PROVIDER_ID && !(request.baseURL ?? "").includes("opencode.ai")) {
|
|
1287
|
-
throw new
|
|
1321
|
+
throw new LlmError7(
|
|
1288
1322
|
"llm-opencode-go discovers only OpenCode zen/go endpoints; enter this provider's models by hand",
|
|
1289
1323
|
"DISCOVERY_UNSUPPORTED"
|
|
1290
1324
|
);
|
|
@@ -36,8 +36,9 @@ export interface PiImageRequestBudget {
|
|
|
36
36
|
export declare function toPiContext(options: GenerateOptions, images?: undefined, onReplayDegrade?: (reason: string) => void): PiContext;
|
|
37
37
|
/**
|
|
38
38
|
* Convert harness history to a pi-ai Context while resolving durable images.
|
|
39
|
-
* Tool result names are recovered from preceding assistant tool calls.
|
|
40
|
-
*
|
|
39
|
+
* Tool result names are recovered from preceding assistant tool calls. On DSH
|
|
40
|
+
* 0.1.5, oldest images over the request budget become transient placeholders.
|
|
41
|
+
* On newer hosts, occurrences the surface marks offloaded become placeholders; when the
|
|
41
42
|
* retained occurrences' exact base64 payload still exceeds
|
|
42
43
|
* `maxRequestImageBytes`, the call fails with `IMAGE_OFFLOAD_REQUIRED` naming
|
|
43
44
|
* how many more oldest occurrences must be offloaded.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Message } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
import type { ImageAttachmentRef } from '@deepseek-ai/dsh-attachment';
|
|
3
|
+
interface ImageProjectionPolicy {
|
|
4
|
+
maxBytes?: number;
|
|
5
|
+
byteLength: (ref: ImageAttachmentRef) => number;
|
|
6
|
+
placeholder: (ref: ImageAttachmentRef) => string;
|
|
7
|
+
/** False before preparing image bytes, true once encoded sizes are known. */
|
|
8
|
+
exact: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Preserve the host generation's image policy, using estimates first and exact sizes second. */
|
|
11
|
+
export declare function projectRequestImages(messages: readonly Message[], policy: ImageProjectionPolicy): readonly Message[];
|
|
12
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-opencode-go",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "OpenCode Go model provider and settings UI for DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"url": "https://github.com/Duskriver/dsh-opencode-go/issues"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": "^22.19.0 || >=24.0.0"
|
|
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"
|
|
17
18
|
},
|
|
18
19
|
"main": "./lib/index.js",
|
|
19
20
|
"types": "./lib/types/index.d.ts",
|
|
@@ -60,25 +61,25 @@
|
|
|
60
61
|
},
|
|
61
62
|
"peerDependencies": {
|
|
62
63
|
"@deepseek-ai/cordis": "4.0.2",
|
|
63
|
-
"@deepseek-ai/dsh-api-gateway": "0.1.6-alpha.1",
|
|
64
|
-
"@deepseek-ai/dsh-api-remotes": "0.1.6-alpha.1",
|
|
65
|
-
"@deepseek-ai/dsh-api-settings-controller": "0.1.6-alpha.1",
|
|
66
|
-
"@deepseek-ai/dsh-attachment": "0.1.6-alpha.1",
|
|
67
|
-
"@deepseek-ai/dsh-client-locale": "0.1.6-alpha.1",
|
|
68
|
-
"@deepseek-ai/dsh-client-store": "0.1.6-alpha.1",
|
|
69
|
-
"@deepseek-ai/dsh-client-ui-
|
|
70
|
-
"@deepseek-ai/dsh-client-ui-
|
|
71
|
-
"@deepseek-ai/dsh-client-ui-
|
|
72
|
-
"@deepseek-ai/dsh-client-ui-
|
|
73
|
-
"@deepseek-ai/dsh-
|
|
74
|
-
"@deepseek-ai/dsh-
|
|
75
|
-
"@deepseek-ai/dsh-
|
|
76
|
-
"@deepseek-ai/dsh-
|
|
77
|
-
"@deepseek-ai/dsh-
|
|
78
|
-
"@deepseek-ai/dsh-
|
|
79
|
-
"@deepseek-ai/dsh-
|
|
80
|
-
"@deepseek-ai/dsh-
|
|
81
|
-
"@deepseek-ai/dsh-typert-registry": "0.1.6-alpha.1"
|
|
64
|
+
"@deepseek-ai/dsh-api-gateway": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-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",
|
|
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",
|
|
67
|
+
"@deepseek-ai/dsh-attachment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-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",
|
|
69
|
+
"@deepseek-ai/dsh-client-store": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
75
|
+
"@deepseek-ai/dsh-credentials": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-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",
|
|
77
|
+
"@deepseek-ai/dsh-launch-environment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-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",
|
|
79
|
+
"@deepseek-ai/dsh-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-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",
|
|
81
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-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"
|
|
82
83
|
},
|
|
83
84
|
"dependencies": {
|
|
84
85
|
"@deepseek-ai/dsh-brand": "0.1.6-alpha.1",
|
|
@@ -93,6 +94,7 @@
|
|
|
93
94
|
"@deepseek-ai/dsh-api-remotes": "0.1.6-alpha.1",
|
|
94
95
|
"@deepseek-ai/dsh-api-settings-controller": "0.1.6-alpha.1",
|
|
95
96
|
"@deepseek-ai/dsh-attachment": "0.1.6-alpha.1",
|
|
97
|
+
"@deepseek-ai/dsh-attachment-local": "0.1.6-alpha.1",
|
|
96
98
|
"@deepseek-ai/dsh-brand": "0.1.6-alpha.1",
|
|
97
99
|
"@deepseek-ai/dsh-client-locale": "0.1.6-alpha.1",
|
|
98
100
|
"@deepseek-ai/dsh-client-store": "0.1.6-alpha.1",
|
|
@@ -105,6 +107,7 @@
|
|
|
105
107
|
"@deepseek-ai/dsh-credentials": "0.1.6-alpha.1",
|
|
106
108
|
"@deepseek-ai/dsh-credentials-local": "0.1.6-alpha.1",
|
|
107
109
|
"@deepseek-ai/dsh-fs": "0.1.6-alpha.1",
|
|
110
|
+
"@deepseek-ai/dsh-home-paths": "0.1.6-alpha.1",
|
|
108
111
|
"@deepseek-ai/dsh-launch-environment": "0.1.6-alpha.1",
|
|
109
112
|
"@deepseek-ai/dsh-llm": "0.1.6-alpha.1",
|
|
110
113
|
"@deepseek-ai/dsh-settings": "0.1.6-alpha.1",
|
|
@@ -121,6 +124,15 @@
|
|
|
121
124
|
"anser": "^2.3.5",
|
|
122
125
|
"clsx": "^2.0.0",
|
|
123
126
|
"diff": "^9.0.0",
|
|
127
|
+
"dsh-attachment-local-v015-rc1": "npm:@deepseek-ai/dsh-attachment-local@0.1.5-rc.1",
|
|
128
|
+
"dsh-attachment-local-v015-rc2": "npm:@deepseek-ai/dsh-attachment-local@0.1.5-rc.2",
|
|
129
|
+
"dsh-attachment-local-v016-alpha2": "npm:@deepseek-ai/dsh-attachment-local@0.1.6-alpha.2",
|
|
130
|
+
"dsh-attachment-v015-rc1": "npm:@deepseek-ai/dsh-attachment@0.1.5-rc.1",
|
|
131
|
+
"dsh-attachment-v015-rc2": "npm:@deepseek-ai/dsh-attachment@0.1.5-rc.2",
|
|
132
|
+
"dsh-attachment-v016-alpha2": "npm:@deepseek-ai/dsh-attachment@0.1.6-alpha.2",
|
|
133
|
+
"dsh-llm-v015-rc1": "npm:@deepseek-ai/dsh-llm@0.1.5-rc.1",
|
|
134
|
+
"dsh-llm-v015-rc2": "npm:@deepseek-ai/dsh-llm@0.1.5-rc.2",
|
|
135
|
+
"dsh-llm-v016-alpha2": "npm:@deepseek-ai/dsh-llm@0.1.6-alpha.2",
|
|
124
136
|
"esbuild": "^0.25.0",
|
|
125
137
|
"immer": "^10.1.1",
|
|
126
138
|
"jsdom": "29.1.1",
|