dsh-grok-subscription 1.0.2 → 1.0.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.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 +178 -90
- package/package.json +1 -1
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.3`.
|
|
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.3
|
|
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.3`。
|
|
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.3
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
目标选择、profile 锁、依赖解析和 bundle 激活均由 DSH 负责。
|
|
Binary file
|
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -34,7 +34,7 @@ var import_react2 = require("react");
|
|
|
34
34
|
var zh = {
|
|
35
35
|
nav: "Grok \u8BA2\u9605",
|
|
36
36
|
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.
|
|
37
|
+
subtitle: "\u7528 SuperGrok / X Premium\uFF08Grok Build\uFF09\u4F1A\u8BDD\uFF0C\u800C\u4E0D\u662F XAI_API_KEY\u3002\xB7 1.0.3",
|
|
38
38
|
signedIn: "\u5DF2\u767B\u5F55",
|
|
39
39
|
signedOut: "\u672A\u767B\u5F55",
|
|
40
40
|
account: "\u8D26\u6237",
|
|
@@ -52,6 +52,8 @@ var zh = {
|
|
|
52
52
|
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
53
|
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
54
|
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",
|
|
55
|
+
loginHelp: "\u767B\u5F55\u65B9\u5F0F\u8BF4\u660E",
|
|
56
|
+
refreshCatalog: "\u5237\u65B0\u6A21\u578B\u76EE\u5F55",
|
|
55
57
|
busy: "\u5904\u7406\u4E2D\u2026",
|
|
56
58
|
busyCatalog: "\u6B63\u5728\u5237\u65B0\u6A21\u578B\u76EE\u5F55\u2026",
|
|
57
59
|
busyUsage: "\u6B63\u5728\u5237\u65B0\u7528\u91CF\u2026",
|
|
@@ -81,7 +83,7 @@ var zh = {
|
|
|
81
83
|
var en = {
|
|
82
84
|
nav: "Grok Subscription",
|
|
83
85
|
title: "Grok Subscription",
|
|
84
|
-
subtitle: "Use a SuperGrok / X Premium (Grok Build) session, not XAI_API_KEY. \xB7 1.0.
|
|
86
|
+
subtitle: "Use a SuperGrok / X Premium (Grok Build) session, not XAI_API_KEY. \xB7 1.0.3",
|
|
85
87
|
signedIn: "Signed in",
|
|
86
88
|
signedOut: "Signed out",
|
|
87
89
|
account: "Account",
|
|
@@ -99,6 +101,8 @@ var en = {
|
|
|
99
101
|
loginHint: "Runs grok login in the terminal that started DSH. Finish the browser or CLI prompt there, then wait for sync.",
|
|
100
102
|
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
103
|
pullHint: "Reads ~/.grok/auth.json securely (refuses symlinks and group/other-readable files) and stores only the short-lived access token in DSH.",
|
|
104
|
+
loginHelp: "How signing in works",
|
|
105
|
+
refreshCatalog: "Refresh model catalog",
|
|
102
106
|
busy: "Working\u2026",
|
|
103
107
|
busyCatalog: "Refreshing model catalog\u2026",
|
|
104
108
|
busyUsage: "Refreshing usage\u2026",
|
|
@@ -165,6 +169,83 @@ var REQUEST_IMAGE_PIXEL_BUDGET = 2048 * 2048;
|
|
|
165
169
|
var REQUEST_IMAGE_MAX_BYTES = 1024 * 1024;
|
|
166
170
|
var FALLBACK_MODEL_IDS = Object.freeze(["grok-4.7", "grok-4.6", "grok-4.5"]);
|
|
167
171
|
|
|
172
|
+
// src/client-settings-style.js
|
|
173
|
+
var SETTINGS_STYLE = `
|
|
174
|
+
.grokSubscription{display:flex;flex-direction:column;gap:10px;max-width:720px;color:var(--dsw-alias-label-primary);container-type:inline-size}
|
|
175
|
+
.grokSubscription h2,.grokSubscription h3,.grokSubscription p{margin:0}
|
|
176
|
+
.grokSubscription h2{font-size:16px;line-height:24px;font-weight:500}
|
|
177
|
+
.grokSubscription h3{font-size:15px;line-height:22px;font-weight:600}
|
|
178
|
+
|
|
179
|
+
.gsHead{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
|
|
180
|
+
.gsLead{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}
|
|
181
|
+
|
|
182
|
+
.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}
|
|
183
|
+
.gsCardHead{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
184
|
+
.gsCardHead .gsSpacer{flex:1;min-width:0}
|
|
185
|
+
|
|
186
|
+
.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}
|
|
187
|
+
.gsChip--ok{color:var(--dsw-alias-state-success-primary)}
|
|
188
|
+
.gsChip--off{color:var(--dsw-alias-label-tertiary)}
|
|
189
|
+
.gsChip--warn{color:var(--dsw-alias-state-warn-label)}
|
|
190
|
+
.gsChip--error{color:var(--dsw-alias-label-error)}
|
|
191
|
+
.gsDot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
|
|
192
|
+
|
|
193
|
+
.gsAccount{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
|
|
194
|
+
|
|
195
|
+
.gsActions{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
|
|
196
|
+
.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}
|
|
197
|
+
.gsBtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
|
|
198
|
+
.gsBtn:focus-visible{outline:2px solid var(--dsw-alias-border-l3);outline-offset:2px}
|
|
199
|
+
.gsBtn:disabled{opacity:.45;cursor:not-allowed}
|
|
200
|
+
.gsBtn--primary{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border-color:transparent}
|
|
201
|
+
.gsBtn--primary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}
|
|
202
|
+
.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)}
|
|
203
|
+
|
|
204
|
+
.gsStatus{display:flex;align-items:flex-start;gap:8px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}
|
|
205
|
+
.gsStatus--ok{color:var(--dsw-alias-state-success-primary)}
|
|
206
|
+
.gsStatus--error{color:var(--dsw-alias-label-error)}
|
|
207
|
+
.gsStatus--warn{color:var(--dsw-alias-state-warn-label)}
|
|
208
|
+
.gsStatus--busy{color:var(--dsw-alias-label-tertiary)}
|
|
209
|
+
|
|
210
|
+
.gsDisclosure{margin:0}
|
|
211
|
+
.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)}
|
|
212
|
+
.gsDisclosure>summary::-webkit-details-marker{display:none}
|
|
213
|
+
.gsDisclosure>summary:hover{color:var(--dsw-alias-label-primary)}
|
|
214
|
+
.gsDisclosure>summary:focus-visible{outline:2px solid var(--dsw-alias-border-l3);outline-offset:4px;border-radius:4px}
|
|
215
|
+
.gsChevron{flex:none;transition:transform .16s}
|
|
216
|
+
.gsDisclosure[open] .gsChevron{transform:rotate(180deg)}
|
|
217
|
+
.gsDisclosureBody{display:flex;flex-direction:column;gap:6px;padding-top:8px;margin-top:8px;border-top:.5px solid var(--dsw-alias-border-l2)}
|
|
218
|
+
.gsDisclosureBody p{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}
|
|
219
|
+
|
|
220
|
+
.gsGauge{display:flex;flex-direction:column;gap:8px}
|
|
221
|
+
.gsGaugeTop{display:flex;align-items:baseline;gap:8px}
|
|
222
|
+
.gsGaugeValue{font-size:24px;line-height:30px;font-weight:600;color:var(--dsw-alias-label-primary);font-variant-numeric:tabular-nums}
|
|
223
|
+
.gsGaugeLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
224
|
+
.gsBar{height:6px;border-radius:999px;background:color-mix(in srgb, var(--dsw-alias-label-primary) 14%, transparent);overflow:hidden}
|
|
225
|
+
.gsBar>span{display:block;height:100%;border-radius:999px;background:var(--dsw-alias-brand-primary);transition:width .2s}
|
|
226
|
+
.gsGaugeMeta{display:flex;flex-wrap:wrap;gap:4px 10px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
|
|
227
|
+
.gsGaugeMeta code{font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
228
|
+
|
|
229
|
+
.gsRows{display:flex;flex-direction:column;gap:0}
|
|
230
|
+
.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)}
|
|
231
|
+
.gsRow:first-child{border-top:none}
|
|
232
|
+
.gsRowValue{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
233
|
+
|
|
234
|
+
.gsModels{display:flex;flex-wrap:wrap;gap:6px}
|
|
235
|
+
.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)}
|
|
236
|
+
.gsModel code{font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
237
|
+
|
|
238
|
+
.gsHint,.gsEmpty,.gsCaveat{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}
|
|
239
|
+
.gsCaveat{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}
|
|
240
|
+
.gsLink{color:var(--dsw-alias-link);font-size:13px;line-height:20px;text-decoration:none;align-self:center}
|
|
241
|
+
.gsLink:hover{text-decoration:underline}
|
|
242
|
+
|
|
243
|
+
@container (max-width: 420px){
|
|
244
|
+
.grokSubscription .gsGaugeValue{font-size:20px;line-height:26px}
|
|
245
|
+
.grokSubscription .gsBtn{flex:1 1 auto}
|
|
246
|
+
}
|
|
247
|
+
`;
|
|
248
|
+
|
|
168
249
|
// src/client-composer-quota.jsx
|
|
169
250
|
var import_react = require("react");
|
|
170
251
|
var import_react_dom = require("react-dom");
|
|
@@ -533,60 +614,66 @@ async function callRpc(rpc, endpoint, payload = {}) {
|
|
|
533
614
|
if (timer) clearTimeout(timer);
|
|
534
615
|
}
|
|
535
616
|
}
|
|
617
|
+
function Chevron() {
|
|
618
|
+
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" }) });
|
|
619
|
+
}
|
|
620
|
+
function Chip({ tone = "off", children }) {
|
|
621
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: `gsChip gsChip--${tone}`, children: [
|
|
622
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsDot" }),
|
|
623
|
+
children
|
|
624
|
+
] });
|
|
625
|
+
}
|
|
536
626
|
function UsagePanel({ usage, t, usageBusy, onRefresh, signedIn }) {
|
|
537
627
|
const ok = usage?.status === "ok";
|
|
538
628
|
const used = ok ? formatPercent(usage.usedPercent) : void 0;
|
|
539
629
|
const remaining = ok ? formatPercent(usage.remainingPercent) : void 0;
|
|
540
630
|
const resetLabel = usage?.periodEndLocal || usage?.periodEnd;
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("
|
|
549
|
-
|
|
631
|
+
const gaugeValue = remaining ?? (used !== void 0 ? formatPercent(100 - Number(used)) : void 0);
|
|
632
|
+
const gaugeLabel = remaining !== void 0 ? t("usageRemaining") : t("usageUsed");
|
|
633
|
+
const fill = typeof gaugeValue === "number" && Number.isFinite(gaugeValue) ? Math.min(100, Math.max(0, gaugeValue)) : 0;
|
|
634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCard", children: [
|
|
635
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsCardHead", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: t("usageTitle") }) }),
|
|
636
|
+
ok && (used !== void 0 || remaining !== void 0) ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsGauge", children: [
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsGaugeTop", children: [
|
|
638
|
+
gaugeValue !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "gsGaugeValue", children: [
|
|
639
|
+
gaugeValue,
|
|
550
640
|
"%"
|
|
551
|
-
] }),
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
641
|
+
] }) : null,
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsGaugeLabel", children: gaugeLabel })
|
|
643
|
+
] }),
|
|
644
|
+
/* @__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}%` } }) }),
|
|
645
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsGaugeMeta", children: [
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
647
|
+
t("usageUsed"),
|
|
555
648
|
" ",
|
|
556
|
-
|
|
649
|
+
used ?? "\u2014",
|
|
557
650
|
"%"
|
|
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: [
|
|
651
|
+
] }),
|
|
652
|
+
resetLabel ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
653
|
+
t("usageReset"),
|
|
654
|
+
" ",
|
|
655
|
+
resetLabel
|
|
656
|
+
] }) : null,
|
|
657
|
+
usage.periodEnd && usage.periodEndLocal ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { children: usage.periodEnd }) : null
|
|
658
|
+
] })
|
|
659
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsEmpty", children: [
|
|
583
660
|
t("usageUnavailable"),
|
|
584
661
|
usage?.reason ? `: ${usage.reason}` : ""
|
|
585
662
|
] }),
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("
|
|
589
|
-
|
|
663
|
+
Array.isArray(usage.productUsage) && usage.productUsage.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "gsRows", children: usage.productUsage.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsRow", children: [
|
|
664
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: row.name ?? "\u2014" }),
|
|
665
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsRowValue", children: typeof row.usedPercent === "number" ? `${formatPercent(row.usedPercent)}%` : "\u2014" })
|
|
666
|
+
] }, `${row.name ?? "row"}-${index}`)) }) : null,
|
|
667
|
+
usage.fetchedAt ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsHint", children: [
|
|
668
|
+
t("usageFetchedAt"),
|
|
669
|
+
": ",
|
|
670
|
+
usage.fetchedAt
|
|
671
|
+
] }) : null,
|
|
672
|
+
usageBusy ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsStatus gsStatus--busy", children: t("busyUsage") }) : null,
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsHint", children: t("usageSubtitle") }),
|
|
674
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsActions", children: [
|
|
675
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn", type: "button", disabled: Boolean(usageBusy) || !signedIn, onClick: onRefresh, children: t("usageRefresh") }),
|
|
676
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { className: "gsLink", href: USAGE_PAGE_URL, target: "_blank", rel: "noreferrer", children: t("usageOpenGrok") })
|
|
590
677
|
] })
|
|
591
678
|
] });
|
|
592
679
|
}
|
|
@@ -660,7 +747,8 @@ function GrokSubscriptionSection({ rpc, t }) {
|
|
|
660
747
|
"login/cli": "loginOk",
|
|
661
748
|
"login/device": "loginOk",
|
|
662
749
|
logout: "logoutOk",
|
|
663
|
-
"usage/refresh": "usageRefreshOk"
|
|
750
|
+
"usage/refresh": "usageRefreshOk",
|
|
751
|
+
"catalog/refresh": "catalogRefreshOk"
|
|
664
752
|
}[endpoint];
|
|
665
753
|
if (successKey) setNotice(t(successKey));
|
|
666
754
|
if (endpoint === "usage/refresh" && value?.ok !== false && !value?.error) {
|
|
@@ -682,47 +770,43 @@ function GrokSubscriptionSection({ rpc, t }) {
|
|
|
682
770
|
const models = catalog?.models ?? [];
|
|
683
771
|
const signedIn = account?.signedIn === true;
|
|
684
772
|
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: [
|
|
773
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: SETTINGS_STYLE }),
|
|
774
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsHead", children: [
|
|
699
775
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t("title") }),
|
|
700
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
776
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Chip, { tone: signedIn ? "ok" : "off", children: signedIn ? t("signedIn") : t("signedOut") })
|
|
701
777
|
] }),
|
|
702
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
": "
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsLead", children: t("subtitle") }),
|
|
779
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCard", children: [
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCardHead", children: [
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: t("account") }),
|
|
782
|
+
signedIn && account?.maskedAccount ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsAccount", children: account.maskedAccount }) : null
|
|
706
783
|
] }),
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("
|
|
784
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsActions", children: [
|
|
785
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn gsBtn--primary", type: "button", disabled: Boolean(busy), onClick: () => void run("login/cli"), children: t("loginCli") }),
|
|
786
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn", type: "button", disabled: Boolean(busy), onClick: () => void run("login/device"), children: t("loginDevice") }),
|
|
787
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn", type: "button", disabled: Boolean(busy), onClick: () => void run("pull"), children: t("pull") }),
|
|
788
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "gsBtn gsBtn--danger", type: "button", disabled: Boolean(busy) || !signedIn, onClick: () => void run("logout"), children: t("logout") })
|
|
789
|
+
] }),
|
|
790
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsStatus gsStatus--busy", children: t("busy") }) : null,
|
|
791
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsStatus gsStatus--ok", children: notice }) : null,
|
|
792
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsStatus gsStatus--error", children: [
|
|
793
|
+
t("error"),
|
|
794
|
+
": ",
|
|
795
|
+
error
|
|
796
|
+
] }) : null,
|
|
797
|
+
status?.cliAvailable === false ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsStatus gsStatus--warn", children: t("cliMissing") }) : null,
|
|
798
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { className: "gsDisclosure", children: [
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("summary", { children: [
|
|
800
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Chevron, {}),
|
|
801
|
+
t("loginHelp")
|
|
802
|
+
] }),
|
|
803
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsDisclosureBody", children: [
|
|
804
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: t("loginHint") }),
|
|
805
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: t("deviceHint") }),
|
|
806
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: t("pullHint") })
|
|
807
|
+
] })
|
|
808
|
+
] })
|
|
714
809
|
] }),
|
|
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
810
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
727
811
|
UsagePanel,
|
|
728
812
|
{
|
|
@@ -733,21 +817,25 @@ function GrokSubscriptionSection({ rpc, t }) {
|
|
|
733
817
|
onRefresh: () => void run("usage/refresh")
|
|
734
818
|
}
|
|
735
819
|
),
|
|
736
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
737
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
738
|
-
|
|
739
|
-
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCard", children: [
|
|
821
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "gsCardHead", children: [
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: t("models") }),
|
|
823
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "gsSpacer" }),
|
|
824
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Chip, { tone: catalog?.source === "live" ? "ok" : catalog?.source === "fallback" ? "warn" : "off", children: sourceLabel(catalog?.source, t) })
|
|
825
|
+
] }),
|
|
826
|
+
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
827
|
model.name,
|
|
741
828
|
" ",
|
|
742
829
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { children: model.id })
|
|
743
830
|
] }, model.id)) }),
|
|
744
|
-
catalog?.error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "error", children: [
|
|
831
|
+
catalog?.error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "gsStatus gsStatus--error", children: [
|
|
745
832
|
t("catalogError"),
|
|
746
833
|
": ",
|
|
747
834
|
catalog.error
|
|
748
|
-
] }) : null
|
|
835
|
+
] }) : null,
|
|
836
|
+
/* @__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
837
|
] }),
|
|
750
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "
|
|
838
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "gsCaveat", children: t("caveats") })
|
|
751
839
|
] });
|
|
752
840
|
}
|
|
753
841
|
function apply(ctx) {
|