dsh-multi-router 0.6.11 → 1.0.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.
Files changed (56) hide show
  1. package/README.md +2 -427
  2. package/package.json +5 -81
  3. package/CHANGELOG.md +0 -237
  4. package/LICENSE +0 -21
  5. package/THIRD_PARTY_NOTICES.md +0 -171
  6. package/cordis.patch.yml +0 -3
  7. package/lib/accounts.js +0 -19
  8. package/lib/accounts.js.map +0 -7
  9. package/lib/api-service.js +0 -11
  10. package/lib/api-service.js.map +0 -7
  11. package/lib/chunk-2UM45OXY.js +0 -181
  12. package/lib/chunk-2UM45OXY.js.map +0 -7
  13. package/lib/chunk-4L2CBGXN.js +0 -674
  14. package/lib/chunk-4L2CBGXN.js.map +0 -7
  15. package/lib/chunk-4V52V5GO.js +0 -105
  16. package/lib/chunk-4V52V5GO.js.map +0 -7
  17. package/lib/chunk-DNQPZMPF.js +0 -33
  18. package/lib/chunk-DNQPZMPF.js.map +0 -7
  19. package/lib/chunk-FLL3DUVP.js +0 -2017
  20. package/lib/chunk-FLL3DUVP.js.map +0 -7
  21. package/lib/chunk-GEBZMIMA.js +0 -287
  22. package/lib/chunk-GEBZMIMA.js.map +0 -7
  23. package/lib/chunk-KWXLQJS5.js +0 -1102
  24. package/lib/chunk-KWXLQJS5.js.map +0 -7
  25. package/lib/chunk-NZF36O5I.js +0 -5421
  26. package/lib/chunk-NZF36O5I.js.map +0 -7
  27. package/lib/chunk-S5KMFAQM.js +0 -50
  28. package/lib/chunk-S5KMFAQM.js.map +0 -7
  29. package/lib/chunk-TM5XDMGY.js +0 -332
  30. package/lib/chunk-TM5XDMGY.js.map +0 -7
  31. package/lib/chunk-WDIT4E2W.js +0 -120
  32. package/lib/chunk-WDIT4E2W.js.map +0 -7
  33. package/lib/chunk-YCAO7GCT.js +0 -2059
  34. package/lib/chunk-YCAO7GCT.js.map +0 -7
  35. package/lib/cli.js +0 -103
  36. package/lib/cli.js.map +0 -7
  37. package/lib/client.js +0 -2793
  38. package/lib/client.js.map +0 -7
  39. package/lib/clients.js +0 -30
  40. package/lib/clients.js.map +0 -7
  41. package/lib/host-v0.6.11.js +0 -414
  42. package/lib/host.js +0 -414
  43. package/lib/index.js +0 -414
  44. package/lib/index.js.map +0 -7
  45. package/lib/manager.js +0 -27
  46. package/lib/manager.js.map +0 -7
  47. package/lib/region-DO3KAV7V.js +0 -15
  48. package/lib/region-DO3KAV7V.js.map +0 -7
  49. package/lib/router.js +0 -14
  50. package/lib/router.js.map +0 -7
  51. package/lib/shim.js +0 -10
  52. package/lib/shim.js.map +0 -7
  53. package/lib/upstream-VP6J7LU2.js +0 -25
  54. package/lib/upstream-VP6J7LU2.js.map +0 -7
  55. package/router.example.json +0 -289
  56. package/upstream-lock.json +0 -17
