@dan-ai-studio/dshopencodego 0.1.82 → 0.1.84
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 +8 -5
- package/README.md +8 -5
- package/lib/client.js +1 -0
- package/lib/index.js +1421 -61
- package/lib/types/adapter.d.ts +19 -0
- package/lib/types/catalog/constants.d.ts +13 -0
- package/lib/types/catalog/index.d.ts +34 -2
- package/lib/types/catalog/snapshot-cache.d.ts +38 -6
- package/lib/types/request-log/store.d.ts +14 -4
- package/package.json +3 -1
package/README.en.md
CHANGED
|
@@ -95,7 +95,7 @@ Configuration lives in the profile's `cordis.patch.yml`:
|
|
|
95
95
|
baseURL: https://opencode.ai/inference/go/v1 # default (OpenCode Go endpoint)
|
|
96
96
|
# http(s) only, and no query or fragment; writing ?x=1 is refused when the profile is saved
|
|
97
97
|
# or https://opencode.ai/inference/v1 (Console main endpoint, pay-as-you-go/free models)
|
|
98
|
-
refreshMinutes: 60 # live catalog TTL, 1 ~ 10080 (7 days)
|
|
98
|
+
refreshMinutes: 60 # live catalog TTL, 1 ~ 10080 (7 days); stale past 24 hours it refreshes in the background anyway
|
|
99
99
|
streamIdleTimeoutMs: 300000 # stream idle timeout: longest silence between events (ms)
|
|
100
100
|
keepAliveTimeoutMs: 600000 # connection kept idle between requests (ms, 1 ~ 1800000)
|
|
101
101
|
# the timer restarts on every answer, so a connection in
|
|
@@ -152,7 +152,7 @@ The API key comes from the Harness credential store (reference name `OPENCODE_GO
|
|
|
152
152
|
- **Content split**: below the body size the detail shows **Text X / Images Y** — images estimated as base64 per deduped attachment (each capped at the route's encoded target), text as the residual, so the two always sum to the total. Image-dominated turns read at a glance.
|
|
153
153
|
- Session ids are **always stored whole**: an id is a conversation identity, not a credential, and a truncated one reads two conversations as one.
|
|
154
154
|
- The log is a ring buffer (oldest dropped first) that dies with the process; snapshots are read on open and on manual refresh, plus once a second while any request is running, so a page nobody opens costs no traffic.
|
|
155
|
-
- The credential never enters a record: the recorder takes no headers argument at all, only the allowlisted session id and user agent. A request gets a "Requesting" placeholder row the moment it starts (the status column counts its seconds) and the row is completed in place when it ends. Failed requests are recorded with their error code
|
|
155
|
+
- The credential never enters a record: the recorder takes no headers argument at all, only the allowlisted session id and user agent. A request gets a "Requesting" placeholder row the moment it starts (the status column counts its seconds) and the row is completed in place when it ends. Failed requests are recorded with their error code — including failures before the first byte (unresolvable models, missing credentials), whose rows carry the reason but no usage. A stream the consumer abandoned early is recorded as `ABORTED` instead of vanishing silently.
|
|
156
156
|
|
|
157
157
|
**Images**: an over-budget image is refused explicitly rather than silently downscaled or dropped. The budgets ride one preset `imageBudgetPreset` (three choices, default `dsh`), not three numbers:
|
|
158
158
|
|
|
@@ -199,6 +199,7 @@ The gateway's `/v1/models` answers only *which* models exist, never *how* to cal
|
|
|
199
199
|
- a model the provider **adds** appears on the next refresh; if no metadata source describes it, it is labelled as inferred and can be pinned with `modelProtocols`;
|
|
200
200
|
- a model the provider **retires** disappears on the next refresh;
|
|
201
201
|
- the bundled catalog is **frozen at the plugin's version** and affects only the quality of the "how to call it" decision, never *which* models exist.
|
|
202
|
+
- **fresh installs do not wait**: the bundle carries a directory snapshot from publish time (`src/catalog/seed.snapshot.json`), which answers at once when the disk cache is empty and refreshes behind it; past 24 hours without a refresh counts as stale and refreshes in the background too, whatever the TTL says. A timer re-checks on a live host, so long-running processes stay current without a request to trigger it.
|
|
202
203
|
|
|
203
204
|
When the gateway is **temporarily unavailable**, the plugin keeps the last listing that succeeded, marks it stale on the page, and retries in the background. The retry rate is governed by a **five-minute back-off** rather than by the TTL, so a gateway that comes back is picked up within five minutes; while it stays down it is asked once, not once per model request. The settings page's Recheck button revalidates at any time and is not bound by that back-off.
|
|
204
205
|
|
|
@@ -285,17 +286,19 @@ npm run lint # oxlint: static checks (the release workflow runs this too,
|
|
|
285
286
|
npm run typecheck # both halves: host and client
|
|
286
287
|
npm run build # build first: emits lib/index.js and lib/client.js
|
|
287
288
|
npm test # contract tests against a real local HTTP mock gateway
|
|
289
|
+
npm run seed # refresh the bundled catalog seed before a release (see "Releasing")
|
|
288
290
|
```
|
|
289
291
|
|
|
290
292
|
**Order matters**: `npm run build` must come before `npm test` — `tests/pack-contents.spec.ts` walks every `exports` target, and whether `lib/` exists decides whether that check runs or is silently skipped (it does not fail, it just stops protecting you). `package.json` no longer carries `prepare`, so `npm ci` will not build for you; all three CI workflows run `npm run build` explicitly.
|
|
291
293
|
|
|
292
|
-
The suite covers configuration validation, the protocol ladder, gateway and online metadata, the catalog projection, the adapter on the wire (all three protocols), Remote contracts and services, session-header invariants, usage windows and the meter, the client controller and usage pill, both halves' mounting and registration, the error mapping for stream idle timeouts and aborts, the exit-code contract of the verification scripts, and several **structural invariants** (inject declarations match the source's reads, peer coverage holds both ways, the READMEs match the manifest, and the READMEs' claims about the upstream match the upstream actually installed). That is **
|
|
294
|
+
The suite covers configuration validation, the protocol ladder, gateway and online metadata, the catalog projection, the adapter on the wire (all three protocols), Remote contracts and services, session-header invariants, usage windows and the meter, the client controller and usage pill, both halves' mounting and registration, the error mapping for stream idle timeouts and aborts, the exit-code contract of the verification scripts, and several **structural invariants** (inject declarations match the source's reads, peer coverage holds both ways, the READMEs match the manifest, and the READMEs' claims about the upstream match the upstream actually installed). That is **60 test files** — a number `tests/readme-consistency.spec.ts` checks against the `tests/` directory, so it cannot drift.
|
|
293
295
|
|
|
294
296
|
## Releasing (maintainers)
|
|
295
297
|
|
|
296
298
|
1. **Version**: align `package.json`'s `version` with the tag you are about to push (`v<version>`); CI checks the asset name against the tag.
|
|
297
|
-
2. **
|
|
298
|
-
3. **
|
|
299
|
+
2. **Seed**: run `npm run seed` to refresh `src/catalog/seed.snapshot.json` (public endpoints, no key) and commit it, so fresh installs start with a usable catalog.
|
|
300
|
+
3. **GitHub Release**: commit and push `main`, then push the tag. `release.yml` runs the tests, `npm pack`s, and uploads the tarball as the release asset.
|
|
301
|
+
4. **npm (trusted publishing / OIDC, no token)**: `.github/workflows/publish-npm.yml` is manual-only and authenticates through GitHub Actions' OIDC — this repository **has no `NPM_TOKEN` and needs none**. Run it with:
|
|
299
302
|
|
|
300
303
|
```sh
|
|
301
304
|
gh workflow run publish-npm --repo dan-ai-studio/dshopencodego -f tag=v<version>
|
package/README.md
CHANGED
|
@@ -95,7 +95,7 @@ DSH 桌面端是 Electron 壳 + 完整的 dsh Web 应用,本插件对它同样
|
|
|
95
95
|
baseURL: https://opencode.ai/inference/go/v1 # 默认值(OpenCode Go 端点)
|
|
96
96
|
# 只能是不带 query / fragment 的 http(s) 地址;写 ?x=1 会在保存配置时被拒
|
|
97
97
|
# 也可指定为 https://opencode.ai/inference/v1(Console 主端点,含按量/免费模型)
|
|
98
|
-
refreshMinutes: 60 # 目录缓存时长,1 ~ 10080(7
|
|
98
|
+
refreshMinutes: 60 # 目录缓存时长,1 ~ 10080(7 天);超过 24 小时未刷新会被视为过期并在后台更新
|
|
99
99
|
streamIdleTimeoutMs: 300000 # 流空闲超时:两次流事件之间的最长静默(毫秒)
|
|
100
100
|
keepAliveTimeoutMs: 600000 # 连接空闲保留:两次请求之间连接留多久(毫秒,1 ~ 1800000)
|
|
101
101
|
# 每次收到回答后重新计时,所以常用时连接不会被断开;
|
|
@@ -151,7 +151,7 @@ API Key 通过 Harness 凭证库提供(引用名 `OPENCODE_GO_API_KEY`),
|
|
|
151
151
|
- **内容拆分**:明细里"请求体"下面跟一行"文本 X /图片 Y"——图片是各去重后附件按 base64 估的占比(单张按路由的编码上限封顶),文本是总数减图片的剩余,两者恒等于请求体总数。图片 dominant 的请求一眼就能看出来。
|
|
152
152
|
- 会话 id **始终完整记录**(它是会话身份,不是凭据;截断后两个会话会读成一个)。
|
|
153
153
|
- 记录的是环形缓冲(超限丢最旧),进程重启即清;页面平时只在打开与手动刷新时读快照,有请求中时每秒自动刷新一次直到结束,没人打开的页面零流量。
|
|
154
|
-
- 凭据永远不进记录:记录器根本不接收请求头参数,只收白名单里的会话 id 与 UA;请求一开始就有一条"请求中"
|
|
154
|
+
- 凭据永远不进记录:记录器根本不接收请求头参数,只收白名单里的会话 id 与 UA;请求一开始就有一条"请求中"占位行(状态列读秒),结束时原位补全为完整记录。失败的请求同样记一条(含错误码)——包括目录解析失败(未知模型)与凭证缺失这类"第一个字节之前"的失败,行里没有用量只有原因;消费者提前终止的流记一条 `ABORTED`,不再无声丢失。
|
|
155
155
|
|
|
156
156
|
**图片**:三个字段各管一层,超限的图片会被明确拒绝,而不是静默降质或丢弃:
|
|
157
157
|
|
|
@@ -198,6 +198,7 @@ API Key 通过 Harness 凭证库提供(引用名 `OPENCODE_GO_API_KEY`),
|
|
|
198
198
|
- 官方**新增**模型 → 下次刷新即出现,协议/容量若不在内置目录中则标为"推断"并可被 `modelProtocols` 覆盖;
|
|
199
199
|
- 官方**下线**模型 → 下次刷新即消失;
|
|
200
200
|
- 内置目录**冻结**在插件版本里,仅影响"怎么调"的推断质量,不影响"有哪些"。
|
|
201
|
+
- **首次安装不等待**:包里带了一份发布时生成的目录快照(`src/catalog/seed.snapshot.json`,28 个模型上下),磁盘缓存为空时直接用它回答并在后台刷新;过期(超 24 小时未刷新)同样后台刷新,绝不为等网络拦住请求。插件挂载后还会定时触发一次,保证长期运行的进程目录常新。
|
|
201
202
|
|
|
202
203
|
网关**临时不可用**时,插件保留上次成功获取的列表并在页面上标注陈旧,同时在后台重试:重试由**5 分钟的退避**控制,而不是等满一个 TTL,所以网关恢复后 5 分钟内列表就会更新;网关持续不可用时,它只被问一次,不会每次模型请求都去问一遍。设置页的「重新检查」随时可以强制重验,不受这个退避限制。
|
|
203
204
|
|
|
@@ -284,17 +285,19 @@ npm run lint # oxlint:静态检查(发布流程也会跑,失败即
|
|
|
284
285
|
npm run typecheck # host 与 client 两半
|
|
285
286
|
npm run build # 先构建:产出 lib/index.js 与 lib/client.js
|
|
286
287
|
npm test # 契约测试:真实 HTTP mock 网关,断言请求头/体、目录阶梯、用量
|
|
288
|
+
npm run seed # 发版前刷新捆绑的目录种子(见「发布」)
|
|
287
289
|
```
|
|
288
290
|
|
|
289
291
|
**顺序有讲究**:`npm run build` 要排在 `npm test` 之前——`tests/pack-contents.spec.ts` 会遍历 `exports` 的每个目标,`lib/` 存在与否决定这条检查是执行还是被跳过(不报错,但会少一层保护)。`package.json` 已移除 `prepare`,因此 `npm ci` 不会再替你隐式构建;三个 CI workflow 都显式跑了 `npm run build`。
|
|
290
292
|
|
|
291
|
-
测试覆盖配置校验、协议阶梯、网关与在线元数据、目录投影、适配器(三种协议的线上请求)、Remote 契约与服务、会话头不变量、用量窗口与计量、客户端控制器与用量组件、两半的挂载与登记、流空闲超时与中止的错误映射、验证脚本的退出码契约、以及几条**结构性不变量**(inject 声明与源码读取一致、peer 覆盖双向、README 与 manifest 一致、README 对上游的断言与实装的上游一致)。共 **
|
|
293
|
+
测试覆盖配置校验、协议阶梯、网关与在线元数据、目录投影、适配器(三种协议的线上请求)、Remote 契约与服务、会话头不变量、用量窗口与计量、客户端控制器与用量组件、两半的挂载与登记、流空闲超时与中止的错误映射、验证脚本的退出码契约、以及几条**结构性不变量**(inject 声明与源码读取一致、peer 覆盖双向、README 与 manifest 一致、README 对上游的断言与实装的上游一致)。共 **60 个测试文件**——这个数字由 `tests/readme-consistency.spec.ts` 对着 `tests/` 目录校验,不会漂移。
|
|
292
294
|
|
|
293
295
|
## 发布(维护者)
|
|
294
296
|
|
|
295
297
|
1. **版本**:把 `package.json` 的 `version` 与即将打出的 tag 对齐(`v<版本>`)。CI 会校验资产名与 tag。
|
|
296
|
-
2.
|
|
297
|
-
3. **
|
|
298
|
+
2. **种子**:运行 `npm run seed` 刷新 `src/catalog/seed.snapshot.json`(公开接口,无需 key)并一并提交,让新装用户开箱即有目录可用。
|
|
299
|
+
3. **GitHub Release**:提交并推送 `main`,打 tag 推送。`release.yml` 会跑测试、`npm pack` 并把 tarball 作为 Release 资产上传。
|
|
300
|
+
4. **npm(Trusted Publishing / OIDC,无需令牌)**:`.github/workflows/publish-npm.yml` 仅手动触发,认证走 GitHub Actions 的 OIDC——本仓库**没有也不需要** `NPM_TOKEN`。运行方式:
|
|
298
301
|
|
|
299
302
|
```sh
|
|
300
303
|
gh workflow run publish-npm --repo dan-ai-studio/dshopencodego -f tag=v<版本>
|
package/lib/client.js
CHANGED
|
@@ -31,6 +31,7 @@ var BACKGROUND_RETRY_BACKOFF_MS = 5 * 6e4;
|
|
|
31
31
|
var MODEL_LISTING_MAX_BYTES = 1024 * 1024;
|
|
32
32
|
var MODEL_METADATA_MAX_BYTES = 16 * 1024 * 1024;
|
|
33
33
|
var UNKNOWN_MODEL_PROBE_COOLDOWN_MS = 5 * 6e4;
|
|
34
|
+
var MAX_CATALOG_STALENESS_MS = 24 * 60 * 6e4;
|
|
34
35
|
|
|
35
36
|
// src/catalog/metadata.ts
|
|
36
37
|
var INPUT_MODALITIES = ["text", "image", "audio", "video", "pdf"];
|