dsh-opencode-go 0.1.20 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +48 -3
- package/README.md +40 -4
- package/docs/development.md +4 -2
- package/docs/verification.md +87 -0
- package/lib/client.js +1376 -184
- package/lib/index.js +351 -23
- package/lib/types/accounts.d.ts +26 -0
- package/lib/types/adapter.d.ts +14 -0
- package/lib/types/catalog.d.ts +2 -1
- package/lib/types/client/AccountsCard.d.ts +19 -0
- package/lib/types/client/Section.d.ts +3 -6
- package/lib/types/client/UsagePill.d.ts +4 -2
- package/lib/types/client/accounts-controller.d.ts +80 -0
- package/lib/types/client/locales.d.ts +46 -1
- package/lib/types/client/section-controller.d.ts +13 -2
- package/lib/types/config.d.ts +6 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/json-response.d.ts +1 -1
- package/lib/types/proxy-url.d.ts +2 -0
- package/lib/types/proxy.d.ts +11 -0
- package/lib/types/usage-contract.d.ts +5 -0
- package/lib/types/usage.d.ts +14 -2
- package/package.json +4 -2
package/lib/client.js
CHANGED
|
@@ -38,9 +38,9 @@ __export(index_exports, {
|
|
|
38
38
|
module.exports = __toCommonJS(index_exports);
|
|
39
39
|
|
|
40
40
|
// src/client/Section.tsx
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
var
|
|
41
|
+
var import_react3 = require("react");
|
|
42
|
+
var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
43
|
+
var primitives2 = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
|
|
44
44
|
|
|
45
45
|
// src/client/ModelEditor.tsx
|
|
46
46
|
var import_react = require("react");
|
|
@@ -145,10 +145,10 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")
|
|
|
145
145
|
const style = document.createElement("style");
|
|
146
146
|
style.dataset.plugin = "dsh-opencode-go";
|
|
147
147
|
style.dataset.pluginCss = id;
|
|
148
|
-
style.textContent = ".N807zW_page{flex-direction:column;min-width:0;height:100%;min-height:0;display:flex;container-type:size}.N807zW_pageBody{scrollbar-gutter:stable;flex-direction:column;flex:1;min-height:0;padding:0 4px 16px 0;display:flex;overflow-y:auto}.N807zW_pageBody,.N807zW_modelList,.N807zW_modelDetails{scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l3) transparent}.N807zW_pageBody::-webkit-scrollbar,.N807zW_modelList::-webkit-scrollbar,.N807zW_modelDetails::-webkit-scrollbar{width:8px;height:8px}.N807zW_pageBody::-webkit-scrollbar-track,.N807zW_modelList::-webkit-scrollbar-track,.N807zW_modelDetails::-webkit-scrollbar-track{background:0 0}.N807zW_pageBody::-webkit-scrollbar-thumb,.N807zW_modelList::-webkit-scrollbar-thumb,.N807zW_modelDetails::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l3);background-clip:content-box;border:2px solid #0000;border-radius:999px}.N807zW_pageBody:hover::-webkit-scrollbar-thumb,.N807zW_modelList:hover::-webkit-scrollbar-thumb,.N807zW_modelDetails:hover::-webkit-scrollbar-thumb{background:var(--dsw-alias-label-tertiary);background-clip:content-box}.N807zW_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.N807zW_field+.N807zW_field{border-top:.5px solid var(--dsw-alias-border-l2)}.N807zW_head{align-items:center;gap:8px;display:flex}.N807zW_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.N807zW_badges{align-items:center;gap:8px;display:inline-flex}.N807zW_trailing{flex:none;align-items:center;gap:8px;display:inline-flex}.N807zW_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.N807zW_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.N807zW_reset:disabled{cursor:default}.N807zW_reset:focus-visible,.N807zW_cardTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.N807zW_input{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.N807zW_input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px;border-color:var(--dsw-alias-brand-primary)}.N807zW_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.N807zW_inputInvalid{border-color:var(--dsw-alias-label-error);}.N807zW_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.N807zW_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.N807zW_pageTop{flex-direction:column;gap:3px;padding:2px 0 12px;display:flex}.N807zW_title{color:var(--dsw-alias-label-primary);margin:0;font-size:15px;font-weight:600;line-height:1.4}.N807zW_intro{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:1.5}.N807zW_card,.N807zW_cardModels{border:.5px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-bg-layer-3) 40%, transparent);border-radius:12px;padding:8px 0 10px}.N807zW_card{flex:none}.N807zW_card+.N807zW_card,.N807zW_card+.N807zW_cardModels,.N807zW_cardModels+.N807zW_card{margin-top:8px}.N807zW_cardModels{flex-direction:column;flex:1 0 auto;display:flex}.N807zW_cardFolded{flex:none}.N807zW_cardHead{align-items:center;gap:8px;min-height:24px;padding:0 14px;display:flex}.N807zW_cardTitle{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13.5px;font-weight:600;line-height:1.5}.N807zW_cardSub{color:var(--dsw-alias-label-tertiary);flex:none;font-size:11.5px;line-height:1.5}.N807zW_cardBody{flex-direction:column;gap:8px;padding:4px 14px 0;display:flex}.N807zW_cardBody>.N807zW_input{box-sizing:border-box;width:100%}.N807zW_cardModels>.N807zW_cardBody{flex:1 0 auto}.N807zW_cardNotes{flex-direction:column;gap:8px;padding:6px 14px 2px;display:flex}.N807zW_cardNotes:empty{display:none}.N807zW_cardDivider{border-top:.5px solid var(--dsw-alias-border-l2);margin:10px 14px}.N807zW_cardTrigger{width:100%;min-height:24px;font:inherit;text-align:left;color:inherit;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;margin:0;padding:0 14px;display:flex}.N807zW_cardTrigger:hover .N807zW_cardTitle{color:var(--dsw-alias-brand-primary)}.N807zW_advancedGrid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px 18px;display:grid}.N807zW_advancedGrid .N807zW_field{padding:0}.N807zW_advancedGrid .N807zW_field+.N807zW_field{border-top:none}.N807zW_limitsEditor{flex-direction:column;flex:1 0 auto;gap:10px;padding-top:4px;display:flex}.N807zW_limitsFoot{border-top:.5px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;margin:2px -14px 0;padding:10px 14px 0;display:flex}.N807zW_limitsSummary{min-width:0;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:1;font-size:12px;line-height:1.5}.N807zW_modelMeta{align-items:baseline;gap:10px;display:flex}.N807zW_modelMeta .N807zW_limitsModelId{flex:1;min-width:0}.N807zW_releaseDate{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:11px;line-height:1.4}.N807zW_limitsModelId{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.4;display:block;overflow:hidden}.N807zW_visuallyHidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.N807zW_actions{border-top:.5px solid var(--dsw-alias-border-l2);flex-wrap:wrap;flex:none;align-items:center;gap:8px;padding:12px 0;display:flex}.N807zW_starLink{max-width:100%;color:var(--dsw-alias-label-secondary);border-radius:4px;align-items:center;gap:7px;margin-left:auto;padding:6px 0;font-size:12px;line-height:1.5;text-decoration:none;display:inline-flex}.N807zW_starLink svg{flex:none}.N807zW_starLink:hover{color:var(--dsw-alias-brand-primary)}.N807zW_starLink:hover span{text-underline-offset:3px;text-decoration:underline}.N807zW_starLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.N807zW_failedNote{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.N807zW_slot{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}.N807zW_slot svg{width:15px;height:15px}.N807zW_chevron,.N807zW_chevronOpen{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .15s}.N807zW_chevron{transform:rotate(-90deg)}.N807zW_filters{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.N807zW_filterAction{align-items:center;margin-left:auto;display:inline-flex}.N807zW_filter{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;padding:6px 9px;font-size:12px}.N807zW_filter[aria-pressed=true]{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3)}.N807zW_filter span{color:var(--dsw-alias-label-tertiary);margin-left:4px}.N807zW_modelLayout{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;flex:auto;grid-template-columns:minmax(0,45fr) minmax(0,55fr);min-height:260px;max-height:560px;display:grid;overflow:hidden}.N807zW_modelList{border-right:.5px solid var(--dsw-alias-border-l2);min-height:0;padding:4px 6px;overflow-y:auto}.N807zW_modelRow{align-items:center;gap:8px;padding-right:6px;display:flex}.N807zW_modelRow+.N807zW_modelRow{border-top:.5px solid var(--dsw-alias-border-l2)}.N807zW_modelRowSelected{background:var(--dsw-alias-bg-layer-3);border-top-color:#0000;border-radius:6px}.N807zW_modelRow>[role=switch]{flex-shrink:0}.N807zW_modelChoice{text-align:left;min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:1;align-items:baseline;padding:9px 3px 9px 6px;display:flex}.N807zW_modelRow:hover:not(.N807zW_modelRowSelected){background:color-mix(in srgb, var(--dsw-alias-bg-layer-3) 92%, var(--dsw-alias-label-primary));border-top-color:#0000;border-radius:6px}.N807zW_modelName{overflow-wrap:anywhere;flex-wrap:wrap;flex:0 auto;align-items:center;gap:5px;min-width:0;font-size:13px;display:flex}.N807zW_overrideDot{background:var(--dsw-alias-brand-primary);border-radius:50%;flex:none;width:6px;height:6px}.N807zW_modelDetails{flex-direction:column;gap:10px;min-height:0;padding:14px;display:flex;overflow-y:auto}.N807zW_modelDetails h3{overflow-wrap:anywhere;margin:0;font-size:14px}.N807zW_modelHeading{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.N807zW_stats{flex-direction:column;gap:10px;display:flex}.N807zW_stat{flex-direction:column;gap:4px;display:flex}.N807zW_statLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}.N807zW_modelDetails .N807zW_input{box-sizing:border-box;width:100%;min-width:0;height:30px;padding:0 9px;font-size:12px}.N807zW_modalities{flex-wrap:wrap;gap:4px;display:flex}.N807zW_modality,.N807zW_modalityOff{border-radius:6px;padding:2px 7px;font-size:11px;line-height:1.5}.N807zW_modality{background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-secondary)}.N807zW_modalityOff{border:.5px dashed var(--dsw-alias-border-l4);color:var(--dsw-alias-label-tertiary)}.N807zW_modelDetails .N807zW_reset{align-self:flex-start}.N807zW_paneFoot{color:var(--dsw-alias-label-tertiary);margin:auto 0 0;font-size:11px;line-height:1.5}.N807zW_newBadge{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);border:.5px solid var(--dsw-alias-border-l4);border-radius:4px;padding:2px 4px;font-size:9px}.N807zW_modelChoice:focus-visible,.N807zW_filter:focus-visible,.N807zW_cardTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}@container (width<=440px){.N807zW_advancedGrid{grid-template-columns:minmax(0,1fr)}.N807zW_modelLayout{flex:none;grid-template-columns:minmax(0,1fr);max-height:none}.N807zW_modelList{border-right:0;border-bottom:.5px solid var(--dsw-alias-border-l2);max-height:240px}.N807zW_modelDetails{max-height:460px}}@media (prefers-reduced-motion:reduce){.N807zW_chevron,.N807zW_chevronOpen{transition:none}}";
|
|
148
|
+
style.textContent = ".N807zW_accounts{gap:10px;margin:12px 0;display:grid}.N807zW_accountRow{border:.5px solid var(--dsw-alias-border-l2);border-radius:10px}.N807zW_accountRow[data-dragging=true]{opacity:.55}.N807zW_accountMain{grid-template-columns:16px 112px 92px minmax(0,1fr) 38px 106px 14px;align-items:center;gap:9px;padding:9px 11px;display:grid}.N807zW_accountHandle{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);cursor:grab;-webkit-user-drag:element;background:0 0;border:0;place-items:center;padding:0;display:grid}.N807zW_accountHandle:disabled{cursor:default;opacity:.5}.N807zW_accountHandle:focus-visible,.N807zW_accountToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;border-radius:4px}.N807zW_accountName{white-space:nowrap;text-overflow:ellipsis;min-width:0;color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:600;overflow:hidden}.N807zW_accountState{min-width:0;color:var(--dsw-alias-label-tertiary);align-items:center;gap:5px;font-size:11.5px;display:inline-flex;overflow:hidden}.N807zW_accountDot{background:#39a878;border-radius:50%;flex:none;width:6px;height:6px}.N807zW_accountDot[data-off=true]{background:#d9a441}.N807zW_accountPercent{text-align:right;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:650}.N807zW_accountBar{background:#ffffff1a;border-radius:99px;height:12px;position:relative;overflow:hidden}.N807zW_accountBarFill{background:#39a878;border-radius:99px;position:absolute;inset:0 auto 0 0}.N807zW_accountBar[data-level=high] .N807zW_accountBarFill{background:#e0a100}.N807zW_accountBar[data-level=limited] .N807zW_accountBarFill{background:#e5484d}.N807zW_accountBarTick{background:#fff3;width:1px;position:absolute;top:0;bottom:0}.N807zW_accountReset{text-align:right;color:var(--dsw-alias-label-tertiary);font-size:11.5px}.N807zW_accountIdle{text-align:right;color:var(--dsw-alias-label-tertiary);grid-column:4/7;font-size:11.5px;line-height:1.5}.N807zW_accountToggle{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;place-items:center;padding:0;display:grid}.N807zW_accountProblems{align-items:baseline;gap:8px;padding:0 11px 9px 36px;display:flex}.N807zW_accountRetry{font:inherit;color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border:none;flex:none;padding:0;font-size:11.5px;line-height:1.5}.N807zW_accountRetry:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.N807zW_accountHandle:active{cursor:grabbing}.N807zW_accountDetail{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;padding:9px 11px 10px 36px;display:flex}.N807zW_accountDropLine{background:var(--dsw-alias-brand-primary);border-radius:2px;height:2px}.N807zW_accountUsage{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;font-size:12px;display:grid}.N807zW_accountUsage progress{accent-color:#39a878;width:100%;height:8px;margin:6px 0;display:block}.N807zW_accountUsage progress[data-level=high]{accent-color:#e0a100}.N807zW_accountUsage progress[data-level=limited]{accent-color:#e5484d}.N807zW_accountUsage .N807zW_hint{overflow-wrap:anywhere;display:block}.N807zW_accountActions{flex-wrap:wrap;gap:8px;margin-top:10px;display:flex}.N807zW_accountEditor{border:.5px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-bg-layer-3) 25%, transparent);border-radius:10px;flex-direction:column;gap:8px;margin:0 11px 10px 36px;padding:10px 12px;display:flex}.N807zW_accountEditorHead{align-items:baseline;gap:6px;min-width:0;display:flex}.N807zW_accountEditorTitle{color:var(--dsw-alias-label-primary);flex:none;font-size:12.5px;font-weight:600;line-height:1.5}.N807zW_accountEditorFor{min-width:0;color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:11.5px;line-height:1.5}.N807zW_accountField{color:var(--dsw-alias-label-tertiary);flex-direction:column;gap:5px;font-size:11.5px;line-height:1.5;display:flex}.N807zW_accountEditorActions{align-items:center;gap:8px;margin-top:2px;display:flex}@media (width<=480px){.N807zW_accountUsage{grid-template-columns:1fr}}.N807zW_page{flex-direction:column;min-width:0;height:100%;min-height:0;display:flex;container-type:size}.N807zW_pageBody{scrollbar-gutter:stable;flex-direction:column;flex:1;min-height:0;padding:0 4px 16px 0;display:flex;overflow-y:auto}.N807zW_pageBody,.N807zW_modelList,.N807zW_modelDetails{scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l3) transparent}.N807zW_pageBody::-webkit-scrollbar,.N807zW_modelList::-webkit-scrollbar,.N807zW_modelDetails::-webkit-scrollbar{width:8px;height:8px}.N807zW_pageBody::-webkit-scrollbar-track,.N807zW_modelList::-webkit-scrollbar-track,.N807zW_modelDetails::-webkit-scrollbar-track{background:0 0}.N807zW_pageBody::-webkit-scrollbar-thumb,.N807zW_modelList::-webkit-scrollbar-thumb,.N807zW_modelDetails::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l3);background-clip:content-box;border:2px solid #0000;border-radius:999px}.N807zW_pageBody:hover::-webkit-scrollbar-thumb,.N807zW_modelList:hover::-webkit-scrollbar-thumb,.N807zW_modelDetails:hover::-webkit-scrollbar-thumb{background:var(--dsw-alias-label-tertiary);background-clip:content-box}.N807zW_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.N807zW_field+.N807zW_field{border-top:.5px solid var(--dsw-alias-border-l2)}.N807zW_head{align-items:center;gap:8px;display:flex}.N807zW_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.N807zW_badges{align-items:center;gap:8px;display:inline-flex}.N807zW_trailing{flex:none;align-items:center;gap:8px;display:inline-flex}.N807zW_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.N807zW_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.N807zW_reset:disabled{cursor:default}.N807zW_reset:focus-visible,.N807zW_cardTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.N807zW_input{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.N807zW_input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px;border-color:var(--dsw-alias-brand-primary)}.N807zW_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.N807zW_inputInvalid{border-color:var(--dsw-alias-label-error);}.N807zW_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.N807zW_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.N807zW_pageTop{flex-direction:column;gap:3px;padding:2px 0 12px;display:flex}.N807zW_title{color:var(--dsw-alias-label-primary);margin:0;font-size:15px;font-weight:600;line-height:1.4}.N807zW_intro{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:1.5}.N807zW_card,.N807zW_cardModels{border:.5px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-bg-layer-3) 40%, transparent);border-radius:12px;padding:8px 0 10px}.N807zW_card{flex:none}.N807zW_card+.N807zW_card,.N807zW_card+.N807zW_cardModels,.N807zW_cardModels+.N807zW_card{margin-top:8px}.N807zW_cardModels{flex-direction:column;flex:1 0 auto;display:flex}.N807zW_cardFolded{flex:none}.N807zW_cardHead{align-items:center;gap:8px;min-height:24px;padding:0 14px;display:flex}.N807zW_cardTitle{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13.5px;font-weight:600;line-height:1.5}.N807zW_cardSub{color:var(--dsw-alias-label-tertiary);flex:none;font-size:11.5px;line-height:1.5}.N807zW_cardStamp{white-space:nowrap;color:var(--dsw-alias-label-tertiary);flex:none;font-size:11.5px;line-height:1.5}.N807zW_cardBody{flex-direction:column;gap:8px;padding:4px 14px 0;display:flex}.N807zW_cardBody>.N807zW_input{box-sizing:border-box;width:100%}.N807zW_cardModels>.N807zW_cardBody{flex:1 0 auto}.N807zW_cardNotes{flex-direction:column;gap:8px;padding:6px 14px 2px;display:flex}.N807zW_cardNotes:empty{display:none}.N807zW_cardDivider{border-top:.5px solid var(--dsw-alias-border-l2);margin:10px 14px}.N807zW_cardTrigger{width:100%;min-height:24px;font:inherit;text-align:left;color:inherit;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;margin:0;padding:0 14px;display:flex}.N807zW_cardTrigger:hover .N807zW_cardTitle{color:var(--dsw-alias-brand-primary)}.N807zW_cardHead>.N807zW_cardTrigger{padding:0}.N807zW_advancedGrid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px 18px;display:grid}.N807zW_advancedGrid .N807zW_field{padding:0}.N807zW_advancedGrid .N807zW_field+.N807zW_field{border-top:none}.N807zW_limitsEditor{flex-direction:column;flex:1 0 auto;gap:10px;padding-top:4px;display:flex}.N807zW_limitsFoot{border-top:.5px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;margin:2px -14px 0;padding:10px 14px 0;display:flex}.N807zW_limitsSummary{min-width:0;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:1;font-size:12px;line-height:1.5}.N807zW_modelMeta{align-items:baseline;gap:10px;display:flex}.N807zW_modelMeta .N807zW_limitsModelId{flex:1;min-width:0}.N807zW_releaseDate{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:11px;line-height:1.4}.N807zW_limitsModelId{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.4;display:block;overflow:hidden}.N807zW_visuallyHidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.N807zW_actions{border-top:.5px solid var(--dsw-alias-border-l2);flex-wrap:wrap;flex:none;align-items:center;gap:8px;padding:12px 0;display:flex}.N807zW_starLink{max-width:100%;color:var(--dsw-alias-label-secondary);border-radius:4px;align-items:center;gap:7px;margin-left:auto;padding:6px 0;font-size:12px;line-height:1.5;text-decoration:none;display:inline-flex}.N807zW_starLink svg{flex:none}.N807zW_starLink:hover{color:var(--dsw-alias-brand-primary)}.N807zW_starLink:hover span{text-underline-offset:3px;text-decoration:underline}.N807zW_starLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.N807zW_failedNote{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.N807zW_slot{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}.N807zW_slot svg{width:15px;height:15px}.N807zW_chevron,.N807zW_chevronOpen{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .15s}.N807zW_chevron{transform:rotate(-90deg)}.N807zW_filters{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.N807zW_filterAction{align-items:center;margin-left:auto;display:inline-flex}.N807zW_filter{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;padding:6px 9px;font-size:12px}.N807zW_filter[aria-pressed=true]{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3)}.N807zW_filter span{color:var(--dsw-alias-label-tertiary);margin-left:4px}.N807zW_modelLayout{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;flex:auto;grid-template-columns:minmax(0,45fr) minmax(0,55fr);min-height:260px;max-height:560px;display:grid;overflow:hidden}.N807zW_modelList{border-right:.5px solid var(--dsw-alias-border-l2);min-height:0;padding:4px 6px;overflow-y:auto}.N807zW_modelRow{align-items:center;gap:8px;padding-right:6px;display:flex}.N807zW_modelRow+.N807zW_modelRow{border-top:.5px solid var(--dsw-alias-border-l2)}.N807zW_modelRowSelected{background:var(--dsw-alias-bg-layer-3);border-top-color:#0000;border-radius:6px}.N807zW_modelRow>[role=switch]{flex-shrink:0}.N807zW_modelChoice{text-align:left;min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:1;align-items:baseline;padding:9px 3px 9px 6px;display:flex}.N807zW_modelRow:hover:not(.N807zW_modelRowSelected){background:color-mix(in srgb, var(--dsw-alias-bg-layer-3) 92%, var(--dsw-alias-label-primary));border-top-color:#0000;border-radius:6px}.N807zW_modelName{overflow-wrap:anywhere;flex-wrap:wrap;flex:0 auto;align-items:center;gap:5px;min-width:0;font-size:13px;display:flex}.N807zW_overrideDot{background:var(--dsw-alias-brand-primary);border-radius:50%;flex:none;width:6px;height:6px}.N807zW_modelDetails{flex-direction:column;gap:10px;min-height:0;padding:14px;display:flex;overflow-y:auto}.N807zW_modelDetails h3{overflow-wrap:anywhere;margin:0;font-size:14px}.N807zW_modelHeading{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.N807zW_stats{flex-direction:column;gap:10px;display:flex}.N807zW_stat{flex-direction:column;gap:4px;display:flex}.N807zW_statLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}.N807zW_modelDetails .N807zW_input{box-sizing:border-box;width:100%;min-width:0;height:30px;padding:0 9px;font-size:12px}.N807zW_modalities{flex-wrap:wrap;gap:4px;display:flex}.N807zW_modality,.N807zW_modalityOff{border-radius:6px;padding:2px 7px;font-size:11px;line-height:1.5}.N807zW_modality{background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-secondary)}.N807zW_modalityOff{border:.5px dashed var(--dsw-alias-border-l4);color:var(--dsw-alias-label-tertiary)}.N807zW_modelDetails .N807zW_reset{align-self:flex-start}.N807zW_paneFoot{color:var(--dsw-alias-label-tertiary);margin:auto 0 0;font-size:11px;line-height:1.5}.N807zW_newBadge{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);border:.5px solid var(--dsw-alias-border-l4);border-radius:4px;padding:2px 4px;font-size:9px}.N807zW_modelChoice:focus-visible,.N807zW_filter:focus-visible,.N807zW_cardTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}@container (width<=440px){.N807zW_advancedGrid{grid-template-columns:minmax(0,1fr)}.N807zW_modelLayout{flex:none;grid-template-columns:minmax(0,1fr);max-height:none}.N807zW_modelList{border-right:0;border-bottom:.5px solid var(--dsw-alias-border-l2);max-height:240px}.N807zW_modelDetails{max-height:460px}}@media (prefers-reduced-motion:reduce){.N807zW_chevron,.N807zW_chevronOpen{transition:none}}";
|
|
149
149
|
document.head.appendChild(style);
|
|
150
150
|
}
|
|
151
|
-
var Section_default = { "actions": "N807zW_actions", "advancedGrid": "N807zW_advancedGrid", "badges": "N807zW_badges", "card": "N807zW_card", "cardBody": "N807zW_cardBody", "cardDivider": "N807zW_cardDivider", "cardFolded": "N807zW_cardFolded", "cardHead": "N807zW_cardHead", "cardModels": "N807zW_cardModels", "cardNotes": "N807zW_cardNotes", "cardSub": "N807zW_cardSub", "cardTitle": "N807zW_cardTitle", "cardTrigger": "N807zW_cardTrigger", "chevron": "N807zW_chevron", "chevronOpen": "N807zW_chevronOpen", "failedNote": "N807zW_failedNote", "field": "N807zW_field", "filter": "N807zW_filter", "filterAction": "N807zW_filterAction", "filters": "N807zW_filters", "head": "N807zW_head", "hint": "N807zW_hint", "input": "N807zW_input", "inputInvalid": "N807zW_inputInvalid N807zW_input", "intro": "N807zW_intro", "invalid": "N807zW_invalid", "label": "N807zW_label", "limitsEditor": "N807zW_limitsEditor", "limitsFoot": "N807zW_limitsFoot", "limitsModelId": "N807zW_limitsModelId", "limitsSummary": "N807zW_limitsSummary", "modalities": "N807zW_modalities", "modality": "N807zW_modality", "modalityOff": "N807zW_modalityOff", "modelChoice": "N807zW_modelChoice", "modelDetails": "N807zW_modelDetails", "modelHeading": "N807zW_modelHeading", "modelLayout": "N807zW_modelLayout", "modelList": "N807zW_modelList", "modelMeta": "N807zW_modelMeta", "modelName": "N807zW_modelName", "modelRow": "N807zW_modelRow", "modelRowSelected": "N807zW_modelRowSelected", "newBadge": "N807zW_newBadge", "overrideDot": "N807zW_overrideDot", "page": "N807zW_page", "pageBody": "N807zW_pageBody", "pageTop": "N807zW_pageTop", "paneFoot": "N807zW_paneFoot", "releaseDate": "N807zW_releaseDate", "reset": "N807zW_reset", "slot": "N807zW_slot", "starLink": "N807zW_starLink", "stat": "N807zW_stat", "statLabel": "N807zW_statLabel", "stats": "N807zW_stats", "title": "N807zW_title", "trailing": "N807zW_trailing", "visuallyHidden": "N807zW_visuallyHidden" };
|
|
151
|
+
var Section_default = { "accountActions": "N807zW_accountActions", "accountBar": "N807zW_accountBar", "accountBarFill": "N807zW_accountBarFill", "accountBarTick": "N807zW_accountBarTick", "accountDetail": "N807zW_accountDetail", "accountDot": "N807zW_accountDot", "accountDropLine": "N807zW_accountDropLine", "accountEditor": "N807zW_accountEditor", "accountEditorActions": "N807zW_accountEditorActions", "accountEditorFor": "N807zW_accountEditorFor", "accountEditorHead": "N807zW_accountEditorHead", "accountEditorTitle": "N807zW_accountEditorTitle", "accountField": "N807zW_accountField", "accountHandle": "N807zW_accountHandle", "accountIdle": "N807zW_accountIdle", "accountMain": "N807zW_accountMain", "accountName": "N807zW_accountName", "accountPercent": "N807zW_accountPercent", "accountProblems": "N807zW_accountProblems", "accountReset": "N807zW_accountReset", "accountRetry": "N807zW_accountRetry", "accountRow": "N807zW_accountRow", "accountState": "N807zW_accountState", "accountToggle": "N807zW_accountToggle", "accountUsage": "N807zW_accountUsage", "accounts": "N807zW_accounts", "actions": "N807zW_actions", "advancedGrid": "N807zW_advancedGrid", "badges": "N807zW_badges", "card": "N807zW_card", "cardBody": "N807zW_cardBody", "cardDivider": "N807zW_cardDivider", "cardFolded": "N807zW_cardFolded", "cardHead": "N807zW_cardHead", "cardModels": "N807zW_cardModels", "cardNotes": "N807zW_cardNotes", "cardStamp": "N807zW_cardStamp", "cardSub": "N807zW_cardSub", "cardTitle": "N807zW_cardTitle", "cardTrigger": "N807zW_cardTrigger", "chevron": "N807zW_chevron", "chevronOpen": "N807zW_chevronOpen", "failedNote": "N807zW_failedNote", "field": "N807zW_field", "filter": "N807zW_filter", "filterAction": "N807zW_filterAction", "filters": "N807zW_filters", "head": "N807zW_head", "hint": "N807zW_hint", "input": "N807zW_input", "inputInvalid": "N807zW_inputInvalid N807zW_input", "intro": "N807zW_intro", "invalid": "N807zW_invalid", "label": "N807zW_label", "limitsEditor": "N807zW_limitsEditor", "limitsFoot": "N807zW_limitsFoot", "limitsModelId": "N807zW_limitsModelId", "limitsSummary": "N807zW_limitsSummary", "modalities": "N807zW_modalities", "modality": "N807zW_modality", "modalityOff": "N807zW_modalityOff", "modelChoice": "N807zW_modelChoice", "modelDetails": "N807zW_modelDetails", "modelHeading": "N807zW_modelHeading", "modelLayout": "N807zW_modelLayout", "modelList": "N807zW_modelList", "modelMeta": "N807zW_modelMeta", "modelName": "N807zW_modelName", "modelRow": "N807zW_modelRow", "modelRowSelected": "N807zW_modelRowSelected", "newBadge": "N807zW_newBadge", "overrideDot": "N807zW_overrideDot", "page": "N807zW_page", "pageBody": "N807zW_pageBody", "pageTop": "N807zW_pageTop", "paneFoot": "N807zW_paneFoot", "releaseDate": "N807zW_releaseDate", "reset": "N807zW_reset", "slot": "N807zW_slot", "starLink": "N807zW_starLink", "stat": "N807zW_stat", "statLabel": "N807zW_statLabel", "stats": "N807zW_stats", "title": "N807zW_title", "trailing": "N807zW_trailing", "visuallyHidden": "N807zW_visuallyHidden" };
|
|
152
152
|
|
|
153
153
|
// src/client/ModelEditor.tsx
|
|
154
154
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -375,21 +375,447 @@ function Capacity({ model, field, limit, disabled, t, locale, onChange }) {
|
|
|
375
375
|
] });
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
// src/client/AccountsCard.tsx
|
|
379
|
+
var import_react2 = require("react");
|
|
380
|
+
var primitives = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
|
|
381
|
+
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
382
|
+
|
|
383
|
+
// src/accounts.ts
|
|
384
|
+
var MAX_ACCOUNTS = 20;
|
|
385
|
+
var ACCOUNT_REF_PREFIX = "DSH_OPENCODE_GO_ACCOUNT_";
|
|
386
|
+
var DEFAULT_ACCOUNT_REF = "OPENCODE_API_KEY";
|
|
387
|
+
function accountRefOf(settings) {
|
|
388
|
+
return settings.apiKeyEnv || DEFAULT_ACCOUNT_REF;
|
|
389
|
+
}
|
|
390
|
+
function accountsOf(settings) {
|
|
391
|
+
const ref = accountRefOf(settings);
|
|
392
|
+
if (settings.accounts?.length === 0) return [];
|
|
393
|
+
const accounts = settings.accounts ?? [];
|
|
394
|
+
return accounts.some((account) => account.apiKeyEnv === ref) ? accounts : [
|
|
395
|
+
{ id: `legacy:${ref}`, name: "", apiKeyEnv: ref },
|
|
396
|
+
...accounts
|
|
397
|
+
];
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// src/client/AccountsCard.tsx
|
|
401
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
402
|
+
var WINDOWS = ["rolling", "weekly", "monthly"];
|
|
403
|
+
var TICKS = [25, 50, 75];
|
|
404
|
+
var ChevronDown = primitives.IconChevronDownOutlineRegular ?? primitives.IconChevronDownOutline14;
|
|
405
|
+
function resetText(resetsAt, t) {
|
|
406
|
+
const remaining = Date.parse(resetsAt) - Date.now();
|
|
407
|
+
if (!Number.isFinite(remaining)) return t("usageResetUnknown");
|
|
408
|
+
if (remaining <= 0) return t("usageResetDue");
|
|
409
|
+
const minutes = Math.max(1, Math.round(remaining / 6e4));
|
|
410
|
+
if (minutes < 60) return t("usageResetMinutes", { minutes });
|
|
411
|
+
const hours = Math.round(minutes / 60);
|
|
412
|
+
if (hours < 24) return t("usageResetHours", { hours });
|
|
413
|
+
return t("usageResetDays", { days: Math.round(hours / 24) });
|
|
414
|
+
}
|
|
415
|
+
function barLevel(window) {
|
|
416
|
+
if (window.status === "rate-limited" || window.percent >= 100) return "limited";
|
|
417
|
+
return window.percent >= 80 ? "high" : "ok";
|
|
418
|
+
}
|
|
419
|
+
function stampText(at, locale) {
|
|
420
|
+
const date = new Date(at);
|
|
421
|
+
const time = date.toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit" });
|
|
422
|
+
return date.toDateString() === (/* @__PURE__ */ new Date()).toDateString() ? time : `${date.toLocaleDateString(locale)} ${time}`;
|
|
423
|
+
}
|
|
424
|
+
function GripIcon() {
|
|
425
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "10", height: "14", viewBox: "0 0 10 14", fill: "currentColor", "aria-hidden": "true", children: [
|
|
426
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2.5", cy: "2.5", r: "1.3" }),
|
|
427
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7.5", cy: "2.5", r: "1.3" }),
|
|
428
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2.5", cy: "7", r: "1.3" }),
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7.5", cy: "7", r: "1.3" }),
|
|
430
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2.5", cy: "11.5", r: "1.3" }),
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7.5", cy: "11.5", r: "1.3" })
|
|
432
|
+
] });
|
|
433
|
+
}
|
|
434
|
+
function AccountsCard({ state, actions, writable, t, locale }) {
|
|
435
|
+
const [open, setOpen] = (0, import_react2.useState)(false);
|
|
436
|
+
const [details, setDetails] = (0, import_react2.useState)(null);
|
|
437
|
+
const [dragging, setDragging] = (0, import_react2.useState)(null);
|
|
438
|
+
const [dropAt, setDropAt] = (0, import_react2.useState)(null);
|
|
439
|
+
const [editor, setEditor] = (0, import_react2.useState)(null);
|
|
440
|
+
const [name, setName] = (0, import_react2.useState)("");
|
|
441
|
+
const [key, setKey] = (0, import_react2.useState)("");
|
|
442
|
+
const disabled = state.busy || state.blocked || !writable;
|
|
443
|
+
const total = state.entries.length;
|
|
444
|
+
const ready = state.entries.filter((entry) => entry.configured === true).length;
|
|
445
|
+
const unreadable = state.entries.filter((entry) => entry.failed === true).length;
|
|
446
|
+
const preferred = state.entries.find((entry) => entry.apiKeyEnv === state.activeRef);
|
|
447
|
+
const reorderable = !disabled && total > 1;
|
|
448
|
+
const updatedAt = state.entries.reduce((latest, entry) => Math.max(latest, entry.updatedAt ?? 0), 0);
|
|
449
|
+
(0, import_react2.useEffect)(() => {
|
|
450
|
+
actions.loadAccounts();
|
|
451
|
+
const timer = setInterval(() => {
|
|
452
|
+
if (document.visibilityState !== "hidden") actions.loadAccounts();
|
|
453
|
+
}, 6e4);
|
|
454
|
+
return () => {
|
|
455
|
+
clearInterval(timer);
|
|
456
|
+
};
|
|
457
|
+
}, [actions.loadAccounts]);
|
|
458
|
+
const start = (next, label = "") => {
|
|
459
|
+
setEditor(next);
|
|
460
|
+
setName(label);
|
|
461
|
+
setKey("");
|
|
462
|
+
};
|
|
463
|
+
const cancel = () => {
|
|
464
|
+
setEditor(null);
|
|
465
|
+
setName("");
|
|
466
|
+
setKey("");
|
|
467
|
+
};
|
|
468
|
+
(0, import_react2.useEffect)(() => {
|
|
469
|
+
if (editor?.ref != null && !state.entries.some((entry) => entry.apiKeyEnv === editor.ref)) cancel();
|
|
470
|
+
}, [state.entries, editor]);
|
|
471
|
+
const submit = async () => {
|
|
472
|
+
if (!editor) return;
|
|
473
|
+
const accepted = editor.kind === "add" ? await actions.addAccount(name, key) : editor.kind === "rename" ? await actions.renameAccount(editor.ref, name) : editor.kind === "key" ? await actions.replaceAccountKey(editor.ref, key) : await actions.removeAccount(editor.ref);
|
|
474
|
+
if (accepted) cancel();
|
|
475
|
+
};
|
|
476
|
+
const move = (ref, toIndex) => {
|
|
477
|
+
void actions.moveAccount(ref, toIndex);
|
|
478
|
+
};
|
|
479
|
+
const summary = total ? t("accountsSummary", { count: total, name: preferred ? preferred.name || t("accountDefault") : "" }) : t("accountsSummaryEmpty");
|
|
480
|
+
const editorTitle = (kind) => t(kind === "add" ? "accountAdd" : kind === "rename" ? "accountRename" : kind === "key" ? "accountReplaceKey" : "accountRemove");
|
|
481
|
+
const editorForm = (label = "") => editor ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
482
|
+
"form",
|
|
483
|
+
{
|
|
484
|
+
className: Section_default.accountEditor,
|
|
485
|
+
onSubmit: (event) => {
|
|
486
|
+
event.preventDefault();
|
|
487
|
+
void submit();
|
|
488
|
+
},
|
|
489
|
+
onKeyDown: (event) => {
|
|
490
|
+
if (event.key === "Escape") {
|
|
491
|
+
event.preventDefault();
|
|
492
|
+
cancel();
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
children: [
|
|
496
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountEditorHead, children: [
|
|
497
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountEditorTitle, children: editorTitle(editor.kind) }),
|
|
498
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountEditorFor, children: label }) : null
|
|
499
|
+
] }),
|
|
500
|
+
editor.kind === "remove" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountRemoveHint", { name }) }) : null,
|
|
501
|
+
editor.kind === "add" || editor.kind === "rename" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: Section_default.accountField, children: [
|
|
502
|
+
t("accountName"),
|
|
503
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
504
|
+
"input",
|
|
505
|
+
{
|
|
506
|
+
className: Section_default.input,
|
|
507
|
+
value: name,
|
|
508
|
+
maxLength: 80,
|
|
509
|
+
required: true,
|
|
510
|
+
disabled: state.busy,
|
|
511
|
+
autoFocus: true,
|
|
512
|
+
onChange: (event) => {
|
|
513
|
+
setName(event.target.value);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
)
|
|
517
|
+
] }) : null,
|
|
518
|
+
editor.kind === "add" || editor.kind === "key" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
519
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: Section_default.accountField, children: [
|
|
520
|
+
t("keyLabel"),
|
|
521
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
522
|
+
"input",
|
|
523
|
+
{
|
|
524
|
+
className: Section_default.input,
|
|
525
|
+
type: "password",
|
|
526
|
+
autoComplete: "off",
|
|
527
|
+
value: key,
|
|
528
|
+
required: true,
|
|
529
|
+
disabled: state.busy,
|
|
530
|
+
autoFocus: true,
|
|
531
|
+
onChange: (event) => {
|
|
532
|
+
setKey(event.target.value);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
)
|
|
536
|
+
] }),
|
|
537
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountKeyHint") })
|
|
538
|
+
] }) : null,
|
|
539
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountEditorActions, children: [
|
|
540
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
541
|
+
import_dsh_client_ui_primitives2.Button,
|
|
542
|
+
{
|
|
543
|
+
variant: "primary",
|
|
544
|
+
size: "sm",
|
|
545
|
+
type: "submit",
|
|
546
|
+
disabled: editor.kind === "key" ? state.busy || state.blocked : disabled,
|
|
547
|
+
children: t(state.busy ? "saving" : "accountConfirm")
|
|
548
|
+
}
|
|
549
|
+
),
|
|
550
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", type: "button", disabled: state.busy, onClick: cancel, children: t("accountCancel") })
|
|
551
|
+
] })
|
|
552
|
+
]
|
|
553
|
+
}
|
|
554
|
+
) : null;
|
|
555
|
+
const detail = (account, label) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountDetail, children: [
|
|
556
|
+
account.usage ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: Section_default.accountUsage, children: WINDOWS.map((window) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
557
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
558
|
+
t(`usage_${window}`),
|
|
559
|
+
" \xB7 ",
|
|
560
|
+
account.usage[window].percent,
|
|
561
|
+
"%"
|
|
562
|
+
] }),
|
|
563
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
564
|
+
"progress",
|
|
565
|
+
{
|
|
566
|
+
"data-level": barLevel(account.usage[window]),
|
|
567
|
+
max: 100,
|
|
568
|
+
value: Math.min(100, account.usage[window].percent),
|
|
569
|
+
"aria-label": `${label} ${t(`usage_${window}`)}`
|
|
570
|
+
}
|
|
571
|
+
),
|
|
572
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.hint, children: [
|
|
573
|
+
t("usageResets"),
|
|
574
|
+
" ",
|
|
575
|
+
new Date(account.usage[window].resetsAt).toLocaleString(locale)
|
|
576
|
+
] })
|
|
577
|
+
] }, window)) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t(account.loading ? "usageLoading" : "usageUnavailable") }),
|
|
578
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountActions, children: [
|
|
579
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", disabled, onClick: () => {
|
|
580
|
+
start({ kind: "rename", ref: account.apiKeyEnv }, label);
|
|
581
|
+
}, children: t("accountRename") }),
|
|
582
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", disabled: state.busy || state.blocked || account.writable === false, onClick: () => {
|
|
583
|
+
start({ kind: "key", ref: account.apiKeyEnv }, label);
|
|
584
|
+
}, children: t("accountReplaceKey") }),
|
|
585
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", disabled, onClick: () => {
|
|
586
|
+
start({ kind: "remove", ref: account.apiKeyEnv }, label);
|
|
587
|
+
}, children: t("accountRemove") })
|
|
588
|
+
] })
|
|
589
|
+
] });
|
|
590
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: open ? Section_default.card : Section_default.card + " " + Section_default.cardFolded, children: [
|
|
591
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.cardHead, children: [
|
|
592
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
593
|
+
"button",
|
|
594
|
+
{
|
|
595
|
+
type: "button",
|
|
596
|
+
className: Section_default.cardTrigger,
|
|
597
|
+
"aria-expanded": open,
|
|
598
|
+
"aria-controls": "opencode-go-accounts",
|
|
599
|
+
onClick: () => {
|
|
600
|
+
setOpen(!open);
|
|
601
|
+
},
|
|
602
|
+
children: [
|
|
603
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.cardTitle, children: t("accountsTitle") }),
|
|
604
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.cardSub, children: summary }),
|
|
605
|
+
total > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Tag, { tone: unreadable > 0 || ready < total ? "warning" : "success", children: t(unreadable > 0 ? "accountsAvailabilityFailed" : "accountsAvailability", { ready, total, failed: unreadable }) }) : null,
|
|
606
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronDown, { className: open ? Section_default.chevronOpen : Section_default.chevron })
|
|
607
|
+
]
|
|
608
|
+
}
|
|
609
|
+
),
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.trailing, children: [
|
|
611
|
+
updatedAt > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.cardStamp, title: new Date(updatedAt).toLocaleString(locale), children: [
|
|
612
|
+
t("usageLastUpdated"),
|
|
613
|
+
" ",
|
|
614
|
+
stampText(updatedAt, locale)
|
|
615
|
+
] }) : null,
|
|
616
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
617
|
+
import_dsh_client_ui_primitives2.Button,
|
|
618
|
+
{
|
|
619
|
+
variant: "outline",
|
|
620
|
+
size: "sm",
|
|
621
|
+
disabled: state.refreshing,
|
|
622
|
+
onClick: actions.loadAccounts,
|
|
623
|
+
children: t(state.refreshing ? "usageRefreshing" : "accountsRefresh")
|
|
624
|
+
}
|
|
625
|
+
)
|
|
626
|
+
] })
|
|
627
|
+
] }),
|
|
628
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { id: "opencode-go-accounts", className: Section_default.cardBody, children: [
|
|
629
|
+
state.blocked ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountsBlocked") }) : null,
|
|
630
|
+
state.failure ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t(state.failure === "cleanup" ? "accountsCleanupFailed" : state.failure === "remove" ? "accountsRemoveKeyFailed" : state.failure === "read" ? "accountsReadFailed" : "accountsWriteFailed") }) : null,
|
|
631
|
+
!total ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountsEmpty") }) : null,
|
|
632
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accounts, children: [
|
|
633
|
+
state.entries.map((account, index) => {
|
|
634
|
+
const label = account.name || t("accountDefault");
|
|
635
|
+
const rolling = account.usage?.rolling;
|
|
636
|
+
const expanded = details === account.apiKeyEnv;
|
|
637
|
+
const panelId = `opencode-go-account-${index}`;
|
|
638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react2.Fragment, { children: [
|
|
639
|
+
reorderable && dropAt === index ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: Section_default.accountDropLine }) : null,
|
|
640
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
641
|
+
"div",
|
|
642
|
+
{
|
|
643
|
+
className: Section_default.accountRow,
|
|
644
|
+
"data-account-row": account.apiKeyEnv,
|
|
645
|
+
"data-dragging": dragging === account.apiKeyEnv ? "true" : void 0,
|
|
646
|
+
onDragStart: (event) => {
|
|
647
|
+
if (!reorderable || event.target?.closest?.("[data-account-handle]") == null) {
|
|
648
|
+
event.preventDefault();
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
if (event.dataTransfer) {
|
|
652
|
+
event.dataTransfer.effectAllowed = "move";
|
|
653
|
+
event.dataTransfer.setData("text/plain", account.apiKeyEnv);
|
|
654
|
+
if (typeof event.dataTransfer.setDragImage === "function") {
|
|
655
|
+
event.dataTransfer.setDragImage(event.currentTarget, 16, 16);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
setDragging(account.apiKeyEnv);
|
|
659
|
+
},
|
|
660
|
+
onDragOver: (event) => {
|
|
661
|
+
if (!reorderable || dragging === null || dragging === account.apiKeyEnv) return;
|
|
662
|
+
event.preventDefault();
|
|
663
|
+
if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
|
|
664
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
665
|
+
setDropAt(event.clientY < box.top + box.height / 2 ? index : index + 1);
|
|
666
|
+
},
|
|
667
|
+
onDrop: (event) => {
|
|
668
|
+
const source = dragging;
|
|
669
|
+
const slot = dropAt;
|
|
670
|
+
setDragging(null);
|
|
671
|
+
setDropAt(null);
|
|
672
|
+
if (source === null || slot === null) return;
|
|
673
|
+
event.preventDefault();
|
|
674
|
+
const from = state.entries.findIndex((entry) => entry.apiKeyEnv === source);
|
|
675
|
+
if (from >= 0) move(source, slot > from ? slot - 1 : slot);
|
|
676
|
+
},
|
|
677
|
+
onDragEnd: () => {
|
|
678
|
+
setDragging(null);
|
|
679
|
+
setDropAt(null);
|
|
680
|
+
},
|
|
681
|
+
children: [
|
|
682
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountMain, "data-account-main": "", children: [
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
684
|
+
"button",
|
|
685
|
+
{
|
|
686
|
+
type: "button",
|
|
687
|
+
className: Section_default.accountHandle,
|
|
688
|
+
"data-account-handle": "",
|
|
689
|
+
draggable: reorderable,
|
|
690
|
+
disabled: !reorderable,
|
|
691
|
+
title: t("accountDragHandle", { name: label }),
|
|
692
|
+
"aria-label": t("accountDragHandle", { name: label }),
|
|
693
|
+
onKeyDown: (event) => {
|
|
694
|
+
if (event.key === "ArrowUp" && index > 0) {
|
|
695
|
+
event.preventDefault();
|
|
696
|
+
move(account.apiKeyEnv, index - 1);
|
|
697
|
+
}
|
|
698
|
+
if (event.key === "ArrowDown" && index < total - 1) {
|
|
699
|
+
event.preventDefault();
|
|
700
|
+
move(account.apiKeyEnv, index + 1);
|
|
701
|
+
}
|
|
702
|
+
},
|
|
703
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GripIcon, {})
|
|
704
|
+
}
|
|
705
|
+
),
|
|
706
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { className: Section_default.accountName, title: label, children: label }),
|
|
707
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.accountState, children: [
|
|
708
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountDot, "data-off": account.configured === false ? "true" : void 0 }),
|
|
709
|
+
account.configured === void 0 ? t(account.failed ? "accountsStatusUnknown" : "usageLoading") : account.configured ? t("keyConfigured") : t("keyMissing")
|
|
710
|
+
] }),
|
|
711
|
+
rolling ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
712
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
713
|
+
"span",
|
|
714
|
+
{
|
|
715
|
+
className: Section_default.accountBar,
|
|
716
|
+
role: "progressbar",
|
|
717
|
+
"data-level": barLevel(rolling),
|
|
718
|
+
"aria-valuemin": 0,
|
|
719
|
+
"aria-valuemax": 100,
|
|
720
|
+
"aria-valuenow": Math.min(100, rolling.percent),
|
|
721
|
+
"aria-label": `${label} ${t("usage_rolling")}`,
|
|
722
|
+
children: [
|
|
723
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountBarFill, style: { width: `${Math.min(100, rolling.percent)}%` } }),
|
|
724
|
+
TICKS.map((at) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountBarTick, style: { left: `${at}%` } }, at))
|
|
725
|
+
]
|
|
726
|
+
}
|
|
727
|
+
),
|
|
728
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.accountPercent, children: [
|
|
729
|
+
rolling.percent,
|
|
730
|
+
"%"
|
|
731
|
+
] }),
|
|
732
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountReset, children: resetText(rolling.resetsAt, t) })
|
|
733
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountIdle, children: account.configured === false ? t("accountConfigureHint") : t(account.loading ? "usageLoading" : "usageUnavailable") }),
|
|
734
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
735
|
+
"button",
|
|
736
|
+
{
|
|
737
|
+
type: "button",
|
|
738
|
+
className: Section_default.accountToggle,
|
|
739
|
+
"aria-expanded": expanded,
|
|
740
|
+
"aria-controls": panelId,
|
|
741
|
+
"aria-label": t(expanded ? "accountsDetailsHide" : "accountsDetails", { name: label }),
|
|
742
|
+
onClick: () => {
|
|
743
|
+
setDetails(expanded ? null : account.apiKeyEnv);
|
|
744
|
+
},
|
|
745
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronDown, { className: expanded ? Section_default.chevronOpen : Section_default.chevron })
|
|
746
|
+
}
|
|
747
|
+
)
|
|
748
|
+
] }),
|
|
749
|
+
account.failed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountProblems, role: "alert", children: [
|
|
750
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.failedNote, children: account.problem ?? t(account.stale ? "usageStaleHint" : "usageRefreshFailed") }),
|
|
751
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
752
|
+
"button",
|
|
753
|
+
{
|
|
754
|
+
type: "button",
|
|
755
|
+
className: Section_default.accountRetry,
|
|
756
|
+
disabled: state.refreshing,
|
|
757
|
+
onClick: actions.loadAccounts,
|
|
758
|
+
children: t("usageRetry")
|
|
759
|
+
}
|
|
760
|
+
)
|
|
761
|
+
] }) : null,
|
|
762
|
+
expanded ? detail(account, label) : null,
|
|
763
|
+
editor?.ref === account.apiKeyEnv ? editorForm(label) : null
|
|
764
|
+
]
|
|
765
|
+
}
|
|
766
|
+
)
|
|
767
|
+
] }, account.id);
|
|
768
|
+
}),
|
|
769
|
+
reorderable && dropAt === total ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: Section_default.accountDropLine }) : null
|
|
770
|
+
] }),
|
|
771
|
+
editor ? editor.kind === "add" ? editorForm() : null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
772
|
+
import_dsh_client_ui_primitives2.Button,
|
|
773
|
+
{
|
|
774
|
+
variant: "outline",
|
|
775
|
+
size: "sm",
|
|
776
|
+
disabled: disabled || total >= MAX_ACCOUNTS,
|
|
777
|
+
onClick: () => {
|
|
778
|
+
start({ kind: "add" });
|
|
779
|
+
},
|
|
780
|
+
children: t("accountAdd")
|
|
781
|
+
}
|
|
782
|
+
),
|
|
783
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.field, children: [
|
|
784
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.head, children: [
|
|
785
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.label, children: t("accountAutoSwitch") }),
|
|
786
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
787
|
+
import_dsh_client_ui_primitives2.Switch,
|
|
788
|
+
{
|
|
789
|
+
checked: state.autoSwitch,
|
|
790
|
+
disabled,
|
|
791
|
+
label: t("accountAutoSwitch"),
|
|
792
|
+
onChange: (next) => {
|
|
793
|
+
void actions.setAutoSwitch(next);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
)
|
|
797
|
+
] }),
|
|
798
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountAutoSwitchHint") })
|
|
799
|
+
] })
|
|
800
|
+
] }) : null
|
|
801
|
+
] });
|
|
802
|
+
}
|
|
803
|
+
|
|
378
804
|
// src/usage-display.ts
|
|
379
805
|
var USAGE_DISPLAY_MODES = ["auto", "always", "off"];
|
|
380
806
|
var DEFAULT_USAGE_DISPLAY = "auto";
|
|
381
807
|
|
|
382
808
|
// src/client/Section.tsx
|
|
383
|
-
var
|
|
384
|
-
var
|
|
809
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
810
|
+
var ChevronDown2 = primitives2.IconChevronDownOutlineRegular ?? primitives2.IconChevronDownOutline14;
|
|
385
811
|
function ValueField(props) {
|
|
386
812
|
const hintId = props.id + "-hint";
|
|
387
|
-
return /* @__PURE__ */ (0,
|
|
388
|
-
/* @__PURE__ */ (0,
|
|
389
|
-
/* @__PURE__ */ (0,
|
|
390
|
-
props.field.overridden ? /* @__PURE__ */ (0,
|
|
391
|
-
/* @__PURE__ */ (0,
|
|
392
|
-
/* @__PURE__ */ (0,
|
|
813
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.field, children: [
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.head, children: [
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: Section_default.label, htmlFor: props.id, children: props.label }),
|
|
816
|
+
props.field.overridden ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: Section_default.badges, children: [
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Tag, { tone: "neutral", children: props.overriddenLabel }),
|
|
818
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
393
819
|
"button",
|
|
394
820
|
{
|
|
395
821
|
type: "button",
|
|
@@ -401,7 +827,7 @@ function ValueField(props) {
|
|
|
401
827
|
)
|
|
402
828
|
] }) : null
|
|
403
829
|
] }),
|
|
404
|
-
props.options ? /* @__PURE__ */ (0,
|
|
830
|
+
props.options ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
405
831
|
"select",
|
|
406
832
|
{
|
|
407
833
|
id: props.id,
|
|
@@ -414,14 +840,15 @@ function ValueField(props) {
|
|
|
414
840
|
onChange: (event) => {
|
|
415
841
|
props.onEdit(event.target.value);
|
|
416
842
|
},
|
|
417
|
-
children: props.options.map((option) => /* @__PURE__ */ (0,
|
|
843
|
+
children: props.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: option.value, children: option.label }, option.value))
|
|
418
844
|
}
|
|
419
|
-
) : /* @__PURE__ */ (0,
|
|
845
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
420
846
|
"input",
|
|
421
847
|
{
|
|
422
848
|
id: props.id,
|
|
423
849
|
name: props.id,
|
|
424
850
|
autoComplete: "off",
|
|
851
|
+
placeholder: props.placeholder,
|
|
425
852
|
"aria-describedby": hintId,
|
|
426
853
|
className: props.field.invalid ? Section_default.inputInvalid : Section_default.input,
|
|
427
854
|
type: props.numeric === true ? "number" : "text",
|
|
@@ -434,7 +861,7 @@ function ValueField(props) {
|
|
|
434
861
|
}
|
|
435
862
|
}
|
|
436
863
|
),
|
|
437
|
-
/* @__PURE__ */ (0,
|
|
864
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { id: hintId, className: props.field.invalid ? Section_default.invalid : Section_default.hint, children: props.field.invalid ? props.invalidLabel : props.hint })
|
|
438
865
|
] });
|
|
439
866
|
}
|
|
440
867
|
function ModelsBody({ models, t, locale }) {
|
|
@@ -442,7 +869,7 @@ function ModelsBody({ models, t, locale }) {
|
|
|
442
869
|
const metadataOnlyFailure = sources?.metadata.error !== void 0 && sources.listing.error === void 0;
|
|
443
870
|
const sourceStatus = sources ? ["listing", "metadata"].map((source) => {
|
|
444
871
|
const status = sources[source];
|
|
445
|
-
return /* @__PURE__ */ (0,
|
|
872
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: Section_default.hint, children: [
|
|
446
873
|
t(source === "listing" ? "modelsListingSource" : "modelsMetadataSource"),
|
|
447
874
|
": ",
|
|
448
875
|
" ",
|
|
@@ -453,28 +880,28 @@ function ModelsBody({ models, t, locale }) {
|
|
|
453
880
|
] }, source);
|
|
454
881
|
}) : null;
|
|
455
882
|
if (models.status === "failed") {
|
|
456
|
-
return /* @__PURE__ */ (0,
|
|
457
|
-
/* @__PURE__ */ (0,
|
|
458
|
-
models.message ? /* @__PURE__ */ (0,
|
|
883
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t(metadataOnlyFailure ? "modelsMetadataFailed" : "modelsFailed") }),
|
|
885
|
+
models.message ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: models.message }) : null,
|
|
459
886
|
sourceStatus
|
|
460
887
|
] });
|
|
461
888
|
}
|
|
462
|
-
if (models.status !== "ready") return /* @__PURE__ */ (0,
|
|
463
|
-
const progress = models.refreshing ? /* @__PURE__ */ (0,
|
|
464
|
-
if (models.stale) return /* @__PURE__ */ (0,
|
|
889
|
+
if (models.status !== "ready") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, role: "status", "aria-live": "polite", children: t("modelsLoading") });
|
|
890
|
+
const progress = models.refreshing ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, role: "status", children: t("modelsRefreshing") }) : null;
|
|
891
|
+
if (models.stale) return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
465
892
|
progress,
|
|
466
|
-
/* @__PURE__ */ (0,
|
|
467
|
-
models.message ? /* @__PURE__ */ (0,
|
|
893
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t(metadataOnlyFailure ? "modelsMetadataFailed" : "modelsStale") }),
|
|
894
|
+
models.message ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: models.message }) : null,
|
|
468
895
|
sourceStatus
|
|
469
896
|
] });
|
|
470
897
|
if (models.refreshing) return progress;
|
|
471
|
-
if (models.count === 0) return /* @__PURE__ */ (0,
|
|
898
|
+
if (models.count === 0) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: t("modelsEmpty") });
|
|
472
899
|
return null;
|
|
473
900
|
}
|
|
474
901
|
function OpencodeGoSection(props) {
|
|
475
902
|
const { useOpencodeGo, edit, resetField, save, discard, loadModels, setEnabled, setModelEnabled, t } = props;
|
|
476
903
|
if (useOpencodeGo === void 0 || edit === void 0 || resetField === void 0 || save === void 0 || discard === void 0 || loadModels === void 0 || setEnabled === void 0 || setModelEnabled === void 0 || t === void 0) return null;
|
|
477
|
-
return /* @__PURE__ */ (0,
|
|
904
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
478
905
|
Loaded,
|
|
479
906
|
{
|
|
480
907
|
state: useOpencodeGo((snapshot) => snapshot),
|
|
@@ -486,43 +913,63 @@ function OpencodeGoSection(props) {
|
|
|
486
913
|
discard,
|
|
487
914
|
loadModels,
|
|
488
915
|
setEnabled,
|
|
489
|
-
setModelEnabled
|
|
916
|
+
setModelEnabled,
|
|
917
|
+
accountActions: props.loadAccounts && props.addAccount && props.renameAccount && props.removeAccount && props.selectAccount && props.setAutoSwitch && props.replaceAccountKey && props.moveAccount ? {
|
|
918
|
+
loadAccounts: props.loadAccounts,
|
|
919
|
+
addAccount: props.addAccount,
|
|
920
|
+
renameAccount: props.renameAccount,
|
|
921
|
+
removeAccount: props.removeAccount,
|
|
922
|
+
selectAccount: props.selectAccount,
|
|
923
|
+
setAutoSwitch: props.setAutoSwitch,
|
|
924
|
+
replaceAccountKey: props.replaceAccountKey,
|
|
925
|
+
moveAccount: props.moveAccount
|
|
926
|
+
} : void 0
|
|
490
927
|
}
|
|
491
928
|
);
|
|
492
929
|
}
|
|
493
930
|
function Loaded(props) {
|
|
494
931
|
const { t, state, loadModels } = props;
|
|
495
|
-
const [advanced, setAdvanced] = (0,
|
|
496
|
-
const [modelsOpen, setModelsOpen] = (0,
|
|
497
|
-
const modelNotices = /* @__PURE__ */ (0,
|
|
498
|
-
/* @__PURE__ */ (0,
|
|
499
|
-
state.pickerFailed ? /* @__PURE__ */ (0,
|
|
932
|
+
const [advanced, setAdvanced] = (0, import_react3.useState)(false);
|
|
933
|
+
const [modelsOpen, setModelsOpen] = (0, import_react3.useState)(false);
|
|
934
|
+
const modelNotices = /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
935
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModelsBody, { models: state.models, t, locale: props.locale }),
|
|
936
|
+
state.pickerFailed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t("pickerFailed") }) : null
|
|
500
937
|
] });
|
|
501
|
-
(0,
|
|
938
|
+
(0, import_react3.useEffect)(() => {
|
|
502
939
|
if (state.available && state.models.status === "idle") loadModels();
|
|
503
940
|
}, [state.available, state.models.status, loadModels]);
|
|
504
941
|
if (!state.available) {
|
|
505
|
-
return /* @__PURE__ */ (0,
|
|
942
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.intro, children: t("unavailable") });
|
|
506
943
|
}
|
|
507
944
|
const disabled = !state.writable;
|
|
945
|
+
const accountCard = state.accounts && props.accountActions ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
946
|
+
AccountsCard,
|
|
947
|
+
{
|
|
948
|
+
state: state.accounts,
|
|
949
|
+
actions: props.accountActions,
|
|
950
|
+
writable: state.writable,
|
|
951
|
+
t,
|
|
952
|
+
locale: props.locale
|
|
953
|
+
}
|
|
954
|
+
) : null;
|
|
508
955
|
const fieldProps = {
|
|
509
956
|
invalidLabel: t("invalidValue"),
|
|
510
957
|
overriddenLabel: t("overridden"),
|
|
511
958
|
resetLabel: t("reset"),
|
|
512
959
|
disabled
|
|
513
960
|
};
|
|
514
|
-
const advancedOverridden = state.usageDisplay.overridden || state.apiKeyEnv.overridden || state.baseURL.overridden || state.refreshMinutes.overridden || state.streamIdleTimeoutMs.overridden || state.maxImages.overridden || state.maxRequestImageBytes.overridden || state.requestImagePixelBudget.overridden || state.requestImageMaxBytes.overridden;
|
|
515
|
-
return /* @__PURE__ */ (0,
|
|
516
|
-
/* @__PURE__ */ (0,
|
|
517
|
-
/* @__PURE__ */ (0,
|
|
518
|
-
/* @__PURE__ */ (0,
|
|
519
|
-
/* @__PURE__ */ (0,
|
|
961
|
+
const advancedOverridden = state.usageDisplay.overridden || state.apiKeyEnv.overridden || state.baseURL.overridden || state.proxyURL.overridden || state.refreshMinutes.overridden || state.streamIdleTimeoutMs.overridden || state.maxImages.overridden || state.maxRequestImageBytes.overridden || state.requestImagePixelBudget.overridden || state.requestImageMaxBytes.overridden;
|
|
962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.page, children: [
|
|
963
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.pageBody, children: [
|
|
964
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.pageTop, children: [
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: Section_default.title, children: t("titleLabel") }),
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.intro, children: t("intro") })
|
|
520
967
|
] }),
|
|
521
|
-
/* @__PURE__ */ (0,
|
|
522
|
-
/* @__PURE__ */ (0,
|
|
523
|
-
/* @__PURE__ */ (0,
|
|
524
|
-
/* @__PURE__ */ (0,
|
|
525
|
-
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: Section_default.card, children: [
|
|
969
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.cardHead, children: [
|
|
970
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { className: Section_default.cardTitle, children: t("enabledLabel") }),
|
|
971
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
972
|
+
import_dsh_client_ui_primitives3.Switch,
|
|
526
973
|
{
|
|
527
974
|
checked: state.enabled,
|
|
528
975
|
label: t("enabledLabel"),
|
|
@@ -531,38 +978,41 @@ function Loaded(props) {
|
|
|
531
978
|
}
|
|
532
979
|
)
|
|
533
980
|
] }),
|
|
534
|
-
/* @__PURE__ */ (0,
|
|
535
|
-
/* @__PURE__ */ (0,
|
|
536
|
-
|
|
537
|
-
/* @__PURE__ */ (0,
|
|
538
|
-
/* @__PURE__ */ (0,
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
/* @__PURE__ */ (0,
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
981
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: Section_default.cardBody, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: state.enabled ? t("enabledHint") : t("enabledOff") }) }),
|
|
982
|
+
accountCard ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: Section_default.cardDivider }),
|
|
984
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.cardHead, children: [
|
|
985
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Section_default.slot, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", focusable: "false", children: [
|
|
986
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "5.4", cy: "8", r: "3.1" }),
|
|
987
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8.5 8h5.3M11.9 8v2.2M10.2 8v1.6" })
|
|
988
|
+
] }) }),
|
|
989
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: Section_default.label, htmlFor: "opencode-go-key", children: t("keyLabel") }),
|
|
990
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Section_default.trailing, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Tag, { tone: state.apiKeyConfigured ? "success" : "warning", children: state.apiKeyConfigured ? t("keyConfigured") : t("keyMissing") }) })
|
|
991
|
+
] }),
|
|
992
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.cardBody, children: [
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
994
|
+
"input",
|
|
995
|
+
{
|
|
996
|
+
id: "opencode-go-key",
|
|
997
|
+
name: "api-key",
|
|
998
|
+
className: Section_default.input,
|
|
999
|
+
type: "password",
|
|
1000
|
+
autoComplete: "off",
|
|
1001
|
+
"aria-describedby": "opencode-go-key-hint",
|
|
1002
|
+
value: state.apiKey.text,
|
|
1003
|
+
disabled: !state.apiKeyWritable,
|
|
1004
|
+
onChange: (event) => {
|
|
1005
|
+
props.edit("apiKey", event.target.value);
|
|
1006
|
+
}
|
|
558
1007
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
1008
|
+
),
|
|
1009
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { id: "opencode-go-key-hint", className: Section_default.hint, children: state.apiKeyWritable ? t("keyHint") : t("keyNotWritable") })
|
|
1010
|
+
] })
|
|
562
1011
|
] })
|
|
563
1012
|
] }),
|
|
564
|
-
|
|
565
|
-
|
|
1013
|
+
accountCard,
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: modelsOpen ? Section_default.cardModels : Section_default.cardModels + " " + Section_default.cardFolded, children: [
|
|
1015
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
566
1016
|
"button",
|
|
567
1017
|
{
|
|
568
1018
|
type: "button",
|
|
@@ -573,14 +1023,14 @@ function Loaded(props) {
|
|
|
573
1023
|
setModelsOpen(!modelsOpen);
|
|
574
1024
|
},
|
|
575
1025
|
children: [
|
|
576
|
-
/* @__PURE__ */ (0,
|
|
577
|
-
/* @__PURE__ */ (0,
|
|
1026
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Section_default.cardTitle, children: t("modelsLabel") }),
|
|
1027
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChevronDown2, { className: modelsOpen ? Section_default.chevronOpen : Section_default.chevron })
|
|
578
1028
|
]
|
|
579
1029
|
}
|
|
580
1030
|
),
|
|
581
|
-
modelsOpen ? /* @__PURE__ */ (0,
|
|
1031
|
+
modelsOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { id: "opencode-go-models", className: Section_default.cardBody, children: [
|
|
582
1032
|
modelNotices,
|
|
583
|
-
/* @__PURE__ */ (0,
|
|
1033
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
584
1034
|
ModelEditor,
|
|
585
1035
|
{
|
|
586
1036
|
models: state.models,
|
|
@@ -590,8 +1040,8 @@ function Loaded(props) {
|
|
|
590
1040
|
disabled: disabled || state.saving,
|
|
591
1041
|
modelVisibility: state.modelVisibility,
|
|
592
1042
|
visibilitySaving: state.pickerSaving,
|
|
593
|
-
filterAction: /* @__PURE__ */ (0,
|
|
594
|
-
|
|
1043
|
+
filterAction: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1044
|
+
import_dsh_client_ui_primitives3.Button,
|
|
595
1045
|
{
|
|
596
1046
|
variant: "outline",
|
|
597
1047
|
size: "sm",
|
|
@@ -606,10 +1056,10 @@ function Loaded(props) {
|
|
|
606
1056
|
}
|
|
607
1057
|
}
|
|
608
1058
|
)
|
|
609
|
-
] }) : /* @__PURE__ */ (0,
|
|
1059
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: Section_default.cardNotes, children: modelNotices })
|
|
610
1060
|
] }),
|
|
611
|
-
/* @__PURE__ */ (0,
|
|
612
|
-
/* @__PURE__ */ (0,
|
|
1061
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: Section_default.card, children: [
|
|
1062
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
613
1063
|
"button",
|
|
614
1064
|
{
|
|
615
1065
|
type: "button",
|
|
@@ -620,17 +1070,17 @@ function Loaded(props) {
|
|
|
620
1070
|
setAdvanced(!advanced);
|
|
621
1071
|
},
|
|
622
1072
|
children: [
|
|
623
|
-
/* @__PURE__ */ (0,
|
|
624
|
-
/* @__PURE__ */ (0,
|
|
625
|
-
advancedOverridden ? /* @__PURE__ */ (0,
|
|
626
|
-
/* @__PURE__ */ (0,
|
|
1073
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Section_default.cardTitle, children: t("advancedLabel") }),
|
|
1074
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Section_default.cardSub, children: t("advancedSummary") }),
|
|
1075
|
+
advancedOverridden ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Tag, { tone: "neutral", children: t("overridden") }) : null,
|
|
1076
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChevronDown2, { className: advanced ? Section_default.chevronOpen : Section_default.chevron })
|
|
627
1077
|
]
|
|
628
1078
|
}
|
|
629
1079
|
),
|
|
630
|
-
advanced ? /* @__PURE__ */ (0,
|
|
631
|
-
/* @__PURE__ */ (0,
|
|
632
|
-
/* @__PURE__ */ (0,
|
|
633
|
-
/* @__PURE__ */ (0,
|
|
1080
|
+
advanced ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { id: "opencode-go-advanced", className: Section_default.cardBody, children: [
|
|
1081
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: t("advancedHint") }),
|
|
1082
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.advancedGrid, children: [
|
|
1083
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
634
1084
|
ValueField,
|
|
635
1085
|
{
|
|
636
1086
|
id: "opencode-go-usage-display",
|
|
@@ -647,7 +1097,7 @@ function Loaded(props) {
|
|
|
647
1097
|
}
|
|
648
1098
|
}
|
|
649
1099
|
),
|
|
650
|
-
/* @__PURE__ */ (0,
|
|
1100
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
651
1101
|
ValueField,
|
|
652
1102
|
{
|
|
653
1103
|
id: "opencode-go-api-key-env",
|
|
@@ -663,7 +1113,7 @@ function Loaded(props) {
|
|
|
663
1113
|
}
|
|
664
1114
|
}
|
|
665
1115
|
),
|
|
666
|
-
/* @__PURE__ */ (0,
|
|
1116
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
667
1117
|
ValueField,
|
|
668
1118
|
{
|
|
669
1119
|
id: "opencode-go-base-url",
|
|
@@ -679,7 +1129,25 @@ function Loaded(props) {
|
|
|
679
1129
|
}
|
|
680
1130
|
}
|
|
681
1131
|
),
|
|
682
|
-
/* @__PURE__ */ (0,
|
|
1132
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1133
|
+
ValueField,
|
|
1134
|
+
{
|
|
1135
|
+
id: "opencode-go-proxy-url",
|
|
1136
|
+
label: t("proxyURLLabel"),
|
|
1137
|
+
hint: t("proxyURLHint"),
|
|
1138
|
+
placeholder: "http://127.0.0.1:7890",
|
|
1139
|
+
field: state.proxyURL,
|
|
1140
|
+
...fieldProps,
|
|
1141
|
+
invalidLabel: t("proxyURLInvalid"),
|
|
1142
|
+
onEdit: (text) => {
|
|
1143
|
+
props.edit("proxyURL", text);
|
|
1144
|
+
},
|
|
1145
|
+
onReset: () => {
|
|
1146
|
+
props.resetField("proxyURL");
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
),
|
|
1150
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
683
1151
|
ValueField,
|
|
684
1152
|
{
|
|
685
1153
|
id: "opencode-go-refresh-minutes",
|
|
@@ -696,7 +1164,7 @@ function Loaded(props) {
|
|
|
696
1164
|
}
|
|
697
1165
|
}
|
|
698
1166
|
),
|
|
699
|
-
/* @__PURE__ */ (0,
|
|
1167
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
700
1168
|
ValueField,
|
|
701
1169
|
{
|
|
702
1170
|
id: "opencode-go-stream-idle",
|
|
@@ -713,7 +1181,7 @@ function Loaded(props) {
|
|
|
713
1181
|
}
|
|
714
1182
|
}
|
|
715
1183
|
),
|
|
716
|
-
/* @__PURE__ */ (0,
|
|
1184
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
717
1185
|
ValueField,
|
|
718
1186
|
{
|
|
719
1187
|
id: "opencode-go-max-images",
|
|
@@ -730,7 +1198,7 @@ function Loaded(props) {
|
|
|
730
1198
|
}
|
|
731
1199
|
}
|
|
732
1200
|
),
|
|
733
|
-
/* @__PURE__ */ (0,
|
|
1201
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
734
1202
|
ValueField,
|
|
735
1203
|
{
|
|
736
1204
|
id: "opencode-go-max-request-image-bytes",
|
|
@@ -747,7 +1215,7 @@ function Loaded(props) {
|
|
|
747
1215
|
}
|
|
748
1216
|
}
|
|
749
1217
|
),
|
|
750
|
-
/* @__PURE__ */ (0,
|
|
1218
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
751
1219
|
ValueField,
|
|
752
1220
|
{
|
|
753
1221
|
id: "opencode-go-image-pixel-budget",
|
|
@@ -764,7 +1232,7 @@ function Loaded(props) {
|
|
|
764
1232
|
}
|
|
765
1233
|
}
|
|
766
1234
|
),
|
|
767
|
-
/* @__PURE__ */ (0,
|
|
1235
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
768
1236
|
ValueField,
|
|
769
1237
|
{
|
|
770
1238
|
id: "opencode-go-image-max-bytes",
|
|
@@ -784,12 +1252,12 @@ function Loaded(props) {
|
|
|
784
1252
|
] })
|
|
785
1253
|
] }) : null
|
|
786
1254
|
] }),
|
|
787
|
-
disabled ? /* @__PURE__ */ (0,
|
|
1255
|
+
disabled ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: t("readOnly") }) : null
|
|
788
1256
|
] }),
|
|
789
|
-
/* @__PURE__ */ (0,
|
|
790
|
-
/* @__PURE__ */ (0,
|
|
791
|
-
/* @__PURE__ */ (0,
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
1257
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.actions, children: [
|
|
1258
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "primary", size: "md", disabled: disabled || !state.dirty || state.invalid || state.saving || state.pickerSaving, onClick: props.save, children: state.saving ? t("saving") : t("save") }),
|
|
1259
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Button, { variant: "outline", size: "md", disabled: disabled || !state.dirty || state.saving, onClick: props.discard, children: t("discard") }),
|
|
1260
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
793
1261
|
"a",
|
|
794
1262
|
{
|
|
795
1263
|
className: Section_default.starLink,
|
|
@@ -798,12 +1266,12 @@ function Loaded(props) {
|
|
|
798
1266
|
rel: "noopener noreferrer",
|
|
799
1267
|
title: t("starProjectTitle"),
|
|
800
1268
|
children: [
|
|
801
|
-
/* @__PURE__ */ (0,
|
|
802
|
-
/* @__PURE__ */ (0,
|
|
1269
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { viewBox: "0 0 24 24", width: "18", height: "18", fill: "currentColor", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" }) }),
|
|
1270
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t("starProject") })
|
|
803
1271
|
]
|
|
804
1272
|
}
|
|
805
1273
|
),
|
|
806
|
-
state.failed ? /* @__PURE__ */ (0,
|
|
1274
|
+
state.failed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, children: t("savedFailed") }) : null
|
|
807
1275
|
] })
|
|
808
1276
|
] });
|
|
809
1277
|
}
|
|
@@ -811,6 +1279,329 @@ function Loaded(props) {
|
|
|
811
1279
|
// src/provider-identity.ts
|
|
812
1280
|
var PROVIDER_ID = "dsh-opencode-go";
|
|
813
1281
|
|
|
1282
|
+
// src/proxy-url.ts
|
|
1283
|
+
function assertProxyURL(raw) {
|
|
1284
|
+
const value = raw?.trim() ?? "";
|
|
1285
|
+
if (!value) return "";
|
|
1286
|
+
let url;
|
|
1287
|
+
try {
|
|
1288
|
+
url = new URL(value);
|
|
1289
|
+
} catch {
|
|
1290
|
+
throw new Error("OpenCode Go: proxy address must be a valid URL");
|
|
1291
|
+
}
|
|
1292
|
+
if (!["http:", "https:", "socks5:"].includes(url.protocol)) {
|
|
1293
|
+
throw new Error("OpenCode Go: proxy address must use http://, https:// or socks5://");
|
|
1294
|
+
}
|
|
1295
|
+
if (!url.hostname || url.port === "0" || url.pathname !== "" && url.pathname !== "/" || url.search || url.hash) {
|
|
1296
|
+
throw new Error("OpenCode Go: proxy address must contain a host and optional port, without a path, query or fragment");
|
|
1297
|
+
}
|
|
1298
|
+
try {
|
|
1299
|
+
decodeURIComponent(url.username);
|
|
1300
|
+
decodeURIComponent(url.password);
|
|
1301
|
+
} catch {
|
|
1302
|
+
throw new Error("OpenCode Go: proxy credentials contain invalid URL encoding");
|
|
1303
|
+
}
|
|
1304
|
+
return url.href;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
// src/client/accounts-controller.ts
|
|
1308
|
+
function isSettingsConflict(error) {
|
|
1309
|
+
if (!error || typeof error !== "object") return false;
|
|
1310
|
+
const { name, code, message } = error;
|
|
1311
|
+
return /conflict/i.test(`${String(name ?? "")} ${String(code ?? "")} ${String(message ?? "")}`);
|
|
1312
|
+
}
|
|
1313
|
+
var GoAccountsController = class {
|
|
1314
|
+
constructor(scope, ctx, readUsage, publish, blocked) {
|
|
1315
|
+
this.scope = scope;
|
|
1316
|
+
this.ctx = ctx;
|
|
1317
|
+
this.readUsage = readUsage;
|
|
1318
|
+
this.publish = publish;
|
|
1319
|
+
this.blocked = blocked;
|
|
1320
|
+
this.sync();
|
|
1321
|
+
}
|
|
1322
|
+
rows = /* @__PURE__ */ new Map();
|
|
1323
|
+
busy = false;
|
|
1324
|
+
refreshing = false;
|
|
1325
|
+
failure;
|
|
1326
|
+
epoch = 0;
|
|
1327
|
+
identity = "";
|
|
1328
|
+
loaded = false;
|
|
1329
|
+
disposed = false;
|
|
1330
|
+
snapshot() {
|
|
1331
|
+
const config = this.scope.getSnapshot().value ?? {};
|
|
1332
|
+
return {
|
|
1333
|
+
entries: accountsOf(config).map((account) => ({ ...this.rows.get(account.apiKeyEnv), ...account })),
|
|
1334
|
+
activeRef: accountRefOf(config),
|
|
1335
|
+
autoSwitch: config.autoSwitch === true,
|
|
1336
|
+
busy: this.busy,
|
|
1337
|
+
blocked: this.blocked(),
|
|
1338
|
+
refreshing: this.refreshing,
|
|
1339
|
+
failure: this.failure
|
|
1340
|
+
};
|
|
1341
|
+
}
|
|
1342
|
+
sync() {
|
|
1343
|
+
const config = this.scope.getSnapshot().value ?? {};
|
|
1344
|
+
const identity = JSON.stringify([
|
|
1345
|
+
accountsOf(config).map((account) => [account.id, account.apiKeyEnv]).sort((left, right) => left[1] < right[1] ? -1 : left[1] > right[1] ? 1 : 0),
|
|
1346
|
+
config.baseURL,
|
|
1347
|
+
config.proxyURL
|
|
1348
|
+
]);
|
|
1349
|
+
if (identity === this.identity) return;
|
|
1350
|
+
this.identity = identity;
|
|
1351
|
+
this.epoch++;
|
|
1352
|
+
this.rows.clear();
|
|
1353
|
+
this.refreshing = false;
|
|
1354
|
+
if (this.loaded) void this.refresh();
|
|
1355
|
+
}
|
|
1356
|
+
dispose() {
|
|
1357
|
+
this.disposed = true;
|
|
1358
|
+
this.epoch++;
|
|
1359
|
+
}
|
|
1360
|
+
invalidate(ref) {
|
|
1361
|
+
if (!accountsOf(this.scope.getSnapshot().value ?? {}).some((account) => account.apiKeyEnv === ref)) return;
|
|
1362
|
+
this.epoch++;
|
|
1363
|
+
this.rows.delete(ref);
|
|
1364
|
+
if (this.loaded) void this.refresh();
|
|
1365
|
+
}
|
|
1366
|
+
async refresh() {
|
|
1367
|
+
this.loaded = true;
|
|
1368
|
+
const epoch = ++this.epoch;
|
|
1369
|
+
const accounts = [...accountsOf(this.scope.getSnapshot().value ?? {})];
|
|
1370
|
+
this.refreshing = true;
|
|
1371
|
+
this.publish();
|
|
1372
|
+
try {
|
|
1373
|
+
const described = await this.ctx.remote.credentials.describe(accounts.map((account) => account.apiKeyEnv));
|
|
1374
|
+
if (this.disposed || epoch !== this.epoch) return;
|
|
1375
|
+
if (!described.ok) {
|
|
1376
|
+
this.failure = "read";
|
|
1377
|
+
this.markUnreadable(accounts, described.error instanceof Error ? described.error.message : String(described.error));
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
this.failure = void 0;
|
|
1381
|
+
await Promise.all(accounts.map(async (account) => {
|
|
1382
|
+
const ref = account.apiKeyEnv;
|
|
1383
|
+
const info = described.value[ref];
|
|
1384
|
+
const previous = this.rows.get(ref);
|
|
1385
|
+
this.rows.set(ref, {
|
|
1386
|
+
...previous,
|
|
1387
|
+
...account,
|
|
1388
|
+
configured: info?.configured ?? false,
|
|
1389
|
+
writable: info?.writable ?? true,
|
|
1390
|
+
loading: info?.configured === true,
|
|
1391
|
+
failed: false
|
|
1392
|
+
});
|
|
1393
|
+
this.publish();
|
|
1394
|
+
if (!info?.configured) {
|
|
1395
|
+
this.rows.set(ref, { ...account, configured: false, writable: info?.writable ?? true });
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
try {
|
|
1399
|
+
const usage = await this.readUsage(ref);
|
|
1400
|
+
if (this.disposed || epoch !== this.epoch) return;
|
|
1401
|
+
this.rows.set(ref, { ...account, configured: true, writable: info.writable, usage, updatedAt: Date.now() });
|
|
1402
|
+
} catch (error) {
|
|
1403
|
+
if (this.disposed || epoch !== this.epoch) return;
|
|
1404
|
+
const details = error && typeof error === "object" && "code" in error && error.code === "opencode-go/usage-unavailable" && "details" in error && error.details && typeof error.details === "object" ? error.details : void 0;
|
|
1405
|
+
const retain = details?.retryable === true && details.retainPrevious === true && previous?.usage?.source && previous.usage.source === details.source;
|
|
1406
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1407
|
+
this.rows.set(ref, {
|
|
1408
|
+
...account,
|
|
1409
|
+
configured: true,
|
|
1410
|
+
writable: info.writable,
|
|
1411
|
+
failed: true,
|
|
1412
|
+
problem: message.length > 200 ? message.slice(0, 200) + "\u2026" : message,
|
|
1413
|
+
...retain ? { usage: previous.usage, updatedAt: previous.updatedAt, stale: true } : {}
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
1416
|
+
this.publish();
|
|
1417
|
+
}));
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
if (epoch === this.epoch) {
|
|
1420
|
+
this.failure = "read";
|
|
1421
|
+
this.markUnreadable(accounts, error instanceof Error ? error.message : String(error));
|
|
1422
|
+
}
|
|
1423
|
+
} finally {
|
|
1424
|
+
if (!this.disposed && epoch === this.epoch) {
|
|
1425
|
+
this.refreshing = false;
|
|
1426
|
+
this.publish();
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
/** Mark every account row as unreadable with the Host's own diagnostic. */
|
|
1431
|
+
markUnreadable(accounts, message) {
|
|
1432
|
+
const problem = message.length > 200 ? message.slice(0, 200) + "\u2026" : message;
|
|
1433
|
+
for (const account of accounts) this.rows.set(account.apiKeyEnv, { ...account, failed: true, problem });
|
|
1434
|
+
this.publish();
|
|
1435
|
+
}
|
|
1436
|
+
actions() {
|
|
1437
|
+
return {
|
|
1438
|
+
loadAccounts: () => {
|
|
1439
|
+
void this.refresh();
|
|
1440
|
+
},
|
|
1441
|
+
addAccount: (name, key) => this.add(name, key),
|
|
1442
|
+
renameAccount: (ref, name) => this.rename(ref, name),
|
|
1443
|
+
removeAccount: (ref) => this.remove(ref),
|
|
1444
|
+
selectAccount: (ref) => this.select(ref),
|
|
1445
|
+
setAutoSwitch: (next) => this.run(async () => {
|
|
1446
|
+
await this.scope.set("autoSwitch", next);
|
|
1447
|
+
return this.scope.getSnapshot().value?.autoSwitch === next;
|
|
1448
|
+
}),
|
|
1449
|
+
replaceAccountKey: (ref, key) => this.run(async () => {
|
|
1450
|
+
if (!key.trim() || !this.account(ref) || this.rows.get(ref)?.writable === false) return false;
|
|
1451
|
+
const response = await this.ctx.remote.credentials.set(ref, key.trim());
|
|
1452
|
+
if (!response.ok) return false;
|
|
1453
|
+
this.invalidate(ref);
|
|
1454
|
+
return true;
|
|
1455
|
+
}, false),
|
|
1456
|
+
moveAccount: (ref, toIndex) => this.move(ref, toIndex)
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Reorder the visible accounts and keep the preferred reference on the first row.
|
|
1461
|
+
* The adapter tries the preferred reference first and the rest in array order, so
|
|
1462
|
+
* one write is what makes top-to-bottom the real call order. A placeholder row the
|
|
1463
|
+
* settings never stored is materialized here, which its `legacy:` id admits.
|
|
1464
|
+
*/
|
|
1465
|
+
move(ref, toIndex) {
|
|
1466
|
+
return this.run(async () => {
|
|
1467
|
+
const snapshot = this.scope.getSnapshot();
|
|
1468
|
+
const entries = [...accountsOf(snapshot.value ?? {})];
|
|
1469
|
+
const from = entries.findIndex((account) => account.apiKeyEnv === ref);
|
|
1470
|
+
if (from < 0 || !Number.isInteger(toIndex) || toIndex < 0 || toIndex >= entries.length || toIndex === from) return false;
|
|
1471
|
+
const [moved] = entries.splice(from, 1);
|
|
1472
|
+
entries.splice(toIndex, 0, moved);
|
|
1473
|
+
await this.mutate([
|
|
1474
|
+
{ op: "set", path: ["accounts"], value: entries },
|
|
1475
|
+
{ op: "set", path: ["apiKeyEnv"], value: entries[0].apiKeyEnv }
|
|
1476
|
+
], snapshot.revision);
|
|
1477
|
+
const after = this.scope.getSnapshot().value;
|
|
1478
|
+
return after?.apiKeyEnv === entries[0].apiKeyEnv && after.accounts?.[toIndex]?.apiKeyEnv === ref;
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
account(ref) {
|
|
1482
|
+
return accountsOf(this.scope.getSnapshot().value ?? {}).find((account) => account.apiKeyEnv === ref);
|
|
1483
|
+
}
|
|
1484
|
+
async mutate(ops, revision = this.scope.getSnapshot().revision) {
|
|
1485
|
+
await this.scope.mutate(ops, revision);
|
|
1486
|
+
}
|
|
1487
|
+
add(name, key) {
|
|
1488
|
+
return this.run(async () => {
|
|
1489
|
+
if (!name.trim() || name.trim().length > 80 || !key.trim()) return false;
|
|
1490
|
+
const id3 = Array.from(crypto.getRandomValues(new Uint8Array(16)), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1491
|
+
const ref = ACCOUNT_REF_PREFIX + id3.replaceAll("-", "").toUpperCase();
|
|
1492
|
+
const account = { id: id3, name: name.trim(), apiKeyEnv: ref };
|
|
1493
|
+
const response = await this.ctx.remote.credentials.set(ref, key.trim());
|
|
1494
|
+
if (!response.ok) return false;
|
|
1495
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
1496
|
+
const snapshot = this.scope.getSnapshot();
|
|
1497
|
+
const existing = accountsOf(snapshot.value ?? {});
|
|
1498
|
+
if (existing.some((entry) => entry.id === id3)) return true;
|
|
1499
|
+
const configured = await this.configuredOf(existing.map((entry) => entry.apiKeyEnv));
|
|
1500
|
+
const accounts = existing.filter((entry) => !(snapshot.value?.accounts == null && !entry.name && configured.get(entry.apiKeyEnv) === false));
|
|
1501
|
+
if (accounts.length >= MAX_ACCOUNTS) break;
|
|
1502
|
+
const first = existing.length === 0 || existing.every((entry) => configured.get(entry.apiKeyEnv) === false);
|
|
1503
|
+
try {
|
|
1504
|
+
await this.mutate([
|
|
1505
|
+
{ op: "set", path: ["accounts"], value: [...accounts, account] },
|
|
1506
|
+
...first ? [{ op: "set", path: ["apiKeyEnv"], value: ref }] : []
|
|
1507
|
+
], snapshot.revision);
|
|
1508
|
+
} catch (error) {
|
|
1509
|
+
if (attempt < 2 && isSettingsConflict(error)) continue;
|
|
1510
|
+
return false;
|
|
1511
|
+
}
|
|
1512
|
+
if (this.scope.getSnapshot().value?.accounts?.some((entry) => entry.id === id3)) return true;
|
|
1513
|
+
break;
|
|
1514
|
+
}
|
|
1515
|
+
try {
|
|
1516
|
+
if (!(await this.ctx.remote.credentials.unset(ref)).ok) this.failure = "cleanup";
|
|
1517
|
+
} catch {
|
|
1518
|
+
this.failure = "cleanup";
|
|
1519
|
+
}
|
|
1520
|
+
return false;
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1523
|
+
/** Loaded rows answer from cache; anything they do not know is described on
|
|
1524
|
+
* the spot, so a placeholder decision never races the page's first describe. */
|
|
1525
|
+
async configuredOf(refs) {
|
|
1526
|
+
const configured = /* @__PURE__ */ new Map();
|
|
1527
|
+
const unknown = refs.filter((ref) => {
|
|
1528
|
+
const known = this.rows.get(ref)?.configured;
|
|
1529
|
+
if (known === void 0) return true;
|
|
1530
|
+
configured.set(ref, known);
|
|
1531
|
+
return false;
|
|
1532
|
+
});
|
|
1533
|
+
if (unknown.length === 0) return configured;
|
|
1534
|
+
try {
|
|
1535
|
+
const described = await this.ctx.remote.credentials.describe(unknown);
|
|
1536
|
+
if (described.ok) for (const ref of unknown) configured.set(ref, described.value[ref]?.configured ?? false);
|
|
1537
|
+
} catch {
|
|
1538
|
+
}
|
|
1539
|
+
return configured;
|
|
1540
|
+
}
|
|
1541
|
+
rename(ref, name) {
|
|
1542
|
+
return this.run(async () => {
|
|
1543
|
+
if (!this.account(ref) || !name.trim() || name.trim().length > 80) return false;
|
|
1544
|
+
const accounts = accountsOf(this.scope.getSnapshot().value ?? {}).map((account) => account.apiKeyEnv === ref ? { ...account, name: name.trim() } : account);
|
|
1545
|
+
await this.mutate([{ op: "set", path: ["accounts"], value: accounts }]);
|
|
1546
|
+
return this.scope.getSnapshot().value?.accounts?.find((account) => account.apiKeyEnv === ref)?.name === name.trim();
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
select(ref) {
|
|
1550
|
+
return this.run(async () => {
|
|
1551
|
+
if (!this.account(ref)) return false;
|
|
1552
|
+
await this.mutate([{ op: "set", path: ["apiKeyEnv"], value: ref }]);
|
|
1553
|
+
return accountRefOf(this.scope.getSnapshot().value ?? {}) === ref;
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
remove(ref) {
|
|
1557
|
+
return this.run(async () => {
|
|
1558
|
+
if (!this.account(ref)) return false;
|
|
1559
|
+
if (ref.startsWith(ACCOUNT_REF_PREFIX)) {
|
|
1560
|
+
const described = await this.ctx.remote.credentials.describe([ref]).catch(() => void 0);
|
|
1561
|
+
if (!described?.ok || described.value[ref] === void 0) {
|
|
1562
|
+
this.failure = "remove";
|
|
1563
|
+
return false;
|
|
1564
|
+
}
|
|
1565
|
+
if (described.value[ref].configured === true) {
|
|
1566
|
+
let removed = false;
|
|
1567
|
+
try {
|
|
1568
|
+
removed = (await this.ctx.remote.credentials.unset(ref)).ok;
|
|
1569
|
+
} catch {
|
|
1570
|
+
}
|
|
1571
|
+
if (!removed) {
|
|
1572
|
+
this.failure = "remove";
|
|
1573
|
+
return false;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
const config = this.scope.getSnapshot().value ?? {};
|
|
1578
|
+
const remaining = accountsOf(config).filter((account) => account.apiKeyEnv !== ref);
|
|
1579
|
+
await this.mutate([
|
|
1580
|
+
{ op: "set", path: ["accounts"], value: remaining },
|
|
1581
|
+
...accountRefOf(config) === ref && remaining.length ? [{ op: "set", path: ["apiKeyEnv"], value: remaining[0].apiKeyEnv }] : []
|
|
1582
|
+
]);
|
|
1583
|
+
return !this.account(ref);
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
async run(action, requiresSettings = true) {
|
|
1587
|
+
if (this.busy || this.blocked() || requiresSettings && !this.scope.getSnapshot().writable) return false;
|
|
1588
|
+
this.busy = true;
|
|
1589
|
+
this.failure = void 0;
|
|
1590
|
+
this.publish();
|
|
1591
|
+
try {
|
|
1592
|
+
const accepted = await action();
|
|
1593
|
+
if (!accepted && !this.failure) this.failure = "write";
|
|
1594
|
+
return accepted;
|
|
1595
|
+
} catch {
|
|
1596
|
+
this.failure ??= "write";
|
|
1597
|
+
return false;
|
|
1598
|
+
} finally {
|
|
1599
|
+
this.busy = false;
|
|
1600
|
+
this.publish();
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
};
|
|
1604
|
+
|
|
814
1605
|
// src/client/staged-form.ts
|
|
815
1606
|
var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
816
1607
|
function numberField(field, validate = () => true) {
|
|
@@ -978,7 +1769,11 @@ var StagedForm = class {
|
|
|
978
1769
|
this.publish();
|
|
979
1770
|
let landed = true;
|
|
980
1771
|
for (const write of writes) {
|
|
981
|
-
|
|
1772
|
+
try {
|
|
1773
|
+
landed = await write() && landed;
|
|
1774
|
+
} catch {
|
|
1775
|
+
landed = false;
|
|
1776
|
+
}
|
|
982
1777
|
}
|
|
983
1778
|
if (landed) this.staged.clear();
|
|
984
1779
|
this.saving = false;
|
|
@@ -1088,6 +1883,10 @@ var OpencodeGoSectionController = class {
|
|
|
1088
1883
|
constructor(scope, ctx, readModels = async () => {
|
|
1089
1884
|
const result = await ctx.remote.llm.discoverModels(OPENCODE_GO_NS, { provider: PROVIDER_ID });
|
|
1090
1885
|
return result.ok ? { ok: true, value: { models: result.value, stale: false } } : result;
|
|
1886
|
+
}, readUsage = async (ref) => {
|
|
1887
|
+
const result = await ctx.remote.opencodeGoUsage.readAccount(ref);
|
|
1888
|
+
if (!result.ok) throw result.error;
|
|
1889
|
+
return result.value;
|
|
1091
1890
|
}) {
|
|
1092
1891
|
this.scope = scope;
|
|
1093
1892
|
this.ctx = ctx;
|
|
@@ -1105,6 +1904,18 @@ var OpencodeGoSectionController = class {
|
|
|
1105
1904
|
},
|
|
1106
1905
|
textField("apiKeyEnv"),
|
|
1107
1906
|
textField("baseURL"),
|
|
1907
|
+
{
|
|
1908
|
+
...textField("proxyURL"),
|
|
1909
|
+
// Blank explicitly disables an inherited proxy; Reset removes the override.
|
|
1910
|
+
parse: (text) => {
|
|
1911
|
+
try {
|
|
1912
|
+
assertProxyURL(text);
|
|
1913
|
+
return { kind: "set", value: text.trim() };
|
|
1914
|
+
} catch {
|
|
1915
|
+
return void 0;
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
},
|
|
1108
1919
|
numberField("refreshMinutes"),
|
|
1109
1920
|
numberField("streamIdleTimeoutMs"),
|
|
1110
1921
|
numberField("maxImages", (value) => Number.isSafeInteger(value) && value > 0),
|
|
@@ -1116,9 +1927,25 @@ var OpencodeGoSectionController = class {
|
|
|
1116
1927
|
[{ field: API_KEY_FIELD, write: (text) => this.writeKey(text) }]
|
|
1117
1928
|
);
|
|
1118
1929
|
this.store = this.form.bind(() => this.projection());
|
|
1119
|
-
|
|
1930
|
+
this.accounts = new GoAccountsController(
|
|
1931
|
+
scope,
|
|
1932
|
+
ctx,
|
|
1933
|
+
readUsage,
|
|
1934
|
+
() => {
|
|
1935
|
+
this.store.set(this.projection());
|
|
1936
|
+
},
|
|
1937
|
+
() => this.form.shell().saving || this.pickerSaving || Boolean(this.form.field(API_KEY_FIELD).text.trim())
|
|
1938
|
+
);
|
|
1939
|
+
this.store.set(this.projection());
|
|
1940
|
+
const networkIdentity = () => JSON.stringify([
|
|
1941
|
+
scope.getSnapshot().value?.baseURL,
|
|
1942
|
+
scope.getSnapshot().value?.proxyURL
|
|
1943
|
+
]);
|
|
1944
|
+
let modelsEndpoint = networkIdentity();
|
|
1120
1945
|
this.unsubscribe = scope.subscribe(() => {
|
|
1121
|
-
|
|
1946
|
+
this.accounts?.sync();
|
|
1947
|
+
this.store.set(this.projection());
|
|
1948
|
+
const endpoint = networkIdentity();
|
|
1122
1949
|
if (endpoint !== modelsEndpoint) {
|
|
1123
1950
|
modelsEndpoint = endpoint;
|
|
1124
1951
|
this.modelsRequest++;
|
|
@@ -1138,8 +1965,13 @@ var OpencodeGoSectionController = class {
|
|
|
1138
1965
|
pickerFailed = false;
|
|
1139
1966
|
face;
|
|
1140
1967
|
unsubscribe;
|
|
1968
|
+
accounts;
|
|
1969
|
+
credentialRequest = 0;
|
|
1970
|
+
keyDraftRef;
|
|
1141
1971
|
/** Release subscriptions without disposing the host's shared form. */
|
|
1142
1972
|
dispose() {
|
|
1973
|
+
this.credentialRequest++;
|
|
1974
|
+
this.accounts?.dispose();
|
|
1143
1975
|
this.modelsRequest++;
|
|
1144
1976
|
this.unsubscribe();
|
|
1145
1977
|
this.form.dispose();
|
|
@@ -1147,6 +1979,8 @@ var OpencodeGoSectionController = class {
|
|
|
1147
1979
|
projection() {
|
|
1148
1980
|
return {
|
|
1149
1981
|
...this.form.shell(),
|
|
1982
|
+
saving: this.form.shell().saving || this.accounts?.snapshot().busy === true,
|
|
1983
|
+
accounts: this.accounts?.snapshot(),
|
|
1150
1984
|
enabled: this.enabled(),
|
|
1151
1985
|
usageDisplay: this.form.field("usageDisplay"),
|
|
1152
1986
|
modelVisibility: this.scope.getSnapshot().value?.modelVisibility ?? {},
|
|
@@ -1154,6 +1988,7 @@ var OpencodeGoSectionController = class {
|
|
|
1154
1988
|
pickerFailed: this.pickerFailed,
|
|
1155
1989
|
apiKeyEnv: this.form.field("apiKeyEnv"),
|
|
1156
1990
|
baseURL: this.form.field("baseURL"),
|
|
1991
|
+
proxyURL: this.form.field("proxyURL"),
|
|
1157
1992
|
refreshMinutes: this.form.field("refreshMinutes"),
|
|
1158
1993
|
streamIdleTimeoutMs: this.form.field("streamIdleTimeoutMs"),
|
|
1159
1994
|
maxImages: this.form.field("maxImages"),
|
|
@@ -1161,7 +1996,7 @@ var OpencodeGoSectionController = class {
|
|
|
1161
1996
|
requestImagePixelBudget: this.form.field("requestImagePixelBudget"),
|
|
1162
1997
|
requestImageMaxBytes: this.form.field("requestImageMaxBytes"),
|
|
1163
1998
|
apiKey: this.form.field(API_KEY_FIELD),
|
|
1164
|
-
apiKeyConfigured: this.credential.configured,
|
|
1999
|
+
apiKeyConfigured: this.credential.ref === refOf(this.scope.getSnapshot()) && this.credential.configured && accountsOf(this.scope.getSnapshot().value ?? {}).length > 0,
|
|
1165
2000
|
apiKeyWritable: this.credential.writable,
|
|
1166
2001
|
models: this.models,
|
|
1167
2002
|
modelLimits: this.form.field("modelLimits"),
|
|
@@ -1218,7 +2053,7 @@ var OpencodeGoSectionController = class {
|
|
|
1218
2053
|
}
|
|
1219
2054
|
/** Serialize immediate switches with form saves; refused writes retain committed values. */
|
|
1220
2055
|
async writePickerSetting(field, value, accepted) {
|
|
1221
|
-
if (this.pickerSaving || this.form.shell().saving || !this.scope.getSnapshot().writable) return;
|
|
2056
|
+
if (this.pickerSaving || this.form.shell().saving || this.accounts?.snapshot().busy || !this.scope.getSnapshot().writable) return;
|
|
1222
2057
|
this.pickerSaving = true;
|
|
1223
2058
|
this.pickerFailed = false;
|
|
1224
2059
|
this.store.set(this.projection());
|
|
@@ -1283,13 +2118,19 @@ var OpencodeGoSectionController = class {
|
|
|
1283
2118
|
* reference in force.
|
|
1284
2119
|
*/
|
|
1285
2120
|
async readCredential() {
|
|
2121
|
+
const request = ++this.credentialRequest;
|
|
1286
2122
|
const ref = refOf(this.scope.getSnapshot());
|
|
2123
|
+
if (accountsOf(this.scope.getSnapshot().value ?? {}).length === 0) {
|
|
2124
|
+
this.credential = { ref, configured: false, writable: false };
|
|
2125
|
+
this.store.set(this.projection());
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
1287
2128
|
if (ref !== this.credential.ref) {
|
|
1288
2129
|
this.credential = { ref, configured: false, writable: true };
|
|
1289
2130
|
this.store.set(this.projection());
|
|
1290
2131
|
}
|
|
1291
|
-
const response = await this.ctx.remote.credentials.describe([ref]);
|
|
1292
|
-
if (!response
|
|
2132
|
+
const response = await this.ctx.remote.credentials.describe([ref]).catch(() => void 0);
|
|
2133
|
+
if (!response?.ok || request !== this.credentialRequest || ref !== refOf(this.scope.getSnapshot())) return;
|
|
1293
2134
|
const view = response.value[ref];
|
|
1294
2135
|
const next = {
|
|
1295
2136
|
ref,
|
|
@@ -1311,6 +2152,7 @@ var OpencodeGoSectionController = class {
|
|
|
1311
2152
|
* @param ref - the reference the Host reports as changed.
|
|
1312
2153
|
*/
|
|
1313
2154
|
refreshCredential(ref) {
|
|
2155
|
+
this.accounts?.invalidate(ref);
|
|
1314
2156
|
if (ref !== this.credential.ref) return;
|
|
1315
2157
|
void this.readCredential();
|
|
1316
2158
|
}
|
|
@@ -1331,7 +2173,24 @@ var OpencodeGoSectionController = class {
|
|
|
1331
2173
|
setModelEnabled: (id3, next) => {
|
|
1332
2174
|
void this.setModelEnabled(id3, next);
|
|
1333
2175
|
},
|
|
1334
|
-
...this.form.actions()
|
|
2176
|
+
...this.form.actions(),
|
|
2177
|
+
...this.accounts.actions(),
|
|
2178
|
+
edit: (field, text) => {
|
|
2179
|
+
if (field === API_KEY_FIELD) {
|
|
2180
|
+
if (text.trim()) this.keyDraftRef ??= refOf(this.scope.getSnapshot());
|
|
2181
|
+
else this.keyDraftRef = void 0;
|
|
2182
|
+
}
|
|
2183
|
+
this.form.actions().edit(field, text);
|
|
2184
|
+
},
|
|
2185
|
+
discard: () => {
|
|
2186
|
+
this.keyDraftRef = void 0;
|
|
2187
|
+
this.form.actions().discard();
|
|
2188
|
+
},
|
|
2189
|
+
save: () => {
|
|
2190
|
+
if (!this.accounts?.snapshot().busy) void this.form.save().then(() => {
|
|
2191
|
+
if (!this.form.field(API_KEY_FIELD).text.trim()) this.keyDraftRef = void 0;
|
|
2192
|
+
});
|
|
2193
|
+
}
|
|
1335
2194
|
};
|
|
1336
2195
|
return this.face;
|
|
1337
2196
|
}
|
|
@@ -1341,9 +2200,12 @@ var OpencodeGoSectionController = class {
|
|
|
1341
2200
|
* @returns whether the Host reports a configured credential afterwards.
|
|
1342
2201
|
*/
|
|
1343
2202
|
async writeKey(value) {
|
|
1344
|
-
|
|
2203
|
+
const ref = this.keyDraftRef ?? refOf(this.scope.getSnapshot());
|
|
2204
|
+
const response = await this.ctx.remote.credentials.set(ref, value);
|
|
2205
|
+
if (!response.ok) return false;
|
|
2206
|
+
this.accounts?.invalidate(ref);
|
|
1345
2207
|
await this.readCredential();
|
|
1346
|
-
return this.credential.configured;
|
|
2208
|
+
return ref === this.credential.ref ? this.credential.configured : true;
|
|
1347
2209
|
}
|
|
1348
2210
|
};
|
|
1349
2211
|
function modelLimitsOf(value) {
|
|
@@ -1376,9 +2238,50 @@ function refOf(snapshot) {
|
|
|
1376
2238
|
|
|
1377
2239
|
// src/client/locales.ts
|
|
1378
2240
|
var en = {
|
|
2241
|
+
accountsTitle: "Accounts",
|
|
2242
|
+
accountsRefresh: "Refresh accounts",
|
|
2243
|
+
accountsBlocked: "Save or discard the API key draft before changing accounts.",
|
|
2244
|
+
accountsEmpty: "Add an account to use OpenCode Go.",
|
|
2245
|
+
accountsWriteFailed: "Could not apply the account change. Your input is kept; please retry.",
|
|
2246
|
+
accountsReadFailed: "Could not read account status. Please refresh.",
|
|
2247
|
+
accountsCleanupFailed: "The account entry was removed, but its stored key could not be deleted. Remove the unused reference through the host credential service.",
|
|
2248
|
+
accountsRemoveKeyFailed: "The stored key could not be deleted, so the account was kept. Please retry.",
|
|
2249
|
+
accountsStatusUnknown: "Status unknown",
|
|
2250
|
+
accountDefault: "Default account",
|
|
2251
|
+
accountAdd: "Add account",
|
|
2252
|
+
accountRename: "Rename",
|
|
2253
|
+
accountReplaceKey: "Replace key",
|
|
2254
|
+
accountRemove: "Remove account",
|
|
2255
|
+
accountRemoveHint: "Remove \u201C{name}\u201D? If it is selected, the next account becomes preferred. Keys added here are deleted from the credential service; existing external references are kept.",
|
|
2256
|
+
accountName: "Account name",
|
|
2257
|
+
accountKeyHint: "The key is saved through the host credential service and is never returned to this page.",
|
|
2258
|
+
accountConfirm: "Confirm",
|
|
2259
|
+
accountCancel: "Cancel",
|
|
2260
|
+
accountAutoSwitch: "Automatic fallback",
|
|
2261
|
+
accountAutoSwitchHint: "Off by default. On quota exhaustion or a rejected key, try the other accounts in order before any content or tool call is emitted. Each account is tried at most once. Your preferred account stays selected; ordinary rate limits and network failures use host recovery.",
|
|
2262
|
+
accountPreferredTag: "Preferred",
|
|
2263
|
+
accountSwitchAction: "Switch",
|
|
2264
|
+
accountSwitchTitle: "Switch account",
|
|
2265
|
+
accountSwitchBack: "Back to usage",
|
|
2266
|
+
accountSwitchHint: "Later requests in this profile use this account. The consumption order stays on the Settings page.",
|
|
2267
|
+
accountSwitchFailed: "Could not switch account. Please retry.",
|
|
2268
|
+
accountFallbackQuota: "The preferred account reached its quota; automatically used",
|
|
2269
|
+
accountFallbackCredential: "The preferred key was unavailable or rejected; automatically used",
|
|
2270
|
+
accountsSummary: "{count} accounts \xB7 Preferred {name}",
|
|
2271
|
+
accountsSummaryEmpty: "No accounts yet",
|
|
2272
|
+
accountsAvailability: "{ready}/{total} configured",
|
|
2273
|
+
accountsAvailabilityFailed: "{ready}/{total} configured \xB7 {failed} unreadable",
|
|
2274
|
+
accountsDetails: "Details for {name}",
|
|
2275
|
+
accountsDetailsHide: "Hide details for {name}",
|
|
2276
|
+
accountDragHandle: "Reorder {name}",
|
|
2277
|
+
accountConfigureHint: "Add a key to read usage",
|
|
2278
|
+
usageResetMinutes: "resets in {minutes} min",
|
|
2279
|
+
usageResetHours: "resets in {hours} h",
|
|
2280
|
+
usageResetDays: "resets in {days} d",
|
|
2281
|
+
usageResetDue: "resets now",
|
|
2282
|
+
usageResetUnknown: "reset time unknown",
|
|
1379
2283
|
usageTitle: "OpenCode Go usage",
|
|
1380
2284
|
usageRollingShort: "5h",
|
|
1381
|
-
usageHint: "Account usage \xB7 used percentage \xB7 refreshes every minute",
|
|
1382
2285
|
usageWeekShort: "week",
|
|
1383
2286
|
usage_rolling: "5 hours",
|
|
1384
2287
|
usage_weekly: "Weekly",
|
|
@@ -1388,6 +2291,7 @@ var en = {
|
|
|
1388
2291
|
usageLoading: "Loading usage\u2026",
|
|
1389
2292
|
usageUnavailable: "Unavailable",
|
|
1390
2293
|
usageStaleShort: "Last data",
|
|
2294
|
+
usageFallbackShort: "fallback",
|
|
1391
2295
|
usageStaleHint: "Showing the last successful usage reading. Current usage may have changed.",
|
|
1392
2296
|
usageRefreshFailed: "Refresh failed",
|
|
1393
2297
|
usageLastUpdated: "Last updated",
|
|
@@ -1477,6 +2381,9 @@ var en = {
|
|
|
1477
2381
|
apiKeyEnvHint: "The name the key is resolved from, addressed through the credentials service.",
|
|
1478
2382
|
baseURLLabel: "Gateway URL",
|
|
1479
2383
|
baseURLHint: "The endpoint that serves requests and the live model list.",
|
|
2384
|
+
proxyURLLabel: "Proxy address",
|
|
2385
|
+
proxyURLHint: "HTTP(S) or SOCKS5 proxy for conversations, model updates and usage. For example, socks5://127.0.0.1:1080. Leave blank to use the default network settings. The address is relative to the machine running DSH.",
|
|
2386
|
+
proxyURLInvalid: "Enter an http://, https:// or socks5:// proxy address without a path, query or fragment.",
|
|
1480
2387
|
refreshMinutesLabel: "Catalog refresh (minutes)",
|
|
1481
2388
|
refreshMinutesHint: "Catalog cache lifetime for conversations and model pickers. Opening this settings page or clicking Refresh checks the gateway and online model metadata immediately.",
|
|
1482
2389
|
streamIdleTimeoutMsLabel: "Stream idle timeout (ms)",
|
|
@@ -1500,9 +2407,50 @@ var en = {
|
|
|
1500
2407
|
unavailable: "The OpenCode Go settings are not served in this deployment."
|
|
1501
2408
|
};
|
|
1502
2409
|
var zh = {
|
|
2410
|
+
accountsTitle: "\u8D26\u53F7",
|
|
2411
|
+
accountsRefresh: "\u5237\u65B0\u989D\u5EA6",
|
|
2412
|
+
accountsBlocked: "\u8BF7\u5148\u4FDD\u5B58\u6216\u653E\u5F03 API Key \u8349\u7A3F\uFF0C\u518D\u5207\u6362\u6216\u4FEE\u6539\u8D26\u53F7\u3002",
|
|
2413
|
+
accountsEmpty: "\u6DFB\u52A0\u8D26\u53F7\u540E\u5373\u53EF\u4F7F\u7528 OpenCode Go\u3002",
|
|
2414
|
+
accountsWriteFailed: "\u8D26\u53F7\u4FEE\u6539\u672A\u751F\u6548\uFF0C\u8F93\u5165\u5DF2\u4FDD\u7559\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
2415
|
+
accountsReadFailed: "\u672A\u80FD\u8BFB\u53D6\u8D26\u53F7\u72B6\u6001\uFF0C\u8BF7\u5237\u65B0\u91CD\u8BD5\u3002",
|
|
2416
|
+
accountsCleanupFailed: "\u8D26\u53F7\u6761\u76EE\u5DF2\u79FB\u9664\uFF0C\u4F46\u4FDD\u5B58\u7684 Key \u672A\u80FD\u5220\u9664\u3002\u8BF7\u901A\u8FC7\u5BBF\u4E3B\u51ED\u636E\u670D\u52A1\u5220\u9664\u672A\u4F7F\u7528\u7684\u5F15\u7528\u3002",
|
|
2417
|
+
accountsRemoveKeyFailed: "\u672A\u80FD\u5220\u9664\u5DF2\u4FDD\u5B58\u7684 Key\uFF0C\u8D26\u53F7\u6682\u65F6\u4FDD\u7559\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
2418
|
+
accountsStatusUnknown: "\u72B6\u6001\u672A\u77E5",
|
|
2419
|
+
accountDefault: "\u9ED8\u8BA4\u8D26\u53F7",
|
|
2420
|
+
accountAdd: "\u6DFB\u52A0\u8D26\u53F7",
|
|
2421
|
+
accountRename: "\u91CD\u547D\u540D",
|
|
2422
|
+
accountReplaceKey: "\u66FF\u6362 Key",
|
|
2423
|
+
accountRemove: "\u5220\u9664\u8D26\u53F7",
|
|
2424
|
+
accountRemoveHint: "\u5220\u9664\u201C{name}\u201D\uFF1F\u82E5\u5B83\u662F\u5F53\u524D\u9996\u9009\uFF0C\u5C06\u4F7F\u7528\u4E0B\u4E00\u4E2A\u8D26\u53F7\u3002\u5728\u8FD9\u91CC\u6DFB\u52A0\u7684 Key \u4F1A\u4ECE\u51ED\u636E\u670D\u52A1\u5220\u9664\uFF1B\u5DF2\u6709\u5916\u90E8\u5F15\u7528\u4F1A\u4FDD\u7559\u3002",
|
|
2425
|
+
accountName: "\u8D26\u53F7\u540D\u79F0",
|
|
2426
|
+
accountKeyHint: "Key \u901A\u8FC7\u5BBF\u4E3B\u51ED\u636E\u670D\u52A1\u4FDD\u5B58\uFF0C\u9875\u9762\u4E0D\u4F1A\u56DE\u663E\u5DF2\u4FDD\u5B58\u7684\u5BC6\u94A5\u3002",
|
|
2427
|
+
accountConfirm: "\u786E\u8BA4",
|
|
2428
|
+
accountCancel: "\u53D6\u6D88",
|
|
2429
|
+
accountAutoSwitch: "\u81EA\u52A8\u4F7F\u7528\u5907\u7528\u8D26\u53F7",
|
|
2430
|
+
accountAutoSwitchHint: "\u9ED8\u8BA4\u5173\u95ED\u3002\u989D\u5EA6\u8017\u5C3D\u6216 Key \u4E0D\u53EF\u7528\u65F6\uFF0C\u5728\u5C1A\u672A\u8F93\u51FA\u5185\u5BB9\u6216\u5DE5\u5177\u8C03\u7528\u524D\u6309\u987A\u5E8F\u5C1D\u8BD5\u5176\u4ED6\u8D26\u53F7\uFF0C\u6BCF\u4E2A\u8D26\u53F7\u6700\u591A\u4E00\u6B21\u3002\u624B\u52A8\u9009\u5B9A\u7684\u9996\u9009\u8D26\u53F7\u4FDD\u6301\u4E0D\u53D8\uFF1B\u666E\u901A\u9650\u6D41\u548C\u7F51\u7EDC\u9519\u8BEF\u4EA4\u7531\u5BBF\u4E3B\u6062\u590D\u3002",
|
|
2431
|
+
accountPreferredTag: "\u9996\u9009",
|
|
2432
|
+
accountSwitchAction: "\u5207\u6362",
|
|
2433
|
+
accountSwitchTitle: "\u5207\u6362\u8D26\u53F7",
|
|
2434
|
+
accountSwitchBack: "\u8FD4\u56DE\u989D\u5EA6",
|
|
2435
|
+
accountSwitchHint: "\u5207\u6362\u540E\uFF0C\u672C profile \u7684\u540E\u7EED\u8BF7\u6C42\u4F7F\u7528\u8BE5\u8D26\u53F7\uFF1B\u989D\u5EA6\u6D88\u8017\u987A\u5E8F\u5728\u8BBE\u7F6E\u9875\u8C03\u6574\u3002",
|
|
2436
|
+
accountSwitchFailed: "\u8D26\u53F7\u5207\u6362\u672A\u751F\u6548\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
2437
|
+
accountFallbackQuota: "\u9996\u9009\u8D26\u53F7\u989D\u5EA6\u8017\u5C3D\uFF0C\u5DF2\u81EA\u52A8\u4F7F\u7528\u5907\u7528\u8D26\u53F7\uFF1A",
|
|
2438
|
+
accountFallbackCredential: "\u9996\u9009 Key \u4E0D\u53EF\u7528\u6216\u88AB\u62D2\u7EDD\uFF0C\u5DF2\u81EA\u52A8\u4F7F\u7528\u5907\u7528\u8D26\u53F7\uFF1A",
|
|
2439
|
+
accountsSummary: "{count} \u4E2A \xB7 \u9996\u9009 {name}",
|
|
2440
|
+
accountsSummaryEmpty: "\u5C1A\u672A\u6DFB\u52A0\u8D26\u53F7",
|
|
2441
|
+
accountsAvailability: "{ready}/{total} \u5DF2\u914D\u7F6E",
|
|
2442
|
+
accountsAvailabilityFailed: "{ready}/{total} \u5DF2\u914D\u7F6E \xB7 {failed} \u4E2A\u8BFB\u53D6\u5931\u8D25",
|
|
2443
|
+
accountsDetails: "{name} \u7684\u8BE6\u60C5",
|
|
2444
|
+
accountsDetailsHide: "\u6536\u8D77 {name} \u7684\u8BE6\u60C5",
|
|
2445
|
+
accountDragHandle: "\u62D6\u52A8 {name} \u8C03\u6574\u987A\u5E8F",
|
|
2446
|
+
accountConfigureHint: "\u914D\u7F6E Key \u540E\u663E\u793A\u989D\u5EA6",
|
|
2447
|
+
usageResetMinutes: "{minutes} \u5206\u949F\u540E\u91CD\u7F6E",
|
|
2448
|
+
usageResetHours: "{hours} \u5C0F\u65F6\u540E\u91CD\u7F6E",
|
|
2449
|
+
usageResetDays: "{days} \u5929\u540E\u91CD\u7F6E",
|
|
2450
|
+
usageResetDue: "\u5373\u5C06\u91CD\u7F6E",
|
|
2451
|
+
usageResetUnknown: "\u91CD\u7F6E\u65F6\u95F4\u672A\u77E5",
|
|
1503
2452
|
usageTitle: "OpenCode Go \u7528\u91CF",
|
|
1504
2453
|
usageRollingShort: "5\u5C0F\u65F6",
|
|
1505
|
-
usageHint: "\u8D26\u53F7\u989D\u5EA6 \xB7 \u5DF2\u7528\u767E\u5206\u6BD4 \xB7 \u6BCF\u5206\u949F\u5237\u65B0",
|
|
1506
2454
|
usageWeekShort: "\u5468",
|
|
1507
2455
|
usage_rolling: "5 \u5C0F\u65F6",
|
|
1508
2456
|
usage_weekly: "\u6BCF\u5468",
|
|
@@ -1512,6 +2460,7 @@ var zh = {
|
|
|
1512
2460
|
usageLoading: "\u6B63\u5728\u8BFB\u53D6\u7528\u91CF\u2026",
|
|
1513
2461
|
usageUnavailable: "\u6682\u4E0D\u53EF\u7528",
|
|
1514
2462
|
usageStaleShort: "\u4E0A\u6B21\u6570\u636E",
|
|
2463
|
+
usageFallbackShort: "\u5DF2\u56DE\u9000",
|
|
1515
2464
|
usageStaleHint: "\u5F53\u524D\u663E\u793A\u4E0A\u6B21\u6210\u529F\u8BFB\u53D6\u7684\u7528\u91CF\uFF0C\u5B9E\u9645\u7528\u91CF\u53EF\u80FD\u5DF2\u53D8\u5316\u3002",
|
|
1516
2465
|
usageRefreshFailed: "\u5237\u65B0\u5931\u8D25",
|
|
1517
2466
|
usageLastUpdated: "\u66F4\u65B0\u4E8E",
|
|
@@ -1601,6 +2550,9 @@ var zh = {
|
|
|
1601
2550
|
apiKeyEnvHint: "key \u89E3\u6790\u6240\u4F9D\u636E\u7684\u5F15\u7528\u540D\uFF0C\u7ECF\u51ED\u8BC1\u670D\u52A1\u5BFB\u5740\u3002",
|
|
1602
2551
|
baseURLLabel: "\u7F51\u5173\u5730\u5740",
|
|
1603
2552
|
baseURLHint: "\u540C\u65F6\u63D0\u4F9B\u6A21\u578B\u8BF7\u6C42\u4E0E\u5B9E\u65F6\u6A21\u578B\u5217\u8868\u7684\u7AEF\u70B9\u3002",
|
|
2553
|
+
proxyURLLabel: "\u4EE3\u7406\u5730\u5740",
|
|
2554
|
+
proxyURLHint: "\u5BF9\u8BDD\u3001\u6A21\u578B\u66F4\u65B0\u548C\u7528\u91CF\u67E5\u8BE2\u4F7F\u7528\u7684 HTTP(S) \u6216 SOCKS5 \u4EE3\u7406\uFF0C\u4F8B\u5982 socks5://127.0.0.1:1080\u3002\u7559\u7A7A\u4F7F\u7528\u9ED8\u8BA4\u7F51\u7EDC\u8BBE\u7F6E\u3002\u5730\u5740\u4EE5\u8FD0\u884C DSH \u7684\u673A\u5668\u4E3A\u51C6\u3002",
|
|
2555
|
+
proxyURLInvalid: "\u8BF7\u8F93\u5165 http://\u3001https:// \u6216 socks5:// \u4EE3\u7406\u5730\u5740\uFF0C\u4E0D\u5305\u542B\u8DEF\u5F84\u3001\u67E5\u8BE2\u53C2\u6570\u6216\u7247\u6BB5\u3002",
|
|
1604
2556
|
refreshMinutesLabel: "\u76EE\u5F55\u5237\u65B0\uFF08\u5206\u949F\uFF09",
|
|
1605
2557
|
refreshMinutesHint: "\u4F1A\u8BDD\u8BF7\u6C42\u548C\u6A21\u578B\u9009\u62E9\u5668\u7684\u76EE\u5F55\u7F13\u5B58\u65F6\u957F\u3002\u6253\u5F00\u672C\u8BBE\u7F6E\u9875\u6216\u70B9\u51FB\u5237\u65B0\u65F6\uFF0C\u4F1A\u7ACB\u5373\u6838\u5BF9\u7F51\u5173\u4E0E\u5728\u7EBF\u6A21\u578B\u914D\u7F6E\u3002",
|
|
1606
2558
|
streamIdleTimeoutMsLabel: "\u6D41\u7A7A\u95F2\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
@@ -1625,6 +2577,11 @@ var zh = {
|
|
|
1625
2577
|
};
|
|
1626
2578
|
|
|
1627
2579
|
// src/usage-contract.ts
|
|
2580
|
+
function parseAccountSwitch(value) {
|
|
2581
|
+
const notice = value;
|
|
2582
|
+
if (!notice || typeof notice.fromRef !== "string" || typeof notice.toRef !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(notice.fromRef) || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(notice.toRef) || notice.reason !== "quota" && notice.reason !== "credential" || typeof notice.at !== "number" || !Number.isSafeInteger(notice.at) || notice.at < 0 || notice.at > 864e13) throw new Error("Invalid account switch notice");
|
|
2583
|
+
return { fromRef: notice.fromRef, toRef: notice.toRef, reason: notice.reason, at: notice.at };
|
|
2584
|
+
}
|
|
1628
2585
|
function parseGoUsage(value) {
|
|
1629
2586
|
if (!value || typeof value !== "object") throw new Error("Invalid OpenCode Go usage response");
|
|
1630
2587
|
const source = value;
|
|
@@ -1635,6 +2592,9 @@ function parseGoUsage(value) {
|
|
|
1635
2592
|
}
|
|
1636
2593
|
result.source = source.source;
|
|
1637
2594
|
}
|
|
2595
|
+
if (source.lastSwitch !== void 0) {
|
|
2596
|
+
result.lastSwitch = parseAccountSwitch(source.lastSwitch);
|
|
2597
|
+
}
|
|
1638
2598
|
for (const key of ["rolling", "weekly", "monthly"]) {
|
|
1639
2599
|
const row = source[key];
|
|
1640
2600
|
if (!row || row.status !== "ok" && row.status !== "rate-limited" || typeof row.percent !== "number" || !Number.isFinite(row.percent) || row.percent < 0 || typeof row.resetsAt !== "string" || !Number.isFinite(Date.parse(row.resetsAt))) {
|
|
@@ -1650,6 +2610,16 @@ var usageCodec = {
|
|
|
1650
2610
|
schema: { parse: parseGoUsage },
|
|
1651
2611
|
create: () => ({ parse: parseGoUsage })
|
|
1652
2612
|
};
|
|
2613
|
+
var parseRef = (value) => {
|
|
2614
|
+
if (typeof value !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) throw new Error("Invalid account reference");
|
|
2615
|
+
return value;
|
|
2616
|
+
};
|
|
2617
|
+
var refCodec = {
|
|
2618
|
+
mode: "strict",
|
|
2619
|
+
typeSymbol: "dsh-opencode-go#AccountRef",
|
|
2620
|
+
schema: { parse: parseRef },
|
|
2621
|
+
create: () => ({ parse: parseRef })
|
|
2622
|
+
};
|
|
1653
2623
|
var usageRemote = {
|
|
1654
2624
|
package: "dsh-opencode-go",
|
|
1655
2625
|
descriptors: [{
|
|
@@ -1660,6 +2630,14 @@ var usageRemote = {
|
|
|
1660
2630
|
invocation: { kind: "direct" },
|
|
1661
2631
|
parameters: [],
|
|
1662
2632
|
result: usageCodec
|
|
2633
|
+
}, {
|
|
2634
|
+
id: "dsh-opencode-go#opencodeGoUsage/readAccount",
|
|
2635
|
+
service: "opencodeGoUsage",
|
|
2636
|
+
namespace: "opencodeGoUsage",
|
|
2637
|
+
method: "readAccount",
|
|
2638
|
+
invocation: { kind: "direct" },
|
|
2639
|
+
parameters: [{ name: "ref", wire: "ref", source: "json", codec: refCodec }],
|
|
2640
|
+
result: usageCodec
|
|
1663
2641
|
}]
|
|
1664
2642
|
};
|
|
1665
2643
|
|
|
@@ -1670,7 +2648,7 @@ var goRemote = {
|
|
|
1670
2648
|
};
|
|
1671
2649
|
|
|
1672
2650
|
// src/client/UsagePill.tsx
|
|
1673
|
-
var
|
|
2651
|
+
var import_react4 = require("react");
|
|
1674
2652
|
|
|
1675
2653
|
// plugin-css:src/client/UsagePill.module.css
|
|
1676
2654
|
var id2 = "dsh-opencode-go/UsagePill.module.css";
|
|
@@ -1678,20 +2656,29 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
|
|
|
1678
2656
|
const style = document.createElement("style");
|
|
1679
2657
|
style.dataset.plugin = "dsh-opencode-go";
|
|
1680
2658
|
style.dataset.pluginCss = id2;
|
|
1681
|
-
style.textContent =
|
|
2659
|
+
style.textContent = '.mAjYhq_root{min-width:0;display:inline-flex;position:relative}.mAjYhq_trigger{color:inherit;opacity:.75;font:inherit;cursor:pointer;white-space:nowrap;background:0 0;border:0;border-radius:6px;padding:4px 6px;font-size:12px}.mAjYhq_trigger:hover,.mAjYhq_trigger:focus-visible{opacity:1;background:color-mix(in srgb, currentColor 8%, transparent)}.mAjYhq_account{text-overflow:ellipsis;vertical-align:bottom;max-width:12ch;display:inline-block;overflow:hidden}@container (width<=460px){.mAjYhq_brand,.mAjYhq_stale,.mAjYhq_account,.mAjYhq_fallback{display:none}.mAjYhq_reading[data-stale]:after{content:"*"}.mAjYhq_trigger[data-fallback]:after{content:" \u21B3"}}@container (width<=360px){.mAjYhq_unit{display:none}}.mAjYhq_panel{z-index:100;box-sizing:border-box;border-radius:var(--dsw-radius-lg,16px);width:320px;max-width:calc(100vw - 32px);max-height:70vh;color:var(--dsw-alias-label-primary,CanvasText);isolation:isolate;--dsw-elevation-stroke-color:var(--dsw-alias-border-l1,color-mix(in srgb, currentColor 10%, transparent));box-shadow:var(--dsw-elevation-prominent,0 8px 30px #0003);border:0;flex-direction:column;font-size:12px;display:flex;position:absolute;bottom:calc(100% + 12px);right:0}.mAjYhq_material{z-index:-1;border-radius:inherit;pointer-events:none;background:var(--dsw-menu-surface-fill,var(--dsw-specific-menu,#43454a73));backdrop-filter:var(--dsw-menu-backdrop-filter,blur(40px) saturate(150%));position:absolute;inset:0}@supports not (backdrop-filter:blur(1px)){.mAjYhq_material{background:var(--dsw-alias-bg-layer-2,Canvas)}}.mAjYhq_body{overscroll-behavior:contain;box-sizing:border-box;flex-direction:column;flex:1;gap:6px;min-height:0;padding:10px;display:flex;overflow-y:auto}.mAjYhq_panelTitle,.mAjYhq_panelHead{color:var(--dsw-alias-label-tertiary,currentColor);flex:none;padding:2px 6px 0;font-size:11.5px;line-height:1.6}.mAjYhq_panelHead{align-items:center;gap:6px;display:flex}.mAjYhq_panelHead strong{color:var(--dsw-alias-label-primary,CanvasText);font-size:12px;font-weight:600}.mAjYhq_back{width:18px;height:18px;color:inherit;cursor:pointer;background:0 0;border:0;border-radius:5px;place-items:center;padding:0;display:grid}.mAjYhq_back:hover{background:color-mix(in srgb, currentColor 8%, transparent)}.mAjYhq_icon{flex:none;width:14px;height:14px}.mAjYhq_tick{color:#39a878;flex:none;width:14px;height:14px}.mAjYhq_tile{background:color-mix(in srgb, currentColor 6%, transparent);border-radius:10px;flex:none;overflow:hidden}.mAjYhq_divider{background:color-mix(in srgb, currentColor 10%, transparent);height:.5px;margin:0 12px}.mAjYhq_accHead{align-items:center;gap:8px;min-height:42px;padding:0 12px;display:flex}.mAjYhq_dot{background:#39a878;border-radius:50%;flex:none;width:7px;height:7px}.mAjYhq_accName{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13.5px;font-weight:600;overflow:hidden}.mAjYhq_tag{color:#39a878;background:#39a8781f;border:.5px solid #39a87873;border-radius:999px;flex:none;padding:0 7px;font-size:10.5px;line-height:1.7}.mAjYhq_switch{font:inherit;color:var(--dsw-alias-label-tertiary,currentColor);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;align-items:center;gap:3px;padding:3px 6px;font-size:11.5px;display:inline-flex}.mAjYhq_switch:hover:not(:disabled){background:color-mix(in srgb, currentColor 8%, transparent)}.mAjYhq_switch:disabled{opacity:.55;cursor:default}.mAjYhq_option{width:100%;min-height:38px;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:8px;padding:0 12px;display:flex}.mAjYhq_option:hover:not(:disabled){background:color-mix(in srgb, currentColor 6%, transparent)}.mAjYhq_option:disabled{opacity:.6;cursor:default}.mAjYhq_optionName{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary,currentColor);flex:1;font-size:13px;overflow:hidden}.mAjYhq_option[data-selected] .mAjYhq_optionName{color:var(--dsw-alias-label-primary,CanvasText);font-weight:600}.mAjYhq_hint{opacity:.65;font-size:11px;line-height:1.6}.mAjYhq_warning{background:color-mix(in srgb, currentColor 6%, transparent);overflow-wrap:anywhere;border-radius:6px;margin:10px 0;padding:10px;line-height:1.5}.mAjYhq_warning p{margin:5px 0 0}.mAjYhq_retry{border:1px solid color-mix(in srgb, currentColor 25%, transparent);color:inherit;font:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:5px 9px}.mAjYhq_retry:disabled{opacity:.6;cursor:default}.mAjYhq_back:focus-visible,.mAjYhq_switch:focus-visible,.mAjYhq_option:focus-visible,.mAjYhq_retry:focus-visible{outline-offset:2px;outline:2px solid}.mAjYhq_window{padding:10px 12px}.mAjYhq_windowRow{align-items:center;gap:10px;display:flex}.mAjYhq_windowLabel{width:48px;color:var(--dsw-alias-label-secondary,currentColor);flex:none;font-size:12.5px}.mAjYhq_windowPercent{text-align:right;font-variant-numeric:tabular-nums;flex:none;width:38px;font-size:13px;font-weight:650}.mAjYhq_window progress{appearance:none;background:color-mix(in srgb, currentColor 15%, transparent);border:0;border-radius:99px;flex:1;min-width:60px;height:10px;display:block}.mAjYhq_window progress::-webkit-progress-bar{background:0 0;border-radius:99px}.mAjYhq_window progress::-webkit-progress-value{background:#39a878;border-radius:99px}.mAjYhq_window progress::-moz-progress-bar{background:#39a878;border-radius:99px}.mAjYhq_windowReset{color:var(--dsw-alias-label-tertiary,currentColor);margin-top:6px;font-size:11px;line-height:1.6}.mAjYhq_foot{color:var(--dsw-alias-label-tertiary,currentColor);justify-content:space-between;align-items:center;gap:8px;padding:3px 6px 1px;font-size:11px;display:flex}.mAjYhq_window progress.mAjYhq_high::-webkit-progress-value{background:#e0a100}.mAjYhq_window progress.mAjYhq_high::-moz-progress-bar{background:#e0a100}.mAjYhq_window progress.mAjYhq_limited::-webkit-progress-value{background:#e5484d}.mAjYhq_window progress.mAjYhq_limited::-moz-progress-bar{background:#e5484d}.mAjYhq_limitedText{color:#e5484d;margin-top:2px;font-weight:600}';
|
|
1682
2660
|
document.head.appendChild(style);
|
|
1683
2661
|
}
|
|
1684
|
-
var UsagePill_default = { "high": "mAjYhq_high", "hint": "mAjYhq_hint", "limited": "mAjYhq_limited", "limitedText": "mAjYhq_limitedText", "panel": "mAjYhq_panel", "retry": "mAjYhq_retry", "root": "mAjYhq_root", "
|
|
2662
|
+
var UsagePill_default = { "accHead": "mAjYhq_accHead", "accName": "mAjYhq_accName", "account": "mAjYhq_account", "back": "mAjYhq_back", "body": "mAjYhq_body", "brand": "mAjYhq_brand", "divider": "mAjYhq_divider", "dot": "mAjYhq_dot", "fallback": "mAjYhq_fallback", "foot": "mAjYhq_foot", "high": "mAjYhq_high", "hint": "mAjYhq_hint", "icon": "mAjYhq_icon", "limited": "mAjYhq_limited", "limitedText": "mAjYhq_limitedText", "material": "mAjYhq_material", "option": "mAjYhq_option", "optionName": "mAjYhq_optionName", "panel": "mAjYhq_panel", "panelHead": "mAjYhq_panelHead", "panelTitle": "mAjYhq_panelTitle", "reading": "mAjYhq_reading", "retry": "mAjYhq_retry", "root": "mAjYhq_root", "stale": "mAjYhq_stale", "switch": "mAjYhq_switch", "tag": "mAjYhq_tag", "tick": "mAjYhq_tick", "tile": "mAjYhq_tile", "trigger": "mAjYhq_trigger", "unit": "mAjYhq_unit", "warning": "mAjYhq_warning", "window": "mAjYhq_window", "windowLabel": "mAjYhq_windowLabel", "windowPercent": "mAjYhq_windowPercent", "windowReset": "mAjYhq_windowReset", "windowRow": "mAjYhq_windowRow" };
|
|
1685
2663
|
|
|
1686
2664
|
// src/client/UsagePill.tsx
|
|
1687
|
-
var
|
|
2665
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2666
|
+
var unchanged = () => 0;
|
|
2667
|
+
var noSubscription = () => () => {
|
|
2668
|
+
};
|
|
1688
2669
|
function usageFailure(error) {
|
|
1689
2670
|
if (error && typeof error === "object" && "code" in error && error.code === "opencode-go/usage-unavailable" && "details" in error && error.details && typeof error.details === "object") {
|
|
1690
2671
|
const details = error.details;
|
|
2672
|
+
let lastSwitch;
|
|
2673
|
+
try {
|
|
2674
|
+
if (details.lastSwitch) lastSwitch = parseAccountSwitch(details.lastSwitch);
|
|
2675
|
+
} catch {
|
|
2676
|
+
}
|
|
1691
2677
|
return {
|
|
1692
2678
|
..."message" in error && typeof error.message === "string" ? { message: error.message } : {},
|
|
1693
2679
|
retainPrevious: details.retryable === true && details.retainPrevious === true,
|
|
1694
|
-
...typeof details.source === "string" ? { source: details.source } : {}
|
|
2680
|
+
...typeof details.source === "string" ? { source: details.source } : {},
|
|
2681
|
+
...lastSwitch ? { lastSwitch } : {}
|
|
1695
2682
|
};
|
|
1696
2683
|
}
|
|
1697
2684
|
return { retainPrevious: false };
|
|
@@ -1700,24 +2687,50 @@ function usageLevel(window) {
|
|
|
1700
2687
|
if (window.status === "rate-limited" || window.percent >= 100) return UsagePill_default.limited;
|
|
1701
2688
|
return window.percent >= 80 ? UsagePill_default.high : void 0;
|
|
1702
2689
|
}
|
|
1703
|
-
function
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
2690
|
+
function ChevronRight() {
|
|
2691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: UsagePill_default.icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M6 4l4 4-4 4" }) });
|
|
2692
|
+
}
|
|
2693
|
+
function ChevronLeft() {
|
|
2694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: UsagePill_default.icon, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M10 4 6 8l4 4" }) });
|
|
2695
|
+
}
|
|
2696
|
+
function Tick() {
|
|
2697
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: UsagePill_default.tick, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M3.5 8.5 6.5 11.5 12.5 4.5" }) });
|
|
2698
|
+
}
|
|
2699
|
+
function UsagePill({ directory, settings, credentialChanges, ...props }) {
|
|
2700
|
+
const state = (0, import_react4.useSyncExternalStore)(directory.subscribe, directory.getSnapshot, directory.getSnapshot);
|
|
2701
|
+
const readSettings = (0, import_react4.useCallback)(() => settings.getSnapshot(), [settings]);
|
|
2702
|
+
const subscribeSettings = (0, import_react4.useCallback)((listener) => settings.subscribe(listener), [settings]);
|
|
2703
|
+
const config = (0, import_react4.useSyncExternalStore)(subscribeSettings, readSettings, readSettings);
|
|
2704
|
+
const readChanges = (0, import_react4.useCallback)(() => credentialChanges?.getSnapshot() ?? unchanged(), [credentialChanges]);
|
|
2705
|
+
const subscribeChanges = (0, import_react4.useCallback)((listener) => credentialChanges?.subscribe(listener) ?? noSubscription(), [credentialChanges]);
|
|
2706
|
+
const credentialRevision = (0, import_react4.useSyncExternalStore)(subscribeChanges, readChanges, readChanges);
|
|
1708
2707
|
const mode = config.value?.usageDisplay ?? DEFAULT_USAGE_DISPLAY;
|
|
1709
2708
|
const visible = config.status === "ready" && config.value?.enabled !== false && (mode === "always" || mode === "auto" && state.current?.provider === PROVIDER_ID);
|
|
1710
|
-
|
|
2709
|
+
const accounts = accountsOf(config.value ?? {});
|
|
2710
|
+
const activeRef = accountRefOf(config.value ?? {});
|
|
2711
|
+
return visible ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2712
|
+
ActiveUsage,
|
|
2713
|
+
{
|
|
2714
|
+
...props,
|
|
2715
|
+
accounts,
|
|
2716
|
+
activeRef,
|
|
2717
|
+
writable: config.writable
|
|
2718
|
+
},
|
|
2719
|
+
JSON.stringify([activeRef, config.value?.baseURL, config.value?.proxyURL, credentialRevision, accounts])
|
|
2720
|
+
) : null;
|
|
1711
2721
|
}
|
|
1712
|
-
function ActiveUsage({ readUsage, t, getLocale }) {
|
|
1713
|
-
const [snapshot, setSnapshot] = (0,
|
|
1714
|
-
const [failed, setFailed] = (0,
|
|
1715
|
-
const [refreshing, setRefreshing] = (0,
|
|
1716
|
-
const [open, setOpen] = (0,
|
|
1717
|
-
const
|
|
1718
|
-
const
|
|
2722
|
+
function ActiveUsage({ readUsage, t, getLocale, accounts, activeRef, writable, selectAccount }) {
|
|
2723
|
+
const [snapshot, setSnapshot] = (0, import_react4.useState)(null);
|
|
2724
|
+
const [failed, setFailed] = (0, import_react4.useState)(null);
|
|
2725
|
+
const [refreshing, setRefreshing] = (0, import_react4.useState)(false);
|
|
2726
|
+
const [open, setOpen] = (0, import_react4.useState)(false);
|
|
2727
|
+
const [switching, setSwitching] = (0, import_react4.useState)(false);
|
|
2728
|
+
const [switchFailed, setSwitchFailed] = (0, import_react4.useState)(false);
|
|
2729
|
+
const [view, setView] = (0, import_react4.useState)("usage");
|
|
2730
|
+
const root = (0, import_react4.useRef)(null);
|
|
2731
|
+
const retry = (0, import_react4.useRef)(() => {
|
|
1719
2732
|
});
|
|
1720
|
-
(0,
|
|
2733
|
+
(0, import_react4.useEffect)(() => {
|
|
1721
2734
|
let alive = true;
|
|
1722
2735
|
let busy = false;
|
|
1723
2736
|
setSnapshot(null);
|
|
@@ -1763,7 +2776,7 @@ function ActiveUsage({ readUsage, t, getLocale }) {
|
|
|
1763
2776
|
document.removeEventListener("visibilitychange", visible);
|
|
1764
2777
|
};
|
|
1765
2778
|
}, [readUsage]);
|
|
1766
|
-
(0,
|
|
2779
|
+
(0, import_react4.useEffect)(() => {
|
|
1767
2780
|
if (!open) return;
|
|
1768
2781
|
const click = (event) => {
|
|
1769
2782
|
if (!root.current?.contains(event.target)) setOpen(false);
|
|
@@ -1781,71 +2794,227 @@ function ActiveUsage({ readUsage, t, getLocale }) {
|
|
|
1781
2794
|
const current = snapshot?.reader === readUsage ? snapshot : null;
|
|
1782
2795
|
const usage = current?.usage;
|
|
1783
2796
|
const failure = failed?.reader === readUsage ? failed.failure : null;
|
|
1784
|
-
const
|
|
1785
|
-
|
|
1786
|
-
|
|
2797
|
+
const notice = usage?.lastSwitch ?? failure?.lastSwitch;
|
|
2798
|
+
const accountName = accounts.find((account) => account.apiKeyEnv === activeRef)?.name || t("accountDefault");
|
|
2799
|
+
const accountsView = view === "accounts" && accounts.length > 1;
|
|
2800
|
+
const switchable = accounts.length > 1 && writable && selectAccount !== void 0;
|
|
2801
|
+
const switchTo = (ref) => {
|
|
2802
|
+
if (ref === activeRef) {
|
|
2803
|
+
setView("usage");
|
|
2804
|
+
return;
|
|
2805
|
+
}
|
|
2806
|
+
setSwitching(true);
|
|
2807
|
+
setSwitchFailed(false);
|
|
2808
|
+
void selectAccount?.(ref).then((accepted) => {
|
|
2809
|
+
setSwitchFailed(!accepted);
|
|
2810
|
+
if (accepted) setView("usage");
|
|
2811
|
+
}).catch(() => {
|
|
2812
|
+
setSwitchFailed(true);
|
|
2813
|
+
}).finally(() => {
|
|
2814
|
+
setSwitching(false);
|
|
2815
|
+
});
|
|
2816
|
+
};
|
|
2817
|
+
const label = usage ? `Go \xB7 ${t("usageRollingShort")} ${usage.rolling.percent}% \xB7 ${t("usageWeekShort")} ${usage.weekly.percent}%${failure ? ` \xB7 ${t("usageStaleShort")}` : ""}${notice ? ` \xB7 ${t("usageFallbackShort")}` : ""}${accounts.length > 1 ? ` \xB7 ${accountName}` : ""}` : `Go \xB7 ${failure ? t("usageUnavailable") : "\u2026"}${notice ? ` \xB7 ${t("usageFallbackShort")}` : ""}${accounts.length > 1 ? ` \xB7 ${accountName}` : ""}`;
|
|
2818
|
+
const segments = usage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2819
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.brand, children: "Go \xB7 " }),
|
|
2820
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.reading, "data-stale": failure ? "" : void 0, children: [
|
|
2821
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.unit, children: [
|
|
2822
|
+
t("usageRollingShort"),
|
|
2823
|
+
" "
|
|
2824
|
+
] }),
|
|
2825
|
+
usage.rolling.percent,
|
|
2826
|
+
"%",
|
|
2827
|
+
" \xB7 ",
|
|
2828
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.unit, children: [
|
|
2829
|
+
t("usageWeekShort"),
|
|
2830
|
+
" "
|
|
2831
|
+
] }),
|
|
2832
|
+
usage.weekly.percent,
|
|
2833
|
+
"%"
|
|
2834
|
+
] }),
|
|
2835
|
+
failure ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.stale, children: [
|
|
2836
|
+
" \xB7 ",
|
|
2837
|
+
t("usageStaleShort")
|
|
2838
|
+
] }) : null,
|
|
2839
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.fallback, children: [
|
|
2840
|
+
" \xB7 ",
|
|
2841
|
+
t("usageFallbackShort")
|
|
2842
|
+
] }) : null,
|
|
2843
|
+
accounts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.account, children: [
|
|
2844
|
+
" \xB7 ",
|
|
2845
|
+
accountName
|
|
2846
|
+
] }) : null
|
|
2847
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2848
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.brand, children: "Go \xB7 " }),
|
|
2849
|
+
failure ? t("usageUnavailable") : "\u2026",
|
|
2850
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.fallback, children: [
|
|
2851
|
+
" \xB7 ",
|
|
2852
|
+
t("usageFallbackShort")
|
|
2853
|
+
] }) : null,
|
|
2854
|
+
accounts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.account, children: [
|
|
2855
|
+
" \xB7 ",
|
|
2856
|
+
accountName
|
|
2857
|
+
] }) : null
|
|
2858
|
+
] });
|
|
2859
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.root, ref: root, children: [
|
|
2860
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1787
2861
|
"button",
|
|
1788
2862
|
{
|
|
1789
2863
|
type: "button",
|
|
1790
2864
|
className: UsagePill_default.trigger,
|
|
1791
2865
|
"aria-expanded": open,
|
|
1792
2866
|
"aria-haspopup": "dialog",
|
|
2867
|
+
"data-fallback": notice ? "" : void 0,
|
|
1793
2868
|
"aria-label": `${t("usageTitle")}: ${label}`,
|
|
2869
|
+
title: label,
|
|
1794
2870
|
onClick: () => {
|
|
1795
2871
|
setOpen(!open);
|
|
2872
|
+
setView("usage");
|
|
1796
2873
|
},
|
|
1797
|
-
children:
|
|
2874
|
+
children: segments
|
|
1798
2875
|
}
|
|
1799
2876
|
),
|
|
1800
|
-
open && /* @__PURE__ */ (0,
|
|
1801
|
-
/* @__PURE__ */ (0,
|
|
1802
|
-
/* @__PURE__ */ (0,
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
failure ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1809
|
-
"button",
|
|
1810
|
-
{
|
|
1811
|
-
type: "button",
|
|
1812
|
-
className: UsagePill_default.retry,
|
|
1813
|
-
disabled: refreshing,
|
|
1814
|
-
onClick: () => {
|
|
1815
|
-
retry.current();
|
|
1816
|
-
},
|
|
1817
|
-
children: t(refreshing ? "usageRefreshing" : "usageRetry")
|
|
1818
|
-
}
|
|
1819
|
-
) : null,
|
|
1820
|
-
current ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: UsagePill_default.hint, children: [
|
|
1821
|
-
t("usageLastUpdated"),
|
|
1822
|
-
" ",
|
|
1823
|
-
new Date(current.updatedAt).toLocaleString(getLocale?.())
|
|
1824
|
-
] }) : null,
|
|
1825
|
-
usage ? ["rolling", "weekly", "monthly"].map((key) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.window, children: [
|
|
1826
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.row, children: [
|
|
1827
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t(`usage_${key}`) }),
|
|
1828
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
1829
|
-
usage[key].percent,
|
|
1830
|
-
"%"
|
|
1831
|
-
] })
|
|
2877
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.panel, role: "dialog", "aria-label": t("usageTitle"), "aria-busy": refreshing, children: [
|
|
2878
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.material, "aria-hidden": "true" }),
|
|
2879
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.body, children: accountsView ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2880
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.panelHead, children: [
|
|
2881
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: UsagePill_default.back, "aria-label": t("accountSwitchBack"), onClick: () => {
|
|
2882
|
+
setView("usage");
|
|
2883
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronLeft, {}) }),
|
|
2884
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: t("accountSwitchTitle") })
|
|
1832
2885
|
] }),
|
|
1833
|
-
/* @__PURE__ */ (0,
|
|
1834
|
-
|
|
1835
|
-
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2887
|
+
"div",
|
|
2888
|
+
{
|
|
2889
|
+
className: UsagePill_default.tile,
|
|
2890
|
+
role: "listbox",
|
|
2891
|
+
"aria-label": t("accountSwitchTitle"),
|
|
2892
|
+
onKeyDown: (event) => {
|
|
2893
|
+
if (event.key === "Escape") {
|
|
2894
|
+
event.stopPropagation();
|
|
2895
|
+
setView("usage");
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
const step = event.key === "ArrowDown" ? 1 : event.key === "ArrowUp" ? -1 : 0;
|
|
2899
|
+
if (step === 0) return;
|
|
2900
|
+
event.preventDefault();
|
|
2901
|
+
const options = Array.from(event.currentTarget.querySelectorAll('[role="option"]'));
|
|
2902
|
+
const at = options.indexOf(document.activeElement);
|
|
2903
|
+
options[(at + step + options.length) % options.length]?.focus();
|
|
2904
|
+
},
|
|
2905
|
+
children: accounts.map((account, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react4.Fragment, { children: [
|
|
2906
|
+
index ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.divider }) : null,
|
|
2907
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2908
|
+
"button",
|
|
2909
|
+
{
|
|
2910
|
+
type: "button",
|
|
2911
|
+
role: "option",
|
|
2912
|
+
"aria-selected": account.apiKeyEnv === activeRef,
|
|
2913
|
+
"data-selected": account.apiKeyEnv === activeRef ? "" : void 0,
|
|
2914
|
+
className: UsagePill_default.option,
|
|
2915
|
+
disabled: switching,
|
|
2916
|
+
onClick: () => {
|
|
2917
|
+
switchTo(account.apiKeyEnv);
|
|
2918
|
+
},
|
|
2919
|
+
children: [
|
|
2920
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.optionName, children: account.name || t("accountDefault") }),
|
|
2921
|
+
account.apiKeyEnv === activeRef ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tick, {}) : null
|
|
2922
|
+
]
|
|
2923
|
+
}
|
|
2924
|
+
)
|
|
2925
|
+
] }, account.id))
|
|
2926
|
+
}
|
|
2927
|
+
),
|
|
2928
|
+
switchFailed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: UsagePill_default.warning, role: "alert", children: t("accountSwitchFailed") }) : null,
|
|
2929
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: UsagePill_default.hint, children: t("accountSwitchHint") })
|
|
2930
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2931
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.panelTitle, children: t("usageTitle") }),
|
|
2932
|
+
accounts.length ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.tile, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.accHead, children: [
|
|
2933
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.dot }),
|
|
2934
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.accName, children: accountName }),
|
|
2935
|
+
accounts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.tag, children: t("accountPreferredTag") }) : null,
|
|
2936
|
+
accounts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2937
|
+
"button",
|
|
2938
|
+
{
|
|
2939
|
+
type: "button",
|
|
2940
|
+
className: UsagePill_default.switch,
|
|
2941
|
+
disabled: !switchable || switching,
|
|
2942
|
+
"aria-haspopup": "listbox",
|
|
2943
|
+
onClick: () => {
|
|
2944
|
+
setView("accounts");
|
|
2945
|
+
},
|
|
2946
|
+
children: [
|
|
2947
|
+
t("accountSwitchAction"),
|
|
2948
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronRight, {})
|
|
2949
|
+
]
|
|
2950
|
+
}
|
|
2951
|
+
) : null
|
|
2952
|
+
] }) }) : null,
|
|
2953
|
+
switchFailed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: UsagePill_default.warning, role: "alert", children: t("accountSwitchFailed") }) : null,
|
|
2954
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: UsagePill_default.warning, role: "status", children: [
|
|
2955
|
+
t(notice.reason === "quota" ? "accountFallbackQuota" : "accountFallbackCredential"),
|
|
1836
2956
|
" ",
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
2957
|
+
accounts.find((account) => account.apiKeyEnv === notice.toRef)?.name || t("accountDefault"),
|
|
2958
|
+
" \xB7 ",
|
|
2959
|
+
new Date(notice.at).toLocaleString(getLocale?.())
|
|
2960
|
+
] }) : null,
|
|
2961
|
+
failure ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.warning, role: "alert", children: [
|
|
2962
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: t("usageRefreshFailed") }),
|
|
2963
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: failure.message ?? t("usageUnavailable") }),
|
|
2964
|
+
usage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: t("usageStaleHint") }) : null
|
|
2965
|
+
] }) : null,
|
|
2966
|
+
failure ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2967
|
+
"button",
|
|
2968
|
+
{
|
|
2969
|
+
type: "button",
|
|
2970
|
+
className: UsagePill_default.retry,
|
|
2971
|
+
disabled: refreshing,
|
|
2972
|
+
onClick: () => {
|
|
2973
|
+
retry.current();
|
|
2974
|
+
},
|
|
2975
|
+
children: t(refreshing ? "usageRefreshing" : "usageRetry")
|
|
2976
|
+
}
|
|
2977
|
+
) : null,
|
|
2978
|
+
usage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.tile, children: ["rolling", "weekly", "monthly"].map((key, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react4.Fragment, { children: [
|
|
2979
|
+
index ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.divider }) : null,
|
|
2980
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.window, children: [
|
|
2981
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.windowRow, children: [
|
|
2982
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.windowLabel, children: t(`usage_${key}`) }),
|
|
2983
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("progress", { className: usageLevel(usage[key]), "aria-label": t(`usage_${key}`), max: 100, value: Math.min(100, usage[key].percent) }),
|
|
2984
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("strong", { className: UsagePill_default.windowPercent, children: [
|
|
2985
|
+
usage[key].percent,
|
|
2986
|
+
"%"
|
|
2987
|
+
] })
|
|
2988
|
+
] }),
|
|
2989
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.windowReset, children: [
|
|
2990
|
+
t("usageResets"),
|
|
2991
|
+
" ",
|
|
2992
|
+
new Date(usage[key].resetsAt).toLocaleString(getLocale?.())
|
|
2993
|
+
] }),
|
|
2994
|
+
usage[key].status === "rate-limited" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.limitedText, children: t("usageLimited") })
|
|
2995
|
+
] })
|
|
2996
|
+
] }, key)) }) : failure ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: UsagePill_default.hint, children: t("usageLoading") }),
|
|
2997
|
+
current ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.foot, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
|
|
2998
|
+
t("usageLastUpdated"),
|
|
2999
|
+
" ",
|
|
3000
|
+
new Date(current.updatedAt).toLocaleString(getLocale?.())
|
|
3001
|
+
] }) }) : null
|
|
3002
|
+
] }) })
|
|
1841
3003
|
] })
|
|
1842
3004
|
] });
|
|
1843
3005
|
}
|
|
1844
3006
|
|
|
1845
3007
|
// src/client/usage.ts
|
|
3008
|
+
var import_dsh_client_store2 = require("@deepseek-ai/dsh-client-store");
|
|
1846
3009
|
function registerUsagePill(ctx, settings) {
|
|
1847
3010
|
ctx.inject(["modelDirectories", "sessions", "remote.session"], (scope) => {
|
|
1848
3011
|
scope.inject(["remote.opencodeGoUsage"], (ready) => {
|
|
3012
|
+
const credentialChanges = (0, import_dsh_client_store2.createSnapshotStore)(0);
|
|
3013
|
+
ready.effect(() => ready.remote.$on("credentials/reference-updated", (ref) => {
|
|
3014
|
+
if (accountsOf(settings.getSnapshot().value ?? {}).some((account) => account.apiKeyEnv === ref)) {
|
|
3015
|
+
credentialChanges.set(credentialChanges.getSnapshot() + 1);
|
|
3016
|
+
}
|
|
3017
|
+
}));
|
|
1849
3018
|
const readUsage = async () => {
|
|
1850
3019
|
const result = await ready.remote.opencodeGoUsage.read();
|
|
1851
3020
|
if (!result.ok) throw result.error;
|
|
@@ -1859,6 +3028,17 @@ function registerUsagePill(ctx, settings) {
|
|
|
1859
3028
|
inject: (sessionId) => ({
|
|
1860
3029
|
directory: ready.modelDirectories.directoryFor(sessionId).store,
|
|
1861
3030
|
settings,
|
|
3031
|
+
credentialChanges,
|
|
3032
|
+
selectAccount: async (ref) => {
|
|
3033
|
+
const snapshot = settings.getSnapshot();
|
|
3034
|
+
if (!snapshot.writable || !accountsOf(snapshot.value ?? {}).some((account) => account.apiKeyEnv === ref)) return false;
|
|
3035
|
+
try {
|
|
3036
|
+
await settings.mutate([{ op: "set", path: ["apiKeyEnv"], value: ref }], snapshot.revision);
|
|
3037
|
+
return accountRefOf(settings.getSnapshot().value ?? {}) === ref;
|
|
3038
|
+
} catch {
|
|
3039
|
+
return false;
|
|
3040
|
+
}
|
|
3041
|
+
},
|
|
1862
3042
|
readUsage,
|
|
1863
3043
|
getLocale: () => ready.locale.getLocale().active,
|
|
1864
3044
|
t: (key) => translate(key)
|
|
@@ -1888,9 +3068,21 @@ function apply(ctx) {
|
|
|
1888
3068
|
}
|
|
1889
3069
|
function mountSettings(ctx, scope, modelsReady) {
|
|
1890
3070
|
registerUsagePill(ctx, scope);
|
|
3071
|
+
let readAccount;
|
|
3072
|
+
ctx.inject(["remote.opencodeGoUsage"], (ready) => {
|
|
3073
|
+
readAccount = async (ref) => {
|
|
3074
|
+
const result = await ready.remote.opencodeGoUsage.readAccount(ref);
|
|
3075
|
+
if (!result.ok) throw result.error;
|
|
3076
|
+
return result.value;
|
|
3077
|
+
};
|
|
3078
|
+
});
|
|
1891
3079
|
const controller = new OpencodeGoSectionController(scope, ctx, async () => {
|
|
1892
3080
|
await modelsReady;
|
|
1893
3081
|
return ctx.remote.opencodeGoModels.read();
|
|
3082
|
+
}, async (ref) => {
|
|
3083
|
+
await modelsReady;
|
|
3084
|
+
if (readAccount === void 0) throw new Error("OpenCode Go account usage is unavailable in this session");
|
|
3085
|
+
return readAccount(ref);
|
|
1894
3086
|
});
|
|
1895
3087
|
ctx.effect(() => () => controller.dispose());
|
|
1896
3088
|
const t = ctx.locale.bind(NS);
|