dsh-opencode-go 0.1.19 → 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 +51 -4
- package/README.md +43 -5
- package/docs/development.md +4 -2
- package/docs/verification.md +105 -0
- package/lib/client.js +1390 -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/client/staged-form.d.ts +8 -0
- 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) {
|
|
@@ -932,7 +1723,9 @@ var StagedForm = class {
|
|
|
932
1723
|
const write = staged.clear ? { kind: "clear" } : spec.parse(staged.text);
|
|
933
1724
|
return {
|
|
934
1725
|
text: staged.text,
|
|
935
|
-
|
|
1726
|
+
// A draft a save would skip leaves the user layer exactly as it stands, so
|
|
1727
|
+
// the badge answers for that standing override instead of the edit.
|
|
1728
|
+
overridden: this.unchangedDraft(field, staged) ? this.stored(field) : write?.kind === "set",
|
|
936
1729
|
invalid: write === void 0
|
|
937
1730
|
};
|
|
938
1731
|
}
|
|
@@ -976,7 +1769,11 @@ var StagedForm = class {
|
|
|
976
1769
|
this.publish();
|
|
977
1770
|
let landed = true;
|
|
978
1771
|
for (const write of writes) {
|
|
979
|
-
|
|
1772
|
+
try {
|
|
1773
|
+
landed = await write() && landed;
|
|
1774
|
+
} catch {
|
|
1775
|
+
landed = false;
|
|
1776
|
+
}
|
|
980
1777
|
}
|
|
981
1778
|
if (landed) this.staged.clear();
|
|
982
1779
|
this.saving = false;
|
|
@@ -1003,7 +1800,7 @@ var StagedForm = class {
|
|
|
1003
1800
|
if (this.stored(field)) plan.push({ field, run: () => this.clear(field) });
|
|
1004
1801
|
continue;
|
|
1005
1802
|
}
|
|
1006
|
-
if (
|
|
1803
|
+
if (this.unchangedDraft(field, staged)) continue;
|
|
1007
1804
|
const write = spec.parse(staged.text);
|
|
1008
1805
|
if (write === void 0) plan.push({ field, run: void 0 });
|
|
1009
1806
|
else if (write.kind === "clear") plan.push({ field, run: () => this.clear(field) });
|
|
@@ -1045,6 +1842,16 @@ var StagedForm = class {
|
|
|
1045
1842
|
const user = this.userLayer();
|
|
1046
1843
|
return user !== void 0 && Object.hasOwn(user, field);
|
|
1047
1844
|
}
|
|
1845
|
+
/**
|
|
1846
|
+
* Whether a draft already equals the field's effective value, so a save would
|
|
1847
|
+
* write nothing. The save plan and the override badge both answer for it.
|
|
1848
|
+
* @param field - field name inside the namespace section.
|
|
1849
|
+
* @param staged - the staged edit to test.
|
|
1850
|
+
* @returns true when the draft is a no-op; a clear is never one.
|
|
1851
|
+
*/
|
|
1852
|
+
unchangedDraft(field, staged) {
|
|
1853
|
+
return !staged.clear && staged.text === this.spec(field).format(this.sectionValue(field));
|
|
1854
|
+
}
|
|
1048
1855
|
publish() {
|
|
1049
1856
|
for (const listener of this.listeners) listener();
|
|
1050
1857
|
}
|
|
@@ -1076,6 +1883,10 @@ var OpencodeGoSectionController = class {
|
|
|
1076
1883
|
constructor(scope, ctx, readModels = async () => {
|
|
1077
1884
|
const result = await ctx.remote.llm.discoverModels(OPENCODE_GO_NS, { provider: PROVIDER_ID });
|
|
1078
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;
|
|
1079
1890
|
}) {
|
|
1080
1891
|
this.scope = scope;
|
|
1081
1892
|
this.ctx = ctx;
|
|
@@ -1093,6 +1904,18 @@ var OpencodeGoSectionController = class {
|
|
|
1093
1904
|
},
|
|
1094
1905
|
textField("apiKeyEnv"),
|
|
1095
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
|
+
},
|
|
1096
1919
|
numberField("refreshMinutes"),
|
|
1097
1920
|
numberField("streamIdleTimeoutMs"),
|
|
1098
1921
|
numberField("maxImages", (value) => Number.isSafeInteger(value) && value > 0),
|
|
@@ -1104,9 +1927,25 @@ var OpencodeGoSectionController = class {
|
|
|
1104
1927
|
[{ field: API_KEY_FIELD, write: (text) => this.writeKey(text) }]
|
|
1105
1928
|
);
|
|
1106
1929
|
this.store = this.form.bind(() => this.projection());
|
|
1107
|
-
|
|
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();
|
|
1108
1945
|
this.unsubscribe = scope.subscribe(() => {
|
|
1109
|
-
|
|
1946
|
+
this.accounts?.sync();
|
|
1947
|
+
this.store.set(this.projection());
|
|
1948
|
+
const endpoint = networkIdentity();
|
|
1110
1949
|
if (endpoint !== modelsEndpoint) {
|
|
1111
1950
|
modelsEndpoint = endpoint;
|
|
1112
1951
|
this.modelsRequest++;
|
|
@@ -1126,8 +1965,13 @@ var OpencodeGoSectionController = class {
|
|
|
1126
1965
|
pickerFailed = false;
|
|
1127
1966
|
face;
|
|
1128
1967
|
unsubscribe;
|
|
1968
|
+
accounts;
|
|
1969
|
+
credentialRequest = 0;
|
|
1970
|
+
keyDraftRef;
|
|
1129
1971
|
/** Release subscriptions without disposing the host's shared form. */
|
|
1130
1972
|
dispose() {
|
|
1973
|
+
this.credentialRequest++;
|
|
1974
|
+
this.accounts?.dispose();
|
|
1131
1975
|
this.modelsRequest++;
|
|
1132
1976
|
this.unsubscribe();
|
|
1133
1977
|
this.form.dispose();
|
|
@@ -1135,6 +1979,8 @@ var OpencodeGoSectionController = class {
|
|
|
1135
1979
|
projection() {
|
|
1136
1980
|
return {
|
|
1137
1981
|
...this.form.shell(),
|
|
1982
|
+
saving: this.form.shell().saving || this.accounts?.snapshot().busy === true,
|
|
1983
|
+
accounts: this.accounts?.snapshot(),
|
|
1138
1984
|
enabled: this.enabled(),
|
|
1139
1985
|
usageDisplay: this.form.field("usageDisplay"),
|
|
1140
1986
|
modelVisibility: this.scope.getSnapshot().value?.modelVisibility ?? {},
|
|
@@ -1142,6 +1988,7 @@ var OpencodeGoSectionController = class {
|
|
|
1142
1988
|
pickerFailed: this.pickerFailed,
|
|
1143
1989
|
apiKeyEnv: this.form.field("apiKeyEnv"),
|
|
1144
1990
|
baseURL: this.form.field("baseURL"),
|
|
1991
|
+
proxyURL: this.form.field("proxyURL"),
|
|
1145
1992
|
refreshMinutes: this.form.field("refreshMinutes"),
|
|
1146
1993
|
streamIdleTimeoutMs: this.form.field("streamIdleTimeoutMs"),
|
|
1147
1994
|
maxImages: this.form.field("maxImages"),
|
|
@@ -1149,7 +1996,7 @@ var OpencodeGoSectionController = class {
|
|
|
1149
1996
|
requestImagePixelBudget: this.form.field("requestImagePixelBudget"),
|
|
1150
1997
|
requestImageMaxBytes: this.form.field("requestImageMaxBytes"),
|
|
1151
1998
|
apiKey: this.form.field(API_KEY_FIELD),
|
|
1152
|
-
apiKeyConfigured: this.credential.configured,
|
|
1999
|
+
apiKeyConfigured: this.credential.ref === refOf(this.scope.getSnapshot()) && this.credential.configured && accountsOf(this.scope.getSnapshot().value ?? {}).length > 0,
|
|
1153
2000
|
apiKeyWritable: this.credential.writable,
|
|
1154
2001
|
models: this.models,
|
|
1155
2002
|
modelLimits: this.form.field("modelLimits"),
|
|
@@ -1206,7 +2053,7 @@ var OpencodeGoSectionController = class {
|
|
|
1206
2053
|
}
|
|
1207
2054
|
/** Serialize immediate switches with form saves; refused writes retain committed values. */
|
|
1208
2055
|
async writePickerSetting(field, value, accepted) {
|
|
1209
|
-
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;
|
|
1210
2057
|
this.pickerSaving = true;
|
|
1211
2058
|
this.pickerFailed = false;
|
|
1212
2059
|
this.store.set(this.projection());
|
|
@@ -1271,13 +2118,19 @@ var OpencodeGoSectionController = class {
|
|
|
1271
2118
|
* reference in force.
|
|
1272
2119
|
*/
|
|
1273
2120
|
async readCredential() {
|
|
2121
|
+
const request = ++this.credentialRequest;
|
|
1274
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
|
+
}
|
|
1275
2128
|
if (ref !== this.credential.ref) {
|
|
1276
2129
|
this.credential = { ref, configured: false, writable: true };
|
|
1277
2130
|
this.store.set(this.projection());
|
|
1278
2131
|
}
|
|
1279
|
-
const response = await this.ctx.remote.credentials.describe([ref]);
|
|
1280
|
-
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;
|
|
1281
2134
|
const view = response.value[ref];
|
|
1282
2135
|
const next = {
|
|
1283
2136
|
ref,
|
|
@@ -1299,6 +2152,7 @@ var OpencodeGoSectionController = class {
|
|
|
1299
2152
|
* @param ref - the reference the Host reports as changed.
|
|
1300
2153
|
*/
|
|
1301
2154
|
refreshCredential(ref) {
|
|
2155
|
+
this.accounts?.invalidate(ref);
|
|
1302
2156
|
if (ref !== this.credential.ref) return;
|
|
1303
2157
|
void this.readCredential();
|
|
1304
2158
|
}
|
|
@@ -1319,7 +2173,24 @@ var OpencodeGoSectionController = class {
|
|
|
1319
2173
|
setModelEnabled: (id3, next) => {
|
|
1320
2174
|
void this.setModelEnabled(id3, next);
|
|
1321
2175
|
},
|
|
1322
|
-
...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
|
+
}
|
|
1323
2194
|
};
|
|
1324
2195
|
return this.face;
|
|
1325
2196
|
}
|
|
@@ -1329,9 +2200,12 @@ var OpencodeGoSectionController = class {
|
|
|
1329
2200
|
* @returns whether the Host reports a configured credential afterwards.
|
|
1330
2201
|
*/
|
|
1331
2202
|
async writeKey(value) {
|
|
1332
|
-
|
|
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);
|
|
1333
2207
|
await this.readCredential();
|
|
1334
|
-
return this.credential.configured;
|
|
2208
|
+
return ref === this.credential.ref ? this.credential.configured : true;
|
|
1335
2209
|
}
|
|
1336
2210
|
};
|
|
1337
2211
|
function modelLimitsOf(value) {
|
|
@@ -1364,9 +2238,50 @@ function refOf(snapshot) {
|
|
|
1364
2238
|
|
|
1365
2239
|
// src/client/locales.ts
|
|
1366
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",
|
|
1367
2283
|
usageTitle: "OpenCode Go usage",
|
|
1368
2284
|
usageRollingShort: "5h",
|
|
1369
|
-
usageHint: "Account usage \xB7 used percentage \xB7 refreshes every minute",
|
|
1370
2285
|
usageWeekShort: "week",
|
|
1371
2286
|
usage_rolling: "5 hours",
|
|
1372
2287
|
usage_weekly: "Weekly",
|
|
@@ -1376,6 +2291,7 @@ var en = {
|
|
|
1376
2291
|
usageLoading: "Loading usage\u2026",
|
|
1377
2292
|
usageUnavailable: "Unavailable",
|
|
1378
2293
|
usageStaleShort: "Last data",
|
|
2294
|
+
usageFallbackShort: "fallback",
|
|
1379
2295
|
usageStaleHint: "Showing the last successful usage reading. Current usage may have changed.",
|
|
1380
2296
|
usageRefreshFailed: "Refresh failed",
|
|
1381
2297
|
usageLastUpdated: "Last updated",
|
|
@@ -1465,6 +2381,9 @@ var en = {
|
|
|
1465
2381
|
apiKeyEnvHint: "The name the key is resolved from, addressed through the credentials service.",
|
|
1466
2382
|
baseURLLabel: "Gateway URL",
|
|
1467
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.",
|
|
1468
2387
|
refreshMinutesLabel: "Catalog refresh (minutes)",
|
|
1469
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.",
|
|
1470
2389
|
streamIdleTimeoutMsLabel: "Stream idle timeout (ms)",
|
|
@@ -1488,9 +2407,50 @@ var en = {
|
|
|
1488
2407
|
unavailable: "The OpenCode Go settings are not served in this deployment."
|
|
1489
2408
|
};
|
|
1490
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",
|
|
1491
2452
|
usageTitle: "OpenCode Go \u7528\u91CF",
|
|
1492
2453
|
usageRollingShort: "5\u5C0F\u65F6",
|
|
1493
|
-
usageHint: "\u8D26\u53F7\u989D\u5EA6 \xB7 \u5DF2\u7528\u767E\u5206\u6BD4 \xB7 \u6BCF\u5206\u949F\u5237\u65B0",
|
|
1494
2454
|
usageWeekShort: "\u5468",
|
|
1495
2455
|
usage_rolling: "5 \u5C0F\u65F6",
|
|
1496
2456
|
usage_weekly: "\u6BCF\u5468",
|
|
@@ -1500,6 +2460,7 @@ var zh = {
|
|
|
1500
2460
|
usageLoading: "\u6B63\u5728\u8BFB\u53D6\u7528\u91CF\u2026",
|
|
1501
2461
|
usageUnavailable: "\u6682\u4E0D\u53EF\u7528",
|
|
1502
2462
|
usageStaleShort: "\u4E0A\u6B21\u6570\u636E",
|
|
2463
|
+
usageFallbackShort: "\u5DF2\u56DE\u9000",
|
|
1503
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",
|
|
1504
2465
|
usageRefreshFailed: "\u5237\u65B0\u5931\u8D25",
|
|
1505
2466
|
usageLastUpdated: "\u66F4\u65B0\u4E8E",
|
|
@@ -1589,6 +2550,9 @@ var zh = {
|
|
|
1589
2550
|
apiKeyEnvHint: "key \u89E3\u6790\u6240\u4F9D\u636E\u7684\u5F15\u7528\u540D\uFF0C\u7ECF\u51ED\u8BC1\u670D\u52A1\u5BFB\u5740\u3002",
|
|
1590
2551
|
baseURLLabel: "\u7F51\u5173\u5730\u5740",
|
|
1591
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",
|
|
1592
2556
|
refreshMinutesLabel: "\u76EE\u5F55\u5237\u65B0\uFF08\u5206\u949F\uFF09",
|
|
1593
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",
|
|
1594
2558
|
streamIdleTimeoutMsLabel: "\u6D41\u7A7A\u95F2\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
@@ -1613,6 +2577,11 @@ var zh = {
|
|
|
1613
2577
|
};
|
|
1614
2578
|
|
|
1615
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
|
+
}
|
|
1616
2585
|
function parseGoUsage(value) {
|
|
1617
2586
|
if (!value || typeof value !== "object") throw new Error("Invalid OpenCode Go usage response");
|
|
1618
2587
|
const source = value;
|
|
@@ -1623,6 +2592,9 @@ function parseGoUsage(value) {
|
|
|
1623
2592
|
}
|
|
1624
2593
|
result.source = source.source;
|
|
1625
2594
|
}
|
|
2595
|
+
if (source.lastSwitch !== void 0) {
|
|
2596
|
+
result.lastSwitch = parseAccountSwitch(source.lastSwitch);
|
|
2597
|
+
}
|
|
1626
2598
|
for (const key of ["rolling", "weekly", "monthly"]) {
|
|
1627
2599
|
const row = source[key];
|
|
1628
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))) {
|
|
@@ -1638,6 +2610,16 @@ var usageCodec = {
|
|
|
1638
2610
|
schema: { parse: parseGoUsage },
|
|
1639
2611
|
create: () => ({ parse: parseGoUsage })
|
|
1640
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
|
+
};
|
|
1641
2623
|
var usageRemote = {
|
|
1642
2624
|
package: "dsh-opencode-go",
|
|
1643
2625
|
descriptors: [{
|
|
@@ -1648,6 +2630,14 @@ var usageRemote = {
|
|
|
1648
2630
|
invocation: { kind: "direct" },
|
|
1649
2631
|
parameters: [],
|
|
1650
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
|
|
1651
2641
|
}]
|
|
1652
2642
|
};
|
|
1653
2643
|
|
|
@@ -1658,7 +2648,7 @@ var goRemote = {
|
|
|
1658
2648
|
};
|
|
1659
2649
|
|
|
1660
2650
|
// src/client/UsagePill.tsx
|
|
1661
|
-
var
|
|
2651
|
+
var import_react4 = require("react");
|
|
1662
2652
|
|
|
1663
2653
|
// plugin-css:src/client/UsagePill.module.css
|
|
1664
2654
|
var id2 = "dsh-opencode-go/UsagePill.module.css";
|
|
@@ -1666,20 +2656,29 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
|
|
|
1666
2656
|
const style = document.createElement("style");
|
|
1667
2657
|
style.dataset.plugin = "dsh-opencode-go";
|
|
1668
2658
|
style.dataset.pluginCss = id2;
|
|
1669
|
-
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}';
|
|
1670
2660
|
document.head.appendChild(style);
|
|
1671
2661
|
}
|
|
1672
|
-
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" };
|
|
1673
2663
|
|
|
1674
2664
|
// src/client/UsagePill.tsx
|
|
1675
|
-
var
|
|
2665
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2666
|
+
var unchanged = () => 0;
|
|
2667
|
+
var noSubscription = () => () => {
|
|
2668
|
+
};
|
|
1676
2669
|
function usageFailure(error) {
|
|
1677
2670
|
if (error && typeof error === "object" && "code" in error && error.code === "opencode-go/usage-unavailable" && "details" in error && error.details && typeof error.details === "object") {
|
|
1678
2671
|
const details = error.details;
|
|
2672
|
+
let lastSwitch;
|
|
2673
|
+
try {
|
|
2674
|
+
if (details.lastSwitch) lastSwitch = parseAccountSwitch(details.lastSwitch);
|
|
2675
|
+
} catch {
|
|
2676
|
+
}
|
|
1679
2677
|
return {
|
|
1680
2678
|
..."message" in error && typeof error.message === "string" ? { message: error.message } : {},
|
|
1681
2679
|
retainPrevious: details.retryable === true && details.retainPrevious === true,
|
|
1682
|
-
...typeof details.source === "string" ? { source: details.source } : {}
|
|
2680
|
+
...typeof details.source === "string" ? { source: details.source } : {},
|
|
2681
|
+
...lastSwitch ? { lastSwitch } : {}
|
|
1683
2682
|
};
|
|
1684
2683
|
}
|
|
1685
2684
|
return { retainPrevious: false };
|
|
@@ -1688,22 +2687,50 @@ function usageLevel(window) {
|
|
|
1688
2687
|
if (window.status === "rate-limited" || window.percent >= 100) return UsagePill_default.limited;
|
|
1689
2688
|
return window.percent >= 80 ? UsagePill_default.high : void 0;
|
|
1690
2689
|
}
|
|
1691
|
-
function
|
|
1692
|
-
|
|
1693
|
-
|
|
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);
|
|
1694
2707
|
const mode = config.value?.usageDisplay ?? DEFAULT_USAGE_DISPLAY;
|
|
1695
2708
|
const visible = config.status === "ready" && config.value?.enabled !== false && (mode === "always" || mode === "auto" && state.current?.provider === PROVIDER_ID);
|
|
1696
|
-
|
|
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;
|
|
1697
2721
|
}
|
|
1698
|
-
function ActiveUsage({ readUsage, t, getLocale }) {
|
|
1699
|
-
const [snapshot, setSnapshot] = (0,
|
|
1700
|
-
const [failed, setFailed] = (0,
|
|
1701
|
-
const [refreshing, setRefreshing] = (0,
|
|
1702
|
-
const [open, setOpen] = (0,
|
|
1703
|
-
const
|
|
1704
|
-
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)(() => {
|
|
1705
2732
|
});
|
|
1706
|
-
(0,
|
|
2733
|
+
(0, import_react4.useEffect)(() => {
|
|
1707
2734
|
let alive = true;
|
|
1708
2735
|
let busy = false;
|
|
1709
2736
|
setSnapshot(null);
|
|
@@ -1749,7 +2776,7 @@ function ActiveUsage({ readUsage, t, getLocale }) {
|
|
|
1749
2776
|
document.removeEventListener("visibilitychange", visible);
|
|
1750
2777
|
};
|
|
1751
2778
|
}, [readUsage]);
|
|
1752
|
-
(0,
|
|
2779
|
+
(0, import_react4.useEffect)(() => {
|
|
1753
2780
|
if (!open) return;
|
|
1754
2781
|
const click = (event) => {
|
|
1755
2782
|
if (!root.current?.contains(event.target)) setOpen(false);
|
|
@@ -1767,71 +2794,227 @@ function ActiveUsage({ readUsage, t, getLocale }) {
|
|
|
1767
2794
|
const current = snapshot?.reader === readUsage ? snapshot : null;
|
|
1768
2795
|
const usage = current?.usage;
|
|
1769
2796
|
const failure = failed?.reader === readUsage ? failed.failure : null;
|
|
1770
|
-
const
|
|
1771
|
-
|
|
1772
|
-
|
|
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)(
|
|
1773
2861
|
"button",
|
|
1774
2862
|
{
|
|
1775
2863
|
type: "button",
|
|
1776
2864
|
className: UsagePill_default.trigger,
|
|
1777
2865
|
"aria-expanded": open,
|
|
1778
2866
|
"aria-haspopup": "dialog",
|
|
2867
|
+
"data-fallback": notice ? "" : void 0,
|
|
1779
2868
|
"aria-label": `${t("usageTitle")}: ${label}`,
|
|
2869
|
+
title: label,
|
|
1780
2870
|
onClick: () => {
|
|
1781
2871
|
setOpen(!open);
|
|
2872
|
+
setView("usage");
|
|
1782
2873
|
},
|
|
1783
|
-
children:
|
|
2874
|
+
children: segments
|
|
1784
2875
|
}
|
|
1785
2876
|
),
|
|
1786
|
-
open && /* @__PURE__ */ (0,
|
|
1787
|
-
/* @__PURE__ */ (0,
|
|
1788
|
-
/* @__PURE__ */ (0,
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
failure ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1795
|
-
"button",
|
|
1796
|
-
{
|
|
1797
|
-
type: "button",
|
|
1798
|
-
className: UsagePill_default.retry,
|
|
1799
|
-
disabled: refreshing,
|
|
1800
|
-
onClick: () => {
|
|
1801
|
-
retry.current();
|
|
1802
|
-
},
|
|
1803
|
-
children: t(refreshing ? "usageRefreshing" : "usageRetry")
|
|
1804
|
-
}
|
|
1805
|
-
) : null,
|
|
1806
|
-
current ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: UsagePill_default.hint, children: [
|
|
1807
|
-
t("usageLastUpdated"),
|
|
1808
|
-
" ",
|
|
1809
|
-
new Date(current.updatedAt).toLocaleString(getLocale?.())
|
|
1810
|
-
] }) : null,
|
|
1811
|
-
usage ? ["rolling", "weekly", "monthly"].map((key) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.window, children: [
|
|
1812
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.row, children: [
|
|
1813
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t(`usage_${key}`) }),
|
|
1814
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
1815
|
-
usage[key].percent,
|
|
1816
|
-
"%"
|
|
1817
|
-
] })
|
|
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") })
|
|
1818
2885
|
] }),
|
|
1819
|
-
/* @__PURE__ */ (0,
|
|
1820
|
-
|
|
1821
|
-
|
|
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"),
|
|
1822
2956
|
" ",
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
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
|
+
] }) })
|
|
1827
3003
|
] })
|
|
1828
3004
|
] });
|
|
1829
3005
|
}
|
|
1830
3006
|
|
|
1831
3007
|
// src/client/usage.ts
|
|
3008
|
+
var import_dsh_client_store2 = require("@deepseek-ai/dsh-client-store");
|
|
1832
3009
|
function registerUsagePill(ctx, settings) {
|
|
1833
3010
|
ctx.inject(["modelDirectories", "sessions", "remote.session"], (scope) => {
|
|
1834
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
|
+
}));
|
|
1835
3018
|
const readUsage = async () => {
|
|
1836
3019
|
const result = await ready.remote.opencodeGoUsage.read();
|
|
1837
3020
|
if (!result.ok) throw result.error;
|
|
@@ -1845,6 +3028,17 @@ function registerUsagePill(ctx, settings) {
|
|
|
1845
3028
|
inject: (sessionId) => ({
|
|
1846
3029
|
directory: ready.modelDirectories.directoryFor(sessionId).store,
|
|
1847
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
|
+
},
|
|
1848
3042
|
readUsage,
|
|
1849
3043
|
getLocale: () => ready.locale.getLocale().active,
|
|
1850
3044
|
t: (key) => translate(key)
|
|
@@ -1874,9 +3068,21 @@ function apply(ctx) {
|
|
|
1874
3068
|
}
|
|
1875
3069
|
function mountSettings(ctx, scope, modelsReady) {
|
|
1876
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
|
+
});
|
|
1877
3079
|
const controller = new OpencodeGoSectionController(scope, ctx, async () => {
|
|
1878
3080
|
await modelsReady;
|
|
1879
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);
|
|
1880
3086
|
});
|
|
1881
3087
|
ctx.effect(() => () => controller.dispose());
|
|
1882
3088
|
const t = ctx.locale.bind(NS);
|