dsh-opencode-go-usage 1.2.1 → 1.2.3
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 +5 -1
- package/README.zh.md +5 -1
- package/lib/client.js +44 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
+
> ⚡ Get an **OpenCode GO plan**: [buycodingplan.com](https://buycodingplan.com/)
|
|
6
|
+
|
|
5
7
|
A [DSH](https://github.com/deepseek-ai/deepseek-harness) (DeepSeek Harness) plugin that watches your **OpenCode GO plan** quota — the $10/month subscription that gives you usage limits on open-source models (rolling 5-hour, weekly, and monthly windows).
|
|
6
8
|
|
|
9
|
+
Compatible with DSH `0.1.1-rc.2` and `0.1.2-alpha.2`.
|
|
10
|
+
|
|
7
11
|
## Features
|
|
8
12
|
|
|
9
13
|
- **Sidebar widget** — a live widget pinned at the bottom of the DSH web sidebar (`sidebar.footer.action` slot) showing three usage bars: rolling (5h), weekly, and monthly, each with a relative countdown to its window reset. When the sidebar is collapsed it shrinks to a compact percentage badge.
|
|
@@ -17,7 +21,7 @@ The plugin is a **dual-half DSH package**:
|
|
|
17
21
|
| half | file | role |
|
|
18
22
|
|---|---|---|
|
|
19
23
|
| host (Node) | `lib/index.js` | registers the `/opencode-go/usage` web route (`ctx.webServer`) and the `/opencode-go` command (`ctx.commands`); resolves the key through DSH credentials; caches the upstream call (30 s) |
|
|
20
|
-
| browser | `lib/client.js` | a hand-authored `window.__ModuleLoader__.load({ id, factory })` bundle that registers into the `sidebar.footer.action` list slot
|
|
24
|
+
| browser | `lib/client.js` | a hand-authored `window.__ModuleLoader__.load({ id, factory })` bundle that waits for and registers into the `sidebar.footer.action` list slot, then polls the same-origin route every 60 s |
|
|
21
25
|
|
|
22
26
|
`package.json` declares `"dsh": { "client": { "platform": "web" } }`, so DSH's client-modules node half scans it into the browser boot graph (`window.__DSH_BOOT__`) and serves the bundle at `/plugins/dsh-opencode-go-usage/client.js`.
|
|
23
27
|
|
package/README.zh.md
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 中文
|
|
4
4
|
|
|
5
|
+
> ⚡ **OpenCode GO 套餐**: [buycodingplan.com](https://buycodingplan.com/)
|
|
6
|
+
|
|
5
7
|
[DSH](https://github.com/deepseek-ai/deepseek-harness)(DeepSeek Harness)插件:监控你的 **OpenCode GO 套餐**额度 —— 10 美元/月的订阅,按模型提供滚动 5 小时 / 每周 / 每月三个窗口的用量限额。
|
|
6
8
|
|
|
9
|
+
兼容 DSH `0.1.1-rc.2` 与 `0.1.2-alpha.2`。
|
|
10
|
+
|
|
7
11
|
## 功能
|
|
8
12
|
|
|
9
13
|
- **侧边栏小组件**:常驻 DSH Web 侧边栏底部(`sidebar.footer.action` 槽位),三条用量进度条:滚动窗口(5h)、周窗口、月窗口,每条带重置倒计时;侧边栏收起时收缩为紧凑的百分比徽标。
|
|
@@ -17,7 +21,7 @@
|
|
|
17
21
|
| 端 | 文件 | 职责 |
|
|
18
22
|
|---|---|---|
|
|
19
23
|
| host(Node) | `lib/index.js` | 注册 `/opencode-go/usage` Web 路由(`ctx.webServer`)与 `/opencode-go` 命令(`ctx.commands`);通过 DSH credentials 解析 key;上游调用带 30s 缓存 |
|
|
20
|
-
| 浏览器 | `lib/client.js` | 手写的 `window.__ModuleLoader__.load({ id, factory })` bundle
|
|
24
|
+
| 浏览器 | `lib/client.js` | 手写的 `window.__ModuleLoader__.load({ id, factory })` bundle,等待 `sidebar.footer.action` 列表槽就绪后注册,每 60s 轮询同源路由 |
|
|
21
25
|
|
|
22
26
|
`package.json` 声明了 `"dsh": { "client": { "platform": "web" } }`,DSH 的 client-modules 节点端会把它扫描进浏览器启动图(`window.__DSH_BOOT__`),并在 `/plugins/dsh-opencode-go-usage/client.js` 提供该 bundle。
|
|
23
27
|
|
package/lib/client.js
CHANGED
|
@@ -25,14 +25,17 @@ window.__ModuleLoader__.load({
|
|
|
25
25
|
tag.dataset.plugin = "dsh-opencode-go-usage";
|
|
26
26
|
tag.dataset.pluginCss = CSS_ID;
|
|
27
27
|
tag.textContent = [
|
|
28
|
-
".ocg-widget{box-sizing:border-box;width:100%;min-width:0;padding:
|
|
28
|
+
".ocg-widget{box-sizing:border-box;width:100%;min-width:0;padding:6px 6px 4px;display:flex;flex-direction:column;gap:4px;border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}",
|
|
29
29
|
".ocg-widget:hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
30
30
|
".ocg-head{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:12px;font-weight:600;line-height:18px}",
|
|
31
31
|
".ocg-refresh{cursor:pointer;border:none;background:none;padding:0;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:18px}",
|
|
32
32
|
".ocg-refresh:hover{color:var(--dsw-alias-label-primary)}",
|
|
33
33
|
".ocg-row{display:flex;flex-direction:column;gap:3px;min-width:0}",
|
|
34
|
-
".ocg-row-label{display:flex;justify-content:space-between;gap:8px;font-size:11px;line-height:
|
|
34
|
+
".ocg-row-label{display:flex;justify-content:space-between;gap:8px;font-size:11px;line-height:15px;color:var(--dsw-alias-label-secondary)}",
|
|
35
35
|
".ocg-row-label b{font-weight:500;color:var(--dsw-alias-label-primary)}",
|
|
36
|
+
".ocg-meta{display:flex;align-items:center;gap:6px;min-width:0}",
|
|
37
|
+
".ocg-meta .ocg-track{flex:1;min-width:0}",
|
|
38
|
+
".ocg-meta>span{font-size:10px;line-height:14px;color:var(--dsw-alias-label-secondary);white-space:nowrap;flex:none}",
|
|
36
39
|
".ocg-track{box-sizing:border-box;height:5px;border-radius:3px;background:var(--dsw-alias-border-l2);overflow:hidden}",
|
|
37
40
|
".ocg-fill{height:100%;border-radius:3px;transition:width .4s ease}",
|
|
38
41
|
".ocg-err{font-size:11px;line-height:16px;color:var(--dsw-alias-label-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
@@ -49,12 +52,11 @@ window.__ModuleLoader__.load({
|
|
|
49
52
|
"window.rolling": "滚动窗口 (5h)",
|
|
50
53
|
"window.weekly": "周窗口",
|
|
51
54
|
"window.monthly": "月窗口",
|
|
52
|
-
"window.rolling.hint": "
|
|
53
|
-
"status.ok": "正常",
|
|
55
|
+
"window.rolling.hint": "5h",
|
|
54
56
|
"time.soon": "即将重置",
|
|
55
|
-
"time.minutes": "{n}
|
|
56
|
-
"time.hours": "{n}
|
|
57
|
-
"time.days": "{n}
|
|
57
|
+
"time.minutes": "{n}分",
|
|
58
|
+
"time.hours": "{n}小时{m}分",
|
|
59
|
+
"time.days": "{n}天{m}小时",
|
|
58
60
|
"refresh": "刷新",
|
|
59
61
|
"loading": "加载中…",
|
|
60
62
|
"rail.title": "OpenCode GO 月用量 {pct}%",
|
|
@@ -66,12 +68,11 @@ window.__ModuleLoader__.load({
|
|
|
66
68
|
"window.rolling": "Rolling (5h)",
|
|
67
69
|
"window.weekly": "Weekly",
|
|
68
70
|
"window.monthly": "Monthly",
|
|
69
|
-
"window.rolling.hint": "
|
|
70
|
-
"status.ok": "OK",
|
|
71
|
+
"window.rolling.hint": "5h",
|
|
71
72
|
"time.soon": "resets soon",
|
|
72
|
-
"time.minutes": "
|
|
73
|
-
"time.hours": "
|
|
74
|
-
"time.days": "
|
|
73
|
+
"time.minutes": "{n}m",
|
|
74
|
+
"time.hours": "{n}h{m}m",
|
|
75
|
+
"time.days": "{n}d{m}h",
|
|
75
76
|
"refresh": "Refresh",
|
|
76
77
|
"loading": "Loading…",
|
|
77
78
|
"rail.title": "OpenCode GO monthly {pct}%",
|
|
@@ -100,11 +101,11 @@ window.__ModuleLoader__.load({
|
|
|
100
101
|
return t("time.days", { n: Math.floor(hours / 24), m: hours % 24 });
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
/** Fill color by usage percent. */
|
|
104
|
+
/** Fill color by usage percent — themed alias tokens (light/dark safe). */
|
|
104
105
|
function fillColor(percent) {
|
|
105
|
-
if (percent >= 90) return "
|
|
106
|
-
if (percent >= 70) return "
|
|
107
|
-
return "
|
|
106
|
+
if (percent >= 90) return "var(--dsw-alias-state-error-primary)";
|
|
107
|
+
if (percent >= 70) return "var(--dsw-alias-state-warn-primary)";
|
|
108
|
+
return "var(--dsw-alias-state-success-primary)";
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
// ── widget component ──
|
|
@@ -164,28 +165,34 @@ window.__ModuleLoader__.load({
|
|
|
164
165
|
rows.push(react_jsx_runtime.jsx("div", {
|
|
165
166
|
className: "ocg-row",
|
|
166
167
|
children: [
|
|
168
|
+
// Name + percentage on one line (percentage right-aligned).
|
|
167
169
|
react_jsx_runtime.jsx("div", {
|
|
168
170
|
className: "ocg-row-label",
|
|
169
171
|
children: [
|
|
170
172
|
react_jsx_runtime.jsx("b", { children: t(w.labelKey) }),
|
|
171
|
-
react_jsx_runtime.jsx("
|
|
173
|
+
react_jsx_runtime.jsx("b", { children: win.percent + "%" })
|
|
172
174
|
]
|
|
173
175
|
}),
|
|
176
|
+
// Track + countdown on one line (track flexes, countdown
|
|
177
|
+
// right-aligned small text; status replaces it when not ok).
|
|
174
178
|
react_jsx_runtime.jsx("div", {
|
|
175
|
-
className: "ocg-
|
|
176
|
-
children: react_jsx_runtime.jsx("div", {
|
|
177
|
-
className: "ocg-fill",
|
|
178
|
-
style: {
|
|
179
|
-
width: Math.max(0, Math.min(100, win.percent)) + "%",
|
|
180
|
-
background: fillColor(win.percent)
|
|
181
|
-
}
|
|
182
|
-
})
|
|
183
|
-
}),
|
|
184
|
-
react_jsx_runtime.jsx("div", {
|
|
185
|
-
className: "ocg-row-label",
|
|
179
|
+
className: "ocg-meta",
|
|
186
180
|
children: [
|
|
187
|
-
react_jsx_runtime.jsx("
|
|
188
|
-
|
|
181
|
+
react_jsx_runtime.jsx("div", {
|
|
182
|
+
className: "ocg-track",
|
|
183
|
+
children: react_jsx_runtime.jsx("div", {
|
|
184
|
+
className: "ocg-fill",
|
|
185
|
+
style: {
|
|
186
|
+
width: Math.max(0, Math.min(100, win.percent)) + "%",
|
|
187
|
+
background: fillColor(win.percent)
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
}),
|
|
191
|
+
react_jsx_runtime.jsx("span", {
|
|
192
|
+
children: win.status === "ok"
|
|
193
|
+
? (win.resetsAt ? timeUntil(win.resetsAt, t) : (w.hintKey ? t(w.hintKey) : ""))
|
|
194
|
+
: win.status
|
|
195
|
+
})
|
|
189
196
|
]
|
|
190
197
|
})
|
|
191
198
|
]
|
|
@@ -228,13 +235,18 @@ window.__ModuleLoader__.load({
|
|
|
228
235
|
|
|
229
236
|
function apply(ctx) {
|
|
230
237
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-opencode-go-usage: dictionaries");
|
|
231
|
-
|
|
238
|
+
const registerWidget = () => ctx.slots.register({
|
|
232
239
|
name: "sidebar.footer.action",
|
|
233
240
|
id: "dsh-opencode-go-usage",
|
|
234
241
|
order: 0,
|
|
235
242
|
label: "OpenCode GO",
|
|
236
243
|
locale: NS
|
|
237
|
-
}, Widget)
|
|
244
|
+
}, Widget);
|
|
245
|
+
if (typeof ctx.slots.inject === "function") {
|
|
246
|
+
ctx.slots.inject("sidebar.footer.action", registerWidget);
|
|
247
|
+
} else {
|
|
248
|
+
ctx.effect(registerWidget, "dsh-opencode-go-usage: widget registration");
|
|
249
|
+
}
|
|
238
250
|
}
|
|
239
251
|
|
|
240
252
|
exports.apply = apply;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-opencode-go-usage",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "DSH (DeepSeek Harness) plugin: OpenCode GO plan quota widget in the sidebar, same-origin usage proxy, and a /opencode-go chat command",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|