@eddyskywalker/dsh-chatgpt-subscription 0.4.0 → 0.6.0
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/CHANGELOG.md +56 -0
- package/README.md +67 -1
- package/lib/client.js +2255 -742
- package/lib/client.js.map +1 -1
- package/lib/index.js +17139 -12058
- package/lib/types/client/CodexSubscriptionSection.d.ts +1 -1
- package/lib/types/client/CodexSubscriptionSection.d.ts.map +1 -1
- package/lib/types/client/ProviderHubSection.d.ts.map +1 -1
- package/lib/types/client/antigravity/AntigravitySection.d.ts.map +1 -1
- package/lib/types/client/antigravity/locales.d.ts +24 -192
- package/lib/types/client/antigravity/locales.d.ts.map +1 -1
- package/lib/types/client/api.d.ts +13 -1
- package/lib/types/client/api.d.ts.map +1 -1
- package/lib/types/client/command-code/CommandCodeSection.d.ts.map +1 -1
- package/lib/types/client/command-code/locales.d.ts +66 -201
- package/lib/types/client/command-code/locales.d.ts.map +1 -1
- package/lib/types/client/common/AccountPoolSection.d.ts +55 -0
- package/lib/types/client/common/AccountPoolSection.d.ts.map +1 -0
- package/lib/types/client/common/account-pool-labels.d.ts +43 -0
- package/lib/types/client/common/account-pool-labels.d.ts.map +1 -0
- package/lib/types/client/common/styles.d.ts +11 -0
- package/lib/types/client/common/styles.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +1 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/kimi-code/KimiCodeSection.d.ts.map +1 -1
- package/lib/types/client/kimi-code/locales.d.ts +63 -336
- package/lib/types/client/kimi-code/locales.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +41 -1
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/workbuddy/WorkBuddyComposerQuota.d.ts +26 -0
- package/lib/types/client/workbuddy/WorkBuddyComposerQuota.d.ts.map +1 -0
- package/lib/types/client/workbuddy/WorkBuddySection.d.ts +41 -0
- package/lib/types/client/workbuddy/WorkBuddySection.d.ts.map +1 -0
- package/lib/types/client/workbuddy/locales.d.ts +563 -0
- package/lib/types/client/workbuddy/locales.d.ts.map +1 -0
- package/lib/types/client/workbuddy/styles.d.ts +11 -0
- package/lib/types/client/workbuddy/styles.d.ts.map +1 -0
- package/lib/types/host/antigravity/account-pool.d.ts +15 -5
- package/lib/types/host/antigravity/account-pool.d.ts.map +1 -1
- package/lib/types/host/antigravity/routes.d.ts.map +1 -1
- package/lib/types/host/codex-account-pool.d.ts +64 -0
- package/lib/types/host/codex-account-pool.d.ts.map +1 -0
- package/lib/types/host/command-code/account-pool.d.ts +60 -0
- package/lib/types/host/command-code/account-pool.d.ts.map +1 -0
- package/lib/types/host/command-code/adapter.d.ts +11 -1
- package/lib/types/host/command-code/adapter.d.ts.map +1 -1
- package/lib/types/host/command-code/client.d.ts +17 -1
- package/lib/types/host/command-code/client.d.ts.map +1 -1
- package/lib/types/host/command-code/oauth.d.ts +4 -1
- package/lib/types/host/command-code/oauth.d.ts.map +1 -1
- package/lib/types/host/command-code/routes.d.ts +11 -2
- package/lib/types/host/command-code/routes.d.ts.map +1 -1
- package/lib/types/host/common/account-pool.d.ts +197 -0
- package/lib/types/host/common/account-pool.d.ts.map +1 -0
- package/lib/types/host/common/home.d.ts +8 -0
- package/lib/types/host/common/home.d.ts.map +1 -0
- package/lib/types/host/kimi-code/account-pool.d.ts +48 -0
- package/lib/types/host/kimi-code/account-pool.d.ts.map +1 -0
- package/lib/types/host/kimi-code/adapter.d.ts +10 -1
- package/lib/types/host/kimi-code/adapter.d.ts.map +1 -1
- package/lib/types/host/kimi-code/client.d.ts +16 -0
- package/lib/types/host/kimi-code/client.d.ts.map +1 -1
- package/lib/types/host/kimi-code/oauth.d.ts +2 -0
- package/lib/types/host/kimi-code/oauth.d.ts.map +1 -1
- package/lib/types/host/kimi-code/routes.d.ts +10 -2
- package/lib/types/host/kimi-code/routes.d.ts.map +1 -1
- package/lib/types/host/oauth-service.d.ts +41 -2
- package/lib/types/host/oauth-service.d.ts.map +1 -1
- package/lib/types/host/preset-sync.d.ts +7 -1
- package/lib/types/host/preset-sync.d.ts.map +1 -1
- package/lib/types/host/responses-client.d.ts +15 -0
- package/lib/types/host/responses-client.d.ts.map +1 -1
- package/lib/types/host/routes.d.ts +2 -1
- package/lib/types/host/routes.d.ts.map +1 -1
- package/lib/types/host/usage-service.d.ts +15 -0
- package/lib/types/host/usage-service.d.ts.map +1 -1
- package/lib/types/host/workbuddy/account-pool.d.ts +106 -0
- package/lib/types/host/workbuddy/account-pool.d.ts.map +1 -0
- package/lib/types/host/workbuddy/adapter.d.ts +97 -0
- package/lib/types/host/workbuddy/adapter.d.ts.map +1 -0
- package/lib/types/host/workbuddy/client.d.ts +90 -0
- package/lib/types/host/workbuddy/client.d.ts.map +1 -0
- package/lib/types/host/workbuddy/mapper.d.ts +114 -0
- package/lib/types/host/workbuddy/mapper.d.ts.map +1 -0
- package/lib/types/host/workbuddy/model-catalog.d.ts +108 -0
- package/lib/types/host/workbuddy/model-catalog.d.ts.map +1 -0
- package/lib/types/host/workbuddy/oauth.d.ts +38 -0
- package/lib/types/host/workbuddy/oauth.d.ts.map +1 -0
- package/lib/types/host/workbuddy/routes.d.ts +33 -0
- package/lib/types/host/workbuddy/routes.d.ts.map +1 -0
- package/lib/types/host/workbuddy/token-store.d.ts +216 -0
- package/lib/types/host/workbuddy/token-store.d.ts.map +1 -0
- package/lib/types/host/workbuddy/types.d.ts +127 -0
- package/lib/types/host/workbuddy/types.d.ts.map +1 -0
- package/lib/types/index.d.ts +10 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/account-pool-contracts.d.ts +55 -0
- package/lib/types/shared/account-pool-contracts.d.ts.map +1 -0
- package/lib/types/shared/antigravity-contracts.d.ts +4 -10
- package/lib/types/shared/antigravity-contracts.d.ts.map +1 -1
- package/lib/types/shared/command-code-contracts.d.ts +14 -0
- package/lib/types/shared/command-code-contracts.d.ts.map +1 -1
- package/lib/types/shared/contracts.d.ts +6 -0
- package/lib/types/shared/contracts.d.ts.map +1 -1
- package/lib/types/shared/kimi-code-contracts.d.ts +14 -0
- package/lib/types/shared/kimi-code-contracts.d.ts.map +1 -1
- package/lib/types/shared/workbuddy-contracts.d.ts +204 -0
- package/lib/types/shared/workbuddy-contracts.d.ts.map +1 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -56,7 +56,7 @@ window.__ModuleLoader__.load({
|
|
|
56
56
|
//#endregion
|
|
57
57
|
//#region src/client/CodexComposerQuota.tsx
|
|
58
58
|
function CodexComposerQuota({ api, directory, loadModelDirectory, t }) {
|
|
59
|
-
const modelState = useStore$
|
|
59
|
+
const modelState = useStore$4(directory);
|
|
60
60
|
const [status, setStatus] = (0, react.useState)(null);
|
|
61
61
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
62
62
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -103,7 +103,7 @@ window.__ModuleLoader__.load({
|
|
|
103
103
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("quickQuotaLabel") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota === null ? loading ? t("quickQuotaLoading") : "—" : formatPercent$1(quota.remainingPercent) })]
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
|
-
function useStore$
|
|
106
|
+
function useStore$4(store) {
|
|
107
107
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
108
108
|
}
|
|
109
109
|
function formatPercent$1(value) {
|
|
@@ -313,8 +313,21 @@ window.__ModuleLoader__.load({
|
|
|
313
313
|
cancelLogin(loginId) {
|
|
314
314
|
return post(`${ROUTE_PREFIX}/login/cancel`, { loginId });
|
|
315
315
|
}
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
/** Sign out one pooled account; without an id, the active one. */
|
|
317
|
+
logout(accountId) {
|
|
318
|
+
return post(`${ROUTE_PREFIX}/logout`, accountId === void 0 ? {} : { accountId });
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* One account-pool action, returning the refreshed status.
|
|
322
|
+
*
|
|
323
|
+
* The host answers with the same envelope the status route uses, so the card
|
|
324
|
+
* never has to guess what the pool looks like after a change.
|
|
325
|
+
*/
|
|
326
|
+
accountAction(action, body = {}) {
|
|
327
|
+
return post(`${ROUTE_PREFIX}/accounts`, {
|
|
328
|
+
action,
|
|
329
|
+
...body
|
|
330
|
+
});
|
|
318
331
|
}
|
|
319
332
|
refresh() {
|
|
320
333
|
return post(`${ROUTE_PREFIX}/token/refresh`, {});
|
|
@@ -360,6 +373,275 @@ window.__ModuleLoader__.load({
|
|
|
360
373
|
}
|
|
361
374
|
}
|
|
362
375
|
//#endregion
|
|
376
|
+
//#region src/client/common/account-pool-labels.ts
|
|
377
|
+
/** Chinese labels; the wording the Antigravity card shipped with. */
|
|
378
|
+
const accountPoolZh = {
|
|
379
|
+
accountPool: "账号管理",
|
|
380
|
+
addAccount: "添加账号",
|
|
381
|
+
accountCount: "已登录 {count} 个账号",
|
|
382
|
+
primaryAccount: "主账号",
|
|
383
|
+
activeAccount: "当前使用",
|
|
384
|
+
setPrimary: "设为主账号",
|
|
385
|
+
deleteAccount: "删除",
|
|
386
|
+
cooling: "冷却中",
|
|
387
|
+
cooldownLeft: "剩 {minutes} 分",
|
|
388
|
+
clearCooldown: "重置冷却",
|
|
389
|
+
needsRelogin: "需重新登录",
|
|
390
|
+
relogin: "重新登录",
|
|
391
|
+
rotationStrategy: "调度策略",
|
|
392
|
+
strategySequential: "顺序耗尽(当前优先,遇限流自动切号)",
|
|
393
|
+
strategyRoundRobin: "轮询调度(按账号循环均匀分摊)",
|
|
394
|
+
strategySticky: "粘性会话(保持当前账号,遇限流才切换)",
|
|
395
|
+
noAccounts: "暂无账号,点击「添加账号」完成登录授权。",
|
|
396
|
+
storage: "凭据存储",
|
|
397
|
+
storageNotice: "令牌由 Host 保存于本地安全存储,不会进入浏览器。",
|
|
398
|
+
email: "邮箱",
|
|
399
|
+
expires: "令牌到期",
|
|
400
|
+
lastUsed: "上次调用",
|
|
401
|
+
accountId: "账号 ID"
|
|
402
|
+
};
|
|
403
|
+
/** English labels for the ChatGPT tab, which is the bilingual one. */
|
|
404
|
+
const accountPoolEn = {
|
|
405
|
+
accountPool: "Account Management",
|
|
406
|
+
addAccount: "Add Account",
|
|
407
|
+
accountCount: "{count} account(s) signed in",
|
|
408
|
+
primaryAccount: "Primary",
|
|
409
|
+
activeAccount: "In Use",
|
|
410
|
+
setPrimary: "Set as Primary",
|
|
411
|
+
deleteAccount: "Delete",
|
|
412
|
+
cooling: "In Cooldown",
|
|
413
|
+
cooldownLeft: "{minutes} min left",
|
|
414
|
+
clearCooldown: "Clear Cooldown",
|
|
415
|
+
needsRelogin: "Sign-in required",
|
|
416
|
+
relogin: "Sign in again",
|
|
417
|
+
rotationStrategy: "Scheduling Strategy",
|
|
418
|
+
strategySequential: "Sequential Drain (primary first, fail over on 429)",
|
|
419
|
+
strategyRoundRobin: "Round-Robin (evenly rotate across accounts)",
|
|
420
|
+
strategySticky: "Sticky Session (keep the current account until it is limited)",
|
|
421
|
+
noAccounts: "No accounts yet. Click \"Add Account\" to authorize.",
|
|
422
|
+
storage: "Credential storage",
|
|
423
|
+
storageNotice: "Credentials are stored locally by the Host and never sent to the browser.",
|
|
424
|
+
email: "Email",
|
|
425
|
+
expires: "Token expires",
|
|
426
|
+
lastUsed: "Last used",
|
|
427
|
+
accountId: "Account ID"
|
|
428
|
+
};
|
|
429
|
+
/** Replace `{name}` placeholders in one label. */
|
|
430
|
+
function formatPoolLabel(template, values) {
|
|
431
|
+
return template.replace(/\{(\w+)\}/g, (match, name) => name in values ? String(values[name]) : match);
|
|
432
|
+
}
|
|
433
|
+
//#endregion
|
|
434
|
+
//#region src/client/common/AccountPoolSection.tsx
|
|
435
|
+
/** Format one account timestamp the way every tab renders it. */
|
|
436
|
+
function formatAccountDate(ms) {
|
|
437
|
+
if (!ms || ms <= 0) return "—";
|
|
438
|
+
try {
|
|
439
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
440
|
+
dateStyle: "medium",
|
|
441
|
+
timeStyle: "short"
|
|
442
|
+
}).format(ms);
|
|
443
|
+
} catch {
|
|
444
|
+
return "—";
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
/** Whole minutes left in a cooldown, never below one. */
|
|
448
|
+
function cooldownMinutesLeft(cooldownUntil, now = Date.now()) {
|
|
449
|
+
return Math.max(1, Math.ceil((cooldownUntil - now) / 6e4));
|
|
450
|
+
}
|
|
451
|
+
/** Whether one account currently carries a live 429 cooldown. */
|
|
452
|
+
function isCoolingDown(account, now = Date.now()) {
|
|
453
|
+
return typeof account.cooldownUntil === "number" && account.cooldownUntil > now;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* The account-management group every provider tab renders.
|
|
457
|
+
*
|
|
458
|
+
* One component rather than four near-identical blocks: the account card, its
|
|
459
|
+
* badges, the rotation-strategy picker and the storage notice are identical
|
|
460
|
+
* across providers, and only the identity details differ.
|
|
461
|
+
*/
|
|
462
|
+
function AccountPoolSection(props) {
|
|
463
|
+
const t = props.labels;
|
|
464
|
+
const accounts = props.accounts;
|
|
465
|
+
const now = Date.now();
|
|
466
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
467
|
+
className: "dsha-group",
|
|
468
|
+
children: [
|
|
469
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
470
|
+
className: "dsha-grouphead",
|
|
471
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", { children: [t.accountPool, accounts.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
472
|
+
className: "dsha-muted",
|
|
473
|
+
style: {
|
|
474
|
+
fontWeight: 400,
|
|
475
|
+
marginLeft: 8
|
|
476
|
+
},
|
|
477
|
+
children: [
|
|
478
|
+
"(",
|
|
479
|
+
formatPoolLabel(t.accountCount, { count: accounts.length }),
|
|
480
|
+
")"
|
|
481
|
+
]
|
|
482
|
+
})] }), props.renderLoginActions !== void 0 ? props.renderLoginActions() : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
483
|
+
className: "dsha-btn dsha-btn-primary",
|
|
484
|
+
disabled: props.busy !== null,
|
|
485
|
+
onClick: props.onLogin,
|
|
486
|
+
children: props.loginBusyLabel || t.addAccount
|
|
487
|
+
})]
|
|
488
|
+
}),
|
|
489
|
+
accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
490
|
+
className: "dsha-pref-row",
|
|
491
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.rotationStrategy }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
492
|
+
className: "dsha-muted",
|
|
493
|
+
style: {
|
|
494
|
+
fontSize: 12,
|
|
495
|
+
marginTop: 2
|
|
496
|
+
},
|
|
497
|
+
children: props.rotationStrategy === "round-robin" ? t.strategyRoundRobin : props.rotationStrategy === "sticky" ? t.strategySticky : t.strategySequential
|
|
498
|
+
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
499
|
+
className: "dsha-select",
|
|
500
|
+
"aria-label": t.rotationStrategy,
|
|
501
|
+
value: props.rotationStrategy,
|
|
502
|
+
disabled: props.busy !== null,
|
|
503
|
+
onChange: (event) => props.onSetStrategy(event.target.value),
|
|
504
|
+
children: [
|
|
505
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
506
|
+
value: "sequential",
|
|
507
|
+
children: "顺序耗尽"
|
|
508
|
+
}),
|
|
509
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
510
|
+
value: "round-robin",
|
|
511
|
+
children: "轮询调度"
|
|
512
|
+
}),
|
|
513
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
514
|
+
value: "sticky",
|
|
515
|
+
children: "粘性会话"
|
|
516
|
+
})
|
|
517
|
+
]
|
|
518
|
+
})]
|
|
519
|
+
}),
|
|
520
|
+
accounts.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
521
|
+
className: "dsha-empty",
|
|
522
|
+
children: t.noAccounts
|
|
523
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
524
|
+
className: "dsha-accounts-list",
|
|
525
|
+
children: accounts.map((account) => {
|
|
526
|
+
const isActive = account.id === props.activeAccountId;
|
|
527
|
+
const cooling = isCoolingDown(account, now);
|
|
528
|
+
const needsRelogin = account.authStatus !== void 0 && account.authStatus !== "ok";
|
|
529
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
530
|
+
className: `dsha-account-card ${isActive ? "active" : ""}`,
|
|
531
|
+
children: [
|
|
532
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
533
|
+
className: "dsha-account-header",
|
|
534
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
535
|
+
className: "dsha-account-identity",
|
|
536
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
537
|
+
className: "dsha-account-title",
|
|
538
|
+
children: account.alias || account.email || account.id
|
|
539
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
540
|
+
className: "dsha-badges",
|
|
541
|
+
children: [
|
|
542
|
+
account.isPrimary && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
543
|
+
className: "dsha-badge primary",
|
|
544
|
+
children: t.primaryAccount
|
|
545
|
+
}),
|
|
546
|
+
isActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
547
|
+
className: "dsha-badge active",
|
|
548
|
+
children: t.activeAccount
|
|
549
|
+
}),
|
|
550
|
+
cooling && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
551
|
+
className: "dsha-badge cooldown",
|
|
552
|
+
children: [
|
|
553
|
+
t.cooling,
|
|
554
|
+
"(",
|
|
555
|
+
formatPoolLabel(t.cooldownLeft, { minutes: cooldownMinutesLeft(account.cooldownUntil, now) }),
|
|
556
|
+
")"
|
|
557
|
+
]
|
|
558
|
+
}),
|
|
559
|
+
needsRelogin && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
560
|
+
className: "dsha-badge danger",
|
|
561
|
+
children: t.needsRelogin
|
|
562
|
+
})
|
|
563
|
+
]
|
|
564
|
+
})]
|
|
565
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
566
|
+
className: "dsha-account-actions",
|
|
567
|
+
children: [
|
|
568
|
+
props.renderAccountActions?.(account),
|
|
569
|
+
!account.isPrimary && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
570
|
+
className: "dsha-btn",
|
|
571
|
+
disabled: props.busy !== null,
|
|
572
|
+
onClick: () => props.onSetPrimary(account.id),
|
|
573
|
+
children: t.setPrimary
|
|
574
|
+
}),
|
|
575
|
+
cooling && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
576
|
+
className: "dsha-btn",
|
|
577
|
+
disabled: props.busy !== null,
|
|
578
|
+
onClick: () => props.onClearCooldown(account.id),
|
|
579
|
+
children: t.clearCooldown
|
|
580
|
+
}),
|
|
581
|
+
needsRelogin && props.onRelogin && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
582
|
+
className: "dsha-btn",
|
|
583
|
+
disabled: props.busy !== null,
|
|
584
|
+
onClick: () => props.onRelogin(account.id),
|
|
585
|
+
children: t.relogin
|
|
586
|
+
}),
|
|
587
|
+
account.removable !== false && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
588
|
+
className: "dsha-btn",
|
|
589
|
+
disabled: props.busy !== null,
|
|
590
|
+
onClick: () => props.onDelete(account.id),
|
|
591
|
+
children: t.deleteAccount
|
|
592
|
+
})
|
|
593
|
+
]
|
|
594
|
+
})]
|
|
595
|
+
}),
|
|
596
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
597
|
+
className: "dsha-account-details",
|
|
598
|
+
children: [
|
|
599
|
+
props.renderDetails?.(account),
|
|
600
|
+
account.email && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
601
|
+
t.email,
|
|
602
|
+
": ",
|
|
603
|
+
account.email
|
|
604
|
+
] }),
|
|
605
|
+
account.expiresAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
606
|
+
t.expires,
|
|
607
|
+
": ",
|
|
608
|
+
formatAccountDate(account.expiresAt)
|
|
609
|
+
] }),
|
|
610
|
+
account.lastUsedAt !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
611
|
+
t.lastUsed,
|
|
612
|
+
": ",
|
|
613
|
+
formatAccountDate(account.lastUsedAt)
|
|
614
|
+
] })
|
|
615
|
+
]
|
|
616
|
+
}),
|
|
617
|
+
needsRelogin && account.authFailedReason && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
618
|
+
className: "dsha-account-details",
|
|
619
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: account.authFailedReason })
|
|
620
|
+
})
|
|
621
|
+
]
|
|
622
|
+
}, account.id);
|
|
623
|
+
})
|
|
624
|
+
}),
|
|
625
|
+
props.children,
|
|
626
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
627
|
+
className: "dsha-row",
|
|
628
|
+
style: { marginTop: 12 },
|
|
629
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
630
|
+
className: "dsha-label",
|
|
631
|
+
children: t.storage
|
|
632
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
633
|
+
className: "dsha-value",
|
|
634
|
+
children: props.storageValue ?? "本地安全存储 (JSON/DPAPI)"
|
|
635
|
+
})]
|
|
636
|
+
}),
|
|
637
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
638
|
+
className: "dsha-notice",
|
|
639
|
+
children: t.storageNotice
|
|
640
|
+
})
|
|
641
|
+
]
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
//#endregion
|
|
363
645
|
//#region src/client/CodexSubscriptionSection.tsx
|
|
364
646
|
function CodexSubscriptionSection({ t }) {
|
|
365
647
|
const apiRef = (0, react.useRef)(new SubscriptionApi());
|
|
@@ -531,14 +813,71 @@ window.__ModuleLoader__.load({
|
|
|
531
813
|
await updatePreferences({ customProxyUrl: draft ? draft : null });
|
|
532
814
|
setCustomProxyDraft(null);
|
|
533
815
|
};
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
816
|
+
/**
|
|
817
|
+
* The shared card takes a label object while this tab translates by key, so
|
|
818
|
+
* every pool label is resolved through the tab's own translator and follows
|
|
819
|
+
* whichever locale is active.
|
|
820
|
+
*/
|
|
821
|
+
const poolLabels = (() => {
|
|
822
|
+
const keys = [
|
|
823
|
+
"accountPool",
|
|
824
|
+
"addAccount",
|
|
825
|
+
"accountCount",
|
|
826
|
+
"primaryAccount",
|
|
827
|
+
"activeAccount",
|
|
828
|
+
"setPrimary",
|
|
829
|
+
"deleteAccount",
|
|
830
|
+
"cooling",
|
|
831
|
+
"cooldownLeft",
|
|
832
|
+
"clearCooldown",
|
|
833
|
+
"needsRelogin",
|
|
834
|
+
"relogin",
|
|
835
|
+
"rotationStrategy",
|
|
836
|
+
"strategySequential",
|
|
837
|
+
"strategyRoundRobin",
|
|
838
|
+
"strategySticky",
|
|
839
|
+
"noAccounts",
|
|
840
|
+
"storage",
|
|
841
|
+
"storageNotice",
|
|
842
|
+
"email",
|
|
843
|
+
"expires",
|
|
844
|
+
"lastUsed",
|
|
845
|
+
"accountId"
|
|
846
|
+
];
|
|
847
|
+
const labels = {};
|
|
848
|
+
for (const key of keys) labels[key] = t(key);
|
|
849
|
+
return labels;
|
|
850
|
+
})();
|
|
851
|
+
const accountAction = async (action, accountId) => {
|
|
852
|
+
await run(action, async () => {
|
|
853
|
+
const next = await apiRef.current.accountAction(action, { accountId });
|
|
854
|
+
setStatus(next);
|
|
855
|
+
});
|
|
856
|
+
};
|
|
857
|
+
const setRotationStrategy = async (strategy) => {
|
|
858
|
+
await run("strategy", async () => {
|
|
859
|
+
const next = await apiRef.current.accountAction("strategy", { strategy });
|
|
860
|
+
setStatus(next);
|
|
861
|
+
});
|
|
862
|
+
};
|
|
863
|
+
/**
|
|
864
|
+
* Re-authorize one account.
|
|
865
|
+
*
|
|
866
|
+
* The failure marker is cleared first and nothing is deleted: the account
|
|
867
|
+
* keeps its alias and place in the rotation.
|
|
868
|
+
*/
|
|
869
|
+
const relogin = (accountId) => {
|
|
870
|
+
(async () => {
|
|
871
|
+
try {
|
|
872
|
+
const next = await apiRef.current.accountAction("relogin", { accountId });
|
|
873
|
+
setStatus(next);
|
|
874
|
+
} catch (cause) {
|
|
875
|
+
setError(messageOf(cause));
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
await startLogin();
|
|
879
|
+
})();
|
|
880
|
+
};
|
|
542
881
|
const run = async (action, task) => {
|
|
543
882
|
setBusy(action);
|
|
544
883
|
setError(null);
|
|
@@ -551,14 +890,14 @@ window.__ModuleLoader__.load({
|
|
|
551
890
|
setBusy(null);
|
|
552
891
|
}
|
|
553
892
|
};
|
|
554
|
-
|
|
893
|
+
status?.account;
|
|
555
894
|
const preferences = status?.preferences;
|
|
556
895
|
const quota = status?.quota;
|
|
557
896
|
const storage = status?.storage;
|
|
558
897
|
const login = status?.login;
|
|
559
898
|
const visibleModelIds = preferences?.visibleModelIds ?? DEFAULT_VISIBLE_CODEX_MODEL_IDS;
|
|
560
899
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
561
|
-
className: "
|
|
900
|
+
className: "dsha-page",
|
|
562
901
|
"aria-labelledby": "dsh-codex-title",
|
|
563
902
|
children: [
|
|
564
903
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
@@ -579,37 +918,36 @@ window.__ModuleLoader__.load({
|
|
|
579
918
|
}) : null]
|
|
580
919
|
}) : null,
|
|
581
920
|
status === null && error === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Skeleton, { label: t("loading") }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
582
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
583
|
-
|
|
921
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(AccountPoolSection, {
|
|
922
|
+
accounts: status?.accounts ?? [],
|
|
923
|
+
activeAccountId: status?.activeAccountId,
|
|
924
|
+
rotationStrategy: status?.rotationStrategy ?? "sequential",
|
|
925
|
+
busy,
|
|
926
|
+
labels: poolLabels,
|
|
927
|
+
loginBusyLabel: login?.active ? t("pending") : void 0,
|
|
928
|
+
onLogin: () => void startLogin(),
|
|
929
|
+
onSetPrimary: (accountId) => void accountAction("set-primary", accountId),
|
|
930
|
+
onDelete: (accountId) => void accountAction("delete", accountId),
|
|
931
|
+
onClearCooldown: (accountId) => void accountAction("clear-cooldown", accountId),
|
|
932
|
+
onRelogin: (accountId) => relogin(accountId),
|
|
933
|
+
onSetStrategy: (strategy) => void setRotationStrategy(strategy),
|
|
934
|
+
storageValue: storageLabel(storage, t),
|
|
935
|
+
renderDetails: (entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [entry.planLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
936
|
+
t("plan"),
|
|
937
|
+
": ",
|
|
938
|
+
entry.planLabel
|
|
939
|
+
] }), entry.email && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
940
|
+
t("email"),
|
|
941
|
+
": ",
|
|
942
|
+
entry.email
|
|
943
|
+
] })] }),
|
|
584
944
|
children: [
|
|
585
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoRow, {
|
|
586
|
-
label: status?.authenticated ? t("signedIn") : t("signedOut"),
|
|
587
|
-
value: account?.email ?? "—"
|
|
588
|
-
}),
|
|
589
|
-
status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
590
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoRow, {
|
|
591
|
-
label: t("plan"),
|
|
592
|
-
value: account?.planType ?? t("unknown")
|
|
593
|
-
}),
|
|
594
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoRow, {
|
|
595
|
-
label: t("accountId"),
|
|
596
|
-
value: account?.accountIdSuffix ?? "—"
|
|
597
|
-
}),
|
|
598
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoRow, {
|
|
599
|
-
label: t("expires"),
|
|
600
|
-
value: formatDate$3(account?.tokenExpiresAt)
|
|
601
|
-
})
|
|
602
|
-
] }) : null,
|
|
603
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoRow, {
|
|
604
|
-
label: t("storage"),
|
|
605
|
-
value: storageLabel(storage, t)
|
|
606
|
-
}),
|
|
607
945
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
608
|
-
className: "
|
|
946
|
+
className: "dsha-notice",
|
|
609
947
|
children: storageNotice(storage, t)
|
|
610
948
|
}),
|
|
611
949
|
login?.active ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
612
|
-
className: "
|
|
950
|
+
className: "dsha-muted",
|
|
613
951
|
role: "status",
|
|
614
952
|
children: t("pending")
|
|
615
953
|
}) : null,
|
|
@@ -625,25 +963,16 @@ window.__ModuleLoader__.load({
|
|
|
625
963
|
children: t("continueLogin")
|
|
626
964
|
}) : null,
|
|
627
965
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
628
|
-
className: "
|
|
966
|
+
className: "dsha-actions",
|
|
629
967
|
children: [login?.active ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
630
968
|
disabled: busy !== null,
|
|
631
969
|
onClick: cancelLogin,
|
|
632
970
|
children: t("cancel")
|
|
633
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
634
|
-
primary: true,
|
|
635
|
-
disabled: busy !== null || storage?.available === false,
|
|
636
|
-
onClick: startLogin,
|
|
637
|
-
children: status?.authenticated ? t("signInAgain") : t("signIn")
|
|
638
|
-
}), status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
971
|
+
}) : null, status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
639
972
|
disabled: busy !== null,
|
|
640
973
|
onClick: refreshToken,
|
|
641
974
|
children: t("refreshToken")
|
|
642
|
-
})
|
|
643
|
-
disabled: busy !== null,
|
|
644
|
-
onClick: logout,
|
|
645
|
-
children: t("signOut")
|
|
646
|
-
})] }) : null]
|
|
975
|
+
}) : null]
|
|
647
976
|
})
|
|
648
977
|
]
|
|
649
978
|
}),
|
|
@@ -651,7 +980,7 @@ window.__ModuleLoader__.load({
|
|
|
651
980
|
title: t("connection"),
|
|
652
981
|
children: [
|
|
653
982
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
654
|
-
className: "
|
|
983
|
+
className: "dsha-pref-row",
|
|
655
984
|
style: { marginBottom: 12 },
|
|
656
985
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("enableProvider") }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
657
986
|
type: "checkbox",
|
|
@@ -683,11 +1012,11 @@ window.__ModuleLoader__.load({
|
|
|
683
1012
|
value: `${connection.latencyMs} ms · ${formatDate$3(connection.checkedAt)}`
|
|
684
1013
|
}) : null,
|
|
685
1014
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
686
|
-
className: "
|
|
1015
|
+
className: "dsha-muted dsha-models-hint",
|
|
687
1016
|
children: t("modelsHint")
|
|
688
1017
|
}),
|
|
689
1018
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
690
|
-
className: "
|
|
1019
|
+
className: "dsha-models",
|
|
691
1020
|
"aria-label": t("models"),
|
|
692
1021
|
children: CODEX_MODEL_CATALOG.map((model) => {
|
|
693
1022
|
const checked = visibleModelIds.some((id) => id === model.id);
|
|
@@ -720,7 +1049,7 @@ window.__ModuleLoader__.load({
|
|
|
720
1049
|
})]
|
|
721
1050
|
}),
|
|
722
1051
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
723
|
-
className: "
|
|
1052
|
+
className: "dsha-actions",
|
|
724
1053
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
725
1054
|
disabled: !status?.authenticated || busy !== null,
|
|
726
1055
|
onClick: testConnection,
|
|
@@ -733,12 +1062,12 @@ window.__ModuleLoader__.load({
|
|
|
733
1062
|
title: t("proxySettings"),
|
|
734
1063
|
children: [
|
|
735
1064
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
736
|
-
className: "
|
|
1065
|
+
className: "dsha-pref-row",
|
|
737
1066
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("proxyMode") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
738
|
-
className: "
|
|
1067
|
+
className: "dsha-muted",
|
|
739
1068
|
children: t("proxyModeHint")
|
|
740
1069
|
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
741
|
-
className: "
|
|
1070
|
+
className: "dsha-select",
|
|
742
1071
|
"aria-label": t("proxyMode"),
|
|
743
1072
|
value: preferences?.proxyMode ?? "auto",
|
|
744
1073
|
disabled: busy !== null,
|
|
@@ -782,22 +1111,22 @@ window.__ModuleLoader__.load({
|
|
|
782
1111
|
children: t("proxyDetectedEffective")
|
|
783
1112
|
})
|
|
784
1113
|
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
785
|
-
className: "
|
|
1114
|
+
className: "dsha-muted",
|
|
786
1115
|
children: t("proxyNoneDetected")
|
|
787
1116
|
})
|
|
788
1117
|
}) : null,
|
|
789
1118
|
preferences?.proxyMode === "direct" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
790
|
-
className: "
|
|
1119
|
+
className: "dsha-muted",
|
|
791
1120
|
style: { margin: "8px 0 0" },
|
|
792
1121
|
children: t("proxyDirectHint")
|
|
793
1122
|
}) : null,
|
|
794
1123
|
preferences?.proxyMode === "custom" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
795
|
-
className: "
|
|
1124
|
+
className: "dsha-context-settings",
|
|
796
1125
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("customProxyUrl") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
797
|
-
className: "
|
|
1126
|
+
className: "dsha-muted",
|
|
798
1127
|
children: t("customProxyUrlHint")
|
|
799
1128
|
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
800
|
-
className: "
|
|
1129
|
+
className: "dsha-context-row",
|
|
801
1130
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
802
1131
|
className: "dsh-codex-proxy-control",
|
|
803
1132
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
@@ -816,7 +1145,7 @@ window.__ModuleLoader__.load({
|
|
|
816
1145
|
updateCustomProxyUrl();
|
|
817
1146
|
}
|
|
818
1147
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
819
|
-
className: "
|
|
1148
|
+
className: "dsha-context-save",
|
|
820
1149
|
type: "button",
|
|
821
1150
|
"aria-label": t("saveProxyUrl"),
|
|
822
1151
|
disabled: busy !== null || customProxyDraft === null,
|
|
@@ -832,9 +1161,9 @@ window.__ModuleLoader__.load({
|
|
|
832
1161
|
title: t("enhancements"),
|
|
833
1162
|
children: [
|
|
834
1163
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
835
|
-
className: "
|
|
1164
|
+
className: "dsha-pref-row",
|
|
836
1165
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("searchProvider") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
837
|
-
className: "
|
|
1166
|
+
className: "dsha-muted",
|
|
838
1167
|
children: t("searchProviderHint")
|
|
839
1168
|
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
840
1169
|
className: "dsh-codex-segments",
|
|
@@ -858,12 +1187,12 @@ window.__ModuleLoader__.load({
|
|
|
858
1187
|
})]
|
|
859
1188
|
}),
|
|
860
1189
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
861
|
-
className: "
|
|
1190
|
+
className: "dsha-pref-row",
|
|
862
1191
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("outputVerbosity") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
863
|
-
className: "
|
|
1192
|
+
className: "dsha-muted",
|
|
864
1193
|
children: t("outputVerbosityHint")
|
|
865
1194
|
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
866
|
-
className: "
|
|
1195
|
+
className: "dsha-select",
|
|
867
1196
|
"aria-label": t("outputVerbosity"),
|
|
868
1197
|
value: preferences?.outputVerbosity ?? "",
|
|
869
1198
|
disabled: busy !== null,
|
|
@@ -892,12 +1221,12 @@ window.__ModuleLoader__.load({
|
|
|
892
1221
|
})]
|
|
893
1222
|
}),
|
|
894
1223
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
895
|
-
className: "
|
|
1224
|
+
className: "dsha-pref-row",
|
|
896
1225
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("reasoningSummary") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
897
|
-
className: "
|
|
1226
|
+
className: "dsha-muted",
|
|
898
1227
|
children: t("reasoningSummaryHint")
|
|
899
1228
|
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
900
|
-
className: "
|
|
1229
|
+
className: "dsha-select",
|
|
901
1230
|
"aria-label": t("reasoningSummary"),
|
|
902
1231
|
value: preferences?.reasoningSummary ?? "",
|
|
903
1232
|
disabled: busy !== null,
|
|
@@ -930,9 +1259,9 @@ window.__ModuleLoader__.load({
|
|
|
930
1259
|
})]
|
|
931
1260
|
}),
|
|
932
1261
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
933
|
-
className: "
|
|
1262
|
+
className: "dsha-context-settings",
|
|
934
1263
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("contextWindows") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
935
|
-
className: "
|
|
1264
|
+
className: "dsha-muted",
|
|
936
1265
|
children: t("contextWindowsHint")
|
|
937
1266
|
})] }), CONFIGURABLE_CONTEXT_MODEL_IDS.map((model) => {
|
|
938
1267
|
const entry = resolveCodexCatalogEntry(model);
|
|
@@ -942,18 +1271,18 @@ window.__ModuleLoader__.load({
|
|
|
942
1271
|
const dirty = draft !== void 0 && parsedDraft !== fallback;
|
|
943
1272
|
const inputId = `dsh-codex-context-${model}`;
|
|
944
1273
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
945
|
-
className: "
|
|
1274
|
+
className: "dsha-context-row",
|
|
946
1275
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
947
1276
|
htmlFor: inputId,
|
|
948
1277
|
children: entry.name
|
|
949
1278
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
950
|
-
className: "
|
|
1279
|
+
className: "dsha-capacity-control",
|
|
951
1280
|
children: [
|
|
952
1281
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
953
1282
|
id: inputId,
|
|
954
1283
|
type: "text",
|
|
955
1284
|
inputMode: "numeric",
|
|
956
|
-
value: draft ?? formatCapacity$
|
|
1285
|
+
value: draft ?? formatCapacity$4(fallback),
|
|
957
1286
|
disabled: busy !== null,
|
|
958
1287
|
"aria-label": entry.name + " " + t("contextWindow"),
|
|
959
1288
|
onChange: (event) => {
|
|
@@ -971,7 +1300,7 @@ window.__ModuleLoader__.load({
|
|
|
971
1300
|
}),
|
|
972
1301
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") }),
|
|
973
1302
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
974
|
-
className: "
|
|
1303
|
+
className: "dsha-context-save",
|
|
975
1304
|
type: "button",
|
|
976
1305
|
"data-model": model,
|
|
977
1306
|
"aria-label": entry.name + " " + t("saveContextWindow"),
|
|
@@ -1013,7 +1342,7 @@ window.__ModuleLoader__.load({
|
|
|
1013
1342
|
}),
|
|
1014
1343
|
children: [
|
|
1015
1344
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1016
|
-
className: "
|
|
1345
|
+
className: "dsha-muted",
|
|
1017
1346
|
children: t("quotaIntro")
|
|
1018
1347
|
}),
|
|
1019
1348
|
quota?.state === "signed-out" || !status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
@@ -1083,16 +1412,16 @@ window.__ModuleLoader__.load({
|
|
|
1083
1412
|
}
|
|
1084
1413
|
function Section({ title, aside, children }) {
|
|
1085
1414
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1086
|
-
className: "
|
|
1415
|
+
className: "dsha-group",
|
|
1087
1416
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1088
|
-
className: "
|
|
1417
|
+
className: "dsha-grouphead",
|
|
1089
1418
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: title }), aside]
|
|
1090
1419
|
}), children]
|
|
1091
1420
|
});
|
|
1092
1421
|
}
|
|
1093
1422
|
function Button({ primary = false, disabled, onClick, children }) {
|
|
1094
1423
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1095
|
-
className: `
|
|
1424
|
+
className: `dsha-btn${primary ? " dsha-btn-primary" : ""}`,
|
|
1096
1425
|
type: "button",
|
|
1097
1426
|
disabled,
|
|
1098
1427
|
onClick: () => void onClick(),
|
|
@@ -1101,12 +1430,12 @@ window.__ModuleLoader__.load({
|
|
|
1101
1430
|
}
|
|
1102
1431
|
function InfoRow({ label, value }) {
|
|
1103
1432
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1104
|
-
className: "
|
|
1433
|
+
className: "dsha-row",
|
|
1105
1434
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1106
|
-
className: "
|
|
1435
|
+
className: "dsha-label",
|
|
1107
1436
|
children: label
|
|
1108
1437
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1109
|
-
className: "
|
|
1438
|
+
className: "dsha-value",
|
|
1110
1439
|
children: value
|
|
1111
1440
|
})]
|
|
1112
1441
|
});
|
|
@@ -1159,7 +1488,7 @@ window.__ModuleLoader__.load({
|
|
|
1159
1488
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("small", { children: [
|
|
1160
1489
|
t("resetCreditExpires"),
|
|
1161
1490
|
": ",
|
|
1162
|
-
resetCredits.expiresAt == null ? t("unknown") : formatReset$
|
|
1491
|
+
resetCredits.expiresAt == null ? t("unknown") : formatReset$3(resetCredits.expiresAt)
|
|
1163
1492
|
] })
|
|
1164
1493
|
]
|
|
1165
1494
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
@@ -1192,7 +1521,7 @@ window.__ModuleLoader__.load({
|
|
|
1192
1521
|
}),
|
|
1193
1522
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1194
1523
|
className: "dsh-codex-meter-meta",
|
|
1195
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: percent >= 100 ? `${t("exhausted")} · ${formatPercent(remaining)} ${t("remaining")}` : `${formatPercent(percent)} ${t("used")} · ${formatPercent(remaining)} ${t("remaining")}` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: window?.resetsAt == null ? "—" : `${t("resets")}: ${formatReset$
|
|
1524
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: percent >= 100 ? `${t("exhausted")} · ${formatPercent(remaining)} ${t("remaining")}` : `${formatPercent(percent)} ${t("used")} · ${formatPercent(remaining)} ${t("remaining")}` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: window?.resetsAt == null ? "—" : `${t("resets")}: ${formatReset$3(window.resetsAt)}` })]
|
|
1196
1525
|
})
|
|
1197
1526
|
]
|
|
1198
1527
|
});
|
|
@@ -1218,7 +1547,7 @@ window.__ModuleLoader__.load({
|
|
|
1218
1547
|
return `${value} ${t("limitWindow")}`;
|
|
1219
1548
|
}
|
|
1220
1549
|
}
|
|
1221
|
-
function parsePositiveCapacity$
|
|
1550
|
+
function parsePositiveCapacity$4(value) {
|
|
1222
1551
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
1223
1552
|
if (matched === null) return null;
|
|
1224
1553
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
@@ -1226,10 +1555,10 @@ window.__ModuleLoader__.load({
|
|
|
1226
1555
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
1227
1556
|
}
|
|
1228
1557
|
function parseCapacity(value, maxContextWindow = GPT_56_MAX_CONTEXT_WINDOW) {
|
|
1229
|
-
const parsed = parsePositiveCapacity$
|
|
1558
|
+
const parsed = parsePositiveCapacity$4(value);
|
|
1230
1559
|
return parsed !== null && parsed <= maxContextWindow ? parsed : null;
|
|
1231
1560
|
}
|
|
1232
|
-
function formatCapacity$
|
|
1561
|
+
function formatCapacity$4(value) {
|
|
1233
1562
|
if (value % 1e3 === 0) return `${value / 1e3}K`;
|
|
1234
1563
|
return String(value);
|
|
1235
1564
|
}
|
|
@@ -1246,7 +1575,7 @@ window.__ModuleLoader__.load({
|
|
|
1246
1575
|
limit.remainingPercent !== null && limit.remainingPercent !== void 0 ? `${formatPercent(limit.remainingPercent)} ${t("remaining")}` : null,
|
|
1247
1576
|
limit.limit !== null && limit.limit !== void 0 ? `${t("limit")}: ${limit.limit}` : null,
|
|
1248
1577
|
limit.used !== null && limit.used !== void 0 ? `${t("used")}: ${limit.used}` : null,
|
|
1249
|
-
limit.resetsAt !== null && limit.resetsAt !== void 0 ? `${t("resets")}: ${formatReset$
|
|
1578
|
+
limit.resetsAt !== null && limit.resetsAt !== void 0 ? `${t("resets")}: ${formatReset$3(limit.resetsAt)}` : null
|
|
1250
1579
|
].filter((part) => part !== null);
|
|
1251
1580
|
return parts.length > 0 ? parts.join(" · ") : t("unknown");
|
|
1252
1581
|
}
|
|
@@ -1262,7 +1591,7 @@ window.__ModuleLoader__.load({
|
|
|
1262
1591
|
return "—";
|
|
1263
1592
|
}
|
|
1264
1593
|
}
|
|
1265
|
-
function formatReset$
|
|
1594
|
+
function formatReset$3(seconds) {
|
|
1266
1595
|
if (seconds === void 0 || seconds === null || typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0) return "—";
|
|
1267
1596
|
const ms = seconds > 1e10 ? seconds : seconds * 1e3;
|
|
1268
1597
|
const absolute = formatDate$3(seconds);
|
|
@@ -1281,7 +1610,8 @@ window.__ModuleLoader__.load({
|
|
|
1281
1610
|
//#endregion
|
|
1282
1611
|
//#region src/client/antigravity/locales.ts
|
|
1283
1612
|
const NS_ANTIGRAVITY = "dsh-antigravity";
|
|
1284
|
-
const zh$
|
|
1613
|
+
const zh$4 = {
|
|
1614
|
+
...accountPoolZh,
|
|
1285
1615
|
title: "Antigravity",
|
|
1286
1616
|
pageDesc: "登录 Google Antigravity / Cloud Code Assist,并查看当前账号的共享额度。",
|
|
1287
1617
|
account: "已登录",
|
|
@@ -1298,6 +1628,7 @@ window.__ModuleLoader__.load({
|
|
|
1298
1628
|
rotationStrategy: "调度策略",
|
|
1299
1629
|
strategySequential: "顺序耗尽(当前优先,遇限流自动切号)",
|
|
1300
1630
|
strategyRoundRobin: "轮询调度(按账号循环均匀分摊)",
|
|
1631
|
+
strategySticky: "会话粘性(保持当前账号直到被限流)",
|
|
1301
1632
|
noAccounts: "暂无账号,点击「添加账号」完成登录授权。",
|
|
1302
1633
|
plan: "套餐",
|
|
1303
1634
|
accountId: "账号 ID",
|
|
@@ -1345,7 +1676,8 @@ window.__ModuleLoader__.load({
|
|
|
1345
1676
|
loginFailed: "登录失败",
|
|
1346
1677
|
tokens: "tokens"
|
|
1347
1678
|
};
|
|
1348
|
-
const en$
|
|
1679
|
+
const en$4 = {
|
|
1680
|
+
...accountPoolEn,
|
|
1349
1681
|
title: "Antigravity",
|
|
1350
1682
|
pageDesc: "Sign in to Google Antigravity / Cloud Code Assist and view shared quotas.",
|
|
1351
1683
|
account: "Signed in",
|
|
@@ -1362,6 +1694,7 @@ window.__ModuleLoader__.load({
|
|
|
1362
1694
|
rotationStrategy: "Scheduling Strategy",
|
|
1363
1695
|
strategySequential: "Sequential Drain (Primary first, failover on 429)",
|
|
1364
1696
|
strategyRoundRobin: "Round-Robin (Evenly rotate across accounts)",
|
|
1697
|
+
strategySticky: "Sticky session (hold the current account until it is limited)",
|
|
1365
1698
|
noAccounts: "No accounts yet. Click \"Add Account\" to authorize.",
|
|
1366
1699
|
plan: "Plan",
|
|
1367
1700
|
accountId: "Account ID",
|
|
@@ -1409,17 +1742,17 @@ window.__ModuleLoader__.load({
|
|
|
1409
1742
|
loginFailed: "Login failed",
|
|
1410
1743
|
tokens: "tokens"
|
|
1411
1744
|
};
|
|
1412
|
-
const dictionaries$
|
|
1413
|
-
zh: zh$
|
|
1414
|
-
"zh-CN": zh$
|
|
1415
|
-
en: en$
|
|
1416
|
-
"en-US": en$
|
|
1745
|
+
const dictionaries$4 = {
|
|
1746
|
+
zh: zh$4,
|
|
1747
|
+
"zh-CN": zh$4,
|
|
1748
|
+
en: en$4,
|
|
1749
|
+
"en-US": en$4
|
|
1417
1750
|
};
|
|
1418
1751
|
//#endregion
|
|
1419
1752
|
//#region src/client/antigravity/AntigravitySection.tsx
|
|
1420
|
-
const API$
|
|
1421
|
-
async function fetchApi$
|
|
1422
|
-
const res = await fetch(`${API$
|
|
1753
|
+
const API$7 = "/antigravity/api";
|
|
1754
|
+
async function fetchApi$7(path, options) {
|
|
1755
|
+
const res = await fetch(`${API$7}${path}`, {
|
|
1423
1756
|
...options,
|
|
1424
1757
|
headers: {
|
|
1425
1758
|
"Content-Type": "application/json",
|
|
@@ -1430,14 +1763,14 @@ window.__ModuleLoader__.load({
|
|
|
1430
1763
|
if (!res.ok || !json.ok) throw new Error(json.error || `HTTP ${res.status}`);
|
|
1431
1764
|
return json.value;
|
|
1432
1765
|
}
|
|
1433
|
-
function parsePositiveCapacity$
|
|
1766
|
+
function parsePositiveCapacity$3(value) {
|
|
1434
1767
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
1435
1768
|
if (matched === null) return null;
|
|
1436
1769
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
1437
1770
|
const parsed = Number(matched[1]) * multiplier;
|
|
1438
1771
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
1439
1772
|
}
|
|
1440
|
-
function formatCapacity$
|
|
1773
|
+
function formatCapacity$3(value) {
|
|
1441
1774
|
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
1442
1775
|
if (value % 1e3 === 0) return `${value / 1e3}K`;
|
|
1443
1776
|
return String(value);
|
|
@@ -1473,7 +1806,7 @@ window.__ModuleLoader__.load({
|
|
|
1473
1806
|
const [loginProgress, setLoginProgress] = (0, react.useState)(null);
|
|
1474
1807
|
const [contextDrafts, setContextDrafts] = (0, react.useState)({});
|
|
1475
1808
|
const [savingModel, setSavingModel] = (0, react.useState)(null);
|
|
1476
|
-
const t = zh$
|
|
1809
|
+
const t = zh$4;
|
|
1477
1810
|
const notifyChange = (0, react.useCallback)(() => {
|
|
1478
1811
|
onModelChange?.();
|
|
1479
1812
|
loadModelDirectory?.();
|
|
@@ -1484,12 +1817,12 @@ window.__ModuleLoader__.load({
|
|
|
1484
1817
|
setValidationUrl(null);
|
|
1485
1818
|
}
|
|
1486
1819
|
try {
|
|
1487
|
-
const data = await fetchApi$
|
|
1820
|
+
const data = await fetchApi$7("/status");
|
|
1488
1821
|
setStatus(data);
|
|
1489
1822
|
const drafts = {};
|
|
1490
1823
|
for (const m of data.models) {
|
|
1491
1824
|
const val = data.contextWindowOverrides[m.id] || m.defaultContextWindow;
|
|
1492
|
-
drafts[m.id] = formatCapacity$
|
|
1825
|
+
drafts[m.id] = formatCapacity$3(val);
|
|
1493
1826
|
}
|
|
1494
1827
|
setContextDrafts(drafts);
|
|
1495
1828
|
} catch (err) {
|
|
@@ -1516,11 +1849,11 @@ window.__ModuleLoader__.load({
|
|
|
1516
1849
|
setError(null);
|
|
1517
1850
|
setValidationUrl(null);
|
|
1518
1851
|
setLoginProgress(null);
|
|
1519
|
-
const flow = await fetchApi$
|
|
1852
|
+
const flow = await fetchApi$7("/login", { method: "POST" });
|
|
1520
1853
|
if (flow.authUrl) window.open(flow.authUrl, "_blank");
|
|
1521
1854
|
const pollTimer = setInterval(async () => {
|
|
1522
1855
|
try {
|
|
1523
|
-
const pollStatus = await fetchApi$
|
|
1856
|
+
const pollStatus = await fetchApi$7("/login/status");
|
|
1524
1857
|
if (pollStatus.progress) setLoginProgress(pollStatus.progress);
|
|
1525
1858
|
if (pollStatus.status === "complete") {
|
|
1526
1859
|
clearInterval(pollTimer);
|
|
@@ -1552,7 +1885,7 @@ window.__ModuleLoader__.load({
|
|
|
1552
1885
|
try {
|
|
1553
1886
|
setBusy("quota");
|
|
1554
1887
|
setError(null);
|
|
1555
|
-
const updated = await fetchApi$
|
|
1888
|
+
const updated = await fetchApi$7("/quota", { method: "POST" });
|
|
1556
1889
|
setStatus(updated);
|
|
1557
1890
|
} catch (err) {
|
|
1558
1891
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -1564,7 +1897,7 @@ window.__ModuleLoader__.load({
|
|
|
1564
1897
|
try {
|
|
1565
1898
|
setBusy(`primary-${accountId}`);
|
|
1566
1899
|
setError(null);
|
|
1567
|
-
const updated = await fetchApi$
|
|
1900
|
+
const updated = await fetchApi$7("/accounts", {
|
|
1568
1901
|
method: "POST",
|
|
1569
1902
|
body: JSON.stringify({
|
|
1570
1903
|
action: "set-primary",
|
|
@@ -1583,7 +1916,7 @@ window.__ModuleLoader__.load({
|
|
|
1583
1916
|
try {
|
|
1584
1917
|
setBusy(`delete-${accountId}`);
|
|
1585
1918
|
setError(null);
|
|
1586
|
-
const updated = await fetchApi$
|
|
1919
|
+
const updated = await fetchApi$7("/accounts", {
|
|
1587
1920
|
method: "POST",
|
|
1588
1921
|
body: JSON.stringify({
|
|
1589
1922
|
action: "delete",
|
|
@@ -1602,7 +1935,7 @@ window.__ModuleLoader__.load({
|
|
|
1602
1935
|
try {
|
|
1603
1936
|
setBusy(`cooldown-${accountId}`);
|
|
1604
1937
|
setError(null);
|
|
1605
|
-
const updated = await fetchApi$
|
|
1938
|
+
const updated = await fetchApi$7("/accounts", {
|
|
1606
1939
|
method: "POST",
|
|
1607
1940
|
body: JSON.stringify({
|
|
1608
1941
|
action: "clear-cooldown",
|
|
@@ -1620,7 +1953,7 @@ window.__ModuleLoader__.load({
|
|
|
1620
1953
|
try {
|
|
1621
1954
|
setBusy("strategy");
|
|
1622
1955
|
setError(null);
|
|
1623
|
-
const updated = await fetchApi$
|
|
1956
|
+
const updated = await fetchApi$7("/accounts", {
|
|
1624
1957
|
method: "POST",
|
|
1625
1958
|
body: JSON.stringify({
|
|
1626
1959
|
action: "strategy",
|
|
@@ -1640,7 +1973,7 @@ window.__ModuleLoader__.load({
|
|
|
1640
1973
|
enabled
|
|
1641
1974
|
} : prev);
|
|
1642
1975
|
try {
|
|
1643
|
-
const updated = await fetchApi$
|
|
1976
|
+
const updated = await fetchApi$7("/settings", {
|
|
1644
1977
|
method: "POST",
|
|
1645
1978
|
body: JSON.stringify({ enabled })
|
|
1646
1979
|
});
|
|
@@ -1656,7 +1989,7 @@ window.__ModuleLoader__.load({
|
|
|
1656
1989
|
const currentEnabled = status.models.filter((m) => m.enabled).map((m) => m.id);
|
|
1657
1990
|
const nextEnabled = checked ? [.../* @__PURE__ */ new Set([...currentEnabled, modelId])] : currentEnabled.filter((id) => id !== modelId);
|
|
1658
1991
|
try {
|
|
1659
|
-
const updated = await fetchApi$
|
|
1992
|
+
const updated = await fetchApi$7("/models", {
|
|
1660
1993
|
method: "POST",
|
|
1661
1994
|
body: JSON.stringify({ enabledModelIds: nextEnabled })
|
|
1662
1995
|
});
|
|
@@ -1670,7 +2003,7 @@ window.__ModuleLoader__.load({
|
|
|
1670
2003
|
if (!status) return;
|
|
1671
2004
|
const nextEnabled = selectAll ? status.models.map((m) => m.id) : [];
|
|
1672
2005
|
try {
|
|
1673
|
-
const updated = await fetchApi$
|
|
2006
|
+
const updated = await fetchApi$7("/models", {
|
|
1674
2007
|
method: "POST",
|
|
1675
2008
|
body: JSON.stringify({ enabledModelIds: nextEnabled })
|
|
1676
2009
|
});
|
|
@@ -1682,7 +2015,7 @@ window.__ModuleLoader__.load({
|
|
|
1682
2015
|
};
|
|
1683
2016
|
const handleUpdateEffort = async (effort) => {
|
|
1684
2017
|
try {
|
|
1685
|
-
const updated = await fetchApi$
|
|
2018
|
+
const updated = await fetchApi$7("/settings", {
|
|
1686
2019
|
method: "POST",
|
|
1687
2020
|
body: JSON.stringify({ defaultReasoningEffort: effort })
|
|
1688
2021
|
});
|
|
@@ -1694,7 +2027,7 @@ window.__ModuleLoader__.load({
|
|
|
1694
2027
|
};
|
|
1695
2028
|
const handleSaveContextWindow = async (modelId) => {
|
|
1696
2029
|
const raw = contextDrafts[modelId] || "";
|
|
1697
|
-
const parsed = parsePositiveCapacity$
|
|
2030
|
+
const parsed = parsePositiveCapacity$3(raw);
|
|
1698
2031
|
if (parsed === null) {
|
|
1699
2032
|
setError(`无效的上下文容量值: ${raw}`);
|
|
1700
2033
|
return;
|
|
@@ -1702,14 +2035,14 @@ window.__ModuleLoader__.load({
|
|
|
1702
2035
|
try {
|
|
1703
2036
|
setSavingModel(modelId);
|
|
1704
2037
|
setError(null);
|
|
1705
|
-
const updated = await fetchApi$
|
|
2038
|
+
const updated = await fetchApi$7("/settings", {
|
|
1706
2039
|
method: "POST",
|
|
1707
2040
|
body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
|
|
1708
2041
|
});
|
|
1709
2042
|
setStatus(updated);
|
|
1710
2043
|
setContextDrafts((prev) => ({
|
|
1711
2044
|
...prev,
|
|
1712
|
-
[modelId]: formatCapacity$
|
|
2045
|
+
[modelId]: formatCapacity$3(parsed)
|
|
1713
2046
|
}));
|
|
1714
2047
|
notifyChange();
|
|
1715
2048
|
} catch (err) {
|
|
@@ -1731,148 +2064,40 @@ window.__ModuleLoader__.load({
|
|
|
1731
2064
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1732
2065
|
className: "dsha-page",
|
|
1733
2066
|
children: [
|
|
1734
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
}),
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
value: status.rotationStrategy || "sequential",
|
|
1769
|
-
disabled: busy !== null,
|
|
1770
|
-
onChange: (e) => void handleSetStrategy(e.target.value),
|
|
1771
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1772
|
-
value: "sequential",
|
|
1773
|
-
children: "顺序耗尽"
|
|
1774
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1775
|
-
value: "round-robin",
|
|
1776
|
-
children: "轮询调度"
|
|
1777
|
-
})]
|
|
1778
|
-
})]
|
|
1779
|
-
}),
|
|
1780
|
-
!status?.accounts || status.accounts.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1781
|
-
className: "dsha-empty",
|
|
1782
|
-
children: t.noAccounts
|
|
1783
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1784
|
-
className: "dsha-accounts-list",
|
|
1785
|
-
children: status.accounts.map((acc) => {
|
|
1786
|
-
const isCurrentActive = acc.id === status.activeAccountId;
|
|
1787
|
-
const isCooling = typeof acc.cooldownUntil === "number" && acc.cooldownUntil > Date.now();
|
|
1788
|
-
const cooldownLeftSec = isCooling ? Math.ceil((acc.cooldownUntil - Date.now()) / 1e3) : 0;
|
|
1789
|
-
const cooldownLeftMin = Math.ceil(cooldownLeftSec / 60);
|
|
1790
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1791
|
-
className: `dsha-account-card ${isCurrentActive ? "active" : ""}`,
|
|
1792
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1793
|
-
className: "dsha-account-header",
|
|
1794
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1795
|
-
className: "dsha-account-identity",
|
|
1796
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1797
|
-
className: "dsha-account-title",
|
|
1798
|
-
children: acc.alias || acc.email || acc.id
|
|
1799
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1800
|
-
className: "dsha-badges",
|
|
1801
|
-
children: [
|
|
1802
|
-
acc.isPrimary && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1803
|
-
className: "dsha-badge primary",
|
|
1804
|
-
children: t.primaryAccount
|
|
1805
|
-
}),
|
|
1806
|
-
isCurrentActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1807
|
-
className: "dsha-badge active",
|
|
1808
|
-
children: t.activeAccount
|
|
1809
|
-
}),
|
|
1810
|
-
isCooling && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1811
|
-
className: "dsha-badge cooldown",
|
|
1812
|
-
children: [
|
|
1813
|
-
t.cooling,
|
|
1814
|
-
"(剩 ",
|
|
1815
|
-
cooldownLeftMin,
|
|
1816
|
-
" 分)"
|
|
1817
|
-
]
|
|
1818
|
-
})
|
|
1819
|
-
]
|
|
1820
|
-
})]
|
|
1821
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1822
|
-
className: "dsha-account-actions",
|
|
1823
|
-
children: [
|
|
1824
|
-
!acc.isPrimary && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1825
|
-
className: "dsha-btn",
|
|
1826
|
-
disabled: busy !== null,
|
|
1827
|
-
onClick: () => void handleSetPrimary(acc.id),
|
|
1828
|
-
children: t.setPrimary
|
|
1829
|
-
}),
|
|
1830
|
-
isCooling && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1831
|
-
className: "dsha-btn",
|
|
1832
|
-
disabled: busy !== null,
|
|
1833
|
-
onClick: () => void handleClearCooldown(acc.id),
|
|
1834
|
-
children: t.clearCooldown
|
|
1835
|
-
}),
|
|
1836
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1837
|
-
className: "dsha-btn",
|
|
1838
|
-
disabled: busy !== null,
|
|
1839
|
-
onClick: () => void handleDeleteAccount(acc.id),
|
|
1840
|
-
children: t.deleteAccount
|
|
1841
|
-
})
|
|
1842
|
-
]
|
|
1843
|
-
})]
|
|
1844
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1845
|
-
className: "dsha-account-details",
|
|
1846
|
-
children: [
|
|
1847
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
1848
|
-
t.accountId,
|
|
1849
|
-
": ",
|
|
1850
|
-
acc.projectId || "antigravity-default"
|
|
1851
|
-
] }),
|
|
1852
|
-
acc.email && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["邮箱: ", acc.email] }),
|
|
1853
|
-
acc.expiresAt && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["令牌到期: ", formatDate$2(acc.expiresAt)] }),
|
|
1854
|
-
acc.lastUsedAt && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["上次调用: ", formatDate$2(acc.lastUsedAt)] })
|
|
1855
|
-
]
|
|
1856
|
-
})]
|
|
1857
|
-
}, acc.id);
|
|
1858
|
-
})
|
|
1859
|
-
}),
|
|
1860
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1861
|
-
className: "dsha-row",
|
|
1862
|
-
style: { marginTop: 12 },
|
|
1863
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1864
|
-
className: "dsha-label",
|
|
1865
|
-
children: t.storage
|
|
1866
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1867
|
-
className: "dsha-value",
|
|
1868
|
-
children: "本地安全存储 (JSON/DPAPI)"
|
|
1869
|
-
})]
|
|
1870
|
-
}),
|
|
1871
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1872
|
-
className: "dsha-notice",
|
|
1873
|
-
children: t.storageNotice
|
|
1874
|
-
})
|
|
1875
|
-
]
|
|
2067
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPoolSection, {
|
|
2068
|
+
accounts: status?.accounts ?? [],
|
|
2069
|
+
activeAccountId: status?.activeAccountId,
|
|
2070
|
+
rotationStrategy: status?.rotationStrategy ?? "sequential",
|
|
2071
|
+
busy,
|
|
2072
|
+
labels: t,
|
|
2073
|
+
loginBusyLabel: busy === "login" ? loginProgress || t.signingIn : void 0,
|
|
2074
|
+
onLogin: () => void handleLogin(),
|
|
2075
|
+
onSetPrimary: (accountId) => void handleSetPrimary(accountId),
|
|
2076
|
+
onDelete: (accountId) => void handleDeleteAccount(accountId),
|
|
2077
|
+
onClearCooldown: (accountId) => void handleClearCooldown(accountId),
|
|
2078
|
+
onSetStrategy: (strategy) => void handleSetStrategy(strategy),
|
|
2079
|
+
renderDetails: (account) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2080
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
2081
|
+
t.accountId,
|
|
2082
|
+
": ",
|
|
2083
|
+
account.projectId || "antigravity-default"
|
|
2084
|
+
] }),
|
|
2085
|
+
account.email && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
2086
|
+
t.email,
|
|
2087
|
+
": ",
|
|
2088
|
+
account.email
|
|
2089
|
+
] }),
|
|
2090
|
+
account.expiresAt && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
2091
|
+
t.expires,
|
|
2092
|
+
": ",
|
|
2093
|
+
formatDate$2(account.expiresAt)
|
|
2094
|
+
] }),
|
|
2095
|
+
account.lastUsedAt && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
2096
|
+
t.lastUsed,
|
|
2097
|
+
": ",
|
|
2098
|
+
formatDate$2(account.lastUsedAt)
|
|
2099
|
+
] })
|
|
2100
|
+
] })
|
|
1876
2101
|
}),
|
|
1877
2102
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1878
2103
|
className: "dsha-group",
|
|
@@ -2126,7 +2351,8 @@ window.__ModuleLoader__.load({
|
|
|
2126
2351
|
//#endregion
|
|
2127
2352
|
//#region src/client/command-code/locales.ts
|
|
2128
2353
|
const NS_COMMAND_CODE = "dsh-command-code";
|
|
2129
|
-
const zh$
|
|
2354
|
+
const zh$3 = {
|
|
2355
|
+
...accountPoolZh,
|
|
2130
2356
|
title: "Command Code",
|
|
2131
2357
|
pageDesc: "登录 Command Code,管理可用模型、上下文窗口与额度。",
|
|
2132
2358
|
account: "账号",
|
|
@@ -2193,7 +2419,8 @@ window.__ModuleLoader__.load({
|
|
|
2193
2419
|
loginFailed: "登录失败",
|
|
2194
2420
|
tokens: "tokens"
|
|
2195
2421
|
};
|
|
2196
|
-
const en$
|
|
2422
|
+
const en$3 = {
|
|
2423
|
+
...accountPoolEn,
|
|
2197
2424
|
title: "Command Code",
|
|
2198
2425
|
pageDesc: "Sign in to Command Code and manage models, context windows, and quota.",
|
|
2199
2426
|
account: "Account",
|
|
@@ -2260,11 +2487,11 @@ window.__ModuleLoader__.load({
|
|
|
2260
2487
|
loginFailed: "Sign-in failed",
|
|
2261
2488
|
tokens: "tokens"
|
|
2262
2489
|
};
|
|
2263
|
-
const dictionaries$
|
|
2264
|
-
zh: zh$
|
|
2265
|
-
"zh-CN": zh$
|
|
2266
|
-
en: en$
|
|
2267
|
-
"en-US": en$
|
|
2490
|
+
const dictionaries$3 = {
|
|
2491
|
+
zh: zh$3,
|
|
2492
|
+
"zh-CN": zh$3,
|
|
2493
|
+
en: en$3,
|
|
2494
|
+
"en-US": en$3
|
|
2268
2495
|
};
|
|
2269
2496
|
//#endregion
|
|
2270
2497
|
//#region src/client/command-code/CommandCodeSection.tsx
|
|
@@ -2272,7 +2499,7 @@ window.__ModuleLoader__.load({
|
|
|
2272
2499
|
* Display label per reasoning level. The locale dictionary only accepts flat
|
|
2273
2500
|
* string values, so this nested table lives with the control that renders it.
|
|
2274
2501
|
*/
|
|
2275
|
-
const EFFORT_LABELS = {
|
|
2502
|
+
const EFFORT_LABELS$1 = {
|
|
2276
2503
|
minimal: "Minimal",
|
|
2277
2504
|
low: "Low",
|
|
2278
2505
|
medium: "Medium",
|
|
@@ -2280,9 +2507,9 @@ window.__ModuleLoader__.load({
|
|
|
2280
2507
|
xhigh: "X-High",
|
|
2281
2508
|
max: "Max"
|
|
2282
2509
|
};
|
|
2283
|
-
const API$
|
|
2284
|
-
async function fetchApi$
|
|
2285
|
-
const res = await fetch(`${API$
|
|
2510
|
+
const API$6 = "/command-code/api";
|
|
2511
|
+
async function fetchApi$6(path, options) {
|
|
2512
|
+
const res = await fetch(`${API$6}${path}`, {
|
|
2286
2513
|
...options,
|
|
2287
2514
|
headers: {
|
|
2288
2515
|
"Content-Type": "application/json",
|
|
@@ -2294,30 +2521,19 @@ window.__ModuleLoader__.load({
|
|
|
2294
2521
|
return json.value;
|
|
2295
2522
|
}
|
|
2296
2523
|
/** Parse "1M", "512K", "200000" into a positive integer token count. */
|
|
2297
|
-
function parsePositiveCapacity$
|
|
2524
|
+
function parsePositiveCapacity$2(value) {
|
|
2298
2525
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
2299
2526
|
if (matched === null) return null;
|
|
2300
2527
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
2301
2528
|
const parsed = Number(matched[1]) * multiplier;
|
|
2302
2529
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
2303
2530
|
}
|
|
2304
|
-
function formatCapacity$
|
|
2531
|
+
function formatCapacity$2(value) {
|
|
2305
2532
|
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
2306
2533
|
if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
|
|
2307
2534
|
return String(value);
|
|
2308
2535
|
}
|
|
2309
|
-
function
|
|
2310
|
-
if (ms === void 0 || ms === null || ms <= 0) return "—";
|
|
2311
|
-
try {
|
|
2312
|
-
return new Intl.DateTimeFormat(void 0, {
|
|
2313
|
-
dateStyle: "medium",
|
|
2314
|
-
timeStyle: "short"
|
|
2315
|
-
}).format(ms);
|
|
2316
|
-
} catch {
|
|
2317
|
-
return "—";
|
|
2318
|
-
}
|
|
2319
|
-
}
|
|
2320
|
-
function formatReset$1(resetsAt) {
|
|
2536
|
+
function formatReset$2(resetsAt) {
|
|
2321
2537
|
if (resetsAt === void 0 || resetsAt === null || resetsAt <= 0) return "";
|
|
2322
2538
|
const diff = resetsAt - Date.now();
|
|
2323
2539
|
if (diff <= 0) return "now";
|
|
@@ -2337,7 +2553,7 @@ window.__ModuleLoader__.load({
|
|
|
2337
2553
|
const [contextDrafts, setContextDrafts] = (0, react.useState)({});
|
|
2338
2554
|
const [savingModel, setSavingModel] = (0, react.useState)(null);
|
|
2339
2555
|
const [apiKey, setApiKey] = (0, react.useState)("");
|
|
2340
|
-
const t = zh$
|
|
2556
|
+
const t = zh$3;
|
|
2341
2557
|
const notifyChange = (0, react.useCallback)(() => {
|
|
2342
2558
|
onModelChange?.();
|
|
2343
2559
|
loadModelDirectory?.();
|
|
@@ -2345,10 +2561,10 @@ window.__ModuleLoader__.load({
|
|
|
2345
2561
|
const loadStatus = (0, react.useCallback)(async (quiet = false) => {
|
|
2346
2562
|
if (!quiet) setError(null);
|
|
2347
2563
|
try {
|
|
2348
|
-
const data = await fetchApi$
|
|
2564
|
+
const data = await fetchApi$6("/status");
|
|
2349
2565
|
setStatus(data);
|
|
2350
2566
|
const drafts = {};
|
|
2351
|
-
for (const model of data.models) drafts[model.id] = formatCapacity$
|
|
2567
|
+
for (const model of data.models) drafts[model.id] = formatCapacity$2(data.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
2352
2568
|
setContextDrafts(drafts);
|
|
2353
2569
|
} catch (err) {
|
|
2354
2570
|
if (!quiet) setError(err instanceof Error ? err.message : String(err));
|
|
@@ -2373,12 +2589,12 @@ window.__ModuleLoader__.load({
|
|
|
2373
2589
|
setBusy("login");
|
|
2374
2590
|
setError(null);
|
|
2375
2591
|
setLoginProgress(null);
|
|
2376
|
-
const flow = await fetchApi$
|
|
2592
|
+
const flow = await fetchApi$6("/login", { method: "POST" });
|
|
2377
2593
|
if (flow.authUrl) window.open(flow.authUrl, "_blank");
|
|
2378
2594
|
const pollTimer = window.setInterval(() => {
|
|
2379
2595
|
(async () => {
|
|
2380
2596
|
try {
|
|
2381
|
-
const poll = await fetchApi$
|
|
2597
|
+
const poll = await fetchApi$6("/login/status");
|
|
2382
2598
|
if (poll.progress) setLoginProgress(poll.progress);
|
|
2383
2599
|
if (poll.status === "complete") {
|
|
2384
2600
|
window.clearInterval(pollTimer);
|
|
@@ -2410,7 +2626,7 @@ window.__ModuleLoader__.load({
|
|
|
2410
2626
|
try {
|
|
2411
2627
|
setBusy("apikey");
|
|
2412
2628
|
setError(null);
|
|
2413
|
-
const updated = await fetchApi$
|
|
2629
|
+
const updated = await fetchApi$6("/login/apikey", {
|
|
2414
2630
|
method: "POST",
|
|
2415
2631
|
body: JSON.stringify({ apiKey })
|
|
2416
2632
|
});
|
|
@@ -2423,11 +2639,18 @@ window.__ModuleLoader__.load({
|
|
|
2423
2639
|
setBusy(null);
|
|
2424
2640
|
}
|
|
2425
2641
|
};
|
|
2426
|
-
|
|
2642
|
+
/** One account-level action on the shared pool card. */
|
|
2643
|
+
const handleAccountAction = async (action, accountId) => {
|
|
2427
2644
|
try {
|
|
2428
|
-
setBusy(
|
|
2645
|
+
setBusy(`${action}-${accountId}`);
|
|
2429
2646
|
setError(null);
|
|
2430
|
-
const updated = await fetchApi$
|
|
2647
|
+
const updated = await fetchApi$6("/accounts", {
|
|
2648
|
+
method: "POST",
|
|
2649
|
+
body: JSON.stringify({
|
|
2650
|
+
action,
|
|
2651
|
+
accountId
|
|
2652
|
+
})
|
|
2653
|
+
});
|
|
2431
2654
|
setStatus(updated);
|
|
2432
2655
|
notifyChange();
|
|
2433
2656
|
} catch (err) {
|
|
@@ -2436,11 +2659,53 @@ window.__ModuleLoader__.load({
|
|
|
2436
2659
|
setBusy(null);
|
|
2437
2660
|
}
|
|
2438
2661
|
};
|
|
2662
|
+
const handleSetStrategy = async (strategy) => {
|
|
2663
|
+
try {
|
|
2664
|
+
setBusy("strategy");
|
|
2665
|
+
setError(null);
|
|
2666
|
+
const updated = await fetchApi$6("/accounts", {
|
|
2667
|
+
method: "POST",
|
|
2668
|
+
body: JSON.stringify({
|
|
2669
|
+
action: "strategy",
|
|
2670
|
+
strategy
|
|
2671
|
+
})
|
|
2672
|
+
});
|
|
2673
|
+
setStatus(updated);
|
|
2674
|
+
} catch (err) {
|
|
2675
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2676
|
+
} finally {
|
|
2677
|
+
setBusy(null);
|
|
2678
|
+
}
|
|
2679
|
+
};
|
|
2680
|
+
/**
|
|
2681
|
+
* Re-authorize one key.
|
|
2682
|
+
*
|
|
2683
|
+
* Nothing is deleted: the failure marker is cleared and the ordinary sign-in
|
|
2684
|
+
* flow runs again, so the account keeps its alias and place in the rotation.
|
|
2685
|
+
*/
|
|
2686
|
+
const handleRelogin = (accountId) => {
|
|
2687
|
+
(async () => {
|
|
2688
|
+
try {
|
|
2689
|
+
const updated = await fetchApi$6("/accounts", {
|
|
2690
|
+
method: "POST",
|
|
2691
|
+
body: JSON.stringify({
|
|
2692
|
+
action: "relogin",
|
|
2693
|
+
accountId
|
|
2694
|
+
})
|
|
2695
|
+
});
|
|
2696
|
+
setStatus(updated);
|
|
2697
|
+
} catch (err) {
|
|
2698
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2699
|
+
return;
|
|
2700
|
+
}
|
|
2701
|
+
await handleLogin();
|
|
2702
|
+
})();
|
|
2703
|
+
};
|
|
2439
2704
|
const handleRefreshQuota = async () => {
|
|
2440
2705
|
try {
|
|
2441
2706
|
setBusy("quota");
|
|
2442
2707
|
setError(null);
|
|
2443
|
-
const updated = await fetchApi$
|
|
2708
|
+
const updated = await fetchApi$6("/quota", { method: "POST" });
|
|
2444
2709
|
setStatus(updated);
|
|
2445
2710
|
} catch (err) {
|
|
2446
2711
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -2452,10 +2717,10 @@ window.__ModuleLoader__.load({
|
|
|
2452
2717
|
try {
|
|
2453
2718
|
setBusy("catalog");
|
|
2454
2719
|
setError(null);
|
|
2455
|
-
const updated = await fetchApi$
|
|
2720
|
+
const updated = await fetchApi$6("/catalog/refresh", { method: "POST" });
|
|
2456
2721
|
setStatus(updated);
|
|
2457
2722
|
const drafts = {};
|
|
2458
|
-
for (const model of updated.models) drafts[model.id] = formatCapacity$
|
|
2723
|
+
for (const model of updated.models) drafts[model.id] = formatCapacity$2(updated.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
2459
2724
|
setContextDrafts(drafts);
|
|
2460
2725
|
notifyChange();
|
|
2461
2726
|
} catch (err) {
|
|
@@ -2468,7 +2733,7 @@ window.__ModuleLoader__.load({
|
|
|
2468
2733
|
try {
|
|
2469
2734
|
setBusy("connection");
|
|
2470
2735
|
setError(null);
|
|
2471
|
-
await fetchApi$
|
|
2736
|
+
await fetchApi$6("/connection/test", { method: "POST" });
|
|
2472
2737
|
await loadStatus(true);
|
|
2473
2738
|
} catch (err) {
|
|
2474
2739
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -2478,7 +2743,7 @@ window.__ModuleLoader__.load({
|
|
|
2478
2743
|
};
|
|
2479
2744
|
const applyEnabled = async (enabledModelIds) => {
|
|
2480
2745
|
try {
|
|
2481
|
-
const updated = await fetchApi$
|
|
2746
|
+
const updated = await fetchApi$6("/models", {
|
|
2482
2747
|
method: "POST",
|
|
2483
2748
|
body: JSON.stringify({ enabledModelIds })
|
|
2484
2749
|
});
|
|
@@ -2494,7 +2759,7 @@ window.__ModuleLoader__.load({
|
|
|
2494
2759
|
enabled
|
|
2495
2760
|
} : prev);
|
|
2496
2761
|
try {
|
|
2497
|
-
const updated = await fetchApi$
|
|
2762
|
+
const updated = await fetchApi$6("/settings", {
|
|
2498
2763
|
method: "POST",
|
|
2499
2764
|
body: JSON.stringify({ enabled })
|
|
2500
2765
|
});
|
|
@@ -2517,7 +2782,7 @@ window.__ModuleLoader__.load({
|
|
|
2517
2782
|
};
|
|
2518
2783
|
const handleUpdateEffort = async (effort) => {
|
|
2519
2784
|
try {
|
|
2520
|
-
const updated = await fetchApi$
|
|
2785
|
+
const updated = await fetchApi$6("/settings", {
|
|
2521
2786
|
method: "POST",
|
|
2522
2787
|
body: JSON.stringify({ defaultReasoningEffort: effort })
|
|
2523
2788
|
});
|
|
@@ -2529,7 +2794,7 @@ window.__ModuleLoader__.load({
|
|
|
2529
2794
|
};
|
|
2530
2795
|
const handleSaveContextWindow = async (modelId) => {
|
|
2531
2796
|
const raw = contextDrafts[modelId] || "";
|
|
2532
|
-
const parsed = parsePositiveCapacity$
|
|
2797
|
+
const parsed = parsePositiveCapacity$2(raw);
|
|
2533
2798
|
if (parsed === null) {
|
|
2534
2799
|
setError(`Invalid context capacity: ${raw}`);
|
|
2535
2800
|
return;
|
|
@@ -2537,14 +2802,14 @@ window.__ModuleLoader__.load({
|
|
|
2537
2802
|
try {
|
|
2538
2803
|
setSavingModel(modelId);
|
|
2539
2804
|
setError(null);
|
|
2540
|
-
const updated = await fetchApi$
|
|
2805
|
+
const updated = await fetchApi$6("/settings", {
|
|
2541
2806
|
method: "POST",
|
|
2542
2807
|
body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
|
|
2543
2808
|
});
|
|
2544
2809
|
setStatus(updated);
|
|
2545
2810
|
setContextDrafts((prev) => ({
|
|
2546
2811
|
...prev,
|
|
2547
|
-
[modelId]: formatCapacity$
|
|
2812
|
+
[modelId]: formatCapacity$2(parsed)
|
|
2548
2813
|
}));
|
|
2549
2814
|
notifyChange();
|
|
2550
2815
|
} catch (err) {
|
|
@@ -2561,155 +2826,57 @@ window.__ModuleLoader__.load({
|
|
|
2561
2826
|
})
|
|
2562
2827
|
});
|
|
2563
2828
|
const quota = status?.quota;
|
|
2564
|
-
|
|
2829
|
+
status?.account;
|
|
2565
2830
|
status?.models.filter((model) => model.enabled).length;
|
|
2566
2831
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2567
2832
|
className: "dsha-page",
|
|
2568
2833
|
children: [
|
|
2569
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
}
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
})]
|
|
2616
|
-
}),
|
|
2617
|
-
account?.organizationName && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2618
|
-
className: "dsha-row",
|
|
2619
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2620
|
-
className: "dsha-label",
|
|
2621
|
-
children: t.organization
|
|
2622
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2623
|
-
className: "dsha-value",
|
|
2624
|
-
children: account.organizationName
|
|
2625
|
-
})]
|
|
2626
|
-
}),
|
|
2627
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2628
|
-
className: "dsha-row",
|
|
2629
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2630
|
-
className: "dsha-label",
|
|
2631
|
-
children: t.authenticatedAt
|
|
2632
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2633
|
-
className: "dsha-value",
|
|
2634
|
-
children: formatDate$1(account?.authenticatedAt)
|
|
2635
|
-
})]
|
|
2636
|
-
})
|
|
2637
|
-
] }),
|
|
2638
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2639
|
-
className: "dsha-row",
|
|
2640
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2641
|
-
className: "dsha-label",
|
|
2642
|
-
children: t.storage
|
|
2643
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2644
|
-
className: "dsha-value",
|
|
2645
|
-
children: status?.storagePath || "—"
|
|
2646
|
-
})]
|
|
2647
|
-
}),
|
|
2648
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2649
|
-
className: "dsha-notice",
|
|
2650
|
-
children: t.storageNotice
|
|
2651
|
-
}),
|
|
2652
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2653
|
-
className: "dsha-actions",
|
|
2654
|
-
children: !status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2655
|
-
className: "dsha-btn dsha-btn-primary",
|
|
2656
|
-
disabled: busy !== null,
|
|
2657
|
-
onClick: () => void handleLogin(),
|
|
2658
|
-
children: busy === "login" ? loginProgress || t.signingIn : t.signIn
|
|
2659
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2660
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2661
|
-
className: "dsha-btn dsha-btn-primary",
|
|
2662
|
-
disabled: busy !== null,
|
|
2663
|
-
onClick: () => void handleLogin(),
|
|
2664
|
-
children: busy === "login" ? loginProgress || t.signingIn : t.signInAgain
|
|
2665
|
-
}),
|
|
2666
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2667
|
-
className: "dsha-btn",
|
|
2668
|
-
disabled: busy !== null,
|
|
2669
|
-
onClick: () => void handleRefreshQuota(),
|
|
2670
|
-
children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
|
|
2671
|
-
}),
|
|
2672
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2673
|
-
className: "dsha-btn",
|
|
2674
|
-
disabled: busy !== null,
|
|
2675
|
-
onClick: () => void handleLogout(),
|
|
2676
|
-
children: t.signOut
|
|
2677
|
-
})
|
|
2678
|
-
] })
|
|
2679
|
-
})
|
|
2680
|
-
]
|
|
2681
|
-
}),
|
|
2682
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2683
|
-
className: "dsha-group",
|
|
2684
|
-
children: [
|
|
2685
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2686
|
-
className: "dsha-grouphead",
|
|
2687
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.apiKeySection })
|
|
2688
|
-
}),
|
|
2689
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2690
|
-
className: "dsha-muted",
|
|
2691
|
-
children: t.apiKeyHint
|
|
2692
|
-
}),
|
|
2693
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2694
|
-
className: "dsha-capacity-control",
|
|
2695
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2696
|
-
type: "password",
|
|
2697
|
-
"aria-label": t.apiKeySection,
|
|
2698
|
-
placeholder: t.apiKeyPlaceholder,
|
|
2699
|
-
value: apiKey,
|
|
2700
|
-
onChange: (event) => setApiKey(event.currentTarget.value),
|
|
2701
|
-
onKeyDown: (event) => {
|
|
2702
|
-
if (event.key === "Enter" && apiKey.trim() !== "") handleApiKey();
|
|
2703
|
-
}
|
|
2704
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2705
|
-
type: "button",
|
|
2706
|
-
className: "dsha-context-save",
|
|
2707
|
-
disabled: busy !== null || apiKey.trim() === "",
|
|
2708
|
-
onClick: () => void handleApiKey(),
|
|
2709
|
-
children: busy === "apikey" ? t.apiKeySaving : t.apiKeySave
|
|
2710
|
-
})]
|
|
2711
|
-
})
|
|
2712
|
-
]
|
|
2834
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(AccountPoolSection, {
|
|
2835
|
+
accounts: status?.accounts ?? [],
|
|
2836
|
+
activeAccountId: status?.activeAccountId,
|
|
2837
|
+
rotationStrategy: status?.rotationStrategy ?? "sequential",
|
|
2838
|
+
busy,
|
|
2839
|
+
labels: t,
|
|
2840
|
+
loginBusyLabel: busy === "login" ? loginProgress || t.signingIn : void 0,
|
|
2841
|
+
onLogin: () => void handleLogin(),
|
|
2842
|
+
onSetPrimary: (accountId) => void handleAccountAction("set-primary", accountId),
|
|
2843
|
+
onDelete: (accountId) => void handleAccountAction("delete", accountId),
|
|
2844
|
+
onClearCooldown: (accountId) => void handleAccountAction("clear-cooldown", accountId),
|
|
2845
|
+
onRelogin: (accountId) => handleRelogin(accountId),
|
|
2846
|
+
onSetStrategy: (strategy) => void handleSetStrategy(strategy),
|
|
2847
|
+
storageValue: status?.storagePath || "—",
|
|
2848
|
+
renderDetails: (entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [entry.keyName && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
2849
|
+
t.keyName,
|
|
2850
|
+
": ",
|
|
2851
|
+
entry.keyName
|
|
2852
|
+
] }), entry.planLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
2853
|
+
t.plan,
|
|
2854
|
+
": ",
|
|
2855
|
+
entry.planLabel
|
|
2856
|
+
] })] }),
|
|
2857
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2858
|
+
className: "dsha-muted",
|
|
2859
|
+
style: { paddingTop: 12 },
|
|
2860
|
+
children: t.apiKeyHint
|
|
2861
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2862
|
+
className: "dsha-capacity-control",
|
|
2863
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
2864
|
+
type: "password",
|
|
2865
|
+
"aria-label": t.apiKeySection,
|
|
2866
|
+
placeholder: t.apiKeyPlaceholder,
|
|
2867
|
+
value: apiKey,
|
|
2868
|
+
onChange: (event) => setApiKey(event.currentTarget.value),
|
|
2869
|
+
onKeyDown: (event) => {
|
|
2870
|
+
if (event.key === "Enter" && apiKey.trim() !== "") handleApiKey();
|
|
2871
|
+
}
|
|
2872
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2873
|
+
type: "button",
|
|
2874
|
+
className: "dsha-context-save",
|
|
2875
|
+
disabled: busy !== null || apiKey.trim() === "",
|
|
2876
|
+
onClick: () => void handleApiKey(),
|
|
2877
|
+
children: busy === "apikey" ? t.apiKeySaving : t.apiKeySave
|
|
2878
|
+
})]
|
|
2879
|
+
})]
|
|
2713
2880
|
}),
|
|
2714
2881
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
2715
2882
|
className: "dsha-group",
|
|
@@ -2838,7 +3005,7 @@ window.__ModuleLoader__.load({
|
|
|
2838
3005
|
children: t.defaultEffortAuto
|
|
2839
3006
|
}), COMMAND_CODE_REASONING_EFFORTS.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
2840
3007
|
value: effort,
|
|
2841
|
-
children: EFFORT_LABELS[effort]
|
|
3008
|
+
children: EFFORT_LABELS$1[effort]
|
|
2842
3009
|
}, effort))]
|
|
2843
3010
|
})]
|
|
2844
3011
|
})]
|
|
@@ -2932,7 +3099,7 @@ window.__ModuleLoader__.load({
|
|
|
2932
3099
|
}),
|
|
2933
3100
|
window.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2934
3101
|
className: "dsha-meter-meta",
|
|
2935
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Reset: ", formatReset$
|
|
3102
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Reset: ", formatReset$2(window.resetsAt)] })
|
|
2936
3103
|
})
|
|
2937
3104
|
]
|
|
2938
3105
|
}, window.id)),
|
|
@@ -2957,7 +3124,7 @@ window.__ModuleLoader__.load({
|
|
|
2957
3124
|
meter.used ?? "—",
|
|
2958
3125
|
" / ",
|
|
2959
3126
|
meter.limit ?? "—"
|
|
2960
|
-
] }), meter.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Reset: ", formatReset$
|
|
3127
|
+
] }), meter.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Reset: ", formatReset$2(meter.resetsAt)] })]
|
|
2961
3128
|
}) : meter.description !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2962
3129
|
className: "dsha-meter-meta",
|
|
2963
3130
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meter.description })
|
|
@@ -2996,7 +3163,8 @@ window.__ModuleLoader__.load({
|
|
|
2996
3163
|
//#endregion
|
|
2997
3164
|
//#region src/client/kimi-code/locales.ts
|
|
2998
3165
|
const NS_KIMI_CODE = "dsh-kimi-code";
|
|
2999
|
-
const zh$
|
|
3166
|
+
const zh$2 = {
|
|
3167
|
+
...accountPoolZh,
|
|
3000
3168
|
title: "Kimi Code",
|
|
3001
3169
|
pageDesc: "登录 Kimi Code 订阅,管理模型、思考档位、上下文窗口与额度。",
|
|
3002
3170
|
account: "账号",
|
|
@@ -3108,7 +3276,8 @@ window.__ModuleLoader__.load({
|
|
|
3108
3276
|
requests: "次请求",
|
|
3109
3277
|
tokens: "tokens"
|
|
3110
3278
|
};
|
|
3111
|
-
const en$
|
|
3279
|
+
const en$2 = {
|
|
3280
|
+
...accountPoolEn,
|
|
3112
3281
|
title: "Kimi Code",
|
|
3113
3282
|
pageDesc: "Sign in to the Kimi Code subscription and manage models, thinking level, context windows, and quota.",
|
|
3114
3283
|
account: "Account",
|
|
@@ -3220,11 +3389,11 @@ window.__ModuleLoader__.load({
|
|
|
3220
3389
|
requests: "requests",
|
|
3221
3390
|
tokens: "tokens"
|
|
3222
3391
|
};
|
|
3223
|
-
const dictionaries$
|
|
3224
|
-
zh: zh$
|
|
3225
|
-
"zh-CN": zh$
|
|
3226
|
-
en: en$
|
|
3227
|
-
"en-US": en$
|
|
3392
|
+
const dictionaries$2 = {
|
|
3393
|
+
zh: zh$2,
|
|
3394
|
+
"zh-CN": zh$2,
|
|
3395
|
+
en: en$2,
|
|
3396
|
+
"en-US": en$2
|
|
3228
3397
|
};
|
|
3229
3398
|
//#endregion
|
|
3230
3399
|
//#region src/client/kimi-code/KimiModelCapabilities.tsx
|
|
@@ -3237,7 +3406,7 @@ window.__ModuleLoader__.load({
|
|
|
3237
3406
|
* Capabilities are now short tags in their own columns, with the per-model
|
|
3238
3407
|
* detail kept in a hover title.
|
|
3239
3408
|
*/
|
|
3240
|
-
const t = zh$
|
|
3409
|
+
const t = zh$2;
|
|
3241
3410
|
function KimiModelCapabilities({ models }) {
|
|
3242
3411
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3243
3412
|
className: "dsha-cap-table",
|
|
@@ -3281,9 +3450,9 @@ window.__ModuleLoader__.load({
|
|
|
3281
3450
|
}
|
|
3282
3451
|
//#endregion
|
|
3283
3452
|
//#region src/client/kimi-code/KimiCodeSection.tsx
|
|
3284
|
-
const API$
|
|
3285
|
-
async function fetchApi$
|
|
3286
|
-
const res = await fetch(`${API$
|
|
3453
|
+
const API$5 = "/kimi-code/api";
|
|
3454
|
+
async function fetchApi$5(path, options) {
|
|
3455
|
+
const res = await fetch(`${API$5}${path}`, {
|
|
3287
3456
|
...options,
|
|
3288
3457
|
headers: {
|
|
3289
3458
|
"Content-Type": "application/json",
|
|
@@ -3295,19 +3464,19 @@ window.__ModuleLoader__.load({
|
|
|
3295
3464
|
return json.value;
|
|
3296
3465
|
}
|
|
3297
3466
|
/** Parse "1M", "512K", "200000" into a positive integer token count. */
|
|
3298
|
-
function parsePositiveCapacity(value) {
|
|
3467
|
+
function parsePositiveCapacity$1(value) {
|
|
3299
3468
|
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
3300
3469
|
if (matched === null) return null;
|
|
3301
3470
|
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
3302
3471
|
const parsed = Number(matched[1]) * multiplier;
|
|
3303
3472
|
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
3304
3473
|
}
|
|
3305
|
-
function formatCapacity(value) {
|
|
3474
|
+
function formatCapacity$1(value) {
|
|
3306
3475
|
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
3307
3476
|
if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
|
|
3308
3477
|
return String(value);
|
|
3309
3478
|
}
|
|
3310
|
-
function formatDate(ms) {
|
|
3479
|
+
function formatDate$1(ms) {
|
|
3311
3480
|
if (ms === void 0 || ms === null || ms <= 0) return "—";
|
|
3312
3481
|
try {
|
|
3313
3482
|
return new Intl.DateTimeFormat(void 0, {
|
|
@@ -3318,7 +3487,7 @@ window.__ModuleLoader__.load({
|
|
|
3318
3487
|
return "—";
|
|
3319
3488
|
}
|
|
3320
3489
|
}
|
|
3321
|
-
function formatReset(resetsAt) {
|
|
3490
|
+
function formatReset$1(resetsAt) {
|
|
3322
3491
|
if (resetsAt === void 0 || resetsAt === null || resetsAt <= 0) return "";
|
|
3323
3492
|
const diff = resetsAt - Date.now();
|
|
3324
3493
|
if (diff <= 0) return "now";
|
|
@@ -3343,10 +3512,10 @@ window.__ModuleLoader__.load({
|
|
|
3343
3512
|
}
|
|
3344
3513
|
}
|
|
3345
3514
|
const EFFORT_LABEL = {
|
|
3346
|
-
low: zh$
|
|
3347
|
-
high: zh$
|
|
3348
|
-
max: zh$
|
|
3349
|
-
none: zh$
|
|
3515
|
+
low: zh$2.effortLow,
|
|
3516
|
+
high: zh$2.effortHigh,
|
|
3517
|
+
max: zh$2.effortMax,
|
|
3518
|
+
none: zh$2.effortNone
|
|
3350
3519
|
};
|
|
3351
3520
|
function KimiCodeSection({ onModelChange, loadModelDirectory }) {
|
|
3352
3521
|
const [status, setStatus] = (0, react.useState)(null);
|
|
@@ -3358,7 +3527,7 @@ window.__ModuleLoader__.load({
|
|
|
3358
3527
|
const [savingModel, setSavingModel] = (0, react.useState)(null);
|
|
3359
3528
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
3360
3529
|
const [connectionNotice, setConnectionNotice] = (0, react.useState)(null);
|
|
3361
|
-
const t = zh$
|
|
3530
|
+
const t = zh$2;
|
|
3362
3531
|
const notifyChange = (0, react.useCallback)(() => {
|
|
3363
3532
|
onModelChange?.();
|
|
3364
3533
|
loadModelDirectory?.();
|
|
@@ -3366,10 +3535,10 @@ window.__ModuleLoader__.load({
|
|
|
3366
3535
|
const loadStatus = (0, react.useCallback)(async (quiet = false) => {
|
|
3367
3536
|
if (!quiet) setError(null);
|
|
3368
3537
|
try {
|
|
3369
|
-
const data = await fetchApi$
|
|
3538
|
+
const data = await fetchApi$5("/status");
|
|
3370
3539
|
setStatus(data);
|
|
3371
3540
|
const drafts = {};
|
|
3372
|
-
for (const model of data.models) drafts[model.id] = formatCapacity(data.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
3541
|
+
for (const model of data.models) drafts[model.id] = formatCapacity$1(data.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
3373
3542
|
setContextDrafts(drafts);
|
|
3374
3543
|
} catch (err) {
|
|
3375
3544
|
if (!quiet) setError(err instanceof Error ? err.message : String(err));
|
|
@@ -3394,7 +3563,7 @@ window.__ModuleLoader__.load({
|
|
|
3394
3563
|
const timer = window.setInterval(() => {
|
|
3395
3564
|
(async () => {
|
|
3396
3565
|
try {
|
|
3397
|
-
const poll = await fetchApi$
|
|
3566
|
+
const poll = await fetchApi$5("/login/status");
|
|
3398
3567
|
setFlow(poll);
|
|
3399
3568
|
if (poll.status === "complete") {
|
|
3400
3569
|
await loadStatus();
|
|
@@ -3415,7 +3584,7 @@ window.__ModuleLoader__.load({
|
|
|
3415
3584
|
setBusy("login");
|
|
3416
3585
|
setError(null);
|
|
3417
3586
|
setCopied(false);
|
|
3418
|
-
const next = await fetchApi$
|
|
3587
|
+
const next = await fetchApi$5("/login", {
|
|
3419
3588
|
method: "POST",
|
|
3420
3589
|
body: JSON.stringify({})
|
|
3421
3590
|
});
|
|
@@ -3428,7 +3597,7 @@ window.__ModuleLoader__.load({
|
|
|
3428
3597
|
};
|
|
3429
3598
|
const handleCancelLogin = async () => {
|
|
3430
3599
|
try {
|
|
3431
|
-
await fetchApi$
|
|
3600
|
+
await fetchApi$5("/login/cancel", { method: "POST" });
|
|
3432
3601
|
setFlow({ status: "idle" });
|
|
3433
3602
|
} catch (err) {
|
|
3434
3603
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -3443,11 +3612,18 @@ window.__ModuleLoader__.load({
|
|
|
3443
3612
|
window.setTimeout(() => setCopied(false), 2e3);
|
|
3444
3613
|
} catch {}
|
|
3445
3614
|
};
|
|
3446
|
-
|
|
3615
|
+
/** One account-level action on the shared pool card. */
|
|
3616
|
+
const handleAccountAction = async (action, accountId) => {
|
|
3447
3617
|
try {
|
|
3448
|
-
setBusy(
|
|
3618
|
+
setBusy(`${action}-${accountId}`);
|
|
3449
3619
|
setError(null);
|
|
3450
|
-
const updated = await fetchApi$
|
|
3620
|
+
const updated = await fetchApi$5("/accounts", {
|
|
3621
|
+
method: "POST",
|
|
3622
|
+
body: JSON.stringify({
|
|
3623
|
+
action,
|
|
3624
|
+
accountId
|
|
3625
|
+
})
|
|
3626
|
+
});
|
|
3451
3627
|
setStatus(updated);
|
|
3452
3628
|
setFlow({ status: "idle" });
|
|
3453
3629
|
notifyChange();
|
|
@@ -3457,11 +3633,53 @@ window.__ModuleLoader__.load({
|
|
|
3457
3633
|
setBusy(null);
|
|
3458
3634
|
}
|
|
3459
3635
|
};
|
|
3636
|
+
const handleSetStrategy = async (strategy) => {
|
|
3637
|
+
try {
|
|
3638
|
+
setBusy("strategy");
|
|
3639
|
+
setError(null);
|
|
3640
|
+
const updated = await fetchApi$5("/accounts", {
|
|
3641
|
+
method: "POST",
|
|
3642
|
+
body: JSON.stringify({
|
|
3643
|
+
action: "strategy",
|
|
3644
|
+
strategy
|
|
3645
|
+
})
|
|
3646
|
+
});
|
|
3647
|
+
setStatus(updated);
|
|
3648
|
+
} catch (err) {
|
|
3649
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
3650
|
+
} finally {
|
|
3651
|
+
setBusy(null);
|
|
3652
|
+
}
|
|
3653
|
+
};
|
|
3654
|
+
/**
|
|
3655
|
+
* Re-authorize one account.
|
|
3656
|
+
*
|
|
3657
|
+
* Nothing is deleted: the failure marker is cleared and the device-code flow
|
|
3658
|
+
* runs again, so the account keeps its alias and place in the rotation.
|
|
3659
|
+
*/
|
|
3660
|
+
const handleRelogin = (accountId) => {
|
|
3661
|
+
(async () => {
|
|
3662
|
+
try {
|
|
3663
|
+
const updated = await fetchApi$5("/accounts", {
|
|
3664
|
+
method: "POST",
|
|
3665
|
+
body: JSON.stringify({
|
|
3666
|
+
action: "relogin",
|
|
3667
|
+
accountId
|
|
3668
|
+
})
|
|
3669
|
+
});
|
|
3670
|
+
setStatus(updated);
|
|
3671
|
+
} catch (err) {
|
|
3672
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
3673
|
+
return;
|
|
3674
|
+
}
|
|
3675
|
+
await handleLogin();
|
|
3676
|
+
})();
|
|
3677
|
+
};
|
|
3460
3678
|
const handleRefreshQuota = async () => {
|
|
3461
3679
|
try {
|
|
3462
3680
|
setBusy("quota");
|
|
3463
3681
|
setError(null);
|
|
3464
|
-
const updated = await fetchApi$
|
|
3682
|
+
const updated = await fetchApi$5("/quota", { method: "POST" });
|
|
3465
3683
|
setStatus(updated);
|
|
3466
3684
|
} catch (err) {
|
|
3467
3685
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -3474,10 +3692,10 @@ window.__ModuleLoader__.load({
|
|
|
3474
3692
|
try {
|
|
3475
3693
|
setBusy("catalog");
|
|
3476
3694
|
setError(null);
|
|
3477
|
-
const updated = await fetchApi$
|
|
3695
|
+
const updated = await fetchApi$5("/catalog/refresh", { method: "POST" });
|
|
3478
3696
|
setStatus(updated);
|
|
3479
3697
|
const drafts = {};
|
|
3480
|
-
for (const model of updated.models) drafts[model.id] = formatCapacity(updated.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
3698
|
+
for (const model of updated.models) drafts[model.id] = formatCapacity$1(updated.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
3481
3699
|
setContextDrafts(drafts);
|
|
3482
3700
|
notifyChange();
|
|
3483
3701
|
} catch (err) {
|
|
@@ -3491,7 +3709,7 @@ window.__ModuleLoader__.load({
|
|
|
3491
3709
|
setBusy("connection");
|
|
3492
3710
|
setError(null);
|
|
3493
3711
|
setConnectionNotice(null);
|
|
3494
|
-
const result = await fetchApi$
|
|
3712
|
+
const result = await fetchApi$5("/connection/test", { method: "POST" });
|
|
3495
3713
|
setConnectionNotice(result.connected ? `${t.testSuccess} · ${result.latencyMs} ms` : t.testFailed);
|
|
3496
3714
|
await loadStatus(true);
|
|
3497
3715
|
} catch (err) {
|
|
@@ -3502,7 +3720,7 @@ window.__ModuleLoader__.load({
|
|
|
3502
3720
|
};
|
|
3503
3721
|
const applyEnabled = async (enabledModelIds) => {
|
|
3504
3722
|
try {
|
|
3505
|
-
const updated = await fetchApi$
|
|
3723
|
+
const updated = await fetchApi$5("/models", {
|
|
3506
3724
|
method: "POST",
|
|
3507
3725
|
body: JSON.stringify({ enabledModelIds })
|
|
3508
3726
|
});
|
|
@@ -3518,7 +3736,7 @@ window.__ModuleLoader__.load({
|
|
|
3518
3736
|
enabled
|
|
3519
3737
|
} : prev);
|
|
3520
3738
|
try {
|
|
3521
|
-
const updated = await fetchApi$
|
|
3739
|
+
const updated = await fetchApi$5("/settings", {
|
|
3522
3740
|
method: "POST",
|
|
3523
3741
|
body: JSON.stringify({ enabled })
|
|
3524
3742
|
});
|
|
@@ -3541,7 +3759,7 @@ window.__ModuleLoader__.load({
|
|
|
3541
3759
|
};
|
|
3542
3760
|
const handleUpdateEffort = async (effort) => {
|
|
3543
3761
|
try {
|
|
3544
|
-
const updated = await fetchApi$
|
|
3762
|
+
const updated = await fetchApi$5("/settings", {
|
|
3545
3763
|
method: "POST",
|
|
3546
3764
|
body: JSON.stringify({ defaultReasoningEffort: effort })
|
|
3547
3765
|
});
|
|
@@ -3553,7 +3771,7 @@ window.__ModuleLoader__.load({
|
|
|
3553
3771
|
};
|
|
3554
3772
|
const handleSaveContextWindow = async (modelId) => {
|
|
3555
3773
|
const raw = contextDrafts[modelId] || "";
|
|
3556
|
-
const parsed = parsePositiveCapacity(raw);
|
|
3774
|
+
const parsed = parsePositiveCapacity$1(raw);
|
|
3557
3775
|
if (parsed === null) {
|
|
3558
3776
|
setError(`Invalid context capacity: ${raw}`);
|
|
3559
3777
|
return;
|
|
@@ -3561,14 +3779,14 @@ window.__ModuleLoader__.load({
|
|
|
3561
3779
|
try {
|
|
3562
3780
|
setSavingModel(modelId);
|
|
3563
3781
|
setError(null);
|
|
3564
|
-
const updated = await fetchApi$
|
|
3782
|
+
const updated = await fetchApi$5("/settings", {
|
|
3565
3783
|
method: "POST",
|
|
3566
3784
|
body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
|
|
3567
3785
|
});
|
|
3568
3786
|
setStatus(updated);
|
|
3569
3787
|
setContextDrafts((prev) => ({
|
|
3570
3788
|
...prev,
|
|
3571
|
-
[modelId]: formatCapacity(parsed)
|
|
3789
|
+
[modelId]: formatCapacity$1(parsed)
|
|
3572
3790
|
}));
|
|
3573
3791
|
notifyChange();
|
|
3574
3792
|
} catch (err) {
|
|
@@ -3585,171 +3803,96 @@ window.__ModuleLoader__.load({
|
|
|
3585
3803
|
})
|
|
3586
3804
|
});
|
|
3587
3805
|
const quota = status?.quota;
|
|
3588
|
-
|
|
3806
|
+
status?.account;
|
|
3589
3807
|
status?.models.filter((model) => model.enabled).length;
|
|
3590
3808
|
const loginPending = flow?.status === "pending";
|
|
3591
3809
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3592
3810
|
className: "dsha-page",
|
|
3593
3811
|
children: [
|
|
3594
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3812
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPoolSection, {
|
|
3813
|
+
accounts: status?.accounts ?? [],
|
|
3814
|
+
activeAccountId: status?.activeAccountId,
|
|
3815
|
+
rotationStrategy: status?.rotationStrategy ?? "sequential",
|
|
3816
|
+
busy,
|
|
3817
|
+
labels: t,
|
|
3818
|
+
loginBusyLabel: loginPending ? t.waitingAuthorization : busy === "login" ? t.requestingCode : void 0,
|
|
3819
|
+
onLogin: () => void handleLogin(),
|
|
3820
|
+
onSetPrimary: (accountId) => void handleAccountAction("set-primary", accountId),
|
|
3821
|
+
onDelete: (accountId) => void handleAccountAction("delete", accountId),
|
|
3822
|
+
onClearCooldown: (accountId) => void handleAccountAction("clear-cooldown", accountId),
|
|
3823
|
+
onRelogin: (accountId) => handleRelogin(accountId),
|
|
3824
|
+
onSetStrategy: (strategy) => void handleSetStrategy(strategy),
|
|
3825
|
+
storageValue: status?.storagePath || "—",
|
|
3826
|
+
renderDetails: (entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3827
|
+
entry.planName && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
3828
|
+
t.plan,
|
|
3829
|
+
": ",
|
|
3830
|
+
entry.planName
|
|
3831
|
+
] }),
|
|
3832
|
+
entry.region && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
3833
|
+
t.region,
|
|
3834
|
+
": ",
|
|
3835
|
+
entry.region === "global" ? t.regionGlobal : t.regionMainland
|
|
3836
|
+
] }),
|
|
3837
|
+
entry.email && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
3838
|
+
t.email,
|
|
3839
|
+
": ",
|
|
3840
|
+
entry.email
|
|
3841
|
+
] })
|
|
3842
|
+
] }),
|
|
3843
|
+
children: loginPending && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3844
|
+
className: "dsha-device-box",
|
|
3845
|
+
children: [
|
|
3846
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.deviceCodeSection }),
|
|
3847
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3848
|
+
className: "dsha-muted",
|
|
3849
|
+
children: t.deviceCodeHint
|
|
3621
3850
|
}),
|
|
3622
|
-
|
|
3623
|
-
className: "dsha-row",
|
|
3851
|
+
flow?.userCode && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3852
|
+
className: "dsha-code-row",
|
|
3624
3853
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3625
|
-
className: "dsha-
|
|
3626
|
-
children:
|
|
3627
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
3628
|
-
className: "dsha-
|
|
3629
|
-
|
|
3854
|
+
className: "dsha-code",
|
|
3855
|
+
children: flow.userCode
|
|
3856
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3857
|
+
className: "dsha-btn",
|
|
3858
|
+
onClick: () => void handleCopyCode(),
|
|
3859
|
+
children: copied ? t.copied : t.copyCode
|
|
3630
3860
|
})]
|
|
3631
3861
|
}),
|
|
3862
|
+
flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3863
|
+
className: "dsha-link",
|
|
3864
|
+
href: flow.verificationUriComplete,
|
|
3865
|
+
target: "_blank",
|
|
3866
|
+
rel: "noreferrer noopener",
|
|
3867
|
+
children: flow.verificationUriComplete
|
|
3868
|
+
}),
|
|
3632
3869
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3633
3870
|
className: "dsha-row",
|
|
3634
3871
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3635
3872
|
className: "dsha-label",
|
|
3636
|
-
children: t.
|
|
3873
|
+
children: t.codeExpires
|
|
3637
3874
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3638
3875
|
className: "dsha-value",
|
|
3639
|
-
children:
|
|
3876
|
+
children: formatDate$1(flow?.expiresAt)
|
|
3640
3877
|
})]
|
|
3641
3878
|
}),
|
|
3642
3879
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3643
|
-
className: "dsha-
|
|
3644
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
3645
|
-
className: "dsha-
|
|
3646
|
-
children: t.authenticatedAt
|
|
3647
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3648
|
-
className: "dsha-value",
|
|
3649
|
-
children: formatDate(account?.authenticatedAt)
|
|
3650
|
-
})]
|
|
3651
|
-
})
|
|
3652
|
-
] }),
|
|
3653
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3654
|
-
className: "dsha-row",
|
|
3655
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3656
|
-
className: "dsha-label",
|
|
3657
|
-
children: t.storage
|
|
3658
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3659
|
-
className: "dsha-value",
|
|
3660
|
-
children: status?.storagePath || "—"
|
|
3661
|
-
})]
|
|
3662
|
-
}),
|
|
3663
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3664
|
-
className: "dsha-notice",
|
|
3665
|
-
children: t.storageNotice
|
|
3666
|
-
}),
|
|
3667
|
-
status?.credentialsRejected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3668
|
-
className: "dsha-notice",
|
|
3669
|
-
children: t.refreshRejected
|
|
3670
|
-
}),
|
|
3671
|
-
loginPending && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3672
|
-
className: "dsha-device-box",
|
|
3673
|
-
children: [
|
|
3674
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.deviceCodeSection }),
|
|
3675
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3676
|
-
className: "dsha-muted",
|
|
3677
|
-
children: t.deviceCodeHint
|
|
3678
|
-
}),
|
|
3679
|
-
flow?.userCode && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3680
|
-
className: "dsha-code-row",
|
|
3681
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3682
|
-
className: "dsha-code",
|
|
3683
|
-
children: flow.userCode
|
|
3684
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3685
|
-
className: "dsha-btn",
|
|
3686
|
-
onClick: () => void handleCopyCode(),
|
|
3687
|
-
children: copied ? t.copied : t.copyCode
|
|
3688
|
-
})]
|
|
3689
|
-
}),
|
|
3690
|
-
flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3691
|
-
className: "dsha-link",
|
|
3880
|
+
className: "dsha-actions",
|
|
3881
|
+
children: [flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3882
|
+
className: "dsha-btn",
|
|
3692
3883
|
href: flow.verificationUriComplete,
|
|
3693
3884
|
target: "_blank",
|
|
3694
3885
|
rel: "noreferrer noopener",
|
|
3695
|
-
children:
|
|
3696
|
-
}),
|
|
3697
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3698
|
-
className: "dsha-row",
|
|
3699
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3700
|
-
className: "dsha-label",
|
|
3701
|
-
children: t.codeExpires
|
|
3702
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3703
|
-
className: "dsha-value",
|
|
3704
|
-
children: formatDate(flow?.expiresAt)
|
|
3705
|
-
})]
|
|
3706
|
-
}),
|
|
3707
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3708
|
-
className: "dsha-actions",
|
|
3709
|
-
children: [flow?.verificationUriComplete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3710
|
-
className: "dsha-btn",
|
|
3711
|
-
href: flow.verificationUriComplete,
|
|
3712
|
-
target: "_blank",
|
|
3713
|
-
rel: "noreferrer noopener",
|
|
3714
|
-
children: t.openSignInPage
|
|
3715
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3716
|
-
className: "dsha-btn",
|
|
3717
|
-
disabled: busy !== null,
|
|
3718
|
-
onClick: () => void handleCancelLogin(),
|
|
3719
|
-
children: t.cancelSignIn
|
|
3720
|
-
})]
|
|
3721
|
-
})
|
|
3722
|
-
]
|
|
3723
|
-
}),
|
|
3724
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3725
|
-
className: "dsha-actions",
|
|
3726
|
-
children: !status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3727
|
-
className: "dsha-btn dsha-btn-primary",
|
|
3728
|
-
disabled: busy !== null || loginPending,
|
|
3729
|
-
onClick: () => void handleLogin(),
|
|
3730
|
-
children: loginPending ? t.waitingAuthorization : busy === "login" ? t.requestingCode : t.signIn
|
|
3731
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3732
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3733
|
-
className: "dsha-btn dsha-btn-primary",
|
|
3734
|
-
disabled: busy !== null || loginPending,
|
|
3735
|
-
onClick: () => void handleLogin(),
|
|
3736
|
-
children: loginPending ? t.waitingAuthorization : t.signInAgain
|
|
3737
|
-
}),
|
|
3738
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3739
|
-
className: "dsha-btn",
|
|
3740
|
-
disabled: busy !== null,
|
|
3741
|
-
onClick: () => void handleRefreshQuota(),
|
|
3742
|
-
children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
|
|
3743
|
-
}),
|
|
3744
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3886
|
+
children: t.openSignInPage
|
|
3887
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3745
3888
|
className: "dsha-btn",
|
|
3746
3889
|
disabled: busy !== null,
|
|
3747
|
-
onClick: () => void
|
|
3748
|
-
children: t.
|
|
3749
|
-
})
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3890
|
+
onClick: () => void handleCancelLogin(),
|
|
3891
|
+
children: t.cancelSignIn
|
|
3892
|
+
})]
|
|
3893
|
+
})
|
|
3894
|
+
]
|
|
3895
|
+
})
|
|
3753
3896
|
}),
|
|
3754
3897
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3755
3898
|
className: "dsha-group",
|
|
@@ -3882,37 +4025,1212 @@ window.__ModuleLoader__.load({
|
|
|
3882
4025
|
children: t.unselectAll
|
|
3883
4026
|
})]
|
|
3884
4027
|
}),
|
|
3885
|
-
status !== null && status.models.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KimiModelCapabilities, { models: status.models })
|
|
3886
|
-
]
|
|
3887
|
-
}),
|
|
3888
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3889
|
-
className: "dsha-group",
|
|
3890
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3891
|
-
className: "dsha-grouphead",
|
|
3892
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.enhanced })
|
|
3893
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3894
|
-
className: "dsha-pref-row",
|
|
3895
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.defaultReasoningEffort }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4028
|
+
status !== null && status.models.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KimiModelCapabilities, { models: status.models })
|
|
4029
|
+
]
|
|
4030
|
+
}),
|
|
4031
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4032
|
+
className: "dsha-group",
|
|
4033
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4034
|
+
className: "dsha-grouphead",
|
|
4035
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.enhanced })
|
|
4036
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4037
|
+
className: "dsha-pref-row",
|
|
4038
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.defaultReasoningEffort }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4039
|
+
className: "dsha-muted",
|
|
4040
|
+
children: t.defaultReasoningEffortHint
|
|
4041
|
+
})] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
4042
|
+
className: "dsha-select",
|
|
4043
|
+
"aria-label": t.defaultReasoningEffort,
|
|
4044
|
+
value: status?.defaultReasoningEffort ?? "",
|
|
4045
|
+
disabled: busy !== null,
|
|
4046
|
+
onChange: (event) => {
|
|
4047
|
+
const value = event.currentTarget.value;
|
|
4048
|
+
handleUpdateEffort(value === "" ? null : value);
|
|
4049
|
+
},
|
|
4050
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4051
|
+
value: "",
|
|
4052
|
+
children: t.defaultEffortAuto
|
|
4053
|
+
}), KIMI_CODE_REASONING_EFFORTS.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
4054
|
+
value: effort,
|
|
4055
|
+
children: EFFORT_LABEL[effort]
|
|
4056
|
+
}, effort))]
|
|
4057
|
+
})]
|
|
4058
|
+
})]
|
|
4059
|
+
}),
|
|
4060
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4061
|
+
className: "dsha-group",
|
|
4062
|
+
children: [
|
|
4063
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4064
|
+
className: "dsha-grouphead",
|
|
4065
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.contextWindowSection })
|
|
4066
|
+
}),
|
|
4067
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4068
|
+
className: "dsha-muted",
|
|
4069
|
+
children: t.contextWindowHint
|
|
4070
|
+
}),
|
|
4071
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4072
|
+
className: "dsha-context-settings",
|
|
4073
|
+
children: status?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4074
|
+
className: "dsha-context-row",
|
|
4075
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4076
|
+
title: model.id,
|
|
4077
|
+
children: [model.name, model.defaultContextWindow < model.contextWindow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4078
|
+
className: "dsha-model-meta",
|
|
4079
|
+
children: formatCapacity$1(model.contextWindow)
|
|
4080
|
+
})]
|
|
4081
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4082
|
+
className: "dsha-capacity-control",
|
|
4083
|
+
children: [
|
|
4084
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4085
|
+
type: "text",
|
|
4086
|
+
"aria-label": `${model.name} context window`,
|
|
4087
|
+
value: contextDrafts[model.id] ?? "",
|
|
4088
|
+
onChange: (event) => setContextDrafts({
|
|
4089
|
+
...contextDrafts,
|
|
4090
|
+
[model.id]: event.currentTarget.value
|
|
4091
|
+
}),
|
|
4092
|
+
onKeyDown: (event) => {
|
|
4093
|
+
if (event.key === "Enter") handleSaveContextWindow(model.id);
|
|
4094
|
+
}
|
|
4095
|
+
}),
|
|
4096
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t.tokens }),
|
|
4097
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4098
|
+
type: "button",
|
|
4099
|
+
className: "dsha-context-save",
|
|
4100
|
+
disabled: savingModel === model.id,
|
|
4101
|
+
onClick: () => void handleSaveContextWindow(model.id),
|
|
4102
|
+
children: savingModel === model.id ? t.saving : t.save
|
|
4103
|
+
})
|
|
4104
|
+
]
|
|
4105
|
+
})]
|
|
4106
|
+
}, model.id))
|
|
4107
|
+
})
|
|
4108
|
+
]
|
|
4109
|
+
}),
|
|
4110
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4111
|
+
className: "dsha-group",
|
|
4112
|
+
children: [
|
|
4113
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4114
|
+
className: "dsha-grouphead",
|
|
4115
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.quotaSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4116
|
+
className: "dsha-btn",
|
|
4117
|
+
disabled: busy !== null || !status?.authenticated,
|
|
4118
|
+
onClick: () => void handleRefreshQuota(),
|
|
4119
|
+
children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
|
|
4120
|
+
})]
|
|
4121
|
+
}),
|
|
4122
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4123
|
+
className: "dsha-muted",
|
|
4124
|
+
children: t.quotaDesc
|
|
4125
|
+
}),
|
|
4126
|
+
status?.quotaError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4127
|
+
className: "dsha-notice",
|
|
4128
|
+
children: status.quotaError
|
|
4129
|
+
}),
|
|
4130
|
+
!status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4131
|
+
className: "dsha-empty",
|
|
4132
|
+
children: t.signedOut
|
|
4133
|
+
}) : quota === null || quota === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4134
|
+
className: "dsha-empty",
|
|
4135
|
+
children: busy === "quota" ? t.refreshingQuota : t.quotaEmpty
|
|
4136
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4137
|
+
className: "dsha-quota-card",
|
|
4138
|
+
children: [
|
|
4139
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4140
|
+
className: "dsha-quota-title",
|
|
4141
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.quotaPlan }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.planName || t.planUnknown })]
|
|
4142
|
+
}),
|
|
4143
|
+
quota.windows.map((window) => {
|
|
4144
|
+
const remaining = Math.max(0, 100 - window.usedPercent);
|
|
4145
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4146
|
+
className: "dsha-meter-wrap",
|
|
4147
|
+
children: [
|
|
4148
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4149
|
+
className: "dsha-meter-label",
|
|
4150
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: window.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [remaining, "% left"] })]
|
|
4151
|
+
}),
|
|
4152
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4153
|
+
className: `dsha-meter ${remaining <= 10 ? "dsha-meter-cyan" : "dsha-meter-green"}`,
|
|
4154
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${remaining}%` } })
|
|
4155
|
+
}),
|
|
4156
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4157
|
+
className: "dsha-meter-meta",
|
|
4158
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
4159
|
+
window.used ?? "—",
|
|
4160
|
+
" / ",
|
|
4161
|
+
window.limit ?? "—",
|
|
4162
|
+
" ",
|
|
4163
|
+
t.requests
|
|
4164
|
+
] }), window.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.resetAt.replace("{time}", formatReset$1(window.resetsAt)) })]
|
|
4165
|
+
})
|
|
4166
|
+
]
|
|
4167
|
+
}, window.id);
|
|
4168
|
+
}),
|
|
4169
|
+
quota.extraUsage !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4170
|
+
className: "dsha-meter-wrap",
|
|
4171
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4172
|
+
className: "dsha-meter-label",
|
|
4173
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaWallet }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatMoney(quota.extraUsage.balanceCents, quota.extraUsage.currency) })]
|
|
4174
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4175
|
+
className: "dsha-meter-meta",
|
|
4176
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatMoney(quota.extraUsage.totalCents, quota.extraUsage.currency) }), quota.extraUsage.monthlyChargeLimitEnabled && quota.extraUsage.monthlyChargeLimitCents !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
4177
|
+
t.quotaWalletLimit,
|
|
4178
|
+
": ",
|
|
4179
|
+
formatMoney(quota.extraUsage.monthlyChargeLimitCents, quota.extraUsage.currency)
|
|
4180
|
+
] })]
|
|
4181
|
+
})]
|
|
4182
|
+
}),
|
|
4183
|
+
quota.windows.length === 0 && quota.extraUsage === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4184
|
+
className: "dsha-empty",
|
|
4185
|
+
children: t.quotaEmpty
|
|
4186
|
+
}),
|
|
4187
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4188
|
+
className: "dsha-timestamp",
|
|
4189
|
+
children: t.updatedAt.replace("{time}", new Date(quota.fetchedAt).toLocaleString())
|
|
4190
|
+
})
|
|
4191
|
+
]
|
|
4192
|
+
})
|
|
4193
|
+
]
|
|
4194
|
+
}),
|
|
4195
|
+
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4196
|
+
className: "dsha-error",
|
|
4197
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: error })
|
|
4198
|
+
})
|
|
4199
|
+
]
|
|
4200
|
+
});
|
|
4201
|
+
}
|
|
4202
|
+
//#endregion
|
|
4203
|
+
//#region src/shared/workbuddy-contracts.ts
|
|
4204
|
+
/** Every level this route can name, in escalating order (the card's sort key). */
|
|
4205
|
+
const WORKBUDDY_REASONING_EFFORTS = [
|
|
4206
|
+
"minimal",
|
|
4207
|
+
"low",
|
|
4208
|
+
"medium",
|
|
4209
|
+
"high",
|
|
4210
|
+
"xhigh",
|
|
4211
|
+
"max"
|
|
4212
|
+
];
|
|
4213
|
+
//#endregion
|
|
4214
|
+
//#region src/client/workbuddy/locales.ts
|
|
4215
|
+
const NS_WORKBUDDY = "dsh-workbuddy";
|
|
4216
|
+
const zh$1 = {
|
|
4217
|
+
title: "WorkBuddy",
|
|
4218
|
+
pageDesc: "复用本机 CodeBuddy 桌面端登录态,管理 WorkBuddy(CodeBuddy 订阅)模型、上下文窗口与额度。",
|
|
4219
|
+
account: "账号",
|
|
4220
|
+
noAccounts: "暂无账号,点击「添加国区账号 / 添加国际区账号」完成浏览器授权,或登录 CodeBuddy 桌面端后重新扫描。",
|
|
4221
|
+
signedIn: "已找到凭据",
|
|
4222
|
+
signedOut: "未找到凭据",
|
|
4223
|
+
nickname: "昵称",
|
|
4224
|
+
uid: "账号 ID",
|
|
4225
|
+
uin: "UIN",
|
|
4226
|
+
region: "区域",
|
|
4227
|
+
regionCn: "国区",
|
|
4228
|
+
regionIntl: "国际区",
|
|
4229
|
+
accountType: "账号类型",
|
|
4230
|
+
backend: "后端地址",
|
|
4231
|
+
domain: "认证域名",
|
|
4232
|
+
tokenExpires: "登录态有效期",
|
|
4233
|
+
tokenExpired: "已过期",
|
|
4234
|
+
sourceFile: "凭据文件",
|
|
4235
|
+
authDirectory: "凭据目录",
|
|
4236
|
+
storage: "凭据存储",
|
|
4237
|
+
storageNotice: "桌面端账号仍读取 CodeBuddy 自己的凭据文件,插件不会删除这些文件;通过这里添加的账号保存在系统加密存储中(Windows DPAPI / macOS Keychain / Linux Secret Service),token 不进入浏览器。",
|
|
4238
|
+
notFoundTitle: "未找到 WorkBuddy 账号",
|
|
4239
|
+
notFoundHint: "可安装并登录 CodeBuddy 后重新扫描,也可以直接点击下方「添加国区账号」或「添加国际区账号」完成浏览器授权。",
|
|
4240
|
+
routeUnreachable: "无法读取 WorkBuddy 设置路由",
|
|
4241
|
+
routeUnreachableHint: "浏览器里加载的插件版本可能比 Host 进程里运行的新(客户端资源是现读磁盘的,Host 只在启动时加载)。请重启 DSH,让两端来自同一份构建。",
|
|
4242
|
+
rescan: "重新扫描",
|
|
4243
|
+
rescanning: "扫描中...",
|
|
4244
|
+
accounts: "本机凭据",
|
|
4245
|
+
accountsHint: "按账号地区分组。插件添加的账号可删除;CodeBuddy 桌面账号只能从本插件隐藏,绝不删除桌面端原凭据。点击账号会切换模型目录、额度和后续对话。",
|
|
4246
|
+
useAccount: "使用此账号",
|
|
4247
|
+
selectedAccount: "当前账号",
|
|
4248
|
+
addCnAccount: "添加国区账号",
|
|
4249
|
+
addIntlAccount: "添加国际区账号",
|
|
4250
|
+
authorizing: "授权中…",
|
|
4251
|
+
loginWaiting: "请在新打开的浏览器页面完成登录与授权。",
|
|
4252
|
+
loginFailed: "账号授权失败",
|
|
4253
|
+
pluginAccount: "插件账号",
|
|
4254
|
+
desktopAccount: "桌面账号",
|
|
4255
|
+
encryptedStorage: "系统加密存储",
|
|
4256
|
+
hiddenAccount: "已隐藏",
|
|
4257
|
+
hideAccount: "从插件隐藏",
|
|
4258
|
+
restoreAccount: "恢复显示",
|
|
4259
|
+
deleteAccount: "删除账号",
|
|
4260
|
+
deleteConfirm: "确定删除这个插件托管的账号吗?加密存储中的登录凭据会被移除。",
|
|
4261
|
+
connection: "连接",
|
|
4262
|
+
provider: "Provider",
|
|
4263
|
+
providerValue: "WorkBuddy Subscription · workbuddy-subscription",
|
|
4264
|
+
connectionState: "连接状态",
|
|
4265
|
+
connected: "已连接",
|
|
4266
|
+
untested: "未测试",
|
|
4267
|
+
testConnection: "测试连接",
|
|
4268
|
+
testingConnection: "测试中...",
|
|
4269
|
+
latency: "延迟",
|
|
4270
|
+
routeOwned: "模型路由由本插件提供",
|
|
4271
|
+
routeConflict: "模型路由已被其他 Provider 占用:{detail}。请在 DSH 设置中移除重复的 Provider 配置后重试。",
|
|
4272
|
+
modelsSection: "模型",
|
|
4273
|
+
enableProvider: "启用此供应商",
|
|
4274
|
+
modelsHint: "勾选后模型才会出现在对话页的模型选择列表中;未勾选或关闭上方开关可在列表中隐藏该供应商。目录与上下文窗口来自订阅网关的模型目录,并按账号所在区域过滤——跨区调用会被上游拒绝。",
|
|
4275
|
+
refreshCatalog: "刷新模型目录",
|
|
4276
|
+
refreshingCatalog: "刷新中...",
|
|
4277
|
+
selectAll: "全选",
|
|
4278
|
+
unselectAll: "全不选",
|
|
4279
|
+
imageSupport: "图片",
|
|
4280
|
+
textOnly: "纯文本",
|
|
4281
|
+
regionBadge: "区域",
|
|
4282
|
+
unavailableHere: "当前区域不可用",
|
|
4283
|
+
enhanced: "增强功能",
|
|
4284
|
+
defaultReasoningEffort: "默认思考深度",
|
|
4285
|
+
defaultReasoningEffortHint: "控制支持推理的模型在未单独指定时的思考强度。",
|
|
4286
|
+
defaultEffortAuto: "使用模型默认值",
|
|
4287
|
+
effortUnsupported: "当前模型不支持",
|
|
4288
|
+
noReasoningModels: "当前账号的模型都没有声明可用的思考档位,因此没有可选的默认档位。",
|
|
4289
|
+
defaultEffortKept: "已保存的档位不被当前任何模型支持,已保留但不会生效。",
|
|
4290
|
+
contextWindowSection: "模型上下文窗口",
|
|
4291
|
+
contextWindowHint: "默认值来自订阅网关的模型目录(每个模型的真实上下文上限);可覆盖为自定义容量,该值用于 DSH 的压缩与溢出判断,可输入 1M、512K、200K 等容量。",
|
|
4292
|
+
save: "保存",
|
|
4293
|
+
saved: "已保存",
|
|
4294
|
+
saving: "保存中...",
|
|
4295
|
+
quotaSection: "用量与配额",
|
|
4296
|
+
quotaDesc: "数据来自订阅的计费接口,页面可见时最多每 60 秒刷新一次。",
|
|
4297
|
+
refreshQuota: "刷新用量",
|
|
4298
|
+
refreshingQuota: "刷新中...",
|
|
4299
|
+
quotaEmpty: "暂无配额数据,点击「刷新用量」重试。",
|
|
4300
|
+
quotaPackage: "套餐",
|
|
4301
|
+
quotaRemaining: "剩余额度",
|
|
4302
|
+
quotaCycle: "本周期已用",
|
|
4303
|
+
quotaReset: "重置时间",
|
|
4304
|
+
updatedAt: "更新时间:{time}",
|
|
4305
|
+
loading: "加载中...",
|
|
4306
|
+
credits: "credits",
|
|
4307
|
+
composerLabel: "额度"
|
|
4308
|
+
};
|
|
4309
|
+
const en$1 = {
|
|
4310
|
+
title: "WorkBuddy",
|
|
4311
|
+
pageDesc: "Reuse the local CodeBuddy desktop sign-in to manage WorkBuddy (CodeBuddy subscription) models, context windows, and quota.",
|
|
4312
|
+
account: "Account",
|
|
4313
|
+
noAccounts: "No accounts yet. Add a China or international account, or sign in with the CodeBuddy desktop client and rescan.",
|
|
4314
|
+
signedIn: "Credential found",
|
|
4315
|
+
signedOut: "No credential found",
|
|
4316
|
+
nickname: "Nickname",
|
|
4317
|
+
uid: "Account ID",
|
|
4318
|
+
uin: "UIN",
|
|
4319
|
+
region: "Region",
|
|
4320
|
+
regionCn: "China",
|
|
4321
|
+
regionIntl: "International",
|
|
4322
|
+
accountType: "Account type",
|
|
4323
|
+
backend: "Backend",
|
|
4324
|
+
domain: "Auth domain",
|
|
4325
|
+
tokenExpires: "Sign-in valid until",
|
|
4326
|
+
tokenExpired: "Expired",
|
|
4327
|
+
sourceFile: "Credential file",
|
|
4328
|
+
authDirectory: "Credential directory",
|
|
4329
|
+
storage: "Credential storage",
|
|
4330
|
+
storageNotice: "Desktop accounts continue to use CodeBuddy’s credential files, which this plugin never deletes. Accounts added here use encrypted OS storage (Windows DPAPI, macOS Keychain, or Linux Secret Service); tokens never enter the browser.",
|
|
4331
|
+
notFoundTitle: "No WorkBuddy account found",
|
|
4332
|
+
notFoundHint: "Install and sign in to CodeBuddy and rescan, or use “Add China account” / “Add international account” below to authorize in the browser.",
|
|
4333
|
+
routeUnreachable: "The WorkBuddy settings route could not be read",
|
|
4334
|
+
routeUnreachableHint: "The plugin loaded in the browser may be newer than the one running in the Host: client assets are read from disk on demand, while the Host loads them only at startup. Restart DSH so both halves come from the same build.",
|
|
4335
|
+
rescan: "Rescan",
|
|
4336
|
+
rescanning: "Scanning...",
|
|
4337
|
+
accounts: "Local credentials",
|
|
4338
|
+
accountsHint: "Accounts are grouped by region. Plugin-managed accounts can be deleted; CodeBuddy desktop accounts can only be hidden from this plugin and their source files are never deleted. Selecting one switches models, quota, and chats.",
|
|
4339
|
+
useAccount: "Use this account",
|
|
4340
|
+
selectedAccount: "Selected account",
|
|
4341
|
+
addCnAccount: "Add China account",
|
|
4342
|
+
addIntlAccount: "Add international account",
|
|
4343
|
+
authorizing: "Authorizing…",
|
|
4344
|
+
loginWaiting: "Complete sign-in and authorization in the newly opened browser page.",
|
|
4345
|
+
loginFailed: "Account authorization failed",
|
|
4346
|
+
pluginAccount: "Plugin account",
|
|
4347
|
+
desktopAccount: "Desktop account",
|
|
4348
|
+
encryptedStorage: "Encrypted OS storage",
|
|
4349
|
+
hiddenAccount: "Hidden",
|
|
4350
|
+
hideAccount: "Hide from plugin",
|
|
4351
|
+
restoreAccount: "Restore",
|
|
4352
|
+
deleteAccount: "Delete account",
|
|
4353
|
+
deleteConfirm: "Delete this plugin-managed account? Its encrypted credential will be removed.",
|
|
4354
|
+
connection: "Connection",
|
|
4355
|
+
provider: "Provider",
|
|
4356
|
+
providerValue: "WorkBuddy Subscription · workbuddy-subscription",
|
|
4357
|
+
connectionState: "Connection state",
|
|
4358
|
+
connected: "Connected",
|
|
4359
|
+
untested: "Untested",
|
|
4360
|
+
testConnection: "Test connection",
|
|
4361
|
+
testingConnection: "Testing...",
|
|
4362
|
+
latency: "Latency",
|
|
4363
|
+
routeOwned: "This plugin serves the model route",
|
|
4364
|
+
routeConflict: "Another provider already owns the model route: {detail}. Remove the duplicate provider configuration in DSH settings and reload.",
|
|
4365
|
+
modelsSection: "Models",
|
|
4366
|
+
enableProvider: "Enable this provider",
|
|
4367
|
+
modelsHint: "Checked models appear in the DSH conversation model list. The catalog and its context windows come from the subscription gateway and are filtered by the account’s region — the upstream rejects a model asked of the wrong region.",
|
|
4368
|
+
refreshCatalog: "Refresh catalog",
|
|
4369
|
+
refreshingCatalog: "Refreshing...",
|
|
4370
|
+
selectAll: "Select all",
|
|
4371
|
+
unselectAll: "Deselect all",
|
|
4372
|
+
imageSupport: "Images",
|
|
4373
|
+
textOnly: "Text only",
|
|
4374
|
+
regionBadge: "Regions",
|
|
4375
|
+
unavailableHere: "Unavailable in this region",
|
|
4376
|
+
enhanced: "Enhanced features",
|
|
4377
|
+
defaultReasoningEffort: "Default reasoning effort",
|
|
4378
|
+
defaultReasoningEffortHint: "Reasoning effort for models that support it when the conversation does not specify one.",
|
|
4379
|
+
defaultEffortAuto: "Use the model default",
|
|
4380
|
+
effortUnsupported: "unsupported by the current models",
|
|
4381
|
+
noReasoningModels: "None of this account’s models declare a reasoning level, so there is no default to choose.",
|
|
4382
|
+
defaultEffortKept: "The saved level is not supported by any current model; it is kept but has no effect.",
|
|
4383
|
+
contextWindowSection: "Model context window",
|
|
4384
|
+
contextWindowHint: "Defaults come from the subscription gateway’s own catalog (each model’s real context cap); override one with the capacity DSH should use for compaction and overflow decisions (e.g., 1M, 512K, 200K).",
|
|
4385
|
+
save: "Save",
|
|
4386
|
+
saved: "Saved",
|
|
4387
|
+
saving: "Saving...",
|
|
4388
|
+
quotaSection: "Usage & quota",
|
|
4389
|
+
quotaDesc: "Read from the subscription billing endpoint; refreshes at most once every 60 seconds while visible.",
|
|
4390
|
+
refreshQuota: "Refresh quota",
|
|
4391
|
+
refreshingQuota: "Refreshing...",
|
|
4392
|
+
quotaEmpty: "No quota data yet — use “Refresh quota” to retry.",
|
|
4393
|
+
quotaPackage: "Package",
|
|
4394
|
+
quotaRemaining: "Remaining credits",
|
|
4395
|
+
quotaCycle: "Used this cycle",
|
|
4396
|
+
quotaReset: "Resets",
|
|
4397
|
+
updatedAt: "Updated at: {time}",
|
|
4398
|
+
loading: "Loading...",
|
|
4399
|
+
credits: "credits",
|
|
4400
|
+
composerLabel: "Quota"
|
|
4401
|
+
};
|
|
4402
|
+
const dictionaries$1 = {
|
|
4403
|
+
zh: zh$1,
|
|
4404
|
+
"zh-CN": zh$1,
|
|
4405
|
+
en: en$1,
|
|
4406
|
+
"en-US": en$1
|
|
4407
|
+
};
|
|
4408
|
+
//#endregion
|
|
4409
|
+
//#region src/client/workbuddy/WorkBuddySection.tsx
|
|
4410
|
+
/**
|
|
4411
|
+
* Display label per reasoning level. The locale dictionary only accepts flat
|
|
4412
|
+
* string values, so this nested table lives with the control that renders it.
|
|
4413
|
+
*/
|
|
4414
|
+
const EFFORT_LABELS = {
|
|
4415
|
+
minimal: "Minimal",
|
|
4416
|
+
low: "Low",
|
|
4417
|
+
medium: "Medium",
|
|
4418
|
+
high: "High",
|
|
4419
|
+
xhigh: "X-High",
|
|
4420
|
+
max: "Max"
|
|
4421
|
+
};
|
|
4422
|
+
const API$4 = "/workbuddy/api";
|
|
4423
|
+
/**
|
|
4424
|
+
* Call one settings route and unwrap its `{ ok, value }` envelope.
|
|
4425
|
+
*
|
|
4426
|
+
* The response body is read as text first, because a route that is not mounted
|
|
4427
|
+
* answers with an empty body — and `res.json()` on that throws a bare
|
|
4428
|
+
* "Unexpected end of JSON input" that says nothing about what actually failed.
|
|
4429
|
+
* That is exactly what happens when the client bundle is newer than the Host
|
|
4430
|
+
* process (a stale Host has no route to answer), so the error is reported as
|
|
4431
|
+
* such instead of as a credential problem.
|
|
4432
|
+
*/
|
|
4433
|
+
async function fetchApi$4(path, options) {
|
|
4434
|
+
const res = await fetch(`${API$4}${path}`, {
|
|
4435
|
+
...options,
|
|
4436
|
+
headers: {
|
|
4437
|
+
"Content-Type": "application/json",
|
|
4438
|
+
...options?.headers
|
|
4439
|
+
}
|
|
4440
|
+
});
|
|
4441
|
+
const text = await res.text();
|
|
4442
|
+
if (text.trim() === "") throw new Error(`The WorkBuddy settings route did not answer (HTTP ${res.status} ${res.statusText || "no body"}). The plugin loaded in the browser may be newer than the one running in the Host — restart DSH so both halves come from the same build.`);
|
|
4443
|
+
let json;
|
|
4444
|
+
try {
|
|
4445
|
+
json = JSON.parse(text);
|
|
4446
|
+
} catch {
|
|
4447
|
+
throw new Error(`The WorkBuddy settings route returned a non-JSON response (HTTP ${res.status}): ${text.slice(0, 200)}`);
|
|
4448
|
+
}
|
|
4449
|
+
if (!res.ok || json.ok !== true) throw new Error(json.error || `HTTP ${res.status}`);
|
|
4450
|
+
return json.value;
|
|
4451
|
+
}
|
|
4452
|
+
/** Parse "1M", "512K", "200000" into a positive integer token count. */
|
|
4453
|
+
function parsePositiveCapacity(value) {
|
|
4454
|
+
const matched = value.trim().toLowerCase().replace(/[,_\s]/g, "").match(/^(\d+(?:\.\d+)?)(k|m)?$/);
|
|
4455
|
+
if (matched === null) return null;
|
|
4456
|
+
const multiplier = matched[2] === "m" ? 1e6 : matched[2] === "k" ? 1e3 : 1;
|
|
4457
|
+
const parsed = Number(matched[1]) * multiplier;
|
|
4458
|
+
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : null;
|
|
4459
|
+
}
|
|
4460
|
+
function formatCapacity(value) {
|
|
4461
|
+
if (value >= 1e6 && value % 1e5 === 0) return `${value / 1e6}M`;
|
|
4462
|
+
if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
|
|
4463
|
+
return String(value);
|
|
4464
|
+
}
|
|
4465
|
+
function formatDate(ms) {
|
|
4466
|
+
if (ms === void 0 || ms === null || ms <= 0) return "—";
|
|
4467
|
+
try {
|
|
4468
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
4469
|
+
dateStyle: "medium",
|
|
4470
|
+
timeStyle: "short"
|
|
4471
|
+
}).format(ms);
|
|
4472
|
+
} catch {
|
|
4473
|
+
return "—";
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
function formatReset(resetsAt) {
|
|
4477
|
+
if (resetsAt === void 0 || resetsAt === null || resetsAt <= 0) return "";
|
|
4478
|
+
const diff = resetsAt - Date.now();
|
|
4479
|
+
if (diff <= 0) return "now";
|
|
4480
|
+
const mins = Math.floor(diff / 6e4);
|
|
4481
|
+
const hours = Math.floor(mins / 60);
|
|
4482
|
+
const days = Math.floor(hours / 24);
|
|
4483
|
+
if (days > 0) return `${days}d ${hours % 24}h`;
|
|
4484
|
+
if (hours > 0) return `${hours}h ${mins % 60}m`;
|
|
4485
|
+
return `${mins}m`;
|
|
4486
|
+
}
|
|
4487
|
+
/** Mask a UIN so the card shows identity without publishing the full number. */
|
|
4488
|
+
function maskUin(uin) {
|
|
4489
|
+
if (uin === void 0 || uin === null || uin === "") return "—";
|
|
4490
|
+
if (uin.length <= 6) return uin;
|
|
4491
|
+
return `${uin.slice(0, 4)}****${uin.slice(-2)}`;
|
|
4492
|
+
}
|
|
4493
|
+
/** Shorten an absolute credential path to its file name for display. */
|
|
4494
|
+
function displayFile(file) {
|
|
4495
|
+
if (file === void 0 || file === null || file === "") return "—";
|
|
4496
|
+
const parts = file.split(/[\\/]/);
|
|
4497
|
+
return parts[parts.length - 1] || file;
|
|
4498
|
+
}
|
|
4499
|
+
/**
|
|
4500
|
+
* Reasoning levels the default-effort control may offer.
|
|
4501
|
+
*
|
|
4502
|
+
* The levels come from what this account's models actually declare — never from
|
|
4503
|
+
* the shipped enum alone. The setting is one global default applied to whichever
|
|
4504
|
+
* model a conversation uses, so the list is their union; each entry carries the
|
|
4505
|
+
* models behind it, and a level only some models accept is labelled as such.
|
|
4506
|
+
* Order follows {@link WORKBUDDY_REASONING_EFFORTS}, which is the escalating
|
|
4507
|
+
* order the upstream ladder uses.
|
|
4508
|
+
*/
|
|
4509
|
+
function reasoningEffortChoices(models) {
|
|
4510
|
+
const declared = /* @__PURE__ */ new Map();
|
|
4511
|
+
for (const model of models) for (const effort of model.reasoningEfforts ?? []) {
|
|
4512
|
+
const names = declared.get(effort);
|
|
4513
|
+
if (names === void 0) declared.set(effort, [model.name]);
|
|
4514
|
+
else names.push(model.name);
|
|
4515
|
+
}
|
|
4516
|
+
return WORKBUDDY_REASONING_EFFORTS.filter((effort) => declared.has(effort)).map((effort) => ({
|
|
4517
|
+
value: effort,
|
|
4518
|
+
models: declared.get(effort)
|
|
4519
|
+
}));
|
|
4520
|
+
}
|
|
4521
|
+
/**
|
|
4522
|
+
* Whether a saved default is unusable for every model on this account.
|
|
4523
|
+
*
|
|
4524
|
+
* The adapter drops a level the chosen model does not accept instead of sending
|
|
4525
|
+
* it, so a value that no model declares silently does nothing. Reporting it is
|
|
4526
|
+
* what keeps that from looking like the setting was applied.
|
|
4527
|
+
*/
|
|
4528
|
+
function unsupportedReasoningEffort(configured, models) {
|
|
4529
|
+
if (configured === null || configured === void 0) return null;
|
|
4530
|
+
return models.some((model) => (model.reasoningEfforts ?? []).includes(configured)) ? null : configured;
|
|
4531
|
+
}
|
|
4532
|
+
/** Defend against a response that omits the arrays the card renders. */
|
|
4533
|
+
function normalizeStatus(data) {
|
|
4534
|
+
return {
|
|
4535
|
+
...data,
|
|
4536
|
+
models: Array.isArray(data?.models) ? data.models : [],
|
|
4537
|
+
contextWindowOverrides: data?.contextWindowOverrides ?? {},
|
|
4538
|
+
accounts: Array.isArray(data?.accounts) ? data.accounts : []
|
|
4539
|
+
};
|
|
4540
|
+
}
|
|
4541
|
+
/**
|
|
4542
|
+
* The shared card's label set, taken from this tab's dictionary.
|
|
4543
|
+
*
|
|
4544
|
+
* Wording is the shared one so the five provider tabs cannot drift apart; the
|
|
4545
|
+
* couple of WorkBuddy-specific words are supplied here.
|
|
4546
|
+
*/
|
|
4547
|
+
function accountPoolLabels(t) {
|
|
4548
|
+
return {
|
|
4549
|
+
...accountPoolZh,
|
|
4550
|
+
accountPool: t.accounts,
|
|
4551
|
+
noAccounts: t.noAccounts,
|
|
4552
|
+
storage: t.storage,
|
|
4553
|
+
storageNotice: t.storageNotice,
|
|
4554
|
+
deleteAccount: t.deleteAccount,
|
|
4555
|
+
email: t.nickname,
|
|
4556
|
+
accountId: t.uid
|
|
4557
|
+
};
|
|
4558
|
+
}
|
|
4559
|
+
function WorkBuddySection({ onModelChange, loadModelDirectory }) {
|
|
4560
|
+
const [status, setStatus] = (0, react.useState)(null);
|
|
4561
|
+
const [loading, setLoading] = (0, react.useState)(true);
|
|
4562
|
+
const [busy, setBusy] = (0, react.useState)(null);
|
|
4563
|
+
const [error, setError] = (0, react.useState)(null);
|
|
4564
|
+
const [statusFailed, setStatusFailed] = (0, react.useState)(false);
|
|
4565
|
+
const [connection, setConnection] = (0, react.useState)(null);
|
|
4566
|
+
const [accounts, setAccounts] = (0, react.useState)(null);
|
|
4567
|
+
const [loginProgress, setLoginProgress] = (0, react.useState)(null);
|
|
4568
|
+
const loginIntervalRef = (0, react.useRef)(null);
|
|
4569
|
+
const loginTimeoutRef = (0, react.useRef)(null);
|
|
4570
|
+
const [contextDrafts, setContextDrafts] = (0, react.useState)({});
|
|
4571
|
+
const [savingModel, setSavingModel] = (0, react.useState)(null);
|
|
4572
|
+
const t = zh$1;
|
|
4573
|
+
const notifyChange = (0, react.useCallback)(() => {
|
|
4574
|
+
onModelChange?.();
|
|
4575
|
+
loadModelDirectory?.();
|
|
4576
|
+
}, [onModelChange, loadModelDirectory]);
|
|
4577
|
+
const effortChoices = (0, react.useMemo)(() => reasoningEffortChoices(status?.models ?? []), [status?.models]);
|
|
4578
|
+
const allModels = status?.models ?? [];
|
|
4579
|
+
const poolAccounts = (0, react.useMemo)(() => Array.isArray(status?.accounts) ? status.accounts : [], [status?.accounts]);
|
|
4580
|
+
const strayEffort = unsupportedReasoningEffort(status?.defaultReasoningEffort, allModels);
|
|
4581
|
+
const loadStatus = (0, react.useCallback)(async (quiet = false) => {
|
|
4582
|
+
if (!quiet) setError(null);
|
|
4583
|
+
try {
|
|
4584
|
+
const normalized = normalizeStatus(await fetchApi$4("/status"));
|
|
4585
|
+
setStatus(normalized);
|
|
4586
|
+
setStatusFailed(false);
|
|
4587
|
+
const drafts = {};
|
|
4588
|
+
for (const model of normalized.models) drafts[model.id] = formatCapacity(normalized.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
4589
|
+
setContextDrafts(drafts);
|
|
4590
|
+
} catch (err) {
|
|
4591
|
+
setStatusFailed(true);
|
|
4592
|
+
if (!quiet) setError(err instanceof Error ? err.message : String(err));
|
|
4593
|
+
} finally {
|
|
4594
|
+
setLoading(false);
|
|
4595
|
+
}
|
|
4596
|
+
}, []);
|
|
4597
|
+
const loadAccounts = (0, react.useCallback)(async () => {
|
|
4598
|
+
try {
|
|
4599
|
+
const payload = await fetchApi$4("/accounts");
|
|
4600
|
+
setAccounts({
|
|
4601
|
+
authDirectory: payload?.authDirectory ?? "",
|
|
4602
|
+
managedStoragePath: payload?.managedStoragePath,
|
|
4603
|
+
accounts: Array.isArray(payload?.accounts) ? payload.accounts : []
|
|
4604
|
+
});
|
|
4605
|
+
} catch {}
|
|
4606
|
+
}, []);
|
|
4607
|
+
(0, react.useEffect)(() => {
|
|
4608
|
+
loadStatus();
|
|
4609
|
+
loadAccounts();
|
|
4610
|
+
const refreshWhenVisible = () => {
|
|
4611
|
+
if (document.visibilityState === "visible") {
|
|
4612
|
+
loadStatus(true);
|
|
4613
|
+
loadAccounts();
|
|
4614
|
+
}
|
|
4615
|
+
};
|
|
4616
|
+
document.addEventListener("visibilitychange", refreshWhenVisible);
|
|
4617
|
+
return () => {
|
|
4618
|
+
document.removeEventListener("visibilitychange", refreshWhenVisible);
|
|
4619
|
+
if (loginIntervalRef.current !== null) window.clearInterval(loginIntervalRef.current);
|
|
4620
|
+
if (loginTimeoutRef.current !== null) window.clearTimeout(loginTimeoutRef.current);
|
|
4621
|
+
};
|
|
4622
|
+
}, [loadStatus, loadAccounts]);
|
|
4623
|
+
const handleRescan = async () => {
|
|
4624
|
+
try {
|
|
4625
|
+
setBusy("rescan");
|
|
4626
|
+
setError(null);
|
|
4627
|
+
const updated = await fetchApi$4("/rescan", { method: "POST" });
|
|
4628
|
+
setStatus(updated);
|
|
4629
|
+
await loadAccounts();
|
|
4630
|
+
notifyChange();
|
|
4631
|
+
} catch (err) {
|
|
4632
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4633
|
+
} finally {
|
|
4634
|
+
setBusy(null);
|
|
4635
|
+
}
|
|
4636
|
+
};
|
|
4637
|
+
const handleAddAccount = async (region) => {
|
|
4638
|
+
try {
|
|
4639
|
+
setBusy(`login:${region}`);
|
|
4640
|
+
setError(null);
|
|
4641
|
+
setLoginProgress(t.loginWaiting);
|
|
4642
|
+
const flow = await fetchApi$4("/accounts/login", {
|
|
4643
|
+
method: "POST",
|
|
4644
|
+
body: JSON.stringify({ region })
|
|
4645
|
+
});
|
|
4646
|
+
if (flow.authUrl) window.open(flow.authUrl, "_blank", "noopener,noreferrer");
|
|
4647
|
+
if (loginIntervalRef.current !== null) window.clearInterval(loginIntervalRef.current);
|
|
4648
|
+
if (loginTimeoutRef.current !== null) window.clearTimeout(loginTimeoutRef.current);
|
|
4649
|
+
const timer = window.setInterval(() => {
|
|
4650
|
+
(async () => {
|
|
4651
|
+
try {
|
|
4652
|
+
const poll = await fetchApi$4("/accounts/login/status");
|
|
4653
|
+
if (poll.progress) setLoginProgress(poll.progress);
|
|
4654
|
+
if (poll.status === "complete") {
|
|
4655
|
+
window.clearInterval(timer);
|
|
4656
|
+
loginIntervalRef.current = null;
|
|
4657
|
+
if (loginTimeoutRef.current !== null) window.clearTimeout(loginTimeoutRef.current);
|
|
4658
|
+
loginTimeoutRef.current = null;
|
|
4659
|
+
setBusy(null);
|
|
4660
|
+
setLoginProgress(null);
|
|
4661
|
+
if (poll.accountId) await fetchApi$4("/settings", {
|
|
4662
|
+
method: "POST",
|
|
4663
|
+
body: JSON.stringify({ selectedAccountId: poll.accountId })
|
|
4664
|
+
});
|
|
4665
|
+
await loadStatus();
|
|
4666
|
+
await loadAccounts();
|
|
4667
|
+
notifyChange();
|
|
4668
|
+
} else if (poll.status === "error") {
|
|
4669
|
+
window.clearInterval(timer);
|
|
4670
|
+
loginIntervalRef.current = null;
|
|
4671
|
+
if (loginTimeoutRef.current !== null) window.clearTimeout(loginTimeoutRef.current);
|
|
4672
|
+
loginTimeoutRef.current = null;
|
|
4673
|
+
setBusy(null);
|
|
4674
|
+
setLoginProgress(null);
|
|
4675
|
+
setError(poll.error || t.loginFailed);
|
|
4676
|
+
}
|
|
4677
|
+
} catch {}
|
|
4678
|
+
})();
|
|
4679
|
+
}, 1500);
|
|
4680
|
+
loginIntervalRef.current = timer;
|
|
4681
|
+
loginTimeoutRef.current = window.setTimeout(() => {
|
|
4682
|
+
window.clearInterval(timer);
|
|
4683
|
+
loginIntervalRef.current = null;
|
|
4684
|
+
loginTimeoutRef.current = null;
|
|
4685
|
+
setBusy(null);
|
|
4686
|
+
setLoginProgress(null);
|
|
4687
|
+
}, 300 * 1e3);
|
|
4688
|
+
} catch (err) {
|
|
4689
|
+
setBusy(null);
|
|
4690
|
+
setLoginProgress(null);
|
|
4691
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4692
|
+
}
|
|
4693
|
+
};
|
|
4694
|
+
/**
|
|
4695
|
+
* One account action, whether it is a pool action (`set-primary`, `hide`) or a
|
|
4696
|
+
* credential action (`delete`). The host route dispatches on `action`.
|
|
4697
|
+
*/
|
|
4698
|
+
const handlePoolAction = async (action, accountId) => {
|
|
4699
|
+
try {
|
|
4700
|
+
setBusy(`${action}:${accountId}`);
|
|
4701
|
+
setError(null);
|
|
4702
|
+
const updated = await fetchApi$4("/accounts/action", {
|
|
4703
|
+
method: "POST",
|
|
4704
|
+
body: JSON.stringify({
|
|
4705
|
+
action,
|
|
4706
|
+
accountId
|
|
4707
|
+
})
|
|
4708
|
+
});
|
|
4709
|
+
setStatus(normalizeStatus(updated));
|
|
4710
|
+
await loadAccounts();
|
|
4711
|
+
notifyChange();
|
|
4712
|
+
} catch (err) {
|
|
4713
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4714
|
+
} finally {
|
|
4715
|
+
setBusy(null);
|
|
4716
|
+
}
|
|
4717
|
+
};
|
|
4718
|
+
const handleDeleteAccount = async (accountId) => {
|
|
4719
|
+
if (!window.confirm(t.deleteConfirm)) return;
|
|
4720
|
+
await handlePoolAction("delete", accountId);
|
|
4721
|
+
};
|
|
4722
|
+
const handleSetStrategy = async (strategy) => {
|
|
4723
|
+
try {
|
|
4724
|
+
setBusy("strategy");
|
|
4725
|
+
setError(null);
|
|
4726
|
+
const updated = await fetchApi$4("/accounts/strategy", {
|
|
4727
|
+
method: "POST",
|
|
4728
|
+
body: JSON.stringify({ strategy })
|
|
4729
|
+
});
|
|
4730
|
+
setStatus(normalizeStatus(updated));
|
|
4731
|
+
await loadAccounts();
|
|
4732
|
+
} catch (err) {
|
|
4733
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4734
|
+
} finally {
|
|
4735
|
+
setBusy(null);
|
|
4736
|
+
}
|
|
4737
|
+
};
|
|
4738
|
+
const handleTestConnection = async () => {
|
|
4739
|
+
try {
|
|
4740
|
+
setBusy("connection");
|
|
4741
|
+
setError(null);
|
|
4742
|
+
setConnection(await fetchApi$4("/connection/test", { method: "POST" }));
|
|
4743
|
+
} catch (err) {
|
|
4744
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4745
|
+
} finally {
|
|
4746
|
+
setBusy(null);
|
|
4747
|
+
}
|
|
4748
|
+
};
|
|
4749
|
+
const handleRefreshQuota = async () => {
|
|
4750
|
+
try {
|
|
4751
|
+
setBusy("quota");
|
|
4752
|
+
setError(null);
|
|
4753
|
+
const updated = await fetchApi$4("/quota", { method: "POST" });
|
|
4754
|
+
setStatus(updated);
|
|
4755
|
+
} catch (err) {
|
|
4756
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4757
|
+
} finally {
|
|
4758
|
+
setBusy(null);
|
|
4759
|
+
}
|
|
4760
|
+
};
|
|
4761
|
+
const toggleEnabled = async (enabled) => {
|
|
4762
|
+
try {
|
|
4763
|
+
setBusy("enabled");
|
|
4764
|
+
setError(null);
|
|
4765
|
+
const updated = await fetchApi$4("/settings", {
|
|
4766
|
+
method: "POST",
|
|
4767
|
+
body: JSON.stringify({ enabled })
|
|
4768
|
+
});
|
|
4769
|
+
setStatus(updated);
|
|
4770
|
+
notifyChange();
|
|
4771
|
+
} catch (err) {
|
|
4772
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4773
|
+
} finally {
|
|
4774
|
+
setBusy(null);
|
|
4775
|
+
}
|
|
4776
|
+
};
|
|
4777
|
+
const toggleModel = async (modelId, enabled) => {
|
|
4778
|
+
if (status === null) return;
|
|
4779
|
+
const current = status.models.filter((model) => model.enabled).map((model) => model.id);
|
|
4780
|
+
const next = enabled ? [.../* @__PURE__ */ new Set([...current, modelId])] : current.filter((id) => id !== modelId);
|
|
4781
|
+
try {
|
|
4782
|
+
setBusy(`model:${modelId}`);
|
|
4783
|
+
setError(null);
|
|
4784
|
+
const updated = await fetchApi$4("/settings", {
|
|
4785
|
+
method: "POST",
|
|
4786
|
+
body: JSON.stringify({ enabledModelIds: next })
|
|
4787
|
+
});
|
|
4788
|
+
setStatus(updated);
|
|
4789
|
+
notifyChange();
|
|
4790
|
+
} catch (err) {
|
|
4791
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4792
|
+
} finally {
|
|
4793
|
+
setBusy(null);
|
|
4794
|
+
}
|
|
4795
|
+
};
|
|
4796
|
+
const setAllModels = async (enabled) => {
|
|
4797
|
+
if (status === null) return;
|
|
4798
|
+
try {
|
|
4799
|
+
setBusy("models-all");
|
|
4800
|
+
setError(null);
|
|
4801
|
+
const updated = await fetchApi$4("/settings", {
|
|
4802
|
+
method: "POST",
|
|
4803
|
+
body: JSON.stringify({ enabledModelIds: enabled ? status.models.map((model) => model.id) : [] })
|
|
4804
|
+
});
|
|
4805
|
+
setStatus(updated);
|
|
4806
|
+
notifyChange();
|
|
4807
|
+
} catch (err) {
|
|
4808
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4809
|
+
} finally {
|
|
4810
|
+
setBusy(null);
|
|
4811
|
+
}
|
|
4812
|
+
};
|
|
4813
|
+
const handleUpdateEffort = async (effort) => {
|
|
4814
|
+
try {
|
|
4815
|
+
setBusy("effort");
|
|
4816
|
+
setError(null);
|
|
4817
|
+
const updated = await fetchApi$4("/settings", {
|
|
4818
|
+
method: "POST",
|
|
4819
|
+
body: JSON.stringify({ defaultReasoningEffort: effort })
|
|
4820
|
+
});
|
|
4821
|
+
setStatus(updated);
|
|
4822
|
+
notifyChange();
|
|
4823
|
+
} catch (err) {
|
|
4824
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4825
|
+
} finally {
|
|
4826
|
+
setBusy(null);
|
|
4827
|
+
}
|
|
4828
|
+
};
|
|
4829
|
+
const handleRefreshCatalog = async () => {
|
|
4830
|
+
try {
|
|
4831
|
+
setBusy("catalog");
|
|
4832
|
+
setError(null);
|
|
4833
|
+
const updated = await fetchApi$4("/catalog/refresh", { method: "POST" });
|
|
4834
|
+
const normalized = {
|
|
4835
|
+
...updated,
|
|
4836
|
+
models: Array.isArray(updated?.models) ? updated.models : [],
|
|
4837
|
+
contextWindowOverrides: updated?.contextWindowOverrides ?? {}
|
|
4838
|
+
};
|
|
4839
|
+
setStatus(normalized);
|
|
4840
|
+
const drafts = {};
|
|
4841
|
+
for (const model of normalized.models) drafts[model.id] = formatCapacity(normalized.contextWindowOverrides[model.id] || model.defaultContextWindow);
|
|
4842
|
+
setContextDrafts(drafts);
|
|
4843
|
+
notifyChange();
|
|
4844
|
+
} catch (err) {
|
|
4845
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4846
|
+
} finally {
|
|
4847
|
+
setBusy(null);
|
|
4848
|
+
}
|
|
4849
|
+
};
|
|
4850
|
+
const handleSaveContextWindow = async (modelId) => {
|
|
4851
|
+
const raw = contextDrafts[modelId] || "";
|
|
4852
|
+
const parsed = parsePositiveCapacity(raw);
|
|
4853
|
+
if (parsed === null) {
|
|
4854
|
+
setError(`Invalid context capacity: ${raw}`);
|
|
4855
|
+
return;
|
|
4856
|
+
}
|
|
4857
|
+
try {
|
|
4858
|
+
setSavingModel(modelId);
|
|
4859
|
+
setError(null);
|
|
4860
|
+
const updated = await fetchApi$4("/settings", {
|
|
4861
|
+
method: "POST",
|
|
4862
|
+
body: JSON.stringify({ contextWindowOverrides: { [modelId]: parsed } })
|
|
4863
|
+
});
|
|
4864
|
+
setStatus(updated);
|
|
4865
|
+
setContextDrafts((prev) => ({
|
|
4866
|
+
...prev,
|
|
4867
|
+
[modelId]: formatCapacity(parsed)
|
|
4868
|
+
}));
|
|
4869
|
+
notifyChange();
|
|
4870
|
+
} catch (err) {
|
|
4871
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
4872
|
+
} finally {
|
|
4873
|
+
setSavingModel(null);
|
|
4874
|
+
}
|
|
4875
|
+
};
|
|
4876
|
+
if (loading) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4877
|
+
className: "dsha-page",
|
|
4878
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4879
|
+
className: "dsha-empty",
|
|
4880
|
+
children: t.loading
|
|
4881
|
+
})
|
|
4882
|
+
});
|
|
4883
|
+
const quota = status?.quota;
|
|
4884
|
+
const account = status?.account;
|
|
4885
|
+
const authenticated = status?.authenticated === true;
|
|
4886
|
+
const unreachable = statusFailed && status === null;
|
|
4887
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4888
|
+
className: "dsha-page",
|
|
4889
|
+
children: [
|
|
4890
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4891
|
+
className: "dsha-group",
|
|
4892
|
+
children: [
|
|
4893
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4894
|
+
className: "dsha-grouphead",
|
|
4895
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: authenticated ? t.account : t.signedOut }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4896
|
+
className: "dsha-btn",
|
|
4897
|
+
disabled: busy !== null,
|
|
4898
|
+
onClick: () => void handleRescan(),
|
|
4899
|
+
children: busy === "rescan" ? t.rescanning : t.rescan
|
|
4900
|
+
})]
|
|
4901
|
+
}),
|
|
4902
|
+
unreachable ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4903
|
+
className: "dsha-empty",
|
|
4904
|
+
children: t.routeUnreachable
|
|
4905
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4906
|
+
className: "dsha-notice",
|
|
4907
|
+
children: t.routeUnreachableHint
|
|
4908
|
+
})] }) : !authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4909
|
+
className: "dsha-empty",
|
|
4910
|
+
children: t.notFoundTitle
|
|
4911
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4912
|
+
className: "dsha-notice",
|
|
4913
|
+
children: t.notFoundHint
|
|
4914
|
+
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4915
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4916
|
+
className: "dsha-row",
|
|
4917
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4918
|
+
className: "dsha-label",
|
|
4919
|
+
children: t.nickname
|
|
4920
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4921
|
+
className: "dsha-value",
|
|
4922
|
+
children: account?.nickname || "—"
|
|
4923
|
+
})]
|
|
4924
|
+
}),
|
|
4925
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4926
|
+
className: "dsha-row",
|
|
4927
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4928
|
+
className: "dsha-label",
|
|
4929
|
+
children: t.uid
|
|
4930
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4931
|
+
className: "dsha-value dshwb-mono",
|
|
4932
|
+
children: account?.uid || "—"
|
|
4933
|
+
})]
|
|
4934
|
+
}),
|
|
4935
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4936
|
+
className: "dsha-row",
|
|
4937
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4938
|
+
className: "dsha-label",
|
|
4939
|
+
children: t.uin
|
|
4940
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4941
|
+
className: "dsha-value dshwb-mono",
|
|
4942
|
+
children: maskUin(account?.uin)
|
|
4943
|
+
})]
|
|
4944
|
+
}),
|
|
4945
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4946
|
+
className: "dsha-row",
|
|
4947
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4948
|
+
className: "dsha-label",
|
|
4949
|
+
children: t.region
|
|
4950
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4951
|
+
className: "dsha-value",
|
|
4952
|
+
children: [account?.region === "intl" ? t.regionIntl : t.regionCn, account?.accountType ? ` · ${account.accountType}` : ""]
|
|
4953
|
+
})]
|
|
4954
|
+
}),
|
|
4955
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4956
|
+
className: "dsha-row",
|
|
4957
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4958
|
+
className: "dsha-label",
|
|
4959
|
+
children: t.domain
|
|
4960
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4961
|
+
className: "dsha-value dshwb-mono",
|
|
4962
|
+
children: account?.domain || "—"
|
|
4963
|
+
})]
|
|
4964
|
+
}),
|
|
4965
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4966
|
+
className: "dsha-row",
|
|
4967
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4968
|
+
className: "dsha-label",
|
|
4969
|
+
children: t.backend
|
|
4970
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4971
|
+
className: "dsha-value dshwb-mono",
|
|
4972
|
+
children: account?.backend || "—"
|
|
4973
|
+
})]
|
|
4974
|
+
}),
|
|
4975
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4976
|
+
className: "dsha-row",
|
|
4977
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4978
|
+
className: "dsha-label",
|
|
4979
|
+
children: t.tokenExpires
|
|
4980
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4981
|
+
className: "dsha-value",
|
|
4982
|
+
children: account?.expiresAt === null || account?.expiresAt === void 0 ? "—" : account.expiresAt <= Date.now() ? t.tokenExpired : formatDate(account.expiresAt)
|
|
4983
|
+
})]
|
|
4984
|
+
}),
|
|
4985
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4986
|
+
className: "dsha-row",
|
|
4987
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4988
|
+
className: "dsha-label",
|
|
4989
|
+
children: t.sourceFile
|
|
4990
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4991
|
+
className: "dsha-value dshwb-mono",
|
|
4992
|
+
title: account?.sourceFile ?? status?.managedStoragePath ?? "",
|
|
4993
|
+
children: account?.source === "managed" ? t.encryptedStorage : displayFile(account?.sourceFile)
|
|
4994
|
+
})]
|
|
4995
|
+
})
|
|
4996
|
+
] }),
|
|
4997
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4998
|
+
className: "dsha-row",
|
|
4999
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5000
|
+
className: "dsha-label",
|
|
5001
|
+
children: t.authDirectory
|
|
5002
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5003
|
+
className: "dsha-value dshwb-mono",
|
|
5004
|
+
children: status?.authDirectory || "—"
|
|
5005
|
+
})]
|
|
5006
|
+
}),
|
|
5007
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5008
|
+
className: "dsha-notice",
|
|
5009
|
+
children: t.storageNotice
|
|
5010
|
+
})
|
|
5011
|
+
]
|
|
5012
|
+
}),
|
|
5013
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountPoolSection, {
|
|
5014
|
+
accounts: poolAccounts,
|
|
5015
|
+
activeAccountId: status?.activeAccountId,
|
|
5016
|
+
rotationStrategy: status?.rotationStrategy ?? "sequential",
|
|
5017
|
+
labels: accountPoolLabels(t),
|
|
5018
|
+
busy,
|
|
5019
|
+
onLogin: () => void handleAddAccount("cn"),
|
|
5020
|
+
onSetPrimary: (id) => void handlePoolAction("set-primary", id),
|
|
5021
|
+
onDelete: (id) => void handleDeleteAccount(id),
|
|
5022
|
+
onClearCooldown: (id) => void handlePoolAction("clear-cooldown", id),
|
|
5023
|
+
onRelogin: (id) => void handlePoolAction("relogin", id),
|
|
5024
|
+
onSetStrategy: (strategy) => void handleSetStrategy(strategy),
|
|
5025
|
+
storageValue: status?.managedStoragePath,
|
|
5026
|
+
renderLoginActions: () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5027
|
+
className: "dsha-account-add-actions",
|
|
5028
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5029
|
+
className: "dsha-btn",
|
|
5030
|
+
disabled: busy !== null,
|
|
5031
|
+
onClick: () => void handleAddAccount("cn"),
|
|
5032
|
+
children: busy === "login:cn" ? t.authorizing : t.addCnAccount
|
|
5033
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5034
|
+
className: "dsha-btn",
|
|
5035
|
+
disabled: busy !== null,
|
|
5036
|
+
onClick: () => void handleAddAccount("intl"),
|
|
5037
|
+
children: busy === "login:intl" ? t.authorizing : t.addIntlAccount
|
|
5038
|
+
})]
|
|
5039
|
+
}),
|
|
5040
|
+
renderAccountActions: (candidate) => candidate.removable ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [candidate.hidden === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5041
|
+
className: "dsha-btn",
|
|
5042
|
+
disabled: busy !== null,
|
|
5043
|
+
onClick: () => void handlePoolAction("restore", candidate.id),
|
|
5044
|
+
children: t.restoreAccount
|
|
5045
|
+
}), candidate.hidden !== true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5046
|
+
className: "dsha-btn",
|
|
5047
|
+
disabled: busy !== null,
|
|
5048
|
+
onClick: () => void handlePoolAction("hide", candidate.id),
|
|
5049
|
+
children: t.hideAccount
|
|
5050
|
+
})] }),
|
|
5051
|
+
renderDetails: (candidate) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
5052
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
5053
|
+
t.region,
|
|
5054
|
+
": ",
|
|
5055
|
+
candidate.region === "intl" ? t.regionIntl : t.regionCn
|
|
5056
|
+
] }),
|
|
5057
|
+
candidate.uin ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
5058
|
+
t.uin,
|
|
5059
|
+
": ",
|
|
5060
|
+
maskUin(candidate.uin)
|
|
5061
|
+
] }) : null,
|
|
5062
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5063
|
+
className: "dshwb-mono",
|
|
5064
|
+
children: candidate.source === "managed" ? t.encryptedStorage : displayFile(candidate.sourceFile)
|
|
5065
|
+
}),
|
|
5066
|
+
candidate.hidden === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.hiddenAccount }) : null
|
|
5067
|
+
] })
|
|
5068
|
+
}),
|
|
5069
|
+
loginProgress ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5070
|
+
className: "dsha-notice",
|
|
5071
|
+
children: loginProgress
|
|
5072
|
+
}) : null,
|
|
5073
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5074
|
+
className: "dsha-group",
|
|
5075
|
+
children: [
|
|
5076
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5077
|
+
className: "dsha-grouphead",
|
|
5078
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.connection })
|
|
5079
|
+
}),
|
|
5080
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5081
|
+
className: "dsha-row",
|
|
5082
|
+
style: { marginBottom: 12 },
|
|
5083
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5084
|
+
className: "dsha-label",
|
|
5085
|
+
style: { fontWeight: 600 },
|
|
5086
|
+
children: t.enableProvider
|
|
5087
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5088
|
+
type: "checkbox",
|
|
5089
|
+
checked: status?.enabled !== false,
|
|
5090
|
+
disabled: busy !== null,
|
|
5091
|
+
onChange: (e) => void toggleEnabled(e.currentTarget.checked)
|
|
5092
|
+
})]
|
|
5093
|
+
}),
|
|
5094
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5095
|
+
className: "dsha-row",
|
|
5096
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5097
|
+
className: "dsha-label",
|
|
5098
|
+
children: t.provider
|
|
5099
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5100
|
+
className: "dsha-value",
|
|
5101
|
+
children: t.providerValue
|
|
5102
|
+
})]
|
|
5103
|
+
}),
|
|
5104
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5105
|
+
className: "dsha-row",
|
|
5106
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5107
|
+
className: "dsha-label",
|
|
5108
|
+
children: t.connectionState
|
|
5109
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5110
|
+
className: "dsha-value",
|
|
5111
|
+
children: [connection?.connected ? t.connected : authenticated ? t.untested : t.signedOut, connection?.connected ? ` · ${connection.latencyMs}ms · ${connection.model}` : ""]
|
|
5112
|
+
})]
|
|
5113
|
+
}),
|
|
5114
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5115
|
+
className: "dsha-notice",
|
|
5116
|
+
children: status?.serving === false && status.conflict ? t.routeConflict.replace("{detail}", status.conflict) : t.routeOwned
|
|
5117
|
+
}),
|
|
5118
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5119
|
+
className: "dsha-actions",
|
|
5120
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5121
|
+
className: "dsha-btn",
|
|
5122
|
+
disabled: busy !== null || !authenticated,
|
|
5123
|
+
onClick: () => void handleTestConnection(),
|
|
5124
|
+
children: busy === "connection" ? t.testingConnection : t.testConnection
|
|
5125
|
+
})
|
|
5126
|
+
})
|
|
5127
|
+
]
|
|
5128
|
+
}),
|
|
5129
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5130
|
+
className: "dsha-group",
|
|
5131
|
+
children: [
|
|
5132
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5133
|
+
className: "dsha-grouphead",
|
|
5134
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.modelsSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5135
|
+
className: "dsha-btn",
|
|
5136
|
+
disabled: busy !== null || !authenticated,
|
|
5137
|
+
onClick: () => void handleRefreshCatalog(),
|
|
5138
|
+
children: busy === "catalog" ? t.refreshingCatalog : t.refreshCatalog
|
|
5139
|
+
})]
|
|
5140
|
+
}),
|
|
5141
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5142
|
+
className: "dsha-muted dsha-models-hint",
|
|
5143
|
+
children: t.modelsHint
|
|
5144
|
+
}),
|
|
5145
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5146
|
+
className: "dsha-models",
|
|
5147
|
+
"aria-label": "WorkBuddy Models",
|
|
5148
|
+
children: status?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
5149
|
+
title: model.description ?? model.id,
|
|
5150
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5151
|
+
type: "checkbox",
|
|
5152
|
+
checked: model.enabled,
|
|
5153
|
+
disabled: busy !== null,
|
|
5154
|
+
onChange: (event) => void toggleModel(model.id, event.currentTarget.checked)
|
|
5155
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5156
|
+
className: "dshwb-model",
|
|
5157
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5158
|
+
className: "dshwb-model-meta",
|
|
5159
|
+
children: [
|
|
5160
|
+
formatCapacity(model.contextWindow),
|
|
5161
|
+
" · ",
|
|
5162
|
+
model.supportsImage ? t.imageSupport : t.textOnly,
|
|
5163
|
+
model.reasoningEfforts && model.reasoningEfforts.length > 0 ? ` · ${model.reasoningEfforts.join("/")}` : ""
|
|
5164
|
+
]
|
|
5165
|
+
})]
|
|
5166
|
+
})]
|
|
5167
|
+
}, model.id))
|
|
5168
|
+
}),
|
|
5169
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5170
|
+
className: "dsha-actions",
|
|
5171
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5172
|
+
className: "dsha-btn",
|
|
5173
|
+
disabled: busy !== null,
|
|
5174
|
+
onClick: () => void setAllModels(true),
|
|
5175
|
+
children: t.selectAll
|
|
5176
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5177
|
+
className: "dsha-btn",
|
|
5178
|
+
disabled: busy !== null,
|
|
5179
|
+
onClick: () => void setAllModels(false),
|
|
5180
|
+
children: t.unselectAll
|
|
5181
|
+
})]
|
|
5182
|
+
})
|
|
5183
|
+
]
|
|
5184
|
+
}),
|
|
5185
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5186
|
+
className: "dsha-group",
|
|
5187
|
+
children: [
|
|
5188
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5189
|
+
className: "dsha-grouphead",
|
|
5190
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.enhanced })
|
|
5191
|
+
}),
|
|
5192
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5193
|
+
className: "dsha-pref-row",
|
|
5194
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
5195
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.defaultReasoningEffort }),
|
|
5196
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5197
|
+
className: "dsha-muted",
|
|
5198
|
+
children: t.defaultReasoningEffortHint
|
|
5199
|
+
}),
|
|
5200
|
+
strayEffort !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5201
|
+
className: "dsha-muted",
|
|
5202
|
+
children: t.defaultEffortKept
|
|
5203
|
+
}) : null
|
|
5204
|
+
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
5205
|
+
className: "dsha-select",
|
|
5206
|
+
"aria-label": t.defaultReasoningEffort,
|
|
5207
|
+
value: status?.defaultReasoningEffort ?? "",
|
|
5208
|
+
disabled: busy !== null,
|
|
5209
|
+
onChange: (event) => {
|
|
5210
|
+
const value = event.currentTarget.value;
|
|
5211
|
+
handleUpdateEffort(value === "" ? null : value);
|
|
5212
|
+
},
|
|
5213
|
+
children: [
|
|
5214
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5215
|
+
value: "",
|
|
5216
|
+
children: t.defaultEffortAuto
|
|
5217
|
+
}),
|
|
5218
|
+
strayEffort !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5219
|
+
value: strayEffort,
|
|
5220
|
+
children: `${EFFORT_LABELS[strayEffort]} (${t.effortUnsupported})`
|
|
5221
|
+
}) : null,
|
|
5222
|
+
effortChoices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
5223
|
+
value: choice.value,
|
|
5224
|
+
children: choice.models.length === allModels.length ? EFFORT_LABELS[choice.value] : `${EFFORT_LABELS[choice.value]} (${choice.models.length}/${allModels.length})`
|
|
5225
|
+
}, choice.value))
|
|
5226
|
+
]
|
|
5227
|
+
})]
|
|
5228
|
+
}),
|
|
5229
|
+
effortChoices.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3896
5230
|
className: "dsha-muted",
|
|
3897
|
-
children: t.
|
|
3898
|
-
})
|
|
3899
|
-
|
|
3900
|
-
"aria-label": t.defaultReasoningEffort,
|
|
3901
|
-
value: status?.defaultReasoningEffort ?? "",
|
|
3902
|
-
disabled: busy !== null,
|
|
3903
|
-
onChange: (event) => {
|
|
3904
|
-
const value = event.currentTarget.value;
|
|
3905
|
-
handleUpdateEffort(value === "" ? null : value);
|
|
3906
|
-
},
|
|
3907
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3908
|
-
value: "",
|
|
3909
|
-
children: t.defaultEffortAuto
|
|
3910
|
-
}), KIMI_CODE_REASONING_EFFORTS.map((effort) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
3911
|
-
value: effort,
|
|
3912
|
-
children: EFFORT_LABEL[effort]
|
|
3913
|
-
}, effort))]
|
|
3914
|
-
})]
|
|
3915
|
-
})]
|
|
5231
|
+
children: t.noReasoningModels
|
|
5232
|
+
}) : null
|
|
5233
|
+
]
|
|
3916
5234
|
}),
|
|
3917
5235
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3918
5236
|
className: "dsha-group",
|
|
@@ -3929,12 +5247,9 @@ window.__ModuleLoader__.load({
|
|
|
3929
5247
|
className: "dsha-context-settings",
|
|
3930
5248
|
children: status?.models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3931
5249
|
className: "dsha-context-row",
|
|
3932
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5250
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3933
5251
|
title: model.id,
|
|
3934
|
-
children:
|
|
3935
|
-
className: "dsha-model-meta",
|
|
3936
|
-
children: formatCapacity(model.contextWindow)
|
|
3937
|
-
})]
|
|
5252
|
+
children: model.name
|
|
3938
5253
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3939
5254
|
className: "dsha-capacity-control",
|
|
3940
5255
|
children: [
|
|
@@ -3950,7 +5265,7 @@ window.__ModuleLoader__.load({
|
|
|
3950
5265
|
if (event.key === "Enter") handleSaveContextWindow(model.id);
|
|
3951
5266
|
}
|
|
3952
5267
|
}),
|
|
3953
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children:
|
|
5268
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "tokens" }),
|
|
3954
5269
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3955
5270
|
type: "button",
|
|
3956
5271
|
className: "dsha-context-save",
|
|
@@ -3971,7 +5286,7 @@ window.__ModuleLoader__.load({
|
|
|
3971
5286
|
className: "dsha-grouphead",
|
|
3972
5287
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t.quotaSection }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3973
5288
|
className: "dsha-btn",
|
|
3974
|
-
disabled: busy !== null || !
|
|
5289
|
+
disabled: busy !== null || !authenticated,
|
|
3975
5290
|
onClick: () => void handleRefreshQuota(),
|
|
3976
5291
|
children: busy === "quota" ? t.refreshingQuota : t.refreshQuota
|
|
3977
5292
|
})]
|
|
@@ -3980,11 +5295,7 @@ window.__ModuleLoader__.load({
|
|
|
3980
5295
|
className: "dsha-muted",
|
|
3981
5296
|
children: t.quotaDesc
|
|
3982
5297
|
}),
|
|
3983
|
-
|
|
3984
|
-
className: "dsha-notice",
|
|
3985
|
-
children: status.quotaError
|
|
3986
|
-
}),
|
|
3987
|
-
!status?.authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5298
|
+
!authenticated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3988
5299
|
className: "dsha-empty",
|
|
3989
5300
|
children: t.signedOut
|
|
3990
5301
|
}) : quota === null || quota === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -3995,49 +5306,62 @@ window.__ModuleLoader__.load({
|
|
|
3995
5306
|
children: [
|
|
3996
5307
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3997
5308
|
className: "dsha-quota-title",
|
|
3998
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t.
|
|
5309
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: quota.packageName || t.quotaPackage }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: quota.remainingCredits !== null ? `${quota.remainingCredits} ${t.credits}` : "—" })]
|
|
3999
5310
|
}),
|
|
4000
|
-
quota.
|
|
4001
|
-
|
|
5311
|
+
quota.cycleUsedCredits !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5312
|
+
className: "dsha-row",
|
|
5313
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5314
|
+
className: "dsha-label",
|
|
5315
|
+
children: t.quotaCycle
|
|
5316
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5317
|
+
className: "dsha-value",
|
|
5318
|
+
children: [
|
|
5319
|
+
quota.cycleUsedCredits,
|
|
5320
|
+
quota.cycleCredits !== null ? ` / ${quota.cycleCredits}` : "",
|
|
5321
|
+
` ${t.credits}`
|
|
5322
|
+
]
|
|
5323
|
+
})]
|
|
5324
|
+
}),
|
|
5325
|
+
quota.cycleEndsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5326
|
+
className: "dsha-row",
|
|
5327
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5328
|
+
className: "dsha-label",
|
|
5329
|
+
children: t.quotaReset
|
|
5330
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5331
|
+
className: "dsha-value",
|
|
5332
|
+
children: [formatDate(quota.cycleEndsAt), formatReset(quota.cycleEndsAt) ? ` · ${formatReset(quota.cycleEndsAt)}` : ""]
|
|
5333
|
+
})]
|
|
5334
|
+
}),
|
|
5335
|
+
quota.meters.map((meter) => {
|
|
5336
|
+
const remaining = meter.remainingFraction;
|
|
5337
|
+
const percent = remaining === null ? null : Math.round(remaining * 100);
|
|
4002
5338
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4003
5339
|
className: "dsha-meter-wrap",
|
|
4004
5340
|
children: [
|
|
4005
5341
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4006
5342
|
className: "dsha-meter-label",
|
|
4007
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children:
|
|
5343
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: meter.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: percent === null ? meter.limit ?? "—" : `${percent}% left` })]
|
|
4008
5344
|
}),
|
|
4009
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4010
|
-
className:
|
|
4011
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${
|
|
5345
|
+
percent !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5346
|
+
className: "dsha-meter dsha-meter-green",
|
|
5347
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { width: `${percent}%` } })
|
|
4012
5348
|
}),
|
|
4013
5349
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4014
5350
|
className: "dsha-meter-meta",
|
|
4015
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
4016
|
-
|
|
5351
|
+
children: [meter.used !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
5352
|
+
meter.used,
|
|
4017
5353
|
" / ",
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
t.
|
|
4021
|
-
|
|
5354
|
+
meter.limit ?? "—"
|
|
5355
|
+
] }), meter.resetsAt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
5356
|
+
t.quotaReset,
|
|
5357
|
+
": ",
|
|
5358
|
+
formatReset(meter.resetsAt)
|
|
5359
|
+
] })]
|
|
4022
5360
|
})
|
|
4023
5361
|
]
|
|
4024
|
-
},
|
|
4025
|
-
}),
|
|
4026
|
-
quota.extraUsage !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4027
|
-
className: "dsha-meter-wrap",
|
|
4028
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4029
|
-
className: "dsha-meter-label",
|
|
4030
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t.quotaWallet }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: formatMoney(quota.extraUsage.balanceCents, quota.extraUsage.currency) })]
|
|
4031
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4032
|
-
className: "dsha-meter-meta",
|
|
4033
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatMoney(quota.extraUsage.totalCents, quota.extraUsage.currency) }), quota.extraUsage.monthlyChargeLimitEnabled && quota.extraUsage.monthlyChargeLimitCents !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
4034
|
-
t.quotaWalletLimit,
|
|
4035
|
-
": ",
|
|
4036
|
-
formatMoney(quota.extraUsage.monthlyChargeLimitCents, quota.extraUsage.currency)
|
|
4037
|
-
] })]
|
|
4038
|
-
})]
|
|
5362
|
+
}, meter.id);
|
|
4039
5363
|
}),
|
|
4040
|
-
quota.
|
|
5364
|
+
quota.meters.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4041
5365
|
className: "dsha-empty",
|
|
4042
5366
|
children: t.quotaEmpty
|
|
4043
5367
|
}),
|
|
@@ -4074,6 +5398,10 @@ window.__ModuleLoader__.load({
|
|
|
4074
5398
|
{
|
|
4075
5399
|
id: "kimi-code",
|
|
4076
5400
|
label: "Kimi Code"
|
|
5401
|
+
},
|
|
5402
|
+
{
|
|
5403
|
+
id: "workbuddy",
|
|
5404
|
+
label: "WorkBuddy"
|
|
4077
5405
|
}
|
|
4078
5406
|
];
|
|
4079
5407
|
/**
|
|
@@ -4131,7 +5459,8 @@ window.__ModuleLoader__.load({
|
|
|
4131
5459
|
}) : null,
|
|
4132
5460
|
active === "antigravity" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AntigravitySection, { onModelChange }) : null,
|
|
4133
5461
|
active === "command-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CommandCodeSection, { onModelChange }) : null,
|
|
4134
|
-
active === "kimi-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KimiCodeSection, { onModelChange }) : null
|
|
5462
|
+
active === "kimi-code" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KimiCodeSection, { onModelChange }) : null,
|
|
5463
|
+
active === "workbuddy" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkBuddySection, { onModelChange }) : null
|
|
4135
5464
|
]
|
|
4136
5465
|
})
|
|
4137
5466
|
]
|
|
@@ -4142,6 +5471,7 @@ window.__ModuleLoader__.load({
|
|
|
4142
5471
|
const NS = "dsh-chatgpt-subscription";
|
|
4143
5472
|
const dictionaries = {
|
|
4144
5473
|
zh: {
|
|
5474
|
+
...accountPoolZh,
|
|
4145
5475
|
title: "ChatGPT",
|
|
4146
5476
|
hubTitle: "订阅服务",
|
|
4147
5477
|
intro: "使用 ChatGPT 账号登录,在 DSH 中使用订阅可用的模型。",
|
|
@@ -4270,6 +5600,7 @@ window.__ModuleLoader__.load({
|
|
|
4270
5600
|
unknown: "未知"
|
|
4271
5601
|
},
|
|
4272
5602
|
en: {
|
|
5603
|
+
...accountPoolEn,
|
|
4273
5604
|
title: "ChatGPT",
|
|
4274
5605
|
hubTitle: "Subscriptions",
|
|
4275
5606
|
intro: "Sign in with ChatGPT to use models available to your subscription in DSH.",
|
|
@@ -4400,7 +5731,7 @@ window.__ModuleLoader__.load({
|
|
|
4400
5731
|
};
|
|
4401
5732
|
//#endregion
|
|
4402
5733
|
//#region src/client/styles.ts
|
|
4403
|
-
const STYLE_ID$
|
|
5734
|
+
const STYLE_ID$3 = "@eddyskywalker/dsh-chatgpt-subscription/main";
|
|
4404
5735
|
const CSS = `
|
|
4405
5736
|
.dsh-codex-page{box-sizing:border-box;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:20px;max-width:780px;min-width:0;padding:2px 0 30px}
|
|
4406
5737
|
.dsh-codex-page *{box-sizing:border-box}
|
|
@@ -4509,21 +5840,21 @@ window.__ModuleLoader__.load({
|
|
|
4509
5840
|
@media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}}
|
|
4510
5841
|
`;
|
|
4511
5842
|
function installStyles() {
|
|
4512
|
-
if (document.querySelector(`style[data-plugin-css="${STYLE_ID$
|
|
5843
|
+
if (document.querySelector(`style[data-plugin-css="${STYLE_ID$3}"]`) !== null) return () => void 0;
|
|
4513
5844
|
const element = document.createElement("style");
|
|
4514
5845
|
element.dataset.plugin = "@eddyskywalker/dsh-chatgpt-subscription";
|
|
4515
|
-
element.dataset.pluginCss = STYLE_ID$
|
|
5846
|
+
element.dataset.pluginCss = STYLE_ID$3;
|
|
4516
5847
|
element.textContent = CSS;
|
|
4517
5848
|
document.head.appendChild(element);
|
|
4518
5849
|
return () => element.remove();
|
|
4519
5850
|
}
|
|
4520
5851
|
//#endregion
|
|
4521
5852
|
//#region src/client/antigravity/styles.ts
|
|
4522
|
-
const STYLE_ID$
|
|
5853
|
+
const STYLE_ID$2 = "dsh-antigravity-settings-style";
|
|
4523
5854
|
function installAntigravityStyles() {
|
|
4524
5855
|
if (typeof document === "undefined" || document.getElementById("dsh-antigravity-settings-style")) return;
|
|
4525
5856
|
const style = document.createElement("style");
|
|
4526
|
-
style.id = STYLE_ID$
|
|
5857
|
+
style.id = STYLE_ID$2;
|
|
4527
5858
|
style.textContent = `
|
|
4528
5859
|
.dsha-page{box-sizing:border-box;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:20px;max-width:780px;min-width:0;padding:2px 0 30px}
|
|
4529
5860
|
.dsha-page *{box-sizing:border-box}
|
|
@@ -4546,7 +5877,7 @@ window.__ModuleLoader__.load({
|
|
|
4546
5877
|
.dsha-models{display:flex;flex-wrap:wrap;gap:7px;padding-top:8px}
|
|
4547
5878
|
.dsha-models label{cursor:pointer;display:block;position:relative}
|
|
4548
5879
|
.dsha-models input{position:absolute;opacity:0;pointer-events:none}
|
|
4549
|
-
.dsha-models
|
|
5880
|
+
.dsha-models>label>span{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-secondary);display:block;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;padding:5px 8px;transition:all .15s ease}
|
|
4550
5881
|
.dsha-models input:checked+span{background:color-mix(in srgb,var(--dsw-alias-button-info-fill,#397ee8) 14%,var(--dsw-alias-bg-layer-2));border-color:color-mix(in srgb,var(--dsw-alias-button-info-fill,#397ee8) 55%,var(--dsw-alias-border-l2));color:var(--dsw-alias-label-primary);font-weight:600}
|
|
4551
5882
|
.dsha-models input:disabled+span{cursor:default;opacity:.5}
|
|
4552
5883
|
.dsha-pref-row{align-items:center;border-bottom:0.5px solid var(--dsw-alias-border-l2);display:flex;gap:16px;justify-content:space-between;min-height:58px;padding:10px 0}
|
|
@@ -4596,14 +5927,35 @@ window.__ModuleLoader__.load({
|
|
|
4596
5927
|
.dsha-account-details{display:flex;flex-wrap:wrap;gap:14px;font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
4597
5928
|
.dsha-account-actions{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}
|
|
4598
5929
|
.dsha-account-actions .dsha-btn{padding:5px 10px;font-size:12px}
|
|
5930
|
+
`;
|
|
5931
|
+
document.head.append(style);
|
|
5932
|
+
}
|
|
5933
|
+
//#endregion
|
|
5934
|
+
//#region src/client/common/styles.ts
|
|
5935
|
+
const POOL_STYLE_ID = "dsh-provider-pool-style";
|
|
5936
|
+
/**
|
|
5937
|
+
* Styles the shared account-pool card adds on top of the existing provider
|
|
5938
|
+
* stylesheets: the badge variants no single provider tab owned before.
|
|
5939
|
+
*
|
|
5940
|
+
* Additive on purpose — the shared `.dsha-*` block and each provider's own
|
|
5941
|
+
* tweaks keep living in their own modules, in the order the client installs
|
|
5942
|
+
* them, so nothing that already rendered changes appearance.
|
|
5943
|
+
*/
|
|
5944
|
+
function installPoolStyles() {
|
|
5945
|
+
if (typeof document === "undefined" || document.getElementById("dsh-provider-pool-style")) return;
|
|
5946
|
+
const style = document.createElement("style");
|
|
5947
|
+
style.id = POOL_STYLE_ID;
|
|
5948
|
+
style.textContent = `
|
|
5949
|
+
.dsha-badge.danger{background:color-mix(in srgb,var(--dsw-alias-label-danger,#d94b4b) 18%,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-label-danger,#d94b4b);border:0.5px solid color-mix(in srgb,var(--dsw-alias-label-danger,#d94b4b) 40%,transparent)}
|
|
5950
|
+
.dsha-account-card .dsha-btn.danger{color:var(--dsw-alias-label-danger,#d94b4b)}
|
|
4599
5951
|
`;
|
|
4600
5952
|
document.head.append(style);
|
|
4601
5953
|
}
|
|
4602
5954
|
//#endregion
|
|
4603
5955
|
//#region src/client/antigravity/AntigravityComposerQuota.tsx
|
|
4604
|
-
const API$
|
|
4605
|
-
async function fetchApi$
|
|
4606
|
-
const res = await fetch(`${API$
|
|
5956
|
+
const API$3 = "/antigravity/api";
|
|
5957
|
+
async function fetchApi$3(path, options) {
|
|
5958
|
+
const res = await fetch(`${API$3}${path}`, {
|
|
4607
5959
|
...options,
|
|
4608
5960
|
headers: {
|
|
4609
5961
|
"Content-Type": "application/json",
|
|
@@ -4644,7 +5996,7 @@ window.__ModuleLoader__.load({
|
|
|
4644
5996
|
}
|
|
4645
5997
|
}
|
|
4646
5998
|
function AntigravityComposerQuota({ directory, loadModelDirectory }) {
|
|
4647
|
-
const modelState = useStore$
|
|
5999
|
+
const modelState = useStore$3(directory);
|
|
4648
6000
|
const [status, setStatus] = (0, react.useState)(null);
|
|
4649
6001
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
4650
6002
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -4663,7 +6015,7 @@ window.__ModuleLoader__.load({
|
|
|
4663
6015
|
if (!mountedRef.current) return;
|
|
4664
6016
|
setLoading(true);
|
|
4665
6017
|
try {
|
|
4666
|
-
const data = refresh ? await fetchApi$
|
|
6018
|
+
const data = refresh ? await fetchApi$3("/quota", { method: "POST" }) : await fetchApi$3("/status");
|
|
4667
6019
|
if (mountedRef.current) setStatus(data);
|
|
4668
6020
|
} catch {} finally {
|
|
4669
6021
|
if (mountedRef.current) setLoading(false);
|
|
@@ -4701,14 +6053,14 @@ window.__ModuleLoader__.load({
|
|
|
4701
6053
|
})]
|
|
4702
6054
|
});
|
|
4703
6055
|
}
|
|
4704
|
-
function useStore$
|
|
6056
|
+
function useStore$3(store) {
|
|
4705
6057
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
4706
6058
|
}
|
|
4707
6059
|
//#endregion
|
|
4708
6060
|
//#region src/client/command-code/CommandCodeComposerQuota.tsx
|
|
4709
|
-
const API$
|
|
4710
|
-
async function fetchApi$
|
|
4711
|
-
const res = await fetch(`${API$
|
|
6061
|
+
const API$2 = "/command-code/api";
|
|
6062
|
+
async function fetchApi$2(path, options) {
|
|
6063
|
+
const res = await fetch(`${API$2}${path}`, {
|
|
4712
6064
|
...options,
|
|
4713
6065
|
headers: {
|
|
4714
6066
|
"Content-Type": "application/json",
|
|
@@ -4725,7 +6077,7 @@ window.__ModuleLoader__.load({
|
|
|
4725
6077
|
* A bounded usage window is the number a user actually spends down, so it wins
|
|
4726
6078
|
* over a credit balance; the balance shows only when no window is reported.
|
|
4727
6079
|
*/
|
|
4728
|
-
function selectBadgeFacts$
|
|
6080
|
+
function selectBadgeFacts$2(status) {
|
|
4729
6081
|
const quota = status?.quota;
|
|
4730
6082
|
if (quota === null || quota === void 0) return {
|
|
4731
6083
|
text: "—",
|
|
@@ -4767,7 +6119,7 @@ window.__ModuleLoader__.load({
|
|
|
4767
6119
|
};
|
|
4768
6120
|
}
|
|
4769
6121
|
function CommandCodeComposerQuota({ directory, loadModelDirectory }) {
|
|
4770
|
-
const modelState = useStore$
|
|
6122
|
+
const modelState = useStore$2(directory);
|
|
4771
6123
|
const [status, setStatus] = (0, react.useState)(null);
|
|
4772
6124
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
4773
6125
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -4785,7 +6137,7 @@ window.__ModuleLoader__.load({
|
|
|
4785
6137
|
if (!mountedRef.current) return;
|
|
4786
6138
|
setLoading(true);
|
|
4787
6139
|
try {
|
|
4788
|
-
const data = refresh ? await fetchApi$
|
|
6140
|
+
const data = refresh ? await fetchApi$2("/quota", { method: "POST" }) : await fetchApi$2("/status");
|
|
4789
6141
|
if (mountedRef.current) setStatus(data);
|
|
4790
6142
|
} catch {} finally {
|
|
4791
6143
|
if (mountedRef.current) setLoading(false);
|
|
@@ -4801,7 +6153,7 @@ window.__ModuleLoader__.load({
|
|
|
4801
6153
|
window.clearInterval(timer);
|
|
4802
6154
|
};
|
|
4803
6155
|
}, [fetchStatus, isCommandCode]);
|
|
4804
|
-
const facts = (0, react.useMemo)(() => selectBadgeFacts$
|
|
6156
|
+
const facts = (0, react.useMemo)(() => selectBadgeFacts$2(status), [status]);
|
|
4805
6157
|
if (!isCommandCode || !status?.authenticated || facts === null) return null;
|
|
4806
6158
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4807
6159
|
className: "dsha-composer-quota",
|
|
@@ -4818,14 +6170,14 @@ window.__ModuleLoader__.load({
|
|
|
4818
6170
|
})]
|
|
4819
6171
|
});
|
|
4820
6172
|
}
|
|
4821
|
-
function useStore$
|
|
6173
|
+
function useStore$2(store) {
|
|
4822
6174
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
4823
6175
|
}
|
|
4824
6176
|
//#endregion
|
|
4825
6177
|
//#region src/client/kimi-code/KimiCodeComposerQuota.tsx
|
|
4826
|
-
const API = "/kimi-code/api";
|
|
4827
|
-
async function fetchApi(path, options) {
|
|
4828
|
-
const res = await fetch(`${API}${path}`, {
|
|
6178
|
+
const API$1 = "/kimi-code/api";
|
|
6179
|
+
async function fetchApi$1(path, options) {
|
|
6180
|
+
const res = await fetch(`${API$1}${path}`, {
|
|
4829
6181
|
...options,
|
|
4830
6182
|
headers: {
|
|
4831
6183
|
"Content-Type": "application/json",
|
|
@@ -4843,7 +6195,7 @@ window.__ModuleLoader__.load({
|
|
|
4843
6195
|
* blocks work soonest, so it wins over the longer pools; the 7-day allowance
|
|
4844
6196
|
* shows only when no 5-hour window is reported.
|
|
4845
6197
|
*/
|
|
4846
|
-
function selectBadgeFacts(status) {
|
|
6198
|
+
function selectBadgeFacts$1(status) {
|
|
4847
6199
|
const quota = status?.quota;
|
|
4848
6200
|
if (quota === null || quota === void 0) return {
|
|
4849
6201
|
text: "—",
|
|
@@ -4875,7 +6227,7 @@ window.__ModuleLoader__.load({
|
|
|
4875
6227
|
};
|
|
4876
6228
|
}
|
|
4877
6229
|
function KimiCodeComposerQuota({ directory, loadModelDirectory }) {
|
|
4878
|
-
const modelState = useStore(directory);
|
|
6230
|
+
const modelState = useStore$1(directory);
|
|
4879
6231
|
const [status, setStatus] = (0, react.useState)(null);
|
|
4880
6232
|
const [loading, setLoading] = (0, react.useState)(false);
|
|
4881
6233
|
const mountedRef = (0, react.useRef)(false);
|
|
@@ -4893,7 +6245,7 @@ window.__ModuleLoader__.load({
|
|
|
4893
6245
|
if (!mountedRef.current) return;
|
|
4894
6246
|
setLoading(true);
|
|
4895
6247
|
try {
|
|
4896
|
-
const data = refresh ? await fetchApi("/quota", { method: "POST" }) : await fetchApi("/status");
|
|
6248
|
+
const data = refresh ? await fetchApi$1("/quota", { method: "POST" }) : await fetchApi$1("/status");
|
|
4897
6249
|
if (mountedRef.current) setStatus(data);
|
|
4898
6250
|
} catch {} finally {
|
|
4899
6251
|
if (mountedRef.current) setLoading(false);
|
|
@@ -4909,7 +6261,7 @@ window.__ModuleLoader__.load({
|
|
|
4909
6261
|
window.clearInterval(timer);
|
|
4910
6262
|
};
|
|
4911
6263
|
}, [fetchStatus, isKimiCode]);
|
|
4912
|
-
const facts = (0, react.useMemo)(() => selectBadgeFacts(status), [status]);
|
|
6264
|
+
const facts = (0, react.useMemo)(() => selectBadgeFacts$1(status), [status]);
|
|
4913
6265
|
if (!isKimiCode || !status?.authenticated || facts === null) return null;
|
|
4914
6266
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4915
6267
|
className: "dsha-composer-quota",
|
|
@@ -4926,12 +6278,12 @@ window.__ModuleLoader__.load({
|
|
|
4926
6278
|
})]
|
|
4927
6279
|
});
|
|
4928
6280
|
}
|
|
4929
|
-
function useStore(store) {
|
|
6281
|
+
function useStore$1(store) {
|
|
4930
6282
|
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
4931
6283
|
}
|
|
4932
6284
|
//#endregion
|
|
4933
6285
|
//#region src/client/kimi-code/styles.ts
|
|
4934
|
-
const STYLE_ID = "dsh-kimi-code-settings-style";
|
|
6286
|
+
const STYLE_ID$1 = "dsh-kimi-code-settings-style";
|
|
4935
6287
|
/**
|
|
4936
6288
|
* Node the base control styles come from.
|
|
4937
6289
|
*
|
|
@@ -4961,7 +6313,7 @@ window.__ModuleLoader__.load({
|
|
|
4961
6313
|
.dsha-models{display:flex;flex-wrap:wrap;gap:7px;padding-top:8px}
|
|
4962
6314
|
.dsha-models label{cursor:pointer;display:block;position:relative}
|
|
4963
6315
|
.dsha-models input{position:absolute;opacity:0;pointer-events:none}
|
|
4964
|
-
.dsha-models
|
|
6316
|
+
.dsha-models>label>span{background:var(--dsw-alias-bg-layer-2);border:0.5px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-secondary);display:block;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;padding:5px 8px;transition:all .15s ease}
|
|
4965
6317
|
.dsha-models input:checked+span{background:color-mix(in srgb,var(--dsw-alias-button-info-fill,#397ee8) 14%,var(--dsw-alias-bg-layer-2));border-color:color-mix(in srgb,var(--dsw-alias-button-info-fill,#397ee8) 55%,var(--dsw-alias-border-l2));color:var(--dsw-alias-label-primary);font-weight:600}
|
|
4966
6318
|
.dsha-models input:disabled+span{cursor:default;opacity:.5}
|
|
4967
6319
|
.dsha-pref-row{align-items:center;border-bottom:0.5px solid var(--dsw-alias-border-l2);display:flex;gap:16px;justify-content:space-between;min-height:58px;padding:10px 0}
|
|
@@ -5021,11 +6373,148 @@ window.__ModuleLoader__.load({
|
|
|
5021
6373
|
function installKimiCodeStyles() {
|
|
5022
6374
|
if (typeof document === "undefined" || document.getElementById("dsh-kimi-code-settings-style")) return;
|
|
5023
6375
|
const style = document.createElement("style");
|
|
5024
|
-
style.id = STYLE_ID;
|
|
6376
|
+
style.id = STYLE_ID$1;
|
|
5025
6377
|
style.textContent = BASE;
|
|
5026
6378
|
document.head.appendChild(style);
|
|
5027
6379
|
}
|
|
5028
6380
|
//#endregion
|
|
6381
|
+
//#region src/client/workbuddy/WorkBuddyComposerQuota.tsx
|
|
6382
|
+
const API = "/workbuddy/api";
|
|
6383
|
+
async function fetchApi(path, options) {
|
|
6384
|
+
const res = await fetch(`${API}${path}`, {
|
|
6385
|
+
...options,
|
|
6386
|
+
headers: {
|
|
6387
|
+
"Content-Type": "application/json",
|
|
6388
|
+
...options?.headers
|
|
6389
|
+
}
|
|
6390
|
+
});
|
|
6391
|
+
const json = await res.json();
|
|
6392
|
+
if (!res.ok || !json.ok) throw new Error(json.error || `HTTP ${res.status}`);
|
|
6393
|
+
return json.value;
|
|
6394
|
+
}
|
|
6395
|
+
/**
|
|
6396
|
+
* Pick the most meaningful number for the badge.
|
|
6397
|
+
*
|
|
6398
|
+
* A bounded allowance is what a user spends down, so it wins over a bare credit
|
|
6399
|
+
* balance; the balance shows only when no percentage is reported. The billing
|
|
6400
|
+
* payload reports both a cycle meter and a package meter, and the cycle meter
|
|
6401
|
+
* is the one that actually resets, so it is preferred when both exist.
|
|
6402
|
+
*/
|
|
6403
|
+
function selectBadgeFacts(status) {
|
|
6404
|
+
const quota = status?.quota;
|
|
6405
|
+
if (quota === null || quota === void 0) return {
|
|
6406
|
+
text: "—",
|
|
6407
|
+
tooltip: "WorkBuddy quota unavailable — click to refresh",
|
|
6408
|
+
level: "normal"
|
|
6409
|
+
};
|
|
6410
|
+
const meter = (quota.meters ?? []).find((candidate) => candidate.id === "cycle" && candidate.remainingFraction !== null) ?? (quota.meters ?? []).find((candidate) => candidate.remainingFraction !== null);
|
|
6411
|
+
if (meter !== void 0 && meter.remainingFraction !== null) {
|
|
6412
|
+
const remaining = Math.round(meter.remainingFraction * 100);
|
|
6413
|
+
return {
|
|
6414
|
+
text: `${remaining}%`,
|
|
6415
|
+
tooltip: `[WorkBuddy] ${meter.label}: ${remaining}% left`,
|
|
6416
|
+
level: remaining <= 5 ? "danger" : remaining <= 20 ? "warning" : "normal"
|
|
6417
|
+
};
|
|
6418
|
+
}
|
|
6419
|
+
if (quota.remainingCredits !== null) return {
|
|
6420
|
+
text: String(quota.remainingCredits),
|
|
6421
|
+
tooltip: `[WorkBuddy] Remaining credits: ${quota.remainingCredits}`,
|
|
6422
|
+
level: "normal"
|
|
6423
|
+
};
|
|
6424
|
+
return {
|
|
6425
|
+
text: "—",
|
|
6426
|
+
tooltip: "WorkBuddy quota unavailable — click to refresh",
|
|
6427
|
+
level: "normal"
|
|
6428
|
+
};
|
|
6429
|
+
}
|
|
6430
|
+
function WorkBuddyComposerQuota({ directory, loadModelDirectory }) {
|
|
6431
|
+
const modelState = useStore(directory);
|
|
6432
|
+
const [status, setStatus] = (0, react.useState)(null);
|
|
6433
|
+
const [loading, setLoading] = (0, react.useState)(false);
|
|
6434
|
+
const mountedRef = (0, react.useRef)(false);
|
|
6435
|
+
const isWorkBuddy = modelState.current?.provider === "workbuddy-subscription";
|
|
6436
|
+
(0, react.useEffect)(() => {
|
|
6437
|
+
loadModelDirectory();
|
|
6438
|
+
}, [loadModelDirectory]);
|
|
6439
|
+
(0, react.useEffect)(() => {
|
|
6440
|
+
mountedRef.current = true;
|
|
6441
|
+
return () => {
|
|
6442
|
+
mountedRef.current = false;
|
|
6443
|
+
};
|
|
6444
|
+
}, []);
|
|
6445
|
+
const fetchStatus = (0, react.useCallback)(async (refresh = false) => {
|
|
6446
|
+
if (!mountedRef.current) return;
|
|
6447
|
+
setLoading(true);
|
|
6448
|
+
try {
|
|
6449
|
+
const data = refresh ? await fetchApi("/quota", { method: "POST" }) : await fetchApi("/status");
|
|
6450
|
+
if (mountedRef.current) setStatus(data);
|
|
6451
|
+
} catch {} finally {
|
|
6452
|
+
if (mountedRef.current) setLoading(false);
|
|
6453
|
+
}
|
|
6454
|
+
}, []);
|
|
6455
|
+
(0, react.useEffect)(() => {
|
|
6456
|
+
if (!isWorkBuddy) return;
|
|
6457
|
+
fetchStatus(false);
|
|
6458
|
+
const timer = window.setInterval(() => {
|
|
6459
|
+
if (document.visibilityState === "visible") fetchStatus(false);
|
|
6460
|
+
}, 6e4);
|
|
6461
|
+
return () => {
|
|
6462
|
+
window.clearInterval(timer);
|
|
6463
|
+
};
|
|
6464
|
+
}, [fetchStatus, isWorkBuddy]);
|
|
6465
|
+
const facts = (0, react.useMemo)(() => selectBadgeFacts(status), [status]);
|
|
6466
|
+
if (!isWorkBuddy || !status?.authenticated || facts === null) return null;
|
|
6467
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6468
|
+
className: "dsha-composer-quota",
|
|
6469
|
+
"data-level": facts.level,
|
|
6470
|
+
title: facts.tooltip,
|
|
6471
|
+
"aria-label": facts.tooltip,
|
|
6472
|
+
onClick: () => void fetchStatus(true),
|
|
6473
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6474
|
+
className: "dsha-composer-quota-label",
|
|
6475
|
+
children: "额度"
|
|
6476
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
6477
|
+
className: "dsha-composer-quota-val",
|
|
6478
|
+
children: loading ? "…" : facts.text
|
|
6479
|
+
})]
|
|
6480
|
+
});
|
|
6481
|
+
}
|
|
6482
|
+
function useStore(store) {
|
|
6483
|
+
return (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getSnapshot(), () => store.getSnapshot());
|
|
6484
|
+
}
|
|
6485
|
+
//#endregion
|
|
6486
|
+
//#region src/client/workbuddy/styles.ts
|
|
6487
|
+
const STYLE_ID = "dsh-workbuddy-settings-style";
|
|
6488
|
+
/**
|
|
6489
|
+
* WorkBuddy-only additions to the shared settings design system.
|
|
6490
|
+
*
|
|
6491
|
+
* The base control styles (`.dsha-page`, `.dsha-group`, `.dsha-models`, …) come
|
|
6492
|
+
* from the stylesheet the sibling routes install, so this file declares only
|
|
6493
|
+
* what is unique to this card: the per-model capability line and the
|
|
6494
|
+
* "unavailable in this region" treatment.
|
|
6495
|
+
*/
|
|
6496
|
+
function installWorkBuddyStyles() {
|
|
6497
|
+
if (typeof document === "undefined" || document.getElementById("dsh-workbuddy-settings-style")) return;
|
|
6498
|
+
const style = document.createElement("style");
|
|
6499
|
+
style.id = STYLE_ID;
|
|
6500
|
+
style.textContent = `
|
|
6501
|
+
.dshwb-model{display:flex;flex-direction:column;gap:2px;min-width:0}
|
|
6502
|
+
.dshwb-model-meta{color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:400;line-height:1.3;white-space:nowrap}
|
|
6503
|
+
.dsha-models input:checked+span .dshwb-model-meta{color:var(--dsw-alias-label-secondary)}
|
|
6504
|
+
.dshwb-region{display:inline-flex;align-items:center;gap:4px}
|
|
6505
|
+
.dshwb-muted-note{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;margin:8px 0 0}
|
|
6506
|
+
.dshwb-mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px}
|
|
6507
|
+
.dsha-account-region{margin-top:14px}
|
|
6508
|
+
.dsha-account-region h4{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:650;margin:0 0 8px}
|
|
6509
|
+
.dsha-account-add-actions{display:flex;flex-wrap:wrap;gap:8px}
|
|
6510
|
+
.dsha-account-card.hidden{opacity:.68}
|
|
6511
|
+
.dshwb-account-select{appearance:none;background:transparent;border:0;color:inherit;cursor:pointer;font:inherit;padding:0;text-align:left;width:100%}
|
|
6512
|
+
.dshwb-account-select:disabled{cursor:default}
|
|
6513
|
+
.dshwb-account-select:hover:not(:disabled) .dsha-account-title{color:var(--dsw-alias-label-link,#397ee8)}
|
|
6514
|
+
`;
|
|
6515
|
+
document.head.append(style);
|
|
6516
|
+
}
|
|
6517
|
+
//#endregion
|
|
5029
6518
|
//#region src/client/mermaid/sanitize.ts
|
|
5030
6519
|
const STRIP_ELEMENTS = /* @__PURE__ */ new Set([
|
|
5031
6520
|
"foreignobject",
|
|
@@ -5365,17 +6854,26 @@ window.__ModuleLoader__.load({
|
|
|
5365
6854
|
function apply(ctx) {
|
|
5366
6855
|
ctx.effect(() => ctx.locale.register(NS, dictionaries), "dsh-chatgpt-subscription: dictionaries");
|
|
5367
6856
|
ctx.effect(() => installStyles(), "dsh-chatgpt-subscription: styles");
|
|
5368
|
-
ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$
|
|
6857
|
+
ctx.effect(() => ctx.locale.register(NS_ANTIGRAVITY, dictionaries$4), "dsh-antigravity: dictionaries");
|
|
5369
6858
|
ctx.effect(() => {
|
|
5370
6859
|
installAntigravityStyles();
|
|
5371
6860
|
return () => {};
|
|
5372
6861
|
}, "dsh-antigravity: styles");
|
|
5373
|
-
ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$
|
|
5374
|
-
ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$
|
|
6862
|
+
ctx.effect(() => ctx.locale.register(NS_COMMAND_CODE, dictionaries$3), "dsh-command-code: dictionaries");
|
|
6863
|
+
ctx.effect(() => ctx.locale.register(NS_KIMI_CODE, dictionaries$2), "dsh-kimi-code: dictionaries");
|
|
5375
6864
|
ctx.effect(() => {
|
|
5376
6865
|
installKimiCodeStyles();
|
|
5377
6866
|
return () => {};
|
|
5378
6867
|
}, "dsh-kimi-code: styles");
|
|
6868
|
+
ctx.effect(() => ctx.locale.register(NS_WORKBUDDY, dictionaries$1), "dsh-workbuddy: dictionaries");
|
|
6869
|
+
ctx.effect(() => {
|
|
6870
|
+
installWorkBuddyStyles();
|
|
6871
|
+
return () => {};
|
|
6872
|
+
}, "dsh-workbuddy: styles");
|
|
6873
|
+
ctx.effect(() => {
|
|
6874
|
+
installPoolStyles();
|
|
6875
|
+
return () => {};
|
|
6876
|
+
}, "dsh-chatgpt-subscription: pool styles");
|
|
5379
6877
|
ctx.effect(() => setupMermaidObserver(), "dsh-mermaid: observer");
|
|
5380
6878
|
const t = ctx.locale.bind(NS);
|
|
5381
6879
|
const handleModelDirectoryReload = () => {
|
|
@@ -5459,6 +6957,21 @@ window.__ModuleLoader__.load({
|
|
|
5459
6957
|
};
|
|
5460
6958
|
}
|
|
5461
6959
|
}, KimiCodeComposerQuota));
|
|
6960
|
+
ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
|
|
6961
|
+
name: "conversation.input.right",
|
|
6962
|
+
id: "workbuddy-quota",
|
|
6963
|
+
order: 39,
|
|
6964
|
+
locale: NS_WORKBUDDY,
|
|
6965
|
+
inject: (sessionId) => {
|
|
6966
|
+
const directory = ctx.modelDirectories.directoryFor(sessionId);
|
|
6967
|
+
return {
|
|
6968
|
+
directory: directory.store,
|
|
6969
|
+
loadModelDirectory: () => {
|
|
6970
|
+
directory.load().catch(() => void 0);
|
|
6971
|
+
}
|
|
6972
|
+
};
|
|
6973
|
+
}
|
|
6974
|
+
}, WorkBuddyComposerQuota));
|
|
5462
6975
|
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
5463
6976
|
name: "tool.call.toolview",
|
|
5464
6977
|
key: CODEX_IMAGE_TOOL_NAME,
|