dsh-opencode-go 0.1.13 → 0.1.14
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 +3 -7
- package/README.md +3 -7
- package/docs/verification.md +8 -0
- package/lib/client.js +37 -192
- package/lib/index.js +10 -3
- package/lib/types/client/UsagePill.d.ts +0 -2
- package/lib/types/client/locales.d.ts +0 -11
- package/lib/types/conversion/context.d.ts +1 -1
- package/package.json +1 -1
- package/lib/types/client/SessionCache.d.ts +0 -6
- package/lib/types/client/session-cache.d.ts +0 -18
package/README.en.md
CHANGED
|
@@ -36,7 +36,7 @@ If your DSH version does not have an **Add plugin** entry, use the command-line
|
|
|
36
36
|
### Command-line installation (alternative)
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
dsh plugin --profile web add dsh-opencode-go@0.1.
|
|
39
|
+
dsh plugin --profile web add dsh-opencode-go@0.1.14
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Start or restart `dsh web`, then:
|
|
@@ -50,7 +50,7 @@ Start or restart `dsh web`, then:
|
|
|
50
50
|
Install the plugin into the Headless profile:
|
|
51
51
|
|
|
52
52
|
```sh
|
|
53
|
-
dsh plugin --profile headless add dsh-opencode-go@0.1.
|
|
53
|
+
dsh plugin --profile headless add dsh-opencode-go@0.1.14
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Save the following as `headless.patch.yml` to select a default model:
|
|
@@ -77,7 +77,7 @@ To build from source and install a local package:
|
|
|
77
77
|
```sh
|
|
78
78
|
npm ci --legacy-peer-deps
|
|
79
79
|
npm pack
|
|
80
|
-
dsh plugin --profile web add ./dsh-opencode-go-0.1.
|
|
80
|
+
dsh plugin --profile web add ./dsh-opencode-go-0.1.14.tgz
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
The development dependencies include real test packages from multiple DSH generations, so installation requires `--legacy-peer-deps`. For Headless, replace `web` with `headless`.
|
|
@@ -96,10 +96,6 @@ Restart `dsh web` and refresh the browser afterwards. For Headless, replace `web
|
|
|
96
96
|
|
|
97
97
|
Usage refreshes every minute. Temporary network or service errors retain the last reading for the same account, with a failure notice, timestamp, and reason; the usage panel offers an immediate retry. Initial and authentication failures do not show old usage. Catalog, metadata, and usage JSON requests retry a transient connection reset once within the original timeout budget; this cannot guarantee recovery while the network is failing.
|
|
98
98
|
|
|
99
|
-
The usage panel also shows the current session's cached input share, cache read/write tokens, total input tokens, and measured response count. The formula is `cacheReadTokens / (inputTokens + cacheReadTokens + cacheWriteTokens)`, weighted by tokens and excluding output tokens. Statistics are derived from the Host's loaded session history, can be reconstructed after session restore, and add no network requests. The panel subscribes only while open. Account usage failures do not affect these statistics.
|
|
100
|
-
|
|
101
|
-
Only settled Go responses with an identifiable route and valid usage are counted. Unsettled attempts and inherited fork responses are excluded; missing route/usage and incomplete history are indicated. Older Hosts without a session event feed continue to show account usage. A stable `x-opencode-session` supports routing affinity but does not establish a cache hit; actual cache reads are reported by the gateway.
|
|
102
|
-
|
|
103
99
|

|
|
104
100
|
|
|
105
101
|
## Interface language
|
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
### 命令行安装(备选)
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
dsh plugin --profile web add dsh-opencode-go@0.1.
|
|
39
|
+
dsh plugin --profile web add dsh-opencode-go@0.1.14
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
安装后启动或重启 `dsh web`,然后:
|
|
@@ -50,7 +50,7 @@ dsh plugin --profile web add dsh-opencode-go@0.1.13
|
|
|
50
50
|
安装到 Headless profile:
|
|
51
51
|
|
|
52
52
|
```sh
|
|
53
|
-
dsh plugin --profile headless add dsh-opencode-go@0.1.
|
|
53
|
+
dsh plugin --profile headless add dsh-opencode-go@0.1.14
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
将以下内容保存为 `headless.patch.yml`,选择默认模型:
|
|
@@ -77,7 +77,7 @@ dsh --profile headless --patch ./headless.patch.yml "你好"
|
|
|
77
77
|
```sh
|
|
78
78
|
npm ci --legacy-peer-deps
|
|
79
79
|
npm pack
|
|
80
|
-
dsh plugin --profile web add ./dsh-opencode-go-0.1.
|
|
80
|
+
dsh plugin --profile web add ./dsh-opencode-go-0.1.14.tgz
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
开发依赖包含多代 DSH 的真实测试包,安装时需要 `--legacy-peer-deps`。Headless 用户将 `web` 换成 `headless`。
|
|
@@ -96,10 +96,6 @@ dsh plugin --profile web update dsh-opencode-go --latest
|
|
|
96
96
|
|
|
97
97
|
用量每分钟刷新。临时网络或服务错误会保留同一账号的上次数据,并标明刷新失败、更新时间和错误原因;可在用量弹层中立即重试。首次获取失败或鉴权失败时不显示旧额度。模型目录、模型配置和用量的 JSON 请求遇到短暂连接重置时会在原有超时范围内额外重试一次;这不能保证故障中的网络恢复可用。
|
|
98
98
|
|
|
99
|
-
用量弹层还会显示当前会话的缓存读取比例、缓存读取/写入 tokens、总输入 tokens 和已统计响应数。计算公式为 `cacheReadTokens / (inputTokens + cacheReadTokens + cacheWriteTokens)`,按 tokens 加权,不包含输出 tokens。数据来自宿主已加载的会话历史,恢复会话后可重新计算,不增加网络请求;仅打开弹层时订阅更新。账号额度读取失败不影响这些统计。
|
|
100
|
-
|
|
101
|
-
统计只包含可确定路由且有有效用量的 Go 已结算响应,排除未结算请求和分叉继承的响应;缺少路由或用量的响应会注明未统计,历史未加载完整时也会提示。不支持会话事件接口的旧宿主继续显示账号额度。稳定的 `x-opencode-session` 只支持路由保持一致,不能证明缓存命中;实际读取量由网关报告。
|
|
102
|
-
|
|
103
99
|

|
|
104
100
|
|
|
105
101
|
## 界面语言
|
package/docs/verification.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Verification
|
|
2
2
|
|
|
3
|
+
## Account usage panel and unsupported-history guards (plugin 0.1.14, 2026-09-26)
|
|
4
|
+
|
|
5
|
+
The OpenCode Go usage panel again shows only the account's rolling, weekly, and monthly limits. Session cache statistics introduced in 0.1.13 have been removed, including their event subscription, component, styles, and translations; token statistics remain available in DSH's own interface. The original account polling, refresh failure handling, and retry behavior are retained. This supersedes the session-cache panel behavior described in the earlier verification entry below.
|
|
6
|
+
|
|
7
|
+
PR #11 adds explicit `UNSUPPORTED_CONTENT` errors for developer-role history, tool-addition/tool-removal blocks, and tools with `deferLoading: true`, on both text-only and image conversion paths. Existing image-role validation and normal tool conversion are retained. These guards are preventive hardening for inputs the adapter cannot represent; no known production source for those inputs was reproduced. Dependencies and the minimum Host version are unchanged.
|
|
8
|
+
|
|
9
|
+
Validation: `npm test` on the combined release changes passed both TypeScript checks, the production build, and **323 tests in 23 files**, including the existing Host compatibility and distributed client fixtures. Additional in-memory checks of PR #11 passed 15 scenarios on both conversion paths, covering tool-removal, empty history with deferred tools, ordinary tools, and `deferLoading: false`. The published UI dependencies still emit their existing missing-source-map warnings. These checks use local fixtures; no installed-profile update or live inference was performed.
|
|
10
|
+
|
|
3
11
|
## Issue #14: distinguish unavailable metadata from missing model configuration (2026-09-26)
|
|
4
12
|
|
|
5
13
|
The existing source diagnostics now drive a specific Settings warning when model configuration fails while the gateway listing succeeds, including an empty successful listing. Unconfigured models show “Configuration unavailable” during a metadata-source failure and explain how to check connectivity from the machine running DSH. A retained model list keeps its warning and source details visible while retrying. Successful metadata recovery clears the warning; models still absent from usable metadata return to “Configuration missing”, and models with newly usable configuration become selectable.
|
package/lib/client.js
CHANGED
|
@@ -130,16 +130,16 @@ var modelsRemote = {
|
|
|
130
130
|
}]
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
-
// plugin-css:/
|
|
133
|
+
// plugin-css:/Users/tanglei/.codex/worktrees/release-0-1-14/dsh-opencode-go/src/client/Section.module.css
|
|
134
134
|
var id = "dsh-opencode-go/Section.module.css";
|
|
135
135
|
if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")) {
|
|
136
136
|
const style = document.createElement("style");
|
|
137
137
|
style.dataset.plugin = "dsh-opencode-go";
|
|
138
138
|
style.dataset.pluginCss = id;
|
|
139
|
-
style.textContent = '.
|
|
139
|
+
style.textContent = '.LKs06q_page{flex-direction:column;min-width:0;height:100%;min-height:0;display:flex;container-type:size}.LKs06q_pageBody{scrollbar-gutter:stable;flex:1;min-height:0;padding-right:4px;overflow-y:auto}.LKs06q_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.LKs06q_field+.LKs06q_field{border-top:.5px solid var(--dsw-alias-border-l2)}.LKs06q_head{align-items:center;gap:8px;display:flex}.LKs06q_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.LKs06q_badges{align-items:center;gap:8px;display:inline-flex}.LKs06q_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}.LKs06q_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.LKs06q_reset:disabled{cursor:default}.LKs06q_reset:focus-visible,.LKs06q_disclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.LKs06q_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}.LKs06q_input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px;border-color:var(--dsw-alias-brand-primary)}.LKs06q_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.LKs06q_inputInvalid{border-color:var(--dsw-alias-label-error);}.LKs06q_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.LKs06q_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.LKs06q_intro{color:var(--dsw-alias-label-secondary);margin:0 0 8px;font-size:13px;line-height:1.5}.LKs06q_disclosure{font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;margin:0;padding:0;display:flex}.LKs06q_disclosure:hover .LKs06q_label{color:var(--dsw-alias-brand-primary)}.LKs06q_chevron,.LKs06q_chevronOpen{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none}.LKs06q_chevron{transform:rotate(-90deg)}.LKs06q_advanced{flex-direction:column;gap:4px;padding:4px 0 0 22px;display:flex}.LKs06q_advanced .LKs06q_field+.LKs06q_field{border-top:none}.LKs06q_chips{flex-wrap:wrap;gap:6px;display:flex}.LKs06q_limitsEditor{flex-direction:column;gap:10px;padding-top:4px;display:flex}.LKs06q_limitsToolbar{grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:6px 10px;display:grid}.LKs06q_limitsFilterLabel{color:var(--dsw-alias-label-secondary);grid-column:1/-1;font-size:12px;font-weight:500;line-height:1.5}.LKs06q_limitsSummary{color:var(--dsw-alias-label-tertiary);white-space:nowrap;padding-bottom:8px;font-size:12px;line-height:1.5}.LKs06q_limitsId,.LKs06q_limitsModelId{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}.LKs06q_limitsId{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.4}.LKs06q_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}.LKs06q_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){.LKs06q_limitsToolbar{grid-template-columns:1fr}.LKs06q_limitsSummary{padding-bottom:0}}.LKs06q_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}.LKs06q_starLink{max-width:100%;color:var(--dsw-alias-label-secondary);border-radius:4px;align-items:center;gap:7px;margin-left:auto;padding:6px 0;font-size:12px;line-height:1.5;text-decoration:none;display:inline-flex}.LKs06q_starLink svg{flex:none}.LKs06q_starLink:hover{color:var(--dsw-alias-brand-primary)}.LKs06q_starLink:hover span{text-underline-offset:3px;text-decoration:underline}.LKs06q_starLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.LKs06q_failedNote{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.LKs06q_pageTop{align-items:flex-start;gap:16px;display:flex}.LKs06q_pageTop .LKs06q_intro{flex:1}.LKs06q_advancedTrigger{flex-shrink:0;margin-left:auto;}.LKs06q_advancedTrigger .LKs06q_label{color:var(--dsw-alias-label-tertiary);font-size:12px}.LKs06q_filters{flex-wrap:wrap;gap:6px;display:flex}.LKs06q_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}.LKs06q_filter[aria-pressed=true]{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3)}.LKs06q_filter span{color:var(--dsw-alias-label-tertiary);margin-left:4px}.LKs06q_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}.LKs06q_modelList{border-right:.5px solid var(--dsw-alias-border-l2);min-height:0;padding:6px;overflow-y:auto}.LKs06q_modelRow{align-items:center;gap:8px;padding-right:6px;display:flex}.LKs06q_modelRow>[role=switch]{flex-shrink:0}.LKs06q_modelChoice{text-align:left;min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:1;padding:12px 9px;display:block}.LKs06q_modelChoice[aria-pressed=true],.LKs06q_modelChoice:hover{background:var(--dsw-alias-bg-layer-3)}.LKs06q_modelName{overflow-wrap:anywhere;flex-wrap:wrap;align-items:center;gap:5px;font-size:13px;display:flex}.LKs06q_modelDetails{flex-direction:column;align-items:stretch;gap:10px;min-width:0;padding:18px;display:flex;overflow-y:auto}.LKs06q_modelDetails h3{overflow-wrap:anywhere;margin:0;font-size:16px}.LKs06q_modelHeading{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.LKs06q_modelDetails .LKs06q_field{border:0;padding:8px 0}.LKs06q_modelDetails .LKs06q_input{box-sizing:border-box;width:100%;min-width:0}.LKs06q_modelDetails .LKs06q_reset{align-self:flex-start}.LKs06q_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}.LKs06q_releaseDate{color:var(--dsw-alias-label-tertiary);margin-top:4px;font-size:10px;display:block}.LKs06q_modelChoice:focus-visible,.LKs06q_filter:focus-visible,.LKs06q_advancedTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}@container (width<=440px){.LKs06q_pageTop{flex-wrap:wrap}.LKs06q_modelLayout{grid-template-columns:minmax(0,1fr);height:auto}.LKs06q_modelList{border-right:0;border-bottom:.5px solid var(--dsw-alias-border-l2);max-height:240px}.LKs06q_modelDetails{max-height:460px}}.LKs06q_keySection{border-top:.5px solid var(--dsw-alias-border-l2);padding:12px 0}.LKs06q_keySection summary{cursor:pointer;list-style:none}.LKs06q_keySection summary:after{content:"\u2304";color:var(--dsw-alias-label-tertiary)}.LKs06q_keySection summary::-webkit-details-marker{display:none}.LKs06q_keySection>.LKs06q_input{box-sizing:border-box;width:100%;margin:10px 0 6px}.LKs06q_keySection summary:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}';
|
|
140
140
|
document.head.appendChild(style);
|
|
141
141
|
}
|
|
142
|
-
var Section_default = { "
|
|
142
|
+
var Section_default = { "field": "LKs06q_field", "head": "LKs06q_head", "chevron": "LKs06q_chevron", "label": "LKs06q_label", "inputInvalid": "LKs06q_inputInvalid LKs06q_input", "chevronOpen": "LKs06q_chevronOpen", "chips": "LKs06q_chips", "badges": "LKs06q_badges", "actions": "LKs06q_actions", "modelRow": "LKs06q_modelRow", "pageBody": "LKs06q_pageBody", "visuallyHidden": "LKs06q_visuallyHidden", "advancedTrigger": "LKs06q_advancedTrigger LKs06q_disclosure", "pageTop": "LKs06q_pageTop", "filters": "LKs06q_filters", "newBadge": "LKs06q_newBadge", "limitsModelId": "LKs06q_limitsModelId", "releaseDate": "LKs06q_releaseDate", "hint": "LKs06q_hint", "limitsToolbar": "LKs06q_limitsToolbar", "input": "LKs06q_input", "limitsId": "LKs06q_limitsId", "starLink": "LKs06q_starLink", "modelName": "LKs06q_modelName", "invalid": "LKs06q_invalid", "limitsFilterLabel": "LKs06q_limitsFilterLabel", "limitsSummary": "LKs06q_limitsSummary", "modelLayout": "LKs06q_modelLayout", "modelDetails": "LKs06q_modelDetails", "modelHeading": "LKs06q_modelHeading", "keySection": "LKs06q_keySection", "advanced": "LKs06q_advanced", "failedNote": "LKs06q_failedNote", "filter": "LKs06q_filter", "reset": "LKs06q_reset", "intro": "LKs06q_intro", "limitsEditor": "LKs06q_limitsEditor", "modelList": "LKs06q_modelList", "modelChoice": "LKs06q_modelChoice", "page": "LKs06q_page", "disclosure": "LKs06q_disclosure" };
|
|
143
143
|
|
|
144
144
|
// src/client/ModelEditor.tsx
|
|
145
145
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -1229,17 +1229,6 @@ function refOf(snapshot) {
|
|
|
1229
1229
|
|
|
1230
1230
|
// src/client/locales.ts
|
|
1231
1231
|
var en = {
|
|
1232
|
-
cacheTitle: "Session cache reads",
|
|
1233
|
-
cacheReadRatio: "Cached input share",
|
|
1234
|
-
cacheReadTokens: "Cache read tokens",
|
|
1235
|
-
cacheInputTokens: "Total input tokens",
|
|
1236
|
-
cacheWriteTokens: "Cache write tokens",
|
|
1237
|
-
cacheResponses: "Measured responses",
|
|
1238
|
-
cacheEmpty: "No usable Go response usage in the loaded history yet.",
|
|
1239
|
-
cacheExcluded: "Responses excluded for missing route or usage:",
|
|
1240
|
-
cacheScope: "Settled Go responses in loaded history. Inherited fork responses and unsettled attempts are excluded.",
|
|
1241
|
-
cacheMore: "Older history is not fully loaded.",
|
|
1242
|
-
cacheRoutingHint: "A stable session header supports routing affinity. Cache reads are reported separately by the gateway and may remain zero.",
|
|
1243
1232
|
usageTitle: "OpenCode Go usage",
|
|
1244
1233
|
usageRollingShort: "5h",
|
|
1245
1234
|
usageHint: "Account usage \xB7 used percentage \xB7 refreshes every minute",
|
|
@@ -1348,17 +1337,6 @@ var en = {
|
|
|
1348
1337
|
unavailable: "The OpenCode Go settings are not served in this deployment."
|
|
1349
1338
|
};
|
|
1350
1339
|
var zh = {
|
|
1351
|
-
cacheTitle: "\u4F1A\u8BDD\u7F13\u5B58\u8BFB\u53D6",
|
|
1352
|
-
cacheReadRatio: "\u7F13\u5B58\u8BFB\u53D6\u5360\u8F93\u5165\u6BD4\u4F8B",
|
|
1353
|
-
cacheReadTokens: "\u7F13\u5B58\u8BFB\u53D6 tokens",
|
|
1354
|
-
cacheInputTokens: "\u603B\u8F93\u5165 tokens",
|
|
1355
|
-
cacheWriteTokens: "\u7F13\u5B58\u5199\u5165 tokens",
|
|
1356
|
-
cacheResponses: "\u5DF2\u7EDF\u8BA1\u54CD\u5E94\u6570",
|
|
1357
|
-
cacheEmpty: "\u5DF2\u52A0\u8F7D\u5386\u53F2\u4E2D\u6682\u65E0\u53EF\u7528\u7684 Go \u54CD\u5E94\u7528\u91CF\u3002",
|
|
1358
|
-
cacheExcluded: "\u56E0\u7F3A\u5C11\u8DEF\u7531\u6216\u7528\u91CF\u800C\u672A\u7EDF\u8BA1\u7684\u54CD\u5E94\uFF1A",
|
|
1359
|
-
cacheScope: "\u7EDF\u8BA1\u5DF2\u52A0\u8F7D\u5386\u53F2\u4E2D\u7684 Go \u5DF2\u7ED3\u7B97\u54CD\u5E94\uFF0C\u6392\u9664\u5206\u53C9\u7EE7\u627F\u7684\u54CD\u5E94\u53CA\u672A\u7ED3\u7B97\u7684\u8BF7\u6C42\u3002",
|
|
1360
|
-
cacheMore: "\u66F4\u65E9\u7684\u5386\u53F2\u5C1A\u672A\u5168\u90E8\u52A0\u8F7D\u3002",
|
|
1361
|
-
cacheRoutingHint: "\u7A33\u5B9A\u7684\u4F1A\u8BDD\u6807\u8BC6\u6709\u52A9\u4E8E\u8DEF\u7531\u4FDD\u6301\u4E00\u81F4\uFF1B\u5B9E\u9645\u7F13\u5B58\u8BFB\u53D6\u91CF\u7531\u7F51\u5173\u53E6\u884C\u62A5\u544A\uFF0C\u4ECD\u53EF\u80FD\u4E3A\u96F6\u3002",
|
|
1362
1340
|
usageTitle: "OpenCode Go \u7528\u91CF",
|
|
1363
1341
|
usageRollingShort: "5\u5C0F\u65F6",
|
|
1364
1342
|
usageHint: "\u8D26\u53F7\u989D\u5EA6 \xB7 \u5DF2\u7528\u767E\u5206\u6BD4 \xB7 \u6BCF\u5206\u949F\u5237\u65B0",
|
|
@@ -1513,152 +1491,21 @@ var goRemote = {
|
|
|
1513
1491
|
};
|
|
1514
1492
|
|
|
1515
1493
|
// src/client/UsagePill.tsx
|
|
1516
|
-
var import_react4 = require("react");
|
|
1517
|
-
|
|
1518
|
-
// src/client/SessionCache.tsx
|
|
1519
1494
|
var import_react3 = require("react");
|
|
1520
1495
|
|
|
1521
|
-
// src/client/
|
|
1522
|
-
function record(value) {
|
|
1523
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
1524
|
-
}
|
|
1525
|
-
function tokens(value) {
|
|
1526
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
1527
|
-
}
|
|
1528
|
-
function sessionEventSource(sessions, sessionId) {
|
|
1529
|
-
const service = record(sessions);
|
|
1530
|
-
if (typeof service?.binding !== "function") return void 0;
|
|
1531
|
-
const source = record(record(service.binding(sessionId))?.eventSource);
|
|
1532
|
-
if (typeof source?.getSnapshot !== "function" || typeof source.subscribe !== "function") return void 0;
|
|
1533
|
-
const getSnapshot = source.getSnapshot.bind(source);
|
|
1534
|
-
const subscribe = source.subscribe.bind(source);
|
|
1535
|
-
return {
|
|
1536
|
-
getSnapshot: () => getSnapshot(),
|
|
1537
|
-
subscribe: (listener) => subscribe(listener)
|
|
1538
|
-
};
|
|
1539
|
-
}
|
|
1540
|
-
function summarizeSessionCache(window) {
|
|
1541
|
-
const snapshot = record(window);
|
|
1542
|
-
let stats = {
|
|
1543
|
-
responses: 0,
|
|
1544
|
-
missingUsage: 0,
|
|
1545
|
-
unattributed: 0,
|
|
1546
|
-
inputTokens: 0,
|
|
1547
|
-
cacheReadTokens: 0,
|
|
1548
|
-
cacheWriteTokens: 0,
|
|
1549
|
-
hasMore: snapshot?.hasMore === true
|
|
1550
|
-
};
|
|
1551
|
-
let provider;
|
|
1552
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1553
|
-
for (const entry of Array.isArray(snapshot?.entries) ? snapshot.entries : []) {
|
|
1554
|
-
const row = record(entry);
|
|
1555
|
-
const event = record(row?.event);
|
|
1556
|
-
if (row?.type !== "event" || !event || !tokens(event.seq) || seen.has(event.seq)) continue;
|
|
1557
|
-
seen.add(event.seq);
|
|
1558
|
-
const data = record(event.data);
|
|
1559
|
-
if (event.type === "request/header") provider = record(record(data?.header)?.config)?.provider;
|
|
1560
|
-
if (event.type === "session/end-seed" && data?.inherited === true) {
|
|
1561
|
-
stats = {
|
|
1562
|
-
...stats,
|
|
1563
|
-
responses: 0,
|
|
1564
|
-
missingUsage: 0,
|
|
1565
|
-
unattributed: 0,
|
|
1566
|
-
inputTokens: 0,
|
|
1567
|
-
cacheReadTokens: 0,
|
|
1568
|
-
cacheWriteTokens: 0
|
|
1569
|
-
};
|
|
1570
|
-
}
|
|
1571
|
-
if (event.type !== "assistant/message") continue;
|
|
1572
|
-
if (provider === void 0) {
|
|
1573
|
-
stats.unattributed++;
|
|
1574
|
-
continue;
|
|
1575
|
-
}
|
|
1576
|
-
if (provider !== "opencode-go") continue;
|
|
1577
|
-
const usage = record(data?.usage);
|
|
1578
|
-
const input = usage?.inputTokens;
|
|
1579
|
-
const read = usage?.cacheReadTokens === void 0 ? 0 : usage.cacheReadTokens;
|
|
1580
|
-
const write = usage?.cacheWriteTokens === void 0 ? 0 : usage.cacheWriteTokens;
|
|
1581
|
-
if (!tokens(input) || !tokens(read) || !tokens(write) || !Number.isSafeInteger(stats.inputTokens + input + read + write)) {
|
|
1582
|
-
stats.missingUsage++;
|
|
1583
|
-
continue;
|
|
1584
|
-
}
|
|
1585
|
-
stats.responses++;
|
|
1586
|
-
stats.inputTokens += input + read + write;
|
|
1587
|
-
stats.cacheReadTokens += read;
|
|
1588
|
-
stats.cacheWriteTokens += write;
|
|
1589
|
-
}
|
|
1590
|
-
return stats;
|
|
1591
|
-
}
|
|
1592
|
-
function sessionCacheSource(events) {
|
|
1593
|
-
let window;
|
|
1594
|
-
let value;
|
|
1595
|
-
return {
|
|
1596
|
-
subscribe: (listener) => events.subscribe(listener),
|
|
1597
|
-
getSnapshot: () => {
|
|
1598
|
-
const next = events.getSnapshot();
|
|
1599
|
-
if (value !== void 0 && next === window) return value;
|
|
1600
|
-
const previous = record(window);
|
|
1601
|
-
window = next;
|
|
1602
|
-
const current = record(next);
|
|
1603
|
-
const change = record(current?.change);
|
|
1604
|
-
if (value !== void 0 && typeof previous?.revision === "number" && current?.revision === previous.revision + 1 && change?.kind === "append" && Array.isArray(change.entries) && change.entries.every((entry) => record(entry)?.type === "transient")) return value;
|
|
1605
|
-
const stats = summarizeSessionCache(next);
|
|
1606
|
-
if (value === void 0 || Object.keys(stats).some((key) => stats[key] !== value[key])) value = stats;
|
|
1607
|
-
return value;
|
|
1608
|
-
}
|
|
1609
|
-
};
|
|
1610
|
-
}
|
|
1611
|
-
|
|
1612
|
-
// plugin-css:/private/var/folders/4z/q9yrksqd0y12spqrxkv0p_dm0000gn/T/dsh-release-0.1.13-Tf3MEL/source/src/client/UsagePill.module.css
|
|
1496
|
+
// plugin-css:/Users/tanglei/.codex/worktrees/release-0-1-14/dsh-opencode-go/src/client/UsagePill.module.css
|
|
1613
1497
|
var id2 = "dsh-opencode-go/UsagePill.module.css";
|
|
1614
1498
|
if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]")) {
|
|
1615
1499
|
const style = document.createElement("style");
|
|
1616
1500
|
style.dataset.plugin = "dsh-opencode-go";
|
|
1617
1501
|
style.dataset.pluginCss = id2;
|
|
1618
|
-
style.textContent = ".
|
|
1502
|
+
style.textContent = ".XD2TAq_root{min-width:0;display:inline-flex;position:relative}.XD2TAq_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}.XD2TAq_trigger:hover,.XD2TAq_trigger:focus-visible{opacity:1;background:color-mix(in srgb, currentColor 8%, transparent)}.XD2TAq_panel{z-index:100;box-sizing:border-box;border:1px solid color-mix(in srgb, currentColor 18%, transparent);width:280px;max-width:calc(100vw - 32px);max-height:70vh;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;overflow-y:auto;box-shadow:0 8px 30px #0002}.XD2TAq_hint{opacity:.65;font-size:11px;line-height:1.6}.XD2TAq_warning{background:color-mix(in srgb, currentColor 6%, transparent);overflow-wrap:anywhere;border-radius:6px;margin:10px 0;padding:10px;line-height:1.5}.XD2TAq_warning p{margin:5px 0 0}.XD2TAq_retry{border:1px solid color-mix(in srgb, currentColor 25%, transparent);color:inherit;font:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:5px 9px}.XD2TAq_retry:disabled{opacity:.6;cursor:default}.XD2TAq_retry:focus-visible{outline-offset:2px;outline:2px solid}.XD2TAq_window{margin-top:14px}.XD2TAq_row{justify-content:space-between;margin-bottom:5px;display:flex}.XD2TAq_window progress{appearance:none;background:color-mix(in srgb, currentColor 15%, transparent);border:0;border-radius:4px;width:100%;height:5px;margin-bottom:5px;display:block}.XD2TAq_window progress::-webkit-progress-bar{background:0 0;border-radius:4px}.XD2TAq_window progress::-webkit-progress-value{background:#39a878;border-radius:4px}.XD2TAq_window progress::-moz-progress-bar{background:#39a878;border-radius:4px}";
|
|
1619
1503
|
document.head.appendChild(style);
|
|
1620
1504
|
}
|
|
1621
|
-
var UsagePill_default = { "
|
|
1622
|
-
|
|
1623
|
-
// src/client/SessionCache.tsx
|
|
1624
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1625
|
-
function SessionCache({ events, t, getLocale }) {
|
|
1626
|
-
const source = (0, import_react3.useMemo)(() => sessionCacheSource(events), [events]);
|
|
1627
|
-
const stats = (0, import_react3.useSyncExternalStore)(source.subscribe, source.getSnapshot, source.getSnapshot);
|
|
1628
|
-
const format = new Intl.NumberFormat(getLocale?.());
|
|
1629
|
-
const ratio = stats.inputTokens > 0 ? new Intl.NumberFormat(getLocale?.(), { style: "percent", maximumFractionDigits: 1 }).format(stats.cacheReadTokens / stats.inputTokens) : "\u2014";
|
|
1630
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: UsagePill_default.cache, "aria-label": t("cacheTitle"), children: [
|
|
1631
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: t("cacheTitle") }),
|
|
1632
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.row, children: [
|
|
1633
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t("cacheReadRatio") }),
|
|
1634
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: ratio })
|
|
1635
|
-
] }),
|
|
1636
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("dl", { className: UsagePill_default.stats, children: [
|
|
1637
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("dt", { children: t("cacheReadTokens") }),
|
|
1638
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("dd", { children: format.format(stats.cacheReadTokens) }),
|
|
1639
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("dt", { children: t("cacheInputTokens") }),
|
|
1640
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("dd", { children: format.format(stats.inputTokens) }),
|
|
1641
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("dt", { children: t("cacheWriteTokens") }),
|
|
1642
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("dd", { children: format.format(stats.cacheWriteTokens) }),
|
|
1643
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("dt", { children: t("cacheResponses") }),
|
|
1644
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("dd", { children: format.format(stats.responses) })
|
|
1645
|
-
] }),
|
|
1646
|
-
stats.responses === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: UsagePill_default.hint, children: t("cacheEmpty") }),
|
|
1647
|
-
stats.missingUsage + stats.unattributed > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: UsagePill_default.hint, children: [
|
|
1648
|
-
t("cacheExcluded"),
|
|
1649
|
-
" ",
|
|
1650
|
-
format.format(stats.missingUsage + stats.unattributed)
|
|
1651
|
-
] }),
|
|
1652
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: UsagePill_default.hint, children: [
|
|
1653
|
-
t("cacheScope"),
|
|
1654
|
-
stats.hasMore ? ` ${t("cacheMore")}` : ""
|
|
1655
|
-
] }),
|
|
1656
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: UsagePill_default.hint, children: t("cacheRoutingHint") })
|
|
1657
|
-
] });
|
|
1658
|
-
}
|
|
1505
|
+
var UsagePill_default = { "root": "XD2TAq_root", "hint": "XD2TAq_hint", "window": "XD2TAq_window", "trigger": "XD2TAq_trigger", "panel": "XD2TAq_panel", "warning": "XD2TAq_warning", "row": "XD2TAq_row", "retry": "XD2TAq_retry" };
|
|
1659
1506
|
|
|
1660
1507
|
// src/client/UsagePill.tsx
|
|
1661
|
-
var
|
|
1508
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1662
1509
|
function usageFailure(error) {
|
|
1663
1510
|
if (error && typeof error === "object" && "code" in error && error.code === "opencode-go/usage-unavailable" && "details" in error && error.details && typeof error.details === "object") {
|
|
1664
1511
|
const details = error.details;
|
|
@@ -1671,18 +1518,18 @@ function usageFailure(error) {
|
|
|
1671
1518
|
return { retainPrevious: false };
|
|
1672
1519
|
}
|
|
1673
1520
|
function UsagePill({ directory, ...props }) {
|
|
1674
|
-
const state = (0,
|
|
1675
|
-
return state.current?.provider === "opencode-go" ? /* @__PURE__ */ (0,
|
|
1521
|
+
const state = (0, import_react3.useSyncExternalStore)(directory.subscribe, directory.getSnapshot, directory.getSnapshot);
|
|
1522
|
+
return state.current?.provider === "opencode-go" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ActiveUsage, { ...props }) : null;
|
|
1676
1523
|
}
|
|
1677
|
-
function ActiveUsage({ readUsage, t, getLocale
|
|
1678
|
-
const [snapshot, setSnapshot] = (0,
|
|
1679
|
-
const [failed, setFailed] = (0,
|
|
1680
|
-
const [refreshing, setRefreshing] = (0,
|
|
1681
|
-
const [open, setOpen] = (0,
|
|
1682
|
-
const root = (0,
|
|
1683
|
-
const retry = (0,
|
|
1524
|
+
function ActiveUsage({ readUsage, t, getLocale }) {
|
|
1525
|
+
const [snapshot, setSnapshot] = (0, import_react3.useState)(null);
|
|
1526
|
+
const [failed, setFailed] = (0, import_react3.useState)(null);
|
|
1527
|
+
const [refreshing, setRefreshing] = (0, import_react3.useState)(false);
|
|
1528
|
+
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
1529
|
+
const root = (0, import_react3.useRef)(null);
|
|
1530
|
+
const retry = (0, import_react3.useRef)(() => {
|
|
1684
1531
|
});
|
|
1685
|
-
(0,
|
|
1532
|
+
(0, import_react3.useEffect)(() => {
|
|
1686
1533
|
let alive = true;
|
|
1687
1534
|
let busy = false;
|
|
1688
1535
|
setSnapshot(null);
|
|
@@ -1728,7 +1575,7 @@ function ActiveUsage({ readUsage, t, getLocale, sessionEvents }) {
|
|
|
1728
1575
|
document.removeEventListener("visibilitychange", visible);
|
|
1729
1576
|
};
|
|
1730
1577
|
}, [readUsage]);
|
|
1731
|
-
(0,
|
|
1578
|
+
(0, import_react3.useEffect)(() => {
|
|
1732
1579
|
if (!open) return;
|
|
1733
1580
|
const click = (event) => {
|
|
1734
1581
|
if (!root.current?.contains(event.target)) setOpen(false);
|
|
@@ -1747,8 +1594,8 @@ function ActiveUsage({ readUsage, t, getLocale, sessionEvents }) {
|
|
|
1747
1594
|
const usage = current?.usage;
|
|
1748
1595
|
const failure = failed?.reader === readUsage ? failed.failure : null;
|
|
1749
1596
|
const label = usage ? `Go \xB7 ${t("usageRollingShort")} ${usage.rolling.percent}% \xB7 ${t("usageWeekShort")} ${usage.weekly.percent}%${failure ? ` \xB7 ${t("usageStaleShort")}` : ""}` : `Go \xB7 ${failure ? t("usageUnavailable") : "\u2026"}`;
|
|
1750
|
-
return /* @__PURE__ */ (0,
|
|
1751
|
-
/* @__PURE__ */ (0,
|
|
1597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: UsagePill_default.root, ref: root, children: [
|
|
1598
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1752
1599
|
"button",
|
|
1753
1600
|
{
|
|
1754
1601
|
type: "button",
|
|
@@ -1762,15 +1609,15 @@ function ActiveUsage({ readUsage, t, getLocale, sessionEvents }) {
|
|
|
1762
1609
|
children: label
|
|
1763
1610
|
}
|
|
1764
1611
|
),
|
|
1765
|
-
open && /* @__PURE__ */ (0,
|
|
1766
|
-
/* @__PURE__ */ (0,
|
|
1767
|
-
/* @__PURE__ */ (0,
|
|
1768
|
-
failure ? /* @__PURE__ */ (0,
|
|
1769
|
-
/* @__PURE__ */ (0,
|
|
1770
|
-
/* @__PURE__ */ (0,
|
|
1771
|
-
usage ? /* @__PURE__ */ (0,
|
|
1612
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.panel, role: "dialog", "aria-label": t("usageTitle"), "aria-busy": refreshing, children: [
|
|
1613
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: t("usageTitle") }),
|
|
1614
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: UsagePill_default.hint, children: t("usageHint") }),
|
|
1615
|
+
failure ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.warning, role: "alert", children: [
|
|
1616
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: t("usageRefreshFailed") }),
|
|
1617
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: failure.message ?? t("usageUnavailable") }),
|
|
1618
|
+
usage ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: t("usageStaleHint") }) : null
|
|
1772
1619
|
] }) : null,
|
|
1773
|
-
failure ? /* @__PURE__ */ (0,
|
|
1620
|
+
failure ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1774
1621
|
"button",
|
|
1775
1622
|
{
|
|
1776
1623
|
type: "button",
|
|
@@ -1782,28 +1629,27 @@ function ActiveUsage({ readUsage, t, getLocale, sessionEvents }) {
|
|
|
1782
1629
|
children: t(refreshing ? "usageRefreshing" : "usageRetry")
|
|
1783
1630
|
}
|
|
1784
1631
|
) : null,
|
|
1785
|
-
current ? /* @__PURE__ */ (0,
|
|
1632
|
+
current ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: UsagePill_default.hint, children: [
|
|
1786
1633
|
t("usageLastUpdated"),
|
|
1787
1634
|
" ",
|
|
1788
1635
|
new Date(current.updatedAt).toLocaleString(getLocale?.())
|
|
1789
1636
|
] }) : null,
|
|
1790
|
-
usage ? ["rolling", "weekly", "monthly"].map((key) => /* @__PURE__ */ (0,
|
|
1791
|
-
/* @__PURE__ */ (0,
|
|
1792
|
-
/* @__PURE__ */ (0,
|
|
1793
|
-
/* @__PURE__ */ (0,
|
|
1637
|
+
usage ? ["rolling", "weekly", "monthly"].map((key) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.window, children: [
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.row, children: [
|
|
1639
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t(`usage_${key}`) }),
|
|
1640
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
1794
1641
|
usage[key].percent,
|
|
1795
1642
|
"%"
|
|
1796
1643
|
] })
|
|
1797
1644
|
] }),
|
|
1798
|
-
/* @__PURE__ */ (0,
|
|
1799
|
-
/* @__PURE__ */ (0,
|
|
1645
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("progress", { "aria-label": t(`usage_${key}`), max: 100, value: Math.min(100, usage[key].percent) }),
|
|
1646
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.hint, children: [
|
|
1800
1647
|
t("usageResets"),
|
|
1801
1648
|
" ",
|
|
1802
1649
|
new Date(usage[key].resetsAt).toLocaleString(getLocale?.())
|
|
1803
1650
|
] }),
|
|
1804
|
-
usage[key].status === "rate-limited" && /* @__PURE__ */ (0,
|
|
1805
|
-
] }, key)) : failure ? null : /* @__PURE__ */ (0,
|
|
1806
|
-
sessionEvents && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SessionCache, { events: sessionEvents, t, getLocale })
|
|
1651
|
+
usage[key].status === "rate-limited" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: t("usageLimited") })
|
|
1652
|
+
] }, key)) : failure ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: t("usageLoading") })
|
|
1807
1653
|
] })
|
|
1808
1654
|
] });
|
|
1809
1655
|
}
|
|
@@ -1824,7 +1670,6 @@ function registerUsagePill(ctx) {
|
|
|
1824
1670
|
order: 1e3,
|
|
1825
1671
|
inject: (sessionId) => ({
|
|
1826
1672
|
directory: ready.modelDirectories.directoryFor(sessionId).store,
|
|
1827
|
-
sessionEvents: sessionEventSource(ready.get("sessions"), sessionId),
|
|
1828
1673
|
readUsage,
|
|
1829
1674
|
getLocale: () => ready.locale.getLocale().active,
|
|
1830
1675
|
t: (key) => translate(key)
|
package/lib/index.js
CHANGED
|
@@ -312,8 +312,12 @@ function toolMessage(message) {
|
|
|
312
312
|
if (message.role !== "tool") return void 0;
|
|
313
313
|
return message;
|
|
314
314
|
}
|
|
315
|
-
function
|
|
315
|
+
function assertSupportedHistory(messages) {
|
|
316
316
|
for (const message of messages) {
|
|
317
|
+
if (message.role === "developer") throw new LlmError3("Developer messages are not supported yet", "UNSUPPORTED_CONTENT");
|
|
318
|
+
if (message.content.some((block) => block.type === "tool-addition" || block.type === "tool-removal")) {
|
|
319
|
+
throw new LlmError3("Tool-change blocks require developer role", "UNSUPPORTED_CONTENT");
|
|
320
|
+
}
|
|
317
321
|
if (message.role !== "user" && !toolMessage(message) && contentHasImage(message.content)) {
|
|
318
322
|
throw new LlmError3(
|
|
319
323
|
`pi-ai cannot represent an image in an in-history ${message.role} message`,
|
|
@@ -382,6 +386,9 @@ async function prepareRequestImages(messages, attachments, budget, signal) {
|
|
|
382
386
|
return versions;
|
|
383
387
|
}
|
|
384
388
|
function toolsOf(options) {
|
|
389
|
+
if (options.tools?.some((tool) => tool.deferLoading === true)) {
|
|
390
|
+
throw new LlmError3("Deferred tool loading is not supported yet", "UNSUPPORTED_CONTENT");
|
|
391
|
+
}
|
|
385
392
|
return options.tools?.map((tool) => ({
|
|
386
393
|
name: tool.name,
|
|
387
394
|
description: tool.description,
|
|
@@ -413,7 +420,7 @@ function appendAssistant(message, messages, toolNames, onReplayDegrade) {
|
|
|
413
420
|
messages.push(assistant);
|
|
414
421
|
}
|
|
415
422
|
function textOnlyContext(options, onReplayDegrade) {
|
|
416
|
-
|
|
423
|
+
assertSupportedHistory(options.messages);
|
|
417
424
|
const split = splitSystemPrompt(options);
|
|
418
425
|
const toolNames = /* @__PURE__ */ new Map();
|
|
419
426
|
const messages = [];
|
|
@@ -476,7 +483,7 @@ async function toPiContextWithImages(options, images, onReplayDegrade) {
|
|
|
476
483
|
maxPixels: DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET,
|
|
477
484
|
maxBytes: DEFAULT_REQUEST_IMAGE_MAX_BYTES
|
|
478
485
|
};
|
|
479
|
-
|
|
486
|
+
assertSupportedHistory(options.messages);
|
|
480
487
|
const split = splitSystemPrompt(options);
|
|
481
488
|
const projection = {
|
|
482
489
|
maxBytes: maxRequestImageBytes,
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
2
2
|
import type { ModelDirectoryState } from '@deepseek-ai/dsh-client-ui-model-selection/client';
|
|
3
3
|
import type { GoUsage } from '../usage-contract.ts';
|
|
4
|
-
import type { SessionEventSource } from './session-cache.ts';
|
|
5
4
|
export interface UsagePillProps {
|
|
6
5
|
directory: SnapshotStore<ModelDirectoryState>;
|
|
7
6
|
readUsage: () => Promise<GoUsage>;
|
|
8
7
|
t: (key: string) => string;
|
|
9
8
|
getLocale?: () => string;
|
|
10
|
-
sessionEvents?: SessionEventSource;
|
|
11
9
|
}
|
|
12
10
|
/** Only the selected Go provider mounts a poller, so other models send no usage traffic. */
|
|
13
11
|
export declare function UsagePill({ directory, ...props }: UsagePillProps): import("react").JSX.Element | null;
|
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
/** Copy dictionaries for the OpenCode Go settings page. English is the key-set source of truth. */
|
|
2
2
|
export declare const en: {
|
|
3
|
-
cacheTitle: string;
|
|
4
|
-
cacheReadRatio: string;
|
|
5
|
-
cacheReadTokens: string;
|
|
6
|
-
cacheInputTokens: string;
|
|
7
|
-
cacheWriteTokens: string;
|
|
8
|
-
cacheResponses: string;
|
|
9
|
-
cacheEmpty: string;
|
|
10
|
-
cacheExcluded: string;
|
|
11
|
-
cacheScope: string;
|
|
12
|
-
cacheMore: string;
|
|
13
|
-
cacheRoutingHint: string;
|
|
14
3
|
usageTitle: string;
|
|
15
4
|
usageRollingShort: string;
|
|
16
5
|
usageHint: string;
|
|
@@ -31,7 +31,7 @@ export interface PiImageRequestBudget {
|
|
|
31
31
|
* @param images - absent; selects the synchronous conversion.
|
|
32
32
|
* @param onReplayDegrade - forwarded to {@link toPiAssistant} for each assistant message.
|
|
33
33
|
* @returns the pi-ai context; `tools` is omitted when the request declares none.
|
|
34
|
-
* @throws {LlmError} `UNSUPPORTED_CONTENT` for
|
|
34
|
+
* @throws {LlmError} `UNSUPPORTED_CONTENT` for a `developer` history message, a tool-change block, a deferred tool, or an image in any history role, including a leading system message.
|
|
35
35
|
*/
|
|
36
36
|
export declare function toPiContext(options: GenerateOptions, images?: undefined, onReplayDegrade?: (reason: string) => void): PiContext;
|
|
37
37
|
/**
|
package/package.json
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
|
|
2
|
-
/** Small structural face of the optional Host session event feed, across Host versions. */
|
|
3
|
-
export type SessionEventSource = ObservableSnapshot<unknown>;
|
|
4
|
-
export interface SessionCacheStats {
|
|
5
|
-
responses: number;
|
|
6
|
-
missingUsage: number;
|
|
7
|
-
unattributed: number;
|
|
8
|
-
inputTokens: number;
|
|
9
|
-
cacheReadTokens: number;
|
|
10
|
-
cacheWriteTokens: number;
|
|
11
|
-
hasMore: boolean;
|
|
12
|
-
}
|
|
13
|
-
/** Use only already-loaded history; never open a session or fetch more pages for diagnostics. */
|
|
14
|
-
export declare function sessionEventSource(sessions: unknown, sessionId: string): SessionEventSource | undefined;
|
|
15
|
-
/** Aggregate settled Go responses. Pi-ai's input excludes cache reads AND writes. */
|
|
16
|
-
export declare function summarizeSessionCache(window: unknown): SessionCacheStats;
|
|
17
|
-
/** Stable snapshots avoid rendering on unrelated live chunks; history replacement recomputes. */
|
|
18
|
-
export declare function sessionCacheSource(events: SessionEventSource): ObservableSnapshot<SessionCacheStats>;
|