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 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 and polls the same-origin route every 60 s |
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,注册进 `sidebar.footer.action` 列表槽,每 60s 轮询同源路由 |
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:8px 6px;display:flex;flex-direction:column;gap:6px;border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}",
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:16px;color:var(--dsw-alias-label-secondary)}",
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": "5 小时",
53
- "status.ok": "正常",
55
+ "window.rolling.hint": "5h",
54
56
  "time.soon": "即将重置",
55
- "time.minutes": "{n} 分后重置",
56
- "time.hours": "{n} 小时 {m} 分后",
57
- "time.days": "{n} {m} 小时后",
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": "5 hours",
70
- "status.ok": "OK",
71
+ "window.rolling.hint": "5h",
71
72
  "time.soon": "resets soon",
72
- "time.minutes": "in {n} min",
73
- "time.hours": "in {n}h {m}m",
74
- "time.days": "in {n}d {m}h",
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 "#ff3b30";
106
- if (percent >= 70) return "#ff9500";
107
- return "#34c759";
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("span", { children: (win.resetsAt ? timeUntil(win.resetsAt, t) : (w.hintKey ? t(w.hintKey) : "")) })
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-track",
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("span", { children: win.status === "ok" ? t("status.ok") : win.status }),
188
- react_jsx_runtime.jsx("span", { children: win.percent + "%" })
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
- ctx.effect(() => ctx.slots.register({
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), "dsh-opencode-go-usage: widget registration");
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.1",
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",