package/lib/client.js DELETED
@@ -1,2793 +0,0 @@
1
- window.__ModuleLoader__.load({ id: "dsh-multi-router", factory: (require) => { var module = { exports: {} };
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name2 in all)
8
- __defProp(target, name2, { get: all[name2], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/client.jsx
21
- var client_exports = {};
22
- __export(client_exports, {
23
- AccountPool: () => AccountPool,
24
- ApiServicePanel: () => ApiServicePanel,
25
- CheckinPanel: () => CheckinPanel,
26
- ContextSelect: () => ContextSelect,
27
- InitialSetup: () => InitialSetup,
28
- ModelSettings: () => ModelSettings,
29
- ModelsPanel: () => ModelsPanel,
30
- PluginUpdatesPanel: () => PluginUpdatesPanel,
31
- RestartGuidance: () => RestartGuidance,
32
- RouteReasoningSelect: () => RouteReasoningSelect,
33
- RouterPage: () => RouterPage,
34
- RoutesTable: () => RoutesTable,
35
- SidebarUsage: () => SidebarUsage,
36
- SidebarUsageCard: () => SidebarUsageCard,
37
- UpdateReminder: () => UpdateReminder,
38
- UsageDetails: () => UsageDetails,
39
- apply: () => apply,
40
- backendNeedsRestart: () => backendNeedsRestart,
41
- duration: () => duration,
42
- inject: () => inject,
43
- name: () => name,
44
- performanceSummary: () => performanceSummary,
45
- readManagementResponse: () => readManagementResponse,
46
- requestPluginReload: () => requestPluginReload,
47
- usageDateBounds: () => usageDateBounds
48
- });
49
- module.exports = __toCommonJS(client_exports);
50
- var import_react = require("react");
51
-
52
- // package.json
53
- var version = "0.6.11";
54
-
55
- // src/client.jsx
56
- var import_jsx_runtime = require("react/jsx-runtime");
57
- var name = "dsh-multi-router-client";
58
- var inject = ["slots"];
59
- var ENDPOINT = "/.well-known/dsh-multi-router";
60
- var reloadFromHost;
61
- async function requestPluginReload(remote) {
62
- if (!remote?.pluginManager?.setBundleEnabled) throw Error("\u5F53\u524D DSH \u672A\u63D0\u4F9B\u91CD\u65B0\u52A0\u8F7D\u63A5\u53E3\uFF0C\u8BF7\u5347\u7EA7 DSH \u6216\u5728\u63D2\u4EF6\u9875\u5173\u95ED\u540E\u91CD\u65B0\u542F\u7528\u672C\u63D2\u4EF6\u3002");
63
- const answer = await remote.pluginManager.setBundleEnabled("dsh-multi-router", true);
64
- const result = answer?.ok === true ? answer.value : answer;
65
- if (answer?.ok === false || result?.application !== "applied") throw Error("DSH \u672A\u80FD\u5373\u65F6\u91CD\u8F7D\uFF0C\u8BF7\u68C0\u67E5\u7EC4\u4EF6\u9519\u8BEF\uFF1B\u4E0D\u652F\u6301\u70ED\u52A0\u8F7D\u7684\u65E7\u7248 DSH \u4ECD\u9700\u91CD\u542F\u3002");
66
- }
67
- var backendNeedsRestart = (data) => !!data && data.pluginVersion !== version;
68
- function RestartGuidance({ data, retry, reload, busy }) {
69
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", role: "alert", children: [
70
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u63D2\u4EF6\u6B63\u5728\u8FDE\u63A5\u6216\u540C\u6B65\u7248\u672C" }),
71
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: data ? `\u9762\u677F v${version}\uFF0C\u8FD0\u884C\u4E2D\u7684\u540E\u53F0 v${data.pluginVersion || "\u65E7\u7248"}\u3002\u6B63\u5728\u7B49\u5F85 DSH \u540C\u6B65\u65B0\u7248\u672C\u3002` : "\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u63D2\u4EF6\u540E\u53F0\u3002\u5B89\u88C5\u6216\u66F4\u65B0\u540E\u4F1A\u81EA\u52A8\u91CD\u8BD5\uFF0C\u4E5F\u53EF\u4EE5\u53EA\u91CD\u65B0\u52A0\u8F7D\u672C\u63D2\u4EF6\u3002" }),
72
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
73
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: reload, children: "\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6" }),
74
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: retry, children: "\u91CD\u65B0\u8FDE\u63A5" })
75
- ] }),
76
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [
77
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u4ECD\u65E0\u6CD5\u8FDE\u63A5\uFF1F" }),
78
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5148\u68C0\u67E5\u4E0B\u65B9\u7EC4\u4EF6\u7684\u542F\u7528\u9519\u8BEF\u3002\u65E7\u7248 DSH \u82E5\u4E0D\u652F\u6301\u8FD0\u884C\u4E2D\u91CD\u8F7D\uFF0C\u53EF\u5347\u7EA7 DSH\uFF0C\u6216\u901A\u8FC7\u300C\u9000\u51FA DeepSeek Harness\u300D\u5B8C\u5168\u9000\u51FA\u540E\u91CD\u65B0\u6253\u5F00\u3002\u5173\u95ED\u7A97\u53E3\u4E0D\u7B49\u4E8E\u9000\u51FA\uFF0C\u8D26\u53F7\u3001\u8DEF\u7531\u4E0E\u7528\u91CF\u4F1A\u4FDD\u7559\u3002" })
79
- ] })
80
- ] });
81
- }
82
- async function readManagementResponse(res) {
83
- let next;
84
- try {
85
- next = JSON.parse(await res.text());
86
- } catch {
87
- throw Error(`\u63D2\u4EF6\u540E\u53F0\u672A\u5C31\u7EEA\uFF08HTTP ${res.status}\uFF09\u3002\u6B63\u5728\u91CD\u65B0\u8FDE\u63A5\uFF1B\u82E5\u6301\u7EED\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6\u5E76\u68C0\u67E5\u7EC4\u4EF6\u9519\u8BEF\u3002`);
88
- }
89
- if (!next || typeof next !== "object" || Array.isArray(next)) throw Error("\u63D2\u4EF6\u540E\u53F0\u8FD4\u56DE\u4E86\u65E0\u6548\u6570\u636E\uFF0C\u8BF7\u5237\u65B0\u9762\u677F\u6216\u91CD\u542F DSH\u3002");
90
- if (!res.ok) throw Error(next.error || `\u64CD\u4F5C\u5931\u8D25\uFF08HTTP ${res.status}\uFF09`);
91
- return next;
92
- }
93
- var fmt = (n) => typeof n === "number" ? new Intl.NumberFormat("zh-CN", { maximumFractionDigits: 2 }).format(n) : "\u2014";
94
- var when = (n) => n ? new Date(n).toLocaleString("zh-CN", { hour12: false }) : "\u5C1A\u672A\u83B7\u53D6";
95
- var strategies = { failover: "\u6545\u969C\u5207\u6362", weighted: "\u6309\u6743\u91CD\u5206\u914D", tokens: "\u6309 Token \u989D\u5EA6\u8F6E\u6362", credits: "\u6309\u79EF\u5206\u6D88\u8017\u8F6E\u6362" };
96
- var loginNames = { valid: "\u767B\u5F55\u6709\u6548", configured: "\u5DF2\u4FDD\u5B58 PAT", "refresh-needed": "\u7B49\u5F85\u5237\u65B0", expired: "\u767B\u5F55\u5DF2\u8FC7\u671F", missing: "\u672A\u83B7\u53D6\u767B\u5F55\u4FE1\u606F" };
97
- var effortNames = { off: "\u5173\u95ED\u601D\u8003 \xB7 Off", minimal: "\u6700\u4F4E \xB7 Minimal", low: "\u4F4E \xB7 Low", medium: "\u4E2D \xB7 Medium", high: "\u9AD8 \xB7 High", xhigh: "\u8D85\u9AD8 \xB7 XHigh", max: "\u6700\u9AD8 \xB7 Max" };
98
- function downloadJson(exported) {
99
- const url = URL.createObjectURL(new Blob([JSON.stringify(exported.document, null, 2)], { type: "application/json" }));
100
- const a = document.createElement("a");
101
- a.href = url;
102
- a.download = exported.filename;
103
- document.body.append(a);
104
- a.click();
105
- a.remove();
106
- setTimeout(() => URL.revokeObjectURL(url), 1e4);
107
- }
108
- var styles = `
109
- .mr{--mr-accent:var(--dsw-alias-state-active-primary,#3a71db);--mr-border:var(--dsw-alias-border-l2,#444);--mr-bg:var(--dsw-alias-bg-layer-1,#202020);--mr-card:var(--dsw-alias-bg-module-platform,#282828);--mr-text:var(--dsw-alias-label-primary,#f4f4f4);--mr-muted:var(--dsw-alias-label-secondary,#b0b0b0);color:var(--mr-text);font:inherit;font-size:14px;line-height:1.6;max-width:1120px}
110
- .mr *{box-sizing:border-box}.mr h2,.mr h3,.mr p{margin:0}.mr h2{font-size:22px}.mr h3{font-size:16px}.mr small,.mr .muted,.mr .notice{color:var(--mr-muted)}.mr .notice{font-size:13px}.mr .mono{font:12px ui-monospace,monospace;overflow-wrap:anywhere}
111
- .mr .bar,.mr .row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.mr .bar{justify-content:space-between}.mr .stack{display:flex;flex-direction:column;gap:16px}.mr .grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.mr .metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.mr .providers{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.mr .full{grid-column:1/-1}
112
- .mr .box{border:1px solid var(--mr-border);border-radius:12px;padding:20px;background:var(--mr-card)}.mr .metric strong{font-size:26px;line-height:1.3;display:block;margin:8px 0}.mr .metric small{font-size:12px}.mr .item{padding:16px 0;border-top:1px solid var(--mr-border)}.mr .item:first-child{border-top:0}.mr .item:last-child{padding-bottom:0}.mr .badge{border:1px solid var(--mr-border);border-radius:6px;padding:3px 8px;font-size:12px;white-space:nowrap}.mr .empty{padding:24px 0;text-align:center;color:var(--mr-muted)}
113
- .mr nav{display:flex;flex-wrap:wrap;gap:8px;border-bottom:1px solid var(--mr-border);padding:18px 0;margin-bottom:20px}.mr button,.mr input,.mr select,.mr textarea,.mr .link{font:inherit;color:inherit;border:1px solid var(--mr-border);border-radius:8px;background:var(--mr-bg);min-height:44px;padding:9px 12px}.mr button,.mr .link{cursor:pointer;transition:background .15s}.mr button:hover,.mr .link:hover{background:var(--mr-card)}.mr button:disabled{opacity:.45;cursor:default}.mr button.primary,.mr button[aria-pressed=true]{background:var(--mr-accent);color:#fff;border-color:transparent}.mr button.quiet{border-color:transparent;background:transparent}.mr :is(button,input,select,textarea,a):focus-visible{outline:2px solid var(--mr-accent);outline-offset:3px}.mr input:not([type=checkbox]),.mr select,.mr textarea{width:100%;min-width:0}.mr input[type=checkbox]{width:18px;height:18px;min-height:0;accent-color:var(--mr-accent)}.mr label{display:flex;flex-direction:column;gap:6px;font-size:13px}.mr label.check{flex-direction:row;align-items:center;gap:8px;min-height:44px}.mr .filter{min-width:170px;max-width:240px}.mr .feedback{padding:12px 16px;border-radius:8px;border:1px solid var(--mr-border)}.mr .error{color:var(--dsw-alias-state-error-primary,#ef9393)}.mr .good{color:var(--dsw-alias-state-success-primary,#77ca9d)}.mr .route-path{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.mr .route-path span{padding:4px 9px;border:1px solid var(--mr-border);border-radius:6px}.mr details{border-top:1px solid var(--mr-border);padding-top:14px}.mr summary{cursor:pointer;color:var(--mr-muted)}.mr progress{width:100%;height:7px;accent-color:var(--mr-accent)}.mr .trend{height:100px;display:flex;align-items:flex-end;gap:8px;margin:16px 0}.mr .trend>div{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%;min-width:0}.mr .trend i{display:block;width:100%;min-height:3px;border-radius:4px 4px 0 0;background:var(--mr-accent)}.mr .trend small{font-size:11px;white-space:nowrap}.mr .table{width:100%;border-collapse:collapse;font-size:13px}.mr th,.mr td{text-align:left;border-bottom:1px solid var(--mr-border);padding:10px 8px}.mr th{font-weight:500;color:var(--mr-muted)}.mr .scroll{overflow:auto}.mr .steps{padding:14px 16px;border-left:3px solid var(--mr-accent);background:var(--mr-bg);border-radius:8px}.mr .link{text-decoration:none;display:inline-flex;align-items:center}
114
- .mr dialog{color:var(--mr-text);background:var(--mr-bg);border:1px solid var(--mr-border);border-radius:16px;width:min(900px,calc(100vw - 32px));max-height:calc(100vh - 40px);padding:0;box-shadow:0 24px 80px #0008}.mr dialog::backdrop{background:#000a}.mr .modal-head,.mr .modal-foot{padding:18px 24px;background:var(--mr-bg);position:sticky;z-index:1}.mr .modal-head{top:0;border-bottom:1px solid var(--mr-border)}.mr .modal-foot{bottom:0;border-top:1px solid var(--mr-border)}.mr .modal-body{padding:24px}.mr .target-head strong{font-size:14px}.mr .subtle{background:var(--mr-bg)}
115
- @media(max-width:850px){.mr .providers{grid-template-columns:1fr}.mr .metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:600px){.mr .grid{grid-template-columns:1fr}.mr .box{padding:16px}.mr nav{flex-wrap:wrap}.mr .modal-body,.mr .modal-head,.mr .modal-foot{padding:16px}.mr .metrics{gap:8px}.mr .metric strong{font-size:22px}}
116
- .mr{--mr-soft:color-mix(in srgb,var(--mr-text) 3%,var(--mr-card));--mr-selected:color-mix(in srgb,var(--mr-accent) 7%,var(--mr-card));max-width:1280px;min-width:0;line-height:1.55}
117
- .mr h2{font-size:24px;letter-spacing:-.5px;font-weight:650}.mr h3{font-weight:600}.mr .stack{gap:20px}.mr .row{gap:8px}.mr .box{border-radius:14px;background:var(--mr-card)}.mr .box.stack{gap:16px}
118
- .mr nav{gap:4px;padding:16px 0 0;margin-bottom:24px}.mr nav button{border:0;border-radius:0;background:transparent;padding:12px 14px;border-bottom:2px solid transparent;color:var(--mr-muted)}.mr nav button[aria-pressed=true]{background:transparent;color:var(--mr-text);border-bottom-color:var(--mr-text);font-weight:600}.mr nav button:hover{background:var(--mr-soft)}
119
- .mr button.primary{background:var(--mr-text);color:var(--mr-card);border-color:var(--mr-text)}.mr button.primary:hover{opacity:.85}.mr button:active:not(:disabled){filter:brightness(.9)}.mr button.quiet{color:var(--mr-muted)}.mr .badge{border-radius:100px;background:var(--mr-soft);padding:4px 10px}.mr .metric{background:var(--mr-soft)}.mr .metric strong{font-size:28px;font-variant-numeric:tabular-nums;letter-spacing:-.5px;margin:10px 0 4px}.mr .metrics{gap:16px}
120
- .mr .status{display:inline-flex;align-items:center;gap:7px;font-size:13px;white-space:nowrap}.mr .status i{width:8px;height:8px;border-radius:50%;background:var(--mr-muted);display:inline-block;flex-shrink:0}.mr .status i.good{background:var(--dsw-alias-state-success-primary,#38a16a)}.mr .status i.warn{background:var(--dsw-alias-state-warning-primary,#c48b28)}.mr .warn{color:var(--dsw-alias-state-warning-primary,#c48b28)}
121
- .mr .table-shell{padding:0;overflow:hidden}.mr .scroll>.table{min-width:760px}.mr .table{font-size:14px}.mr .table th{background:var(--mr-soft);font-size:12px;letter-spacing:.02em;font-weight:500;white-space:nowrap}.mr .table th,.mr .table td{padding:16px 20px;vertical-align:middle}.mr .table td:last-child{white-space:nowrap}.mr .table tbody tr:last-child td{border-bottom:0}.mr .table td small{display:block;font-size:12px;margin-top:3px}.mr .table td>strong{font-weight:600}.mr .table tr.selected{background:var(--mr-selected)}.mr .table tbody tr:hover{background:var(--mr-soft)}.mr .table .account-name{max-width:230px;overflow-wrap:anywhere}.mr .table .amount{font-size:20px;line-height:1.35;font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap}.mr .table .cell-actions{white-space:nowrap;text-align:right}.mr .table .account-check{min-width:44px;min-height:44px;justify-content:center;flex-shrink:0}.mr .table .account-cell{display:flex;gap:10px;align-items:center}.mr .table .account-cell .check{margin-left:-12px}.mr .table .account-cell input{accent-color:var(--mr-text)}.mr .table .row{flex-wrap:nowrap}.mr .section-title{margin-bottom:4px}.mr .toolbar{align-items:flex-end;gap:16px}.mr .search{max-width:280px;flex:1;min-width:160px}.mr .table-footer{padding:14px 20px;background:var(--mr-soft)}.mr .hint{font-size:13px;color:var(--mr-muted)}.mr details.help{border:0;padding:0}.mr details.help>div{padding:12px 0;max-width:76ch}.mr .plan-form{align-items:flex-end;padding:16px 0 0;border-top:1px solid var(--mr-border)}.mr .plan-form .filter{min-width:180px}.mr .steps{border:1px solid var(--mr-border);border-radius:10px;background:var(--mr-soft);padding:14px 16px}.mr .route-path span{background:var(--mr-soft);border-color:transparent;font-size:12px}.mr .route-card details{padding-top:10px}.mr .feedback{margin-bottom:16px}.mr .box .feedback{margin-bottom:0}.mr .scroll{max-width:100%}.mr .scroll:focus-visible{outline:2px solid var(--mr-accent);outline-offset:-3px}
122
- @media(max-width:850px){.mr .metrics{gap:10px}.mr nav{gap:0}.mr nav button{padding:12px 10px}}@media(max-width:600px){.mr h2{font-size:22px}.mr nav{display:grid;grid-template-columns:repeat(4,minmax(0,1fr))}.mr nav button{padding:10px 4px;font-size:12px;white-space:nowrap}.mr .toolbar>.row{width:100%}.mr .toolbar .search{max-width:none}.mr .metric strong{font-size:24px}.mr .table th,.mr .table td{padding:14px 16px}.mr .filter{max-width:none}.mr .plan-form label{flex:1}.mr .box.table-shell{padding:0}}
123
-
124
-
125
- .mr .metrics{gap:0;border:1px solid var(--mr-border);border-radius:12px;overflow:hidden;background:var(--mr-card)}
126
- .mr .metrics .metric{border:0;border-radius:0;background:transparent;border-right:1px solid var(--mr-border);padding:16px 20px}.mr .metrics .metric:last-child{border-right:0}.mr .metric strong{font-size:25px;margin:6px 0}.mr .performance{gap:10px}.mr .performance .metrics{background:var(--mr-soft);border-color:transparent}.mr .performance .metric strong{font-size:21px}.mr .performance .metric{padding:12px 20px}.mr .performance h3{font-size:14px}.mr .refresh-control{font-size:12px;color:var(--mr-muted)}
127
- .mr .section-pad{padding:16px 20px}.mr .table-shell>.section-pad+.section-pad{padding-top:0}.mr .route-table td{max-width:300px}.mr .route-table .route-targets{max-width:300px;white-space:normal;overflow-wrap:anywhere}.mr .route-table small{max-width:320px}.mr .model-table td:first-child{width:38%}.mr .table .cell-actions{width:1%}.mr .install-plugin>div{padding-top:16px}.mr details.help.box{padding:18px 20px}.mr .sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
128
- @media(max-width:600px){.mr .metrics .metric{padding:12px 14px}.mr .metrics .metric:nth-child(2){border-right:0}.mr .metrics .metric:nth-child(-n+2){border-bottom:1px solid var(--mr-border)}.mr .section-pad{padding:14px 16px}}
129
-
130
- @media(prefers-reduced-motion:reduce){.mr *{transition:none!important}}
131
- `;
132
- function apply(ctx) {
133
- reloadFromHost = () => requestPluginReload(ctx.get?.("remote"));
134
- ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({ name: "plugins.bundle.config", key: "dsh-multi-router" }, RouterPage));
135
- ctx.slots.inject("shell.overlay", () => ctx.slots.register({ name: "shell.overlay", id: "dsh-multi-router-updates" }, UpdateReminder));
136
- ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
137
- name: "sidebar.footer.action",
138
- id: "dsh-multi-router-usage",
139
- order: 10,
140
- inject: () => ({ open: () => {
141
- const navigation = ctx.get?.("pluginNavigation");
142
- if (!navigation?.openBundle) throw Error("\u8BF7\u5728\u63D2\u4EF6\u9875\u6253\u5F00 dsh-multi-router\uFF1B\u5F53\u524D DSH \u672A\u63D0\u4F9B\u8BE6\u60C5\u5BFC\u822A\u3002");
143
- navigation.openBundle("dsh-multi-router");
144
- } })
145
- }, SidebarUsage));
146
- }
147
- var SUMMARY_EVENT = "dsh-multi-router-summary";
148
- var compactTokens = (n) => n >= 1e9 ? `${(n / 1e9).toFixed(1)}B` : n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${(n / 1e3).toFixed(1)}K` : fmt(n);
149
- function SidebarUsageCard({ data, wide = true, open, error }) {
150
- const title = `${data.today}\uFF08\u5317\u4EAC\u65F6\u95F4\uFF09
151
- \u4ECA\u65E5 ${fmt(data.tokens)} Token \xB7 ${fmt(data.requests)} \u6B21\u8BF7\u6C42
152
- \u7D2F\u8BA1 ${fmt(data.totalTokens)} Token${data.unmetered ? `
153
- ${fmt(data.unmetered)} \u6B21\u8C03\u7528\u672A\u8FD4\u56DE\u7528\u91CF` : ""}${error ? `
154
- ${error}` : ""}
155
- \u70B9\u51FB\u6253\u5F00\u8D26\u53F7\u4E0E\u8DEF\u7531`;
156
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
157
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
158
- [class*="_footArea"] [class*="_footerActions"]:has(.mr-sidebar-usage){flex-direction:column}
159
- .mr-sidebar-usage{box-sizing:border-box;display:flex;align-items:center;gap:10px;width:100%;min-width:0;min-height:48px;padding:7px 10px;border:1px solid var(--dsw-alias-border-l2,#444);border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary,#eee);font:inherit;text-align:left;cursor:pointer}
160
- .mr-sidebar-usage:hover{background:var(--dsw-alias-bg-module-platform,#303036)}.mr-sidebar-usage:focus-visible{outline:2px solid var(--dsw-alias-state-active-primary,#3a71db);outline-offset:2px}
161
- .mr-sidebar-usage svg{flex-shrink:0}.mr-sidebar-usage span{flex:1;min-width:0}.mr-sidebar-usage small{display:block;color:var(--dsw-alias-label-secondary,#aaa);font-size:10px;line-height:15px;white-space:nowrap}.mr-sidebar-usage strong{display:block;font-size:13px;font-weight:600;line-height:18px;font-variant-numeric:tabular-nums;white-space:nowrap}.mr-sidebar-usage[data-wide=false]{width:36px;min-height:36px;padding:8px;justify-content:center}
162
- ` }),
163
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: "mr-sidebar-usage", "data-wide": wide, title, "aria-label": `Token \u7528\u91CF\u6982\u89C8\uFF0C\u4ECA\u65E5 ${fmt(data.tokens)}\uFF0C\u7D2F\u8BA1 ${fmt(data.totalTokens)}\uFF0C\u6253\u5F00\u63D2\u4EF6\u8BE6\u60C5`, onClick: open, children: [
164
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 4v16h17M8 16v-5m5 5V7m5 9v-7" }) }),
165
- wide && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
166
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
167
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
168
- "\u4ECA\u65E5 Token",
169
- error ? " \xB7 \u672A\u5237\u65B0" : ""
170
- ] }),
171
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: compactTokens(data.tokens) })
172
- ] }),
173
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
174
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: "\u7D2F\u8BA1 Token" }),
175
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: compactTokens(data.totalTokens) })
176
- ] })
177
- ] })
178
- ] })
179
- ] });
180
- }
181
- function SidebarUsage({ wide = true, open }) {
182
- const [data, setData] = (0, import_react.useState)(null), [error, setError] = (0, import_react.useState)("");
183
- (0, import_react.useEffect)(() => {
184
- let stopped = false, pending = false, again = false;
185
- const abort = new AbortController();
186
- async function poll(event) {
187
- if (document.hidden) return;
188
- if (pending) {
189
- if (event?.type === SUMMARY_EVENT) again = true;
190
- return;
191
- }
192
- pending = true;
193
- try {
194
- const next = await readManagementResponse(await fetch(`${ENDPOINT}/summary`, { cache: "no-store", signal: AbortSignal.any([abort.signal, AbortSignal.timeout(8e3)]) }));
195
- if (!stopped) {
196
- setData(next);
197
- setError("");
198
- }
199
- } catch {
200
- if (!stopped) setError("\u6682\u65F6\u65E0\u6CD5\u5237\u65B0\u672C\u673A\u7EDF\u8BA1");
201
- } finally {
202
- pending = false;
203
- if (again && !stopped) {
204
- again = false;
205
- void poll();
206
- }
207
- }
208
- }
209
- void poll();
210
- const timer = setInterval(() => {
211
- void poll();
212
- }, 6e4);
213
- document.addEventListener("visibilitychange", poll);
214
- window.addEventListener(SUMMARY_EVENT, poll);
215
- return () => {
216
- stopped = true;
217
- abort.abort();
218
- clearInterval(timer);
219
- document.removeEventListener("visibilitychange", poll);
220
- window.removeEventListener(SUMMARY_EVENT, poll);
221
- };
222
- }, []);
223
- if (!data || data.enabled === false) return null;
224
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarUsageCard, { data, wide, error, open: () => {
225
- try {
226
- open();
227
- } catch (e) {
228
- setError(e.message);
229
- }
230
- } });
231
- }
232
- function Modal({ title, close, children, busy }) {
233
- const ref = (0, import_react.useRef)(null);
234
- (0, import_react.useEffect)(() => {
235
- const dialog = ref.current;
236
- dialog.showModal();
237
- return () => dialog.close();
238
- }, []);
239
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dialog", { ref, "aria-label": title, onCancel: (e) => {
240
- e.preventDefault();
241
- if (!busy) close();
242
- }, children: [
243
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-head bar", children: [
244
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: title }),
245
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy, onClick: close, children: "\u5173\u95ED" })
246
- ] }),
247
- children
248
- ] });
249
- }
250
- function UpdateReminder() {
251
- const [data, setData] = (0, import_react.useState)(null), [opened, setOpened] = (0, import_react.useState)(null), [manage, setManage] = (0, import_react.useState)(false), [busy, setBusy] = (0, import_react.useState)(false), [error, setError] = (0, import_react.useState)("");
252
- (0, import_react.useEffect)(() => {
253
- let live = true, pending = false;
254
- async function poll() {
255
- if (document.hidden || pending) return;
256
- pending = true;
257
- try {
258
- const next = await readManagementResponse(await fetch(ENDPOINT, { cache: "no-store" }));
259
- if (live && !backendNeedsRestart(next)) {
260
- setData(next);
261
- setOpened((current) => current ?? (next.pluginUpdates?.reminders?.length && !document.querySelector("dialog[open]") ? next.pluginUpdates.reminders : null));
262
- }
263
- } catch {
264
- } finally {
265
- pending = false;
266
- }
267
- }
268
- void poll();
269
- const timer = setInterval(() => {
270
- void poll();
271
- }, 6e4);
272
- return () => {
273
- live = false;
274
- clearInterval(timer);
275
- };
276
- }, []);
277
- (0, import_react.useEffect)(() => {
278
- if (data?.pluginUpdates?.job?.state !== "running") return;
279
- let live = true;
280
- const timer = setInterval(() => {
281
- void fetch(ENDPOINT, { cache: "no-store" }).then(readManagementResponse).then((next) => {
282
- if (live) setData(next);
283
- }).catch(() => {
284
- });
285
- }, 2e3);
286
- return () => {
287
- live = false;
288
- clearInterval(timer);
289
- };
290
- }, [data?.pluginUpdates?.job?.state]);
291
- async function act(action) {
292
- if (busy) return false;
293
- setBusy(true);
294
- setError("");
295
- try {
296
- const next = await readManagementResponse(await fetch(ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", "X-Multi-Router-Key": data.key }, body: JSON.stringify({ revision: data.revision, ...action }) }));
297
- setData(next);
298
- return next;
299
- } catch (e) {
300
- setError(e.message);
301
- return false;
302
- } finally {
303
- setBusy(false);
304
- }
305
- }
306
- async function dismiss() {
307
- if (await act({ action: "plugins.dismiss", keys: opened.map((r) => r.key) })) {
308
- setOpened(null);
309
- setManage(false);
310
- }
311
- }
312
- if (!opened || !data) return null;
313
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mr", children: [
314
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: styles }),
315
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: "\u53D1\u73B0\u63D2\u4EF6\u66F4\u65B0", busy: busy || data.pluginUpdates?.job?.state === "running", close: () => {
316
- void dismiss();
317
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
318
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error }),
319
- manage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PluginUpdatesPanel, { data: data.pluginUpdates, busy, act }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
320
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
321
- opened.length,
322
- " \u4E2A\u7528\u6237\u5B89\u88C5\u7684\u63D2\u4EF6\u6709\u66F4\u65B0\u3002\u8BF7\u9009\u62E9\u67E5\u770B\u66F4\u65B0\uFF0C\u6216\u7A0D\u540E\u5904\u7406\u3002"
323
- ] }),
324
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { children: opened.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
325
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: r.name }),
326
- " \xB7 ",
327
- r.version || "\u672A\u77E5\u7248\u672C",
328
- " \u2192 ",
329
- r.latestVersion || `Git ${r.latestCommit?.slice(0, 8)}`
330
- ] }, r.key)) }),
331
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u6BCF 24 \u5C0F\u65F6\u81EA\u52A8\u68C0\u67E5 GitHub / npm \u5B89\u88C5\u6765\u6E90\uFF1B\u540C\u4E00\u7248\u672C\u53EA\u63D0\u9192\u4E00\u6B21\u3002DSH \u5185\u7F6E\u63D2\u4EF6\u4E0D\u53C2\u4E0E\u68C0\u67E5\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u5B89\u88C5\u66F4\u65B0\u3002" })
332
- ] }),
333
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
334
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy || data.pluginUpdates?.job?.state === "running", onClick: () => {
335
- void dismiss();
336
- }, children: "\u7A0D\u540E\u5904\u7406" }),
337
- !manage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy, onClick: () => setManage(true), children: "\u67E5\u770B\u5E76\u66F4\u65B0" })
338
- ] })
339
- ] }) })
340
- ] });
341
- }
342
- function Feedback({ error, notice }) {
343
- return error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "feedback error", role: "alert", children: error }) : notice ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "feedback", role: "status", children: notice }) : null;
344
- }
345
- var metric = (label, value, detail) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "box metric", children: [
346
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: label }),
347
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: value }),
348
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: detail })
349
- ] });
350
- function RouterPage({ view = "page" }) {
351
- const [data, setData] = (0, import_react.useState)(null), [tab, setTab] = (0, import_react.useState)("overview");
352
- const [accountProvider, setAccountProvider] = (0, import_react.useState)(""), [provider, setProvider] = (0, import_react.useState)("workbuddy"), [busy, setBusy] = (0, import_react.useState)(false), [live, setLive] = (0, import_react.useState)(true);
353
- const [error, setError] = (0, import_react.useState)(""), [notice, setNotice] = (0, import_react.useState)(""), [draft, setDraft] = (0, import_react.useState)(null), [accountModal, setAccountModal] = (0, import_react.useState)(null), [presetModal, setPresetModal] = (0, import_react.useState)(false), [search, setSearch] = (0, import_react.useState)("");
354
- const polling = (0, import_react.useRef)(false);
355
- async function load(signal = AbortSignal.timeout(8e3)) {
356
- const next = await readManagementResponse(await fetch(ENDPOINT, { cache: "no-store", signal }));
357
- setData(next);
358
- setError("");
359
- }
360
- (0, import_react.useEffect)(() => {
361
- if (view === "summary") return;
362
- let stopped = false, retry, attempts = 0;
363
- const abort = new AbortController();
364
- async function connect() {
365
- try {
366
- await load(AbortSignal.any([abort.signal, AbortSignal.timeout(4e3)]));
367
- } catch (e) {
368
- if (stopped) return;
369
- if (++attempts < 8) retry = setTimeout(connect, 750);
370
- else setError(e.message);
371
- }
372
- }
373
- void connect();
374
- const timer = live && setInterval(() => {
375
- if (document.hidden || polling.current) return;
376
- polling.current = true;
377
- void load(abort.signal).catch((e) => {
378
- if (!stopped) setError(e.message);
379
- }).finally(() => {
380
- polling.current = false;
381
- });
382
- }, 6e4);
383
- return () => {
384
- stopped = true;
385
- abort.abort();
386
- clearTimeout(retry);
387
- clearInterval(timer);
388
- };
389
- }, [view, live]);
390
- (0, import_react.useEffect)(() => {
391
- if (data?.startup?.phase !== "discovering" && !["waiting", "reloading"].includes(data?.runtime?.phase) && data?.pluginUpdates?.job?.state !== "running" && !data?.checkins?.running) return;
392
- const timer = setInterval(() => {
393
- if (document.hidden || polling.current) return;
394
- polling.current = true;
395
- void load().catch((e) => setError(e.message)).finally(() => {
396
- polling.current = false;
397
- });
398
- }, 2e3);
399
- return () => clearInterval(timer);
400
- }, [data?.startup?.phase, data?.runtime?.phase, data?.pluginUpdates?.job?.state, data?.checkins?.running]);
401
- async function reload() {
402
- setBusy(true);
403
- setError("");
404
- try {
405
- if (!reloadFromHost) throw Error("\u8BF7\u5728 DSH \u63D2\u4EF6\u9875\u91CD\u65B0\u542F\u7528\u672C\u63D2\u4EF6\u3002");
406
- await reloadFromHost();
407
- await load();
408
- } catch (e) {
409
- setError(e.message);
410
- } finally {
411
- setBusy(false);
412
- }
413
- }
414
- async function act(action) {
415
- if (busy || backendNeedsRestart(data)) return false;
416
- setBusy(true);
417
- setError("");
418
- setNotice("");
419
- try {
420
- const res = await fetch(ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", "X-Multi-Router-Key": data.key }, body: JSON.stringify({ revision: data.revision, ...action }) });
421
- const next = await readManagementResponse(res);
422
- const { exported, workbuddyLogin, loginResult, apiKey, modelTest, ...state } = next;
423
- setData(state);
424
- if (action.sidebarUsage !== void 0 || action.action === "config.import") window.dispatchEvent(new Event(SUMMARY_EVENT));
425
- setNotice(action.action === "model.test" ? "" : action.action.startsWith("api.") ? next.apiService?.phase === "error" ? "\u914D\u7F6E\u5DF2\u4FDD\u5B58\uFF0C\u4F46\u670D\u52A1\u5C1A\u672A\u542F\u52A8\uFF0C\u8BF7\u67E5\u770B\u4E0B\u65B9\u63D0\u793A\u3002" : action.action === "api.key.reveal" ? "" : "API \u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u3002" : action.action === "workbuddy.sms" ? "" : action.action === "workbuddy.login" ? loginResult?.warning || "\u767B\u5F55\u51ED\u8BC1\u5DF2\u4FDD\u5B58\uFF0C\u81EA\u52A8\u7B7E\u5230\u5F00\u5173\u4FDD\u6301\u539F\u8BBE\u7F6E\u3002" : action.action === "checkins.verify" ? "\u767B\u5F55\u9A8C\u8BC1\u901A\u8FC7\uFF0C\u65E7\u7684\u4EE4\u724C\u5931\u6548\u63D0\u793A\u5DF2\u89E3\u9664\uFF1B\u672A\u63D0\u4EA4\u7B7E\u5230\u3002" : action.action === "checkins.settings" ? "\u7B7E\u5230\u8BA1\u5212\u5DF2\u4FDD\u5B58\uFF1B\u4ECA\u65E5\u5DF2\u5904\u7406\u8BB0\u5F55\u4FDD\u6301\u4E0D\u53D8\u3002" : action.action.startsWith("checkins.") || action.action.startsWith("plugins.") || action.action === "setup.dismiss" ? "" : action.action === "accounts.discover" || action.action === "monitor.refresh" ? "\u5DF2\u91CD\u65B0\u68C0\u6D4B\u672C\u673A\u767B\u5F55\u5E76\u5237\u65B0\u7528\u91CF\uFF1B\u68C0\u6D4B\u7ED3\u679C\u89C1\u4E0B\u65B9\u3002" : action.action.includes("refresh") ? "\u5DF2\u5237\u65B0\u3002\u65E0\u6CD5\u83B7\u53D6\u7684\u8D26\u53F7\u4F1A\u4FDD\u7559\u4E0A\u6B21\u6570\u636E\u5E76\u6807\u8BB0\u3002" : action.action === "config.import" ? "\u914D\u7F6E\u5DF2\u5BFC\u5165\u5E76\u751F\u6548\uFF0C\u539F\u914D\u7F6E\u5DF2\u5907\u4EFD\uFF1B\u6A21\u578B\u548C\u7528\u91CF\u6B63\u5728\u540E\u53F0\u66F4\u65B0\u3002" : action.action.startsWith("config.") || action.action === "account.export" ? "" : "\u5DF2\u4FDD\u5B58\u5E76\u751F\u6548\u3002");
426
- return next;
427
- } catch (e) {
428
- setError(e.message);
429
- return false;
430
- } finally {
431
- setBusy(false);
432
- }
433
- }
434
- function openAccount(mode, account) {
435
- setError("");
436
- setNotice("");
437
- setAccountModal({ mode, account, revision: data.revision });
438
- }
439
- const newTarget = (target = { provider: "workbuddy" }) => ({ ...target, key: crypto.randomUUID(), weight: target.weight ?? 1, tokenBudget: target.tokenBudget ?? 1e5, creditBudget: target.creditBudget ?? 100, modelText: (target.models ?? [target.model ?? ""]).join(", ") });
440
- function editRoute(route) {
441
- setError("");
442
- setNotice("");
443
- setDraft({ ...structuredClone(route), revision: data.revision, previousId: route.id, strategy: route.strategy ?? "failover", targets: route.targets.map(newTarget) });
444
- }
445
- const p = data?.providers.find((p2) => p2.id === provider);
446
- const providerSelect = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
447
- "\u4F9B\u5E94\u5546 / \u533A\u57DF",
448
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { value: provider, onChange: (e) => {
449
- setProvider(e.target.value);
450
- setSearch("");
451
- }, children: data?.providers.map((p2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: p2.id, children: p2.name }, p2.id)) })
452
- ] });
453
- const accountProviderSelect = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
454
- "\u4F9B\u5E94\u5546 / \u533A\u57DF",
455
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: accountProvider, onChange: (e) => setAccountProvider(e.target.value), children: [
456
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5168\u90E8\u4F9B\u5E94\u5546" }),
457
- data?.providers.map((p2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: p2.id, children: p2.name }, p2.id))
458
- ] })
459
- ] });
460
- if (view === "summary") return "\u4E09\u5BB6\u8D26\u53F7\u4E0E\u767B\u5F55\u4FE1\u606F\u3001\u7528\u91CF\u76D1\u63A7\u3001\u6A21\u578B\u7BA1\u7406\uFF0C\u4EE5\u53CA\u6743\u91CD\u548C\u989D\u5EA6\u8DEF\u7531\u3002";
461
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mr", children: [
462
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: styles }),
463
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
464
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
465
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: "\u8D26\u53F7\u4E0E\u8DEF\u7531" }),
466
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "muted", children: "\u7BA1\u7406\u4E09\u5BB6\u8D26\u53F7\u3001\u6A21\u578B\u4E0E\u7528\u91CF" })
467
- ] }),
468
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
469
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "badge", children: [
470
- "v",
471
- data?.pluginVersion ?? version
472
- ] }),
473
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check refresh-control", children: [
474
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", disabled: busy || !data || backendNeedsRestart(data), checked: data?.options?.sidebarUsage !== false, onChange: (e) => {
475
- void act({ action: "options.save", sidebarUsage: e.target.checked });
476
- } }),
477
- "\u4FA7\u680F\u7528\u91CF"
478
- ] }),
479
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "status", children: [
480
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { className: busy || !data ? "warn" : "good", "aria-hidden": "true" }),
481
- busy ? "\u6B63\u5728\u5904\u7406\u2026" : !data ? "\u6B63\u5728\u8FDE\u63A5\u2026" : "\u672C\u673A\u8FD0\u884C"
482
- ] }),
483
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check refresh-control", children: [
484
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: live, onChange: (e) => setLive(e.target.checked) }),
485
- "\u6BCF\u5206\u949F\u5237\u65B0"
486
- ] }),
487
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
488
- void load().catch((e) => setError(e.message));
489
- }, children: "\u5237\u65B0\u9762\u677F" })
490
- ] })
491
- ] }),
492
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", { "aria-label": "\u8DEF\u7531\u63D2\u4EF6\u914D\u7F6E\u9875\u7B7E", children: [["overview", "\u603B\u89C8\u4E0E\u7528\u91CF"], ["usage", "Token \u660E\u7EC6"], ["accounts", "\u8D26\u53F7\u4E0E\u767B\u5F55"], ["checkins", "\u79EF\u5206\u7B7E\u5230"], ["models", "\u6A21\u578B\u7BA1\u7406"], ["routes", "\u8DEF\u7531\u89C4\u5219"], ["api", "API \u670D\u52A1"], ["plugins", "\u63D2\u4EF6\u66F4\u65B0"], ["migration", "\u914D\u7F6E\u8FC1\u79FB"]].map(([key, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { "aria-pressed": tab === key, onClick: () => {
493
- setTab(key);
494
- setError("");
495
- setNotice("");
496
- }, children: label }, key)) }),
497
- !draft && !accountModal && !presetModal && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
498
- (backendNeedsRestart(data) || !data && error) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RestartGuidance, { data, busy, reload: () => {
499
- void reload();
500
- }, retry: () => {
501
- void load().catch((e) => setError(e.message));
502
- } }),
503
- !data ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", role: "status", "aria-live": "polite", children: [
504
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: error ? "\u7B49\u5F85\u540E\u53F0\u8FDE\u63A5" : "\u6B63\u5728\u8FDE\u63A5\u672C\u673A\u63D2\u4EF6\u2026" }),
505
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u9875\u9762\u4F1A\u81EA\u52A8\u91CD\u65B0\u8FDE\u63A5\u3002\u8D26\u53F7\u53D1\u73B0\u3001\u7528\u91CF\u548C\u6A21\u578B\u76EE\u5F55\u5C06\u5728\u540E\u53F0\u66F4\u65B0\u3002" }),
506
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("progress", { "aria-label": "\u6B63\u5728\u8FDE\u63A5\u63D2\u4EF6\u540E\u53F0" })
507
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { className: "stack", style: { border: 0, padding: 0, margin: 0, minWidth: 0 }, disabled: backendNeedsRestart(data), "aria-busy": busy, children: [
508
- data.startup?.phase === "discovering" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", role: "status", children: "\u6B63\u5728\u540E\u53F0\u83B7\u53D6\u672C\u673A\u8D26\u53F7\uFF0C\u5DF2\u6709\u8D26\u53F7\u548C\u8DEF\u7531\u73B0\u5728\u5373\u53EF\u4F7F\u7528\u3002" }),
509
- data.runtime?.phase && data.runtime.phase !== "current" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "steps", children: [
510
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
511
- data.runtime.message,
512
- "\uFF08\u8FD0\u884C v",
513
- data.runtime.runningVersion,
514
- " / \u5DF2\u5B89\u88C5 v",
515
- data.runtime.installedVersion,
516
- "\uFF09"
517
- ] }),
518
- ["failed", "restart-required"].includes(data.runtime.phase) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
519
- void reload();
520
- }, children: "\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6" })
521
- ] }),
522
- ["overview", "accounts"].includes(tab) && data.setup?.dismissed !== true && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InitialSetup, { data, busy, act, go: (key) => setTab(key) }),
523
- tab === "overview" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Overview, { data, busy, act, go: (key) => setTab(key) }),
524
- tab === "api" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ApiServicePanel, { data: data.apiService, busy, act }),
525
- tab === "plugins" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PluginUpdatesPanel, { data: data.pluginUpdates, busy, act }),
526
- tab === "checkins" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CheckinPanel, { data, busy, act }),
527
- tab === "usage" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageDetails, { data, busy, act }),
528
- tab === "accounts" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccountPool, { data, provider: accountProvider, providerSelect: accountProviderSelect, busy, act, manage: (a) => openAccount("edit", a), add: () => openAccount("add") }, accountProvider),
529
- tab === "models" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModelsPanel, { error, notice, data, provider, providerSelect, search, setSearch, busy, act }),
530
- tab === "routes" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
531
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
532
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
533
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u6A21\u578B\u8DEF\u7531" }),
534
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
535
- data.routes.length,
536
- " \u6761\u8DEF\u7531 \xB7 \u89C4\u5219\u4E0E\u8D26\u53F7\u5728\u7F16\u8F91\u4E2D\u8C03\u6574"
537
- ] })
538
- ] }),
539
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
540
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
541
- setError("");
542
- setNotice("");
543
- setPresetModal(true);
544
- }, children: "\u6DFB\u52A0\u9884\u914D\u7F6E" }),
545
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy, onClick: () => {
546
- setError("");
547
- setNotice("");
548
- setDraft({ id: "", name: "", revision: data.revision, contextMode: "maximum", contextWindow: 2e5, maxTokens: 32e3, strategy: "failover", preferExpiringCredits: true, expiringWithinDays: 7, visible: true, targets: [newTarget()] });
549
- }, children: "\u65B0\u5EFA\u8DEF\u7531" })
550
- ] })
551
- ] }),
552
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RoutesTable, { data, busy, act, edit: editRoute }),
553
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [
554
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u5168\u5C40\u5207\u6362\u8BBE\u7F6E" }),
555
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "box stack", style: { marginTop: 16 }, onSubmit: (e) => {
556
- e.preventDefault();
557
- const f = new FormData(e.currentTarget);
558
- void act({ action: "options.save", cooldownMs: Number(f.get("cooldown")) * 1e3, requestTimeoutMs: Number(f.get("timeout")) * 1e3, retryServerErrors: f.has("server") });
559
- }, children: [
560
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid", children: [
561
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
562
- "\u5931\u8D25\u8D26\u53F7\u51B7\u5374\uFF08\u79D2\uFF09",
563
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { disabled: busy, name: "cooldown", type: "number", min: "1", required: true, defaultValue: data.options.cooldownMs / 1e3 })
564
- ] }),
565
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
566
- "\u8BF7\u6C42\u8D85\u65F6\uFF08\u79D2\uFF09",
567
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { disabled: busy, name: "timeout", type: "number", min: "1", required: true, defaultValue: data.options.requestTimeoutMs / 1e3 })
568
- ] })
569
- ] }),
570
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
571
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { disabled: busy, name: "server", type: "checkbox", defaultChecked: data.options.retryServerErrors }),
572
- "5xx \u548C\u7F51\u7EDC\u9519\u8BEF\u4E5F\u5207\u6362\u8D26\u53F7"
573
- ] }),
574
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, type: "submit", children: "\u4FDD\u5B58\u8BBE\u7F6E" }) })
575
- ] })
576
- ] })
577
- ] }),
578
- tab === "migration" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MigrationForm, { data, act, busy })
579
- ] }),
580
- draft && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: draft.previousId ? "\u7F16\u8F91\u8DEF\u7531" : "\u65B0\u5EFA\u8DEF\u7531", busy, close: () => setDraft(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouteForm, { draft, setDraft, data, act, busy, error, notice }) }),
581
- presetModal && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Modal, { title: "\u6A21\u578B\u8DEF\u7531\u9884\u914D\u7F6E", busy, close: () => setPresetModal(false), children: [
582
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
583
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
584
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "Free \u81EA\u52A8\u53D1\u73B0\u5404\u8D26\u53F7\u7684\u514D\u8D39\u6A21\u578B\uFF1B\u5176\u4ED6\u9884\u914D\u7F6E\u7ED1\u5B9A\u5DF2\u6838\u5BF9\u7684\u6E20\u9053\u6A21\u578B\u3002\u5DF2\u6709\u8DEF\u7531\u4E0D\u4F1A\u88AB\u8986\u76D6\u3002" }),
585
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid", children: (data.presets || []).map((preset) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
586
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: preset.name }) }),
587
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: preset.freeOnly ? "\u6BCF\u5929\u81EA\u52A8\u68C0\u67E5\u514D\u8D39\u6A21\u578B\uFF0C\u8C03\u7528\u524D\u590D\u6838\u96F6\u500D\u7387\uFF1B\u4EC5\u5728\u514D\u8D39\u6A21\u578B\u95F4\u5207\u6362\u3002" : `\u5DF2\u53D1\u73B0\u53EF\u7528\u6E20\u9053\uFF1A${preset.availableProviders.length} / ${preset.providerCount ?? preset.targets.length}${preset.availableProviders.length < (preset.providerCount ?? preset.targets.length) ? " \xB7 \u53EF\u6DFB\u52A0\u8D26\u53F7\u6216\u5237\u65B0\u6A21\u578B\u76EE\u5F55\u540E\u4F7F\u7528" : ""}` }),
588
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy || preset.added, onClick: () => {
589
- void act({ action: "preset.add", id: preset.id });
590
- }, children: preset.added ? "\u5DF2\u6DFB\u52A0" : "\u6DFB\u52A0\u6B64\u8DEF\u7531" })
591
- ] }, preset.id)) })
592
- ] }),
593
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-foot bar", children: [
594
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u65B0\u589E\u8DEF\u7531\u53EF\u7EE7\u7EED\u7F16\u8F91\u540D\u79F0\u3001\u8D26\u53F7\u548C\u5207\u6362\u89C4\u5219\u3002" }),
595
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy || !(data.presets || []).some((p2) => !p2.added), onClick: () => {
596
- void act({ action: "preset.add-all" });
597
- }, children: "\u8865\u9F50\u5168\u90E8\u9884\u914D\u7F6E" })
598
- ] })
599
- ] }),
600
- accountModal && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: accountModal.mode === "edit" ? "\u8D26\u53F7\u767B\u5F55\u8BE6\u60C5" : accountModal.mode === "credentials" ? "\u8865\u5145 / \u66F4\u65B0\u8D26\u53F7\u51ED\u8BC1" : "\u6DFB\u52A0\u8D26\u53F7\u4E0E\u83B7\u53D6\u767B\u5F55", busy, close: () => setAccountModal(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccountForm, { modal: accountModal, provider: accountProvider || "workbuddy", data, busy, act, replace: () => openAccount("credentials", accountModal.account), close: (selected) => {
601
- if (typeof selected === "string" && accountProvider) setAccountProvider(selected);
602
- setAccountModal(null);
603
- }, error, notice }) })
604
- ] });
605
- }
606
- function ApiServicePanel({ data: a, busy, act }) {
607
- const [key, setKey] = (0, import_react.useState)(""), [hint, setHint] = (0, import_react.useState)(""), [confirmKey, setConfirmKey] = (0, import_react.useState)(null), [models, setModels] = (0, import_react.useState)(false), [example, setExample] = (0, import_react.useState)("");
608
- const copyField = (0, import_react.useRef)(null);
609
- (0, import_react.useEffect)(() => {
610
- setKey((current) => a?.keyHint && current.endsWith(a.keyHint.slice(-4)) ? current : "");
611
- }, [a?.keyHint]);
612
- (0, import_react.useEffect)(() => {
613
- if (!key) return;
614
- const timer = setTimeout(() => setKey(""), 6e4);
615
- return () => clearTimeout(timer);
616
- }, [key]);
617
- if (!a) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "\u5F53\u524D\u540E\u53F0\u672A\u63D0\u4F9B API \u670D\u52A1\uFF0C\u8BF7\u66F4\u65B0\u63D2\u4EF6\u3002" });
618
- const save = (fields) => act({ action: "api.settings", apiRevision: a.revision, ...fields });
619
- async function keyAction(action) {
620
- const result = await act({ action, apiRevision: a.revision });
621
- if (result) {
622
- setKey(result.apiKey || "");
623
- setConfirmKey(null);
624
- }
625
- }
626
- async function copy(value, fallback = false) {
627
- try {
628
- await navigator.clipboard.writeText(value);
629
- setHint("\u5DF2\u590D\u5236\u3002");
630
- } catch {
631
- setHint("\u5F53\u524D\u73AF\u5883\u65E0\u6CD5\u81EA\u52A8\u590D\u5236\uFF0C\u8BF7\u5728\u6587\u672C\u6846\u4E2D\u5168\u9009\u590D\u5236\u3002");
632
- if (fallback) copyField.current?.select();
633
- else setExample(value);
634
- }
635
- }
636
- const model = a.models[0]?.id || "\u4F60\u7684\u8DEF\u7531\u6A21\u578B ID";
637
- const command = `curl '${a.baseUrl}/chat/completions' \\
638
- -H 'Authorization: Bearer YOUR_API_KEY' \\
639
- -H 'Content-Type: application/json' \\
640
- -d '${JSON.stringify({ model, messages: [{ role: "user", content: "\u4F60\u597D" }], stream: true })}'`;
641
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
642
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
643
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
644
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
645
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "API \u670D\u52A1" }),
646
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5C06\u8D26\u53F7\u6C60\u4E0E\u7EDF\u4E00\u8DEF\u7531\u63D0\u4F9B\u7ED9\u5176\u4ED6\u5DE5\u5177\u3002\u968F DSH \u8FD0\u884C\uFF0C\u9ED8\u8BA4\u5173\u95ED\u3002" })
647
- ] }),
648
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "status", role: "status", children: [
649
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { className: a.phase === "running" ? "good" : a.phase === "error" ? "warn" : "", "aria-hidden": "true" }),
650
- { running: "\u8FD0\u884C\u4E2D", stopped: "\u5DF2\u5173\u95ED", starting: "\u542F\u52A8\u4E2D", error: "\u542F\u52A8\u5931\u8D25" }[a.phase] || a.phase
651
- ] })
652
- ] }),
653
- a.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "error", role: "alert", children: a.error }),
654
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
655
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: a.phase === "running" ? `${a.active} \u4E2A\u5904\u7406\u4E2D\u8BF7\u6C42 \xB7 ${a.allowLan ? "\u672C\u673A\u4E0E\u7F51\u7EDC\u8BBF\u95EE" : "\u4EC5\u672C\u673A\u8BBF\u95EE"}` : "\u5F00\u542F\u540E\u5373\u53EF\u590D\u5236\u63A5\u5165\u5730\u5740\uFF1B\u5173\u95ED\u4F1A\u7EC8\u6B62\u6B63\u5728\u5904\u7406\u7684 API \u8BF7\u6C42\u3002" }),
656
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
657
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: a.enabled, disabled: busy || !a.hasKey, onChange: (e) => {
658
- void save({ enabled: e.target.checked });
659
- } }),
660
- "\u542F\u7528 API \u670D\u52A1"
661
- ] })
662
- ] }),
663
- !a.hasKey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "\u5148\u751F\u6210 API Key\uFF0C\u518D\u542F\u7528\u670D\u52A1\u3002\u8D26\u53F7\u767B\u5F55\u51ED\u8BC1\u4E0D\u4F1A\u901A\u8FC7\u6B64\u670D\u52A1\u63D0\u4F9B\u3002" })
664
- ] }),
665
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "metrics", children: [
666
- metric("\u4ECA\u65E5 API \u8C03\u7528", fmt(a.today.calls), `${a.today.attempts} \u6B21\u4E0A\u6E38\u5C1D\u8BD5\uFF0C\u542B\u6545\u969C\u5207\u6362`),
667
- metric("\u4ECA\u65E5 API Token", fmt(a.today.tokens), "\u5E73\u53F0\u5B9E\u9645\u8FD4\u56DE\u7528\u91CF"),
668
- metric("\u5DF2\u5F00\u653E\u6A21\u578B", fmt(a.models.length), a.modelIds === null ? "\u8DDF\u968F\u8DEF\u7531\u5C55\u793A\u8BBE\u7F6E" : "\u81EA\u9009\u6A21\u578B"),
669
- metric("\u5904\u7406\u4E2D", fmt(a.active), "\u6700\u591A 8 \u4E2A\u5E76\u53D1 API \u8BF7\u6C42")
670
- ] }),
671
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
672
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
673
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
674
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u63A5\u5165\u4FE1\u606F" }),
675
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5BA2\u6237\u7AEF\u9009\u62E9 OpenAI \u517C\u5BB9\u65B9\u5F0F\uFF0C\u586B\u5199\u4E0B\u65B9 Base URL \u4E0E API Key\u3002" })
676
- ] }),
677
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => setExample(command), children: "\u8C03\u7528\u793A\u4F8B" })
678
- ] }),
679
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
680
- "Base URL",
681
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
682
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { className: "mono", style: { flex: 1, minWidth: 180 }, readOnly: true, value: a.baseUrl, onFocus: (e) => e.currentTarget.select() }),
683
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => {
684
- void copy(a.baseUrl);
685
- }, children: "\u590D\u5236\u5730\u5740" })
686
- ] })
687
- ] }),
688
- a.allowLan && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
689
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5176\u4ED6\u8BBE\u5907\u53EF\u4F7F\u7528\u4EE5\u4E0B\u672C\u673A\u7F51\u5361\u5730\u5740\uFF08\u9700\u8981\u7F51\u7EDC\u53EF\u8FBE\u53CA\u9632\u706B\u5899\u653E\u884C\uFF09\uFF1A" }),
690
- a.lanUrls.length ? a.lanUrls.map((url) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mono", style: { overflowWrap: "anywhere" }, children: url }, url)) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u6682\u65E0\u53EF\u7528 IPv4 \u7F51\u5361\u5730\u5740\u3002" })
691
- ] }),
692
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
693
- "API Key",
694
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
695
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { ref: copyField, className: "mono", style: { flex: 1, minWidth: 180 }, readOnly: true, autoComplete: "off", spellCheck: "false", value: key || a.keyHint || "\u5C1A\u672A\u751F\u6210", onFocus: (e) => e.currentTarget.select() }),
696
- a.hasKey && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
697
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
698
- if (key) setKey("");
699
- else void keyAction("api.key.reveal");
700
- }, children: key ? "\u9690\u85CF" : "\u663E\u793A" }),
701
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: async () => {
702
- const result = await act({ action: "api.key.reveal", apiRevision: a.revision });
703
- if (result?.apiKey) {
704
- setKey(result.apiKey);
705
- await copy(result.apiKey, true);
706
- }
707
- }, children: "\u590D\u5236 Key" })
708
- ] })
709
- ] })
710
- ] }),
711
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
712
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
713
- if (a.hasKey) setConfirmKey("create");
714
- else void keyAction("api.key.create");
715
- }, children: a.hasKey ? "\u91CD\u7F6E API Key" : "\u751F\u6210 API Key" }),
716
- a.hasKey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => setConfirmKey("revoke"), children: "\u64A4\u9500 Key \u5E76\u5173\u95ED\u670D\u52A1" }),
717
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "Key \u4EC5\u4FDD\u5B58\u5728\u672C\u673A\u79C1\u6709\u6587\u4EF6\uFF1B\u663E\u793A\u540E 60 \u79D2\u81EA\u52A8\u9690\u85CF\u3002" })
718
- ] }),
719
- hint && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", role: "status", children: hint })
720
- ] }),
721
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
722
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u670D\u52A1\u8BBE\u7F6E" }),
723
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "stack", onSubmit: (e) => {
724
- e.preventDefault();
725
- const f = new FormData(e.currentTarget);
726
- void save({ port: Number(f.get("port")), allowLan: f.has("lan") });
727
- }, children: [
728
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
729
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
730
- "\u76D1\u542C\u7AEF\u53E3",
731
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", name: "port", min: "1024", max: "65535", required: true, defaultValue: a.port, disabled: busy })
732
- ] }),
733
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
734
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", name: "lan", defaultChecked: a.allowLan, disabled: busy }),
735
- "\u5141\u8BB8\u5C40\u57DF\u7F51\u8BBF\u95EE"
736
- ] }),
737
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, children: "\u4FDD\u5B58\u8BBE\u7F6E" })
738
- ] }),
739
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u9ED8\u8BA4\u76D1\u542C 127.0.0.1\u3002\u5F00\u542F\u7F51\u7EDC\u8BBF\u95EE\u540E\u76D1\u542C\u6240\u6709 IPv4 \u7F51\u5361\uFF0C\u4F7F\u7528 HTTP\uFF0C\u8BF7\u4EC5\u7528\u4E8E\u53EF\u4FE1\u7F51\u7EDC\uFF1B\u5982\u9700\u5916\u7F51\u8BBF\u95EE\uFF0C\u8BF7\u81EA\u884C\u914D\u7F6E HTTPS \u4E0E\u8BBF\u95EE\u9650\u5236\u3002\u4FEE\u6539\u7AEF\u53E3\u6216\u8BBF\u95EE\u8303\u56F4\u4F1A\u4E2D\u65AD\u5F53\u524D API \u8BF7\u6C42\u3002" })
740
- ] }, a.revision)
741
- ] }),
742
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box table-shell", children: [
743
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar table-footer", children: [
744
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
745
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5F00\u653E\u6A21\u578B" }),
746
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: a.modelIds === null ? "\u81EA\u52A8\u8DDF\u968F\u5DF2\u5C55\u793A\u8DEF\u7531\uFF0C\u5305\u542B\u52A8\u6001\u514D\u8D39\u6A21\u578B\u3002" : "\u4EC5\u5F00\u653E\u624B\u52A8\u9009\u62E9\u7684\u8DEF\u7531\u3002" })
747
- ] }),
748
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => setModels(true), children: "\u9009\u62E9\u5F00\u653E\u6A21\u578B" })
749
- ] }),
750
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", role: "region", "aria-label": "API \u5F00\u653E\u6A21\u578B", tabIndex: "0", children: [
751
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
752
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
753
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u6A21\u578B\u540D\u79F0" }),
754
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8C03\u7528\u6A21\u578B ID" })
755
- ] }) }),
756
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: a.models.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
757
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: m.name }),
758
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "mono", style: { overflowWrap: "anywhere" }, children: m.id })
759
- ] }, m.id)) })
760
- ] }),
761
- !a.models.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: "\u6682\u672A\u5F00\u653E\u6A21\u578B\uFF0C\u8BF7\u5C55\u793A\u8DEF\u7531\u6216\u624B\u52A8\u9009\u62E9\u3002" })
762
- ] })
763
- ] }),
764
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [
765
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u63A5\u53E3\u4E0E\u7EDF\u8BA1\u8BF4\u660E" }),
766
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u652F\u6301 GET /v1/models\u3001POST /v1/chat/completions\uFF08\u6D41\u5F0F\u4E0E\u666E\u901A JSON\uFF09\uFF0C\u6CBF\u7528\u8DEF\u7531\u7684\u63A8\u7406\u9ED8\u8BA4\u503C\uFF0C\u53EF\u7528 reasoning_effort \u8986\u76D6\u3002\u5DE5\u5177\u8C03\u7528\u4E0E\u56FE\u7247\u80FD\u529B\u53D6\u51B3\u4E8E\u76EE\u6807\u6A21\u578B\uFF1B\u5916\u90E8\u5DE5\u5177\u81EA\u884C\u6267\u884C\u5DE5\u5177\u5E76\u56DE\u4F20\u7ED3\u679C\u3002\u7528\u91CF\u8BB0\u5F55\u5230 Token \u660E\u7EC6\u7684\u300CAPI \u670D\u52A1\u300D\u6765\u6E90\uFF0C\u4E0D\u4FDD\u5B58\u8BF7\u6C42\u5185\u5BB9\u6216 Key\uFF1B\u4E0A\u4E0B\u6587\u7531\u8C03\u7528\u5BA2\u6237\u7AEF\u4F20\u5165\u3002\u6B64\u7248\u672C\u4E0D\u63D0\u4F9B Responses\u3001Embeddings \u6216\u8DE8\u7AD9\u6D4F\u89C8\u5668 CORS \u63A5\u53E3\u3002\u542F\u7528\u72B6\u6001\u4F1A\u4FDD\u5B58\uFF0CDSH \u4E0B\u6B21\u542F\u52A8\u81EA\u52A8\u6062\u590D\uFF1B\u9000\u51FA DSH \u540E\u505C\u6B62\u3002" })
767
- ] }),
768
- confirmKey && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Modal, { title: confirmKey === "create" ? "\u91CD\u7F6E API Key" : "\u64A4\u9500 API Key", busy, close: () => setConfirmKey(null), children: [
769
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "modal-body stack", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: confirmKey === "create" ? "\u65E7 Key \u5C06\u7ACB\u5373\u5931\u6548\uFF0C\u5176\u4ED6\u5BA2\u6237\u7AEF\u9700\u8981\u586B\u5199\u65B0 Key\u3002" : "Key \u5C06\u7ACB\u5373\u5931\u6548\uFF0CAPI \u670D\u52A1\u4F1A\u5173\u95ED\uFF0C\u6B63\u5728\u5904\u7406\u7684 API \u8BF7\u6C42\u5C06\u4E2D\u65AD\u3002" }) }),
770
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-foot row", children: [
771
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => setConfirmKey(null), children: "\u53D6\u6D88" }),
772
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: "primary", disabled: busy, onClick: () => {
773
- void keyAction(`api.key.${confirmKey}`);
774
- }, children: [
775
- "\u786E\u8BA4",
776
- confirmKey === "create" ? "\u91CD\u7F6E" : "\u64A4\u9500"
777
- ] })
778
- ] })
779
- ] }),
780
- models && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: "\u9009\u62E9 API \u5F00\u653E\u6A21\u578B", busy, close: () => setModels(false), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ApiModels, { data: a, busy, save: async (modelIds) => {
781
- if (await save({ modelIds })) setModels(false);
782
- } }) }),
783
- example && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: "\u63A5\u5165\u793A\u4F8B / \u624B\u52A8\u590D\u5236", busy: false, close: () => setExample(""), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
784
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5C06 YOUR_API_KEY \u66FF\u6362\u4E3A\u81EA\u5DF1\u7684\u670D\u52A1 Key\u3002Base URL \u5DF2\u5305\u542B /v1\uFF1B\u6D4B\u8BD5\u8C03\u7528\u4F1A\u6B63\u5E38\u6D88\u8017\u76EE\u6807\u8D26\u53F7\u7684\u7528\u91CF\u3002" }),
785
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
786
- "\u53EF\u590D\u5236\u5185\u5BB9",
787
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { className: "mono", readOnly: true, rows: 8, value: example, onFocus: (e) => e.currentTarget.select() })
788
- ] })
789
- ] }) })
790
- ] });
791
- }
792
- function ApiModels({ data, busy, save }) {
793
- const [follow, setFollow] = (0, import_react.useState)(data.modelIds === null), [selected, setSelected] = (0, import_react.useState)(data.modelIds ?? data.models.map((m) => m.id));
794
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: (e) => {
795
- e.preventDefault();
796
- void save(follow ? null : selected);
797
- }, children: [
798
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
799
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
800
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: follow, disabled: busy, onChange: (e) => setFollow(e.target.checked) }),
801
- "\u8DDF\u968F\u8DEF\u7531\u5C55\u793A\uFF08\u65B0\u53D1\u73B0\u7684\u514D\u8D39\u6A21\u578B\u4E5F\u81EA\u52A8\u5F00\u653E\uFF09"
802
- ] }),
803
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
804
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || follow, onClick: () => setSelected(data.choices.map((m) => m.id)), children: "\u5168\u9009" }),
805
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || follow, onClick: () => setSelected([]), children: "\u5168\u4E0D\u9009" })
806
- ] }),
807
- data.choices.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
808
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", disabled: busy || follow, checked: follow ? m.visible : selected.includes(m.id), onChange: (e) => setSelected(e.target.checked ? [...selected, m.id] : selected.filter((id) => id !== m.id)) }),
809
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
810
- m.name,
811
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "mono muted", style: { overflowWrap: "anywhere" }, children: m.id })
812
- ] })
813
- ] }, m.id)),
814
- !data.choices.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u8BF7\u5148\u6DFB\u52A0\u8DEF\u7531\u3002" })
815
- ] }),
816
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "modal-foot row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy, children: "\u4FDD\u5B58\u5F00\u653E\u8303\u56F4" }) })
817
- ] });
818
- }
819
- function ModelsPanel({ error = "", notice = "", data, provider, providerSelect, search, setSearch, busy, act }) {
820
- const [editing, setEditing] = (0, import_react.useState)(null), [testing, setTesting] = (0, import_react.useState)(null), [testResult, setTestResult] = (0, import_react.useState)(null);
821
- const models = data.providers.find((p) => p.id === provider)?.models ?? [];
822
- const all = data.providers.flatMap((p) => p.models), shown = models.filter((m) => `${m.id} ${m.name}`.toLowerCase().includes(search.toLowerCase()));
823
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
824
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
825
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
826
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u539F\u59CB\u6A21\u578B\u5C55\u793A" }),
827
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
828
- "\u5DF2\u5C55\u793A ",
829
- all.filter((m) => m.visible).length,
830
- " / ",
831
- all.length,
832
- " \u4E2A \xB7 \u9ED8\u8BA4\u4EC5\u5C55\u793A\u7EDF\u4E00\u8DEF\u7531"
833
- ] })
834
- ] }),
835
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
836
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
837
- void act({ action: "models.visibility", visible: true });
838
- }, children: "\u5168\u90E8\u5C55\u793A" }),
839
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
840
- void act({ action: "models.visibility", visible: false });
841
- }, children: "\u5168\u90E8\u9690\u85CF\uFF08\u4EC5\u8DEF\u7531\uFF09" })
842
- ] })
843
- ] }),
844
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar toolbar", children: [
845
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
846
- providerSelect,
847
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "search", children: [
848
- "\u641C\u7D22\u6A21\u578B",
849
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "search", placeholder: "\u540D\u79F0\u6216\u6A21\u578B ID", value: search, onChange: (e) => setSearch(e.target.value) })
850
- ] })
851
- ] }),
852
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
853
- void act({ action: "refresh", provider });
854
- }, children: "\u83B7\u53D6\u6A21\u578B\u76EE\u5F55" })
855
- ] }),
856
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box table-shell", children: [
857
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", role: "region", "aria-label": "\u6A21\u578B\u5C55\u793A\u7BA1\u7406", tabIndex: "0", children: [
858
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table model-table", children: [
859
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
860
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u6A21\u578B" }),
861
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u4E0A\u4E0B\u6587 / \u63A8\u7406" }),
862
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u9009\u62E9\u5668\u5C55\u793A" }),
863
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "cell-actions", children: "\u7BA1\u7406" })
864
- ] }) }),
865
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: shown.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: m.visible ? "selected" : "", children: [
866
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
867
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: m.name }),
868
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "mono muted", children: m.id })
869
- ] }),
870
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
871
- capacity(m.contextWindow),
872
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { className: "muted", children: [
873
- "\u6700\u5927 ",
874
- capacity(m.maxContextWindow ?? m.contextWindow),
875
- " \xB7 \u8F93\u51FA ",
876
- capacity(m.maxTokens),
877
- m.supportsImages ? " \xB7 \u56FE\u7247" : ""
878
- ] }),
879
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: m.reasoning?.supportedEfforts?.length ? m.reasoning.supportedEfforts.map((e) => effortNames[e] || e).join(" / ") : "\u5E73\u53F0\u9ED8\u8BA4" })
880
- ] }),
881
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
882
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", "aria-label": `\u5C55\u793A ${m.name}`, disabled: busy, checked: m.visible, onChange: (e) => {
883
- void act({ action: "model.update", provider, id: m.id, visible: e.target.checked });
884
- } }),
885
- m.visible ? "\u5DF2\u5C55\u793A" : "\u5DF2\u9690\u85CF"
886
- ] }) }),
887
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { className: "cell-actions", children: [
888
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => setEditing({ id: m.id, name: m.name, provider, contextWindow: m.configuredContextWindow ?? null, supportsImages: m.supportsImages, reasoningEffort: m.configuredEffort ?? null }), children: "\u8BBE\u7F6E" }),
889
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
890
- setTesting(m);
891
- setTestResult(null);
892
- }, children: "\u6D4B\u8BD5" })
893
- ] })
894
- ] }, m.id)) })
895
- ] }),
896
- !shown.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: models.length ? "\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B\u3002" : "\u6DFB\u52A0\u5E76\u542F\u7528\u8D26\u53F7\u540E\uFF0C\u83B7\u53D6\u6A21\u578B\u76EE\u5F55\u3002" })
897
- ] }),
898
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "table-footer", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u4E0A\u4E0B\u6587\u9ED8\u8BA4\u6700\u5927\uFF0C\u53EF\u5728\u8BBE\u7F6E\u4E2D\u8C03\u4F4E\uFF1B\u539F\u59CB\u6A21\u578B\u4E0E\u8DEF\u7531\u9884\u7B97\u72EC\u7ACB\u3002\u9690\u85CF\u4E0D\u5F71\u54CD\u8DEF\u7531\u6216\u5DF2\u6709\u4F1A\u8BDD\u3002" }) })
899
- ] }),
900
- editing && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: "\u6A21\u578B\u8BBE\u7F6E", busy, close: () => setEditing(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModelSettings, { error, notice, model: models.find((m) => m.id === editing.id), draft: editing, setDraft: setEditing, busy, save: async () => {
901
- if (await act({ action: "model.update", ...editing })) setEditing(null);
902
- } }) }),
903
- testing && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Modal, { title: `\u6D4B\u8BD5 ${testing.name}`, busy, close: () => {
904
- setTesting(null);
905
- setTestResult(null);
906
- }, children: [
907
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
908
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
909
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "\u53D1\u9001\u4E00\u6761\u7B80\u77ED\u8BF7\u6C42\uFF0C\u6B63\u5E38\u6D88\u8017\u76EE\u6807\u8D26\u53F7\u7684\u7528\u91CF\u3002\u6B64\u6D4B\u8BD5\u4EC5\u68C0\u67E5\u8FDE\u901A\u6027\uFF0C\u4E0D\u4EE3\u8868\u5DF2\u9A8C\u8BC1\u6EE1\u4E0A\u4E0B\u6587\u6216\u56FE\u7247\u8BC6\u522B\u80FD\u529B\u3002" }),
910
- testResult && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: testResult.ok ? "good" : "warn", children: testResult.ok ? `\u53EF\u7528 \xB7 ${testResult.elapsedMs} ms` : `\u6D4B\u8BD5\u5931\u8D25\uFF08HTTP ${testResult.status}\uFF09\xB7 ${testResult.hint}` })
911
- ] }),
912
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "modal-foot row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: async () => {
913
- setTestResult(null);
914
- const result = await act({ action: "model.test", provider, id: testing.id });
915
- if (result) setTestResult(result.modelTest);
916
- }, children: busy ? "\u6B63\u5728\u6D4B\u8BD5\u2026" : "\u5F00\u59CB\u6D4B\u8BD5" }) })
917
- ] })
918
- ] });
919
- }
920
- var capacity = (n) => n >= 1e6 && n % 1e6 === 0 ? `${n / 1e6}M` : `${fmt(n / 1e3)}K`;
921
- function ContextSelect({ model, value, onChange, disabled, label = "\u4E0A\u4E0B\u6587\u9884\u7B97" }) {
922
- const max = model.maxContextWindow ?? model.contextWindow;
923
- const choices = [...new Set([model.defaultContextWindow, ...model.supportedContextWindows ?? [], 2e5, 3e5, 5e5, 6e5, value].filter((n) => Number.isSafeInteger(n) && n > 0 && n <= max))].sort((a, b) => a - b);
924
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
925
- label,
926
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { "aria-label": label, disabled, value: value ?? "", onChange: (e) => onChange(e.target.value ? Number(e.target.value) : null), children: [
927
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: "", children: [
928
- "\u6700\u5927\u5BB9\u91CF \xB7 ",
929
- capacity(max),
930
- "\uFF08\u9ED8\u8BA4\uFF09"
931
- ] }),
932
- choices.map((n) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: n, children: [
933
- capacity(n),
934
- n === model.defaultContextWindow ? " \xB7 \u6E20\u9053\u9ED8\u8BA4" : " \xB7 \u672C\u5730\u9884\u7B97"
935
- ] }, n))
936
- ] })
937
- ] });
938
- }
939
- function ModelSettings({ error = "", notice = "", model, draft, setDraft, busy, save }) {
940
- const set = (key, value) => setDraft((d) => ({ ...d, [key]: value }));
941
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: (e) => {
942
- e.preventDefault();
943
- void save();
944
- }, children: [
945
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
946
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
947
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
948
- "\u6A21\u578B\u540D\u79F0",
949
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { autoFocus: true, required: true, maxLength: 200, disabled: busy, value: draft.name, onChange: (e) => set("name", e.target.value) })
950
- ] }),
951
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mono muted", children: model.id }),
952
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextSelect, { model, value: draft.contextWindow, disabled: busy, onChange: (n) => set("contextWindow", n) }),
953
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
954
- "\u6700\u5927\u4E0A\u4E0B\u6587 ",
955
- capacity(model.maxContextWindow),
956
- " \xB7 \u6700\u5927\u8F93\u51FA ",
957
- capacity(model.maxTokens),
958
- "\u3002\u624B\u52A8\u9884\u7B97\u53EA\u8C03\u4F4E DSH \u7684\u4F1A\u8BDD\u538B\u7F29\u9608\u503C\uFF1B\u8BF7\u6C42\u4F7F\u7528\u80FD\u591F\u5BB9\u7EB3\u8BE5\u9884\u7B97\u7684\u6E20\u9053\u6863\u4F4D\u3002"
959
- ] }),
960
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
961
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", disabled: busy || !model.imageCapable, checked: draft.supportsImages, onChange: (e) => set("supportsImages", e.target.checked) }),
962
- "\u56FE\u7247\u8F93\u5165",
963
- !model.imageCapable && "\uFF08\u6E20\u9053\u672A\u58F0\u660E\u652F\u6301\uFF09"
964
- ] }),
965
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
966
- "\u9ED8\u8BA4\u63A8\u7406\u7B49\u7EA7",
967
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { disabled: busy, value: draft.reasoningEffort ?? "", onChange: (e) => set("reasoningEffort", e.target.value || null), children: [
968
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5E73\u53F0\u9ED8\u8BA4" }),
969
- model.reasoning?.supportedEfforts?.map((e) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: e, children: effortNames[e] || e }, e))
970
- ] })
971
- ] }),
972
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5173\u95ED\u601D\u8003\u4EC5\u5728\u6E20\u9053\u58F0\u660E\u652F\u6301\u65F6\u63D0\u4F9B\u3002\u4F1A\u8BDD\u4E2D\u7684\u624B\u52A8\u9009\u62E9\u4F18\u5148\u4E8E\u6B64\u9ED8\u8BA4\u503C\u3002" })
973
- ] }),
974
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "modal-foot row", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy, children: "\u4FDD\u5B58\u5E76\u751F\u6548" }) })
975
- ] });
976
- }
977
- function RoutesTable({ data, busy, act, edit }) {
978
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: "box table-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", role: "region", "aria-label": "\u6A21\u578B\u8DEF\u7531\u89C4\u5219", tabIndex: "0", children: [
979
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table route-table", children: [
980
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
981
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u8DEF\u7531 / \u6A21\u578B" }),
982
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u8D26\u53F7\u4E0E\u6E20\u9053" }),
983
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u5207\u6362\u89C4\u5219" }),
984
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u5C55\u793A" }),
985
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "cell-actions", children: "\u7BA1\u7406" })
986
- ] }) }),
987
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: data.routes.map((r) => {
988
- const accounts = data.accounts.filter((a) => a.enabled !== false && (!r.eligibleAccountIds || r.eligibleAccountIds.includes(a.id)) && r.targets.some((t) => t.provider === a.provider && (!t.account || t.account === a.id)));
989
- const providers = [...new Set(r.targets.map((t) => data.providers.find((p) => p.id === t.provider)?.name || t.provider))];
990
- const cooling = r.expiringStatus?.cooldownUntil > Date.now(), modes = r.reasoning?.supportedEfforts ?? [];
991
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: r.visible !== false ? "selected" : "", children: [
992
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
993
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: r.name }),
994
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: r.contextKnown === false ? "\u7B49\u5F85\u6A21\u578B\u76EE\u5F55" : `${capacity(r.contextWindow)} \u4E0A\u4E0B\u6587 \xB7 ${r.contextMode === "custom" ? "\u81EA\u5B9A\u4E49\u9884\u7B97" : "\u9ED8\u8BA4\u6700\u5927"}` }),
995
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: r.freeOnly ? `${r.freeStatus?.modelRoutes?.filter((m) => m.selected).length || 0} \u4E2A\u514D\u8D39\u6A21\u578B\u5DF2\u5C55\u793A` : modes.length ? `\u63A8\u7406\uFF1A${modes.map((e) => effortNames[e] || e).join(" / ")}` : "\u63A8\u7406\uFF1A\u5E73\u53F0\u9ED8\u8BA4" })
996
- ] }),
997
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { className: "route-targets", children: [
998
- accounts.length,
999
- " \u4E2A\u53C2\u4E0E\u8D26\u53F7",
1000
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: providers.join("\u3001") })
1001
- ] }),
1002
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1003
- r.freeOnly ? "\u4EC5\u514D\u8D39 \xB7 \u81EA\u52A8\u53D1\u73B0" : strategies[r.strategy || "failover"],
1004
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: cooling ? "warn" : "muted", children: cooling ? "\u4E34\u671F\u4F18\u5148\u51B7\u5374\u4E2D" : r.preferExpiringCredits ? "\u4E34\u671F\u79EF\u5206\u4F18\u5148" : `${r.targets.length} \u4E2A\u76EE\u6807 \xB7 4xx \u5207\u6362` })
1005
- ] }),
1006
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
1007
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", "aria-label": `\u5C55\u793A\u8DEF\u7531 ${r.name}`, disabled: busy, checked: r.visible !== false, onChange: (e) => {
1008
- const { id, reasoning, supportsImages, expiringStatus, freeStatus, creditRates, maxContextWindow, supportedContextWindows, configuredContextWindow, contextKnown, eligibleAccountIds, enforceContext, ...route } = r;
1009
- void act({ action: "route.save", id, previousId: id, route: { ...route, visible: e.target.checked } });
1010
- } }),
1011
- r.visible !== false ? "\u5F00\u542F" : "\u5173\u95ED"
1012
- ] }) }),
1013
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "cell-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => edit(r), children: r.freeOnly ? "\u7BA1\u7406\u514D\u8D39\u6A21\u578B" : "\u7F16\u8F91\u8DEF\u7531" }) })
1014
- ] }, r.id);
1015
- }) })
1016
- ] }),
1017
- !data.routes.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: "\u6DFB\u52A0\u6A21\u578B\u9884\u914D\u7F6E\uFF0C\u6216\u521B\u5EFA\u81EA\u5B9A\u4E49\u8DEF\u7531\u3002" })
1018
- ] }) });
1019
- }
1020
- var displayName = (a) => (a?.name || a?.id || "\u672A\u77E5\u8D26\u53F7").replace(/(?<!\d)(\+?\d{2,3})\d{3,8}(\d{4})(?!\d)/g, "$1****$2");
1021
- var resultLabels = { claimed: "\u7B7E\u5230\u6210\u529F", "already-claimed": "\u5DF2\u9886\u53D6", "no-campaign": "\u65E0\u6D3B\u52A8", retryable: "\u67E5\u8BE2\u5931\u8D25", "before-window": "\u7A97\u53E3\u672A\u5F00", "auth-invalid": "\u4EE4\u724C\u5931\u6548", paused: "\u5E73\u53F0\u6682\u505C", uncertain: "\u5F85\u6838\u5BF9", "device-used": "\u8BBE\u5907\u5DF2\u53C2\u4E0E" };
1022
- function Balance({ account }) {
1023
- const b = account.usage?.balance, now = Date.now();
1024
- const expiring = b?.unit === "credits" && !b.error ? (b.packages || []).filter((p) => Number.isFinite(p.remaining) && p.remaining > 0 && p.expiresAt > now && p.expiresAt <= now + 3 * 864e5).reduce((n, p) => n + p.remaining, 0) : 0;
1025
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1026
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "amount", children: [
1027
- b?.unlimited ? "\u4E0D\u9650\u91CF" : fmt(b?.remaining),
1028
- b?.unit === "credits" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", style: { display: "inline", marginLeft: 5 }, children: "\u79EF\u5206" })
1029
- ] }),
1030
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: b?.error ? "error" : expiring ? "warn" : "muted", children: b?.error ? "\u67E5\u8BE2\u5931\u8D25 \xB7 \u4FDD\u7559\u4E0A\u6B21\u4F59\u989D" : expiring ? `${fmt(expiring)} \u79EF\u5206 3 \u5929\u5185\u5230\u671F` : b?.fetchedAt ? `\u66F4\u65B0\u4E8E ${when(b.fetchedAt)}` : "\u7B49\u5F85\u5237\u65B0\u5E73\u53F0\u7528\u91CF" })
1031
- ] });
1032
- }
1033
- function CheckinResult({ row, compact = false }) {
1034
- const last = row?.last, today = (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" });
1035
- const current = last?.day === today;
1036
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1037
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: current && ["claimed", "already-claimed"].includes(last.status) ? "good" : last && ["auth-invalid", "paused", "uncertain", "retryable"].includes(last.status) ? "warn" : "muted", children: !row?.supported ? "\u6682\u4E0D\u652F\u6301" : current || last?.status === "auth-invalid" ? resultLabels[last.status] || "\u5DF2\u5904\u7406" : "\u4ECA\u65E5\u672A\u7B7E\u5230" }),
1038
- (!compact || current && last.amount !== void 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: current && last.amount !== void 0 ? `\u672C\u6B21 ${fmt(last.amount)} \u79EF\u5206` : row?.auto ? "\u81EA\u52A8\u7B7E\u5230\u5DF2\u5F00\u542F" : "\u81EA\u52A8\u7B7E\u5230\u672A\u5F00\u542F" })
1039
- ] });
1040
- }
1041
- function AccountPool({ data, provider, providerSelect, busy, act, manage, add }) {
1042
- const [search, setSearch] = (0, import_react.useState)("");
1043
- const accounts = data.accounts.filter((a) => !provider || a.provider === provider), chosen = accounts.filter((a) => a.enabled !== false).length;
1044
- const visible = accounts.filter((a) => `${a.name} ${a.id}`.toLowerCase().includes(search.toLowerCase()));
1045
- const rows = data.checkins?.accounts || [], eligible = rows.filter((r) => accounts.some((a) => a.id === r.id && a.enabled !== false) && r.ready);
1046
- const setAll = (enabled) => {
1047
- void act({ action: "accounts.enabled", ...provider ? { provider } : {}, enabled });
1048
- };
1049
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
1050
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1051
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1052
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "section-title", children: "\u8D26\u53F7\u6C60" }),
1053
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "muted", children: [
1054
- accounts.length,
1055
- " \u4E2A\u8D26\u53F7 \xB7 ",
1056
- chosen,
1057
- " \u4E2A\u53C2\u4E0E\u8DEF\u7531"
1058
- ] })
1059
- ] }),
1060
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy, onClick: add, children: "\u6DFB\u52A0\u8D26\u53F7" })
1061
- ] }),
1062
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar toolbar", children: [
1063
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1064
- providerSelect,
1065
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "search", children: [
1066
- "\u641C\u7D22\u8D26\u53F7",
1067
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "search", value: search, placeholder: "\u540D\u79F0\u6216\u8D26\u53F7 ID", onChange: (e) => setSearch(e.target.value) })
1068
- ] })
1069
- ] }),
1070
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1071
- !provider?.startsWith("qoder") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
1072
- void act({ action: "accounts.discover", ...provider ? { provider } : {} });
1073
- }, children: "\u83B7\u53D6\u672C\u673A\u767B\u5F55" }),
1074
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
1075
- void act({ action: "monitor.refresh", ...provider ? { provider } : {} });
1076
- }, children: "\u5237\u65B0\u72B6\u6001\u4E0E\u7528\u91CF" })
1077
- ] })
1078
- ] }),
1079
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1080
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "hint", children: "\u52FE\u9009\u7684\u8D26\u53F7\u53C2\u4E0E\u8DEF\u7531\uFF1B\u81EA\u52A8\u7B7E\u5230\u5728\u300C\u79EF\u5206\u7B7E\u5230\u300D\u4E2D\u5355\u72EC\u8BBE\u7F6E\u3002" }),
1081
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1082
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "notice", children: [
1083
- "\u5DF2\u9009 ",
1084
- chosen,
1085
- " / ",
1086
- accounts.length
1087
- ] }),
1088
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy || !accounts.length || chosen === accounts.length, onClick: () => setAll(true), children: "\u5168\u9009" }),
1089
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy || !chosen, onClick: () => setAll(false), children: "\u5168\u4E0D\u9009" }),
1090
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { disabled: busy || data.checkins?.running || data.checkins?.error || !eligible.length, onClick: () => {
1091
- void act({ action: "checkins.run", ids: eligible.map((r) => r.id) });
1092
- }, children: [
1093
- "\u7B7E\u5230\u53EF\u7528\u8D26\u53F7\uFF08",
1094
- eligible.length,
1095
- "\uFF09"
1096
- ] })
1097
- ] })
1098
- ] }),
1099
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: "box table-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", role: "region", "aria-label": "\u8D26\u53F7\u6C60\u5217\u8868", tabIndex: "0", children: [
1100
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
1101
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
1102
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u8D26\u53F7 / \u8DEF\u7531\u53C2\u4E0E" }),
1103
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u5E73\u53F0\u79EF\u5206" }),
1104
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u6A21\u578B\u4E0E\u8C03\u7528" }),
1105
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u4ECA\u65E5\u7B7E\u5230" }),
1106
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "cell-actions", children: "\u7BA1\u7406" })
1107
- ] }) }),
1108
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: visible.map((a) => {
1109
- const cooldown = a.status?.cooldowns || [], active = a.status?.activeFor?.length, enabled = a.enabled !== false;
1110
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: enabled ? "selected" : "", children: [
1111
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "account-cell", children: [
1112
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "check account-check", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { "aria-label": `${displayName(a)} \u53C2\u4E0E\u8DEF\u7531`, type: "checkbox", disabled: busy, checked: enabled, onChange: (e) => {
1113
- void act({ action: "account.update", id: a.id, enabled: e.target.checked });
1114
- } }) }),
1115
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "account-name", children: [
1116
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: displayName(a) }),
1117
- !provider && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: data.providers?.find((p) => p.id === a.provider)?.name || a.provider }),
1118
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "status", children: [
1119
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { className: !enabled ? "" : cooldown.length ? "warn" : "good", "aria-hidden": "true" }),
1120
- !enabled ? "\u672A\u5165\u6C60" : active ? "\u6B63\u5728\u8C03\u7528" : cooldown.length ? "\u90E8\u5206\u8DEF\u7531\u51B7\u5374\u4E2D" : "\u5DF2\u5728\u6C60\u4E2D"
1121
- ] }) }),
1122
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: loginNames[a.login?.state] || "\u5C1A\u672A\u67E5\u8BE2\u767B\u5F55" })
1123
- ] })
1124
- ] }) }),
1125
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Balance, { account: a }) }),
1126
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1127
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
1128
- fmt(a.modelCount || 0),
1129
- " \u4E2A\u76EE\u5F55\u6A21\u578B"
1130
- ] }),
1131
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { className: "muted", children: [
1132
- fmt(a.usage?.requests || 0),
1133
- " \u6B21\u8C03\u7528 \xB7 ",
1134
- fmt(a.usage?.tokens || 0),
1135
- " Token"
1136
- ] }),
1137
- cooldown.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { className: "warn", children: [
1138
- "\u6700\u957F\u7EA6 ",
1139
- Math.ceil(Math.max(...cooldown.map((c) => c.remainingMs)) / 6e4),
1140
- " \u5206\u949F\u540E\u6062\u590D"
1141
- ] })
1142
- ] }),
1143
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CheckinResult, { row: rows.find((r) => r.id === a.id) }) }),
1144
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "cell-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => manage(a), children: "\u7BA1\u7406\u8D26\u53F7" }) })
1145
- ] }, a.id);
1146
- }) })
1147
- ] }),
1148
- !visible.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: accounts.length ? "\u6CA1\u6709\u5339\u914D\u7684\u8D26\u53F7\uFF0C\u8BF7\u8C03\u6574\u641C\u7D22\u3002" : "\u8FD8\u6CA1\u6709\u8D26\u53F7\uFF0C\u70B9\u51FB\u300C\u6DFB\u52A0\u8D26\u53F7\u300D\u83B7\u53D6\u767B\u5F55\u6216\u586B\u5199\u51ED\u8BC1\u3002" })
1149
- ] }) }),
1150
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "help", children: [
1151
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u672C\u673A\u8D26\u53F7\u83B7\u53D6\u4E0E\u51ED\u8BC1\u8BF4\u660E" }),
1152
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
1153
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "WorkBuddy \u4E0E Trae \u542F\u52A8\u65F6\u81EA\u52A8\u8BFB\u53D6\u672C\u673A\u5DF2\u767B\u5F55\u8D26\u53F7\uFF0C\u6BCF\u5206\u949F\u91CD\u65B0\u68C0\u6D4B\uFF1BTrae \u81EA\u52A8\u8BC6\u522B CN\u3001Global \u4E0E SOLO\u3002\u4E5F\u53EF\u6DFB\u52A0\u624B\u52A8\u51ED\u8BC1\u6216\u5BFC\u5165\u5176\u5B83\u8BBE\u5907\u8D26\u53F7\uFF0C\u5404\u8D26\u53F7\u72EC\u7ACB\u4FDD\u5B58\u3002Qoder \u9700\u6DFB\u52A0 PAT\u3002" }),
1154
- data.localDiscovery?.filter((s) => !provider || s.provider === provider).map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
1155
- data.providers?.find((p) => p.id === s.provider)?.name || s.provider,
1156
- " \xB7 ",
1157
- s.state === "found" ? "\u5DF2\u53D1\u73B0\u672C\u673A\u5BA2\u6237\u7AEF\u767B\u5F55\u3002" : s.state === "unreadable" ? "\u65E0\u6CD5\u8BFB\u53D6\u672C\u673A\u767B\u5F55\u6587\u4EF6\uFF0C\u8BF7\u5728\u5B98\u65B9\u5BA2\u6237\u7AEF\u91CD\u65B0\u767B\u5F55\uFF0C\u6216\u624B\u52A8\u586B\u5199\u51ED\u8BC1\u3002" : "\u672A\u627E\u5230\u672C\u673A\u767B\u5F55\uFF0C\u8BF7\u5148\u767B\u5F55\u5BF9\u5E94\u533A\u57DF\u7684\u5B98\u65B9\u5BA2\u6237\u7AEF\u3002",
1158
- " \xB7 ",
1159
- when(s.checkedAt)
1160
- ] }, s.provider))
1161
- ] })
1162
- ] })
1163
- ] });
1164
- }
1165
- function CheckinPanel({ data, busy, act }) {
1166
- const info = data.checkins || {}, rows = info.accounts || [], today = (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" });
1167
- const saved = info.settings ?? { mode: "scheduled", time: "10:05" };
1168
- const [schedule, setSchedule] = (0, import_react.useState)(saved);
1169
- (0, import_react.useEffect)(() => {
1170
- setSchedule(saved);
1171
- }, [saved.mode, saved.time]);
1172
- const changed = schedule.mode !== saved.mode || schedule.time !== saved.time;
1173
- const blocked = busy || info.running || !!info.error;
1174
- const eligible = rows.filter((r) => r.supported && !r.paused && data.accounts.find((a) => a.id === r.id)?.enabled && r.ready === true);
1175
- const ready = (r) => eligible.includes(r);
1176
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
1177
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
1178
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1179
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1180
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u6BCF\u65E5\u79EF\u5206\u7B7E\u5230" }),
1181
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: info.schedule }),
1182
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u81EA\u52A8\u7B7E\u5230\u9ED8\u8BA4\u5173\u95ED\uFF0C\u8BF7\u5728\u4E0B\u65B9\u9010\u4E2A\u5F00\u542F\u3002" })
1183
- ] }),
1184
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: "primary", disabled: blocked || !eligible.length, onClick: () => {
1185
- void act({ action: "checkins.run", ids: eligible.map((r) => r.id) });
1186
- }, children: [
1187
- "\u7B7E\u5230\u5168\u90E8\u53EF\u7528\u8D26\u53F7\uFF08",
1188
- eligible.length,
1189
- "\uFF09"
1190
- ] })
1191
- ] }),
1192
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "row plan-form", onSubmit: (e) => {
1193
- e.preventDefault();
1194
- void act({ action: "checkins.settings", schedule });
1195
- }, children: [
1196
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1197
- "\u81EA\u52A8\u7B7E\u5230\u65B9\u5F0F",
1198
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { "aria-label": "\u81EA\u52A8\u7B7E\u5230\u65B9\u5F0F", value: schedule.mode, disabled: blocked, onChange: (e) => setSchedule({ ...schedule, mode: e.target.value }), children: [
1199
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "startup", children: "\u6BCF\u65E5\u542F\u52A8\u65F6\u7B7E\u5230" }),
1200
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "scheduled", children: "\u6BCF\u5929\u5B9A\u65F6\u7B7E\u5230" })
1201
- ] })
1202
- ] }),
1203
- schedule.mode === "scheduled" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1204
- "\u7B7E\u5230\u65F6\u95F4\uFF08\u5317\u4EAC\u65F6\u95F4\uFF09",
1205
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { "aria-label": "\u7B7E\u5230\u65F6\u95F4\uFF08\u5317\u4EAC\u65F6\u95F4\uFF09", type: "time", required: true, value: schedule.time, disabled: blocked, onChange: (e) => setSchedule({ ...schedule, time: e.target.value }) })
1206
- ] }),
1207
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked || !changed, children: "\u4FDD\u5B58\u7B7E\u5230\u8BA1\u5212" })
1208
- ] }),
1209
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "help", children: [
1210
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u6267\u884C\u89C4\u5219\u3001\u8865\u67E5\u4E0E\u8BBE\u5907\u9650\u5236" }),
1211
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
1212
- " ",
1213
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u81EA\u52A8\u7B7E\u5230\u9ED8\u8BA4\u5173\u95ED\uFF0C\u6309\u8D26\u53F7\u5F00\u542F\u3002\u5148\u67E5\u9886\u53D6\u72B6\u6001\u3001\u4E32\u884C\u63D0\u4EA4\uFF0C\u8D26\u53F7\u95F4\u9694\u81F3\u5C11 10 \u79D2\uFF1B\u6BCF\u4E2A\u8D26\u53F7\u6BCF\u5929\u6700\u591A\u63D0\u4EA4\u4E00\u6B21\u9886\u53D6\u3002\u786E\u8BA4\u5C1A\u672A\u63D0\u4EA4\u7684\u67E5\u8BE2\u5931\u8D25\uFF0C20:05 \u540E\u6700\u591A\u8865\u67E5\u4E00\u6B21\uFF1B\u5DF2\u9886\u53D6\u3001\u65E0\u6D3B\u52A8\u548C\u7ED3\u679C\u4E0D\u660E\u7684\u8D26\u53F7\u8DF3\u8FC7\u3002\u9047\u5230\u9A8C\u8BC1\u3001\u9650\u6D41\u6216\u8BBE\u5907\u9650\u5236\u5C31\u505C\u6B62\uFF0C\u4E0D\u4F1A\u4FEE\u6539\u8BBE\u5907\u8EAB\u4EFD\u6216\u5207\u6362\u8D26\u53F7\u91CD\u8BD5\u3002" }),
1214
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u542F\u52A8\u6A21\u5F0F\u5728\u5F53\u5929\u9996\u6B21\u8FD0\u884C\u65F6\u6267\u884C\uFF0C\u6301\u7EED\u8FD0\u884C\u5219\u65B0\u4E00\u5929\u81EA\u52A8\u6267\u884C\uFF1B\u5B9A\u65F6\u6A21\u5F0F\u5728\u8BBE\u5B9A\u65F6\u95F4\u540E\u6267\u884C\uFF0C\u9519\u8FC7\u65F6\u4E0B\u6B21\u542F\u52A8\u8865\u67E5\u3002Qoder \u6700\u65E9\u5317\u4EAC\u65F6\u95F4 10:05 \u67E5\u8BE2\u5F53\u65E5\u6D3B\u52A8\u3002DSH \u5173\u95ED\u671F\u95F4\u4E0D\u6267\u884C\uFF0C\u8FD0\u884C\u65F6\u7EA6\u4E00\u5206\u949F\u5185\u89E6\u53D1\u3002\u4FEE\u6539\u8BA1\u5212\u3001\u5237\u65B0\u9762\u677F\u6216\u91CD\u542F\u4E0D\u4F1A\u6E05\u9664\u5DF2\u5904\u7406\u8BB0\u5F55\uFF1B\u4EE4\u724C\u5931\u6548\u540E\u8BF7\u66F4\u65B0\u51ED\u8BC1\u518D\u6062\u590D\u3002" })
1215
- ] })
1216
- ] }),
1217
- info.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: "error", children: info.error }),
1218
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: info.running ? `\u6B63\u5728\u5904\u7406 ${displayName(data.accounts.find((a) => a.id === info.current)) || "\u7B7E\u5230\u961F\u5217"}\u2026` : "\u7B7E\u5230\u7ED3\u679C\u548C\u9886\u53D6\u79EF\u5206\u4EE5\u4E0B\u65B9\u5E73\u53F0\u54CD\u5E94\u4E3A\u51C6\u3002" }),
1219
- info.report && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
1220
- "\u6700\u8FD1\u4E00\u8F6E \xB7 ",
1221
- when(info.report.at),
1222
- " \xB7 ",
1223
- Object.entries(info.report.counts || {}).map(([key, n]) => `${resultLabels[key] || "\u672A\u5B8C\u6210"} ${n}`).join(" \xB7 "),
1224
- "\u3002\u6CA1\u6709\u5F85\u8865\u67E5\u8D26\u53F7\u65F6\u4E0D\u91CD\u590D\u6C47\u62A5\u3002"
1225
- ] })
1226
- ] }),
1227
- data.providers.map((p) => {
1228
- const accounts = data.accounts.filter((a) => a.provider === p.id);
1229
- if (!accounts.length) return null;
1230
- const supported = rows.some((r) => r.id === accounts[0].id && r.supported), paused = rows.some((r) => accounts.some((a) => a.id === r.id) && r.paused);
1231
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
1232
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1233
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: p.name }),
1234
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "badge", children: supported ? paused ? "\u5DF2\u6682\u505C" : "\u652F\u6301\u7B7E\u5230" : "\u5B98\u65B9\u5BA2\u6237\u7AEF\u9886\u53D6" })
1235
- ] }),
1236
- !supported ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: p.id.startsWith("workbuddy") ? "WorkBuddy AI \u6682\u672A\u63A5\u5165\u53EF\u6838\u9A8C\u7684\u7B7E\u5230\u63A5\u53E3\uFF0C\u8BF7\u5728\u5B98\u65B9\u5BA2\u6237\u7AEF\u67E5\u770B\u6D3B\u52A8\u4E0E\u9886\u53D6\u5165\u53E3\u3002" : "Trae Global \u6682\u65E0\u5DF2\u6838\u9A8C\u7684\u79EF\u5206\u7B7E\u5230\u63A5\u53E3\uFF0C\u8BF7\u5728\u5B98\u65B9\u5BA2\u6237\u7AEF\u67E5\u770B\u6743\u76CA\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1237
- paused && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "steps", children: [
1238
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "\u5E73\u53F0\u9650\u5236\u6216\u9700\u8981\u9A8C\u8BC1\uFF0C\u5DF2\u6682\u505C\u8BE5\u5E73\u53F0\u7B7E\u5230\u3002\u8BF7\u5728\u5B98\u65B9\u5BA2\u6237\u7AEF\u5904\u7406\u540E\u518D\u6062\u590D\uFF1B\u6062\u590D\u4ECD\u4FDD\u7559\u4ECA\u65E5\u5C1D\u8BD5\u8BB0\u5F55\u548C\u8BBE\u5907\u9650\u5236\u3002" }),
1239
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked, onClick: () => {
1240
- void act({ action: "checkins.resume", provider: p.id });
1241
- }, children: "\u6211\u5DF2\u5728\u5B98\u65B9\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u6062\u590D\u540E\u7EED\u7B7E\u5230" })
1242
- ] }),
1243
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "scroll", role: "region", "aria-label": `${p.name} \u7B7E\u5230\u8BB0\u5F55`, tabIndex: "0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
1244
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
1245
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u8D26\u53F7" }),
1246
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u81EA\u52A8\u7B7E\u5230" }),
1247
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u4ECA\u65E5\u7ED3\u679C" }),
1248
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u6700\u8FD1\u8BB0\u5F55" }),
1249
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "cell-actions", children: "\u64CD\u4F5C" })
1250
- ] }) }),
1251
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: accounts.map((a) => {
1252
- const r = rows.find((r2) => r2.id === a.id) || {}, last = r.last?.day === today ? r.last : void 0;
1253
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: info.current === a.id ? "selected" : "", children: [
1254
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1255
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: displayName(a) }),
1256
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: a.enabled === false ? "\u8D26\u53F7\u5DF2\u505C\u7528" : "\u5DF2\u5728\u8D26\u53F7\u6C60\u4E2D" })
1257
- ] }),
1258
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
1259
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { "aria-label": `${displayName(a)} \u6BCF\u65E5\u81EA\u52A8\u7B7E\u5230`, type: "checkbox", disabled: blocked, checked: r.auto === true, onChange: (e) => {
1260
- void act({ action: "account.update", id: a.id, autoCheckin: e.target.checked });
1261
- } }),
1262
- "\u6BCF\u65E5\u81EA\u52A8\u7B7E\u5230"
1263
- ] }) }),
1264
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CheckinResult, { row: r, compact: true }) }),
1265
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1266
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: r.last ? when(r.last.at) : "\u5C1A\u65E0\u8BB0\u5F55" }),
1267
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: r.last?.message || "\u7B49\u5F85\u9996\u6B21\u7B7E\u5230" }),
1268
- last?.retryAt && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { className: "warn", children: [
1269
- "\u8865\u67E5\u65F6\u95F4 ",
1270
- when(last.retryAt)
1271
- ] }),
1272
- r.last?.activity && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [
1273
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u6D3B\u52A8\u8BE6\u60C5" }),
1274
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: [r.last.activity.streakDays !== void 0 && `\u8FDE\u7B7E ${fmt(r.last.activity.streakDays)} \u5929`, r.last.activity.totalCredits !== void 0 && `\u6D3B\u52A8\u7D2F\u8BA1 ${fmt(r.last.activity.totalCredits)} \u79EF\u5206`, r.last.activity.nextStreakDay !== void 0 && `\u4E0B\u4E00\u8FDE\u7B7E\u6863\u4F4D ${fmt(r.last.activity.nextStreakDay)} \u5929`, r.last.activity.endsAt !== void 0 && `\u6D3B\u52A8\u622A\u6B62 ${when(r.last.activity.endsAt)}`].filter(Boolean).join(" \xB7 ") })
1275
- ] })
1276
- ] }),
1277
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "cell-actions", children: p.id === "workbuddy" && r.last?.status === "auth-invalid" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked, onClick: () => {
1278
- void act({ action: "checkins.verify", id: a.id });
1279
- }, children: "\u91CD\u65B0\u9A8C\u8BC1\u767B\u5F55" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked || !ready(r), onClick: () => {
1280
- void act({ action: "checkins.run", ids: [a.id] });
1281
- }, children: r.last?.status === "auth-invalid" ? "\u8BF7\u66F4\u65B0\u51ED\u8BC1" : last?.retryReady ? "\u8865\u67E5\u7B7E\u5230" : last?.retryAt ? "\u7B49\u5F85\u665A\u95F4\u8865\u67E5" : last ? "\u4ECA\u65E5\u5DF2\u5904\u7406" : "\u7ACB\u5373\u7B7E\u5230" }) })
1282
- ] }, a.id);
1283
- }) })
1284
- ] }) })
1285
- ] })
1286
- ] }, p.id);
1287
- }),
1288
- !data.accounts.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "box empty", children: "\u5148\u5230\u300C\u8D26\u53F7\u4E0E\u767B\u5F55\u300D\u6DFB\u52A0\u8D26\u53F7\uFF0C\u518D\u5F00\u542F\u6BCF\u65E5\u81EA\u52A8\u7B7E\u5230\u3002" }),
1289
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u591A\u53F0\u8BBE\u5907\u7684\u672C\u5730\u8BB0\u5F55\u4E0D\u4F1A\u4E92\u76F8\u540C\u6B65\uFF0C\u6BCF\u6B21\u90FD\u4F1A\u67E5\u8BE2\u5E73\u53F0\u9886\u53D6\u72B6\u6001\uFF1B\u5EFA\u8BAE\u4EC5\u5728\u4E00\u53F0\u5E38\u7528\u8BBE\u5907\u5F00\u542F\u81EA\u52A8\u7B7E\u5230\u3002\u540C\u4E00 Trae \u8BBE\u5907\u6BCF\u5929\u6700\u591A\u5904\u7406\u4E00\u4E2A\u9886\u53D6\u8BF7\u6C42\uFF0C\u91CD\u590D\u8D26\u53F7\u526F\u672C\u4F1A\u53BB\u91CD\uFF1B\u4E0D\u4FDD\u8BC1\u5E73\u53F0\u4E00\u5B9A\u53D1\u653E\u5956\u52B1\u3002" })
1290
- ] });
1291
- }
1292
- function Overview({ data, busy, act, go }) {
1293
- const t = data.telemetry || {}, today = t.days?.[t.today] || {}, totals = data.accounts.reduce((s, a) => ({ requests: s.requests + (a.usage?.requests || 0), tokens: s.tokens + (a.usage?.tokens || 0) }), { requests: 0, tokens: 0 });
1294
- const dates = Array.from({ length: 7 }, (_, i) => {
1295
- const d = /* @__PURE__ */ new Date();
1296
- d.setDate(d.getDate() - 6 + i);
1297
- const key = d.toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" });
1298
- return { key, tokens: t.days?.[key]?.tokens || 0 };
1299
- });
1300
- const max = Math.max(1, ...dates.map((d) => d.tokens));
1301
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
1302
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "metrics", children: [
1303
- metric("\u4ECA\u65E5 Token", fmt(today.tokens || 0), "\u8F93\u5165 + \u8F93\u51FA \xB7 \u5317\u4EAC\u65F6\u95F4"),
1304
- metric("\u4ECA\u65E5\u8BF7\u6C42", fmt(today.requests || 0), `\u5931\u8D25 ${fmt(today.failures || 0)} \u6B21`),
1305
- metric("\u8D26\u53F7\u6C60", `${data.accounts.filter((a) => a.enabled).length} / ${data.accounts.length}`, "\u542F\u7528 / \u5168\u90E8\u8D26\u53F7"),
1306
- metric("\u7D2F\u8BA1 Token", fmt(totals.tokens), `${fmt(totals.requests)} \u6B21\u8BF7\u6C42`)
1307
- ] }),
1308
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PerformanceMetrics, { events: (t.events || []).filter((e) => e.at >= usageDateBounds("1")[0]) }),
1309
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1310
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5E73\u53F0\u989D\u5EA6" }),
1311
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1312
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "notice", children: "\u5E73\u53F0\u7528\u91CF \xB7 \u6BCF 5 \u5206\u949F\u66F4\u65B0" }),
1313
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
1314
- void act({ action: "monitor.refresh" });
1315
- }, children: "\u5237\u65B0\u5E73\u53F0\u7528\u91CF" })
1316
- ] })
1317
- ] }),
1318
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box table-shell", children: [
1319
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", role: "region", "aria-label": "\u5404\u5E73\u53F0\u8D26\u53F7\u989D\u5EA6", tabIndex: "0", children: [
1320
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
1321
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
1322
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u8D26\u53F7" }),
1323
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u4F9B\u5E94\u5546 / \u533A\u57DF" }),
1324
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u5E73\u53F0\u79EF\u5206" }),
1325
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u4ECA\u65E5\u7B7E\u5230" }),
1326
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "cell-actions", children: "\u8DEF\u7531\u72B6\u6001" })
1327
- ] }) }),
1328
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: data.accounts.map((a) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
1329
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1330
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: displayName(a) }),
1331
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: loginNames[a.login?.state] || "\u5C1A\u672A\u67E5\u8BE2\u767B\u5F55" })
1332
- ] }),
1333
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: data.providers.find((p) => p.id === a.provider)?.name || a.provider }),
1334
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Balance, { account: a }) }),
1335
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CheckinResult, { row: data.checkins?.accounts.find((r) => r.id === a.id) }) }),
1336
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "cell-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "status", children: [
1337
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { className: a.enabled === false ? "" : a.status?.cooldowns?.length ? "warn" : "good", "aria-hidden": "true" }),
1338
- a.enabled === false ? "\u672A\u5165\u6C60" : a.status?.cooldowns?.length ? "\u90E8\u5206\u8DEF\u7531\u51B7\u5374" : "\u5DF2\u5728\u6C60\u4E2D"
1339
- ] }) })
1340
- ] }, a.id)) })
1341
- ] }),
1342
- !data.accounts.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: "\u5C1A\u672A\u8FDE\u63A5\u8D26\u53F7\uFF0C\u8BF7\u5148\u83B7\u53D6\u672C\u673A\u767B\u5F55\u6216\u6DFB\u52A0\u51ED\u8BC1\u3002" })
1343
- ] }),
1344
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "table-footer bar", children: [
1345
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5404\u5E73\u53F0\u79EF\u5206\u72EC\u7ACB\u5C55\u793A\uFF0C\u4E34\u671F\u63D0\u9192\u4EC5\u663E\u793A\u5DF2\u786E\u8BA4\u7684\u4F59\u989D\u3002" }),
1346
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => go("accounts"), children: "\u7BA1\u7406\u8D26\u53F7\u6C60" })
1347
- ] })
1348
- ] }),
1349
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u9762\u677F\u8BFB\u53D6\u672C\u673A\u7F13\u5B58\uFF0C\u4E0D\u4F1A\u89E6\u53D1\u5E73\u53F0\u67E5\u8BE2\u3002\u5E73\u53F0\u4F59\u989D\u6BCF 5 \u5206\u949F\u66F4\u65B0\uFF0C\u624B\u52A8\u5237\u65B0\u7ACB\u5373\u67E5\u8BE2\uFF1B\u79EF\u5206\u8F6E\u6362\u4E0E\u4E34\u671F\u4F18\u5148\u6309\u9700\u590D\u6838\u3002Token \u4EC5\u7EDF\u8BA1\u672C\u63D2\u4EF6\u8BF7\u6C42\u3002" }),
1350
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid", children: [
1351
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box", children: [
1352
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u8FD1 7 \u65E5 Token" }),
1353
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "trend", role: "img", "aria-label": dates.map((d) => `${d.key} ${d.tokens} Token`).join("\uFF0C"), children: dates.map((d) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { title: `${d.key} \xB7 ${fmt(d.tokens)} Token`, children: [
1354
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { style: { height: `${Math.max(3, d.tokens / max * 78)}%` } }),
1355
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: d.key.slice(5) })
1356
- ] }, d.key)) }),
1357
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
1358
- "\u672A\u8FD4\u56DE Token \u7528\u91CF\u7684\u8BF7\u6C42\uFF1A",
1359
- fmt(data.accounts.reduce((n, a) => n + (a.usage?.unmetered || 0), 0)),
1360
- " \u6B21"
1361
- ] })
1362
- ] }),
1363
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
1364
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5E38\u7528\u5165\u53E3" }),
1365
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u8FDE\u63A5\u8D26\u53F7\u540E\uFF0C\u5728 DSH \u6A21\u578B\u9009\u62E9\u5668\u4E2D\u4F7F\u7528\u300C\u7EDF\u4E00\u8DEF\u7531\u300D\u3002" }),
1366
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1367
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => go("accounts"), children: "\u67E5\u770B\u8D26\u53F7" }),
1368
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => go("routes"), children: "\u914D\u7F6E\u8DEF\u7531" }),
1369
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => go("checkins"), children: "\u79EF\u5206\u7B7E\u5230" }),
1370
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => go("plugins"), children: "\u68C0\u67E5\u6240\u6709\u63D2\u4EF6\u66F4\u65B0" })
1371
- ] })
1372
- ] })
1373
- ] }),
1374
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box", children: [
1375
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1376
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u6700\u8FD1\u8BF7\u6C42" }),
1377
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => go("usage"), children: "\u67E5\u770B Token \u660E\u7EC6" })
1378
- ] }),
1379
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", children: [
1380
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
1381
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
1382
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u65F6\u95F4" }),
1383
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8D26\u53F7" }),
1384
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8DEF\u7531 / \u6A21\u578B" }),
1385
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "Token" }),
1386
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u6027\u80FD" }),
1387
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u7ED3\u679C" })
1388
- ] }) }),
1389
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: (t.events || []).slice(0, 15).map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
1390
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: when(e.at) }),
1391
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: data.accounts.find((a) => a.id === e.account)?.name || e.account }),
1392
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "mono", children: e.alias }),
1393
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmt(e.tokens) }),
1394
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestPerformance, { event: e }) }),
1395
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: e.outcome === "completed" ? "\u6210\u529F" : e.outcome === "cancelled" ? "\u5DF2\u53D6\u6D88" : `\u5931\u8D25 ${e.status}` })
1396
- ] }, `${e.at}:${i}`)) })
1397
- ] }),
1398
- !t.events?.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: "\u5C1A\u65E0\u8BF7\u6C42\u8BB0\u5F55\u3002\u901A\u8FC7\u672C\u63D2\u4EF6\u8C03\u7528\u6A21\u578B\u540E\u4F1A\u663E\u793A\u5728\u8FD9\u91CC\u3002" })
1399
- ] })
1400
- ] })
1401
- ] });
1402
- }
1403
- function usageDateBounds(period, start, end, now = Date.now()) {
1404
- const today = new Date(now).toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" });
1405
- const midnight = (day) => Date.parse(`${day}T00:00:00+08:00`);
1406
- if (period === "custom") return [midnight(start), midnight(end) + 864e5];
1407
- if (period === "all") return [-Infinity, Infinity];
1408
- return [midnight(today) - (Number(period) - 1) * 864e5, midnight(today) + 864e5];
1409
- }
1410
- var duration = (ms) => typeof ms !== "number" || !Number.isFinite(ms) ? "\u2014" : ms < 6e4 ? `${fmt(ms / 1e3)} \u79D2` : `${Math.floor(ms / 6e4)} \u5206 ${fmt(ms % 6e4 / 1e3)} \u79D2`;
1411
- function performanceSummary(events) {
1412
- const rows = events.filter((e) => e.outcome === "completed" && e.timing);
1413
- const sum = (key, source = rows) => source.some((e) => e.timing[key] != null) ? source.reduce((n, e) => n + (e.timing[key] ?? 0), 0) : null;
1414
- const first = rows.filter((e) => e.timing.ttftMs != null), decode = rows.filter((e) => e.timing.decodeMs > 0 && e.timing.decodeTokens != null), tools = rows.filter((e) => e.timingSource === "dsh-step");
1415
- return {
1416
- modelMs: sum("modelMs"),
1417
- toolMs: sum("toolMs", tools),
1418
- ttftMs: first.length ? sum("ttftMs", first) / first.length : null,
1419
- tps: decode.length ? sum("decodeTokens", decode) / (sum("decodeMs", decode) / 1e3) : null,
1420
- samples: rows.length,
1421
- firstSamples: first.length,
1422
- decodeSamples: decode.length,
1423
- toolSamples: tools.length,
1424
- pendingTools: tools.reduce((n, e) => n + (e.timing.toolCount ?? 0) - (e.timing.toolsCompleted ?? 0), 0)
1425
- };
1426
- }
1427
- function PerformanceMetrics({ events }) {
1428
- const stats = performanceSummary(events);
1429
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "stack performance", "aria-label": "\u8C03\u7528\u6027\u80FD\u7EDF\u8BA1", children: [
1430
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1431
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u8C03\u7528\u6027\u80FD" }),
1432
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
1433
- "\u6210\u529F\u8C03\u7528 \xB7 ",
1434
- fmt(stats.samples),
1435
- " \u6761\u6027\u80FD\u8BB0\u5F55"
1436
- ] })
1437
- ] }),
1438
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "metrics", children: [
1439
- metric("\u6A21\u578B\u7528\u65F6", duration(stats.modelMs), "\u6210\u529F\u8C03\u7528\u7528\u65F6\u5408\u8BA1"),
1440
- metric("\u5DE5\u5177\u8C03\u7528\u7528\u65F6", duration(stats.toolMs), `${stats.toolSamples} \u6761 DSH \u6B65\u9AA4${stats.pendingTools ? ` \xB7 ${stats.pendingTools} \u4E2A\u5DE5\u5177\u672A\u5B8C\u6210` : ""}`),
1441
- metric("\u9996 Token \u5E73\u5747\uFF08TTFT\uFF09", duration(stats.ttftMs), `${stats.firstSamples} \u6761\u9996 Token \u8BB0\u5F55`),
1442
- metric("\u8F93\u51FA\u901F\u5EA6\uFF08TPS\uFF09", stats.tps === null ? "\u2014" : `${fmt(stats.tps)} tok/s`, `${stats.decodeSamples} \u6761\u89E3\u7801\u8BB0\u5F55 \xB7 \u52A0\u6743\u901F\u5EA6`)
1443
- ] }),
1444
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "help", children: [
1445
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u7EDF\u8BA1\u53E3\u5F84\u4E0E\u7F3A\u5931\u6570\u636E" }),
1446
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u968F\u5F53\u524D\u65F6\u95F4\u3001\u8D26\u53F7\u3001\u8DEF\u7531\u548C\u7ED3\u679C\u7B5B\u9009\u6C47\u603B\uFF0C\u4ECE\u672C\u7248\u5F00\u59CB\u8BB0\u5F55\uFF1B\u65E7\u6570\u636E\u4E0D\u8865\u7B97\u3002DSH \u6B65\u9AA4\u53E3\u5F84\u4E0E\u4F1A\u8BDD\u7EDF\u8BA1\u4E00\u81F4\uFF1A\u6A21\u578B\u7528\u65F6\u4ECE\u6B65\u9AA4\u5F00\u59CB\u5230\u56DE\u590D\u5B8C\u6210\uFF0C\u9996 Token \u5305\u62EC\u975E\u7A7A\u6587\u672C\u3001\u63A8\u7406\u6216\u5DE5\u5177\u8C03\u7528\uFF0C\u5DE5\u5177\u7528\u65F6\u6309\u8C03\u7528\u4E0E\u7ED3\u679C\u914D\u5BF9\u76F8\u52A0\uFF08\u5E76\u884C\u5DE5\u5177\u53EF\u80FD\u91CD\u53E0\uFF09\u3002TPS = \u6709\u6548\u8F93\u51FA Token \u5408\u8BA1 \xF7 \u9996 Token \u540E\u7684\u89E3\u7801\u79D2\u6570\u5408\u8BA1\uFF0C\u4E0D\u5BF9\u5404\u6B21\u901F\u5EA6\u7B80\u5355\u5E73\u5747\u3002\u672A\u7ECF\u8FC7 DSH \u6B65\u9AA4\u7684\u8BF7\u6C42\u4F7F\u7528\u4E0A\u6E38\u8BA1\u65F6\uFF0C\u65E0\u6CD5\u8BB0\u5F55\u5DE5\u5177\u6267\u884C\u7528\u65F6\u3002\u8FD9\u91CC\u53EA\u6C47\u603B\u672C\u63D2\u4EF6\u4FDD\u7559\u4E14\u7B5B\u9009\u5185\u7684\u8C03\u7528\uFF0C\u5E76\u975E\u67D0\u4E2A\u4F1A\u8BDD\u7684\u5B8C\u6574\u5386\u53F2\u3002\u5931\u8D25\u4E0E\u53D6\u6D88\u4FDD\u7559\u9010\u6B21\u8017\u65F6\uFF0C\u4E0D\u8BA1\u5165\u4EE5\u4E0A\u6210\u529F\u8C03\u7528\u6307\u6807\u3002" }) })
1447
- ] })
1448
- ] });
1449
- }
1450
- function UsageDetails({ data, busy, act }) {
1451
- const [account, setAccount] = (0, import_react.useState)(""), [route, setRoute] = (0, import_react.useState)(""), [outcome, setOutcome] = (0, import_react.useState)(""), [source, setSource] = (0, import_react.useState)(""), [page, setPage] = (0, import_react.useState)(0);
1452
- const [period, setPeriod] = (0, import_react.useState)("30"), [start, setStart] = (0, import_react.useState)(() => new Date(Date.now() - 29 * 864e5).toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" })), [end, setEnd] = (0, import_react.useState)(() => (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", { timeZone: "Asia/Shanghai" }));
1453
- const all = data.telemetry?.events || [], retention = data.options.usageRetentionDays;
1454
- const [from, until] = usageDateBounds(period, start, end), invalidRange = !(from < until);
1455
- const events = all.filter((e) => e.at >= from && e.at < until && (!account || e.account === account) && (!route || e.alias === route) && (!outcome || e.outcome === outcome) && (!source || (e.source || "dsh") === source));
1456
- const pages = Math.max(1, Math.ceil(events.length / 50)), current = Math.min(page, pages - 1);
1457
- const accountName = (id) => data.accounts.find((a) => a.id === id)?.name || id;
1458
- const routeName = (id) => data.routes.find((r) => r.id === id)?.name || id;
1459
- const total = (key) => events.some((e) => e[key] != null) ? events.reduce((n, e) => n + (e[key] ?? 0), 0) : null;
1460
- const missing = events.filter((e) => e.input == null || e.output == null).length;
1461
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
1462
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
1463
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1464
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1465
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u9010\u6B21\u8BF7\u6C42\u7528\u91CF" }),
1466
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u8BB0\u5F55\u6BCF\u6B21\u4E0A\u6E38\u8C03\u7528\uFF0C\u5305\u62EC\u6545\u969C\u5207\u6362\u4E2D\u5931\u8D25\u7684\u5C1D\u8BD5\u3002" })
1467
- ] }),
1468
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "badge", children: [
1469
- "\u6700\u8FD1 ",
1470
- retention,
1471
- " \u5929 \xB7 ",
1472
- fmt(all.length),
1473
- " \u6761"
1474
- ] })
1475
- ] }),
1476
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "help", children: [
1477
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("summary", { children: [
1478
- "\u8C03\u6574\u660E\u7EC6\u4FDD\u7559\u5929\u6570\uFF08\u5F53\u524D ",
1479
- retention,
1480
- " \u5929\uFF09"
1481
- ] }),
1482
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
1483
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "row", onSubmit: (e) => {
1484
- e.preventDefault();
1485
- void act({ action: "options.save", usageRetentionDays: Number(new FormData(e.currentTarget).get("days")) });
1486
- }, children: [
1487
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1488
- "\u660E\u7EC6\u4FDD\u7559\u5929\u6570",
1489
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { name: "days", type: "number", min: "1", max: "365", step: "1", required: true, disabled: busy, defaultValue: retention })
1490
- ] }),
1491
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "submit", disabled: busy, children: "\u4FDD\u5B58\u4FDD\u7559\u671F\u9650" })
1492
- ] }, retention),
1493
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u9ED8\u8BA4\u6EDA\u52A8\u4FDD\u7559\u6700\u8FD1 30 \u5929\uFF0C\u53EF\u8BBE\u7F6E 1\u2013365 \u5929\u3002\u7F29\u77ED\u671F\u9650\u4F1A\u5220\u9664\u8D85\u671F\u660E\u7EC6\uFF0C\u5EF6\u957F\u4E0D\u80FD\u6062\u590D\u5DF2\u5220\u9664\u8BB0\u5F55\uFF1B\u7D2F\u8BA1\u7EDF\u8BA1\u3001\u989D\u5EA6\u8F6E\u6362\u548C\u4E34\u671F\u51B7\u5374\u4E0D\u53D7\u5F71\u54CD\u3002" })
1494
- ] })
1495
- ] })
1496
- ] }),
1497
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1498
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "row", role: "group", "aria-label": "\u660E\u7EC6\u65F6\u95F4\u8303\u56F4", children: [["1", "\u4ECA\u65E5"], ["3", "\u8FD1 3 \u65E5"], ["7", "\u8FD1 7 \u65E5"], ["30", "\u8FD1 30 \u65E5"], ["all", "\u5168\u90E8\u5DF2\u4FDD\u7559"], ["custom", "\u81EA\u5B9A\u4E49"]].map(([value, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { "aria-pressed": period === value, onClick: () => {
1499
- setPeriod(value);
1500
- setPage(0);
1501
- }, children: label }, value)) }),
1502
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u6309\u5317\u4EAC\u65F6\u95F4\u81EA\u7136\u65E5\u7B5B\u9009" })
1503
- ] }),
1504
- period === "custom" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1505
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1506
- "\u5F00\u59CB\u65E5\u671F\uFF08\u5317\u4EAC\u65F6\u95F4\uFF09",
1507
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "date", value: start, max: end || void 0, required: true, onChange: (e) => {
1508
- setStart(e.target.value);
1509
- setPage(0);
1510
- } })
1511
- ] }),
1512
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1513
- "\u7ED3\u675F\u65E5\u671F\uFF08\u5317\u4EAC\u65F6\u95F4\uFF09",
1514
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "date", value: end, min: start || void 0, required: true, onChange: (e) => {
1515
- setEnd(e.target.value);
1516
- setPage(0);
1517
- } })
1518
- ] }),
1519
- invalidRange && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: "error", children: "\u8BF7\u9009\u62E9\u6709\u6548\u7684\u8D77\u6B62\u65E5\u671F\uFF0C\u7ED3\u675F\u65E5\u671F\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65E5\u671F\u3002" })
1520
- ] }),
1521
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1522
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1523
- "\u8D26\u53F7",
1524
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: account, onChange: (e) => {
1525
- setAccount(e.target.value);
1526
- setPage(0);
1527
- }, children: [
1528
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5168\u90E8\u8D26\u53F7" }),
1529
- [...new Set(all.map((e) => e.account))].map((id) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: id, children: accountName(id) }, id))
1530
- ] })
1531
- ] }),
1532
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1533
- "\u8DEF\u7531 / \u6A21\u578B",
1534
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: route, onChange: (e) => {
1535
- setRoute(e.target.value);
1536
- setPage(0);
1537
- }, children: [
1538
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5168\u90E8\u8DEF\u7531 / \u6A21\u578B" }),
1539
- [...new Set(all.map((e) => e.alias))].map((id) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: id, children: routeName(id) }, id))
1540
- ] })
1541
- ] }),
1542
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1543
- "\u6765\u6E90",
1544
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: source, onChange: (e) => {
1545
- setSource(e.target.value);
1546
- setPage(0);
1547
- }, children: [
1548
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5168\u90E8\u6765\u6E90" }),
1549
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "dsh", children: "DSH \u4F1A\u8BDD" }),
1550
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "api", children: "API \u670D\u52A1" })
1551
- ] })
1552
- ] }),
1553
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
1554
- "\u7ED3\u679C",
1555
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: outcome, onChange: (e) => {
1556
- setOutcome(e.target.value);
1557
- setPage(0);
1558
- }, children: [
1559
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5168\u90E8\u7ED3\u679C" }),
1560
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "completed", children: "\u6210\u529F" }),
1561
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "failed", children: "\u5931\u8D25" }),
1562
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "cancelled", children: "\u5DF2\u53D6\u6D88" })
1563
- ] })
1564
- ] })
1565
- ] }),
1566
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "metrics", children: [
1567
- metric("\u7B5B\u9009\u5185\u8C03\u7528", fmt(events.length), "\u4E0A\u6E38\u5C1D\u8BD5\u6B21\u6570"),
1568
- metric("\u8F93\u5165 Token", fmt(total("input")), "\u5DF2\u8FD4\u56DE\u7684\u8F93\u5165\u5206\u9879"),
1569
- metric("\u8F93\u51FA Token", fmt(total("output")), "\u5DF2\u8FD4\u56DE\u7684\u8F93\u51FA\u5206\u9879"),
1570
- metric("\u603B Token", fmt(total("tokens")), "\u5DF2\u8FD4\u56DE\u7684\u603B\u91CF")
1571
- ] }),
1572
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
1573
- "\u6570\u636E\u6765\u81EA\u5E73\u53F0\u8FD4\u56DE\u7684 usage\u3002",
1574
- missing ? fmt(missing) + " \u6761\u7F3A\u5C11\u8F93\u5165\u6216\u8F93\u51FA\u5206\u9879\uFF1B\u65E7\u8BB0\u5F55\u4E0D\u8865\u7B97\u3002" : "\u8F93\u5165\u3001\u8F93\u51FA\u4E3A\u5B9E\u9645\u8FD4\u56DE\u503C\u3002",
1575
- "\u7F13\u5B58\u8F93\u5165\u5305\u542B\u5728\u8F93\u5165\u4E2D\uFF0C\u63A8\u7406\u8F93\u51FA\u5305\u542B\u5728\u8F93\u51FA\u4E2D\uFF0C\u5747\u4E0D\u91CD\u590D\u76F8\u52A0\u3002\u672A\u8FD4\u56DE\u7684\u6570\u636E\u4EE5\u300C\u2014\u300D\u663E\u793A\u3002"
1576
- ] }),
1577
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PerformanceMetrics, { events }),
1578
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box table-shell", children: [
1579
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", role: "region", "aria-label": "\u8BF7\u6C42\u7528\u91CF\u4E0E\u6027\u80FD\u660E\u7EC6", tabIndex: "0", children: [
1580
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
1581
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
1582
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u65F6\u95F4" }),
1583
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u6E20\u9053 / \u8D26\u53F7" }),
1584
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8DEF\u7531 / \u5B9E\u9645\u6A21\u578B" }),
1585
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u5165" }),
1586
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u8F93\u51FA" }),
1587
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u603B Token" }),
1588
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u6027\u80FD" }),
1589
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "\u7ED3\u679C" })
1590
- ] }) }),
1591
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: events.slice(current * 50, (current + 1) * 50).map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
1592
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1593
- when(e.at),
1594
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: e.source === "api" ? "API \u670D\u52A1" : "DSH \u4F1A\u8BDD" })
1595
- ] }),
1596
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1597
- data.providers.find((p) => p.id === e.provider)?.name || e.provider,
1598
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1599
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: accountName(e.account) })
1600
- ] }),
1601
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1602
- routeName(e.alias),
1603
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1604
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "mono", children: e.model || "\u672A\u8BB0\u5F55\u5B9E\u9645\u6A21\u578B" })
1605
- ] }),
1606
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1607
- fmt(e.input),
1608
- e.cachedInput != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1609
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1610
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
1611
- "\u7F13\u5B58 ",
1612
- fmt(e.cachedInput)
1613
- ] })
1614
- ] })
1615
- ] }),
1616
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1617
- fmt(e.output),
1618
- e.reasoningOutput != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1619
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1620
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
1621
- "\u63A8\u7406 ",
1622
- fmt(e.reasoningOutput)
1623
- ] })
1624
- ] })
1625
- ] }),
1626
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: fmt(e.tokens) }),
1627
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestPerformance, { event: e }) }),
1628
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
1629
- e.outcome === "completed" ? "\u6210\u529F" : e.outcome === "cancelled" ? "\u5DF2\u53D6\u6D88" : "\u5931\u8D25",
1630
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1631
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: e.status })
1632
- ] })
1633
- ] }, e.at + ":" + current + ":" + i)) })
1634
- ] }),
1635
- !events.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: "\u5F53\u524D\u7B5B\u9009\u548C\u4FDD\u7559\u671F\u9650\u5185\u6CA1\u6709\u8BF7\u6C42\u660E\u7EC6\u3002" })
1636
- ] }),
1637
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar table-footer", children: [
1638
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
1639
- "\u7B2C ",
1640
- current + 1,
1641
- " / ",
1642
- pages,
1643
- " \u9875 \xB7 \u6BCF\u9875 50 \u6761"
1644
- ] }),
1645
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1646
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: current === 0, onClick: () => setPage(current - 1), children: "\u4E0A\u4E00\u9875" }),
1647
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: current >= pages - 1, onClick: () => setPage(current + 1), children: "\u4E0B\u4E00\u9875" })
1648
- ] })
1649
- ] })
1650
- ] })
1651
- ] });
1652
- }
1653
- function RequestPerformance({ event: e }) {
1654
- const t = e.timing;
1655
- if (!t) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: "\u672A\u8BB0\u5F55" });
1656
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "help", children: [
1657
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: duration(t.modelMs) }),
1658
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { minWidth: 170 }, children: [
1659
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
1660
- "\u6A21\u578B\uFF1A",
1661
- duration(t.modelMs)
1662
- ] }),
1663
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
1664
- "\u9996 Token\uFF1A",
1665
- duration(t.ttftMs)
1666
- ] }),
1667
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
1668
- "TPS\uFF1A",
1669
- t.decodeMs > 0 && t.decodeTokens != null ? `${fmt(t.decodeTokens / (t.decodeMs / 1e3))} tok/s` : "\u2014"
1670
- ] }),
1671
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
1672
- "\u5DE5\u5177\uFF1A",
1673
- duration(t.toolMs),
1674
- t.toolCount != null ? ` \xB7 ${t.toolsCompleted} / ${t.toolCount} \u5B8C\u6210` : ""
1675
- ] }),
1676
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: e.timingSource === "dsh-step" ? "DSH \u6B65\u9AA4\u8BA1\u65F6" : "\u4E0A\u6E38\u8BF7\u6C42\u8BA1\u65F6" })
1677
- ] })
1678
- ] });
1679
- }
1680
- function AccountForm({ modal, provider, data, busy, act, close, replace, error, notice }) {
1681
- const [revision, setRevision] = (0, import_react.useState)(modal.revision);
1682
- const edit = modal.mode === "edit", account = edit ? data.accounts.find((a) => a.id === modal.account.id) : null;
1683
- return edit ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
1684
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
1685
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "box stack", children: [
1686
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: account.name }),
1687
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: loginNames[account.login?.state] || "\u5C1A\u672A\u67E5\u8BE2" }),
1688
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
1689
- "\u8D26\u53F7\u8EAB\u4EFD\uFF1A",
1690
- account.login?.name || "\u5C1A\u672A\u83B7\u53D6",
1691
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1692
- "\u8BA4\u8BC1\u65B9\u5F0F\uFF1A",
1693
- account.login?.kind || "\u672A\u77E5",
1694
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1695
- "\u767B\u5F55\u6709\u6548\u81F3\uFF1A",
1696
- account.login?.kind === "PAT" ? "\u5E73\u53F0\u672A\u8FD4\u56DE\u6709\u6548\u671F" : when(account.login?.expiresAt),
1697
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1698
- "\u81EA\u52A8\u5237\u65B0\uFF1A",
1699
- account.login?.refreshable ? "\u652F\u6301" : "\u65E0\u5237\u65B0\u51ED\u8BC1",
1700
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1701
- "\u4E0A\u6B21\u7528\u91CF\u66F4\u65B0\uFF1A",
1702
- when(account.usage?.balance?.fetchedAt)
1703
- ] }),
1704
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
1705
- void act({ action: "account.refresh", id: account.id });
1706
- }, children: "\u5237\u65B0\u767B\u5F55\u4E0E\u7528\u91CF" }),
1707
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: replace, children: "\u8865\u5145 / \u66F4\u65B0\u51ED\u8BC1" })
1708
- ] }),
1709
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1710
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1711
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u8DEF\u7531\u8D26\u53F7\u987A\u5E8F" }),
1712
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u6545\u969C\u5207\u6362\u6309\u6B64\u987A\u5E8F\u5C1D\u8BD5\uFF1B\u6743\u91CD\u6216\u989D\u5EA6\u7B56\u7565\u4EE5\u8DEF\u7531\u914D\u7F6E\u4E3A\u51C6\u3002" })
1713
- ] }),
1714
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "row", children: [-1, 1].map((direction) => {
1715
- const group = data.accounts.filter((a) => a.provider === account.provider), i = group.findIndex((a) => a.id === account.id);
1716
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || (direction < 0 ? i === 0 : i === group.length - 1), onClick: async () => {
1717
- const next = await act({ action: "account.move", id: account.id, direction });
1718
- if (next) setRevision(next.revision);
1719
- }, children: direction < 0 ? "\u524D\u79FB" : "\u540E\u79FB" }, direction);
1720
- }) })
1721
- ] }),
1722
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CredentialTransfer, { account, busy, act }),
1723
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box", children: [
1724
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5E73\u53F0\u5957\u9910\u4E0E\u989D\u5EA6" }),
1725
- account.usage?.balance?.plan && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: account.usage.balance.plan }),
1726
- (account.usage?.balance?.packages || []).map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "item", children: [
1727
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1728
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: p.name || "\u989D\u5EA6\u5305" }),
1729
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: p.unlimited ? "\u4E0D\u9650\u91CF" : `${fmt(p.remaining)} / ${fmt(p.total)}` })
1730
- ] }),
1731
- p.expiresAt && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
1732
- "\u6709\u6548\u81F3 ",
1733
- when(p.expiresAt)
1734
- ] })
1735
- ] }, i)),
1736
- !account.usage?.balance?.packages?.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5C1A\u65E0\u53EF\u5C55\u793A\u989D\u5EA6\u5305\uFF0C\u70B9\u51FB\u5237\u65B0\u83B7\u53D6\u3002" })
1737
- ] }),
1738
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "stack", onSubmit: async (e) => {
1739
- e.preventDefault();
1740
- if (await act({ action: "account.update", revision, id: account.id, name: new FormData(e.currentTarget).get("name") })) close();
1741
- }, children: [
1742
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1743
- "\u8D26\u53F7\u663E\u793A\u540D\u79F0",
1744
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { name: "name", required: true, defaultValue: account.name, maxLength: 100, disabled: busy })
1745
- ] }),
1746
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
1747
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy, onClick: async () => {
1748
- if (await act({ action: "account.remove", id: account.id })) close();
1749
- }, children: "\u79FB\u51FA\u8D26\u53F7\u6C60" }),
1750
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", type: "submit", disabled: busy, children: "\u4FDD\u5B58\u540D\u79F0" })
1751
- ] }),
1752
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u79FB\u51FA\u8D26\u53F7\u6C60\u540E\u4FDD\u7559\u51ED\u8BC1\u6587\u4EF6\uFF0C\u53EF\u4ECE\u6587\u4EF6\u91CD\u65B0\u5BFC\u5165\u3002" })
1753
- ] })
1754
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CredentialForm, { modal, provider, data, busy, act, close, error, notice }, modal.mode);
1755
- }
1756
- function CredentialTransfer({ account, busy, act }) {
1757
- const container = (0, import_react.useRef)(null), [pending, setPending] = (0, import_react.useState)(false), [notice, setNotice] = (0, import_react.useState)(""), [error, setError] = (0, import_react.useState)(""), [manual, setManual] = (0, import_react.useState)("");
1758
- async function extract(copy) {
1759
- if (pending || busy) return;
1760
- setPending(true);
1761
- setNotice("");
1762
- setError("");
1763
- setManual("");
1764
- try {
1765
- const result = await act({ action: "account.export", id: account.id });
1766
- if (!result) return;
1767
- if (!copy) {
1768
- downloadJson(result.exported);
1769
- setNotice("\u5DF2\u53D1\u8D77\u51ED\u8BC1 JSON \u4E0B\u8F7D\uFF0C\u5728\u5176\u4ED6\u8BBE\u5907\u6DFB\u52A0\u8D26\u53F7\u65F6\u9009\u62E9\u8BE5\u6587\u4EF6\u5373\u53EF\u3002");
1770
- return;
1771
- }
1772
- const text = JSON.stringify(result.exported.document, null, 2);
1773
- try {
1774
- await navigator.clipboard.writeText(text);
1775
- } catch {
1776
- const focus = document.activeElement, area = document.createElement("textarea");
1777
- area.value = text;
1778
- area.style.cssText = "position:fixed;opacity:0;pointer-events:none";
1779
- container.current.append(area);
1780
- area.select();
1781
- let copied = false;
1782
- try {
1783
- copied = document.execCommand("copy");
1784
- } catch {
1785
- } finally {
1786
- area.remove();
1787
- focus?.focus();
1788
- }
1789
- if (!copied) {
1790
- setManual(text);
1791
- setNotice("\u5F53\u524D\u73AF\u5883\u4E0D\u5141\u8BB8\u81EA\u52A8\u590D\u5236\uFF0C\u8BF7\u70B9\u51FB\u4E0B\u65B9\u6587\u672C\u6846\u5168\u9009\u5E76\u590D\u5236\u3002");
1792
- return;
1793
- }
1794
- }
1795
- setNotice("\u51ED\u8BC1 JSON \u5DF2\u590D\u5236\uFF0C\u53EF\u5728\u5176\u4ED6\u8BBE\u5907\u6DFB\u52A0\u8D26\u53F7\u65F6\u76F4\u63A5\u7C98\u8D34\u3002");
1796
- } catch {
1797
- setError("\u51ED\u8BC1\u63D0\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
1798
- } finally {
1799
- setPending(false);
1800
- }
1801
- }
1802
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { ref: container, className: "box stack", children: [
1803
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u51ED\u8BC1\u63D0\u53D6\u4E0E\u8DE8\u8BBE\u5907\u4F7F\u7528" }),
1804
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5355\u8D26\u53F7 JSON \u5305\u542B\u767B\u5F55 Token / PAT\uFF0CTrae \u540C\u65F6\u5305\u542B\u5FC5\u8981\u8BBE\u5907\u8EAB\u4EFD\u3002\u590D\u5236\u53CA\u6B64\u5904\u5BFC\u51FA\u4E3A\u660E\u6587\uFF0C\u8BF7\u4EC5\u5728\u81EA\u5DF1\u7684\u8BBE\u5907\u95F4\u4F20\u9012\uFF1B\u9700\u8981\u52A0\u5BC6\u65F6\u4F7F\u7528\u300C\u914D\u7F6E\u8FC1\u79FB\u300D\u3002" }),
1805
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1806
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || pending, onClick: () => {
1807
- void extract(true);
1808
- }, children: "\u590D\u5236\u51ED\u8BC1 JSON" }),
1809
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || pending, onClick: () => {
1810
- void extract(false);
1811
- }, children: "\u5BFC\u51FA\u51ED\u8BC1 JSON" })
1812
- ] }),
1813
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
1814
- manual && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1815
- "\u624B\u52A8\u590D\u5236\u51ED\u8BC1 JSON",
1816
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { readOnly: true, rows: "5", autoComplete: "off", spellCheck: "false", value: manual, onFocus: (e) => e.currentTarget.select() })
1817
- ] }),
1818
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u65B0\u8BBE\u5907\uFF1A\u6DFB\u52A0\u8D26\u53F7 \u2192 \u7C98\u8D34 / \u9009\u62E9\u51ED\u8BC1 JSON \u2192 \u4FDD\u5B58\u3002\u5E73\u53F0\u8981\u6C42\u91CD\u65B0\u767B\u5F55\u65F6\uFF0C\u9700\u66F4\u65B0\u51ED\u8BC1\u3002" })
1819
- ] });
1820
- }
1821
- function CredentialForm({ modal, provider, data, busy, act, close, error, notice }) {
1822
- const replacing = modal.mode === "credentials";
1823
- const [selected, setSelected] = (0, import_react.useState)(modal.account?.provider || provider), [mode, setMode] = (0, import_react.useState)("client"), [localError, setLocalError] = (0, import_react.useState)(""), [json, setJson] = (0, import_react.useState)("");
1824
- const [edition, setEdition] = (0, import_react.useState)(modal.account?.login?.edition || "auto");
1825
- const [phone, setPhone] = (0, import_react.useState)(""), [smsCode, setSmsCode] = (0, import_react.useState)(""), [sms, setSms] = (0, import_react.useState)(null), [verify, setVerify] = (0, import_react.useState)(true), [clock, setClock] = (0, import_react.useState)(Date.now());
1826
- (0, import_react.useEffect)(() => {
1827
- if (mode !== "sms") return;
1828
- const timer = setInterval(() => setClock(Date.now()), 1e3);
1829
- return () => clearInterval(timer);
1830
- }, [mode]);
1831
- const resend = Math.max(0, Math.ceil(((sms?.resendAt || 0) - clock) / 1e3));
1832
- const isTrae = selected.startsWith("trae"), isQoder = selected.startsWith("qoder"), global = selected === "trae-global" || selected === "workbuddy-ai" || selected === "qoder-global";
1833
- const field = (label, name2, type = "text", required = true, value) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1834
- label,
1835
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { name: name2, type, autoComplete: "off", required, defaultValue: value, disabled: busy })
1836
- ] });
1837
- function receiveJson(text) {
1838
- setJson(text);
1839
- setLocalError("");
1840
- try {
1841
- const parsed = JSON.parse(text);
1842
- if (!replacing && parsed.format === "dsh-multi-router-account" && data.providers.some((p) => p.id === parsed.provider)) {
1843
- setSelected(parsed.provider);
1844
- setEdition(parsed.credential?.edition || (parsed.provider === "trae-global" ? "sg" : "cn"));
1845
- }
1846
- } catch {
1847
- }
1848
- }
1849
- async function submit(e) {
1850
- e.preventDefault();
1851
- setLocalError("");
1852
- const f = Object.fromEntries(new FormData(e.currentTarget));
1853
- if (mode === "sms") {
1854
- const result = await act({ action: "workbuddy.login", revision: data.revision, challenge: sms?.challenge, code: smsCode, verify, id: replacing ? modal.account.id : void 0, name: f.name || void 0 });
1855
- if (result) {
1856
- setPhone("");
1857
- setSmsCode("");
1858
- setSms(null);
1859
- close(selected);
1860
- }
1861
- return;
1862
- }
1863
- let document2, identityDocument;
1864
- try {
1865
- if (mode === "json") {
1866
- document2 = JSON.parse(json);
1867
- if (f.identityJSON?.trim()) identityDocument = JSON.parse(f.identityJSON);
1868
- }
1869
- if (mode === "manual") {
1870
- if (isQoder) document2 = { version: 2, pat: f.pat.trim(), region: global ? "global" : "china" };
1871
- else {
1872
- const credential = {
1873
- accessToken: f.accessToken.trim(),
1874
- ...f.refreshToken?.trim() ? { refreshToken: f.refreshToken.trim() } : {},
1875
- expiresAtMs: new Date(f.expiresAt).getTime(),
1876
- ...f.refreshExpiresAt ? { refreshExpiresAtMs: new Date(f.refreshExpiresAt).getTime() } : {},
1877
- ...isTrae ? { userId: f.identityId.trim(), edition, host: global ? "https://growsg-normal.trae.ai" : "https://api.trae.cn" } : { uid: f.identityId.trim(), domain: f.domain.trim() }
1878
- };
1879
- document2 = { version: 1, credential };
1880
- if (isTrae) identityDocument = { edition, machineId: f.machineId.trim(), deviceId: f.deviceId.trim() };
1881
- }
1882
- }
1883
- } catch {
1884
- setLocalError("JSON \u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u68C0\u67E5\u51ED\u8BC1\u53CA\u8BBE\u5907\u8EAB\u4EFD JSON\u3002");
1885
- return;
1886
- }
1887
- const action = replacing ? "account.credentials" : "account.capture";
1888
- if (await act({
1889
- action,
1890
- revision: modal.revision,
1891
- id: modal.account?.id,
1892
- provider: selected,
1893
- edition,
1894
- name: f.name || (document2?.format === "dsh-multi-router-account" ? document2.name : void 0),
1895
- ...document2 ? { document: document2, identityDocument } : { source: f.source || void 0, identity: f.identity || void 0 }
1896
- })) {
1897
- setJson("");
1898
- close(selected);
1899
- }
1900
- }
1901
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: submit, children: [
1902
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
1903
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error: localError || error, notice }),
1904
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid", children: [
1905
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1906
- "\u4F9B\u5E94\u5546 / \u533A\u57DF",
1907
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { disabled: busy || replacing, value: selected, onChange: (e) => {
1908
- setSelected(e.target.value);
1909
- setEdition("auto");
1910
- setMode("client");
1911
- setJson("");
1912
- setLocalError("");
1913
- setSms(null);
1914
- setSmsCode("");
1915
- setPhone("");
1916
- }, children: data.providers.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: p.id, children: p.name }, p.id)) })
1917
- ] }),
1918
- field("\u8D26\u53F7\u540D\u79F0\uFF08\u53EF\u9009\uFF09", "name", "text", false, modal.account?.name),
1919
- isTrae && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1920
- "\u767B\u5F55\u7684\u5BA2\u6237\u7AEF",
1921
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { value: edition, disabled: busy, onChange: (e) => setEdition(e.target.value), children: (mode === "client" ? [["auto", "\u81EA\u52A8\u8BC6\u522B\uFF08\u63A8\u8350\uFF09"], ...global ? [["sg", "Trae Global"], ["solo-sg", "TRAE SOLO Global"]] : [["cn", "Trae CN"], ["solo", "TRAE SOLO CN"]]] : global ? [["sg", "Trae Global"], ["solo-sg", "TRAE SOLO Global"]] : [["cn", "Trae CN"], ["solo", "TRAE SOLO CN"]]).map(([id, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: id, children: label }, id)) })
1922
- ] })
1923
- ] }),
1924
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1925
- "\u51ED\u8BC1\u6DFB\u52A0\u65B9\u5F0F",
1926
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { disabled: busy, value: mode, onChange: (e) => {
1927
- setMode(e.target.value);
1928
- if (e.target.value !== "client" && edition === "auto") setEdition(global ? "sg" : "cn");
1929
- setJson("");
1930
- setLocalError("");
1931
- }, children: [
1932
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "client", children: "\u4E00\u952E\u8BFB\u53D6\u672C\u673A\u767B\u5F55" }),
1933
- selected === "workbuddy" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "sms", children: "\u77ED\u4FE1\u767B\u5F55\u5E76\u4FDD\u5B58\u51ED\u8BC1" }),
1934
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: "manual", children: [
1935
- "\u624B\u52A8\u586B\u5199",
1936
- isQoder ? " PAT" : "\u51ED\u8BC1"
1937
- ] }),
1938
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "json", children: "\u7C98\u8D34 / \u9009\u62E9\u51ED\u8BC1 JSON" })
1939
- ] })
1940
- ] }),
1941
- mode === "sms" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "steps stack", children: [
1942
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "WorkBuddy \u624B\u673A\u53F7\u767B\u5F55" }),
1943
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u4EC5\u7528\u4E8E\u5DF2\u6709\u4E2D\u56FD\u7248\u8D26\u53F7\u3002\u624B\u673A\u53F7\u548C\u9A8C\u8BC1\u7801\u63D0\u4EA4\u81F3 WorkBuddy \u5B98\u65B9\uFF0C\u51ED\u8BC1\u4EC5\u4FDD\u5B58\u5728\u672C\u673A\uFF0C\u65E0\u9700\u5B89\u88C5 Python\u3002" }),
1944
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1945
- "\u624B\u673A\u53F7",
1946
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "tel", inputMode: "tel", autoComplete: "tel", required: true, pattern: "1[3-9][0-9]{9}", maxLength: "11", value: phone, disabled: busy || resend > 0, onChange: (e) => {
1947
- setPhone(e.target.value);
1948
- setSms(null);
1949
- setSmsCode("");
1950
- } })
1951
- ] }),
1952
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
1953
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || resend > 0 || !/^1[3-9]\d{9}$/.test(phone), onClick: async () => {
1954
- const next = await act({ action: "workbuddy.sms", phone });
1955
- if (next) {
1956
- setSms(next.workbuddyLogin);
1957
- setClock(Date.now());
1958
- setSmsCode("");
1959
- }
1960
- }, children: resend ? `${resend} \u79D2\u540E\u53EF\u91CD\u53D1` : sms ? "\u91CD\u65B0\u53D1\u9001\u9A8C\u8BC1\u7801" : "\u53D1\u9001\u9A8C\u8BC1\u7801" }),
1961
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "notice", role: "status", children: sms ? clock >= sms.expiresAt ? "\u9A8C\u8BC1\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u83B7\u53D6" : "\u9A8C\u8BC1\u7801\u5DF2\u53D1\u9001\uFF0C\u8BF7\u67E5\u770B\u77ED\u4FE1" : "\u70B9\u51FB\u53D1\u9001\u624D\u4F1A\u8BF7\u6C42\u77ED\u4FE1\uFF0C\u4E0D\u81EA\u52A8\u91CD\u8BD5" })
1962
- ] }),
1963
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
1964
- "\u77ED\u4FE1\u9A8C\u8BC1\u7801",
1965
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "text", inputMode: "numeric", autoComplete: "one-time-code", required: true, pattern: "[0-9]{4,8}", maxLength: "8", value: smsCode, disabled: busy || !sms, onChange: (e) => setSmsCode(e.target.value) })
1966
- ] }),
1967
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
1968
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: verify, disabled: busy, onChange: (e) => setVerify(e.target.checked) }),
1969
- "\u767B\u5F55\u540E\u9A8C\u8BC1\u5237\u65B0\u4EE4\u724C\uFF08\u63A8\u8350\uFF09"
1970
- ] }),
1971
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u540C\u4E00\u8D26\u53F7\u66F4\u65B0\u51ED\u8BC1\uFF0C\u65B0\u8D26\u53F7\u72EC\u7ACB\u4FDD\u5B58\uFF1B\u4E0D\u4F1A\u5F00\u542F\u81EA\u52A8\u7B7E\u5230\u3002\u9047\u5E73\u53F0\u9A8C\u8BC1\u6216\u9650\u5236\uFF0C\u8BF7\u6539\u7528\u672C\u673A\u5BA2\u6237\u7AEF\u8BFB\u53D6\u3002" })
1972
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "steps stack", children: [
1973
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u83B7\u53D6\u51ED\u8BC1\u5F15\u5BFC" }),
1974
- isQoder ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "\u5728\u5BF9\u5E94\u56FD\u5185 / \u56FD\u9645\u7AD9\u7684\u8D26\u53F7\u8BBE\u7F6E\u4E2D\u521B\u5EFA PAT\uFF0C\u7136\u540E\u9009\u62E9\u300C\u624B\u52A8\u586B\u5199 PAT\u300D\u7C98\u8D34\u3002\u5DF2\u6709\u65E7\u8FDE\u63A5\u5668\u767B\u5F55\u65F6\uFF0C\u53EF\u4E00\u952E\u8BFB\u53D6\u672C\u673A\u4FDD\u5B58\u7684 PAT\u3002\u7F51\u9875\u767B\u5F55 Cookie \u4E0D\u4F5C\u4E3A PAT \u4F7F\u7528\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
1975
- "1. \u5728\u6240\u9009\u533A\u57DF\u7684\u5B98\u65B9\u5BA2\u6237\u7AEF\u767B\u5F55\u8D26\u53F7\u3002",
1976
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1977
- "2. \u56DE\u5230\u672C\u9762\u677F\uFF0C\u9009\u62E9\u300C\u4E00\u952E\u8BFB\u53D6\u672C\u673A\u767B\u5F55\u300D\u5E76\u70B9\u51FB\u5E95\u90E8\u6309\u94AE\u3002",
1978
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
1979
- "3. \u6DFB\u52A0\u53E6\u4E00\u4E2A\u8D26\u53F7\u65F6\uFF0C\u5148\u5728\u5BA2\u6237\u7AEF\u5207\u6362\u767B\u5F55\uFF0C\u518D\u91CD\u590D\u8BFB\u53D6\uFF1B\u5DF2\u6DFB\u52A0\u7684\u8D26\u53F7\u4F1A\u4FDD\u7559\u72EC\u7ACB\u526F\u672C\u3002"
1980
- ] }),
1981
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "row", children: isQoder ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1982
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: "link", href: "https://docs.qoder.com/cli/authentication", target: "_blank", rel: "noreferrer", children: "\u5B98\u65B9 PAT \u83B7\u53D6\u8BF4\u660E" }),
1983
- global && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: "link", href: "https://qoder.com/account/integrations", target: "_blank", rel: "noreferrer", children: "\u6253\u5F00 PAT \u7BA1\u7406\u9875" })
1984
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: "link", href: isTrae ? global ? "https://www.trae.ai/" : "https://www.trae.cn/" : global ? "https://www.codebuddy.ai/" : "https://www.codebuddy.cn/", target: "_blank", rel: "noreferrer", children: "\u6253\u5F00\u5B98\u65B9\u5BA2\u6237\u7AEF\u7F51\u7AD9" }) }),
1985
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u8DE8\u8BBE\u5907\u5DF2\u6709\u51ED\u8BC1\u6587\u4EF6\u65F6\u53EF\u9009\u62E9 JSON\uFF1BWorkBuddy \u9700\u8981 accessToken\u3001uid\u3001domain\u3001expiresAtMs\uFF1BTrae \u8FD8\u9700\u8981 userId\u3001edition\uFF0C\u4EE5\u53CA\u540C\u8D26\u53F7\u7684 machineId / deviceId\u3002\u63A8\u8350\u8BFB\u53D6\u5BA2\u6237\u7AEF\u6216\u4F7F\u7528\u52A0\u5BC6\u914D\u7F6E\u8FC1\u79FB\uFF0C\u4E0D\u9700\u8981\u731C\u6D4B\u5B57\u6BB5\u3002" })
1986
- ] }),
1987
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
1988
- mode === "manual" && (isQoder ? field("Qoder PAT", "pat", "password") : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid", children: [
1989
- field("Access Token", "accessToken", "password"),
1990
- field("Refresh Token\uFF08\u53EF\u9009\uFF09", "refreshToken", "password", false),
1991
- field(isTrae ? "User ID" : "UID", "identityId"),
1992
- field("Access Token \u6709\u6548\u81F3", "expiresAt", "datetime-local"),
1993
- field("Refresh Token \u6709\u6548\u81F3\uFF08\u53EF\u9009\uFF09", "refreshExpiresAt", "datetime-local", false),
1994
- !isTrae && field("\u767B\u5F55 Domain", "domain", "text", false, global ? "www.codebuddy.ai" : "www.codebuddy.cn"),
1995
- isTrae && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1996
- field("Machine ID", "machineId"),
1997
- field("Device ID", "deviceId")
1998
- ] })
1999
- ] })),
2000
- mode === "json" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2001
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u672C\u63D2\u4EF6\u590D\u5236 / \u5BFC\u51FA\u7684\u5355\u8D26\u53F7 JSON \u4F1A\u81EA\u52A8\u8BC6\u522B\u4F9B\u5E94\u5546\u3001\u533A\u57DF\u53CA\u8D26\u53F7\u540D\u79F0\uFF1BTrae \u8BBE\u5907\u8EAB\u4EFD\u968F\u6587\u4EF6\u5BFC\u5165\u3002" }),
2002
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2003
- "\u9009\u62E9\u51ED\u8BC1 JSON \u6587\u4EF6",
2004
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "file", accept: ".json,application/json", disabled: busy, onChange: async (e) => {
2005
- const file = e.target.files?.[0];
2006
- if (!file) return;
2007
- if (file.size > 256 * 1024) {
2008
- setLocalError("\u51ED\u8BC1\u6587\u4EF6\u4E0D\u80FD\u8D85\u8FC7 256 KB");
2009
- return;
2010
- }
2011
- try {
2012
- receiveJson(await file.text());
2013
- } catch {
2014
- setLocalError("\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6");
2015
- }
2016
- } })
2017
- ] }),
2018
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2019
- "\u51ED\u8BC1 JSON",
2020
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { rows: "7", required: true, autoComplete: "off", spellCheck: "false", disabled: busy, value: json, onChange: (e) => receiveJson(e.target.value), placeholder: isQoder ? '{"pat":"\u2026","region":"china"}' : '{"version":1,"credential":{"accessToken":"\u2026", "expiresAtMs":\u2026}}' })
2021
- ] }),
2022
- isTrae && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2023
- "Trae \u8BBE\u5907\u8EAB\u4EFD JSON\uFF08\u51ED\u8BC1\u4E2D\u5DF2\u6709 identity \u65F6\u53EF\u7559\u7A7A\uFF09",
2024
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { name: "identityJSON", rows: "3", disabled: busy, autoComplete: "off", placeholder: '{"edition":"cn","machineId":"\u2026","deviceId":"\u2026"}' })
2025
- ] })
2026
- ] }),
2027
- mode === "client" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [
2028
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u9AD8\u7EA7\uFF1A\u6307\u5B9A\u767B\u5F55\u6587\u4EF6\u4F4D\u7F6E" }),
2029
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", style: { marginTop: 12 }, children: [
2030
- field("\u767B\u5F55 / PAT \u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u81EA\u52A8\u67E5\u627E\uFF09", "source", "text", false),
2031
- isTrae && field("Trae \u8BBE\u5907\u8EAB\u4EFD\u6587\u4EF6\u8DEF\u5F84\uFF08\u53EF\u9009\uFF09", "identity", "text", false)
2032
- ] })
2033
- ] })
2034
- ] }, `${selected}:${mode}`),
2035
- mode !== "sms" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
2036
- "\u51ED\u8BC1\u4EC5\u4FDD\u5B58\u5230\u672C\u673A\u63D2\u4EF6\u8D26\u53F7\u6C60\u3002\u4E0D\u4F1A\u5728\u8D26\u53F7\u5217\u8868\u663E\u793A Token\uFF1B\u6BCF\u4E2A\u8D26\u53F7\u72EC\u7ACB\u5237\u65B0\u3002",
2037
- replacing ? "\u4FDD\u5B58\u540E\u542F\u7528\u6B64\u8D26\u53F7\uFF0C\u539F\u51ED\u8BC1\u526F\u672C\u4FDD\u7559\u3002" : "\u91CD\u590D\u8BFB\u53D6\u540C\u4E00\u8D26\u53F7\u4F1A\u63D0\u793A\u3002"
2038
- ] })
2039
- ] }),
2040
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-foot bar", children: [
2041
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy, onClick: close, children: "\u53D6\u6D88" }),
2042
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", type: "submit", disabled: busy || mode === "sms" && (!sms || clock >= sms.expiresAt), children: busy ? "\u6B63\u5728\u5904\u7406\u2026" : mode === "sms" ? "\u767B\u5F55\u5E76\u4FDD\u5B58\u5230\u8D26\u53F7\u6C60" : mode === "client" ? "\u4E00\u952E\u83B7\u53D6\u5E76\u4FDD\u5B58\u767B\u5F55" : "\u4FDD\u5B58\u51ED\u8BC1\u5E76\u83B7\u53D6\u6A21\u578B" })
2043
- ] })
2044
- ] });
2045
- }
2046
- function MigrationForm({ data, act, busy }) {
2047
- const [panel, setPanel] = (0, import_react.useState)(null);
2048
- const [include, setInclude] = (0, import_react.useState)(false), [exportPassword, setExportPassword] = (0, import_react.useState)(""), [confirmPassword, setConfirmPassword] = (0, import_react.useState)(""), [exportError, setExportError] = (0, import_react.useState)("");
2049
- const [document2, setDocument] = (0, import_react.useState)(""), [fileName, setFileName] = (0, import_react.useState)(""), [password, setPassword] = (0, import_react.useState)(""), [mode, setMode] = (0, import_react.useState)("merge"), [preview, setPreview] = (0, import_react.useState)(null), [error, setError] = (0, import_react.useState)("");
2050
- const resetPreview = () => {
2051
- setPreview(null);
2052
- setError("");
2053
- };
2054
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
2055
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
2056
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u914D\u7F6E\u8FC1\u79FB" }),
2057
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5728\u8BBE\u5907\u95F4\u8FC1\u79FB\u8D26\u53F7\u3001\u6A21\u578B\u548C\u8DEF\u7531\u8BBE\u7F6E\u3002" })
2058
- ] }),
2059
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: "box table-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
2060
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
2061
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u64CD\u4F5C" }),
2062
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u5185\u5BB9" }),
2063
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "cell-actions", children: "\u5F00\u59CB" })
2064
- ] }) }),
2065
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tbody", { children: [
2066
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
2067
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "\u5BFC\u51FA\u5230\u5176\u4ED6\u8BBE\u5907" }) }),
2068
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
2069
- "\u8D26\u53F7\u4E0E\u8DEF\u7531\u8BBE\u7F6E",
2070
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: "\u53EF\u9009\u5BC6\u7801\u52A0\u5BC6\u643A\u5E26\u767B\u5F55\u51ED\u8BC1" })
2071
- ] }),
2072
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "cell-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => setPanel("export"), children: "\u5BFC\u51FA\u914D\u7F6E" }) })
2073
- ] }),
2074
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
2075
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "\u5BFC\u5165\u5DF2\u6709\u914D\u7F6E" }) }),
2076
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
2077
- "\u5148\u9884\u89C8\uFF0C\u518D\u786E\u8BA4\u5408\u5E76\u6216\u66FF\u6362",
2078
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: "\u5BFC\u5165\u524D\u81EA\u52A8\u5907\u4EFD\u672C\u673A\u914D\u7F6E" })
2079
- ] }),
2080
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "cell-actions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => setPanel("import"), children: "\u5BFC\u5165\u914D\u7F6E" }) })
2081
- ] })
2082
- ] })
2083
- ] }) }),
2084
- panel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: panel === "export" ? "\u5BFC\u51FA\u914D\u7F6E" : "\u5BFC\u5165\u914D\u7F6E", busy, close: () => setPanel(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
2085
- panel === "export" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "box stack", onSubmit: async (e) => {
2086
- e.preventDefault();
2087
- setExportError("");
2088
- if (include && exportPassword !== confirmPassword) {
2089
- setExportError("\u4E24\u6B21\u8FC1\u79FB\u5BC6\u7801\u4E0D\u4E00\u81F4");
2090
- return;
2091
- }
2092
- const result = await act({ action: "config.export", includeCredentials: include, password: include ? exportPassword : void 0 });
2093
- if (!result) return;
2094
- downloadJson(result.exported);
2095
- setExportPassword("");
2096
- setConfirmPassword("");
2097
- }, children: [
2098
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5BFC\u51FA\u5230\u5176\u4ED6\u8BBE\u5907" }),
2099
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5305\u542B\u8D26\u53F7\u540D\u79F0\u548C\u987A\u5E8F\u3001\u6A21\u578B\u5C55\u793A\u8BBE\u7F6E\u3001\u8DEF\u7531\u4E0E\u5207\u6362\u89C4\u5219\u3002\u4E0D\u4F1A\u5BFC\u51FA\u4F1A\u8BDD\u3001\u7EDF\u8BA1\u3001\u6587\u4EF6\u8DEF\u5F84\u6216\u7BA1\u7406\u5BC6\u94A5\u3002" }),
2100
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
2101
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: include, disabled: busy, onChange: (e) => {
2102
- setInclude(e.target.checked);
2103
- setExportPassword("");
2104
- setConfirmPassword("");
2105
- } }),
2106
- "\u540C\u65F6\u8FC1\u79FB\u8D26\u53F7\u767B\u5F55\u51ED\u8BC1\uFF08\u5BC6\u7801\u52A0\u5BC6\uFF09"
2107
- ] }),
2108
- include ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2109
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "\u52A0\u5BC6\u6587\u4EF6\u5305\u542B\u767B\u5F55 Token / PAT \u548C\u5FC5\u8981\u8BBE\u5907\u8EAB\u4EFD\uFF0C\u8BF7\u81EA\u884C\u4FDD\u7BA1\u3002\u65B0\u8BBE\u5907\u9700\u8981\u540C\u4E00\u5BC6\u7801\uFF1B\u51ED\u8BC1\u53EF\u80FD\u56E0\u5E73\u53F0\u8BBE\u5907\u9650\u5236\u800C\u9700\u8981\u91CD\u65B0\u767B\u5F55\u3002" }),
2110
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2111
- "\u8BBE\u7F6E\u8FC1\u79FB\u5BC6\u7801",
2112
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "password", autoComplete: "new-password", required: true, minLength: "10", maxLength: "1024", value: exportPassword, disabled: busy, onChange: (e) => setExportPassword(e.target.value) })
2113
- ] }),
2114
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2115
- "\u518D\u6B21\u8F93\u5165\u5BC6\u7801",
2116
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "password", autoComplete: "new-password", required: true, value: confirmPassword, disabled: busy, onChange: (e) => setConfirmPassword(e.target.value) })
2117
- ] })
2118
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "\u4EC5\u914D\u7F6E\u6587\u4EF6\u4E0D\u542B\u767B\u5F55\u51ED\u8BC1\u3002\u65B0\u8BBE\u5907\u4E0A\u7684\u8D26\u53F7\u4F1A\u5148\u505C\u7528\uFF0C\u8865\u5145\u51ED\u8BC1\u540E\u5373\u53EF\u542F\u7528\uFF1B\u5408\u5E76\u5BFC\u5165\u4F1A\u4FDD\u7559\u672C\u673A\u5DF2\u6709\u8D26\u53F7\u51ED\u8BC1\u3002" }),
2119
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error: exportError }),
2120
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", type: "submit", disabled: busy, children: include ? "\u5BFC\u51FA\u52A0\u5BC6\u8FC1\u79FB\u6587\u4EF6" : "\u5BFC\u51FA\u914D\u7F6E JSON" })
2121
- ] }),
2122
- panel === "import" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "box stack", onSubmit: async (e) => {
2123
- e.preventDefault();
2124
- setError("");
2125
- const result = await act({ action: "config.preview", document: document2, password, mode });
2126
- if (result) setPreview({ ...result.importPreview, revision: result.revision });
2127
- }, children: [
2128
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5BFC\u5165\u63D2\u4EF6\u914D\u7F6E" }),
2129
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2130
- "\u9009\u62E9\u8FC1\u79FB JSON \u6587\u4EF6",
2131
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "file", accept: ".json,application/json", required: true, disabled: busy, onChange: async (e) => {
2132
- resetPreview();
2133
- setPassword("");
2134
- setDocument("");
2135
- const file = e.target.files?.[0];
2136
- if (!file) return;
2137
- if (file.size > 900 * 1024) {
2138
- setError("\u8FC1\u79FB\u6587\u4EF6\u4E0D\u80FD\u8D85\u8FC7 900 KB");
2139
- return;
2140
- }
2141
- try {
2142
- setDocument(await file.text());
2143
- setFileName(file.name);
2144
- } catch {
2145
- setError("\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6");
2146
- }
2147
- } })
2148
- ] }),
2149
- fileName && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mono muted", children: fileName }),
2150
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2151
- "\u8FC1\u79FB\u5BC6\u7801\uFF08\u4EC5\u52A0\u5BC6\u6587\u4EF6\u9700\u8981\uFF09",
2152
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "password", autoComplete: "off", maxLength: "1024", disabled: busy, value: password, onChange: (e) => {
2153
- setPassword(e.target.value);
2154
- resetPreview();
2155
- } })
2156
- ] }),
2157
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2158
- "\u5BFC\u5165\u65B9\u5F0F",
2159
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { disabled: busy, value: mode, onChange: (e) => {
2160
- setMode(e.target.value);
2161
- resetPreview();
2162
- }, children: [
2163
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "merge", children: "\u5408\u5E76\uFF1A\u4FDD\u7559\u672C\u673A\u989D\u5916\u8D26\u53F7\u548C\u8DEF\u7531" }),
2164
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "replace", children: "\u66FF\u6362\uFF1A\u4F7F\u7528\u5BFC\u5165\u6587\u4EF6\u7684\u5B8C\u6574\u914D\u7F6E" })
2165
- ] })
2166
- ] }),
2167
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5408\u5E76\u65F6\u540C ID \u7684\u914D\u7F6E\u4F1A\u66F4\u65B0\uFF1B\u5E26\u51ED\u8BC1\u7684\u8D26\u53F7\u4F1A\u66F4\u65B0\u767B\u5F55\u526F\u672C\u3002\u66FF\u6362\u4F1A\u79FB\u51FA\u73B0\u6709\u914D\u7F6E\u4E2D\u7684\u989D\u5916\u8D26\u53F7 / \u8DEF\u7531\uFF0C\u4F46\u4FDD\u7559\u539F\u51ED\u8BC1\u6587\u4EF6\u3002\u4E24\u79CD\u65B9\u5F0F\u90FD\u4F1A\u5148\u5907\u4EFD\u672C\u673A\u914D\u7F6E\u3002" }),
2168
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error }),
2169
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "submit", disabled: busy || !document2, children: "\u68C0\u67E5\u6587\u4EF6\u5E76\u9884\u89C8\u53D8\u66F4" }),
2170
- preview && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "steps stack", children: [
2171
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5BFC\u5165\u9884\u89C8" }),
2172
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
2173
- preview.accounts,
2174
- " \u4E2A\u8D26\u53F7\uFF08\u65B0\u589E ",
2175
- preview.newAccounts,
2176
- "\uFF09 \xB7 ",
2177
- preview.credentials,
2178
- " \u4EFD\u51ED\u8BC1",
2179
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
2180
- preview.routes,
2181
- " \u6761\u8DEF\u7531 \xB7 \u66F4\u65B0\u540C\u540D\u8DEF\u7531 ",
2182
- preview.overwrittenRoutes,
2183
- " \u6761",
2184
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
2185
- preview.needsLogin,
2186
- " \u4E2A\u65B0\u8D26\u53F7\u9700\u8865\u5145\u767B\u5F55\uFF0C\u5C06\u5148\u505C\u7528"
2187
- ] }),
2188
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: "primary", type: "button", disabled: busy, onClick: async () => {
2189
- if (await act({ action: "config.import", revision: preview.revision, document: document2, password, mode })) {
2190
- setDocument("");
2191
- setPassword("");
2192
- setPreview(null);
2193
- }
2194
- }, children: [
2195
- "\u786E\u8BA4",
2196
- mode === "merge" ? "\u5408\u5E76" : "\u66FF\u6362",
2197
- "\u5E76\u5BFC\u5165"
2198
- ] })
2199
- ] })
2200
- ] })
2201
- ] }) })
2202
- ] });
2203
- }
2204
- function ExpiryStatus({ route, act, busy, revision, onForce }) {
2205
- const status = route.expiringStatus || {}, cooling = status.cooldownUntil > Date.now();
2206
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "steps stack", children: [
2207
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: cooling ? `\u4E34\u671F\u4F18\u5148\u51B7\u5374\u4E2D \xB7 \u5269\u4F59\u7EA6 ${Math.ceil((status.cooldownUntil - Date.now()) / 36e5)} \u5C0F\u65F6\uFF0C${when(status.cooldownUntil)} \u540E\u6062\u590D` : `\u4E34\u671F\u4F18\u5148\u5DF2\u5C31\u7EEA \xB7 \u7B2C ${status.number || 1} \u8F6E${status.accounts?.length ? ` \xB7 \u5DF2\u5B8C\u6210 ${status.completed?.length || 0} / ${status.accounts.length} \u4E2A\u8D26\u53F7` : ""}` }),
2208
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u6240\u6709\u4E34\u671F\u8D26\u53F7\u7684\u79EF\u5206\u8017\u5C3D\u6216\u8FBE\u5230\u6BCF\u8F6E\u989D\u5EA6\u540E\uFF0C\u4E34\u671F\u4F18\u5148\u6682\u505C 3 \u5929\uFF1B\u671F\u95F4\u6309\u666E\u901A\u8DEF\u7531\u89C4\u5219\u8FD0\u884C\uFF0C\u91CD\u542F\u540E\u51B7\u5374\u4ECD\u4FDD\u7559\u3002" }),
2209
- cooling && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy, onClick: async () => {
2210
- const result = await act({ action: "route.force-expiring", id: route.id, revision });
2211
- if (result) onForce?.(result);
2212
- }, children: "\u5F3A\u5236\u5F00\u542F\u5E76\u5F00\u59CB\u65B0\u4E00\u8F6E" }),
2213
- cooling && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5F3A\u5236\u5F00\u542F\u4F1A\u6E05\u9664\u4E34\u671F\u51B7\u5374\uFF0C\u5E76\u91CD\u7F6E\u672C\u8DEF\u7531\u7684\u672C\u8F6E\u989D\u5EA6\u8BA1\u6570\uFF1B\u7D2F\u8BA1\u7528\u91CF\u4FDD\u7559\u3002" })
2214
- ] });
2215
- }
2216
- function FreeStatus({ route, busy, act, onUpdate }) {
2217
- const status = route.freeStatus, accounts = status?.accounts || [], count = accounts.reduce((n, a) => n + a.models.length, 0);
2218
- const models = status?.modelRoutes || [];
2219
- const update = async (model, patch) => {
2220
- const next = await act({ action: "free.model.update", parentId: route.id, id: model.id, ...patch });
2221
- if (next) onUpdate?.(next);
2222
- };
2223
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "steps stack", children: [
2224
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
2225
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", { children: [
2226
- "\u514D\u8D39\u6A21\u578B \xB7 ",
2227
- models.length,
2228
- " \u79CD \xB7 ",
2229
- count,
2230
- " \u4E2A\u8D26\u53F7 / \u6A21\u578B\u7EC4\u5408"
2231
- ] }),
2232
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || status?.checking, onClick: () => {
2233
- void act({ action: "free.refresh" });
2234
- }, children: status?.checking ? "\u6B63\u5728\u68C0\u67E5\u2026" : "\u7ACB\u5373\u68C0\u67E5\u514D\u8D39\u6A21\u578B" })
2235
- ] }),
2236
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u6309\u6A21\u578B\u81EA\u52A8\u521B\u5EFA\u8DEF\u7531\uFF0C\u52FE\u9009\u540E\u5206\u522B\u51FA\u73B0\u5728 DSH \u6A21\u578B\u5217\u8868\u4E2D\u3002\u540C\u4E00\u6A21\u578B\u53EA\u5728\u6709\u514D\u8D39\u8D44\u683C\u4E14\u652F\u6301\u6240\u9009\u63A8\u7406\u7B49\u7EA7\u7684\u8D26\u53F7\u95F4\u5207\u6362\uFF0C\u4E0D\u6DF7\u7528\u5176\u4ED6\u6A21\u578B\u3002\u6BCF\u5929\u68C0\u67E5\uFF0C\u8C03\u7528\u524D\u590D\u6838\uFF1B\u6062\u590D\u6536\u8D39\u6216\u68C0\u67E5\u5931\u8D25\u65F6\u81EA\u52A8\u79FB\u51FA\uFF0C\u514D\u8D39\u6062\u590D\u540E\u4FDD\u7559\u4F60\u7684\u52FE\u9009\u548C\u6863\u4F4D\u8BBE\u7F6E\u3002" }),
2237
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "box table-shell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "scroll", role: "region", "aria-label": "\u514D\u8D39\u6A21\u578B\u5C55\u793A\u4E0E\u63A8\u7406\u7B49\u7EA7", tabIndex: "0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
2238
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
2239
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u6A21\u578B / \u5C55\u793A" }),
2240
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u53EF\u7528\u8D26\u53F7" }),
2241
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u4E0A\u4E0B\u6587 / \u63A8\u7406\u7B49\u7EA7" })
2242
- ] }) }),
2243
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: models.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: m.selected ? "selected" : "", children: [
2244
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
2245
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
2246
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", "aria-label": `\u5C55\u793A ${m.modelName}`, disabled: busy, checked: m.selected, onChange: (e) => {
2247
- void update(m, { visible: e.target.checked });
2248
- } }),
2249
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: m.modelName })
2250
- ] }),
2251
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { className: "muted", children: [
2252
- m.name.split(" \xB7 ").at(-1),
2253
- " \xB7 ",
2254
- fmt(m.contextWindow / 1e3),
2255
- "K \u4E0A\u4E0B\u6587"
2256
- ] })
2257
- ] }),
2258
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: m.accountNames.join("\u3001") || "\u6682\u65E0\u8D26\u53F7" }),
2259
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
2260
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextSelect, { model: m, value: m.configuredContextWindow, disabled: busy, label: `${m.modelName} \u4E0A\u4E0B\u6587`, onChange: (contextWindow) => {
2261
- void update(m, { contextWindow });
2262
- } }),
2263
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2264
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "sr-only", children: [
2265
- m.modelName,
2266
- " \u63A8\u7406\u7B49\u7EA7"
2267
- ] }),
2268
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { "aria-label": `${m.modelName} \u63A8\u7406\u7B49\u7EA7`, disabled: busy, value: m.reasoningEffort || "", onChange: (e) => {
2269
- void update(m, { reasoningEffort: e.target.value || null });
2270
- }, children: [
2271
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5E73\u53F0\u9ED8\u8BA4" }),
2272
- m.reasoning?.supportedEfforts?.map((e) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: e, children: effortNames[e] || e }, e))
2273
- ] })
2274
- ] }),
2275
- m.effortUnavailable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "warn", children: "\u539F\u6863\u4F4D\u6682\u4E0D\u53EF\u7528\uFF0C\u4F7F\u7528\u5E73\u53F0\u9ED8\u8BA4" })
2276
- ] })
2277
- ] }, m.id)) })
2278
- ] }) }) }),
2279
- !models.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u6682\u65E0\u786E\u8BA4\u514D\u8D39\u7684\u6A21\u578B\u3002\u6DFB\u52A0\u5E76\u542F\u7528\u8D26\u53F7\uFF0C\u6216\u7ACB\u5373\u68C0\u67E5\u76EE\u5F55\u3002" }),
2280
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [
2281
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u5404\u8D26\u53F7\u68C0\u67E5\u72B6\u6001" }),
2282
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "stack", style: { marginTop: 12 }, children: accounts.map((a) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
2283
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
2284
- a.name,
2285
- " \xB7 ",
2286
- a.models.length ? a.models.map((m) => m.name).join("\u3001") : a.error ? "\u68C0\u67E5\u5931\u8D25\uFF0C\u6682\u4E0D\u53C2\u4E0E" : "\u6682\u65E0\u786E\u8BA4\u514D\u8D39\u7684\u6A21\u578B"
2287
- ] }),
2288
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
2289
- a.provider,
2290
- " \xB7 \u4E0A\u6B21\u76EE\u5F55\u68C0\u67E5 ",
2291
- when(a.checkedAt)
2292
- ] })
2293
- ] }, a.id)) })
2294
- ] })
2295
- ] });
2296
- }
2297
- function FreeRouteForm({ draft, setDraft, data, act, busy, error, notice }) {
2298
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: async (e) => {
2299
- e.preventDefault();
2300
- const { id, previousId, revision, reasoning, supportsImages, expiringStatus, freeStatus, creditRates, maxContextWindow, supportedContextWindows, configuredContextWindow, contextKnown, eligibleAccountIds, enforceContext, ...route } = draft;
2301
- route.targets = route.targets.map((t) => ({ provider: t.provider, ...t.account ? { account: t.account } : {}, ...t.model ? { model: t.model } : {}, ...t.models ? { models: t.models } : {} }));
2302
- if (await act({ action: "route.save", id, previousId, revision, route })) setDraft(null);
2303
- }, children: [
2304
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
2305
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
2306
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2307
- "\u7BA1\u7406\u7EC4\u540D\u79F0",
2308
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { required: true, maxLength: 200, disabled: busy, value: draft.name, onChange: (e) => setDraft((d) => ({ ...d, name: e.target.value })) })
2309
- ] }),
2310
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "Free \u7684\u6A21\u578B\u8DEF\u7531\u7531\u76EE\u5F55\u81EA\u52A8\u7EF4\u62A4\uFF0C\u65E0\u9700\u586B\u5199\u6A21\u578B ID\u3002\u8D26\u53F7\u542F\u505C\u5728\u300C\u8D26\u53F7\u4E0E\u767B\u5F55\u300D\u8C03\u6574\u3002" }),
2311
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FreeStatus, { route: data.routes.find((r) => r.id === draft.id) || draft, act, busy, onUpdate: (next) => setDraft((d) => ({ ...d, revision: next.revision, freeModels: next.routes.find((r) => r.id === d.id)?.freeModels })) }),
2312
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
2313
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: draft.visible !== false, disabled: busy, onChange: (e) => setDraft((d) => ({ ...d, visible: e.target.checked })) }),
2314
- "\u5C55\u793A\u52FE\u9009\u7684\u514D\u8D39\u6A21\u578B"
2315
- ] })
2316
- ] }),
2317
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-foot bar", children: [
2318
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy, onClick: async () => {
2319
- if (await act({ action: "route.remove", id: draft.id, revision: draft.revision })) setDraft(null);
2320
- }, children: "\u79FB\u9664\u514D\u8D39\u7BA1\u7406\u7EC4" }),
2321
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy, type: "submit", children: "\u4FDD\u5B58\u8BBE\u7F6E" })
2322
- ] })
2323
- ] });
2324
- }
2325
- function RouteReasoningSelect({ draft, setDraft, data, busy }) {
2326
- const targets = draft.targets.map((t) => ({
2327
- provider: t.provider,
2328
- ...t.account ? { account: t.account } : {},
2329
- models: t.modelText.split(",").map((x) => x.trim()).filter(Boolean)
2330
- }));
2331
- const signature = JSON.stringify({
2332
- action: "route.preview",
2333
- revision: data.revision,
2334
- catalogs: data.accounts?.map((a) => [a.id, a.enabled, a.fetchedAt]),
2335
- id: draft.id || "preview",
2336
- route: {
2337
- contextMode: draft.contextMode ?? "maximum",
2338
- contextWindow: draft.contextWindow,
2339
- maxTokens: 1,
2340
- targets: targets.map(({ models, ...target }) => ({ ...target, ...models.length ? { models } : {} }))
2341
- }
2342
- });
2343
- const [preview, setPreview] = (0, import_react.useState)(null);
2344
- (0, import_react.useEffect)(() => {
2345
- const abort = new AbortController();
2346
- const timer = setTimeout(async () => {
2347
- try {
2348
- const res = await fetch(ENDPOINT, {
2349
- method: "POST",
2350
- signal: abort.signal,
2351
- headers: { "Content-Type": "application/json", "X-Multi-Router-Key": data.key },
2352
- body: signature
2353
- });
2354
- const next = await readManagementResponse(res);
2355
- if (!abort.signal.aborted) setPreview({ signature, ...next.routePreview });
2356
- } catch (e) {
2357
- if (!abort.signal.aborted) setPreview({ signature, error: e.message });
2358
- }
2359
- }, 250);
2360
- return () => {
2361
- clearTimeout(timer);
2362
- abort.abort();
2363
- };
2364
- }, [signature, data.key]);
2365
- const pending = preview?.signature !== signature, modes = pending ? [] : preview?.reasoning?.supportedEfforts ?? [];
2366
- const effort = draft.reasoningEffort ?? "", unavailable = !!effort && !pending && !preview?.error && !modes.includes(effort);
2367
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
2368
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2369
- "\u9ED8\u8BA4\u601D\u8003\u6DF1\u5EA6",
2370
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { "aria-describedby": "route-reasoning-help", disabled: busy || pending || !!preview?.error, value: effort, onChange: (e) => setDraft((d) => ({ ...d, reasoningEffort: e.target.value || null })), children: [
2371
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u5E73\u53F0\u9ED8\u8BA4" }),
2372
- effort && !modes.includes(effort) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: effort, disabled: true, children: [
2373
- effortNames[effort] || effort,
2374
- "\uFF08",
2375
- pending ? "\u6838\u5BF9\u4E2D" : "\u5F53\u524D\u4E0D\u53EF\u7528",
2376
- "\uFF09"
2377
- ] }),
2378
- modes.map((e) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: e, children: effortNames[e] || e }, e))
2379
- ] })
2380
- ] }),
2381
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: "route-reasoning-help", className: preview?.error || unavailable ? "warn notice" : "notice", role: "status", children: pending ? "\u6B63\u5728\u6838\u5BF9\u76EE\u6807\u6A21\u578B\u652F\u6301\u7684\u6863\u4F4D\u2026" : preview?.error || (unavailable ? "\u539F\u6863\u4F4D\u5F53\u524D\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u6863\u4F4D\u6216\u5E73\u53F0\u9ED8\u8BA4\u3002" : !preview?.contextKnown ? "\u5C1A\u672A\u83B7\u53D6\u76EE\u6807\u6A21\u578B\u76EE\u5F55\uFF0C\u6682\u65F6\u53EA\u80FD\u4F7F\u7528\u5E73\u53F0\u9ED8\u8BA4\u3002" : !modes.length ? "\u76EE\u6807\u6A21\u578B\u672A\u58F0\u660E\u53EF\u8C03\u6863\u4F4D\uFF0C\u4F7F\u7528\u5E73\u53F0\u9ED8\u8BA4\u3002" : "\u4EC5\u5C55\u793A\u5F53\u524D\u76EE\u6807\u4E0E\u4E0A\u4E0B\u6587\u5BB9\u91CF\u652F\u6301\u7684\u6863\u4F4D\u3002") }),
2382
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u4F1A\u8BDD\u91CC\u624B\u52A8\u9009\u62E9\u7684\u6863\u4F4D\u4F18\u5148\u3002\u6307\u5B9A\u6DF1\u5EA6\u540E\uFF0C\u4EC5\u5728\u652F\u6301\u8BE5\u6863\u4F4D\u7684\u8D26\u53F7\u95F4\u5207\u6362\uFF1B\u5173\u95ED\u601D\u8003\u4EC5\u5728\u6E20\u9053\u652F\u6301\u65F6\u63D0\u4F9B\u3002" })
2383
- ] });
2384
- }
2385
- function RouteForm({ draft, setDraft, data, act, busy, error, notice }) {
2386
- if (draft.freeOnly) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FreeRouteForm, { draft, setDraft, data, act, busy, error, notice });
2387
- const set = (key, value) => setDraft((d) => ({ ...d, [key]: value }));
2388
- const target = (i, patch) => setDraft((d) => ({ ...d, targets: d.targets.map((t, index) => i === index ? { ...t, ...patch } : t) }));
2389
- const move = (i, delta) => {
2390
- const targets = [...draft.targets];
2391
- [targets[i], targets[i + delta]] = [targets[i + delta], targets[i]];
2392
- set("targets", targets);
2393
- };
2394
- const strategyHelp = { failover: "\u4F18\u5148\u4F7F\u7528\u524D\u9762\u7684\u8D26\u53F7\uFF1B\u9047\u5230 4xx \u540E\u6362\u4E0B\u4E00\u4E2A\uFF0C\u6210\u529F\u8D26\u53F7\u7EE7\u7EED\u627F\u63A5\u8BF7\u6C42\u3002", weighted: "\u6309\u6BCF\u4E2A\u8D26\u53F7\u7684\u6743\u91CD\u5206\u914D\u8BF7\u6C42\u3002\u4F8B\u5982 3:1\uFF0C\u957F\u671F\u7EA6 75%:25%\uFF1B\u77ED\u671F\u6BD4\u4F8B\u4E0E\u8BF7\u6C42\u957F\u5EA6\u53EF\u80FD\u4E0D\u540C\u3002", tokens: "\u6BCF\u4E2A\u8D26\u53F7\u7D2F\u8BA1\u8FBE\u5230\u672C\u8F6E Token \u989D\u5EA6\u540E\uFF0C\u4E0B\u4E00\u6B21\u8BF7\u6C42\u6362\u8D26\u53F7\u3002\u6240\u6709\u76EE\u6807\u7528\u5B8C\u989D\u5EA6\u540E\u5F00\u59CB\u65B0\u4E00\u8F6E\u3002", credits: "\u6309\u5E73\u53F0\u4F59\u989D\u4E0B\u964D\u8BA1\u7B97\u672C\u8F6E\u6D88\u8017\uFF0C\u8FBE\u5230\u9608\u503C\u540E\u6362\u8D26\u53F7\u3002\u4F59\u989D\u53EF\u80FD\u5305\u542B\u5176\u4ED6\u5E94\u7528\u7684\u6D88\u8D39\uFF1B\u79EF\u5206\u67E5\u8BE2\u5931\u8D25\u65F6\u6682\u4E0D\u4F7F\u7528\u8BE5\u8D26\u53F7\u3002" };
2395
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: async (e) => {
2396
- e.preventDefault();
2397
- if (draft.id !== "ds4.1f" && draft.targets.some((t) => !t.modelText.trim())) {
2398
- e.currentTarget.querySelector("details")?.setAttribute("open", "");
2399
- return;
2400
- }
2401
- const { id, previousId, revision, reasoning, supportsImages, expiringStatus, maxContextWindow, supportedContextWindows, configuredContextWindow, contextKnown, eligibleAccountIds, enforceContext, ...route } = draft;
2402
- route.targets = route.targets.map((t) => {
2403
- const models = t.modelText.split(",").map((x) => x.trim()).filter(Boolean);
2404
- return { provider: t.provider, ...t.account ? { account: t.account } : {}, ...models.length ? { models } : {}, ...route.strategy === "weighted" ? { weight: Number(t.weight) } : {}, ...route.strategy === "tokens" ? { tokenBudget: Number(t.tokenBudget) } : {}, ...route.strategy === "credits" ? { creditBudget: Number(t.creditBudget) } : {} };
2405
- });
2406
- if (await act({ action: "route.save", id, previousId, revision, route })) setDraft(null);
2407
- }, children: [
2408
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
2409
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
2410
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2411
- "\u8DEF\u7531\u540D\u79F0",
2412
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { required: true, maxLength: 200, value: draft.name, disabled: busy, onChange: (e) => set("name", e.target.value), placeholder: "\u4F8B\u5982 \u6211\u7684 Flash \u81EA\u52A8\u5207\u6362" })
2413
- ] }),
2414
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u540D\u79F0\u663E\u793A\u5728 DSH \u6A21\u578B\u5217\u8868\u4E2D\uFF0C\u53EF\u968F\u65F6\u4FEE\u6539\uFF0C\u4E0D\u5F71\u54CD\u5DF2\u6709\u4F1A\u8BDD\u7684\u8DEF\u7531\u9009\u62E9\u3002" }),
2415
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", "aria-labelledby": "route-model-parameters", children: [
2416
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { id: "route-model-parameters", children: "\u6A21\u578B\u53C2\u6570" }),
2417
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid", children: [
2418
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
2419
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2420
- "\u4E0A\u4E0B\u6587\u5BB9\u91CF",
2421
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { disabled: busy, value: draft.contextMode ?? "maximum", onChange: (e) => set("contextMode", e.target.value), children: [
2422
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "maximum", children: "\u4F7F\u7528\u6A21\u578B\u6700\u5927\u5BB9\u91CF\uFF08\u9ED8\u8BA4\uFF09" }),
2423
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "custom", children: "\u624B\u52A8\u8BBE\u7F6E\u672C\u5730\u9884\u7B97" })
2424
- ] })
2425
- ] }),
2426
- draft.contextMode === "custom" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2427
- "\u4E0A\u4E0B\u6587\u9884\u7B97\uFF08Token\uFF09",
2428
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", disabled: busy, min: "1", required: true, value: draft.contextWindow, onChange: (e) => set("contextWindow", Number(e.target.value)) })
2429
- ] }),
2430
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u9ED8\u8BA4\u968F\u6A21\u578B\u76EE\u5F55\u66F4\u65B0\u3002\u53EA\u5411\u652F\u6301\u5F53\u524D\u5BB9\u91CF\u7684\u6E20\u9053\u5207\u6362\uFF1B\u8C03\u4F4E\u9884\u7B97\u53EF\u8BA9\u66F4\u591A\u6E20\u9053\u53C2\u4E0E\u3002\u4E0D\u4F1A\u5220\u9664\u4F1A\u8BDD\u5386\u53F2\u3002" })
2431
- ] }),
2432
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouteReasoningSelect, { draft, setDraft, data, busy })
2433
- ] })
2434
- ] }),
2435
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2436
- "\u8D26\u53F7\u5207\u6362\u89C4\u5219",
2437
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { disabled: busy, value: draft.strategy, onChange: (e) => set("strategy", e.target.value), children: Object.entries(strategies).map(([id, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: id, children: label }, id)) })
2438
- ] }),
2439
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "steps", children: [
2440
- strategyHelp[draft.strategy],
2441
- ["tokens", "credits"].includes(draft.strategy) && " \u6B63\u5728\u8F93\u51FA\u7684\u56DE\u7B54\u4F1A\u5B8C\u6210\uFF0C\u989D\u5EA6\u5141\u8BB8\u8D85\u8FC7\u6700\u540E\u4E00\u6B21\u8BF7\u6C42\u7684\u7528\u91CF\u3002"
2442
- ] }),
2443
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "box stack", children: [
2444
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
2445
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", disabled: busy, checked: draft.preferExpiringCredits !== false, onChange: (e) => set("preferExpiringCredits", e.target.checked) }),
2446
- "\u4F18\u5148\u4F7F\u7528\u4E34\u671F\u79EF\u5206\uFF08\u9ED8\u8BA4\u5F00\u542F\uFF09"
2447
- ] }),
2448
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u4F18\u5148\u4F7F\u7528\u4ECD\u6709\u4F59\u989D\u4E14\u66F4\u65E9\u5230\u671F\u7684\u79EF\u5206\u5305\uFF1B\u4F18\u5148\u7EA7\u9AD8\u4E8E\u987A\u5E8F\u548C\u6743\u91CD\uFF0C\u4ECD\u9075\u5B88\u6BCF\u8F6E\u989D\u5EA6\u4E0E\u6545\u969C\u5207\u6362\u3002\u5E73\u53F0\u672A\u63D0\u4F9B\u6709\u6548\u671F\u6216\u7528\u91CF\u6570\u636E\u8FC7\u671F\u65F6\uFF0C\u6309\u666E\u901A\u89C4\u5219\u6267\u884C\u3002" }),
2449
- draft.preferExpiringCredits !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2450
- "\u4E34\u671F\u8303\u56F4\uFF08\u5929\uFF09",
2451
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", disabled: busy, min: "1", max: "365", required: true, value: draft.expiringWithinDays ?? 7, onChange: (e) => set("expiringWithinDays", Number(e.target.value)) })
2452
- ] })
2453
- ] }),
2454
- draft.preferExpiringCredits !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExpiryStatus, { route: data.routes.find((r) => r.id === draft.previousId) || draft, busy, act, revision: draft.revision, onForce: (result) => setDraft((d) => ({ ...d, revision: result.revision, expiringStatus: result.routes.find((r) => r.id === draft.previousId)?.expiringStatus })) }),
2455
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "box stack", children: [
2456
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
2457
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", disabled: busy, checked: draft.balanceCredits !== false, onChange: (e) => set("balanceCredits", e.target.checked) }),
2458
- "\u79EF\u5206\u4F7F\u7528\u5747\u8861\uFF08\u9ED8\u8BA4\u5F00\u542F\uFF09"
2459
- ] }),
2460
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u67D0\u4E2A\u8D26\u53F7\u672C\u8F6E\u6D88\u8017\u8FBE\u5230\u9608\u503C\u540E\uFF0C\u4E0B\u4E00\u6B21\u8BF7\u6C42\u4F18\u5148\u6362\u5230\u5176\u4ED6\u4ECD\u6709\u4F59\u989D\u7684\u8D26\u53F7\u3002\u6240\u6709\u8D26\u53F7\u90FD\u8FBE\u5230\u9608\u503C\u65F6\u7EE7\u7EED\u4F7F\u7528\u73B0\u6709\u8D26\u53F7\uFF0C\u4E0D\u4F1A\u56E0\u6B64\u5931\u8D25\u3002\u4F59\u989D\u7531\u5E73\u53F0\u67E5\u8BE2\u63A8\u7B97\uFF0C\u53EF\u80FD\u591A\u51FA\u4E00\u6B21\u8BF7\u6C42\u7684\u7528\u91CF\uFF1B\u67E5\u8BE2\u5931\u8D25\u671F\u95F4\u4E0D\u505A\u5207\u6362\u5224\u65AD\u3002" }),
2461
- draft.balanceCredits !== false && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2462
- "\u6BCF\u8D26\u53F7\u5207\u6362\u9608\u503C\uFF08\u79EF\u5206\uFF09",
2463
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", disabled: busy, min: "1", step: "1", required: true, value: draft.creditBalanceThreshold ?? 1e3, onChange: (e) => set("creditBalanceThreshold", Number(e.target.value)) })
2464
- ] })
2465
- ] }),
2466
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "box stack", children: [
2467
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
2468
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", disabled: busy, checked: draft.discountOrder !== false, onChange: (e) => set("discountOrder", e.target.checked) }),
2469
- "\u6309\u79EF\u5206\u6298\u6263\u6392\u5E8F\uFF08\u9ED8\u8BA4\u5F00\u542F\uFF09"
2470
- ] }),
2471
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u6BCF\u6B21\u8BF7\u6C42\u6309\u5404\u6E20\u9053\u5F53\u524D\u516C\u5E03\u7684\u79EF\u5206\u500D\u7387\u4ECE\u5C0F\u5230\u5927\u6392\u5217\u5019\u9009\u8D26\u53F7\uFF0C\u500D\u7387\u8D8A\u4F4E\u8D8A\u4FBF\u5B9C\u3001\u8D8A\u5148\u7528\u3002\u500D\u7387\u6765\u81EA\u6A21\u578B\u76EE\u5F55\u5E76\u968F\u76EE\u5F55\u5237\u65B0\uFF0C\u9650\u65F6\u4FC3\u9500\u5230\u671F\u540E\u81EA\u52A8\u6062\u590D\u3002\u4E34\u671F\u79EF\u5206\u4E0E\u79EF\u5206\u5747\u8861\u989D\u5EA6\u4ECD\u7136\u4F18\u5148\uFF0C\u6298\u6263\u53EA\u5728\u540C\u7C7B\u5019\u9009\u4E4B\u95F4\u51B3\u5B9A\u5148\u540E\uFF1B\u6CA1\u6709\u516C\u5E03\u500D\u7387\u7684\u8D26\u53F7\u6392\u5728\u6700\u540E\u3002" })
2472
- ] }),
2473
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
2474
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u6A21\u578B\u4E0E\u8D26\u53F7\u76EE\u6807" }),
2475
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "notice", children: "\u6309\u4E0B\u65B9\u987A\u5E8F\u5207\u6362" })
2476
- ] }),
2477
- draft.targets.map((t, i) => {
2478
- const models = data.providers.find((p) => p.id === t.provider)?.models || [];
2479
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
2480
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar target-head", children: [
2481
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("strong", { children: [
2482
- "\u76EE\u6807 ",
2483
- i + 1
2484
- ] }),
2485
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
2486
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || i === 0, onClick: () => move(i, -1), children: "\u524D\u79FB" }),
2487
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || i === draft.targets.length - 1, onClick: () => move(i, 1), children: "\u540E\u79FB" }),
2488
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy || draft.targets.length === 1, onClick: () => set("targets", draft.targets.filter((_, index) => index !== i)), children: "\u79FB\u9664" })
2489
- ] })
2490
- ] }),
2491
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid", children: [
2492
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2493
- "\u4F9B\u5E94\u5546",
2494
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { disabled: busy, value: t.provider, onChange: (e) => target(i, { provider: e.target.value, account: "", modelText: "" }), children: data.providers.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: p.id, children: p.name }, p.id)) })
2495
- ] }),
2496
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2497
- "\u4F7F\u7528\u8D26\u53F7",
2498
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { disabled: busy, value: t.account || "", onChange: (e) => target(i, { account: e.target.value }), children: [
2499
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u6B64\u4F9B\u5E94\u5546\u5168\u90E8\u542F\u7528\u8D26\u53F7" }),
2500
- data.accounts.filter((a) => a.provider === t.provider).map((a) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: a.id, children: a.name }, a.id))
2501
- ] })
2502
- ] }),
2503
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "full", children: [
2504
- "\u76EE\u6807\u6A21\u578B",
2505
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { disabled: busy, required: draft.id !== "ds4.1f", value: t.modelText, onChange: (e) => {
2506
- if (e.target.value) target(i, { modelText: e.target.value });
2507
- }, children: [
2508
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "\u4ECE\u5DF2\u53D1\u73B0\u6A21\u578B\u4E2D\u9009\u62E9" }),
2509
- t.modelText && !models.some((m) => m.id === t.modelText) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: t.modelText, children: t.modelText }),
2510
- models.map((m) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", { value: m.id, children: [
2511
- m.name,
2512
- " \xB7 ",
2513
- m.id
2514
- ] }, m.id))
2515
- ] })
2516
- ] }),
2517
- draft.strategy === "weighted" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2518
- "\u6BCF\u4E2A\u8D26\u53F7\u7684\u6743\u91CD",
2519
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", disabled: busy, min: "1", max: "1000", required: true, value: t.weight, onChange: (e) => target(i, { weight: e.target.value }) })
2520
- ] }),
2521
- draft.strategy === "tokens" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2522
- "\u6BCF\u4E2A\u8D26\u53F7\u6BCF\u8F6E Token \u989D\u5EA6",
2523
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", disabled: busy, min: "1", step: "1", required: true, value: t.tokenBudget, onChange: (e) => target(i, { tokenBudget: e.target.value }) })
2524
- ] }),
2525
- draft.strategy === "credits" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2526
- "\u6BCF\u4E2A\u8D26\u53F7\u6BCF\u8F6E\u79EF\u5206\u6D88\u8017",
2527
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", disabled: busy, min: "0.01", step: "any", required: true, value: t.creditBudget, onChange: (e) => target(i, { creditBudget: e.target.value }) })
2528
- ] })
2529
- ] }),
2530
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [
2531
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u9AD8\u7EA7\uFF1A\u624B\u52A8\u586B\u5199\u5019\u9009\u6A21\u578B ID" }),
2532
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { marginTop: 10 }, children: [
2533
- "\u5019\u9009\u6A21\u578B ID\uFF08\u9017\u53F7\u5206\u9694\uFF09",
2534
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { disabled: busy, value: t.modelText, onChange: (e) => target(i, { modelText: e.target.value }), placeholder: "\u6309\u987A\u5E8F\u5339\u914D\u771F\u5B9E\u6A21\u578B\u76EE\u5F55" })
2535
- ] })
2536
- ] })
2537
- ] }, t.key);
2538
- }),
2539
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy, onClick: () => set("targets", [...draft.targets, { provider: "workbuddy", account: "", key: crypto.randomUUID(), weight: 1, tokenBudget: 1e5, creditBudget: 100, modelText: "" }]), children: "\u6DFB\u52A0\u5207\u6362\u76EE\u6807" }),
2540
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { children: [
2541
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u9AD8\u7EA7\uFF1A\u8F93\u51FA\u957F\u5EA6" }),
2542
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid", style: { marginTop: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
2543
- "\u6700\u5927\u8F93\u51FA\u957F\u5EA6",
2544
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "number", disabled: busy, min: "1", max: draft.contextWindow, required: true, value: draft.maxTokens, onChange: (e) => set("maxTokens", Number(e.target.value)) })
2545
- ] }) })
2546
- ] })
2547
- ] }),
2548
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-foot bar", children: [
2549
- draft.previousId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy, onClick: async () => {
2550
- if (await act({ action: "route.remove", revision: draft.revision, id: draft.previousId })) setDraft(null);
2551
- }, children: "\u79FB\u9664\u8DEF\u7531" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, type: "button", onClick: () => setDraft(null), children: "\u53D6\u6D88" }),
2552
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", type: "submit", disabled: busy, children: busy ? "\u6B63\u5728\u4FDD\u5B58\u2026" : "\u4FDD\u5B58\u8DEF\u7531" })
2553
- ] })
2554
- ] });
2555
- }
2556
- function InitialSetup({ data, busy, act, go }) {
2557
- const discovery = data.localDiscovery ?? [];
2558
- const discovering = data.startup?.phase === "discovering";
2559
- const saved = discovery.reduce((n, s) => n + (s.savedCount ?? 0), 0);
2560
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", "aria-label": "\u9996\u6B21\u8D26\u53F7\u8BBE\u7F6E", children: [
2561
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
2562
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
2563
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", { children: [
2564
- "\u672C\u673A\u8D26\u53F7\u81EA\u52A8\u83B7\u53D6",
2565
- discovering ? "\u8FDB\u884C\u4E2D" : discovery.length ? "\u5DF2\u5B8C\u6210" : "\u5F85\u91CD\u8BD5"
2566
- ] }),
2567
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: discovering ? "\u6B63\u5728\u540E\u53F0\u8BFB\u53D6 WorkBuddy / Trae \u672C\u673A\u767B\u5F55\uFF0C\u65E0\u9700\u624B\u52A8\u91CD\u590D\u83B7\u53D6\uFF0C\u5DF2\u6709\u8D26\u53F7\u53EF\u4EE5\u7EE7\u7EED\u4F7F\u7528\u3002" : saved ? `\u5DF2\u4FDD\u5B58 ${saved} \u4E2A WorkBuddy / Trae \u672C\u673A\u767B\u5F55\uFF0C\u65E0\u9700\u518D\u6B21\u624B\u52A8\u6DFB\u52A0\u3002` : "\u6682\u672A\u4FDD\u5B58\u672C\u673A\u767B\u5F55\u3002\u5148\u5728\u5B98\u65B9\u5BA2\u6237\u7AEF\u767B\u5F55\uFF0C\u518D\u70B9\u51FB\u300C\u4E00\u952E\u83B7\u53D6\u5E76\u4FDD\u5B58\u300D\u3002" })
2568
- ] }),
2569
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
2570
- void act({ action: "setup.dismiss" });
2571
- }, children: "\u77E5\u9053\u4E86" })
2572
- ] }),
2573
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "providers", children: discovery.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "steps", children: [
2574
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: data.providers.find((p) => p.id === s.provider)?.name ?? s.provider }),
2575
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: (s.savedCount ?? 0) > 0 ? "good" : "notice", children: s.savedCount ? `\u5DF2\u4FDD\u5B58 ${s.savedCount} \u4E2A\u767B\u5F55` : s.state === "found" ? "\u68C0\u6D4B\u5230\u767B\u5F55\uFF1B\u5DF2\u5FFD\u7565\u6216\u5C1A\u672A\u4FDD\u5B58\uFF0C\u8BF7\u91CD\u65B0\u83B7\u53D6" : s.state === "unreadable" ? "\u767B\u5F55\u6587\u4EF6\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u8BF7\u5728\u5BA2\u6237\u7AEF\u91CD\u65B0\u767B\u5F55\u540E\u91CD\u8BD5" : "\u672A\u68C0\u6D4B\u5230\u767B\u5F55\uFF0C\u8BF7\u5148\u767B\u5F55\u5B98\u65B9\u5BA2\u6237\u7AEF" })
2576
- ] }, s.provider)) }),
2577
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
2578
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy || discovering, onClick: () => {
2579
- void act({ action: "accounts.discover" });
2580
- }, children: "\u4E00\u952E\u83B7\u53D6\u5E76\u4FDD\u5B58 WorkBuddy / Trae" }),
2581
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => go("accounts"), children: "\u67E5\u770B\u8D26\u53F7 / \u624B\u52A8\u6DFB\u52A0" }),
2582
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => go("routes"), children: "\u9009\u62E9\u8DEF\u7531\u6A21\u578B" })
2583
- ] }),
2584
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u9996\u6B21\u542F\u52A8\u81EA\u52A8\u6267\u884C\u4E00\u6B21\uFF0C\u4E4B\u540E\u6BCF\u5206\u949F\u68C0\u6D4B\u65B0\u589E\u767B\u5F55\u3002Qoder \u4F7F\u7528 PAT\uFF0C\u8BF7\u5230\u300C\u8D26\u53F7\u4E0E\u767B\u5F55\u300D\u6DFB\u52A0\uFF1B\u672A\u5B89\u88C5\u5BA2\u6237\u7AEF\u4E5F\u53EF\u4EE5\u624B\u52A8\u586B\u5199\u51ED\u8BC1\u3002" })
2585
- ] });
2586
- }
2587
- var updateNames = { unchecked: "\u5F85\u68C0\u67E5", available: "\u53EF\u66F4\u65B0", current: "\u5DF2\u540C\u6B65", pinned: "\u56FA\u5B9A\u63D0\u4EA4", unsupported: "\u672C\u5730\u6765\u6E90", failed: "\u68C0\u67E5 / \u5B89\u88C5\u5931\u8D25", installed: "\u5DF2\u5B89\u88C5" };
2588
- function PluginUpdatesPanel({ data, busy, act }) {
2589
- const [query, setQuery] = (0, import_react.useState)(""), [selected, setSelected] = (0, import_react.useState)([]), [plan, setPlan] = (0, import_react.useState)(null), [registry, setRegistry] = (0, import_react.useState)(""), [filter, setFilter] = (0, import_react.useState)("all"), [pluginSearch, setPluginSearch] = (0, import_react.useState)("");
2590
- const [diagnostic, setDiagnostic] = (0, import_react.useState)(null), [copied, setCopied] = (0, import_react.useState)(false);
2591
- const running = data?.job?.state === "running", blocked = busy || running;
2592
- const rows = (data?.rows ?? []).filter((r) => r.source.kind !== "builtin"), available = rows.filter((r) => r.status === "available" || r.status === "failed" && r.target);
2593
- (0, import_react.useEffect)(() => {
2594
- if (data?.available && !running) void act({ action: !data.checkedAt || Date.now() - data.checkedAt > 864e5 ? "plugins.check" : "plugins.list" });
2595
- }, []);
2596
- const chosen = available.filter((r) => selected.includes(r.name));
2597
- const visibleRows = rows.filter((r) => r.name.toLowerCase().includes(pluginSearch.toLowerCase()) && (filter === "all" || (filter === "updates" ? available.includes(r) : r.source.kind === filter)));
2598
- async function submitPlan() {
2599
- if (await act(plan.kind === "install" ? { action: "plugins.install", spec: plan.spec, registry: registry || void 0 } : { action: "plugins.update", names: plan.rows.map((r) => r.name), registry: registry || void 0 })) {
2600
- setPlan(null);
2601
- setSelected([]);
2602
- }
2603
- }
2604
- if (!data?.available) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
2605
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5F53\u524D DSH \u672A\u63D0\u4F9B\u63D2\u4EF6\u7BA1\u7406\u63A5\u53E3" }),
2606
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "\u8BF7\u5347\u7EA7 DeepSeek Harness \u540E\u91CD\u8BD5\u3002\u672C\u9875\u7BA1\u7406\u5F53\u524D DSH \u914D\u7F6E\u4E2D\u7531\u7528\u6237\u5B89\u88C5\u7684\u63D2\u4EF6\u3002" })
2607
- ] });
2608
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
2609
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
2610
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
2611
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
2612
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u7528\u6237\u5B89\u88C5\u7684\u63D2\u4EF6\u4E0E\u66F4\u65B0" }),
2613
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
2614
- rows.length,
2615
- " \u4E2A\u7528\u6237\u5B89\u88C5\u63D2\u4EF6 \xB7 ",
2616
- available.length,
2617
- " \u4E2A\u53EF\u66F4\u65B0"
2618
- ] })
2619
- ] }),
2620
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: blocked, onClick: () => {
2621
- void act({ action: "plugins.check" });
2622
- }, children: "\u68C0\u67E5\u5168\u90E8\u66F4\u65B0" })
2623
- ] }),
2624
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
2625
- "\u4E0A\u6B21\u68C0\u67E5 ",
2626
- when(data.checkedAt),
2627
- " \xB7 \u6BCF\u5929\u81EA\u52A8\u68C0\u67E5\u5E76\u63D0\u9192"
2628
- ] }),
2629
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "help", children: [
2630
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u5B89\u88C5\u6E90\u4E0E\u68C0\u67E5\u89C4\u5219" }),
2631
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
2632
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
2633
- "npm \u5B89\u88C5\u6E90",
2634
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: registry, disabled: blocked, onChange: (e) => setRegistry(e.target.value), children: [
2635
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "DSH \u8BBE\u7F6E\uFF08\u542B\u56DE\u9000\u6765\u6E90\uFF09" }),
2636
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "https://registry.npmjs.org/", children: "npm \u5B98\u65B9" }),
2637
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "https://registry.npmmirror.com/", children: "npmmirror" })
2638
- ] })
2639
- ] }),
2640
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "npm \u6309\u7248\u672C / \u53D1\u5E03\u9891\u9053\u68C0\u67E5\uFF0CGitHub \u6309\u5206\u652F\u63D0\u4EA4\u68C0\u67E5\uFF1B\u4FDD\u7559\u542F\u7528\u72B6\u6001\uFF0C\u56FA\u5B9A Git \u63D0\u4EA4\u4FDD\u6301\u4E0D\u52A8\u3002" })
2641
- ] })
2642
- ] })
2643
- ] }),
2644
- data.job && !(data.job.kind === "check" && data.job.state === "done") && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", "aria-live": "polite", children: [
2645
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
2646
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: running ? data.job.kind === "check" ? "\u6B63\u5728\u68C0\u67E5\u66F4\u65B0\u2026" : "\u6B63\u5728\u5B89\u88C5\u63D2\u4EF6\u2026" : data.job.state === "cancelled" ? "\u64CD\u4F5C\u5DF2\u53D6\u6D88" : data.job.state === "failed" || data.job.results.some((r) => r.status === "failed") ? "\u6709\u63D2\u4EF6\u672A\u5B8C\u6210\u5B89\u88C5" : "\u64CD\u4F5C\u5DF2\u5B8C\u6210" }),
2647
- running && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
2648
- void act({ action: "plugins.cancel" });
2649
- }, children: "\u53D6\u6D88" })
2650
- ] }),
2651
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("progress", { max: Math.max(1, data.job.total), value: data.job.results.length, "aria-label": "\u63D2\u4EF6\u64CD\u4F5C\u8FDB\u5EA6" }),
2652
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
2653
- data.job.results.length,
2654
- " / ",
2655
- data.job.total,
2656
- data.job.current ? ` \xB7 ${data.job.current}` : ""
2657
- ] }),
2658
- data.job.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "error", children: data.job.message }),
2659
- data.job.results.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "item", children: [
2660
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: r.name }),
2661
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: r.status === "failed" ? "error" : "notice", children: r.message || updateNames[r.status] || r.status }),
2662
- r.diagnostic && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => {
2663
- setCopied(false);
2664
- setDiagnostic(JSON.stringify({ plugin: r.name, targetVersion: r.expectedVersion, ...r.diagnostic }, null, 2));
2665
- }, children: "\u67E5\u770B\u8131\u654F\u8BCA\u65AD" }),
2666
- r.pendingBuilds?.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
2667
- "\u5F85\u6388\u6743\u811A\u672C\uFF1A",
2668
- r.pendingBuilds.join("\u3001"),
2669
- "\u3002\u8BF7\u5728 DSH \u539F\u63D2\u4EF6\u5B89\u88C5\u9875\u6388\u6743\u540E\u91CD\u8BD5\u3002"
2670
- ] })
2671
- ] }, r.name + i)),
2672
- data.job.results.some((r) => r.restartRequired) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "\u66F4\u65B0\u6587\u4EF6\u5DF2\u5B89\u88C5\u3002macOS \u4F7F\u7528 \u2318Q \u5B8C\u5168\u9000\u51FA DSH \u540E\u91CD\u5F00\uFF1BWindows \u9000\u51FA\u6258\u76D8\u5E94\u7528\u540E\u91CD\u5F00\uFF1B\u7F51\u9875\u7248\u91CD\u542F\u670D\u52A1\u3002\u5173\u95ED\u7A97\u53E3\u548C\u300C\u5237\u65B0\u9762\u677F\u300D\u4E0D\u4F1A\u91CD\u8F7D\u540E\u53F0\u3002" })
2673
- ] }),
2674
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box table-shell", children: [
2675
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar section-pad", children: [
2676
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
2677
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked || !available.length, onClick: () => setSelected(available.map((r) => r.name)), children: "\u9009\u62E9\u5168\u90E8\u53EF\u66F4\u65B0" }),
2678
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked || !selected.length, onClick: () => setSelected([]), children: "\u6E05\u7A7A\u9009\u62E9" })
2679
- ] }),
2680
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: "primary", disabled: blocked || !chosen.length, onClick: () => setPlan({ kind: "update", rows: chosen }), children: [
2681
- "\u66F4\u65B0\u6240\u9009\uFF08",
2682
- chosen.length,
2683
- "\uFF09"
2684
- ] })
2685
- ] }),
2686
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row section-pad", children: [
2687
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { flex: 1 }, children: [
2688
- "\u641C\u7D22\u5DF2\u5B89\u88C5\u63D2\u4EF6",
2689
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { value: pluginSearch, onChange: (e) => setPluginSearch(e.target.value), placeholder: "\u6309\u63D2\u4EF6\u540D\u79F0\u7B5B\u9009" })
2690
- ] }),
2691
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
2692
- "\u663E\u793A\u8303\u56F4",
2693
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: filter, onChange: (e) => setFilter(e.target.value), children: [
2694
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "all", children: "\u5168\u90E8\u7528\u6237\u5B89\u88C5\u63D2\u4EF6" }),
2695
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "updates", children: "\u53EF\u66F4\u65B0 / \u91CD\u8BD5" }),
2696
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "npm", children: "npm \u6765\u6E90" }),
2697
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "github", children: "GitHub \u6765\u6E90" })
2698
- ] })
2699
- ] })
2700
- ] }),
2701
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", role: "region", "aria-label": "\u7528\u6237\u5B89\u88C5\u63D2\u4EF6\u5217\u8868", tabIndex: "0", children: [
2702
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
2703
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
2704
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u63D2\u4EF6 / \u9009\u62E9" }),
2705
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u6765\u6E90\u4E0E\u7248\u672C" }),
2706
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u72B6\u6001" }),
2707
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "cell-actions", children: "\u64CD\u4F5C" })
2708
- ] }) }),
2709
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: visibleRows.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: selected.includes(r.name) ? "selected" : "", children: [
2710
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
2711
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
2712
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { "aria-label": `\u9009\u62E9\u66F4\u65B0 ${r.name}`, type: "checkbox", disabled: blocked || !available.includes(r), checked: selected.includes(r.name), onChange: (e) => setSelected(e.target.checked ? [...selected, r.name] : selected.filter((n) => n !== r.name)) }),
2713
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { className: "mono", children: r.name })
2714
- ] }),
2715
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: r.enabled ? "\u542F\u7528" : "\u505C\u7528" })
2716
- ] }),
2717
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
2718
- r.source.kind === "npm" ? `npm \xB7 ${r.version || "\u672A\u77E5"}${r.latestVersion ? " \u2192 " + r.latestVersion : ""}` : r.source.kind === "github" ? `GitHub \xB7 ${r.version || "\u672A\u77E5\u7248\u672C"}` : "\u672C\u5730\u6587\u4EF6 / \u5F00\u53D1\u94FE\u63A5",
2719
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted mono", children: r.source.kind === "npm" ? `\u5B89\u88C5\u58F0\u660E ${r.source.source} \xB7 \u68C0\u67E5 ${r.source.tag}` : r.source.kind === "github" ? `${r.commit?.slice(0, 8) || "\u672A\u77E5\u63D0\u4EA4"}${r.latestCommit ? " \u2192 " + r.latestCommit.slice(0, 8) : ""}` : "" })
2720
- ] }),
2721
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
2722
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: r.status === "failed" ? "error" : r.status === "available" ? "good" : "muted", children: updateNames[r.status] }),
2723
- r.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: r.status === "failed" ? "error" : "muted", children: r.message })
2724
- ] }),
2725
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "cell-actions", children: available.includes(r) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked, onClick: () => setPlan({ kind: "update", rows: [r] }), children: "\u67E5\u770B\u5E76\u66F4\u65B0" }) : "\u2014" })
2726
- ] }, r.name)) })
2727
- ] }),
2728
- !visibleRows.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: running ? "\u6B63\u5728\u8BFB\u53D6\u63D2\u4EF6\u6E05\u5355\u2026" : rows.length ? "\u6CA1\u6709\u5339\u914D\u7684\u5DF2\u5B89\u88C5\u63D2\u4EF6\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002" : "\u5F53\u524D\u914D\u7F6E\u5C1A\u672A\u8BFB\u53D6\u63D2\u4EF6\uFF0C\u8BF7\u68C0\u67E5\u66F4\u65B0\u3002" })
2729
- ] })
2730
- ] }),
2731
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "box help install-plugin", children: [
2732
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u5B89\u88C5 npm / GitHub \u63D2\u4EF6" }),
2733
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
2734
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "row", onSubmit: (e) => {
2735
- e.preventDefault();
2736
- const spec = new FormData(e.currentTarget).get("spec").trim();
2737
- if (spec) setPlan({ kind: "install", spec });
2738
- }, children: [
2739
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { flex: 1 }, children: [
2740
- "\u5B89\u88C5\u5730\u5740",
2741
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { name: "spec", value: query, onChange: (e) => setQuery(e.target.value), disabled: blocked, required: true, placeholder: "\u5305\u540D\u3001\u5305\u540D@\u7248\u672C \u6216 github:\u7528\u6237/\u4ED3\u5E93", autoComplete: "off" })
2742
- ] }),
2743
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked || !query.trim(), children: "\u67E5\u770B\u5E76\u5B89\u88C5" })
2744
- ] }),
2745
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u4F7F\u7528 DSH \u81EA\u5E26\u5B89\u88C5\u5668\u6267\u884C\u517C\u5BB9\u68C0\u67E5\u3001\u955C\u50CF\u91CD\u8BD5\u548C\u5931\u8D25\u56DE\u6EDA\u3002npm \u955C\u50CF\u53EA\u4F5C\u7528\u4E8E npm \u5305\uFF0CGitHub \u4E0B\u8F7D\u5931\u8D25\u9700\u68C0\u67E5 GitHub \u7F51\u7EDC\u3002\u7F51\u7EDC\u5931\u8D25\u540E\u53EF\u91CD\u65B0\u68C0\u67E5\u6216\u66F4\u6362 npm \u5B89\u88C5\u6E90\u518D\u91CD\u8BD5\u3002" })
2746
- ] })
2747
- ] }),
2748
- diagnostic && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: "\u63D2\u4EF6\u5B89\u88C5\u8BCA\u65AD", close: () => setDiagnostic(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
2749
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u4EE5\u4E0B\u4FE1\u606F\u53EA\u542B\u63D2\u4EF6\u540D\u3001\u7248\u672C\u3001\u7CFB\u7EDF\u548C\u9519\u8BEF\u5206\u7C7B\uFF0C\u53EF\u590D\u5236\u7528\u4E8E\u6392\u67E5\uFF1B\u672A\u5305\u542B\u539F\u59CB\u65E5\u5FD7\u3001\u7528\u6237\u540D\u8DEF\u5F84\u6216\u51ED\u8BC1\u3002\u82E5\u539F\u56E0\u672A\u77E5\uFF0C\u8BF7\u5728 DSH \u539F\u751F\u63D2\u4EF6\u9875\u83B7\u53D6\u5B89\u88C5\u65E5\u5FD7\u3002" }),
2750
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { "aria-label": "\u8131\u654F\u5B89\u88C5\u8BCA\u65AD", readOnly: true, rows: "9", value: diagnostic, onFocus: (e) => e.currentTarget.select() }),
2751
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: async () => {
2752
- try {
2753
- await navigator.clipboard.writeText(diagnostic);
2754
- setCopied(true);
2755
- } catch {
2756
- setCopied(false);
2757
- }
2758
- }, children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u8BCA\u65AD" })
2759
- ] }) }),
2760
- plan && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Modal, { title: plan.kind === "install" ? "\u786E\u8BA4\u5B89\u88C5\u63D2\u4EF6" : "\u786E\u8BA4\u66F4\u65B0\u63D2\u4EF6", close: () => setPlan(null), busy: blocked, children: [
2761
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
2762
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "\u8FD9\u4E9B\u64CD\u4F5C\u4F5C\u7528\u4E8E\u5F53\u524D DSH \u914D\u7F6E\u7684\u6240\u6709\u4F1A\u8BDD\u3002\u5B89\u88C5\u540E\u662F\u5426\u9700\u8981\u91CD\u542F\uFF0C\u4F1A\u5728\u7ED3\u679C\u4E2D\u8BF4\u660E\u3002" }),
2763
- plan.kind === "install" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mono", children: plan.spec }) : plan.rows.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "steps", children: [
2764
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: r.name }),
2765
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mono", children: r.target }),
2766
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: r.source.kind === "npm" ? `${r.version || "\u672A\u77E5"} \u2192 ${r.latestVersion}` : `${r.commit?.slice(0, 8) || "\u672A\u77E5\u63D0\u4EA4"} \u2192 ${r.latestCommit?.slice(0, 8) || "\u672A\u77E5\u63D0\u4EA4"}` }),
2767
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
2768
- "\u4FDD\u7559\u4E3A",
2769
- r.enabled ? "\u542F\u7528" : "\u505C\u7528",
2770
- "\uFF1B",
2771
- r.source.kind === "github" ? "\u7EE7\u7EED\u8DDF\u968F\u539F\u5206\u652F / \u6807\u7B7E" : "\u66F4\u65B0\u5230\u6240\u793A npm \u7248\u672C",
2772
- "\u3002"
2773
- ] })
2774
- ] }, r.name)),
2775
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
2776
- "npm \u5B89\u88C5\u6E90\uFF1A",
2777
- registry || "\u6CBF\u7528 DSH \u8BBE\u7F6E"
2778
- ] })
2779
- ] }),
2780
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-foot row", children: [
2781
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: "primary", disabled: blocked, onClick: () => {
2782
- void submitPlan();
2783
- }, children: [
2784
- "\u786E\u8BA4",
2785
- plan.kind === "install" ? "\u5B89\u88C5" : "\u66F4\u65B0"
2786
- ] }),
2787
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked, onClick: () => setPlan(null), children: "\u53D6\u6D88" })
2788
- ] })
2789
- ] })
2790
- ] });
2791
- }
2792
- return module.exports; } });
2793
- //# sourceMappingURL=client.js.map