dsh-grok-subscription 1.0.2 → 1.0.4
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 +4 -4
- package/README.md +4 -4
- package/docs/assets/settings-account.webp +0 -0
- package/docs/assets/settings-usage.webp +0 -0
- package/lib/client.js +216 -93
- package/package.json +10 -7
package/README.en.md
CHANGED
|
@@ -25,7 +25,7 @@ Models, reasoning effort, and weekly quota all stay inside DSH.
|
|
|
25
25
|
|
|
26
26
|
## Three-step start
|
|
27
27
|
|
|
28
|
-
1. **Install the plugin.** Run the command below; to select a candidate version, enter the full `package@version`, for example `dsh-grok-subscription@1.0.
|
|
28
|
+
1. **Install the plugin.** Run the command below; to select a candidate version, enter the full `package@version`, for example `dsh-grok-subscription@1.0.4`.
|
|
29
29
|
|
|
30
30
|
```sh
|
|
31
31
|
dsh plugin --profile web add BaronCyrus/dsh-grok-subscription
|
|
@@ -57,13 +57,13 @@ These capabilities reuse the same local Grok Build sign-in.
|
|
|
57
57
|
<img src="docs/assets/settings-account.webp" width="820" alt="The Grok Subscription page in DSH Settings: sign-in status, account, login buttons and credential notes">
|
|
58
58
|
</p>
|
|
59
59
|
|
|
60
|
-
The **Settings → Grok Subscription** screen
|
|
60
|
+
The **Settings → Grok Subscription** screen uses a status chip for the sign-in state, and an account card offering CLI login, device-code login, pull from the Grok CLI, and logout; how credentials are read lives in a collapsible "How signing in works" disclosure. It is styled with DSH's own design tokens, so it follows the light and dark theme. Account and time values in the screenshot are demo data.
|
|
61
61
|
|
|
62
62
|
<p align="center">
|
|
63
63
|
<img src="docs/assets/settings-usage.webp" width="820" alt="The experimental usage panel in Grok Subscription settings: 6% used, about 94% remaining">
|
|
64
64
|
</p>
|
|
65
65
|
|
|
66
|
-
The experimental usage panel comes from an undocumented subscription billing endpoint (`/v1/billing?format=credits`). It is informational: the endpoint may change or disappear, a failed read never shows an invented percentage, and chat is unaffected.
|
|
66
|
+
The experimental usage panel comes from an undocumented subscription billing endpoint (`/v1/billing?format=credits`): the remaining share is drawn as a progress bar and per-product rows are listed separately. It is informational: the endpoint may change or disappear, a failed read never shows an invented percentage, and chat is unaffected.
|
|
67
67
|
|
|
68
68
|
## Prepare DSH
|
|
69
69
|
|
|
@@ -89,7 +89,7 @@ dsh plugin --profile web add BaronCyrus/dsh-grok-subscription
|
|
|
89
89
|
You can also install the version published on npm:
|
|
90
90
|
|
|
91
91
|
```sh
|
|
92
|
-
dsh plugin --profile web add dsh-grok-subscription@1.0.
|
|
92
|
+
dsh plugin --profile web add dsh-grok-subscription@1.0.4
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
DSH handles target selection, the profile lock, dependency resolution, and bundle activation.
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
## 三步开始
|
|
27
27
|
|
|
28
|
-
1. **安装插件**:在终端运行下面的命令;指定候选版本时填写完整的 `包名@版本`,例如 `dsh-grok-subscription@1.0.
|
|
28
|
+
1. **安装插件**:在终端运行下面的命令;指定候选版本时填写完整的 `包名@版本`,例如 `dsh-grok-subscription@1.0.4`。
|
|
29
29
|
|
|
30
30
|
```sh
|
|
31
31
|
dsh plugin --profile web add BaronCyrus/dsh-grok-subscription
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
<img src="docs/assets/settings-account.webp" width="820" alt="DSH 设置中的 Grok 订阅页面:登录状态、账号、登录按钮与凭据说明">
|
|
58
58
|
</p>
|
|
59
59
|
|
|
60
|
-
上图为 **设置 → Grok 订阅**
|
|
60
|
+
上图为 **设置 → Grok 订阅** 主界面:顶部状态胶囊显示登录状态,账户卡片提供 CLI 登录、设备码登录、从 Grok CLI 拉取和登出,凭据读取方式收在可展开的「登录方式说明」里。样式沿用 DSH 自身的设计变量,因此跟随主题明暗切换。截图中的账号与时间均为演示数据。
|
|
61
61
|
|
|
62
62
|
<p align="center">
|
|
63
63
|
<img src="docs/assets/settings-usage.webp" width="820" alt="Grok 订阅设置页中的实验性用量面板:已用 6%、剩余约 94%">
|
|
64
64
|
</p>
|
|
65
65
|
|
|
66
|
-
实验性用量面板来自未公开的订阅计费接口(`/v1/billing?format=credits
|
|
66
|
+
实验性用量面板来自未公开的订阅计费接口(`/v1/billing?format=credits`):剩余比例以进度条呈现,产品明细逐行列出。它仅供参考:接口可能随时变化或消失,读取失败时不会显示编造的百分比,也不影响聊天。
|
|
67
67
|
|
|
68
68
|
## 准备 DSH
|
|
69
69
|
|
|
@@ -89,7 +89,7 @@ dsh plugin --profile web add BaronCyrus/dsh-grok-subscription
|
|
|
89
89
|
也可以按 npm 上的已发布版本安装:
|
|
90
90
|
|
|
91
91
|
```sh
|
|
92
|
-
dsh plugin --profile web add dsh-grok-subscription@1.0.
|
|
92
|
+
dsh plugin --profile web add dsh-grok-subscription@1.0.4
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
目标选择、profile 锁、依赖解析和 bundle 激活均由 DSH 负责。
|
|
Binary file
|
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -20,8 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/client.jsx
|
|
21
21
|
var client_exports = {};
|
|
22
22
|
__export(client_exports, {
|
|
23
|
+
GrokSubscriptionPanel: () => GrokSubscriptionPanel,
|
|
23
24
|
GrokSubscriptionSection: () => GrokSubscriptionSection,
|
|
24
25
|
RPC_CALL_TIMEOUT_MS: () => RPC_CALL_TIMEOUT_MS,
|
|
26
|
+
SectionBoundary: () => SectionBoundary,
|
|
27
|
+
UsagePanel: () => UsagePanel,
|
|
25
28
|
apply: () => apply,
|
|
26
29
|
callRpc: () => callRpc,
|
|
27
30
|
inject: () => inject,
|
|
@@ -34,7 +37,7 @@ var import_react2 = require("react");
|
|
|
34
37
|
var zh = {
|
|
35
38
|
nav: "Grok \u8BA2\u9605",
|
|
36
39
|
title: "Grok \u8BA2\u9605",
|
|
37
|
-
subtitle: "\u7528 SuperGrok / X Premium\uFF08Grok Build\uFF09\u4F1A\u8BDD\uFF0C\u800C\u4E0D\u662F XAI_API_KEY\u3002\xB7 1.0.
|
|
40
|
+
subtitle: "\u7528 SuperGrok / X Premium\uFF08Grok Build\uFF09\u4F1A\u8BDD\uFF0C\u800C\u4E0D\u662F XAI_API_KEY\u3002\xB7 1.0.4",
|
|
38
41
|
signedIn: "\u5DF2\u767B\u5F55",
|
|
39
42
|
signedOut: "\u672A\u767B\u5F55",
|
|
40
43
|
account: "\u8D26\u6237",
|
|
@@ -52,6 +55,9 @@ var zh = {
|
|
|
52
55
|
loginHint: "\u4F1A\u5728\u542F\u52A8 DSH \u7684\u7EC8\u7AEF\u4E2D\u8FD0\u884C grok login\u3002\u8BF7\u5728\u7EC8\u7AEF\u6216\u6D4F\u89C8\u5668\u4E2D\u5B8C\u6210\u6388\u6743\uFF0C\u7136\u540E\u7B49\u5F85\u540C\u6B65\u3002",
|
|
53
56
|
deviceHint: "\u8BBE\u5907\u7801\u63D0\u793A\u4F1A\u51FA\u73B0\u5728 DSH \u7EC8\u7AEF\u3002\u4E5F\u53EF\u624B\u52A8\u8FD0\u884C grok login --device-auth\uFF0C\u5B8C\u6210\u540E\u70B9\u201C\u4ECE Grok CLI \u62C9\u53D6\u201D\u3002",
|
|
54
57
|
pullHint: "\u5B89\u5168\u8BFB\u53D6 ~/.grok/auth.json\uFF08\u62D2\u7EDD\u7B26\u53F7\u94FE\u63A5\u4E0E\u7EC4/\u5176\u4ED6\u4EBA\u53EF\u8BFB\uFF09\uFF0C\u53EA\u628A\u77ED\u671F access token \u5199\u5165 DSH\u3002",
|
|
58
|
+
loginHelp: "\u767B\u5F55\u65B9\u5F0F\u8BF4\u660E",
|
|
59
|
+
refreshCatalog: "\u5237\u65B0\u6A21\u578B\u76EE\u5F55",
|
|
60
|
+
renderError: "\u754C\u9762\u6E32\u67D3\u5931\u8D25",
|
|
55
61
|
busy: "\u5904\u7406\u4E2D\u2026",
|
|
56
62
|
busyCatalog: "\u6B63\u5728\u5237\u65B0\u6A21\u578B\u76EE\u5F55\u2026",
|
|
57
63
|
busyUsage: "\u6B63\u5728\u5237\u65B0\u7528\u91CF\u2026",
|
|
@@ -81,7 +87,7 @@ var zh = {
|
|
|
81
87
|
var en = {
|
|
82
88
|
nav: "Grok Subscription",
|
|
83
89
|
title: "Grok Subscription",
|
|
84
|
-
subtitle: "Use a SuperGrok / X Premium (Grok Build) session, not XAI_API_KEY. \xB7 1.0.
|
|
90
|
+
subtitle: "Use a SuperGrok / X Premium (Grok Build) session, not XAI_API_KEY. \xB7 1.0.4",
|
|
85
91
|
signedIn: "Signed in",
|
|
86
92
|
signedOut: "Signed out",
|
|
87
93
|
account: "Account",
|
|
@@ -99,6 +105,9 @@ var en = {
|
|
|
99
105
|
loginHint: "Runs grok login in the terminal that started DSH. Finish the browser or CLI prompt there, then wait for sync.",
|
|
100
106
|
deviceHint: "The device-code prompt appears in the DSH terminal. You can also run grok login --device-auth yourself, then Pull from Grok CLI.",
|
|
101
107
|
pullHint: "Reads ~/.grok/auth.json securely (refuses symlinks and group/other-readable files) and stores only the short-lived access token in DSH.",
|
|
108
|
+
loginHelp: "How signing in works",
|
|
109
|
+
refreshCatalog: "Refresh model catalog",
|
|
110
|
+
renderError: "Failed to render this panel",
|
|
102
111
|
busy: "Working\u2026",
|
|
103
112
|
busyCatalog: "Refreshing model catalog\u2026",
|
|
104
113
|
busyUsage: "Refreshing usage\u2026",
|
|
@@ -165,6 +174,83 @@ var REQUEST_IMAGE_PIXEL_BUDGET = 2048 * 2048;
|
|
|
165
174
|
var REQUEST_IMAGE_MAX_BYTES = 1024 * 1024;
|
|
166
175
|
var FALLBACK_MODEL_IDS = Object.freeze(["grok-4.7", "grok-4.6", "grok-4.5"]);
|
|
167
176
|
|
|
177
|
+
// src/client-settings-style.js
|
|
178
|
+
var SETTINGS_STYLE = `
|
|
179
|
+
.grokSubscription{display:flex;flex-direction:column;gap:10px;max-width:720px;color:var(--dsw-alias-label-primary);container-type:inline-size}
|
|
180
|
+
.grokSubscription h2,.grokSubscription h3,.grokSubscription p{margin:0}
|
|
181
|
+
.grokSubscription h2{font-size:16px;line-height:24px;font-weight:500}
|
|
182
|
+
.grokSubscription h3{font-size:15px;line-height:22px;font-weight:600}
|
|
183
|
+
|
|
184
|
+
.gsHead{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
|
|
185
|
+
.gsLead{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}
|
|
186
|
+
|
|
187
|
+
.gsCard{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-3);border-radius:16px;padding:14px 16px;display:flex;flex-direction:column;gap:12px}
|
|
188
|
+
.gsCardHead{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
189
|
+
.gsCardHead .gsSpacer{flex:1;min-width:0}
|
|
190
|
+
|
|
191
|
+
.gsChip{display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:2px 10px;font-size:12px;line-height:18px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);white-space:nowrap}
|
|
192
|
+
.gsChip--ok{color:var(--dsw-alias-state-success-primary)}
|
|
193
|
+
.gsChip--off{color:var(--dsw-alias-label-tertiary)}
|
|
194
|
+
.gsChip--warn{color:var(--dsw-alias-state-warn-label)}
|
|
195
|
+
.gsChip--error{color:var(--dsw-alias-label-error)}
|
|
196
|
+
.gsDot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
|
|
197
|
+
|
|
198
|
+
.gsAccount{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
|
|
199
|
+
|
|
200
|
+
.gsActions{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
|
|
201
|
+
.gsBtn{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border:.5px solid var(--dsw-alias-border-l3);border-radius:18px;display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:0 14px;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary);background:0 0;transition:background .16s,border-color .16s,color .16s}
|
|
202
|
+
.gsBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
|
|
203
|
+
.gsBtn:focus-visible{outline:2px solid var(--dsw-alias-border-l3);outline-offset:2px}
|
|
204
|
+
.gsBtn:disabled{opacity:.45;cursor:not-allowed}
|
|
205
|
+
.gsBtn--primary{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border-color:transparent}
|
|
206
|
+
.gsBtn--primary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}
|
|
207
|
+
.gsBtn--danger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-label-error);border-color:var(--dsw-alias-label-error)}
|
|
208
|
+
|
|
209
|
+
.gsStatus{display:flex;align-items:flex-start;gap:8px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}
|
|
210
|
+
.gsStatus--ok{color:var(--dsw-alias-state-success-primary)}
|
|
211
|
+
.gsStatus--error{color:var(--dsw-alias-label-error)}
|
|
212
|
+
.gsStatus--warn{color:var(--dsw-alias-state-warn-label)}
|
|
213
|
+
.gsStatus--busy{color:var(--dsw-alias-label-tertiary)}
|
|
214
|
+
|
|
215
|
+
.gsDisclosure{margin:0}
|
|
216
|
+
.gsDisclosure>summary{display:flex;align-items:center;gap:8px;min-height:28px;cursor:pointer;list-style:none;font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary)}
|
|
217
|
+
.gsDisclosure>summary::-webkit-details-marker{display:none}
|
|
218
|
+
.gsDisclosure>summary:hover{color:var(--dsw-alias-label-primary)}
|
|
219
|
+
.gsDisclosure>summary:focus-visible{outline:2px solid var(--dsw-alias-border-l3);outline-offset:4px;border-radius:4px}
|
|
220
|
+
.gsChevron{flex:none;transition:transform .16s}
|
|
221
|
+
.gsDisclosure[open] .gsChevron{transform:rotate(180deg)}
|
|
222
|
+
.gsDisclosureBody{display:flex;flex-direction:column;gap:6px;padding-top:8px;margin-top:8px;border-top:.5px solid var(--dsw-alias-border-l2)}
|
|
223
|
+
.gsDisclosureBody p{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}
|
|
224
|
+
|
|
225
|
+
.gsGauge{display:flex;flex-direction:column;gap:8px}
|
|
226
|
+
.gsGaugeTop{display:flex;align-items:baseline;gap:8px}
|
|
227
|
+
.gsGaugeValue{font-size:24px;line-height:30px;font-weight:600;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums}
|
|
228
|
+
.gsGaugeLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
229
|
+
.gsBar{height:6px;border-radius:999px;background:color-mix(in srgb, var(--dsw-alias-label-primary) 14%, transparent);overflow:hidden}
|
|
230
|
+
.gsBar>span{display:block;height:100%;border-radius:999px;background:var(--dsw-alias-brand-primary);transition:width .2s}
|
|
231
|
+
.gsGaugeMeta{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
232
|
+
.gsGaugeMeta code{font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
233
|
+
|
|
234
|
+
.gsRows{display:flex;flex-direction:column;gap:0}
|
|
235
|
+
.gsRow{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:7px 0;font-size:13px;line-height:20px;border-top:.5px solid var(--dsw-alias-border-l2)}
|
|
236
|
+
.gsRow:first-child{border-top:none}
|
|
237
|
+
.gsRowValue{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
238
|
+
|
|
239
|
+
.gsModels{display:flex;flex-wrap:wrap;gap:6px}
|
|
240
|
+
.gsModel{display:inline-flex;align-items:baseline;gap:6px;border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:10px;padding:4px 10px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-primary)}
|
|
241
|
+
.gsModel code{font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
242
|
+
|
|
243
|
+
.gsHint,.gsEmpty,.gsCaveat{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}
|
|
244
|
+
.gsCaveat{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}
|
|
245
|
+
.gsLink{color:var(--dsw-alias-link);font-size:13px;line-height:20px;text-decoration:none;align-self:center}
|
|
246
|
+
.gsLink:hover{text-decoration:underline}
|
|
247
|
+
|
|
248
|
+
@container (max-width: 420px){
|
|
249
|
+
.grokSubscription .gsGaugeValue{font-size:20px;line-height:26px}
|
|
250
|
+
.grokSubscription .gsBtn{flex:1 1 auto}
|
|
251
|
+
}
|
|
252
|
+
`;
|
|
253
|
+
|
|
168
254
|
// src/client-composer-quota.jsx
|
|
169
255
|
var import_react = require("react");
|
|
170
256
|
var import_react_dom = require("react-dom");
|
|
@@ -533,60 +619,96 @@ async function callRpc(rpc, endpoint, payload = {}) {
|
|
|
533
619
|
if (timer) clearTimeout(timer);
|
|
534
620
|
}
|
|
535
621
|
}
|
|
622
|
+
var SectionBoundary = class extends import_react2.Component {
|
|
623
|
+
constructor(props) {
|
|
624
|
+
super(props);
|
|
625
|
+
this.state = { error: void 0 };
|
|
626
|
+
}
|
|
627
|
+
static getDerivedStateFromError(error) {
|
|
628
|
+
return { error };
|
|
629
|
+
}
|
|
630
|
+
render() {
|
|
631
|
+
const { error } = this.state;
|
|
632
|
+
if (!error) return this.props.children;
|
|
633
|
+
const t = this.props.t;
|
|
634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "grokSubscription", children: [
|
|
635
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: SETTINGS_STYLE }),
|
|
636
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsHead", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t("title") }) }),
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsCard", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsStatus gsStatus--error", children: [
|
|
638
|
+
t("renderError"),
|
|
639
|
+
": ",
|
|
640
|
+
error instanceof Error ? error.message : String(error)
|
|
641
|
+
] }) })
|
|
642
|
+
] });
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
function GrokSubscriptionPanel(props) {
|
|
646
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SectionBoundary, { t: props.t, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GrokSubscriptionSection, { ...props }) });
|
|
647
|
+
}
|
|
648
|
+
function Chevron() {
|
|
649
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "gsChevron", width: "12", height: "12", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 6l4 4 4-4", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
650
|
+
}
|
|
651
|
+
function Chip({ tone = "off", children }) {
|
|
652
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: `gsChip gsChip--${tone}`, children: [
|
|
653
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsDot" }),
|
|
654
|
+
children
|
|
655
|
+
] });
|
|
656
|
+
}
|
|
536
657
|
function UsagePanel({ usage, t, usageBusy, onRefresh, signedIn }) {
|
|
537
658
|
const ok = usage?.status === "ok";
|
|
538
|
-
const
|
|
539
|
-
const
|
|
659
|
+
const usedNumber = ok && Number.isFinite(usage.usedPercent) ? usage.usedPercent : void 0;
|
|
660
|
+
const remainingNumber = ok && Number.isFinite(usage.remainingPercent) ? usage.remainingPercent : void 0;
|
|
661
|
+
const used = usedNumber !== void 0 ? formatPercent(usedNumber) : void 0;
|
|
662
|
+
const remaining = remainingNumber !== void 0 ? formatPercent(remainingNumber) : void 0;
|
|
540
663
|
const resetLabel = usage?.periodEndLocal || usage?.periodEnd;
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
664
|
+
const gaugeNumber = remainingNumber ?? (usedNumber !== void 0 ? 100 - usedNumber : void 0);
|
|
665
|
+
const gaugeValue = gaugeNumber !== void 0 ? formatPercent(gaugeNumber) : void 0;
|
|
666
|
+
const gaugeLabel = remainingNumber !== void 0 ? t("usageRemaining") : t("usageUsed");
|
|
667
|
+
const fill = gaugeNumber === void 0 ? 0 : Math.min(100, Math.max(0, gaugeNumber));
|
|
668
|
+
const products = Array.isArray(usage?.productUsage) ? usage.productUsage : [];
|
|
669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCard", children: [
|
|
670
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsCardHead", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: t("usageTitle") }) }),
|
|
671
|
+
ok && (used !== void 0 || remaining !== void 0) ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsGauge", children: [
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsGaugeTop", children: [
|
|
673
|
+
gaugeValue !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "gsGaugeValue", children: [
|
|
674
|
+
gaugeValue,
|
|
550
675
|
"%"
|
|
551
|
-
] }),
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
676
|
+
] }) : null,
|
|
677
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsGaugeLabel", children: gaugeLabel })
|
|
678
|
+
] }),
|
|
679
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsBar", role: "img", "aria-label": `${gaugeLabel} ${gaugeValue ?? 0}%`, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { width: `${fill}%` } }) }),
|
|
680
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsGaugeMeta", children: [
|
|
681
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
682
|
+
t("usageUsed"),
|
|
555
683
|
" ",
|
|
556
|
-
|
|
684
|
+
used ?? "\u2014",
|
|
557
685
|
"%"
|
|
558
|
-
] })
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
usage.periodEnd && usage.periodEndLocal ? /* @__PURE__ */ (0, import_jsx_runtime2.
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
")"
|
|
568
|
-
] }) : null
|
|
569
|
-
] }) : null,
|
|
570
|
-
Array.isArray(usage.productUsage) && usage.productUsage.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
571
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "muted", children: t("usageProduct") }),
|
|
572
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { children: usage.productUsage.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { children: [
|
|
573
|
-
row.name ?? "\u2014",
|
|
574
|
-
typeof row.usedPercent === "number" ? ` \xB7 ${formatPercent(row.usedPercent)}%` : ""
|
|
575
|
-
] }, `${row.name ?? "row"}-${index}`)) })
|
|
576
|
-
] }) : null,
|
|
577
|
-
usage.fetchedAt ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "muted", children: [
|
|
578
|
-
t("usageFetchedAt"),
|
|
579
|
-
": ",
|
|
580
|
-
usage.fetchedAt
|
|
581
|
-
] }) : null
|
|
582
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { children: [
|
|
686
|
+
] }),
|
|
687
|
+
resetLabel ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
688
|
+
t("usageReset"),
|
|
689
|
+
" ",
|
|
690
|
+
resetLabel
|
|
691
|
+
] }) : null,
|
|
692
|
+
usage.periodEnd && usage.periodEndLocal ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { children: usage.periodEnd }) : null
|
|
693
|
+
] })
|
|
694
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsEmpty", children: [
|
|
583
695
|
t("usageUnavailable"),
|
|
584
696
|
usage?.reason ? `: ${usage.reason}` : ""
|
|
585
697
|
] }),
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("
|
|
589
|
-
|
|
698
|
+
products.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsRows", children: products.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsRow", children: [
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: row.name ?? "\u2014" }),
|
|
700
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsRowValue", children: typeof row.usedPercent === "number" ? `${formatPercent(row.usedPercent)}%` : "\u2014" })
|
|
701
|
+
] }, `${row.name ?? "row"}-${index}`)) }) : null,
|
|
702
|
+
usage?.fetchedAt ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsHint", children: [
|
|
703
|
+
t("usageFetchedAt"),
|
|
704
|
+
": ",
|
|
705
|
+
usage.fetchedAt
|
|
706
|
+
] }) : null,
|
|
707
|
+
usageBusy ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsStatus gsStatus--busy", children: t("busyUsage") }) : null,
|
|
708
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsHint", children: t("usageSubtitle") }),
|
|
709
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsActions", children: [
|
|
710
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn", type: "button", disabled: Boolean(usageBusy) || !signedIn, onClick: onRefresh, children: t("usageRefresh") }),
|
|
711
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { className: "gsLink", href: USAGE_PAGE_URL, target: "_blank", rel: "noreferrer", children: t("usageOpenGrok") })
|
|
590
712
|
] })
|
|
591
713
|
] });
|
|
592
714
|
}
|
|
@@ -660,7 +782,8 @@ function GrokSubscriptionSection({ rpc, t }) {
|
|
|
660
782
|
"login/cli": "loginOk",
|
|
661
783
|
"login/device": "loginOk",
|
|
662
784
|
logout: "logoutOk",
|
|
663
|
-
"usage/refresh": "usageRefreshOk"
|
|
785
|
+
"usage/refresh": "usageRefreshOk",
|
|
786
|
+
"catalog/refresh": "catalogRefreshOk"
|
|
664
787
|
}[endpoint];
|
|
665
788
|
if (successKey) setNotice(t(successKey));
|
|
666
789
|
if (endpoint === "usage/refresh" && value?.ok !== false && !value?.error) {
|
|
@@ -682,47 +805,43 @@ function GrokSubscriptionSection({ rpc, t }) {
|
|
|
682
805
|
const models = catalog?.models ?? [];
|
|
683
806
|
const signedIn = account?.signedIn === true;
|
|
684
807
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "grokSubscription", children: [
|
|
685
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children:
|
|
686
|
-
|
|
687
|
-
.grokSubscription h2 { margin: 0 0 4px; font-size: 1.15rem; }
|
|
688
|
-
.grokSubscription p, .grokSubscription li { line-height: 1.5; }
|
|
689
|
-
.grokSubscription .muted { opacity: 0.78; font-size: 0.92rem; }
|
|
690
|
-
.grokSubscription .row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
691
|
-
.grokSubscription button { cursor: pointer; }
|
|
692
|
-
.grokSubscription .error { color: #b42318; }
|
|
693
|
-
.grokSubscription .notice { color: #067647; }
|
|
694
|
-
.grokSubscription ul { margin: 0; padding-left: 1.2rem; }
|
|
695
|
-
.grokSubscription .usageBlock { display: grid; gap: 8px; padding: 10px 0; border-top: 1px solid color-mix(in srgb, currentColor 18%, transparent); }
|
|
696
|
-
.grokSubscription a { color: inherit; }
|
|
697
|
-
` }),
|
|
698
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
808
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: SETTINGS_STYLE }),
|
|
809
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsHead", children: [
|
|
699
810
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t("title") }),
|
|
700
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Chip, { tone: signedIn ? "ok" : "off", children: signedIn ? t("signedIn") : t("signedOut") })
|
|
701
812
|
] }),
|
|
702
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
": "
|
|
813
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsLead", children: t("subtitle") }),
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCard", children: [
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCardHead", children: [
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: t("account") }),
|
|
817
|
+
signedIn && account?.maskedAccount ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsAccount", children: account.maskedAccount }) : null
|
|
706
818
|
] }),
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("
|
|
819
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsActions", children: [
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn gsBtn--primary", type: "button", disabled: Boolean(busy), onClick: () => void run("login/cli"), children: t("loginCli") }),
|
|
821
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn", type: "button", disabled: Boolean(busy), onClick: () => void run("login/device"), children: t("loginDevice") }),
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn", type: "button", disabled: Boolean(busy), onClick: () => void run("pull"), children: t("pull") }),
|
|
823
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn gsBtn--danger", type: "button", disabled: Boolean(busy) || !signedIn, onClick: () => void run("logout"), children: t("logout") })
|
|
824
|
+
] }),
|
|
825
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsStatus gsStatus--busy", children: t("busy") }) : null,
|
|
826
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsStatus gsStatus--ok", children: notice }) : null,
|
|
827
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsStatus gsStatus--error", children: [
|
|
828
|
+
t("error"),
|
|
829
|
+
": ",
|
|
830
|
+
error
|
|
831
|
+
] }) : null,
|
|
832
|
+
status?.cliAvailable === false ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsStatus gsStatus--warn", children: t("cliMissing") }) : null,
|
|
833
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { className: "gsDisclosure", children: [
|
|
834
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("summary", { children: [
|
|
835
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Chevron, {}),
|
|
836
|
+
t("loginHelp")
|
|
837
|
+
] }),
|
|
838
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsDisclosureBody", children: [
|
|
839
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: t("loginHint") }),
|
|
840
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: t("deviceHint") }),
|
|
841
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: t("pullHint") })
|
|
842
|
+
] })
|
|
843
|
+
] })
|
|
714
844
|
] }),
|
|
715
|
-
busy ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "muted", children: t("busy") }) : null,
|
|
716
|
-
notice ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "notice", children: notice }) : null,
|
|
717
|
-
error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "error", children: [
|
|
718
|
-
t("error"),
|
|
719
|
-
": ",
|
|
720
|
-
error
|
|
721
|
-
] }) : null,
|
|
722
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "muted", children: t("loginHint") }),
|
|
723
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "muted", children: t("deviceHint") }),
|
|
724
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "muted", children: t("pullHint") }),
|
|
725
|
-
status?.cliAvailable === false ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "muted", children: t("cliMissing") }) : null,
|
|
726
845
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
727
846
|
UsagePanel,
|
|
728
847
|
{
|
|
@@ -733,21 +852,25 @@ function GrokSubscriptionSection({ rpc, t }) {
|
|
|
733
852
|
onRefresh: () => void run("usage/refresh")
|
|
734
853
|
}
|
|
735
854
|
),
|
|
736
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
737
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
738
|
-
|
|
739
|
-
|
|
855
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCard", children: [
|
|
856
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCardHead", children: [
|
|
857
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: t("models") }),
|
|
858
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsSpacer" }),
|
|
859
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Chip, { tone: catalog?.source === "live" ? "ok" : catalog?.source === "fallback" ? "warn" : "off", children: sourceLabel(catalog?.source, t) })
|
|
860
|
+
] }),
|
|
861
|
+
models.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsEmpty", children: t("noModels") }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsModels", children: models.map((model) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "gsModel", children: [
|
|
740
862
|
model.name,
|
|
741
863
|
" ",
|
|
742
864
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { children: model.id })
|
|
743
865
|
] }, model.id)) }),
|
|
744
|
-
catalog?.error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "error", children: [
|
|
866
|
+
catalog?.error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsStatus gsStatus--error", children: [
|
|
745
867
|
t("catalogError"),
|
|
746
868
|
": ",
|
|
747
869
|
catalog.error
|
|
748
|
-
] }) : null
|
|
870
|
+
] }) : null,
|
|
871
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsActions", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn", type: "button", disabled: !signedIn, onClick: () => void run("catalog/refresh"), children: t("refreshCatalog") }) })
|
|
749
872
|
] }),
|
|
750
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "
|
|
873
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsCaveat", children: t("caveats") })
|
|
751
874
|
] });
|
|
752
875
|
}
|
|
753
876
|
function apply(ctx) {
|
|
@@ -791,7 +914,7 @@ function apply(ctx) {
|
|
|
791
914
|
label: () => t("nav"),
|
|
792
915
|
locale: LOCALE_NS,
|
|
793
916
|
inject: () => ({ rpc, t })
|
|
794
|
-
},
|
|
917
|
+
}, GrokSubscriptionPanel));
|
|
795
918
|
const installDirectorySlots = (scope) => {
|
|
796
919
|
let modelDirectories;
|
|
797
920
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-grok-subscription",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Use a SuperGrok or X Premium Grok Build subscription in DeepSeek Harness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "node scripts/build.mjs",
|
|
42
|
+
"pretest": "npm run build",
|
|
42
43
|
"test": "node --test tests/*.test.mjs",
|
|
43
44
|
"check": "npm test && npm run build"
|
|
44
45
|
},
|
|
@@ -55,8 +56,12 @@
|
|
|
55
56
|
"node": "^22.19.0 || >=24.0.0"
|
|
56
57
|
},
|
|
57
58
|
"peerDependencies": {
|
|
59
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.5-rc.2",
|
|
58
60
|
"@deepseek-ai/dsh-client-connection": "^0.1.5-rc.2",
|
|
59
61
|
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "^0.1.5-rc.2",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.2",
|
|
60
65
|
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.2",
|
|
61
66
|
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.2",
|
|
62
67
|
"@deepseek-ai/dsh-credentials": "^0.1.5-rc.2",
|
|
@@ -66,11 +71,7 @@
|
|
|
66
71
|
"@deepseek-ai/dsh-web": "^0.1.5-rc.2",
|
|
67
72
|
"@earendil-works/pi-ai": "^0.82.1",
|
|
68
73
|
"react": "^18.2.0",
|
|
69
|
-
"react-dom": "^18.2.0"
|
|
70
|
-
"@deepseek-ai/dsh-api-remotes": "^0.1.5-rc.2",
|
|
71
|
-
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-rc.2",
|
|
72
|
-
"@deepseek-ai/dsh-client-ui-model-selection": "^0.1.5-rc.2",
|
|
73
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.2"
|
|
74
|
+
"react-dom": "^18.2.0"
|
|
74
75
|
},
|
|
75
76
|
"peerDependenciesMeta": {
|
|
76
77
|
"@deepseek-ai/dsh-client-connection": {
|
|
@@ -123,7 +124,9 @@
|
|
|
123
124
|
}
|
|
124
125
|
},
|
|
125
126
|
"devDependencies": {
|
|
126
|
-
"esbuild": "^0.25.0"
|
|
127
|
+
"esbuild": "^0.25.0",
|
|
128
|
+
"react": "^18.3.1",
|
|
129
|
+
"react-dom": "^18.3.1"
|
|
127
130
|
},
|
|
128
131
|
"author": "BaronCyrus",
|
|
129
132
|
"repository": {
|